fork download
  1. // make idata by the delayed evaluation
  2. // public domain
  3.  
  4. #include <cstdio>
  5. #include <cstring>
  6. #include <cstdint>
  7. #include <string>
  8. #include <vector>
  9. #include <map>
  10. #include <memory>
  11.  
  12. using namespace std;
  13.  
  14. struct Address {
  15. uint32_t addr;
  16. bool rel;
  17. Address(bool rel): addr(0), rel(rel) {}
  18. };
  19.  
  20. class Buffer {
  21. private:
  22. vector<uint8_t> buffer;
  23. vector<pair<uint32_t, shared_ptr<Address>>> values;
  24. vector<pair<uint32_t, shared_ptr<Address>>> addrs;
  25.  
  26. public:
  27. inline size_t size() const { return buffer.size(); }
  28. inline void resize(size_t size) { buffer.resize(size, 0); }
  29. inline void expand(size_t size) { resize(buffer.size() + size); }
  30.  
  31. inline Buffer &add(const void *src, int size) {
  32. auto sz = buffer.size();
  33. expand(size);
  34. memcpy(&buffer[sz], src, size);
  35. return *this;
  36. }
  37.  
  38. Buffer &operator << (const Buffer &buf) {
  39. auto sz = buffer.size();
  40. expand(buf.size());
  41. memcpy(&buffer[sz], &buf.buffer[0], buf.size());
  42. for (auto it = buf.values.begin(); it != buf.values.end(); ++it)
  43. values.emplace_back(sz + it->first, it->second);
  44. for (auto it = buf.addrs.begin(); it != buf.addrs.end(); ++it)
  45. addrs.emplace_back(sz + it->first, it->second);
  46. return *this;
  47. }
  48.  
  49. Buffer &operator << (const shared_ptr<Address> &f) {
  50. values.emplace_back(size(), f);
  51. expand(4);
  52. return *this;
  53. }
  54.  
  55. Buffer &operator << (const string &s) {
  56. return add(s.c_str(), s.size() + 1);
  57. }
  58.  
  59. template <typename T> Buffer &operator << (T v) {
  60. return add(&v, sizeof(v));
  61. }
  62.  
  63. shared_ptr<Address> addr(bool rel = false) {
  64. if (!addrs.empty()) {
  65. auto p = addrs.back().second;
  66. if (p->addr == size() && p->rel == rel)
  67. return p;
  68. }
  69. shared_ptr<Address> ret(new Address(rel));
  70. addrs.emplace_back(size(), ret);
  71. return ret;
  72. }
  73.  
  74. inline shared_ptr<Address> rva() { return addr(true); }
  75.  
  76. void put(const shared_ptr<Address> addr) {
  77. addrs.emplace_back(size(), addr);
  78. }
  79.  
  80. void reloc(uint32_t imgbase, uint32_t rva) {
  81. for (auto it = addrs.begin(); it != addrs.end(); ++it) {
  82. it->second->addr = rva + it->first;
  83. if (!it->second->rel) it->second->addr += imgbase;
  84. }
  85. for (auto it = values.begin(); it != values.end(); ++it)
  86. *reinterpret_cast<uint32_t *>(&buffer[it->first]) = it->second->addr;
  87. for (int i = 0; i < size(); i += 16) {
  88. string asc;
  89. printf("%08x ", imgbase + rva + i);
  90. for (int j = 0; j < 16; ++j) {
  91. if (i + j < size()) {
  92. auto b = buffer[i + j];
  93. printf("%02x ", b);
  94. asc += 32 <= b && b < 127 ? b : '.';
  95. } else printf(" ");
  96. }
  97. printf("%s\n", asc.c_str());
  98. }
  99. }
  100. };
  101.  
  102. struct IData: public map<string, map<string, shared_ptr<Address>>> {
  103. shared_ptr<Address> import(const string &dll, const string &sym) {
  104. return (*this)[dll][sym] = shared_ptr<Address>(new Address(false));
  105. }
  106.  
  107. Buffer create() {
  108. Buffer idt, ilt, iat, hn, name;
  109. uint32_t zero = 0;
  110. for (auto dll = begin(); dll != end(); ++dll) {
  111. idt << ilt.rva() << zero << zero << name.rva() << iat.rva();
  112. name << dll->first;
  113. for (auto sym = dll->second.begin(); sym != dll->second.end(); ++sym) {
  114. iat.put(sym->second);
  115. ilt << hn.rva();
  116. iat << hn.rva();
  117. hn << uint16_t(0) << sym->first;
  118. if (hn.size() & 1) hn << uint8_t(0);
  119. }
  120. ilt << zero;
  121. iat << zero;
  122. }
  123. idt.expand(20);
  124. return Buffer() << idt << ilt << iat << hn << name;
  125. }
  126. };
  127.  
  128. int main()
  129. {
  130. IData idata;
  131. auto foo = idata.import("a.dll", "foo");
  132. auto bar = idata.import("a.dll", "bar");
  133. auto baz = idata.import("b.dll", "baz");
  134. idata.create().reloc(0x400000, 0x2000);
  135. printf("foo: %08x\n", foo->addr);
  136. printf("bar: %08x\n", bar->addr);
  137. printf("baz: %08x\n", baz->addr);
  138. }
  139.  
Success #stdin #stdout 0s 3092KB
stdin
Standard input is empty
stdout
00402000 3c 20 00 00 00 00 00 00 00 00 00 00 76 20 00 00 < ..........v ..
00402010 50 20 00 00 48 20 00 00 00 00 00 00 00 00 00 00 P ..H ..........
00402020 7c 20 00 00 5c 20 00 00 00 00 00 00 00 00 00 00 | ..\ ..........
00402030 00 00 00 00 00 00 00 00 00 00 00 00 64 20 00 00 ............d ..
00402040 6a 20 00 00 00 00 00 00 70 20 00 00 00 00 00 00 j ......p ......
00402050 64 20 00 00 6a 20 00 00 00 00 00 00 70 20 00 00 d ..j ......p ..
00402060 00 00 00 00 00 00 62 61 72 00 00 00 66 6f 6f 00 ......bar...foo.
00402070 00 00 62 61 7a 00 61 2e 64 6c 6c 00 62 2e 64 6c ..baz.a.dll.b.dl
00402080 6c 00                                           l.
foo: 00402054
bar: 00402050
baz: 0040205c