This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[patch bfd ld]: FIx wrongly interpreted foreign C++ symbols and allow variable image headers for pe-coff
- From: Kai Tietz <ktietz70 at googlemail dot com>
- To: Binutils <binutils at sourceware dot org>
- Cc: Nick Clifton <nickc at redhat dot com>
- Date: Mon, 11 Mar 2013 11:28:55 +0100
- Subject: [patch bfd ld]: FIx wrongly interpreted foreign C++ symbols and allow variable image headers for pe-coff
Hi,
This patch fixes an issue we have in coff_object_p and pe_bfd_object_p.
By this patch we have the ability to handle other valid PE image-headers
in bfd, too, due we don't dependent on fixed PE-header location anymore.
Additional it fixes in ld for pe-coff that VC generated C++-symbols are
wrongly handled as stdcall/fastcall symbols.
ChangeLog bfd/
2013-03-11 Kai Tietz <ktietz@redhat.com>
* coffgen.c (coff_real_object_p): Make global.
* peicode.h (coff_real_object_p): Add prototype.
(FILHDR): Defined for COFF_IMAGE_WITH_PE as
external_PEI_IMAGE_hdr structure.
(coff_swap_filehdr_in): Handle variable header-size.
* peXXigen.c (_bfd_XXi_swap_aouthdr_in): Just handle amount
of directory-entiries as specified in pe-header.
ChangeLog ld/
2013-03-11 Kai Tietz <ktietz@redhat.com>
* pe-dll.c (process_def_file_and_drectve): Don't handle VC
generated C++-symbols as stdcall/fastcall.
Ok for apply?
Regards,
Kai
Index: bfd/coffgen.c
===================================================================
RCS file: /cvs/src/src/bfd/coffgen.c,v
retrieving revision 1.86
diff -p -u -r1.86 coffgen.c
--- bfd/coffgen.c 10 Jan 2013 20:03:52 -0000 1.86
+++ bfd/coffgen.c 11 Mar 2013 10:24:03 -0000
@@ -221,8 +221,12 @@ make_a_section_from_file (bfd *abfd,
/* Read in a COFF object and make it into a BFD. This is used by
ECOFF as well. */
-
-static const bfd_target *
+const bfd_target *
+coff_real_object_p (bfd *,
+ unsigned,
+ struct internal_filehdr *,
+ struct internal_aouthdr *);
+const bfd_target *
coff_real_object_p (bfd *abfd,
unsigned nscns,
struct internal_filehdr *internal_f,
Index: bfd/peXXigen.c
===================================================================
RCS file: /cvs/src/src/bfd/peXXigen.c,v
retrieving revision 1.72
diff -p -u -r1.72 peXXigen.c
--- bfd/peXXigen.c 10 Jan 2013 20:03:54 -0000 1.72
+++ bfd/peXXigen.c 11 Mar 2013 10:24:03 -0000
@@ -461,7 +461,7 @@ _bfd_XXi_swap_aouthdr_in (bfd * abfd,
{
int idx;
- for (idx = 0; idx < 16; idx++)
+ for (idx = 0; idx < a->NumberOfRvaAndSizes; idx++)
{
/* If data directory is empty, rva also should be 0. */
int size =
Index: bfd/peicode.h
===================================================================
RCS file: /cvs/src/src/bfd/peicode.h,v
retrieving revision 1.65
diff -p -u -r1.65 peicode.h
--- bfd/peicode.h 10 Jan 2013 20:03:55 -0000 1.65
+++ bfd/peicode.h 11 Mar 2013 10:24:03 -0000
@@ -123,6 +123,9 @@ typedef struct
}
pe_ILF_vars;
#endif /* COFF_IMAGE_WITH_PE */
+
+const bfd_target *coff_real_object_p
+ (bfd *, unsigned, struct internal_filehdr *, struct internal_aouthdr *);
#ifndef NO_COFF_RELOCS
static void
@@ -159,6 +162,11 @@ coff_swap_reloc_out (bfd * abfd, void *
}
#endif /* not NO_COFF_RELOCS */
+#ifdef COFF_IMAGE_WITH_PE
+#undef FILHDR
+#define FILHDR struct external_PEI_IMAGE_hdr
+#endif
+
static void
coff_swap_filehdr_in (bfd * abfd, void * src, void * dst)
{
@@ -1248,6 +1256,9 @@ pe_bfd_object_p (bfd * abfd)
bfd_byte buffer[4];
struct external_PEI_DOS_hdr dos_hdr;
struct external_PEI_IMAGE_hdr image_hdr;
+ struct internal_filehdr internal_f;
+ struct internal_aouthdr internal_a;
+ file_ptr opt_hdr_size;
file_ptr offset;
/* Detect if this a Microsoft Import Library Format element. */
@@ -1303,17 +1314,38 @@ pe_bfd_object_p (bfd * abfd)
return NULL;
}
- /* Here is the hack. coff_object_p wants to read filhsz bytes to
- pick up the COFF header for PE, see "struct external_PEI_filehdr"
- in include/coff/pe.h. We adjust so that that will work. */
- if (bfd_seek (abfd, (file_ptr) (offset - sizeof (dos_hdr)), SEEK_SET) != 0)
+ /* Swap file header, so that we get the location for calling
+ real_object_p. */
+ bfd_coff_swap_filehdr_in (abfd, (PTR)&image_hdr, &internal_f);
+
+ if (! bfd_coff_bad_format_hook (abfd, &internal_f)
+ || internal_f.f_opthdr > bfd_coff_aoutsz (abfd))
{
- if (bfd_get_error () != bfd_error_system_call)
- bfd_set_error (bfd_error_wrong_format);
+ bfd_set_error (bfd_error_wrong_format);
return NULL;
}
- return coff_object_p (abfd);
+ /* Read the optional header, which has variable size. */
+ opt_hdr_size = internal_f.f_opthdr;
+
+ if (opt_hdr_size != 0)
+ {
+ PTR opthdr;
+
+ opthdr = bfd_alloc (abfd, opt_hdr_size);
+ if (opthdr == NULL)
+ return NULL;
+ if (bfd_bread (opthdr, opt_hdr_size, abfd)
+ != (bfd_size_type) opt_hdr_size)
+ return NULL;
+
+ bfd_coff_swap_aouthdr_in (abfd, opthdr, (PTR) & internal_a);
+ }
+
+ return coff_real_object_p (abfd, internal_f.f_nscns, &internal_f,
+ (opt_hdr_size != 0
+ ? &internal_a
+ : (struct internal_aouthdr *) NULL));
}
#define coff_object_p pe_bfd_object_p
Index: ld/pe-dll.c
===================================================================
RCS file: /cvs/src/src/ld/pe-dll.c,v
retrieving revision 1.146
diff -p -u -r1.146 pe-dll.c
--- ld/pe-dll.c 10 Jan 2013 20:08:02 -0000 1.146
+++ ld/pe-dll.c 11 Mar 2013 10:24:05 -0000
@@ -782,14 +782,17 @@ process_def_file_and_drectve (bfd *abfd
{
for (i = 0; i < NE; i++)
{
- if (strchr (pe_def_file->exports[i].name, '@'))
+ /* Check for fastcall/stdcall-decoration, but ignore
+ C++ mangled names. */
+ if (pe_def_file->exports[i].name[0] != '?'
+ && strchr (pe_def_file->exports[i].name, '@'))
{
/* This will preserve internal_name, which may have been
pointing to the same memory as name, or might not
have. */
int lead_at = (*pe_def_file->exports[i].name == '@');
char *tmp = xstrdup (pe_def_file->exports[i].name + lead_at);
- char *tmp_at = strchr (tmp, '@');
+ char *tmp_at = strrchr (tmp, '@');
if (tmp_at)
*tmp_at = 0;