Commit 6f1fd16f authored by Alexandre Julliard's avatar Alexandre Julliard

winedump: Add dumping of the .apiset PE section.

parent 4a5a3ba7
...@@ -207,7 +207,8 @@ static const struct my_option option_table[] = { ...@@ -207,7 +207,8 @@ static const struct my_option option_table[] = {
{"-C", DUMP, 0, do_symdmngl, "-C Turn on symbol demangling"}, {"-C", DUMP, 0, do_symdmngl, "-C Turn on symbol demangling"},
{"-f", DUMP, 0, do_dumphead, "-f Dump file header information"}, {"-f", DUMP, 0, do_dumphead, "-f Dump file header information"},
{"-G", DUMP, 0, do_rawdebug, "-G Dump raw debug information"}, {"-G", DUMP, 0, do_rawdebug, "-G Dump raw debug information"},
{"-j", DUMP, 1, do_dumpsect, "-j <sect_name> Dump only the content of section 'sect_name' (import, export, debug, resource, tls, loadcfg, clr, reloc, except)"}, {"-j", DUMP, 1, do_dumpsect, "-j <sect_name> Dump only the content of section 'sect_name'\n"
" (import, export, debug, resource, tls, loadcfg, clr, reloc, except, apiset)"},
{"-t", DUMP, 0, do_symtable, "-t Dump symbol table"}, {"-t", DUMP, 0, do_symtable, "-t Dump symbol table"},
{"-x", DUMP, 0, do_dumpall, "-x Dump everything"}, {"-x", DUMP, 0, do_dumpall, "-x Dump everything"},
{"sym", DMGL, 0, do_demangle, "sym <sym> Demangle C++ symbol <sym> and exit"}, {"sym", DMGL, 0, do_demangle, "sym <sym> Demangle C++ symbol <sym> and exit"},
...@@ -232,22 +233,22 @@ void do_usage (const char *arg) ...@@ -232,22 +233,22 @@ void do_usage (const char *arg)
const struct my_option *opt; const struct my_option *opt;
printf ("Usage: winedump [-h | sym <sym> | spec <dll> | dump <file>]\n"); printf ("Usage: winedump [-h | sym <sym> | spec <dll> | dump <file>]\n");
printf ("Mode options (can be put as the mode (sym/spec/dump...) is declared):\n"); printf ("Mode options (can be put as the mode (sym/spec/dump...) is declared):\n");
printf ("\tWhen used in --help mode\n"); printf (" When used in --help mode\n");
for (opt = option_table; opt->name; opt++) for (opt = option_table; opt->name; opt++)
if (opt->mode == NONE) if (opt->mode == NONE)
printf ("\t %s\n", opt->usage); printf (" %s\n", opt->usage);
printf ("\tWhen used in sym mode\n"); printf (" When used in sym mode\n");
for (opt = option_table; opt->name; opt++) for (opt = option_table; opt->name; opt++)
if (opt->mode == DMGL) if (opt->mode == DMGL)
printf ("\t %s\n", opt->usage); printf (" %s\n", opt->usage);
printf ("\tWhen used in spec mode\n"); printf (" When used in spec mode\n");
for (opt = option_table; opt->name; opt++) for (opt = option_table; opt->name; opt++)
if (opt->mode == SPEC) if (opt->mode == SPEC)
printf ("\t %s\n", opt->usage); printf (" %s\n", opt->usage);
printf ("\tWhen used in dump mode\n"); printf (" When used in dump mode\n");
for (opt = option_table; opt->name; opt++) for (opt = option_table; opt->name; opt++)
if (opt->mode == DUMP) if (opt->mode == DUMP)
printf ("\t %s\n", opt->usage); printf (" %s\n", opt->usage);
puts (""); puts ("");
exit (1); exit (1);
......
...@@ -491,6 +491,111 @@ static void dump_sections(const void *base, const void* addr, unsigned num_sect) ...@@ -491,6 +491,111 @@ static void dump_sections(const void *base, const void* addr, unsigned num_sect)
} }
} }
static char *get_str( char *buffer, unsigned int rva, unsigned int len )
{
const WCHAR *wstr = PRD( rva, len );
char *ret = buffer;
len /= sizeof(WCHAR);
while (len--) *buffer++ = *wstr++;
*buffer = 0;
return ret;
}
static void dump_section_apiset(void)
{
const IMAGE_SECTION_HEADER *sect = IMAGE_FIRST_SECTION(PE_nt_headers);
const UINT *ptr, *entry, *value, *hash;
unsigned int i, j, count, val_count, rva;
char buffer[128];
for (i = 0; i < PE_nt_headers->FileHeader.NumberOfSections; i++, sect++)
{
if (strncmp( (const char *)sect->Name, ".apiset", 8 )) continue;
rva = sect->PointerToRawData;
ptr = PRD( rva, sizeof(*ptr) );
printf( "ApiSet section:\n" );
switch (ptr[0]) /* version */
{
case 2:
printf( " Version: %u\n", ptr[0] );
printf( " Count: %08x\n", ptr[1] );
count = ptr[1];
if (!(entry = PRD( rva + 2 * sizeof(*ptr), count * 3 * sizeof(*entry) ))) break;
for (i = 0; i < count; i++, entry += 3)
{
printf( " %s ->", get_str( buffer, rva + entry[0], entry[1] ));
if (!(value = PRD( rva + entry[2], sizeof(*value) ))) break;
val_count = *value++;
for (j = 0; j < val_count; j++, value += 4)
{
putchar( ' ' );
if (value[1]) printf( "%s:", get_str( buffer, rva + value[0], value[1] ));
printf( "%s", get_str( buffer, rva + value[2], value[3] ));
}
printf( "\n");
}
break;
case 4:
printf( " Version: %u\n", ptr[0] );
printf( " Size: %08x\n", ptr[1] );
printf( " Flags: %08x\n", ptr[2] );
printf( " Count: %08x\n", ptr[3] );
count = ptr[3];
if (!(entry = PRD( rva + 4 * sizeof(*ptr), count * 6 * sizeof(*entry) ))) break;
for (i = 0; i < count; i++, entry += 6)
{
printf( " %08x %s ->", entry[0], get_str( buffer, rva + entry[1], entry[2] ));
if (!(value = PRD( rva + entry[5], sizeof(*value) ))) break;
value++; /* flags */
val_count = *value++;
for (j = 0; j < val_count; j++, value += 5)
{
putchar( ' ' );
if (value[1]) printf( "%s:", get_str( buffer, rva + value[1], value[2] ));
printf( "%s", get_str( buffer, rva + value[3], value[4] ));
}
printf( "\n");
}
break;
case 6:
printf( " Version: %u\n", ptr[0] );
printf( " Size: %08x\n", ptr[1] );
printf( " Flags: %08x\n", ptr[2] );
printf( " Count: %08x\n", ptr[3] );
printf( " EntryOffset: %08x\n", ptr[4] );
printf( " HashOffset: %08x\n", ptr[5] );
printf( " HashFactor: %08x\n", ptr[6] );
count = ptr[3];
if (!(entry = PRD( rva + ptr[4], count * 6 * sizeof(*entry) ))) break;
for (i = 0; i < count; i++, entry += 6)
{
printf( " %08x %s ->", entry[0], get_str( buffer, rva + entry[1], entry[2] ));
if (!(value = PRD( rva + entry[4], entry[5] * 5 * sizeof(*value) ))) break;
for (j = 0; j < entry[5]; j++, value += 5)
{
putchar( ' ' );
if (value[1]) printf( "%s:", get_str( buffer, rva + value[1], value[2] ));
printf( "%s", get_str( buffer, rva + value[3], value[4] ));
}
printf( "\n" );
}
printf( " Hash table:\n" );
if (!(hash = PRD( rva + ptr[5], count * 2 * sizeof(*hash) ))) break;
for (i = 0; i < count; i++, hash += 2)
{
entry = PRD( rva + ptr[4] + hash[1] * 6 * sizeof(*entry), 6 * sizeof(*entry) );
printf( " %08x -> %s\n", hash[0], get_str( buffer, rva + entry[1], entry[3] ));
}
break;
default:
printf( "*** Unknown version %u\n", ptr[0] );
break;
}
break;
}
}
static void dump_dir_exported_functions(void) static void dump_dir_exported_functions(void)
{ {
unsigned int size = 0; unsigned int size = 0;
...@@ -2336,6 +2441,8 @@ void pe_dump(void) ...@@ -2336,6 +2441,8 @@ void pe_dump(void)
dump_dir_reloc(); dump_dir_reloc();
if (all || !strcmp(globals.dumpsect, "except")) if (all || !strcmp(globals.dumpsect, "except"))
dump_dir_exceptions(); dump_dir_exceptions();
if (all || !strcmp(globals.dumpsect, "apiset"))
dump_section_apiset();
} }
if (globals.do_symbol_table) if (globals.do_symbol_table)
dump_symbol_table(); dump_symbol_table();
......
...@@ -70,12 +70,12 @@ Dumps file header information. ...@@ -70,12 +70,12 @@ Dumps file header information.
This option dumps only the standard PE header structures, This option dumps only the standard PE header structures,
along with the COFF sections available in the file. along with the COFF sections available in the file.
.IP "\fB-j \fIdir_name\fR" .IP "\fB-j \fIdir_name\fR"
Dumps only the content of directory \fIdir_name\fR, for files Dumps only the content of directory \fIdir_name\fR, for files which
which header points to directories. header points to directories. For PE files, the \fBimport\fR,
For PE files, currently the import, export, debug, resource, \fBexport\fR, \fBdebug\fR, \fBresource\fR, \fBtls\fR, \fBloadcfg\fR,
tls and clr directories are implemented. \fBclr\fR, \fBreloc\fR and \fBexcept\fR directories, as well as the
For NE files, currently the export and resource directories are \fBapiset\fR section, are implemented. For NE files, the \fBexport\fR
implemented. and \fBresource\fR directories are implemented.
.IP \fB-x\fR .IP \fB-x\fR
Dumps everything. Dumps everything.
This command prints all available information (including all This command prints all available information (including all
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment