mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-03 01:33:42 +00:00
winedump: Add dumping of the .apiset PE section.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
4a5a3ba702
commit
6f1fd16f92
|
@ -207,7 +207,8 @@ static const struct my_option option_table[] = {
|
|||
{"-C", DUMP, 0, do_symdmngl, "-C Turn on symbol demangling"},
|
||||
{"-f", DUMP, 0, do_dumphead, "-f Dump file header 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"},
|
||||
{"-x", DUMP, 0, do_dumpall, "-x Dump everything"},
|
||||
{"sym", DMGL, 0, do_demangle, "sym <sym> Demangle C++ symbol <sym> and exit"},
|
||||
|
@ -232,22 +233,22 @@ void do_usage (const char *arg)
|
|||
const struct my_option *opt;
|
||||
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 ("\tWhen used in --help mode\n");
|
||||
printf (" When used in --help mode\n");
|
||||
for (opt = option_table; opt->name; opt++)
|
||||
if (opt->mode == NONE)
|
||||
printf ("\t %s\n", opt->usage);
|
||||
printf ("\tWhen used in sym mode\n");
|
||||
printf (" %s\n", opt->usage);
|
||||
printf (" When used in sym mode\n");
|
||||
for (opt = option_table; opt->name; opt++)
|
||||
if (opt->mode == DMGL)
|
||||
printf ("\t %s\n", opt->usage);
|
||||
printf ("\tWhen used in spec mode\n");
|
||||
printf (" %s\n", opt->usage);
|
||||
printf (" When used in spec mode\n");
|
||||
for (opt = option_table; opt->name; opt++)
|
||||
if (opt->mode == SPEC)
|
||||
printf ("\t %s\n", opt->usage);
|
||||
printf ("\tWhen used in dump mode\n");
|
||||
printf (" %s\n", opt->usage);
|
||||
printf (" When used in dump mode\n");
|
||||
for (opt = option_table; opt->name; opt++)
|
||||
if (opt->mode == DUMP)
|
||||
printf ("\t %s\n", opt->usage);
|
||||
printf (" %s\n", opt->usage);
|
||||
|
||||
puts ("");
|
||||
exit (1);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
unsigned int size = 0;
|
||||
|
@ -2336,6 +2441,8 @@ void pe_dump(void)
|
|||
dump_dir_reloc();
|
||||
if (all || !strcmp(globals.dumpsect, "except"))
|
||||
dump_dir_exceptions();
|
||||
if (all || !strcmp(globals.dumpsect, "apiset"))
|
||||
dump_section_apiset();
|
||||
}
|
||||
if (globals.do_symbol_table)
|
||||
dump_symbol_table();
|
||||
|
|
|
@ -70,12 +70,12 @@ Dumps file header information.
|
|||
This option dumps only the standard PE header structures,
|
||||
along with the COFF sections available in the file.
|
||||
.IP "\fB-j \fIdir_name\fR"
|
||||
Dumps only the content of directory \fIdir_name\fR, for files
|
||||
which header points to directories.
|
||||
For PE files, currently the import, export, debug, resource,
|
||||
tls and clr directories are implemented.
|
||||
For NE files, currently the export and resource directories are
|
||||
implemented.
|
||||
Dumps only the content of directory \fIdir_name\fR, for files which
|
||||
header points to directories. For PE files, the \fBimport\fR,
|
||||
\fBexport\fR, \fBdebug\fR, \fBresource\fR, \fBtls\fR, \fBloadcfg\fR,
|
||||
\fBclr\fR, \fBreloc\fR and \fBexcept\fR directories, as well as the
|
||||
\fBapiset\fR section, are implemented. For NE files, the \fBexport\fR
|
||||
and \fBresource\fR directories are implemented.
|
||||
.IP \fB-x\fR
|
||||
Dumps everything.
|
||||
This command prints all available information (including all
|
||||
|
|
Loading…
Reference in a new issue