/* Support for the generic parts of PE/PEI, for BFD.
- Copyright (C) 1995-2014 Free Software Foundation, Inc.
+ Copyright (C) 1995-2016 Free Software Foundation, Inc.
Written by Cygnus Solutions.
This file is part of BFD, the Binary File Descriptor library.
/* in_reloc_p is architecture dependent. */
pe->in_reloc_p = in_reloc_p;
+ memset (& pe->pe_opthdr, 0, sizeof pe->pe_opthdr);
return TRUE;
}
ent->u.syment.n_sclass = sclass;
ent->u.syment.n_scnum = section->target_index;
ent->u.syment._n._n_n._n_offset = (bfd_hostptr_t) sym;
+ ent->is_sym = TRUE;
sym->symbol.the_bfd = vars->abfd;
sym->symbol.name = vars->string_ptr;
if (size & 1)
vars->data --;
+# if (GCC_VERSION >= 3000)
+ /* PR 18758: See note in pe_ILF_buid_a_bfd. We must make sure that we
+ preserve host alignment requirements. We test 'size' rather than
+ vars.data as we cannot perform binary arithmetic on pointers. We assume
+ that vars.data was sufficiently aligned upon entry to this function.
+ The BFD_ASSERTs in this functions will warn us if we run out of room,
+ but we should already have enough padding built in to ILF_DATA_SIZE. */
+ {
+ unsigned int alignment = __alignof__ (struct coff_section_tdata);
+
+ if (size & (alignment - 1))
+ vars->data += alignment - (size & (alignment - 1));
+ }
+#endif
/* Create a coff_section_tdata structure for our use. */
sec->used_by_bfd = (struct coff_section_tdata *) vars->data;
vars->data += sizeof (struct coff_section_tdata);
/* The remaining space in bim->buffer is used
by the pe_ILF_make_a_section() function. */
+# if (GCC_VERSION >= 3000)
+ /* PR 18758: Make sure that the data area is sufficiently aligned for
+ pointers on the host. __alignof__ is a gcc extension, hence the test
+ above. For other compilers we will have to assume that the alignment is
+ unimportant, or else extra code can be added here and in
+ pe_ILF_make_a_section.
+
+ Note - we cannot test 'ptr' directly as it is illegal to perform binary
+ arithmetic on pointers, but we know that the strings section is the only
+ one that might end on an unaligned boundary. */
+ {
+ unsigned int alignment = __alignof__ (char *);
+
+ if (SIZEOF_ILF_STRINGS & (alignment - 1))
+ ptr += alignment - (SIZEOF_ILF_STRINGS & (alignment - 1));
+ }
+#endif
+
vars.data = ptr;
vars.abfd = abfd;
vars.sec_index = 0;
imp_index);
}
else
+#endif
+#ifdef AMD64MAGIC
+ if (magic == AMD64MAGIC)
+ {
+ pe_ILF_make_a_symbol_reloc (&vars, (bfd_vma) jtab[i].offset,
+ BFD_RELOC_32_PCREL, (asymbol **) imp_sym,
+ imp_index);
+ }
+ else
#endif
pe_ILF_make_a_symbol_reloc (&vars, (bfd_vma) jtab[i].offset,
BFD_RELOC_32, (asymbol **) imp_sym,
static const bfd_target *
pe_ILF_object_p (bfd * abfd)
{
- bfd_byte buffer[16];
+ bfd_byte buffer[14];
bfd_byte * ptr;
char * symbol_name;
char * source_dll;
unsigned int types;
unsigned int magic;
- /* Upon entry the first four buyes of the ILF header have
+ /* Upon entry the first six bytes of the ILF header have
already been read. Now read the rest of the header. */
- if (bfd_bread (buffer, (bfd_size_type) 16, abfd) != 16)
+ if (bfd_bread (buffer, (bfd_size_type) 14, abfd) != 14)
return NULL;
ptr = buffer;
- /* We do not bother to check the version number.
- version = H_GET_16 (abfd, ptr); */
- ptr += 2;
-
machine = H_GET_16 (abfd, ptr);
ptr += 2;
return abfd->xvec;
}
+static void
+pe_bfd_read_buildid(bfd *abfd)
+{
+ pe_data_type *pe = pe_data (abfd);
+ struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr;
+ asection *section;
+ bfd_byte *data = 0;
+ bfd_size_type dataoff;
+ unsigned int i;
+
+ bfd_vma addr = extra->DataDirectory[PE_DEBUG_DATA].VirtualAddress;
+ bfd_size_type size = extra->DataDirectory[PE_DEBUG_DATA].Size;
+
+ if (size == 0)
+ return;
+
+ addr += extra->ImageBase;
+
+ /* Search for the section containing the DebugDirectory */
+ for (section = abfd->sections; section != NULL; section = section->next)
+ {
+ if ((addr >= section->vma) && (addr < (section->vma + section->size)))
+ break;
+ }
+
+ if (section == NULL)
+ {
+ return;
+ }
+ else if (!(section->flags & SEC_HAS_CONTENTS))
+ {
+ return;
+ }
+
+ dataoff = addr - section->vma;
+
+ /* Read the whole section. */
+ if (!bfd_malloc_and_get_section (abfd, section, &data))
+ {
+ if (data != NULL)
+ free (data);
+ return;
+ }
+
+ /* Search for a CodeView entry in the DebugDirectory */
+ for (i = 0; i < size / sizeof (struct external_IMAGE_DEBUG_DIRECTORY); i++)
+ {
+ struct external_IMAGE_DEBUG_DIRECTORY *ext
+ = &((struct external_IMAGE_DEBUG_DIRECTORY *)(data + dataoff))[i];
+ struct internal_IMAGE_DEBUG_DIRECTORY idd;
+
+ _bfd_XXi_swap_debugdir_in (abfd, ext, &idd);
+
+ if (idd.Type == PE_IMAGE_DEBUG_TYPE_CODEVIEW)
+ {
+ char buffer[256 + 1];
+ CODEVIEW_INFO *cvinfo = (CODEVIEW_INFO *) buffer;
+
+ /*
+ The debug entry doesn't have to have to be in a section, in which
+ case AddressOfRawData is 0, so always use PointerToRawData.
+ */
+ if (_bfd_XXi_slurp_codeview_record (abfd,
+ (file_ptr) idd.PointerToRawData,
+ idd.SizeOfData, cvinfo))
+ {
+ struct bfd_build_id* build_id = bfd_alloc(abfd,
+ sizeof(struct bfd_build_id) + cvinfo->SignatureLength);
+ if (build_id)
+ {
+ build_id->size = cvinfo->SignatureLength;
+ memcpy(build_id->data, cvinfo->Signature,
+ cvinfo->SignatureLength);
+ abfd->build_id = build_id;
+ }
+ }
+ break;
+ }
+ }
+}
+
static const bfd_target *
pe_bfd_object_p (bfd * abfd)
{
- bfd_byte buffer[4];
+ bfd_byte buffer[6];
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;
+ const bfd_target *result;
/* Detect if this a Microsoft Import Library Format element. */
+ /* First read the beginning of the header. */
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
- || bfd_bread (buffer, (bfd_size_type) 4, abfd) != 4)
+ || bfd_bread (buffer, (bfd_size_type) 6, abfd) != 6)
{
if (bfd_get_error () != bfd_error_system_call)
bfd_set_error (bfd_error_wrong_format);
return NULL;
}
- if (H_GET_32 (abfd, buffer) == 0xffff0000)
+ /* Then check the magic and the version (only 0 is supported). */
+ if (H_GET_32 (abfd, buffer) == 0xffff0000
+ && H_GET_16 (abfd, buffer + 4) == 0)
return pe_ILF_object_p (abfd);
if (bfd_seek (abfd, (file_ptr) 0, 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);
+ bfd_coff_swap_filehdr_in (abfd, &image_hdr, &internal_f);
if (! bfd_coff_bad_format_hook (abfd, &internal_f)
|| internal_f.f_opthdr > bfd_coff_aoutsz (abfd))
if (opt_hdr_size != 0)
{
- PTR opthdr;
+ bfd_size_type amt = opt_hdr_size;
+ void * opthdr;
+
+ /* PR 17521 file: 230-131433-0.004. */
+ if (amt < sizeof (PEAOUTHDR))
+ amt = sizeof (PEAOUTHDR);
- opthdr = bfd_alloc (abfd, opt_hdr_size);
+ opthdr = bfd_zalloc (abfd, amt);
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);
+ bfd_set_error (bfd_error_no_error);
+ bfd_coff_swap_aouthdr_in (abfd, opthdr, & internal_a);
+ if (bfd_get_error () != bfd_error_no_error)
+ return NULL;
+ }
+
+
+ result = coff_real_object_p (abfd, internal_f.f_nscns, &internal_f,
+ (opt_hdr_size != 0
+ ? &internal_a
+ : (struct internal_aouthdr *) NULL));
+
+
+ if (result)
+ {
+ /* Now the whole header has been processed, see if there is a build-id */
+ pe_bfd_read_buildid(abfd);
}
- return coff_real_object_p (abfd, internal_f.f_nscns, &internal_f,
- (opt_hdr_size != 0
- ? &internal_a
- : (struct internal_aouthdr *) NULL));
+ return result;
}
#define coff_object_p pe_bfd_object_p