diff options
-rw-r--r-- | bfd/ChangeLog | 10 | ||||
-rw-r--r-- | bfd/peXXigen.c | 210 | ||||
-rw-r--r-- | binutils/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/windres/windres.exp | 39 |
4 files changed, 263 insertions, 1 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index a9420cd..3108f73 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,13 @@ +2013-12-03 Nick Clifton <nickc@redhat.com> + + * peXXigen.c (pe_print_resource_entries): New function: Displays + an entry in a .rsrc section. + (pe_print_resource_directory): New function: Displays a directory + in a .rsrc section. + (pe_print_rsrc): New function: Displays the contents of .rsrc + section. + (_bfd_XX_print_private_bfd_data_common): Call pe_print_rsrc. + 2013-12-03 Alan Modra <amodra@gmail.com> * elf64-ppc.c (ppc_build_one_stub <ppc_stub_plt_branch_r2off>): diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c index 287e4a2..b720668 100644 --- a/bfd/peXXigen.c +++ b/bfd/peXXigen.c @@ -1991,6 +1991,214 @@ pe_print_reloc (bfd * abfd, void * vfile) return TRUE; } +static bfd_byte * +pe_print_resource_directory (FILE * , bfd *, unsigned int, + bfd_byte *, bfd_byte *, bfd_byte *, bfd_vma); + +static bfd_byte * +pe_print_resource_entries (FILE * file, + bfd * abfd, + unsigned int indent, + bfd_boolean is_name, + bfd_byte * data, + bfd_byte * datastart, + bfd_byte * dataend, + bfd_vma rva_bias) +{ + unsigned long entry, addr, size; + + if (data + 8 >= dataend) + return dataend + 1; + + fprintf (file, _("%*.s Entry: "), indent, " "); + + entry = (long) bfd_get_32 (abfd, data); + if (is_name) + { + if (datastart + entry < dataend) + { + unsigned int len; + len = bfd_get_16 (abfd, datastart + entry); + + fprintf (file, _("name: %08lx [%d:]"), entry, len); + if (datastart + entry - rva_bias + 2 + len < dataend) + fprintf (file, "%.*s", len, (char *) (datastart + entry - rva_bias + 2)); + else + fprintf (file, _("<corrupt>")); + } + else + fprintf (file, _("<corrupt>")); + } + else + fprintf (file, _("ID: %#08lx"), entry); + + entry = (long) bfd_get_32 (abfd, data + 4); + fprintf (file, _(", Value: %#08lx"), entry); + + if (entry & 0x80000000) + { + fprintf (file, _(" sub-table:\n")); + return pe_print_resource_directory (file, abfd, indent + 1, + datastart + (entry & 0x7fffffff), + datastart, dataend, rva_bias); + } + + if (datastart + entry + 16 >= dataend) + { + fprintf (file, "\n"); + return dataend + 1; + } + + fprintf (file, _(" leaf: Addr: %#08lx, Size: %#08lx, Codepage: %d\n"), + addr = (long) bfd_get_32 (abfd, datastart + entry), + size = (long) bfd_get_32 (abfd, datastart + entry + 4), + (int) bfd_get_32 (abfd, datastart + entry + 8)); + + /* Check that the reserved entry is 0. */ + if (bfd_get_32 (abfd, datastart + entry + 12) != 0 + /* And that the data address/size is valid too. */ + || (datastart + addr - rva_bias + size > dataend)) + return dataend + 1; + + return datastart + addr - rva_bias + size; +} + +static bfd_byte * +pe_print_resource_directory (FILE * file, + bfd * abfd, + unsigned int indent, + bfd_byte * data, + bfd_byte * datastart, + bfd_byte * dataend, + bfd_vma rva_bias) +{ + unsigned int num_names, num_ids; + bfd_byte * enddata = data; + + if (data + 16 >= dataend) + return dataend + 1; + + fprintf (file, "%*.s ", indent, " "); + switch (indent) + { + case 0: fprintf (file, "Type"); break; + case 2: fprintf (file, "Name"); break; + case 4: fprintf (file, "Language"); break; + default: fprintf (file, "<unknown>"); break; + } + + fprintf (file, _(" Table: Char: %d, Time: %08lx, Ver: %d/%d, Num Names: %d, IDs: %d\n"), + (int) bfd_get_32 (abfd, data), + (long) bfd_get_32 (abfd, data + 4), + (int) bfd_get_16 (abfd, data + 8), + (int) bfd_get_16 (abfd, data + 10), + num_names = (int) bfd_get_16 (abfd, data + 12), + num_ids = (int) bfd_get_16 (abfd, data + 14)); + data += 16; + + if (num_names) + { + while (num_names --) + { + bfd_byte * ndata; + ndata = pe_print_resource_entries (file, abfd, indent + 1, TRUE, + data, datastart, dataend, rva_bias); + data += 8; + if (ndata > enddata) + enddata = ndata; + if (ndata >= dataend) + break; + } + } + + if (num_ids) + { + while (num_ids --) + { + bfd_byte * ndata; + ndata = pe_print_resource_entries (file, abfd, indent + 1, FALSE, + data, datastart, dataend, rva_bias); + data += 8; + if (ndata > enddata) + enddata = ndata; + if (ndata >= dataend) + break; + } + } + + return enddata > data ? enddata : data; +} + +/* Display the contents of a .rsrc section. We do not try to + reproduce the resources, windres does that. Instead we dump + the tables in a human readable format. */ + +static bfd_boolean +pe_print_rsrc (bfd * abfd, void * vfile) +{ + bfd_vma rva_bias; + pe_data_type * pe; + FILE * file = (FILE *) vfile; + bfd_size_type datasize; + asection * section; + bfd_byte * data; + bfd_byte * dataend; + bfd_byte * datastart; + + + pe = pe_data (abfd); + if (pe == NULL) + return TRUE; + + section = bfd_get_section_by_name (abfd, ".rsrc"); + if (section == NULL) + return TRUE; + + rva_bias = section->vma - pe->pe_opthdr.ImageBase; + + datasize = section->size; + if (datasize == 0) + return TRUE; + + if (! bfd_malloc_and_get_section (abfd, section, &data)) + { + if (data != NULL) + free (data); + return FALSE; + } + datastart = data; + dataend = data + datasize; + + fflush (file); + fprintf (file, "\nThe .rsrc Resource Directory section:\n"); + + while (data < dataend) + { + data = pe_print_resource_directory (file, abfd, 0, data, data, dataend, rva_bias); + + if (data == dataend + 1) + fprintf (file, _("Corrupt .rsrc section detected!\n")); + else + { + /* Align data before continuing. */ + int align = (1 << section->alignment_power) - 1; + data = (bfd_byte *) (((long) (data + align)) & ~ align); + rva_bias += data - datastart; + + /* For reasons that are unclear .rsrc sections are sometimes created + aligned to a 1^3 boundary even when their alignment is set at + 1^2. Catch that case here before we issue a spurious warning + message. */ + if (data == (dataend - 4)) + data = dataend; + else if (data < dataend) + fprintf (file, _("\nWARNING: Extra data in .rsrc section - it will be ignored by Windows:\n")); + } + } + + return TRUE; +} + /* Print out the program headers. */ bfd_boolean @@ -2165,6 +2373,8 @@ _bfd_XX_print_private_bfd_data_common (bfd * abfd, void * vfile) pe_print_pdata (abfd, vfile); pe_print_reloc (abfd, vfile); + pe_print_rsrc (abfd, vfile); + return TRUE; } diff --git a/binutils/testsuite/ChangeLog b/binutils/testsuite/ChangeLog index 67c7260..693a144 100644 --- a/binutils/testsuite/ChangeLog +++ b/binutils/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2013-12-03 Nick Clifton <nickc@redhat.com> + + * binutils-all/windres/windres.exp: Run for x86_64-pc-cygwin. + Add test of "objump -p" output. + 2013-11-27 Matthew Fortune <matthew.fortune@imgtec.com> * binutils-all/objcopy.exp: Consider mips-mti-elf the same as diff --git a/binutils/testsuite/binutils-all/windres/windres.exp b/binutils/testsuite/binutils-all/windres/windres.exp index 2ef73ff..9f8dd25 100644 --- a/binutils/testsuite/binutils-all/windres/windres.exp +++ b/binutils/testsuite/binutils-all/windres/windres.exp @@ -19,15 +19,18 @@ # Written by DJ Delorie <dj@redhat.com> -if {![istarget "i*86-*-*"] && ![istarget "x86_64-*-mingw*"] } { +if {![istarget "i*86-*-*"] && ![istarget "x86_64-*-mingw*"] && ![istarget "x86_64-*-cygwin"] } { + verbose "Not a Cygwin/Mingw target" 1 return } if {![info exists WINDRES]} then { + verbose "WINDRES not defined" 1 return } if {[which $WINDRES] == 0} then { + verbose "$WINDRES not found" 1 return } @@ -139,3 +142,37 @@ foreach res $res_list { file delete "tmpdir/$broot.dump" } } + +# Test objdump -p + +if {[which $OBJDUMP] == 0} then { + unsupported "objdump -p" + return +} + +verbose "$wr $cpp_opts -J rc $srcdir/$subdir/version.rc tmpdir/version.o" 1 +catch "exec $wr $cpp_opts -J rc $srcdir/$subdir/version.rc tmpdir/version.o" err + +if ![string match "" $err] then { + send_log "$err\n" + verbose "$err" 1 + if [string match "*windows.h: No such file*" $err] then { + unsupported "objdump -p (no header files found)" + } else { + fail "objdump -p (build)" + } + continue +} + +set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -p tmpdir/version.o"] + +# FIXME: We should extend this regexp to check for more information. +set want ".*The .rsrc Resource Directory section.*Type Table:.*Entry: ID:.*Name Table:.*Entry: ID:.*Language Table:.*Entry: ID:.*" + +if ![regexp $want $got] then { + fail "objdump -p" +} else { + pass "objdump -p" +} + +# file delete "tmpdir/version.o" |