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