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