winedump: Add initial version of old (SLTG) typelib dumper.
Dmitry Timoshkov
dmitry at baikal.ru
Wed Dec 9 07:30:22 CST 2015
Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
---
tools/winedump/dump.c | 2 +-
tools/winedump/tlb.c | 377 ++++++++++++++++++++++++++++++++++++++++++----
tools/winedump/winedump.h | 6 +-
3 files changed, 350 insertions(+), 35 deletions(-)
diff --git a/tools/winedump/dump.c b/tools/winedump/dump.c
index e84e473..f608075 100644
--- a/tools/winedump/dump.c
+++ b/tools/winedump/dump.c
@@ -241,7 +241,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_TLB, get_kind_tlb, tlb_dump},
{SIG_UNKNOWN, NULL, NULL} /* sentinel */
};
diff --git a/tools/winedump/tlb.c b/tools/winedump/tlb.c
index df1ea4b..bc78765 100644
--- a/tools/winedump/tlb.c
+++ b/tools/winedump/tlb.c
@@ -2,6 +2,7 @@
* Dump a typelib (tlb) file
*
* Copyright 2006 Jacek Caban
+ * Copyright 2015 Dmitry Timoshkov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -30,6 +31,7 @@
#include "winedump.h"
#define MSFT_MAGIC 0x5446534d
+#define SLTG_MAGIC 0x47544c53
#define HELPDLLFLAG 0x0100
enum TYPEKIND {
@@ -109,7 +111,7 @@ typedef struct seg_t {
int offset;
int length;
} seg_t;
-static seg_t segdir[];
+static seg_t segdir[15];
enum SEGDIRTYPE {
SEGDIR_TYPEINFO,
@@ -134,6 +136,7 @@ static int indent;
static int typeinfo_cnt;
static int header_flags = 0;
static BOOL msft_eof = FALSE;
+static int sltg_first_blk;
static int msft_typeinfo_offs[1000];
static int msft_typeinfo_kind[1000];
@@ -160,7 +163,7 @@ static int tlb_read_int(void)
static int tlb_read_short(void)
{
- const short *ret = tlb_read(sizeof(short));
+ const unsigned short *ret = tlb_read(sizeof(short));
return ret ? *ret : -1;
}
@@ -173,9 +176,6 @@ static int tlb_read_byte(void)
static void print_offset(void)
{
int i;
-
- printf("%04x: ", offset);
-
for(i=0; i<indent; i++)
printf(" ");
}
@@ -226,6 +226,14 @@ static int print_short_hex(const char *name)
return ret;
}
+static int print_short_dec(const char *name)
+{
+ int ret;
+ print_offset();
+ printf("%s = %d\n", name, ret=tlb_read_short());
+ return ret;
+}
+
static int print_dec(const char *name)
{
int ret;
@@ -286,25 +294,45 @@ static void print_ctl2(const char *name)
printf("\n");
}
-static void dump_binary(int n)
+static int _isprint(unsigned char c)
{
- int i;
+ return c >= 32 ? 1 : 0;
+}
- 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());
+static void dump_binary(int size)
+{
+ const unsigned char *ptr;
+ int i, j;
+
+ ptr = tlb_read(size);
+ if (!ptr) return;
+
+ print_offset();
+ printf("%08x: ", offset - size);
+
+ for (i = 0; i < size; i++)
+ {
+ printf("%02x%c", ptr[i], (i % 16 == 7) ? '-' : ' ');
+ if ((i % 16) == 15)
+ {
+ printf( " " );
+ for (j = 0; j < 16; j++)
+ printf("%c", _isprint(ptr[i-15+j]) ? ptr[i-15+j] : '.');
+ if (i < size-1)
+ {
+ printf("\n");
+ print_offset();
+ printf("%08x: ", offset - size + i + 1);
+ }
}
}
-
- if(n&0x0f)
- printf("\n");
+ if (i % 16)
+ {
+ printf("%*s ", 3 * (16-(i%16)), "");
+ for (j = 0; j < i % 16; j++)
+ printf("%c", _isprint(ptr[i-(i%16)+j]) ? ptr[i-(i%16)+j] : '.');
+ }
+ printf("\n");
}
static int dump_msft_varflags(void)
@@ -324,10 +352,10 @@ static int dump_msft_varflags(void)
static void dump_msft_version(void)
{
- int version;
+ unsigned version;
print_offset();
version = tlb_read_int();
- printf("version = %d.%d\n", version & 0xff, version >> 16);
+ printf("version = %u.%u\n", version & 0xffff, version >> 16);
}
static void dump_msft_header(void)
@@ -520,11 +548,26 @@ static BOOL dump_msft_namehashtab(seg_t *seg)
return TRUE;
}
-static void dump_string(int len, int align_off)
+static void print_string0(void)
+{
+ char c;
+
+ printf("\"");
+ while ((c = tlb_read_byte()) != 0) fwrite(&c, 1, 1, stdout);
+ printf("\"");
+}
+
+static void print_string(int len)
{
printf("\"");
fwrite(tlb_read(len), len, 1, stdout);
- printf("\" ");
+ printf("\"");
+}
+
+static void dump_string(int len, int align_off)
+{
+ print_string(len);
+ printf(" ");
while((len++ + align_off) & 3)
printf("\\%2.2x", tlb_read_byte());
}
@@ -960,13 +1003,7 @@ static BOOL dump_offset(void)
return FALSE;
}
-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)
+static void msft_dump(void)
{
int i;
@@ -987,3 +1024,281 @@ void msft_dump(void)
print_hex("unknown");
}
}
+
+/****************************** SLTG Typelibs ******************************/
+
+struct block_entry
+{
+ DWORD len;
+ WORD index_string;
+ WORD next;
+};
+
+static void print_sltg_name(const char *name)
+{
+ unsigned short len = tlb_read_short();
+ print_offset();
+ printf("%s = %#x (", name, len);
+ if (len != 0xffff) print_string(len);
+ printf(")\n");
+}
+
+static int dump_sltg_header(void)
+{
+ int n_file_blocks;
+
+ print_begin_block("Header");
+
+ assert(print_hex("magic") == 0x47544c53);
+ n_file_blocks = print_short_dec("# file blocks");
+ print_short_hex("res06");
+ print_short_hex("res08");
+ sltg_first_blk = print_short_dec("first block");
+ print_guid("guid");
+ print_hex("res1c");
+ print_hex("res20");
+
+ print_end_block();
+
+ return n_file_blocks;
+}
+
+static void dump_sltg_magic(void)
+{
+ dump_binary(1);
+ printf("magic1 = ");
+ print_string0();
+ printf("\n");
+
+ printf("magic2 = ");
+ print_string0();
+ printf("\n\n");
+}
+
+static void dump_sltg_index(int count)
+{
+ int i;
+
+ printf("index:\n");
+
+ for (i = 0; i < count; i++)
+ dump_binary(11);
+
+ printf("\n");
+}
+
+static void dump_sltg_pad9(void)
+{
+ printf("pad9:\n");
+ dump_binary(9);
+ printf("\n");
+}
+
+static void dump_sltg_block_entry(struct block_entry *entry, int idx)
+{
+ char name[32];
+
+ sprintf(name, "Block entry %d", idx);
+ print_begin_block(name);
+
+ entry->len = print_hex("len");
+ entry->index_string = print_short_hex("index string");
+ entry->next = print_short_hex("next");
+
+ print_end_block();
+}
+
+static void dump_sltg_library_block(void)
+{
+ print_begin_block("Library block entry");
+
+ assert(print_short_hex("magic") == 0x51cc);
+ print_short_hex("res02");
+ print_sltg_name("name");
+ print_short_hex("res06");
+ print_sltg_name("helpstring");
+ print_sltg_name("helpfile");
+ print_hex("helpcontext");
+ print_short_hex("syskind");
+ print_short_hex("lcid");
+ print_hex("res12");
+ print_short_hex("libflags");
+ dump_msft_version();
+ print_guid("uuid");
+
+ print_end_block();
+}
+
+static void dump_sltg_other_typeinfo(int idx)
+{
+ int helpstring;
+ char name[32];
+
+ sprintf(name, "Other typeinfo %d", idx);
+ print_begin_block(name);
+
+ print_sltg_name("index name");
+ print_sltg_name("other name");
+ print_short_hex("res1a");
+ print_short_hex("name offset");
+ helpstring = tlb_read_short();
+ offset -= 2;
+ if (helpstring)
+ {
+ print_offset();
+ printf("helpstring:\n");
+ dump_binary(helpstring + 2);
+ }
+ else
+ print_short_hex("helpstring");
+ print_short_hex("res20");
+ print_hex("helpcontext");
+ print_short_hex("res26");
+ print_guid("uuid");
+ print_short_dec("typekind");
+
+ print_end_block();
+}
+
+static void tlb_align(unsigned size, unsigned int align)
+{
+ size = align - (size % align);
+ if (size == align) return;
+
+ dump_binary(size);
+}
+
+static void sltg_dump(void)
+{
+ int i, n_file_blocks, name_table_start, name_table_size;
+ int libblk_start_offset, libblk_len, len;
+ struct block_entry *entry;
+
+ n_file_blocks = dump_sltg_header();
+
+ entry = malloc(sizeof(*entry) * n_file_blocks);
+ if (!entry) return;
+
+ for (i = 0; i < n_file_blocks - 1; i++)
+ dump_sltg_block_entry(&entry[i], i);
+
+ dump_sltg_magic();
+ dump_sltg_index(n_file_blocks - 2);
+ dump_sltg_pad9();
+
+ for (i = sltg_first_blk - 1; entry[i].next != 0; i = entry[i].next - 1)
+ {
+ short magic;
+ char name[32];
+
+ sprintf(name, "Block %d", i);
+ print_begin_block(name);
+ magic = tlb_read_short();
+ assert(magic == 0x0501);
+ offset -= 2;
+ dump_binary(entry[i].len);
+ print_end_block();
+ }
+
+ libblk_len = entry[i].len;
+
+ libblk_start_offset = offset;
+ dump_sltg_library_block();
+
+ printf("skipping 0x40 bytes\n");
+ dump_binary(0x40);
+ printf("\n");
+ typeinfo_cnt = print_short_dec("typeinfo count");
+ printf("\n");
+
+ for (i = 0; i < typeinfo_cnt; i++)
+ dump_sltg_other_typeinfo(i);
+
+ len = print_hex("some length");
+ printf("%#x + %#x = %#x\n", libblk_start_offset, len, libblk_start_offset + len);
+ len = (libblk_start_offset + len) - offset;
+ printf("skipping %#x bytes (encoded/compressed helpstrings)\n", len);
+ dump_binary(len);
+ printf("\n");
+
+ printf("skipping 0x20c bytes\n");
+ dump_binary(0x20c);
+ printf("\n");
+
+ name_table_size = print_hex("name table size");
+
+ name_table_start = offset;
+ printf("name table offset = %#x\n\n", offset);
+
+ while (offset < name_table_start + name_table_size)
+ {
+/*printf("current offset: %08x (relative to name table start: %08x (%u))\n",
+ offset, offset - name_table_start, offset - name_table_start);*/
+ dump_binary(8);
+ print_string0();
+ printf("\n");
+/*printf("current offset: %08x (relative to name table start: %08x (%u))\n",
+ offset, offset - name_table_start, offset - name_table_start);*/
+
+ /* FIXME: sometimes alignment is 4 (on the block boundary?) */
+ tlb_align(offset - name_table_start, 2);
+ printf("\n");
+ }
+
+ assert(print_hex("01ffff01") == 0x01ffff01);
+ len = print_hex("length");
+ printf("skipping %#x bytes\n", len);
+ dump_binary(len);
+ printf("\n");
+
+ len = (libblk_start_offset + libblk_len) - offset;
+ printf("skipping libblk remainder %#x bytes\n", len);
+ dump_binary(len);
+ printf("\n");
+
+ /* msodumper/olestream.py parses this block differently */
+#if 0
+ print_short_hex("unknown");
+ print_short_hex("byte order mark");
+ i = tlb_read_short();
+ printf("version = %u.%u\n", i & 0xff, i >> 8);
+ print_short_hex("system identifier");
+ print_hex("unknown");
+ printf("\n");
+#else
+ printf("skipping 12 bytes\n");
+ dump_binary(12);
+ printf("\n");
+#endif
+
+ print_guid("uuid");
+ printf("\n");
+
+ /* 0x0008,"TYPELIB",0 */
+ dump_binary(12);
+ printf("\n");
+
+ printf("skipping 12 bytes\n");
+ dump_binary(12);
+ printf("\n");
+
+ printf("skipping remainder 0x10 bytes\n");
+ dump_binary(0x10);
+ printf("\n");
+}
+
+void tlb_dump(void)
+{
+ const DWORD *sig = PRD(0, sizeof(DWORD));
+ if (*sig == MSFT_MAGIC)
+ msft_dump();
+ else
+ sltg_dump();
+}
+
+enum FileSig get_kind_tlb(void)
+{
+ const DWORD *sig = PRD(0, sizeof(DWORD));
+ if (sig && (*sig == MSFT_MAGIC || *sig == SLTG_MAGIC)) return SIG_TLB;
+ return SIG_UNKNOWN;
+}
diff --git a/tools/winedump/winedump.h b/tools/winedump/winedump.h
index 339cee3..ea95b27 100644
--- a/tools/winedump/winedump.h
+++ b/tools/winedump/winedump.h
@@ -214,7 +214,7 @@ 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, SIG_MSFT};
+ SIG_EMF, SIG_FNT, SIG_TLB};
const void* PRD(unsigned long prd, unsigned long len);
unsigned long Offset(const void* ptr);
@@ -251,8 +251,8 @@ 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);
+enum FileSig get_kind_tlb(void);
+void tlb_dump(void);
BOOL codeview_dump_symbols(const void* root, unsigned long size);
BOOL codeview_dump_types_from_offsets(const void* table, const DWORD* offsets, unsigned num_types);
--
2.6.4
More information about the wine-patches
mailing list