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