Warning, file /include/boost/dll/detail/pe_info.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_DLL_DETAIL_WINDOWS_PE_INFO_HPP
0009 #define BOOST_DLL_DETAIL_WINDOWS_PE_INFO_HPP
0010
0011 #include <boost/dll/config.hpp>
0012
0013 #ifdef BOOST_HAS_PRAGMA_ONCE
0014 # pragma once
0015 #endif
0016
0017 #include <cstdint>
0018 #include <cstring>
0019 #include <fstream>
0020 #include <string> // for std::getline
0021 #include <vector>
0022
0023 namespace boost { namespace dll { namespace detail {
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 using BYTE_ = unsigned char;
0034 using WORD_ = unsigned short;
0035 using DWORD_ = std::uint32_t;
0036 using LONG_ = std::int32_t;
0037 using ULONG_ = std::uint32_t;
0038 using LONGLONG_ = std::int64_t;
0039 using ULONGLONG_ = std::uint64_t;
0040
0041 struct IMAGE_DOS_HEADER_ {
0042 boost::dll::detail::WORD_ e_magic;
0043 boost::dll::detail::WORD_ e_cblp;
0044 boost::dll::detail::WORD_ e_cp;
0045 boost::dll::detail::WORD_ e_crlc;
0046 boost::dll::detail::WORD_ e_cparhdr;
0047 boost::dll::detail::WORD_ e_minalloc;
0048 boost::dll::detail::WORD_ e_maxalloc;
0049 boost::dll::detail::WORD_ e_ss;
0050 boost::dll::detail::WORD_ e_sp;
0051 boost::dll::detail::WORD_ e_csum;
0052 boost::dll::detail::WORD_ e_ip;
0053 boost::dll::detail::WORD_ e_cs;
0054 boost::dll::detail::WORD_ e_lfarlc;
0055 boost::dll::detail::WORD_ e_ovno;
0056 boost::dll::detail::WORD_ e_res[4];
0057 boost::dll::detail::WORD_ e_oemid;
0058 boost::dll::detail::WORD_ e_oeminfo;
0059 boost::dll::detail::WORD_ e_res2[10];
0060 boost::dll::detail::LONG_ e_lfanew;
0061 };
0062
0063 struct IMAGE_FILE_HEADER_ {
0064 boost::dll::detail::WORD_ Machine;
0065 boost::dll::detail::WORD_ NumberOfSections;
0066 boost::dll::detail::DWORD_ TimeDateStamp;
0067 boost::dll::detail::DWORD_ PointerToSymbolTable;
0068 boost::dll::detail::DWORD_ NumberOfSymbols;
0069 boost::dll::detail::WORD_ SizeOfOptionalHeader;
0070 boost::dll::detail::WORD_ Characteristics;
0071 };
0072
0073 struct IMAGE_DATA_DIRECTORY_ {
0074 boost::dll::detail::DWORD_ VirtualAddress;
0075 boost::dll::detail::DWORD_ Size;
0076 };
0077
0078 struct IMAGE_EXPORT_DIRECTORY_ {
0079 boost::dll::detail::DWORD_ Characteristics;
0080 boost::dll::detail::DWORD_ TimeDateStamp;
0081 boost::dll::detail::WORD_ MajorVersion;
0082 boost::dll::detail::WORD_ MinorVersion;
0083 boost::dll::detail::DWORD_ Name;
0084 boost::dll::detail::DWORD_ Base;
0085 boost::dll::detail::DWORD_ NumberOfFunctions;
0086 boost::dll::detail::DWORD_ NumberOfNames;
0087 boost::dll::detail::DWORD_ AddressOfFunctions;
0088 boost::dll::detail::DWORD_ AddressOfNames;
0089 boost::dll::detail::DWORD_ AddressOfNameOrdinals;
0090 };
0091
0092 struct IMAGE_SECTION_HEADER_ {
0093 static const std::size_t IMAGE_SIZEOF_SHORT_NAME_ = 8;
0094
0095 boost::dll::detail::BYTE_ Name[IMAGE_SIZEOF_SHORT_NAME_];
0096 union {
0097 boost::dll::detail::DWORD_ PhysicalAddress;
0098 boost::dll::detail::DWORD_ VirtualSize;
0099 } Misc;
0100 boost::dll::detail::DWORD_ VirtualAddress;
0101 boost::dll::detail::DWORD_ SizeOfRawData;
0102 boost::dll::detail::DWORD_ PointerToRawData;
0103 boost::dll::detail::DWORD_ PointerToRelocations;
0104 boost::dll::detail::DWORD_ PointerToLinenumbers;
0105 boost::dll::detail::WORD_ NumberOfRelocations;
0106 boost::dll::detail::WORD_ NumberOfLinenumbers;
0107 boost::dll::detail::DWORD_ Characteristics;
0108 };
0109
0110
0111 template <class AddressOffsetT>
0112 struct IMAGE_OPTIONAL_HEADER_template {
0113 static const std::size_t IMAGE_NUMBEROF_DIRECTORY_ENTRIES_ = 16;
0114
0115 boost::dll::detail::WORD_ Magic;
0116 boost::dll::detail::BYTE_ MajorLinkerVersion;
0117 boost::dll::detail::BYTE_ MinorLinkerVersion;
0118 boost::dll::detail::DWORD_ SizeOfCode;
0119 boost::dll::detail::DWORD_ SizeOfInitializedData;
0120 boost::dll::detail::DWORD_ SizeOfUninitializedData;
0121 boost::dll::detail::DWORD_ AddressOfEntryPoint;
0122 union {
0123 boost::dll::detail::DWORD_ BaseOfCode;
0124 unsigned char padding_[sizeof(AddressOffsetT) == 8 ? 4 : 8];
0125 } BaseOfCode_and_BaseOfData;
0126
0127 AddressOffsetT ImageBase;
0128 boost::dll::detail::DWORD_ SectionAlignment;
0129 boost::dll::detail::DWORD_ FileAlignment;
0130 boost::dll::detail::WORD_ MajorOperatingSystemVersion;
0131 boost::dll::detail::WORD_ MinorOperatingSystemVersion;
0132 boost::dll::detail::WORD_ MajorImageVersion;
0133 boost::dll::detail::WORD_ MinorImageVersion;
0134 boost::dll::detail::WORD_ MajorSubsystemVersion;
0135 boost::dll::detail::WORD_ MinorSubsystemVersion;
0136 boost::dll::detail::DWORD_ Win32VersionValue;
0137 boost::dll::detail::DWORD_ SizeOfImage;
0138 boost::dll::detail::DWORD_ SizeOfHeaders;
0139 boost::dll::detail::DWORD_ CheckSum;
0140 boost::dll::detail::WORD_ Subsystem;
0141 boost::dll::detail::WORD_ DllCharacteristics;
0142 AddressOffsetT SizeOfStackReserve;
0143 AddressOffsetT SizeOfStackCommit;
0144 AddressOffsetT SizeOfHeapReserve;
0145 AddressOffsetT SizeOfHeapCommit;
0146 boost::dll::detail::DWORD_ LoaderFlags;
0147 boost::dll::detail::DWORD_ NumberOfRvaAndSizes;
0148 IMAGE_DATA_DIRECTORY_ DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES_];
0149 };
0150
0151 using IMAGE_OPTIONAL_HEADER32_ = IMAGE_OPTIONAL_HEADER_template<boost::dll::detail::DWORD_>;
0152 using IMAGE_OPTIONAL_HEADER64_ = IMAGE_OPTIONAL_HEADER_template<boost::dll::detail::ULONGLONG_>;
0153
0154 template <class AddressOffsetT>
0155 struct IMAGE_NT_HEADERS_template {
0156 boost::dll::detail::DWORD_ Signature;
0157 IMAGE_FILE_HEADER_ FileHeader;
0158 IMAGE_OPTIONAL_HEADER_template<AddressOffsetT> OptionalHeader;
0159 };
0160
0161 using IMAGE_NT_HEADERS32_ = IMAGE_NT_HEADERS_template<boost::dll::detail::DWORD_>;
0162 using IMAGE_NT_HEADERS64_ = IMAGE_NT_HEADERS_template<boost::dll::detail::ULONGLONG_>;
0163
0164
0165 template <class AddressOffsetT>
0166 class pe_info {
0167 using header_t = IMAGE_NT_HEADERS_template<AddressOffsetT>;
0168 using exports_t = IMAGE_EXPORT_DIRECTORY_;
0169 using section_t = IMAGE_SECTION_HEADER_;
0170 using dos_t = IMAGE_DOS_HEADER_;
0171
0172 template <class T>
0173 static void read_raw(std::ifstream& fs, T& value, std::size_t size = sizeof(T)) {
0174 fs.read(reinterpret_cast<char*>(&value), size);
0175 }
0176
0177 public:
0178 static bool parsing_supported(std::ifstream& fs) {
0179 dos_t dos;
0180 fs.seekg(0);
0181 fs.read(reinterpret_cast<char*>(&dos), sizeof(dos));
0182
0183
0184 if (dos.e_magic != 0x4D5A && dos.e_magic != 0x5A4D) {
0185 return false;
0186 }
0187
0188 header_t h;
0189 fs.seekg(dos.e_lfanew);
0190 fs.read(reinterpret_cast<char*>(&h), sizeof(h));
0191
0192 return h.Signature == 0x00004550
0193 && h.OptionalHeader.Magic == (sizeof(std::uint32_t) == sizeof(AddressOffsetT) ? 0x10B : 0x20B);
0194 }
0195
0196 private:
0197 static header_t header(std::ifstream& fs) {
0198 header_t h;
0199
0200 dos_t dos;
0201 fs.seekg(0);
0202 read_raw(fs, dos);
0203
0204 fs.seekg(dos.e_lfanew);
0205 read_raw(fs, h);
0206
0207 return h;
0208 }
0209
0210 static exports_t exports(std::ifstream& fs, const header_t& h) {
0211 static const unsigned int IMAGE_DIRECTORY_ENTRY_EXPORT_ = 0;
0212 const std::size_t exp_virtual_address = h.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT_].VirtualAddress;
0213 exports_t exports;
0214
0215 if (exp_virtual_address == 0) {
0216
0217 std::memset(&exports, 0, sizeof(exports));
0218 return exports;
0219 }
0220
0221 const std::size_t real_offset = get_file_offset(fs, exp_virtual_address, h);
0222
0223 fs.seekg(real_offset);
0224 read_raw(fs, exports);
0225
0226 return exports;
0227 }
0228
0229 static std::size_t get_file_offset(std::ifstream& fs, std::size_t virtual_address, const header_t& h) {
0230 section_t image_section_header;
0231
0232 {
0233 dos_t dos;
0234 fs.seekg(0);
0235 read_raw(fs, dos);
0236 fs.seekg(dos.e_lfanew + sizeof(header_t));
0237 }
0238
0239 for (std::size_t i = 0;i < h.FileHeader.NumberOfSections;++i) {
0240 read_raw(fs, image_section_header);
0241 if (virtual_address >= image_section_header.VirtualAddress
0242 && virtual_address < image_section_header.VirtualAddress + image_section_header.SizeOfRawData)
0243 {
0244 return image_section_header.PointerToRawData + virtual_address - image_section_header.VirtualAddress;
0245 }
0246 }
0247
0248 return 0;
0249 }
0250
0251 public:
0252 static std::vector<std::string> sections(std::ifstream& fs) {
0253 std::vector<std::string> ret;
0254
0255 const header_t h = header(fs);
0256 ret.reserve(h.FileHeader.NumberOfSections);
0257
0258
0259 section_t image_section_header;
0260 char name_helper[section_t::IMAGE_SIZEOF_SHORT_NAME_ + 1];
0261 std::memset(name_helper, 0, sizeof(name_helper));
0262 for (std::size_t i = 0;i < h.FileHeader.NumberOfSections;++i) {
0263
0264 read_raw(fs, image_section_header);
0265 std::memcpy(name_helper, image_section_header.Name, section_t::IMAGE_SIZEOF_SHORT_NAME_);
0266
0267 if (name_helper[0] != '/') {
0268 ret.push_back(name_helper);
0269 } else {
0270
0271
0272
0273 ret.push_back(name_helper);
0274 }
0275 }
0276
0277 return ret;
0278 }
0279
0280 static std::vector<std::string> symbols(std::ifstream& fs) {
0281 std::vector<std::string> ret;
0282
0283 const header_t h = header(fs);
0284 const exports_t exprt = exports(fs, h);
0285 const std::size_t exported_symbols = exprt.NumberOfNames;
0286
0287 if (exported_symbols == 0) {
0288 return ret;
0289 }
0290
0291 const std::size_t fixed_names_addr = get_file_offset(fs, exprt.AddressOfNames, h);
0292
0293 ret.reserve(exported_symbols);
0294 boost::dll::detail::DWORD_ name_offset;
0295 std::string symbol_name;
0296 for (std::size_t i = 0;i < exported_symbols;++i) {
0297 fs.seekg(fixed_names_addr + i * sizeof(name_offset));
0298 read_raw(fs, name_offset);
0299 fs.seekg(get_file_offset(fs, name_offset, h));
0300 std::getline(fs, symbol_name, '\0');
0301 ret.push_back(symbol_name);
0302 }
0303
0304 return ret;
0305 }
0306
0307 static std::vector<std::string> symbols(std::ifstream& fs, const char* section_name) {
0308 std::vector<std::string> ret;
0309
0310 const header_t h = header(fs);
0311
0312 std::size_t section_begin_addr = 0;
0313 std::size_t section_end_addr = 0;
0314
0315 {
0316 section_t image_section_header;
0317 char name_helper[section_t::IMAGE_SIZEOF_SHORT_NAME_ + 1];
0318 std::memset(name_helper, 0, sizeof(name_helper));
0319 for (std::size_t i = 0;i < h.FileHeader.NumberOfSections;++i) {
0320
0321 read_raw(fs, image_section_header);
0322 std::memcpy(name_helper, image_section_header.Name, section_t::IMAGE_SIZEOF_SHORT_NAME_);
0323 if (!std::strcmp(section_name, name_helper)) {
0324 section_begin_addr = image_section_header.PointerToRawData;
0325 section_end_addr = section_begin_addr + image_section_header.SizeOfRawData;
0326 }
0327 }
0328
0329
0330 if(section_begin_addr == 0 || section_end_addr == 0)
0331 return ret;
0332 }
0333
0334 const exports_t exprt = exports(fs, h);
0335 const std::size_t exported_symbols = exprt.NumberOfFunctions;
0336 const std::size_t fixed_names_addr = get_file_offset(fs, exprt.AddressOfNames, h);
0337 const std::size_t fixed_ordinals_addr = get_file_offset(fs, exprt.AddressOfNameOrdinals, h);
0338 const std::size_t fixed_functions_addr = get_file_offset(fs, exprt.AddressOfFunctions, h);
0339
0340 ret.reserve(exported_symbols);
0341 boost::dll::detail::DWORD_ ptr;
0342 boost::dll::detail::WORD_ ordinal;
0343 std::string symbol_name;
0344 for (std::size_t i = 0;i < exported_symbols;++i) {
0345
0346 fs.seekg(fixed_ordinals_addr + i * sizeof(ordinal));
0347 read_raw(fs, ordinal);
0348 if (ordinal >= exported_symbols) {
0349 continue;
0350 }
0351
0352
0353 fs.seekg(fixed_functions_addr + ordinal * sizeof(ptr));
0354 read_raw(fs, ptr);
0355 ptr = static_cast<boost::dll::detail::DWORD_>( get_file_offset(fs, ptr, h) );
0356
0357 if (ptr >= section_end_addr || ptr < section_begin_addr) {
0358 continue;
0359 }
0360
0361 fs.seekg(fixed_names_addr + i * sizeof(ptr));
0362 read_raw(fs, ptr);
0363 fs.seekg(get_file_offset(fs, ptr, h));
0364 std::getline(fs, symbol_name, '\0');
0365 ret.push_back(symbol_name);
0366 }
0367
0368 return ret;
0369 }
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427 };
0428
0429 using pe_info32 = pe_info<boost::dll::detail::DWORD_>;
0430 using pe_info64 = pe_info<boost::dll::detail::ULONGLONG_>;
0431
0432 }}}
0433
0434 #endif