This fixes a few issues with pe/coff build-ids that were discovered since the
authorJon Turney <jon.turney@dronecode.org.uk>
Fri, 16 May 2014 14:34:13 +0000 (15:34 +0100)
committerNick Clifton <nickc@redhat.com>
Fri, 16 May 2014 14:34:13 +0000 (15:34 +0100)
original patches were posted:

  pe/coff: Display GUID build-id in the conventional way
  pe/coff: Don't interpret debug directory in section with no contents
  pe/coff: Keep .build-id with --only-keep-debug
  pe/coff: Don't break .build-id with objcopy/strip

* peXXigen.c (pe_print_debugdata): Don't interpret debug directory
in a section with no contents.
(is_vma_in_section, find_section_by_vma): New functions.
(_bfd_XX_bfd_copy_private_bfd_data_common): Recalculate file
offsets in the debug directory.
(_bfd_XXi_slurp_codeview_record, _bfd_XXi_write_codeview_record):
Byte-swap GUID from little-endian to big-endian order for
consistent and conventional display.

* objcopy.c (is_nondebug_keep_contents_section): New function.
(setup_section): Use it.

bfd/ChangeLog
bfd/peXXigen.c
binutils/ChangeLog
binutils/objcopy.c

index de40fb774c73c9b146ca7613e59d8051e218b8ce..30a145d91be09162e1c84a6f8012f668b4f1b98e 100644 (file)
@@ -1,3 +1,14 @@
+2014-05-16  Jon Turney <jon.turney@dronecode.org.uk>
+
+       * peXXigen.c (pe_print_debugdata): Don't interpret debug directory
+       in a section with no contents.
+       (is_vma_in_section, find_section_by_vma): New functions.
+       (_bfd_XX_bfd_copy_private_bfd_data_common): Recalculate file
+       offsets in the debug directory.
+       (_bfd_XXi_slurp_codeview_record, _bfd_XXi_write_codeview_record):
+       Byte-swap GUID from little-endian to big-endian order for
+       consistent and conventional display.
+
 2014-05-16  Kaushik Phata  <Kaushik.Phatak@kpit.com>
 
        * elf32-rl78.c (rl78_elf_merge_private_bfd_data): Complain if
        of safe ppc476 insns at end of page.  Also remove non-branch insns.
        Expand comments.
 
-2014-04-08  Jon TURNEY  <jon.turney@dronecode.org.uk>
+2014-04-08  Jon Turney  <jon.turney@dronecode.org.uk>
 
        * peXXigen.c (pe_print_debugdata): New function: Displays the
        contents of the debug directory and decodes codeview entries.
index 8f6f0eb56a16bb66a66cf838be4abacf739bcea8..dba0eddca18632a14d114a15b02a793bc3982de2 100644 (file)
@@ -1112,7 +1112,7 @@ _bfd_XXi_slurp_codeview_record (bfd * abfd, file_ptr where, unsigned long length
   if (bfd_bread (buffer, 256, abfd) < 4)
     return NULL;
 
-  /* ensure null termination of filename */
+  /* Ensure null termination of filename.  */
   buffer[256] = '\0';
 
   cvinfo->CVSignature = H_GET_32(abfd, buffer);
@@ -1124,7 +1124,15 @@ _bfd_XXi_slurp_codeview_record (bfd * abfd, file_ptr where, unsigned long length
       CV_INFO_PDB70 *cvinfo70 = (CV_INFO_PDB70 *)(buffer);
 
       cvinfo->Age = H_GET_32(abfd, cvinfo70->Age);
-      memcpy (cvinfo->Signature, cvinfo70->Signature, CV_INFO_SIGNATURE_LENGTH);
+
+      /* A GUID consists of 4,2,2 byte values in little-endian order, followed
+         by 8 single bytes.  Byte swap them so we can conveniently treat the GUID
+         as 16 bytes in big-endian order.  */
+      bfd_putb32 (bfd_getl32 (cvinfo70->Signature), cvinfo->Signature);
+      bfd_putb16 (bfd_getl16 (&(cvinfo70->Signature[4])), &(cvinfo->Signature[4]));
+      bfd_putb16 (bfd_getl16 (&(cvinfo70->Signature[6])), &(cvinfo->Signature[6]));
+      memcpy (&(cvinfo->Signature[8]), &(cvinfo70->Signature[8]), 8);
+
       cvinfo->SignatureLength = CV_INFO_SIGNATURE_LENGTH;
       // cvinfo->PdbFileName = cvinfo70->PdbFileName;
 
@@ -1157,7 +1165,14 @@ _bfd_XXi_write_codeview_record (bfd * abfd, file_ptr where, CODEVIEW_INFO *cvinf
 
   cvinfo70 = (CV_INFO_PDB70 *) buffer;
   H_PUT_32 (abfd, CVINFO_PDB70_CVSIGNATURE, cvinfo70->CvSignature);
-  memcpy (&(cvinfo70->Signature), cvinfo->Signature, CV_INFO_SIGNATURE_LENGTH);
+
+  /* Byte swap the GUID from 16 bytes in big-endian order to 4,2,2 byte values
+     in little-endian order, followed by 8 single bytes.  */
+  bfd_putl32 (bfd_getb32 (cvinfo->Signature), cvinfo70->Signature);
+  bfd_putl16 (bfd_getb16 (&(cvinfo->Signature[4])), &(cvinfo70->Signature[4]));
+  bfd_putl16 (bfd_getb16 (&(cvinfo->Signature[6])), &(cvinfo70->Signature[6]));
+  memcpy (&(cvinfo70->Signature[8]), &(cvinfo->Signature[8]), 8);
+
   H_PUT_32 (abfd, cvinfo->Age, cvinfo70->Age);
   cvinfo70->PdbFileName[0] = '\0';
 
@@ -2446,6 +2461,13 @@ pe_print_debugdata (bfd * abfd, void * vfile)
                _("\nThere is a debug directory, but the section containing it could not be found\n"));
       return TRUE;
     }
+  else if (!(section->flags & SEC_HAS_CONTENTS))
+    {
+      fprintf (file,
+               _("\nThere is a debug directory in %s, but that section has no contents\n"),
+               section->name);
+      return TRUE;
+    }
 
   fprintf (file, _("\nThere is a debug directory in %s at 0x%lx\n\n"),
           section->name, (unsigned long) addr);
@@ -2689,6 +2711,19 @@ _bfd_XX_print_private_bfd_data_common (bfd * abfd, void * vfile)
   return TRUE;
 }
 
+static bfd_boolean
+is_vma_in_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sect, void *obj)
+{
+  bfd_vma addr = * (bfd_vma *) obj;
+  return (addr >= sect->vma) && (addr < (sect->vma + sect->size));
+}
+
+static asection *
+find_section_by_vma (bfd *abfd, bfd_vma addr)
+{
+  return bfd_sections_find_if (abfd, is_vma_in_section, (void *) & addr);
+}
+
 /* Copy any private info we understand from the input bfd
    to the output bfd.  */
 
@@ -2727,6 +2762,47 @@ _bfd_XX_bfd_copy_private_bfd_data_common (bfd * ibfd, bfd * obfd)
       && ! (pe_data (ibfd)->real_flags & IMAGE_FILE_RELOCS_STRIPPED))
     pe_data (obfd)->dont_strip_reloc = 1;
 
+  /* The file offsets contained in the debug directory need rewriting.  */
+  if (ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size != 0)
+    {
+      bfd_vma addr = ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].VirtualAddress
+       + ope->pe_opthdr.ImageBase;
+      asection *section = find_section_by_vma (obfd, addr);
+      bfd_byte *data;
+
+      if (section && bfd_malloc_and_get_section (obfd, section, &data))
+        {
+          unsigned int i;
+          struct external_IMAGE_DEBUG_DIRECTORY *dd =
+           (struct external_IMAGE_DEBUG_DIRECTORY *)(data + (addr - section->vma));
+
+          for (i = 0; i < ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size
+                / sizeof (struct external_IMAGE_DEBUG_DIRECTORY); i++)
+            {
+              asection *ddsection;
+              struct external_IMAGE_DEBUG_DIRECTORY *edd = &(dd[i]);
+              struct internal_IMAGE_DEBUG_DIRECTORY idd;
+
+              _bfd_XXi_swap_debugdir_in (obfd, edd, &idd);
+
+              if (idd.AddressOfRawData == 0)
+                continue; /* RVA 0 means only offset is valid, not handled yet.  */
+
+              ddsection = find_section_by_vma (obfd, idd.AddressOfRawData + ope->pe_opthdr.ImageBase);
+              if (!ddsection)
+                continue; /* Not in a section! */
+
+              idd.PointerToRawData = ddsection->filepos + (idd.AddressOfRawData
+                                                          + ope->pe_opthdr.ImageBase) - ddsection->vma;
+
+              _bfd_XXi_swap_debugdir_out (obfd, &idd, edd);
+            }
+
+          if (!bfd_set_section_contents (obfd, section, data, 0, section->size))
+            _bfd_error_handler (_("Failed to update file offsets in debug directory"));
+        }
+    }
+
   return TRUE;
 }
 
index 66f2ec15c57e73cc80e8bc99a27d789e39ad3bee..82b8eae9363d108cff065a3a138282418e446415 100644 (file)
@@ -1,3 +1,8 @@
+2014-05-16  Jon Turney  <jon.turney@dronecode.org.uk>
+
+       * objcopy.c (is_nondebug_keep_contents_section): New function.
+       (setup_section): Use it.
+
 2014-05-16  Kaushik Phata  <Kaushik.Phatak@kpit.com>
 
        * readelf.c (get_machine_flags): Handle RL78 64-bit doubles flag.
index 873908c688d3d6b450dfe6f6e4faf147b3d45848..46fd8bcd039dd120343130aa5166076df8e02f6d 100644 (file)
@@ -1141,6 +1141,24 @@ is_strip_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
   return FALSE;
 }
 
+static bfd_boolean
+is_nondebug_keep_contents_section (bfd *ibfd, asection *isection)
+{
+  /* Always keep ELF note sections.  */
+  if (ibfd->xvec->flavour == bfd_target_elf_flavour)
+    return (elf_section_type (isection) == SHT_NOTE);
+
+  /* Always keep the .build-id section for PE/COFF.
+
+     Strictly, this should be written "always keep the section storing the debug
+     directory", but that may be the .text section for objects produced by some
+     tools, which it is not sensible to keep.  */
+  if (ibfd->xvec->flavour == bfd_target_coff_flavour)
+    return (strcmp (bfd_get_section_name (ibfd, isection), ".build-id") == 0);
+
+  return FALSE;
+}
+
 /* Return true if SYM is a hidden symbol.  */
 
 static bfd_boolean
@@ -2695,8 +2713,7 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
     flags = p->flags | (flags & (SEC_HAS_CONTENTS | SEC_RELOC));
   else if (strip_symbols == STRIP_NONDEBUG
           && (flags & (SEC_ALLOC | SEC_GROUP)) != 0
-          && !(ibfd->xvec->flavour == bfd_target_elf_flavour
-               && elf_section_type (isection) == SHT_NOTE))
+           && !is_nondebug_keep_contents_section (ibfd, isection))
     {
       flags &= ~(SEC_HAS_CONTENTS | SEC_LOAD | SEC_GROUP);
       if (obfd->xvec->flavour == bfd_target_elf_flavour)