From 6e6e7cfc78e3ae1f4b670fc42d3b4e113d57a62b Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Fri, 16 May 2014 15:34:13 +0100 Subject: [PATCH] This fixes a few issues with pe/coff build-ids that were discovered since the 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 | 13 +++++++- bfd/peXXigen.c | 82 ++++++++++++++++++++++++++++++++++++++++++++-- binutils/ChangeLog | 5 +++ binutils/objcopy.c | 21 ++++++++++-- 4 files changed, 115 insertions(+), 6 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index de40fb774c..30a145d91b 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,14 @@ +2014-05-16 Jon Turney + + * 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 * elf32-rl78.c (rl78_elf_merge_private_bfd_data): Complain if @@ -425,7 +436,7 @@ of safe ppc476 insns at end of page. Also remove non-branch insns. Expand comments. -2014-04-08 Jon TURNEY +2014-04-08 Jon Turney * peXXigen.c (pe_print_debugdata): New function: Displays the contents of the debug directory and decodes codeview entries. diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c index 8f6f0eb56a..dba0eddca1 100644 --- a/bfd/peXXigen.c +++ b/bfd/peXXigen.c @@ -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; } diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 66f2ec15c5..82b8eae936 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,8 @@ +2014-05-16 Jon Turney + + * objcopy.c (is_nondebug_keep_contents_section): New function. + (setup_section): Use it. + 2014-05-16 Kaushik Phata * readelf.c (get_machine_flags): Handle RL78 64-bit doubles flag. diff --git a/binutils/objcopy.c b/binutils/objcopy.c index 873908c688..46fd8bcd03 100644 --- a/binutils/objcopy.c +++ b/binutils/objcopy.c @@ -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) -- 2.34.1