@@ -62,6 +62,11 @@ struct reloc {
6262 reloc_type type;
6363};
6464
65+ struct debugent {
66+ std::uint32_t type;
67+ bounded_buffer *data;
68+ };
69+
6570#define SYMBOL_NAME_OFFSET (sn ) (static_cast <std::uint32_t >(sn.data >> 32 ))
6671#define SYMBOL_TYPE_HI (x ) (x.type >> 8 )
6772
@@ -124,6 +129,7 @@ struct parsed_pe_internal {
124129 std::vector<reloc> relocs;
125130 std::vector<exportent> exports;
126131 std::vector<symbol> symbols;
132+ std::vector<debugent> debugdirs;
127133};
128134
129135// String representation of Rich header object types
@@ -1806,6 +1812,103 @@ bool getRelocations(parsed_pe *p) {
18061812 return true ;
18071813}
18081814
1815+ bool getDebugDir (parsed_pe *p) {
1816+ data_directory debugDir;
1817+ if (p->peHeader .nt .OptionalMagic == NT_OPTIONAL_32_MAGIC) {
1818+ debugDir = p->peHeader .nt .OptionalHeader .DataDirectory [DIR_DEBUG];
1819+ } else if (p->peHeader .nt .OptionalMagic == NT_OPTIONAL_64_MAGIC) {
1820+ debugDir = p->peHeader .nt .OptionalHeader64 .DataDirectory [DIR_DEBUG];
1821+ } else {
1822+ return false ;
1823+ }
1824+
1825+ if (debugDir.Size != 0 ) {
1826+ section d;
1827+ VA vaAddr;
1828+ if (p->peHeader .nt .OptionalMagic == NT_OPTIONAL_32_MAGIC) {
1829+ vaAddr =
1830+ debugDir.VirtualAddress + p->peHeader .nt .OptionalHeader .ImageBase ;
1831+ } else if (p->peHeader .nt .OptionalMagic == NT_OPTIONAL_64_MAGIC) {
1832+ vaAddr =
1833+ debugDir.VirtualAddress + p->peHeader .nt .OptionalHeader64 .ImageBase ;
1834+ } else {
1835+ return false ;
1836+ }
1837+
1838+ uint32_t numOfDebugEnts = debugDir.Size / sizeof (debug_dir_entry);
1839+
1840+ //
1841+ // this will return the rdata section, where the debug directories are
1842+ //
1843+ if (!getSecForVA (p->internal ->secs , vaAddr, d)) {
1844+ return false ;
1845+ }
1846+
1847+ //
1848+ // get debug directory from this section
1849+ //
1850+ auto rvaofft = static_cast <std::uint32_t >(vaAddr - d.sectionBase );
1851+
1852+ debug_dir_entry emptyEnt;
1853+ memset (&emptyEnt, 0 , sizeof (debug_dir_entry));
1854+
1855+ for (uint32_t i = 0 ; i < numOfDebugEnts; i++) {
1856+ debug_dir_entry curEnt = emptyEnt;
1857+
1858+ READ_DWORD (d.sectionData , rvaofft, curEnt, Characteristics);
1859+ READ_DWORD (d.sectionData , rvaofft, curEnt, TimeStamp);
1860+ READ_WORD (d.sectionData , rvaofft, curEnt, MajorVersion);
1861+ READ_WORD (d.sectionData , rvaofft, curEnt, MinorVersion);
1862+ READ_DWORD (d.sectionData , rvaofft, curEnt, Type);
1863+ READ_DWORD (d.sectionData , rvaofft, curEnt, SizeOfData);
1864+ READ_DWORD (d.sectionData , rvaofft, curEnt, AddressOfRawData);
1865+ READ_DWORD (d.sectionData , rvaofft, curEnt, PointerToRawData);
1866+
1867+ // are all the fields in curEnt null? then we break
1868+ if (curEnt.SizeOfData == 0 && curEnt.AddressOfRawData == 0 &&
1869+ curEnt.PointerToRawData == 0 ) {
1870+ break ;
1871+ }
1872+
1873+ //
1874+ // Get the address of the data
1875+ //
1876+ VA rawData;
1877+ if (p->peHeader .nt .OptionalMagic == NT_OPTIONAL_32_MAGIC) {
1878+ rawData =
1879+ curEnt.AddressOfRawData + p->peHeader .nt .OptionalHeader .ImageBase ;
1880+ } else if (p->peHeader .nt .OptionalMagic == NT_OPTIONAL_64_MAGIC) {
1881+ rawData =
1882+ curEnt.AddressOfRawData + p->peHeader .nt .OptionalHeader64 .ImageBase ;
1883+ } else {
1884+ return false ;
1885+ }
1886+
1887+ //
1888+ // Get the section for the data
1889+ //
1890+ section dataSec;
1891+ if (!getSecForVA (p->internal ->secs , rawData, dataSec)) {
1892+ return false ;
1893+ }
1894+
1895+ debugent ent;
1896+
1897+ auto dataofft = static_cast <std::uint32_t >(rawData - dataSec.sectionBase );
1898+ ent.type = curEnt.Type ;
1899+ ent.data = makeBufferFromPointer (
1900+ reinterpret_cast <std::uint8_t *>(dataSec.sectionData ->buf + dataofft),
1901+ curEnt.SizeOfData );
1902+
1903+ p->internal ->debugdirs .push_back (ent);
1904+
1905+ rvaofft += sizeof (debug_dir_entry);
1906+ }
1907+ }
1908+
1909+ return true ;
1910+ }
1911+
18091912bool getImports (parsed_pe *p) {
18101913 data_directory importDir;
18111914 if (p->peHeader .nt .OptionalMagic == NT_OPTIONAL_32_MAGIC) {
@@ -2434,6 +2537,13 @@ parsed_pe *ParsePEFromBuffer(bounded_buffer *buffer) {
24342537 return nullptr ;
24352538 }
24362539
2540+ if (!getDebugDir (p)) {
2541+ deleteBuffer (remaining);
2542+ DestructParsedPE (p);
2543+ PE_ERR (PEERR_MAGIC);
2544+ return nullptr ;
2545+ }
2546+
24372547 // Get imports
24382548 if (!getImports (p)) {
24392549 deleteBuffer (remaining);
@@ -2493,6 +2603,12 @@ void DestructParsedPE(parsed_pe *p) {
24932603 }
24942604 }
24952605
2606+ for (debugent d : p->internal ->debugdirs ) {
2607+ if (d.data != nullptr ) {
2608+ deleteBuffer (d.data );
2609+ }
2610+ }
2611+
24962612 delete p->internal ;
24972613 delete p;
24982614 return ;
@@ -2524,6 +2640,16 @@ void IterRelocs(parsed_pe *pe, iterReloc cb, void *cbd) {
25242640 return ;
25252641}
25262642
2643+ void IterDebugs (parsed_pe *pe, iterDebug cb, void *cbd) {
2644+ std::vector<debugent> &l = pe->internal ->debugdirs ;
2645+
2646+ for (debugent &d : l) {
2647+ if (cb (cbd, d.type , d.data ) != 0 ) {
2648+ break ;
2649+ }
2650+ }
2651+ }
2652+
25272653// Iterate over symbols (symbol table) in the PE file
25282654void IterSymbols (parsed_pe *pe, iterSymbol cb, void *cbd) {
25292655 std::vector<symbol> &l = pe->internal ->symbols ;
0 commit comments