Alexandre Julliard : winedump: Add dumping of x86_64 exception tables.

Alexandre Julliard julliard at winehq.org
Wed May 6 10:33:13 CDT 2009


Module: wine
Branch: master
Commit: 8ad9457fca96c0070e54156d84017030e850a706
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=8ad9457fca96c0070e54156d84017030e850a706

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed May  6 12:06:20 2009 +0200

winedump: Add dumping of x86_64 exception tables.

---

 tools/winedump/pe.c |  173 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 173 insertions(+), 0 deletions(-)

diff --git a/tools/winedump/pe.c b/tools/winedump/pe.c
index 491228f..bbe4d56 100644
--- a/tools/winedump/pe.c
+++ b/tools/winedump/pe.c
@@ -520,6 +520,177 @@ static	void	dump_dir_exported_functions(void)
     printf("\n");
 }
 
+
+struct runtime_function
+{
+    DWORD BeginAddress;
+    DWORD EndAddress;
+    DWORD UnwindData;
+};
+
+union handler_data
+{
+    struct runtime_function chain;
+    DWORD handler;
+};
+
+struct opcode
+{
+    BYTE offset;
+    BYTE code : 4;
+    BYTE info : 4;
+};
+
+struct unwind_info
+{
+    BYTE version : 3;
+    BYTE flags : 5;
+    BYTE prolog;
+    BYTE count;
+    BYTE frame_reg : 4;
+    BYTE frame_offset : 4;
+    struct opcode opcodes[1];  /* count entries */
+    /* followed by union handler_data */
+};
+
+#define UWOP_PUSH_NONVOL     0
+#define UWOP_ALLOC_LARGE     1
+#define UWOP_ALLOC_SMALL     2
+#define UWOP_SET_FPREG       3
+#define UWOP_SAVE_NONVOL     4
+#define UWOP_SAVE_NONVOL_FAR 5
+#define UWOP_SAVE_XMM128     8
+#define UWOP_SAVE_XMM128_FAR 9
+#define UWOP_PUSH_MACHFRAME  10
+
+#define UNW_FLAG_EHANDLER  1
+#define UNW_FLAG_UHANDLER  2
+#define UNW_FLAG_CHAININFO 4
+
+static void dump_x86_64_unwind_info( const struct runtime_function *function )
+{
+    static const char * const reg_names[16] =
+        { "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
+          "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15" };
+
+    union handler_data *handler_data;
+    const struct unwind_info *info;
+    unsigned int i, count;
+
+    printf( "\nFunction %08x-%08x:\n", function->BeginAddress, function->EndAddress );
+    if (function->UnwindData & 1)
+    {
+        const struct runtime_function *next = RVA( function->UnwindData & ~1, sizeof(*next) );
+        printf( "  -> function %08x-%08x\n", next->BeginAddress, next->EndAddress );
+        return;
+    }
+    info = RVA( function->UnwindData, sizeof(*info) );
+
+    printf( "  unwind info at %08x\n", function->UnwindData );
+    if (info->version != 1)
+    {
+        printf( "    *** unknown version %u\n", info->version );
+        return;
+    }
+    printf( "    flags %x", info->flags );
+    if (info->flags & UNW_FLAG_EHANDLER) printf( " EHANDLER" );
+    if (info->flags & UNW_FLAG_UHANDLER) printf( " UHANDLER" );
+    if (info->flags & UNW_FLAG_CHAININFO) printf( " CHAININFO" );
+    printf( "\n    prolog 0x%x bytes\n", info->prolog );
+
+    if (info->frame_reg)
+        printf( "    frame register %s offset 0x%x(%%rsp)\n",
+                reg_names[info->frame_reg], info->frame_offset * 16 );
+
+    for (i = 0; i < info->count; i++)
+    {
+        printf( "      0x%02x: ", info->opcodes[i].offset );
+        switch (info->opcodes[i].code)
+        {
+        case UWOP_PUSH_NONVOL:
+            printf( "push %%%s\n", reg_names[info->opcodes[i].info] );
+            break;
+        case UWOP_ALLOC_LARGE:
+            if (info->opcodes[i].info)
+            {
+                count = *(DWORD *)&info->opcodes[i+1];
+                i += 2;
+            }
+            else
+            {
+                count = *(USHORT *)&info->opcodes[i+1] * 8;
+                i++;
+            }
+            printf( "sub $0x%x,%%rsp\n", count );
+            break;
+        case UWOP_ALLOC_SMALL:
+            count = (info->opcodes[i].info + 1) * 8;
+            printf( "sub $0x%x,%%rsp\n", count );
+            break;
+        case UWOP_SET_FPREG:
+            printf( "lea 0x%x(%%rsp),%s\n",
+                    info->frame_offset * 16, reg_names[info->frame_reg] );
+            break;
+        case UWOP_SAVE_NONVOL:
+            count = *(USHORT *)&info->opcodes[i+1] * 8;
+            printf( "mov %%%s,0x%x(%%rsp)\n", reg_names[info->opcodes[i].info], count );
+            i++;
+            break;
+        case UWOP_SAVE_NONVOL_FAR:
+            count = *(DWORD *)&info->opcodes[i+1];
+            printf( "mov %%%s,0x%x(%%rsp)\n", reg_names[info->opcodes[i].info], count );
+            i += 2;
+            break;
+        case UWOP_SAVE_XMM128:
+            count = *(USHORT *)&info->opcodes[i+1] * 16;
+            printf( "movaps %%xmm%u,0x%x(%%rsp)\n", info->opcodes[i].info, count );
+            i++;
+            break;
+        case UWOP_SAVE_XMM128_FAR:
+            count = *(DWORD *)&info->opcodes[i+1];
+            printf( "movaps %%xmm%u,0x%x(%%rsp)\n", info->opcodes[i].info, count );
+            i += 2;
+            break;
+        case UWOP_PUSH_MACHFRAME:
+            printf( "PUSH_MACHFRAME %u\n", info->opcodes[i].info );
+            break;
+        default:
+            printf( "*** unknown code %u\n", info->opcodes[i].code );
+            break;
+        }
+    }
+
+    handler_data = (union handler_data *)&info->opcodes[(info->count + 1) & ~1];
+    if (info->flags & UNW_FLAG_CHAININFO)
+    {
+        printf( "    -> function %08x-%08x\n",
+                handler_data->chain.BeginAddress, handler_data->chain.EndAddress );
+        return;
+    }
+    if (info->flags & (UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER))
+        printf( "    handler %08x data at %08x\n", handler_data->handler,
+                function->UnwindData + (char *)(&handler_data->handler + 1) - (char *)info );
+}
+
+static void dump_dir_exceptions(void)
+{
+    unsigned int i, size = 0;
+    const struct runtime_function *funcs = get_dir_and_size(IMAGE_FILE_EXCEPTION_DIRECTORY, &size);
+    const IMAGE_FILE_HEADER *file_header = &PE_nt_headers->FileHeader;
+
+    if (!funcs) return;
+
+    if (file_header->Machine == IMAGE_FILE_MACHINE_AMD64)
+    {
+        size /= sizeof(*funcs);
+        printf( "Exception info (%u functions):\n", size );
+        for (i = 0; i < size; i++) dump_x86_64_unwind_info( funcs + i );
+    }
+    else printf( "Exception information not supported for %s binaries\n",
+                 get_machine_str(file_header->Machine));
+}
+
+
 static void dump_image_thunk_data64(const IMAGE_THUNK_DATA64 *il)
 {
     /* FIXME: This does not properly handle large images */
@@ -1295,6 +1466,8 @@ void pe_dump(void)
 	    dump_dir_clr_header();
 	if (all || !strcmp(globals.dumpsect, "reloc"))
 	    dump_dir_reloc();
+	if (all || !strcmp(globals.dumpsect, "except"))
+	    dump_dir_exceptions();
     }
     if (globals.do_debug)
         dump_debug();




More information about the wine-cvs mailing list