void ne_dump( void ) { unsigned int i; const IMAGE_DOS_HEADER *dos; const IMAGE_OS2_HEADER *ne; dos = PRD(0, sizeof(*dos)); if (!dos) return; ne = PRD(dos->e_lfanew, sizeof(*ne)); if (globals.do_dumpheader || !globals.dumpsect) dump_ne_header( ne ); if (globals.do_dumpheader) dump_ne_names( ne ); if (globals.dumpsect) { BOOL all = strcmp(globals.dumpsect, "ALL") == 0; if (all || !strcmp(globals.dumpsect, "resource")) dump_ne_resources( ne ); if (all || !strcmp(globals.dumpsect, "export")) dump_ne_exports( ne ); } if (globals.do_dumpheader) for (i = 1; i <= ne->ne_cseg; i++) dump_ne_segment( ne, i ); }
static BOOL dump_cv_sst_module(const OMFDirEntry* omfde) { const OMFModule* module; const OMFSegDesc* segDesc; int i; module = PRD(Offset(cv_base) + omfde->lfo, sizeof(OMFModule)); if (!module) {printf("Can't get the OMF-Module, aborting\n"); return FALSE;} printf(" olvNumber: %u\n", module->ovlNumber); printf(" iLib: %u\n", module->iLib); printf(" cSeg: %u\n", module->cSeg); printf(" Style: %c%c\n", module->Style[0], module->Style[1]); printf(" Name: %.*s\n", *(const BYTE*)((const char*)(module + 1) + sizeof(OMFSegDesc) * module->cSeg), (const char*)(module + 1) + sizeof(OMFSegDesc) * module->cSeg + 1); segDesc = PRD(Offset(module + 1), sizeof(OMFSegDesc) * module->cSeg); if (!segDesc) {printf("Can't get the OMF-SegDesc, aborting\n"); return FALSE;} for (i = 0; i < module->cSeg; i++) { printf (" segment #%2d: offset = [0x%8x], size = [0x%8x]\n", segDesc->Seg, segDesc->Off, segDesc->cbSeg); segDesc++; } return TRUE; }
static BOOL dump_cv_sst_seg_map(const OMFDirEntry* omfde) { const OMFSegMap* segMap; const OMFSegMapDesc* segMapDesc; int i; segMap = PRD(Offset(cv_base) + omfde->lfo, sizeof(OMFSegMap)); if (!segMap) {printf("Can't get SegMap, aborting\n");return FALSE;} printf(" cSeg: %u\n", segMap->cSeg); printf(" cSegLog: %u\n", segMap->cSegLog); segMapDesc = PRD(Offset(segMap + 1), segMap->cSeg * sizeof(OMFSegDesc)); if (!segMapDesc) {printf("Can't get SegDescr array, aborting\n");return FALSE;} for (i = 0; i < segMap->cSeg; i++) { printf(" SegDescr #%2d\n", i + 1); printf(" flags: %04X\n", segMapDesc[i].flags); printf(" ovl: %u\n", segMapDesc[i].ovl); printf(" group: %u\n", segMapDesc[i].group); printf(" frame: %u\n", segMapDesc[i].frame); printf(" iSegName: %u\n", segMapDesc[i].iSegName); printf(" iClassName: %u\n", segMapDesc[i].iClassName); printf(" offset: %lu\n", segMapDesc[i].offset); printf(" cbSeg: %lu\n", segMapDesc[i].cbSeg); } return TRUE; }
static BOOL dump_cv_sst_global_types(const OMFDirEntry* omfde) { long fileoffset; const OMFGlobalTypes*types; const BYTE* data; unsigned sz; fileoffset = Offset(cv_base) + omfde->lfo; printf (" GlobalTypes section starts at file offset 0x%lx\n", fileoffset); printf ("\n ----- Begin Global Types Table -----\n"); types = PRD(fileoffset, sizeof(OMFGlobalTypes)); if (!types) {printf("Can't get OMF-GlobalTypes, aborting\n");return FALSE;} sz = omfde->cb - sizeof(OMFGlobalTypes) - sizeof(DWORD) * types->cTypes; data = PRD(fileoffset + sizeof(OMFGlobalTypes) + sizeof(DWORD) * types->cTypes, sz); if (!data) {printf("Can't OMF-SymHash details, aborting\n"); return FALSE;} /* doc says: * - for NB07 & NB08 (that we don't support yet), offsets are from types * - for NB09, offsets are from data * For now, we only support the latter */ codeview_dump_types_from_offsets(data, (const DWORD*)(types + 1), types->cTypes); return TRUE; }
static const IMAGE_NT_HEADERS32 *get_nt_header( void ) { const IMAGE_DOS_HEADER *dos; dos = PRD(0, sizeof(*dos)); if (!dos) return NULL; return PRD(dos->e_lfanew, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER)); }
static const void* fetch_block(void) { const unsigned* u; const void* ret; if (!(u = PRD(offset, sizeof(*u)))) return 0; if ((ret = PRD(offset, *u))) offset += *u; return ret; }
static const lnk_string* fetch_string(int unicode) { const unsigned short* s; unsigned short len; const void* ret; if (!(s = PRD(offset, sizeof(*s)))) return 0; len = *s * (unicode ? sizeof(WCHAR) : sizeof(char)); if ((ret = PRD(offset, sizeof(*s) + len))) offset += sizeof(*s) + len; return ret; }
enum FileSig get_kind_pdb(void) { const char* head; head = PRD(0, sizeof(pdb2) - 1); if (head && !memcmp(head, pdb2, sizeof(pdb2) - 1)) return SIG_PDB; head = PRD(0, sizeof(pdb7) - 1); if (head && !memcmp(head, pdb7, sizeof(pdb7) - 1)) return SIG_PDB; return SIG_UNKNOWN; }
static void dump_ne_resources( const IMAGE_OS2_HEADER *ne ) { const NE_NAMEINFO *name; const void *res_ptr = (const char *)ne + ne->ne_rsrctab; WORD size_shift = get_word(res_ptr); const NE_TYPEINFO *info = (const NE_TYPEINFO *)((const WORD *)res_ptr + 1); int count; printf( "\nResources:\n" ); while (info->type_id != 0 && (const char *)info < (const char *)ne + ne->ne_restab) { name = (const NE_NAMEINFO *)(info + 1); for (count = info->count; count > 0; count--, name++) { if (name->id & 0x8000) printf( " %d", (name->id & ~0x8000) ); else printf( " %.*s", *((const unsigned char *)res_ptr + name->id), (const char *)res_ptr + name->id + 1 ); if (info->type_id & 0x8000) printf( " %s", get_resource_type(info->type_id) ); else printf( " %.*s", *((const unsigned char *)res_ptr + info->type_id), (const char *)res_ptr + info->type_id + 1 ); printf(" flags %04x length %04x\n", name->flags, name->length << size_shift); dump_data( PRD(name->offset << size_shift, name->length << size_shift), name->length << size_shift, " " ); } info = (const NE_TYPEINFO *)name; } }
void dump_frame_pointer_omission(unsigned long base, unsigned long len) { const FPO_DATA* fpo; const FPO_DATA* last; const char* x; /* FPO is used to describe nonstandard stack frames */ printf("Range #loc #pmt Prlg #reg Info\n" "-----------------+----+----+----+----+------------\n"); fpo = PRD(base, len); if (!fpo) {printf("Couldn't get FPO blob\n"); return;} last = (const FPO_DATA*)((const char*)fpo + len); while (fpo < last && fpo->ulOffStart) { switch (fpo->cbFrame) { case FRAME_FPO: x = "FRAME_FPO"; break; case FRAME_NONFPO: x = "FRAME_NONFPO"; break; case FRAME_TRAP: x = "FRAME_TRAP"; break; case FRAME_TSS: x = "case FRAME_TSS"; break; default: x = NULL; break; } printf("%08x-%08x %4u %4u %4u %4u %s%s%s\n", fpo->ulOffStart, fpo->ulOffStart + fpo->cbProcSize, fpo->cdwLocals, fpo->cdwParams, fpo->cbProlog, fpo->cbRegs, x, fpo->fHasSEH ? " SEH" : "", fpo->fUseBP ? " UseBP" : ""); fpo++; } }
void dump_coff(unsigned long coffbase, unsigned long len, const IMAGE_SECTION_HEADER* sectHead) { const IMAGE_COFF_SYMBOLS_HEADER *coff = PRD(coffbase, len); const IMAGE_SYMBOL *coff_symbols = (const IMAGE_SYMBOL *) ((const char *)coff + coff->LvaToFirstSymbol); dump_coff_symbol_table(coff_symbols, coff->NumberOfSymbols, sectHead); }
void le_dump( void ) { const IMAGE_DOS_HEADER *dos; const IMAGE_VXD_HEADER *le; dos = PRD(0, sizeof(*dos)); if (!dos) return; le = PRD(dos->e_lfanew, sizeof(*le)); dump_le_header( le ); dump_le_objects( le ); dump_le_resources( le ); dump_le_names( le ); dump_le_entries( le ); dump_le_modules( le ); dump_le_fixups( le ); dump_le_VxD( le ); }
static void pdb_jg_init(struct pdb_reader* reader) { reader->u.jg.header = PRD(0, sizeof(struct PDB_JG_HEADER)); reader->read_file = pdb_jg_read_file; reader->u.jg.toc = pdb_jg_read(reader->u.jg.header, reader->u.jg.header->toc_block, reader->u.jg.header->toc.size); memset(reader->file_used, 0, sizeof(reader->file_used)); }
enum FileSig get_kind_emf(void) { const ENHMETAHEADER* hdr; hdr = PRD(0, sizeof(*hdr)); if (hdr && hdr->iType == EMR_HEADER && hdr->dSignature == ENHMETA_SIGNATURE) return SIG_EMF; return SIG_UNKNOWN; }
static BOOL dump_cv_sst_align_sym(const OMFDirEntry* omfde) { const char* rawdata = PRD(Offset(cv_base) + omfde->lfo, omfde->cb); if (!rawdata) {printf("Can't get srcAlignSym subsection details, aborting\n");return FALSE;} if (omfde->cb < sizeof(DWORD)) return TRUE; codeview_dump_symbols(rawdata + sizeof(DWORD), omfde->cb - sizeof(DWORD)); return TRUE; }
static const void *tlb_read(int size) { const void *ret = PRD(offset, size); if(ret) offset += size; else msft_eof = -1; return ret; }
enum FileSig get_kind_lnk(void) { const LINK_HEADER* hdr; hdr = PRD(0, sizeof(*hdr)); if (hdr && hdr->dwSize == sizeof(LINK_HEADER) && !memcmp(&hdr->MagicGuid, &CLSID_ShellLink, sizeof(GUID))) return SIG_LNK; return SIG_UNKNOWN; }
void pdb_dump(void) { const char* head; /* init_types(); */ head = PRD(0, sizeof(pdb2) - 1); if (head && !memcmp(head, pdb2, sizeof(pdb2) - 1)) { pdb_jg_dump(); return; } head = PRD(0, sizeof(pdb7) - 1); if (head && !memcmp(head, pdb7, sizeof(pdb7) - 1)) { pdb_ds_dump(); return; } printf("Unrecognized header %s\n", head); }
static int is_fake_dll( void ) { static const char fakedll_signature[] = "Wine placeholder DLL"; const IMAGE_DOS_HEADER *dos; dos = PRD(0, sizeof(*dos) + sizeof(fakedll_signature)); if (dos && dos->e_lfanew >= sizeof(*dos) + sizeof(fakedll_signature) && !memcmp( dos + 1, fakedll_signature, sizeof(fakedll_signature) )) return TRUE; return FALSE; }
static BOOL pdb_ds_init(struct pdb_reader* reader) { reader->u.ds.header = PRD(0, sizeof(*reader->u.ds.header)); if (!reader->u.ds.header) return FALSE; reader->read_file = pdb_ds_read_file; reader->u.ds.toc = pdb_ds_read(reader->u.ds.header, (const DWORD*)((const char*)reader->u.ds.header + reader->u.ds.header->toc_page * reader->u.ds.header->block_size), reader->u.ds.header->toc_size); memset(reader->file_used, 0, sizeof(reader->file_used)); return TRUE; }
static void dump_codeview_all_modules(const OMFDirHeader *omfdh) { unsigned i; const OMFDirEntry* dirEntry; const char* str; if (!omfdh || !omfdh->cDir) return; dirEntry = PRD(Offset(omfdh + 1), omfdh->cDir * sizeof(OMFDirEntry)); if (!dirEntry) {printf("Can't read DirEntry array, aborting\n"); return;} for (i = 0; i < omfdh->cDir; i++) { switch (dirEntry[i].SubSection) { case sstModule: str = "sstModule"; break; case sstAlignSym: str = "sstAlignSym"; break; case sstSrcModule: str = "sstSrcModule"; break; case sstLibraries: str = "sstLibraries"; break; case sstGlobalSym: str = "sstGlobalSym"; break; case sstGlobalPub: str = "sstGlobalPub"; break; case sstGlobalTypes: str = "sstGlobalTypes"; break; case sstSegMap: str = "sstSegMap"; break; case sstFileIndex: str = "sstFileIndex"; break; case sstStaticSym: str = "sstStaticSym"; break; default: str = "<undefined>"; break; } printf("Module #%2d (%p)\n", i + 1, &dirEntry[i]); printf(" SubSection: %04X (%s)\n", dirEntry[i].SubSection, str); printf(" iMod: %d\n", dirEntry[i].iMod); printf(" lfo: %d\n", dirEntry[i].lfo); printf(" cb: %u\n", dirEntry[i].cb); switch (dirEntry[i].SubSection) { case sstModule: dump_cv_sst_module(&dirEntry[i]); break; case sstAlignSym: dump_cv_sst_align_sym(&dirEntry[i]); break; case sstSrcModule: dump_cv_sst_src_module(&dirEntry[i]); break; case sstLibraries: dump_cv_sst_libraries(&dirEntry[i]); break; case sstGlobalSym: dump_cv_sst_global_sym(&dirEntry[i]); break; case sstGlobalPub: dump_cv_sst_global_pub(&dirEntry[i]); break; case sstGlobalTypes: dump_cv_sst_global_types(&dirEntry[i]); break; case sstSegMap: dump_cv_sst_seg_map(&dirEntry[i]); break; case sstFileIndex: dump_cv_sst_file_index(&dirEntry[i]); break; case sstStaticSym: dump_cv_sst_static_sym(&dirEntry[i]); break; default: printf("unsupported type %x\n", dirEntry[i].SubSection); break; } printf("\n"); } return; }
static BOOL dump_cv_sst_global_pub(const OMFDirEntry* omfde) { long fileoffset; const OMFSymHash* header; const BYTE* symbols; fileoffset = Offset(cv_base) + omfde->lfo; printf (" GlobalPub section starts at file offset 0x%lx\n", fileoffset); printf (" Symbol table starts at 0x%lx\n", fileoffset + sizeof (OMFSymHash)); printf ("\n ----- Begin Symbol Table -----\n"); header = PRD(fileoffset, sizeof(OMFSymHash)); if (!header) {printf("Can't get OMF-SymHash, aborting\n");return FALSE;} symbols = PRD(fileoffset + sizeof(OMFSymHash), header->cbSymbol); if (!symbols) {printf("Can't OMF-SymHash details, aborting\n"); return FALSE;} codeview_dump_symbols(symbols, header->cbSymbol); return TRUE; }
static void dump_ne_segment( const IMAGE_OS2_HEADER *ne, int segnum ) { const struct ne_segtable_entry *table = (const struct ne_segtable_entry *)((const BYTE *)ne + ne->ne_segtab); const struct ne_segtable_entry *seg = table + segnum - 1; printf( "\nSegment %d:\n", segnum ); printf( " File offset: %08x\n", seg->seg_data_offset << ne->ne_align ); printf( " Length: %08x\n", seg->seg_data_length ); printf( " Flags: %08x %s\n", seg->seg_flags, get_seg_flags(seg->seg_flags) ); printf( " Alloc size: %08x\n", seg->min_alloc ); if (seg->seg_flags & NE_SEGFLAGS_RELOC_DATA) { const BYTE *ptr = PRD((seg->seg_data_offset << ne->ne_align) + seg->seg_data_length, 0); WORD count = get_word(ptr); ptr += sizeof(WORD); printf( " Relocations:\n" ); dump_relocations( ne, count, (const struct relocation_entry *)ptr ); } }
static const void* RVA(unsigned long rva, unsigned long len) { IMAGE_SECTION_HEADER* sectHead; int i; if (rva == 0) return NULL; sectHead = IMAGE_FIRST_SECTION(PE_nt_headers); for (i = PE_nt_headers->FileHeader.NumberOfSections - 1; i >= 0; i--) { if (sectHead[i].VirtualAddress <= rva && rva + len <= (DWORD)sectHead[i].VirtualAddress + sectHead[i].SizeOfRawData) { /* return image import directory offset */ return PRD(sectHead[i].PointerToRawData + rva - sectHead[i].VirtualAddress, len); } } return NULL; }
static void dump_ne_names( const IMAGE_OS2_HEADER *ne ) { const unsigned char *pstr = (const unsigned char *)ne + ne->ne_restab; printf( "\nResident name table:\n" ); while (*pstr) { printf( " %4d: %*.*s\n", get_word(pstr + *pstr + 1), *pstr, *pstr, pstr + 1 ); pstr += *pstr + 1 + sizeof(WORD); } if (ne->ne_cbnrestab) { unsigned int pos = ne->ne_nrestab; printf( "\nNon-resident name table:\n" ); while ((pstr = PRD(pos, 0)) && *pstr) { printf( " %4d: %*.*s\n", get_word(pstr + *pstr + 1), *pstr, *pstr, pstr + 1 ); pos += *pstr + 1 + sizeof(WORD); } } }
int main() { int i; int* p; for (i = 0; i <= 4; i++) PRD(a[i]); // 01234 NL; for (p = &a[0]; p <= &a[4]; p++) PRD(*p); // 01234 NL; for (p = &a[0], i = 0; i <= 4; i++) PRD(p[i]); // 01234 NL; for (p = a, i = 0; p + i <= a + 4; p++, i++) PRD(*(p + i)); // 024 NL; for (p = a + 4; p >= a; p--) PRD(*p); // 43210 NL; for (p = a + 4, i = 0; i <= 4; i++) PRD(p[-i]); // 43210 NL; for (p = a + 4; p >= a; p--) PRD(a[p - a]); // 43210 NL; return 0; }
static void dump_le_names( const IMAGE_VXD_HEADER *le ) { const unsigned char *pstr = (const unsigned char *)le + le->e32_restab; printf( "\nResident name table:\n" ); while (*pstr) { printf( " %4d: %*.*s\n", get_word(pstr + *pstr + 1), *pstr, *pstr, pstr + 1 ); pstr += *pstr + 1 + sizeof(WORD); } if (le->e32_cbnrestab) { printf( "\nNon-resident name table:\n" ); pstr = PRD(le->e32_nrestab, 0); while (*pstr) { printf( " %4d: %*.*s\n", get_word(pstr + *pstr + 1), *pstr, *pstr, pstr + 1 ); pstr += *pstr + 1 + sizeof(WORD); } } }
static const char *get_export_name( const IMAGE_OS2_HEADER *ne, int ordinal ) { static char name[256]; const BYTE *pstr; int pass = 0; /* search the resident names */ while (pass < 2) { if (pass == 0) /* resident names */ { pstr = (const BYTE *)ne + ne->ne_restab; if (*pstr) pstr += *pstr + 1 + sizeof(WORD); /* skip first entry (module name) */ } else /* non-resident names */ { if (!ne->ne_cbnrestab) break; pstr = PRD(ne->ne_nrestab, 0); } while (*pstr) { WORD ord = get_word(pstr + *pstr + 1); if (ord == ordinal) { memcpy( name, pstr + 1, *pstr ); name[*pstr] = 0; return name; } pstr += *pstr + 1 + sizeof(WORD); } pass++; } name[0] = 0; return name; }
static void dump_codeview_headers(unsigned long base, unsigned long len) { const OMFDirHeader* dirHeader; const char* signature; const OMFDirEntry* dirEntry; const OMFSignature* sig; unsigned i; int modulecount = 0, alignsymcount = 0, srcmodulecount = 0, librariescount = 0; int globalsymcount = 0, globalpubcount = 0, globaltypescount = 0; int segmapcount = 0, fileindexcount = 0, staticsymcount = 0; cv_base = PRD(base, len); if (!cv_base) {printf("Can't get full debug content, aborting\n");return;} signature = cv_base; printf(" CodeView Data\n"); printf(" Signature: %.4s\n", signature); if (memcmp(signature, "NB10", 4) == 0) { const CODEVIEW_PDB_DATA* pdb_data; pdb_data = (const void *)cv_base; printf(" Filepos: 0x%08lX\n", pdb_data->filepos); printf(" TimeStamp: %08X (%s)\n", pdb_data->timestamp, get_time_str(pdb_data->timestamp)); printf(" Age: %08X\n", pdb_data->age); printf(" Filename: %s\n", pdb_data->name); return; } if (memcmp(signature, "RSDS", 4) == 0) { const OMFSignatureRSDS* rsds_data; rsds_data = (const void *)cv_base; printf(" Guid: %s\n", get_guid_str(&rsds_data->guid)); printf(" Age: %08X\n", rsds_data->age); printf(" Filename: %s\n", rsds_data->name); return; } if (memcmp(signature, "NB09", 4) != 0 && memcmp(signature, "NB11", 4) != 0) { printf("Unsupported signature (%.4s), aborting\n", signature); return; } sig = cv_base; printf(" Filepos: 0x%08lX\n", sig->filepos); dirHeader = PRD(Offset(cv_base) + sig->filepos, sizeof(OMFDirHeader)); if (!dirHeader) {printf("Can't get debug header, aborting\n"); return;} printf(" Size of header: 0x%4X\n", dirHeader->cbDirHeader); printf(" Size per entry: 0x%4X\n", dirHeader->cbDirEntry); printf(" # of entries: 0x%8X (%d)\n", dirHeader->cDir, dirHeader->cDir); printf(" Offset to NextDir: 0x%8X\n", dirHeader->lfoNextDir); printf(" Flags: 0x%8X\n", dirHeader->flags); if (!dirHeader->cDir) return; dirEntry = PRD(Offset(dirHeader + 1), sizeof(OMFDirEntry) * dirHeader->cDir); if (!dirEntry) {printf("Can't get DirEntry array, aborting\n");return;} for (i = 0; i < dirHeader->cDir; i++) { switch (dirEntry[i].SubSection) { case sstModule: modulecount++; break; case sstAlignSym: alignsymcount++; break; case sstSrcModule: srcmodulecount++; break; case sstLibraries: librariescount++; break; case sstGlobalSym: globalsymcount++; break; case sstGlobalPub: globalpubcount++; break; case sstGlobalTypes: globaltypescount++; break; case sstSegMap: segmapcount++; break; case sstFileIndex: fileindexcount++; break; case sstStaticSym: staticsymcount++; break; } } /* This one has to be > 0 */ printf ("\nFound: %d sstModule subsections\n", modulecount); if (alignsymcount > 0) printf (" %d sstAlignSym subsections\n", alignsymcount); if (srcmodulecount > 0) printf (" %d sstSrcModule subsections\n", srcmodulecount); if (librariescount > 0) printf (" %d sstLibraries subsections\n", librariescount); if (globalsymcount > 0) printf (" %d sstGlobalSym subsections\n", globalsymcount); if (globalpubcount > 0) printf (" %d sstGlobalPub subsections\n", globalpubcount); if (globaltypescount > 0) printf (" %d sstGlobalTypes subsections\n", globaltypescount); if (segmapcount > 0) printf (" %d sstSegMap subsections\n", segmapcount); if (fileindexcount > 0) printf (" %d sstFileIndex subsections\n", fileindexcount); if (staticsymcount > 0) printf (" %d sstStaticSym subsections\n", staticsymcount); dump_codeview_all_modules(dirHeader); }
enum FileSig get_kind_msft(void) { const DWORD *sig = PRD(0, sizeof(DWORD)); return sig && *sig == MSFT_MAGIC ? SIG_MSFT : SIG_UNKNOWN; }