[patch bfd ld]: FIx wrongly interpreted foreign C++ symbols and allow variable image headers for pe-coff

Kai Tietz ktietz70@googlemail.com
Mon Mar 11 10:29:00 GMT 2013


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;



More information about the Binutils mailing list