/* Support for the generic parts of PE/PEI; the common executable parts.
- Copyright (C) 1995-2019 Free Software Foundation, Inc.
+ Copyright (C) 1995-2021 Free Software Foundation, Inc.
Written by Cygnus Solutions.
This file is part of BFD, the Binary File Descriptor library.
#define HighBitSet(val) ((val) & 0x80000000)
#define SetHighBit(val) ((val) | 0x80000000)
#define WithoutHighBit(val) ((val) & 0x7fffffff)
-
-/* FIXME: This file has various tests of POWERPC_LE_PE. Those tests
- worked when the code was in peicode.h, but no longer work now that
- the code is in peigen.c. PowerPC NT is said to be dead. If
- anybody wants to revive the code, you will have to figure out how
- to handle those issues. */
\f
void
_bfd_XXi_swap_sym_in (bfd * abfd, void * ext1, void * in1)
int unused_section_number = 0;
asection *sec;
flagword flags;
+ size_t name_len;
+ char *sec_name;
for (sec = abfd->sections; sec; sec = sec->next)
if (unused_section_number <= sec->target_index)
unused_section_number = sec->target_index + 1;
- if (name == namebuf)
+ name_len = strlen (name) + 1;
+ sec_name = bfd_alloc (abfd, name_len);
+ if (sec_name == NULL)
{
- name = (const char *) bfd_alloc (abfd, strlen (namebuf) + 1);
- if (name == NULL)
- {
- _bfd_error_handler (_("%pB: out of memory creating name for empty section"),
- abfd);
- return;
- }
- strcpy ((char *) name, namebuf);
+ _bfd_error_handler (_("%pB: out of memory creating name "
+ "for empty section"), abfd);
+ return;
}
+ memcpy (sec_name, name, name_len);
flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_DATA | SEC_LOAD;
- sec = bfd_make_section_anyway_with_flags (abfd, name, flags);
+ sec = bfd_make_section_anyway_with_flags (abfd, sec_name, flags);
if (sec == NULL)
{
_bfd_error_handler (_("%pB: unable to create fake empty section"),
in->n_sclass = C_STAT;
}
#endif
-
-#ifdef coff_swap_sym_in_hook
- /* This won't work in peigen.c, but since it's for PPC PE, it's not
- worth fixing. */
- coff_swap_sym_in_hook (abfd, ext1, in1);
-#endif
}
static bfd_boolean
H_PUT_32 (abfd, in->x_file.x_n.x_offset, ext->x_file.x_n.x_offset);
}
else
- memcpy (ext->x_file.x_fname, in->x_file.x_fname, FILNMLEN);
+ memcpy (ext->x_file.x_fname, in->x_file.x_fname, sizeof (ext->x_file.x_fname));
return AUXESZ;
aouthdr_int->data_start &= 0xffffffff;
}
#endif
-
-#ifdef POWERPC_LE_PE
- /* These three fields are normally set up by ppc_relocate_section.
- In the case of reading a file in, we can pick them up from the
- DataDirectory. */
- first_thunk_address = a->DataDirectory[PE_IMPORT_ADDRESS_TABLE].VirtualAddress;
- thunk_size = a->DataDirectory[PE_IMPORT_ADDRESS_TABLE].Size;
- import_table_size = a->DataDirectory[PE_IMPORT_TABLE].Size;
-#endif
}
/* A support function for below. */
/* Use a real timestamp by default, unless the no-insert-timestamp
option was chosen. */
- if ((pe_data (abfd)->insert_timestamp))
+ if ((pe_data (abfd)->timestamp) == -1)
H_PUT_32 (abfd, time (0), filehdr_out->f_timdat);
else
- H_PUT_32 (abfd, 0, filehdr_out->f_timdat);
+ H_PUT_32 (abfd, pe_data (abfd)->timestamp, filehdr_out->f_timdat);
PUT_FILEHDR_SYMPTR (abfd, filehdr_in->f_symptr,
filehdr_out->f_symptr);
memcpy (scnhdr_ext->s_name, scnhdr_int->s_name, sizeof (scnhdr_int->s_name));
- PUT_SCNHDR_VADDR (abfd,
- ((scnhdr_int->s_vaddr
- - pe_data (abfd)->pe_opthdr.ImageBase)
- & 0xffffffff),
- scnhdr_ext->s_vaddr);
+ ss = scnhdr_int->s_vaddr - pe_data (abfd)->pe_opthdr.ImageBase;
+ if (scnhdr_int->s_vaddr < pe_data (abfd)->pe_opthdr.ImageBase)
+ _bfd_error_handler (_("%pB:%.8s: section below image base"),
+ abfd, scnhdr_int->s_name);
+ else if(ss != (ss & 0xffffffff))
+ _bfd_error_handler (_("%pB:%.8s: RVA truncated"), abfd, scnhdr_int->s_name);
+ PUT_SCNHDR_VADDR (abfd, ss & 0xffffffff, scnhdr_ext->s_vaddr);
/* NT wants the size data to be rounded up to the next
NT_FILE_ALIGNMENT, but zero if it has no content (as in .bss,
(0x02000000). Also, the resource data should also be read and
writable. */
- /* FIXME: Alignment is also encoded in this field, at least on PPC and
+ /* FIXME: Alignment is also encoded in this field, at least on
ARM-WINCE. Although - how do we get the original alignment field
back ? */
_bfd_XXi_slurp_codeview_record (bfd * abfd, file_ptr where, unsigned long length, CODEVIEW_INFO *cvinfo)
{
char buffer[256+1];
+ bfd_size_type nread;
if (bfd_seek (abfd, where, SEEK_SET) != 0)
return NULL;
- if (bfd_bread (buffer, 256, abfd) < 4)
+ if (length <= sizeof (CV_INFO_PDB70) && length <= sizeof (CV_INFO_PDB20))
+ return NULL;
+ if (length > 256)
+ length = 256;
+ nread = bfd_bread (buffer, length, abfd);
+ if (length != nread)
return NULL;
/* Ensure null termination of filename. */
- buffer[256] = '\0';
+ memset (buffer + nread, 0, sizeof (buffer) - nread);
cvinfo->CVSignature = H_GET_32 (abfd, buffer);
cvinfo->Age = 0;
memcpy (&(cvinfo->Signature[8]), &(cvinfo70->Signature[8]), 8);
cvinfo->SignatureLength = CV_INFO_SIGNATURE_LENGTH;
- // cvinfo->PdbFileName = cvinfo70->PdbFileName;
+ /* cvinfo->PdbFileName = cvinfo70->PdbFileName; */
return cvinfo;
}
cvinfo->Age = H_GET_32(abfd, cvinfo20->Age);
memcpy (cvinfo->Signature, cvinfo20->Signature, 4);
cvinfo->SignatureLength = 4;
- // cvinfo->PdbFileName = cvinfo20->PdbFileName;
+ /* cvinfo->PdbFileName = cvinfo20->PdbFileName; */
return cvinfo;
}
N_("Reserved")
};
-#ifdef POWERPC_LE_PE
-/* The code for the PPC really falls in the "architecture dependent"
- category. However, it's not clear that anyone will ever care, so
- we're ignoring the issue for now; if/when PPC matters, some of this
- may need to go into peicode.h, or arguments passed to enable the
- PPC- specific code. */
-#endif
-
static bfd_boolean
pe_print_idata (bfd * abfd, void * vfile)
{
bfd_byte *data;
asection *section;
bfd_signed_vma adj;
-
-#ifdef POWERPC_LE_PE
- asection *rel_section = bfd_get_section_by_name (abfd, ".reldata");
-#endif
-
bfd_size_type datasize = 0;
bfd_size_type dataoff;
bfd_size_type i;
dataoff = addr - section->vma;
-#ifdef POWERPC_LE_PE
- if (rel_section != 0 && rel_section->size != 0)
- {
- /* The toc address can be found by taking the starting address,
- which on the PPC locates a function descriptor. The
- descriptor consists of the function code starting address
- followed by the address of the toc. The starting address we
- get from the bfd, and the descriptor is supposed to be in the
- .reldata section. */
-
- bfd_vma loadable_toc_address;
- bfd_vma toc_address;
- bfd_vma start_address;
- bfd_byte *data;
- bfd_vma offset;
-
- if (!bfd_malloc_and_get_section (abfd, rel_section, &data))
- {
- if (data != NULL)
- free (data);
- return FALSE;
- }
-
- offset = abfd->start_address - rel_section->vma;
-
- if (offset >= rel_section->size || offset + 8 > rel_section->size)
- {
- if (data != NULL)
- free (data);
- return FALSE;
- }
-
- start_address = bfd_get_32 (abfd, data + offset);
- loadable_toc_address = bfd_get_32 (abfd, data + offset + 4);
- toc_address = loadable_toc_address - 32768;
-
- fprintf (file,
- _("\nFunction descriptor located at the start address: %04lx\n"),
- (unsigned long int) (abfd->start_address));
- fprintf (file,
- /* xgettext:c-format */
- _("\tcode-base %08lx toc (loadable/actual) %08lx/%08lx\n"),
- start_address, loadable_toc_address, toc_address);
- if (data != NULL)
- free (data);
- }
- else
- {
- fprintf (file,
- _("\nNo reldata section! Function descriptor not decoded.\n"));
- }
-#endif
-
fprintf (file,
_("\nThe Import Tables (interpreted %s section contents)\n"),
section->name);
/* Read the whole section. Some of the fields might be before dataoff. */
if (!bfd_malloc_and_get_section (abfd, section, &data))
{
- if (data != NULL)
- free (data);
+ free (data);
return FALSE;
}
if (! bfd_malloc_and_get_section (abfd, section, &data))
{
- if (data != NULL)
- free (data);
+ free (data);
return FALSE;
}
bfd_fprintf_vma (abfd, file, prolog_end_addr);
fprintf (file, " %x", em_data);
#endif
-
-#ifdef POWERPC_LE_PE
- if (eh_handler == 0 && eh_data != 0)
- {
- /* Special bits here, although the meaning may be a little
- mysterious. The only one I know for sure is 0x03
- Code Significance
- 0x00 None
- 0x01 Register Save Millicode
- 0x02 Register Restore Millicode
- 0x03 Glue Code Sequence. */
- switch (eh_data)
- {
- case 0x01:
- fprintf (file, _(" Register save millicode"));
- break;
- case 0x02:
- fprintf (file, _(" Register restore millicode"));
- break;
- case 0x03:
- fprintf (file, _(" Glue code sequence"));
- break;
- default:
- break;
- }
- }
-#endif
fprintf (file, "\n");
}
if (! bfd_malloc_and_get_section (abfd, section, &data))
{
- if (data != NULL)
- free (data);
+ free (data);
return FALSE;
}
if (! bfd_malloc_and_get_section (abfd, section, &data))
{
- if (data != NULL)
- free (data);
+ free (data);
return FALSE;
}
if (! bfd_malloc_and_get_section (abfd, section, & data))
{
- if (data != NULL)
- free (data);
+ free (data);
return FALSE;
}
return TRUE;
}
-#define IMAGE_NUMBEROF_DEBUG_TYPES 12
+#define IMAGE_NUMBEROF_DEBUG_TYPES 17
static char * debug_type_names[IMAGE_NUMBEROF_DEBUG_TYPES] =
{
"Borland",
"Reserved",
"CLSID",
+ "Feature",
+ "CoffGrp",
+ "ILTCG",
+ "MPX",
+ "Repro",
};
static bfd_boolean
asection *section;
bfd_byte *data = 0;
bfd_size_type dataoff;
- unsigned int i;
+ unsigned int i, j;
bfd_vma addr = extra->DataDirectory[PE_DEBUG_DATA].VirtualAddress;
bfd_size_type size = extra->DataDirectory[PE_DEBUG_DATA].Size;
/* Read the whole section. */
if (!bfd_malloc_and_get_section (abfd, section, &data))
{
- if (data != NULL)
- free (data);
+ free (data);
return FALSE;
}
idd.SizeOfData, cvinfo))
continue;
- for (i = 0; i < cvinfo->SignatureLength; i++)
- sprintf (&signature[i*2], "%02x", cvinfo->Signature[i] & 0xff);
+ for (j = 0; j < cvinfo->SignatureLength; j++)
+ sprintf (&signature[j*2], "%02x", cvinfo->Signature[j] & 0xff);
/* xgettext:c-format */
fprintf (file, _("(format %c%c%c%c signature %s age %ld)\n"),
}
}
+ free(data);
+
if (size % sizeof (struct external_IMAGE_DEBUG_DIRECTORY) != 0)
fprintf (file,
_("The debug directory size is not a multiple of the debug directory entry size\n"));
return TRUE;
}
+static bfd_boolean
+pe_is_repro (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_boolean res = FALSE;
+
+ bfd_vma addr = extra->DataDirectory[PE_DEBUG_DATA].VirtualAddress;
+ bfd_size_type size = extra->DataDirectory[PE_DEBUG_DATA].Size;
+
+ if (size == 0)
+ return FALSE;
+
+ addr += extra->ImageBase;
+ for (section = abfd->sections; section != NULL; section = section->next)
+ {
+ if ((addr >= section->vma) && (addr < (section->vma + section->size)))
+ break;
+ }
+
+ if ((section == NULL)
+ || (!(section->flags & SEC_HAS_CONTENTS))
+ || (section->size < size))
+ {
+ return FALSE;
+ }
+
+ dataoff = addr - section->vma;
+
+ if (size > (section->size - dataoff))
+ {
+ return FALSE;
+ }
+
+ if (!bfd_malloc_and_get_section (abfd, section, &data))
+ {
+ free (data);
+ return FALSE;
+ }
+
+ 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_REPRO)
+ {
+ res = TRUE;
+ break;
+ }
+ }
+
+ free(data);
+
+ return res;
+}
+
/* Print out the program headers. */
bfd_boolean
PF (IMAGE_FILE_BYTES_REVERSED_HI, "big endian");
#undef PF
- /* ctime implies '\n'. */
- {
- time_t t = pe->coff.timestamp;
- fprintf (file, "\nTime/Date\t\t%s", ctime (&t));
- }
+ /*
+ If a PE_IMAGE_DEBUG_TYPE_REPRO entry is present in the debug directory, the
+ timestamp is to be interpreted as the hash of a reproducible build.
+ */
+ if (pe_is_repro (abfd))
+ {
+ fprintf (file, "\nTime/Date\t\t%08lx", pe->coff.timestamp);
+ fprintf (file, "\t(This is a reproducible build file hash, not a timestamp)\n");
+ }
+ else
+ {
+ /* ctime implies '\n'. */
+ time_t t = pe->coff.timestamp;
+ fprintf (file, "\nTime/Date\t\t%s", ctime (&t));
+ }
#ifndef IMAGE_NT_OPTIONAL_HDR_MAGIC
# define IMAGE_NT_OPTIONAL_HDR_MAGIC 0x10b
case IMAGE_SUBSYSTEM_WINDOWS_CE_GUI:
subsystem_name = "Wince CUI";
break;
- // These are from UEFI Platform Initialization Specification 1.1.
+ /* These are from UEFI Platform Initialization Specification 1.1. */
case IMAGE_SUBSYSTEM_EFI_APPLICATION:
subsystem_name = "EFI application";
break;
case IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER:
subsystem_name = "SAL runtime driver";
break;
- // This is from revision 8.0 of the MS PE/COFF spec
+ /* This is from revision 8.0 of the MS PE/COFF spec */
case IMAGE_SUBSYSTEM_XBOX:
subsystem_name = "XBOX";
break;
- // Added default case for clarity - subsystem_name is NULL anyway.
+ /* Added default case for clarity - subsystem_name is NULL anyway. */
default:
subsystem_name = NULL;
}
{
bfd_vma addr = ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].VirtualAddress
+ ope->pe_opthdr.ImageBase;
- asection *section = find_section_by_vma (obfd, addr);
+ /* In particular a .buildid section may overlap (in VA space) with
+ whatever section comes ahead of it (largely because of section->size
+ representing s_size, not virt_size). Therefore don't look for the
+ section containing the first byte, but for that covering the last
+ one. */
+ bfd_vma last = addr + ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size - 1;
+ asection *section = find_section_by_vma (obfd, last);
bfd_byte *data;
+ /* PR 17512: file: 0f15796a. */
+ if (section && addr < section->vma)
+ {
+ /* xgettext:c-format */
+ _bfd_error_handler
+ (_("%pB: Data Directory (%lx bytes at %" PRIx64 ") "
+ "extends across section boundary at %" PRIx64),
+ obfd, ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size,
+ (uint64_t) addr, (uint64_t) section->vma);
+ return FALSE;
+ }
+
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));
- /* PR 17512: file: 0f15796a. */
- if ((unsigned long) ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size
- > section->size - (addr - section->vma))
- {
- /* xgettext:c-format */
- _bfd_error_handler
- (_("%pB: Data Directory size (%lx) "
- "exceeds space left in section (%" PRIx64 ")"),
- obfd, ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size,
- (uint64_t) (section->size - (addr - section->vma)));
- free (data);
- return FALSE;
- }
-
for (i = 0; i < ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size
/ sizeof (struct external_IMAGE_DEBUG_DIRECTORY); i++)
{
{
if (coff_section_data (obfd, osec) == NULL)
{
- bfd_size_type amt = sizeof (struct coff_section_tdata);
+ size_t amt = sizeof (struct coff_section_tdata);
osec->used_by_bfd = bfd_zalloc (obfd, amt);
if (osec->used_by_bfd == NULL)
return FALSE;
if (pei_section_data (obfd, osec) == NULL)
{
- bfd_size_type amt = sizeof (struct pei_section_tdata);
+ size_t amt = sizeof (struct pei_section_tdata);
coff_section_data (obfd, osec)->tdata = bfd_zalloc (obfd, amt);
if (coff_section_data (obfd, osec)->tdata == NULL)
return FALSE;
}
static const char *
-rsrc_resource_name (rsrc_entry * entry, rsrc_directory * dir)
+rsrc_resource_name (rsrc_entry *entry, rsrc_directory *dir, char *buffer)
{
- static char buffer [256];
bfd_boolean is_string = FALSE;
buffer[0] = 0;
|| dir->entry->parent->entry == NULL)
_bfd_error_handler (_(".rsrc merge failure: duplicate leaf"));
else
- _bfd_error_handler (_(".rsrc merge failure: duplicate leaf: %s"),
- rsrc_resource_name (entry, dir));
+ {
+ char buff[256];
+
+ _bfd_error_handler (_(".rsrc merge failure: duplicate leaf: %s"),
+ rsrc_resource_name (entry, dir, buff));
+ }
bfd_set_error (bfd_error_file_truncated);
return;
}