This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH 4/4] pe/coff: Don't break .build-id with objcopy/strip
- From: Jon TURNEY <jon dot turney at dronecode dot org dot uk>
- To: binutils at sourceware dot org
- Cc: Jon TURNEY <jon dot turney at dronecode dot org dot uk>
- Date: Thu, 10 Apr 2014 18:45:08 +0100
- Subject: [PATCH 4/4] pe/coff: Don't break .build-id with objcopy/strip
- Authentication-results: sourceware.org; auth=none
- References: <1397151908-4336-1-git-send-email-jon dot turney at dronecode dot org dot uk>
The file offsets in the debug directory need to be recalculated in
_bfd_XX_bfd_copy_private_bfd_data_common(), so that if an objcopy or strip adds
or removes something which causes the file offset of the CV record to change,
those offsets are correct.
(This can happen due to either sections being added or removed before the
.build-id section directly affecting it's file offset, or by the addition or
removal of sufficent section headers to change the first section's file offset
and hence all subsequent sections' file offsets.)
(In general _bfd_XX_bfd_copy_private_bfd_data_common() could be a whole lot
smarter about adjusting the DataDirectory. If a section corresponding to a RVA
is removed or no longer has any contents, that entry should be cleared? Offsets
should always be recomputed?)
bfd/ChangeLog:
2014-04-10 Jon TURNEY <jon.turney@dronecode.org.uk>
* peXXigen.c (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.
Signed-off-by: Jon TURNEY <jon.turney@dronecode.org.uk>
---
bfd/peXXigen.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index c00a655..837ff6c 100644
--- a/bfd/peXXigen.c
+++ b/bfd/peXXigen.c
@@ -2651,6 +2651,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. */
@@ -2689,6 +2702,43 @@ _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;
}
--
1.8.3.4