From 0dfa1ae223b73a155bede7e836b83c6fad66837d Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Tue, 4 Dec 2012 13:08:53 +0100 Subject: [PATCH] winedump: Added MSFT support. --- tools/winedump/Makefile.in | 3 +- tools/winedump/dump.c | 1 + tools/winedump/tlb.c | 735 +++++++++++++++++++++++++++++++++++++ tools/winedump/winedump.h | 6 +- 4 files changed, 743 insertions(+), 2 deletions(-) create mode 100644 tools/winedump/tlb.c diff --git a/tools/winedump/Makefile.in b/tools/winedump/Makefile.in index c61096a9fe..e8e432387a 100644 --- a/tools/winedump/Makefile.in +++ b/tools/winedump/Makefile.in @@ -22,7 +22,8 @@ C_SRCS = \ pdb.c \ pe.c \ search.c \ - symbol.c + symbol.c \ + tlb.c INSTALLDIRS = $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man$(prog_manext) diff --git a/tools/winedump/dump.c b/tools/winedump/dump.c index e882c3cd55..5da8a10343 100644 --- a/tools/winedump/dump.c +++ b/tools/winedump/dump.c @@ -243,6 +243,7 @@ dumpers[] = {SIG_LNK, get_kind_lnk, lnk_dump}, {SIG_EMF, get_kind_emf, emf_dump}, {SIG_FNT, get_kind_fnt, fnt_dump}, + {SIG_MSFT, get_kind_msft, msft_dump}, {SIG_UNKNOWN, NULL, NULL} /* sentinel */ }; diff --git a/tools/winedump/tlb.c b/tools/winedump/tlb.c new file mode 100644 index 0000000000..8cabca2b55 --- /dev/null +++ b/tools/winedump/tlb.c @@ -0,0 +1,735 @@ +/* + * Dump a typelib (tlb) file + * + * Copyright 2006 Jacek Caban + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include + +#include "windef.h" + +#include "winedump.h" + +#define MSFT_MAGIC 0x5446534d +#define HELPDLLFLAG 0x0100 + +enum TYPEKIND { + TKIND_ENUM = 0, + TKIND_RECORD, + TKIND_MODULE, + TKIND_INTERFACE, + TKIND_DISPATCH, + TKIND_COCLASS, + TKIND_ALIAS, + TKIND_UNION, + TKIND_MAX +}; + +struct seg_t; + +typedef int (*dump_seg_t)(struct seg_t*); + +typedef struct seg_t { + const char *name; + dump_seg_t func; + int offset; + int length; +} seg_t; + +extern seg_t segdir[]; + +static int offset=0; +static int indent; +static int typeinfo_cnt; +static int header_flags = 0; +static int msft_eof = 0; + +static int msft_typeinfo_offs[1000]; +static int msft_typeinfo_kind[1000]; +static int msft_typeinfo_impltypes[1000]; +static int msft_typeinfo_elemcnt[1000]; +static int msft_typeinfo_cnt = 0; + +static const void *tlb_read(int size) { + const void *ret = PRD(offset, size); + + if(ret) + offset += size; + else + msft_eof = -1; + + return ret; +} + +static int tlb_read_int(void) +{ + const int *ret = (const int*)tlb_read(sizeof(int)); + return ret ? *ret : -1; +} + +static int tlb_read_short(void) +{ + const short *ret = (const short*)tlb_read(sizeof(short)); + return ret ? *ret : -1; +} + +static int tlb_read_byte(void) +{ + const unsigned char *ret = (const unsigned char*)tlb_read(sizeof(char)); + return ret ? *ret : -1; +} + +static void print_offset(void) +{ + int i; + + printf("%04x: ", offset); + + for(i=0; i>= 2; + buf = tlb_read(len); + fwrite(buf, len, 1, stdout); + printf("\""); + len += 2; + + while(len++ & 3) + printf("\\%02x", tlb_read_byte()); + printf("\n"); +} + +static void dump_binary(int n) +{ + int i; + + for(i = 1; i <= n; i++) { + switch(i & 0x0f) { + case 0: + printf("%02x\n", tlb_read_byte()); + break; + case 1: + print_offset(); + /* fall through */ + default: + printf("%02x ", tlb_read_byte()); + } + } + + if(n&0x0f) + printf("\n"); +} + +static void dump_msft_header(void) +{ + print_begin_block("Header"); + + print_hex("magic1"); + print_hex("magic2"); + print_hex("posguid"); + print_hex("lcid"); + print_hex("lsid2"); + header_flags = print_hex("varflags"); + print_hex("version"); + print_hex("flags"); + typeinfo_cnt = print_dec("ntypeinfos"); + print_hex("helpstring"); + print_hex("helpstringcontext"); + print_hex("helpcontext"); + print_dec("nametablecont"); + print_dec("nametablechars"); + print_hex("NameOffset"); + print_hex("helpfile"); + print_hex("CustomDataOffset"); + print_hex("res44"); + print_hex("res48"); + print_hex("dispatchpos"); + print_hex("res50"); + + print_end_block(); +} + +static void dump_msft_typeinfobase(void) +{ + print_begin_block_id("TypeInfoBase", msft_typeinfo_cnt); + + msft_typeinfo_kind[msft_typeinfo_cnt] = print_hex("typekind"); + msft_typeinfo_offs[msft_typeinfo_cnt] = print_hex("memoffset"); + print_hex("res2"); + print_hex("res3"); + print_hex("res4"); + print_hex("res5"); + msft_typeinfo_elemcnt[msft_typeinfo_cnt] = print_hex("cElement"); + print_hex("res7"); + print_hex("res8"); + print_hex("res9"); + print_hex("resA"); + print_hex("posguid"); + print_hex("flags"); + print_hex("NameOffset"); + print_hex("version"); + print_hex("docstringoffs"); + print_hex("docstringcontext"); + print_hex("helpcontext"); + print_hex("oCustData"); + msft_typeinfo_impltypes[msft_typeinfo_cnt++] = print_short_hex("cImplTypes"); + print_short_hex("bSizeVftt"); + print_dec("size"); + print_hex("datatype1"); + print_hex("datatype2"); + print_hex("res18"); + print_hex("res19"); + + print_end_block(); +} + +static int dump_msft_typeinfobases(seg_t *seg) +{ + int i; + + for(i = 0; offset < seg->offset+seg->length; i++) + dump_msft_typeinfobase(); + + assert(offset == seg->offset+seg->length); + return -1; +} + +static void dump_msft_impinfo(int n) +{ + print_begin_block_id("ImpInfo", n); + + print_hex("flags"); + print_hex("oImpInfo"); + print_hex("oGuid"); + + print_end_block(); +} + +static int dump_msft_impinfos(seg_t *seg) +{ + int i; + + for(i = 0; offset < seg->offset+seg->length; i++) + dump_msft_impinfo(i); + + assert(offset == seg->offset+seg->length); + return -1; +} + +static void dump_msft_impfile(int n) +{ + print_begin_block_id("ImpFile", n); + + print_hex("guid"); + print_hex("lcid"); + print_hex("version"); + print_ctl2("impfile"); + + print_end_block(); +} + +static int dump_msft_impfiles(seg_t *seg) +{ + int i; + + for(i = 0; offset < seg->offset+seg->length; i++) + dump_msft_impfile(i); + + assert(offset == seg->offset+seg->length); + return -1; +} + +static int dump_msft_reftabs(seg_t *seg) +{ + print_begin_block("RefTab"); + + dump_binary(seg->length); /* FIXME */ + + print_end_block(); + + return -1; +} + +static int dump_msft_libtab(seg_t *seg) +{ + print_begin_block("LibTab"); + + dump_binary(seg->length); /* FIXME */ + + print_end_block(); + + assert(offset == seg->offset+seg->length); + return -1; +} + +static void dump_msft_guidentry(int n) +{ + print_begin_block_id("GuidEntry", n); + + print_guid("guid"); + print_hex("hreftype"); + print_hex("next_hash"); + + print_end_block(); +} + +static int dump_msft_guidtab(seg_t *seg) +{ + int i; + + for(i = 0; offset < seg->offset+seg->length; i++) + dump_msft_guidentry(i); + + assert(offset == seg->offset+seg->length); + return -1; +} + +static int dump_msft_res07(seg_t *seg) +{ + print_begin_block("res07"); + + dump_binary(seg->length); /* FIXME */ + + print_end_block(); + return -1; +} + +static void dump_msft_name(int base, int n) +{ + int len; + + print_begin_block_id("Name", n); + + print_hex("hreftype"); + print_hex("next_hash"); + len = print_hex("namelen")&0xff; + + print_offset(); + printf("name = \""); + fwrite(tlb_read(len), len, 1, stdout); + printf("\" "); + while(len++ & 3) + printf("\\%2.2x", tlb_read_byte()); + printf("\n"); + + print_end_block(); +} + +static int dump_msft_nametab(seg_t *seg) +{ + int i, base = offset; + + for(i = 0; offset < seg->offset+seg->length; i++) + dump_msft_name(base, i); + + assert(offset == seg->offset+seg->length); + return -1; +} + +static int dump_msft_stringtab(seg_t *seg) +{ + print_begin_block("StringTab"); + + dump_binary(seg->length); /* FIXME */ + + print_end_block(); + + return -1; +} + +static void dump_msft_typedesc(int n) +{ + print_begin_block_id("TYPEDESC", n); + + print_hex("hreftype"); + print_hex("vt"); + + print_end_block(); +} + +static int dump_msft_typedesctab(seg_t *seg) +{ + int i; + + print_begin_block("TypedescTab"); + + for(i = 0; offset < seg->offset+seg->length; i++) + dump_msft_typedesc(i); + + print_end_block(); + + assert(offset == seg->offset+seg->length); + return -1; +} + +static int dump_msft_arraydescs(seg_t *seg) +{ + print_begin_block("ArrayDescriptions"); + + dump_binary(seg->length); /* FIXME */ + + print_end_block(); + return -1; +} + +static int dump_msft_custdata(seg_t *seg) +{ + print_begin_block("CustData"); + + dump_binary(seg->length); /* FIXME */ + + print_end_block(); + return -1; +} + +static void dump_msft_cdguid(int n) +{ + print_begin_block_id("CGUid", n); + + print_hex("GuidOffset"); + print_hex("DataOffset"); + print_hex("next"); + + print_end_block(); +} + +static int dump_msft_cdguids(seg_t *seg) +{ + int i; + + for(i = 0; offset < seg->offset+seg->length; i++) + dump_msft_cdguid(i); + + assert(offset == seg->offset+seg->length); + return -1; +} + +static int dump_msft_res0e(seg_t *seg) +{ + print_begin_block("res0e"); + dump_binary(seg->length); + print_end_block(); + + return -1; +} + +static int dump_msft_res0f(seg_t *seg) +{ + print_begin_block("res0f"); + dump_binary(seg->length); + print_end_block(); + + return -1; +} + +static void dump_msft_func(int n) +{ + int size, args_cnt, i, extra_attr; + + print_begin_block_id("FuncRecord", n); + + size = print_short_hex("size"); + print_short_hex("index"); + print_hex("DataType"); + print_hex("flags"); + print_short_hex("VtableOffset"); + print_short_hex("funcdescsize"); + print_hex("FKCCIC"); + args_cnt = print_short_hex("nrargs"); + print_short_hex("noptargs"); + + extra_attr = size/sizeof(INT) - 6 - args_cnt*3; + + if(extra_attr) + print_hex("helpcontext"); + if(extra_attr >= 2) + print_hex("oHelpString"); + if(extra_attr >= 3) + print_hex("toEntry"); + if(extra_attr >= 4) + print_hex("res9"); + if(extra_attr >= 5) + print_hex("resA"); + if(extra_attr >= 6) + print_hex("HelpStringContext"); + if(extra_attr >= 7) + print_hex("oCustData"); + + for(i=0; i < args_cnt; i++) { + print_begin_block_id("param", i); + + /* FIXME: Handle default values */ + print_hex("data[0]"); + print_hex("paramflags"); + print_hex("data[2]"); + + print_end_block(); + } + + print_end_block(); +} + +static void dump_msft_var(int n) +{ + INT size; + + print_begin_block_id("VarRecord", n); + + size = print_hex("recsize")&0x1ff; + print_hex("DataType"); + print_hex("flags"); + print_short_hex("VarKind"); + print_short_hex("vardescsize"); + print_hex("OffsValue"); + + if(size > 5*sizeof(INT)) + dump_binary(size - 5*sizeof(INT)); + + print_end_block(); +} + +static void dump_msft_ref(int n) +{ + print_begin_block_id("RefRecord", n); + + print_hex("reftype"); + print_hex("flags"); + print_hex("oCustData"); + print_hex("onext"); + + print_end_block(); +} + +static void dump_msft_coclass(int n) +{ + int i; + + print_dec("size"); + + for(i=0; i < msft_typeinfo_impltypes[n]; i++) + dump_msft_ref(i); +} + +static int dump_msft_typeinfo(int n) +{ + int i; + + print_begin_block_id("TypeInfo", n); + + if((msft_typeinfo_kind[n] & 0xf) == TKIND_COCLASS) { + dump_msft_coclass(n); + print_end_block(); + return -1; + } + + print_dec("size"); + + for(i = 0; i < LOWORD(msft_typeinfo_elemcnt[n]); i++) + dump_msft_func(i); + + for(i = 0; i < HIWORD(msft_typeinfo_elemcnt[n]); i++) + dump_msft_var(i); + + for(i = 0; i < LOWORD(msft_typeinfo_elemcnt[n]); i++) + print_hex_id("func %d id", i); + + for(i = 0; i < HIWORD(msft_typeinfo_elemcnt[n]); i++) + print_hex_id("var %d id", i); + + for(i = 0; i < LOWORD(msft_typeinfo_elemcnt[n]); i++) + print_hex_id("func %d name", i); + + for(i = 0; i < HIWORD(msft_typeinfo_elemcnt[n]); i++) + print_hex_id("var %d name", i); + + for(i = 0; i < LOWORD(msft_typeinfo_elemcnt[n]); i++) + print_hex_id("func %d offset", i); + + for(i = 0; i < HIWORD(msft_typeinfo_elemcnt[n]); i++) + print_hex_id("var %d offset", i); + + print_end_block(); + + return -1; +} + +seg_t segdir[] = { + {"TypeInfoTab", dump_msft_typeinfobases, -1, -1}, + {"ImpInfo", dump_msft_impinfos, -1, -1}, + {"ImpFiles", dump_msft_impfiles, -1, -1}, + {"RefTab", dump_msft_reftabs, -1, -1}, + {"LibTab", dump_msft_libtab, -1, -1}, + {"GuidTab", dump_msft_guidtab, -1, -1}, + {"res07", dump_msft_res07, -1, -1}, + {"pNameTab", dump_msft_nametab, -1, -1}, + {"pStringTab", dump_msft_stringtab, -1, -1}, + {"TypedescTab", dump_msft_typedesctab, -1, -1}, + {"ArrayDescriptions", dump_msft_arraydescs, -1, -1}, + {"CustData", dump_msft_custdata, -1, -1}, + {"CDGuid", dump_msft_cdguids, -1, -1}, + {"res0e", dump_msft_res0e, -1, -1}, + {"res0f", dump_msft_res0f, -1, -1} +}; + +static void dump_msft_seg(seg_t *seg) +{ + print_begin_block(seg->name); + + seg->offset = print_hex("offset"); + seg->length = print_dec("length"); + print_hex("res08"); + print_hex("res0c"); + + print_end_block(); +} + +static void dump_msft_segdir(void) +{ + int i; + + print_begin_block("SegDir"); + + for(i=0; i < sizeof(segdir)/sizeof(segdir[0]); i++) + dump_msft_seg(segdir+i); + + print_end_block(); +} + +static int dump_offset(void) +{ + int i; + + for(i=0; i < sizeof(segdir)/sizeof(segdir[0]); i++) + if(segdir[i].offset == offset) + return segdir[i].func(segdir+i); + + for(i=0; i < msft_typeinfo_cnt; i++) + if(msft_typeinfo_offs[i] == offset) + return dump_msft_typeinfo(i); + + return 0; +} + +enum FileSig get_kind_msft(void) +{ + const DWORD *sig = PRD(0, sizeof(DWORD)); + return sig && *sig == MSFT_MAGIC ? SIG_MSFT : SIG_UNKNOWN; +} + +void msft_dump(void) +{ + int i; + + dump_msft_header(); + + for(i=0; i < typeinfo_cnt; i++) + print_hex_id("typeinfo %d offset", i); + + if(header_flags & HELPDLLFLAG) + print_hex("help dll offset"); + print_offset(); + printf("\n"); + + dump_msft_segdir(); + + while(!msft_eof) { + if(!dump_offset()) + print_hex("unknown"); + } +} diff --git a/tools/winedump/winedump.h b/tools/winedump/winedump.h index 11f36f360e..dcaa40cd61 100644 --- a/tools/winedump/winedump.h +++ b/tools/winedump/winedump.h @@ -215,7 +215,8 @@ char *str_toupper (char *str); const char *get_machine_str(int mach); /* file dumping functions */ -enum FileSig {SIG_UNKNOWN, SIG_DOS, SIG_PE, SIG_DBG, SIG_PDB, SIG_NE, SIG_LE, SIG_MDMP, SIG_COFFLIB, SIG_LNK, SIG_EMF, SIG_FNT}; +enum FileSig {SIG_UNKNOWN, SIG_DOS, SIG_PE, SIG_DBG, SIG_PDB, SIG_NE, SIG_LE, SIG_MDMP, SIG_COFFLIB, SIG_LNK, + SIG_EMF, SIG_FNT, SIG_MSFT}; const void* PRD(unsigned long prd, unsigned long len); unsigned long Offset(const void* ptr); @@ -252,6 +253,9 @@ enum FileSig get_kind_pdb(void); void pdb_dump(void); enum FileSig get_kind_fnt(void); void fnt_dump( void ); +enum FileSig get_kind_msft(void); +void msft_dump(void); + int codeview_dump_symbols(const void* root, unsigned long size); int codeview_dump_types_from_offsets(const void* table, const DWORD* offsets, unsigned num_types); int codeview_dump_types_from_block(const void* table, unsigned long len); -- 2.32.0.93.g670b81a890