File indexing completed on 2025-10-30 08:13:20
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