Alexandre Julliard : winedump: Add dumping of the .apiset PE section.
Alexandre Julliard
julliard at winehq.org
Fri Feb 18 15:14:59 CST 2022
Module: wine
Branch: master
Commit: 6f1fd16f92ccbc41999878fce1dc16c9d4d4e283
URL: https://source.winehq.org/git/wine.git/?a=commit;h=6f1fd16f92ccbc41999878fce1dc16c9d4d4e283
Author: Alexandre Julliard <julliard at winehq.org>
Date: Fri Feb 18 10:00:55 2022 +0100
winedump: Add dumping of the .apiset PE section.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
tools/winedump/main.c | 19 ++++----
tools/winedump/pe.c | 107 +++++++++++++++++++++++++++++++++++++++++
tools/winedump/winedump.man.in | 12 ++---
3 files changed, 123 insertions(+), 15 deletions(-)
diff --git a/tools/winedump/main.c b/tools/winedump/main.c
index fd5b44d637d..f9557983465 100644
--- a/tools/winedump/main.c
+++ b/tools/winedump/main.c
@@ -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);
diff --git a/tools/winedump/pe.c b/tools/winedump/pe.c
index 6ff14f95791..2207ed9accc 100644
--- a/tools/winedump/pe.c
+++ b/tools/winedump/pe.c
@@ -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();
diff --git a/tools/winedump/winedump.man.in b/tools/winedump/winedump.man.in
index a915ff49225..56460f26e7c 100644
--- a/tools/winedump/winedump.man.in
+++ b/tools/winedump/winedump.man.in
@@ -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
More information about the wine-cvs
mailing list