1,5 → 1,5 |
/* Support for the generic parts of PE/PEI, for BFD. |
Copyright 1995-2013 Free Software Foundation, Inc. |
Copyright (C) 1995-2015 Free Software Foundation, Inc. |
Written by Cygnus Solutions. |
|
This file is part of BFD, the Binary File Descriptor library. |
271,6 → 271,7 |
/* in_reloc_p is architecture dependent. */ |
pe->in_reloc_p = in_reloc_p; |
|
memset (& pe->pe_opthdr, 0, sizeof pe->pe_opthdr); |
return TRUE; |
} |
|
567,6 → 568,7 |
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; |
629,6 → 631,20 |
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); |
834,6 → 850,24 |
|
/* 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; |
971,7 → 1005,16 |
} |
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, |
imp_index); |
|
1077,7 → 1120,7 |
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; |
1087,17 → 1130,13 |
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; |
|
1248,10 → 1287,91 |
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; |
1258,10 → 1378,12 |
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); |
1268,7 → 1390,9 |
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 |
1314,7 → 1438,7 |
|
/* 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)) |
1328,9 → 1452,14 |
|
if (opt_hdr_size != 0) |
{ |
PTR opthdr; |
bfd_size_type amt = opt_hdr_size; |
void * opthdr; |
|
opthdr = bfd_alloc (abfd, opt_hdr_size); |
/* PR 17521 file: 230-131433-0.004. */ |
if (amt < sizeof (PEAOUTHDR)) |
amt = sizeof (PEAOUTHDR); |
|
opthdr = bfd_zalloc (abfd, amt); |
if (opthdr == NULL) |
return NULL; |
if (bfd_bread (opthdr, opt_hdr_size, abfd) |
1337,14 → 1466,27 |
!= (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; |
} |
|
return coff_real_object_p (abfd, internal_f.f_nscns, &internal_f, |
|
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 result; |
} |
|
#define coff_object_p pe_bfd_object_p |
#endif /* COFF_IMAGE_WITH_PE */ |