/* Support for the generic parts of PE/PEI; the common executable parts.
Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006 Free Software Foundation, Inc.
+ 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
Written by Cygnus Solutions.
This file is part of BFD, the Binary File Descriptor library.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
/* Most of this hacked by Steve Chamberlain <sac@cygnus.com>.
on this code has a chance of getting something accomplished without
wasting too much time. */
-/* This expands into COFF_WITH_pe or COFF_WITH_pep depending on whether
- we're compiling for straight PE or PE+. */
+/* This expands into COFF_WITH_pe, COFF_WITH_pep, or COFF_WITH_pex64
+ depending on whether we're compiling for straight PE or PE+. */
#define COFF_WITH_XX
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "libbfd.h"
#include "coff/internal.h"
+#include "bfdver.h"
/* NOTE: it's strange to be including an architecture specific header
in what's supposed to be general (to PE/PEI) code. However, that's
within PE/PEI, so we get them from there. FIXME: The lack of
variance is an assumption which may prove to be incorrect if new
PE/PEI targets are created. */
-#ifdef COFF_WITH_pep
+#if defined COFF_WITH_pex64
+# include "coff/x86_64.h"
+#elif defined COFF_WITH_pep
# include "coff/ia64.h"
#else
# include "coff/i386.h"
#include "libcoff.h"
#include "libpei.h"
-#ifdef COFF_WITH_pep
+#if defined COFF_WITH_pep || defined COFF_WITH_pex64
# undef AOUTSZ
# define AOUTSZ PEPAOUTSZ
# define PEAOUTHDR PEPAOUTHDR
they will be handled somewhat correctly in the bfd code. */
if (in->n_sclass == C_SECTION)
{
+ char namebuf[SYMNMLEN + 1];
+ const char *name = NULL;
+
in->n_value = 0x0;
/* Create synthetic empty sections as needed. DJ */
{
asection *sec;
- for (sec = abfd->sections; sec; sec = sec->next)
- {
- if (strcmp (sec->name, in->n_name) == 0)
- {
- in->n_scnum = sec->target_index;
- break;
- }
- }
+ name = _bfd_coff_internal_syment_name (abfd, in, namebuf);
+ if (name == NULL)
+ /* FIXME: Return error. */
+ abort ();
+ sec = bfd_get_section_by_name (abfd, name);
+ if (sec != NULL)
+ in->n_scnum = sec->target_index;
}
if (in->n_scnum == 0)
{
int unused_section_number = 0;
asection *sec;
- char *name;
+ flagword flags;
for (sec = abfd->sections; sec; sec = sec->next)
if (unused_section_number <= sec->target_index)
unused_section_number = sec->target_index + 1;
- name = bfd_alloc (abfd, (bfd_size_type) strlen (in->n_name) + 10);
- if (name == NULL)
- return;
- strcpy (name, in->n_name);
- sec = bfd_make_section_anyway (abfd, name);
+ if (name == namebuf)
+ {
+ name = (const char *) bfd_alloc (abfd, strlen (namebuf) + 1);
+ if (name == NULL)
+ /* FIXME: Return error. */
+ abort ();
+ strcpy ((char *) name, namebuf);
+ }
+ flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_DATA | SEC_LOAD;
+ sec = bfd_make_section_anyway_with_flags (abfd, name, flags);
+ if (sec == NULL)
+ /* FIXME: Return error. */
+ abort ();
sec->vma = 0;
sec->lma = 0;
sec->userdata = NULL;
sec->next = NULL;
sec->alignment_power = 2;
- sec->flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_DATA | SEC_LOAD;
sec->target_index = unused_section_number;
_bfd_XXi_swap_aux_in (bfd * abfd,
void * ext1,
int type,
- int class,
+ int in_class,
int indx ATTRIBUTE_UNUSED,
int numaux ATTRIBUTE_UNUSED,
void * in1)
AUXENT *ext = (AUXENT *) ext1;
union internal_auxent *in = (union internal_auxent *) in1;
- switch (class)
+ switch (in_class)
{
case C_FILE:
if (ext->x_file.x_fname[0] == 0)
in->x_sym.x_tagndx.l = H_GET_32 (abfd, ext->x_sym.x_tagndx);
in->x_sym.x_tvndx = H_GET_16 (abfd, ext->x_sym.x_tvndx);
- if (class == C_BLOCK || class == C_FCN || ISFCN (type) || ISTAG (class))
+ if (in_class == C_BLOCK || in_class == C_FCN || ISFCN (type)
+ || ISTAG (in_class))
{
in->x_sym.x_fcnary.x_fcn.x_lnnoptr = GET_FCN_LNNOPTR (abfd, ext);
in->x_sym.x_fcnary.x_fcn.x_endndx.l = GET_FCN_ENDNDX (abfd, ext);
_bfd_XXi_swap_aux_out (bfd * abfd,
void * inp,
int type,
- int class,
+ int in_class,
int indx ATTRIBUTE_UNUSED,
int numaux ATTRIBUTE_UNUSED,
void * extp)
memset (ext, 0, AUXESZ);
- switch (class)
+ switch (in_class)
{
case C_FILE:
if (in->x_file.x_fname[0] == 0)
H_PUT_32 (abfd, in->x_sym.x_tagndx.l, ext->x_sym.x_tagndx);
H_PUT_16 (abfd, in->x_sym.x_tvndx, ext->x_sym.x_tvndx);
- if (class == C_BLOCK || class == C_FCN || ISFCN (type) || ISTAG (class))
+ if (in_class == C_BLOCK || in_class == C_FCN || ISFCN (type)
+ || ISTAG (in_class))
{
PUT_FCN_LNNOPTR (abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr, ext);
PUT_FCN_ENDNDX (abfd, in->x_sym.x_fcnary.x_fcn.x_endndx.l, ext);
void * aouthdr_ext1,
void * aouthdr_int1)
{
- struct internal_extra_pe_aouthdr *a;
- PEAOUTHDR * src = (PEAOUTHDR *) (aouthdr_ext1);
+ PEAOUTHDR * src = (PEAOUTHDR *) aouthdr_ext1;
AOUTHDR * aouthdr_ext = (AOUTHDR *) aouthdr_ext1;
- struct internal_aouthdr *aouthdr_int = (struct internal_aouthdr *)aouthdr_int1;
+ struct internal_aouthdr *aouthdr_int
+ = (struct internal_aouthdr *) aouthdr_int1;
+ struct internal_extra_pe_aouthdr *a = &aouthdr_int->pe;
aouthdr_int->magic = H_GET_16 (abfd, aouthdr_ext->magic);
aouthdr_int->vstamp = H_GET_16 (abfd, aouthdr_ext->vstamp);
aouthdr_int->entry = GET_AOUTHDR_ENTRY (abfd, aouthdr_ext->entry);
aouthdr_int->text_start =
GET_AOUTHDR_TEXT_START (abfd, aouthdr_ext->text_start);
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
/* PE32+ does not have data_start member! */
aouthdr_int->data_start =
GET_AOUTHDR_DATA_START (abfd, aouthdr_ext->data_start);
+ a->BaseOfData = aouthdr_int->data_start;
#endif
- a = &aouthdr_int->pe;
+ a->Magic = aouthdr_int->magic;
+ a->MajorLinkerVersion = H_GET_8 (abfd, aouthdr_ext->vstamp);
+ a->MinorLinkerVersion = H_GET_8 (abfd, aouthdr_ext->vstamp + 1);
+ a->SizeOfCode = aouthdr_int->tsize ;
+ a->SizeOfInitializedData = aouthdr_int->dsize ;
+ a->SizeOfUninitializedData = aouthdr_int->bsize ;
+ a->AddressOfEntryPoint = aouthdr_int->entry;
+ a->BaseOfCode = aouthdr_int->text_start;
a->ImageBase = GET_OPTHDR_IMAGE_BASE (abfd, src->ImageBase);
a->SectionAlignment = H_GET_32 (abfd, src->SectionAlignment);
a->FileAlignment = H_GET_32 (abfd, src->FileAlignment);
/* If data directory is empty, rva also should be 0. */
int size =
H_GET_32 (abfd, src->DataDirectory[idx][1]);
+
a->DataDirectory[idx].Size = size;
if (size)
if (aouthdr_int->entry)
{
aouthdr_int->entry += a->ImageBase;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
aouthdr_int->entry &= 0xffffffff;
#endif
}
if (aouthdr_int->tsize)
{
aouthdr_int->text_start += a->ImageBase;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
aouthdr_int->text_start &= 0xffffffff;
#endif
}
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
/* PE32+ does not have data_start member! */
if (aouthdr_int->dsize)
{
/* 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[12].VirtualAddress;
- thunk_size = a->DataDirectory[12].Size;
- import_table_size = a->DataDirectory[1].Size;
+ 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
}
bfd_vma sa, fa, ib;
IMAGE_DATA_DIRECTORY idata2, idata5, tls;
- if (pe->force_minimum_alignment)
- {
- if (!extra->FileAlignment)
- extra->FileAlignment = PE_DEF_FILE_ALIGNMENT;
- if (!extra->SectionAlignment)
- extra->SectionAlignment = PE_DEF_SECTION_ALIGNMENT;
- }
-
- if (extra->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN)
- extra->Subsystem = pe->target_subsystem;
-
sa = extra->SectionAlignment;
fa = extra->FileAlignment;
ib = extra->ImageBase;
- idata2 = pe->pe_opthdr.DataDirectory[1];
- idata5 = pe->pe_opthdr.DataDirectory[12];
- tls = pe->pe_opthdr.DataDirectory[9];
+ idata2 = pe->pe_opthdr.DataDirectory[PE_IMPORT_TABLE];
+ idata5 = pe->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE];
+ tls = pe->pe_opthdr.DataDirectory[PE_TLS_TABLE];
if (aouthdr_in->tsize)
{
aouthdr_in->text_start -= ib;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
aouthdr_in->text_start &= 0xffffffff;
#endif
}
if (aouthdr_in->dsize)
{
aouthdr_in->data_start -= ib;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
aouthdr_in->data_start &= 0xffffffff;
#endif
}
if (aouthdr_in->entry)
{
aouthdr_in->entry -= ib;
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
aouthdr_in->entry &= 0xffffffff;
#endif
}
So - we copy the input values into the output values, and then, if
a final link is going to be performed, it can overwrite them. */
- extra->DataDirectory[1] = idata2;
- extra->DataDirectory[12] = idata5;
- extra->DataDirectory[9] = tls;
+ extra->DataDirectory[PE_IMPORT_TABLE] = idata2;
+ extra->DataDirectory[PE_IMPORT_ADDRESS_TABLE] = idata5;
+ extra->DataDirectory[PE_TLS_TABLE] = tls;
- if (extra->DataDirectory[1].VirtualAddress == 0)
+ if (extra->DataDirectory[PE_IMPORT_TABLE].VirtualAddress == 0)
/* Until other .idata fixes are made (pending patch), the entry for
.idata is needed for backwards compatibility. FIXME. */
add_data_entry (abfd, extra, 1, ".idata", ib);
in the virt_size field). Files have been seen (from MSVC
5.0 link.exe) where the file size of the .data segment is
quite small compared to the virtual size. Without this
- fix, strip munges the file. */
+ fix, strip munges the file.
+
+ FIXME: We need to handle holes between sections, which may
+ happpen when we covert from another format. We just use
+ the virtual address and virtual size of the last section
+ for the image size. */
if (coff_section_data (abfd, sec) != NULL
&& pei_section_data (abfd, sec) != NULL)
- isize += SA (FA (pei_section_data (abfd, sec)->virt_size));
+ isize = (sec->vma - extra->ImageBase
+ + SA (FA (pei_section_data (abfd, sec)->virt_size)));
}
aouthdr_in->dsize = dsize;
aouthdr_in->tsize = tsize;
extra->SizeOfHeaders = hsize;
- extra->SizeOfImage = SA (hsize) + isize;
+ extra->SizeOfImage = isize;
}
H_PUT_16 (abfd, aouthdr_in->magic, aouthdr_out->standard.magic);
-#define LINKER_VERSION 256 /* That is, 2.56 */
+/* e.g. 219510000 is linker version 2.19 */
+#define LINKER_VERSION ((short) (BFD_VERSION / 1000000))
/* This piece of magic sets the "linker version" field to
LINKER_VERSION. */
PUT_AOUTHDR_TEXT_START (abfd, aouthdr_in->text_start,
aouthdr_out->standard.text_start);
-#ifndef COFF_WITH_pep
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
/* PE32+ does not have data_start member! */
PUT_AOUTHDR_DATA_START (abfd, aouthdr_in->data_start,
aouthdr_out->standard.data_start);
sometimes). */
if ((scnhdr_int->s_flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA) != 0)
{
- if (bfd_pe_executable_p (abfd))
+ if (bfd_pei_p (abfd))
{
ps = scnhdr_int->s_size;
ss = 0;
}
else
{
- if (bfd_pe_executable_p (abfd))
+ if (bfd_pei_p (abfd))
ps = scnhdr_int->s_paddr;
else
ps = 0;
N_("Bound Import Directory"),
N_("Import Address Table Directory"),
N_("Delay Import Directory"),
- N_("Reserved"),
+ N_("CLR Runtime Header"),
N_("Reserved")
};
bfd_vma addr;
- addr = extra->DataDirectory[1].VirtualAddress;
+ addr = extra->DataDirectory[PE_IMPORT_TABLE].VirtualAddress;
- if (addr == 0 && extra->DataDirectory[1].Size == 0)
+ if (addr == 0 && extra->DataDirectory[PE_IMPORT_TABLE].Size == 0)
{
/* Maybe the extra header isn't there. Look for the section. */
section = bfd_get_section_by_name (abfd, ".idata");
bfd_size_type j;
char *dll;
- /* Print (i + extra->DataDirectory[1].VirtualAddress). */
+ /* Print (i + extra->DataDirectory[PE_IMPORT_TABLE].VirtualAddress). */
fprintf (file, " %08lx\t", (unsigned long) (i + adj + dataoff));
hint_addr = bfd_get_32 (abfd, data + i + dataoff);
time_stamp = bfd_get_32 (abfd, data + i + 4 + dataoff);
ft_data = data;
ft_idx = first_thunk - adj;
ft_allocated = 0;
-
- if (first_thunk != hint_addr)
+
+ if (first_thunk != hint_addr)
{
/* Find the section which contains the first thunk. */
for (ft_section = abfd->sections;
else
{
ft_idx = first_thunk - (ft_section->vma - extra->ImageBase);
- ft_data = bfd_malloc (datasize);
+ ft_data = (bfd_byte *) bfd_malloc (datasize);
if (ft_data == NULL)
continue;
}
/* Print HintName vector entries. */
+#ifdef COFF_WITH_pex64
+ for (j = 0; j < datasize; j += 8)
+ {
+ unsigned long member = bfd_get_32 (abfd, data + idx + j);
+ unsigned long member_high = bfd_get_32 (abfd, data + idx + j + 4);
+
+ if (!member && !member_high)
+ break;
+
+ if (member_high & 0x80000000)
+ fprintf (file, "\t%lx%08lx\t %4lx%08lx <none>",
+ member_high,member, member_high & 0x7fffffff, member);
+ else
+ {
+ int ordinal;
+ char *member_name;
+
+ ordinal = bfd_get_16 (abfd, data + member - adj);
+ member_name = (char *) data + member - adj + 2;
+ fprintf (file, "\t%04lx\t %4d %s",member, ordinal, member_name);
+ }
+
+ /* If the time stamp is not zero, the import address
+ table holds actual addresses. */
+ if (time_stamp != 0
+ && first_thunk != 0
+ && first_thunk != hint_addr)
+ fprintf (file, "\t%04lx",
+ (unsigned long) bfd_get_32 (abfd, ft_data + ft_idx + j));
+ fprintf (file, "\n");
+ }
+#else
for (j = 0; j < datasize; j += 4)
{
unsigned long member = bfd_get_32 (abfd, data + idx + j);
&& first_thunk != 0
&& first_thunk != hint_addr)
fprintf (file, "\t%04lx",
- (long) bfd_get_32 (abfd, ft_data + ft_idx + j));
+ (unsigned long) bfd_get_32 (abfd, ft_data + ft_idx + j));
fprintf (file, "\n");
}
-
+#endif
if (ft_allocated)
free (ft_data);
}
bfd_vma addr;
- addr = extra->DataDirectory[0].VirtualAddress;
+ addr = extra->DataDirectory[PE_EXPORT_TABLE].VirtualAddress;
- if (addr == 0 && extra->DataDirectory[0].Size == 0)
+ if (addr == 0 && extra->DataDirectory[PE_EXPORT_TABLE].Size == 0)
{
/* Maybe the extra header isn't there. Look for the section. */
section = bfd_get_section_by_name (abfd, ".edata");
}
dataoff = addr - section->vma;
- datasize = extra->DataDirectory[0].Size;
+ datasize = extra->DataDirectory[PE_EXPORT_TABLE].Size;
if (datasize > section->size - dataoff)
{
fprintf (file,
fprintf (file, _("\nThere is an export table in %s at 0x%lx\n"),
section->name, (unsigned long) addr);
- data = bfd_malloc (datasize);
+ data = (bfd_byte *) bfd_malloc (datasize);
if (data == NULL)
return FALSE;
fprintf (file,
_("Name \t\t\t\t"));
- fprintf_vma (file, edt.name);
+ bfd_fprintf_vma (abfd, file, edt.name);
fprintf (file,
" %s\n", data + edt.name - adj);
fprintf (file,
_("\tExport Address Table \t\t"));
- fprintf_vma (file, edt.eat_addr);
+ bfd_fprintf_vma (abfd, file, edt.eat_addr);
fprintf (file, "\n");
fprintf (file,
_("\tName Pointer Table \t\t"));
- fprintf_vma (file, edt.npt_addr);
+ bfd_fprintf_vma (abfd, file, edt.npt_addr);
fprintf (file, "\n");
fprintf (file,
_("\tOrdinal Table \t\t\t"));
- fprintf_vma (file, edt.ot_addr);
+ bfd_fprintf_vma (abfd, file, edt.ot_addr);
fprintf (file, "\n");
/* The next table to find is the Export Address Table. It's basically
/* This really is architecture dependent. On IA-64, a .pdata entry
consists of three dwords containing relative virtual addresses that
specify the start and end address of the code range the entry
- covers and the address of the corresponding unwind info data. */
+ covers and the address of the corresponding unwind info data.
+
+ On ARM and SH-4, a compressed PDATA structure is used :
+ _IMAGE_CE_RUNTIME_FUNCTION_ENTRY, whereas MIPS is documented to use
+ _IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY.
+ See http://msdn2.microsoft.com/en-us/library/ms253988(VS.80).aspx .
+
+ This is the version for uncompressed data. */
static bfd_boolean
pe_print_pdata (bfd * abfd, void * vfile)
{
-#ifdef COFF_WITH_pep
-# define PDATA_ROW_SIZE (3*8)
+#if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
+# define PDATA_ROW_SIZE (3 * 8)
#else
-# define PDATA_ROW_SIZE (5*4)
+# define PDATA_ROW_SIZE (5 * 4)
#endif
FILE *file = (FILE *) vfile;
bfd_byte *data = 0;
fprintf (file,
_("\nThe Function Table (interpreted .pdata section contents)\n"));
-#ifdef COFF_WITH_pep
+#if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
fprintf (file,
_(" vma:\t\t\tBegin Address End Address Unwind Info\n"));
#else
prolog_end_addr &= ~(bfd_vma) 0x3;
fputc (' ', file);
- fprintf_vma (file, i + section->vma); fputc ('\t', file);
- fprintf_vma (file, begin_addr); fputc (' ', file);
- fprintf_vma (file, end_addr); fputc (' ', file);
- fprintf_vma (file, eh_handler);
-#ifndef COFF_WITH_pep
+ bfd_fprintf_vma (abfd, file, i + section->vma); fputc ('\t', file);
+ bfd_fprintf_vma (abfd, file, begin_addr); fputc (' ', file);
+ bfd_fprintf_vma (abfd, file, end_addr); fputc (' ', file);
+ bfd_fprintf_vma (abfd, file, eh_handler);
+#if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64)
fputc (' ', file);
- fprintf_vma (file, eh_data); fputc (' ', file);
- fprintf_vma (file, prolog_end_addr);
+ bfd_fprintf_vma (abfd, file, eh_data); fputc (' ', file);
+ bfd_fprintf_vma (abfd, file, prolog_end_addr);
fprintf (file, " %x", em_data);
#endif
free (data);
return TRUE;
+#undef PDATA_ROW_SIZE
+}
+
+typedef struct sym_cache
+{
+ int symcount;
+ asymbol ** syms;
+} sym_cache;
+
+static asymbol **
+slurp_symtab (bfd *abfd, sym_cache *psc)
+{
+ asymbol ** sy = NULL;
+ long storage;
+
+ if (!(bfd_get_file_flags (abfd) & HAS_SYMS))
+ {
+ psc->symcount = 0;
+ return NULL;
+ }
+
+ storage = bfd_get_symtab_upper_bound (abfd);
+ if (storage < 0)
+ return NULL;
+ if (storage)
+ sy = (asymbol **) bfd_malloc (storage);
+
+ psc->symcount = bfd_canonicalize_symtab (abfd, sy);
+ if (psc->symcount < 0)
+ return NULL;
+ return sy;
+}
+
+static const char *
+my_symbol_for_address (bfd *abfd, bfd_vma func, sym_cache *psc)
+{
+ int i;
+
+ if (psc->syms == 0)
+ psc->syms = slurp_symtab (abfd, psc);
+
+ for (i = 0; i < psc->symcount; i++)
+ {
+ if (psc->syms[i]->section->vma + psc->syms[i]->value == func)
+ return psc->syms[i]->name;
+ }
+
+ return NULL;
+}
+
+static void
+cleanup_syms (sym_cache *psc)
+{
+ psc->symcount = 0;
+ free (psc->syms);
+ psc->syms = NULL;
+}
+
+/* This is the version for "compressed" pdata. */
+
+bfd_boolean
+_bfd_XX_print_ce_compressed_pdata (bfd * abfd, void * vfile)
+{
+# define PDATA_ROW_SIZE (2 * 4)
+ FILE *file = (FILE *) vfile;
+ bfd_byte *data = NULL;
+ asection *section = bfd_get_section_by_name (abfd, ".pdata");
+ bfd_size_type datasize = 0;
+ bfd_size_type i;
+ bfd_size_type start, stop;
+ int onaline = PDATA_ROW_SIZE;
+ struct sym_cache sym_cache = {0, 0} ;
+
+ if (section == NULL
+ || coff_section_data (abfd, section) == NULL
+ || pei_section_data (abfd, section) == NULL)
+ return TRUE;
+
+ stop = pei_section_data (abfd, section)->virt_size;
+ if ((stop % onaline) != 0)
+ fprintf (file,
+ _("Warning, .pdata section size (%ld) is not a multiple of %d\n"),
+ (long) stop, onaline);
+
+ fprintf (file,
+ _("\nThe Function Table (interpreted .pdata section contents)\n"));
+
+ fprintf (file, _("\
+ vma:\t\tBegin Prolog Function Flags Exception EH\n\
+ \t\tAddress Length Length 32b exc Handler Data\n"));
+
+ datasize = section->size;
+ if (datasize == 0)
+ return TRUE;
+
+ if (! bfd_malloc_and_get_section (abfd, section, &data))
+ {
+ if (data != NULL)
+ free (data);
+ return FALSE;
+ }
+
+ start = 0;
+
+ for (i = start; i < stop; i += onaline)
+ {
+ bfd_vma begin_addr;
+ bfd_vma other_data;
+ bfd_vma prolog_length, function_length;
+ int flag32bit, exception_flag;
+ bfd_byte *tdata = 0;
+ asection *tsection;
+
+ if (i + PDATA_ROW_SIZE > stop)
+ break;
+
+ begin_addr = GET_PDATA_ENTRY (abfd, data + i );
+ other_data = GET_PDATA_ENTRY (abfd, data + i + 4);
+
+ if (begin_addr == 0 && other_data == 0)
+ /* We are probably into the padding of the section now. */
+ break;
+
+ prolog_length = (other_data & 0x000000FF);
+ function_length = (other_data & 0x3FFFFF00) >> 8;
+ flag32bit = (int)((other_data & 0x40000000) >> 30);
+ exception_flag = (int)((other_data & 0x80000000) >> 31);
+
+ fputc (' ', file);
+ bfd_fprintf_vma (abfd, file, i + section->vma); fputc ('\t', file);
+ bfd_fprintf_vma (abfd, file, begin_addr); fputc (' ', file);
+ bfd_fprintf_vma (abfd, file, prolog_length); fputc (' ', file);
+ bfd_fprintf_vma (abfd, file, function_length); fputc (' ', file);
+ fprintf (file, "%2d %2d ", flag32bit, exception_flag);
+
+ /* Get the exception handler's address and the data passed from the
+ .text section. This is really the data that belongs with the .pdata
+ but got "compressed" out for the ARM and SH4 architectures. */
+ tsection = bfd_get_section_by_name (abfd, ".text");
+ if (tsection && coff_section_data (abfd, tsection)
+ && pei_section_data (abfd, tsection))
+ {
+ if (bfd_malloc_and_get_section (abfd, tsection, & tdata))
+ {
+ int xx = (begin_addr - 8) - tsection->vma;
+
+ tdata = (bfd_byte *) bfd_malloc (8);
+ if (bfd_get_section_contents (abfd, tsection, tdata, (bfd_vma) xx, 8))
+ {
+ bfd_vma eh, eh_data;
+
+ eh = bfd_get_32 (abfd, tdata);
+ eh_data = bfd_get_32 (abfd, tdata + 4);
+ fprintf (file, "%08x ", (unsigned int) eh);
+ fprintf (file, "%08x", (unsigned int) eh_data);
+ if (eh != 0)
+ {
+ const char *s = my_symbol_for_address (abfd, eh, &sym_cache);
+
+ if (s)
+ fprintf (file, " (%s) ", s);
+ }
+ }
+ free (tdata);
+ }
+ else
+ {
+ if (tdata)
+ free (tdata);
+ }
+ }
+
+ fprintf (file, "\n");
+ }
+
+ free (data);
+
+ cleanup_syms (& sym_cache);
+
+ return TRUE;
+#undef PDATA_ROW_SIZE
}
+\f
#define IMAGE_REL_BASED_HIGHADJ 4
static const char * const tbl[] =
{
fprintf (file,
_("\nVirtual Address: %08lx Chunk size %ld (0x%lx) Number of fixups %ld\n"),
- (unsigned long) virtual_address, size, size, number);
+ (unsigned long) virtual_address, size, (unsigned long) size, number);
for (j = 0; j < number; ++j)
{
fprintf (file,
_("\treloc %4d offset %4x [%4lx] %s"),
- j, off, (long) (off + virtual_address), tbl[t]);
+ j, off, (unsigned long) (off + virtual_address), tbl[t]);
/* HIGHADJ takes an argument, - the next record *is* the
low 16 bits of addend. */
pe_data_type *pe = pe_data (abfd);
struct internal_extra_pe_aouthdr *i = &pe->pe_opthdr;
const char *subsystem_name = NULL;
+ const char *name;
/* The MS dumpbin program reportedly ands with 0xff0f before
printing the characteristics field. Not sure why. No reason to
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
+#endif
+#ifndef IMAGE_NT_OPTIONAL_HDR64_MAGIC
+# define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
+#endif
+#ifndef IMAGE_NT_OPTIONAL_HDRROM_MAGIC
+# define IMAGE_NT_OPTIONAL_HDRROM_MAGIC 0x107
+#endif
+
+ switch (i->Magic)
+ {
+ case IMAGE_NT_OPTIONAL_HDR_MAGIC:
+ name = "PE32";
+ break;
+ case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
+ name = "PE32+";
+ break;
+ case IMAGE_NT_OPTIONAL_HDRROM_MAGIC:
+ name = "ROM";
+ break;
+ default:
+ name = NULL;
+ break;
+ }
+ fprintf (file, "Magic\t\t\t%04x", i->Magic);
+ if (name)
+ fprintf (file, "\t(%s)",name);
+ fprintf (file, "\nMajorLinkerVersion\t%d\n", i->MajorLinkerVersion);
+ fprintf (file, "MinorLinkerVersion\t%d\n", i->MinorLinkerVersion);
+ fprintf (file, "SizeOfCode\t\t%08lx\n", (unsigned long) i->SizeOfCode);
+ fprintf (file, "SizeOfInitializedData\t%08lx\n",
+ (unsigned long) i->SizeOfInitializedData);
+ fprintf (file, "SizeOfUninitializedData\t%08lx\n",
+ (unsigned long) i->SizeOfUninitializedData);
+ fprintf (file, "AddressOfEntryPoint\t");
+ bfd_fprintf_vma (abfd, file, i->AddressOfEntryPoint);
+ fprintf (file, "\nBaseOfCode\t\t");
+ bfd_fprintf_vma (abfd, file, i->BaseOfCode);
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64)
+ /* PE32+ does not have BaseOfData member! */
+ fprintf (file, "\nBaseOfData\t\t");
+ bfd_fprintf_vma (abfd, file, i->BaseOfData);
+#endif
+
fprintf (file, "\nImageBase\t\t");
- fprintf_vma (file, i->ImageBase);
+ bfd_fprintf_vma (abfd, file, i->ImageBase);
fprintf (file, "\nSectionAlignment\t");
- fprintf_vma (file, i->SectionAlignment);
+ bfd_fprintf_vma (abfd, file, i->SectionAlignment);
fprintf (file, "\nFileAlignment\t\t");
- fprintf_vma (file, i->FileAlignment);
+ bfd_fprintf_vma (abfd, file, i->FileAlignment);
fprintf (file, "\nMajorOSystemVersion\t%d\n", i->MajorOperatingSystemVersion);
fprintf (file, "MinorOSystemVersion\t%d\n", i->MinorOperatingSystemVersion);
fprintf (file, "MajorImageVersion\t%d\n", i->MajorImageVersion);
fprintf (file, "MinorImageVersion\t%d\n", i->MinorImageVersion);
fprintf (file, "MajorSubsystemVersion\t%d\n", i->MajorSubsystemVersion);
fprintf (file, "MinorSubsystemVersion\t%d\n", i->MinorSubsystemVersion);
- fprintf (file, "Win32Version\t\t%08lx\n", i->Reserved1);
- fprintf (file, "SizeOfImage\t\t%08lx\n", i->SizeOfImage);
- fprintf (file, "SizeOfHeaders\t\t%08lx\n", i->SizeOfHeaders);
- fprintf (file, "CheckSum\t\t%08lx\n", i->CheckSum);
+ fprintf (file, "Win32Version\t\t%08lx\n", (unsigned long) i->Reserved1);
+ fprintf (file, "SizeOfImage\t\t%08lx\n", (unsigned long) i->SizeOfImage);
+ fprintf (file, "SizeOfHeaders\t\t%08lx\n", (unsigned long) i->SizeOfHeaders);
+ fprintf (file, "CheckSum\t\t%08lx\n", (unsigned long) i->CheckSum);
switch (i->Subsystem)
{
case IMAGE_SUBSYSTEM_WINDOWS_CE_GUI:
subsystem_name = "Wince CUI";
break;
+ // These are from UEFI Platform Initialization Specification 1.1.
case IMAGE_SUBSYSTEM_EFI_APPLICATION:
subsystem_name = "EFI application";
break;
case IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
subsystem_name = "EFI runtime driver";
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
+ case IMAGE_SUBSYSTEM_XBOX:
+ subsystem_name = "XBOX";
+ break;
+ // Added default case for clarity - subsystem_name is NULL anyway.
+ default:
+ subsystem_name = NULL;
}
fprintf (file, "Subsystem\t\t%08x", i->Subsystem);
fprintf (file, "\t(%s)", subsystem_name);
fprintf (file, "\nDllCharacteristics\t%08x\n", i->DllCharacteristics);
fprintf (file, "SizeOfStackReserve\t");
- fprintf_vma (file, i->SizeOfStackReserve);
+ bfd_fprintf_vma (abfd, file, i->SizeOfStackReserve);
fprintf (file, "\nSizeOfStackCommit\t");
- fprintf_vma (file, i->SizeOfStackCommit);
+ bfd_fprintf_vma (abfd, file, i->SizeOfStackCommit);
fprintf (file, "\nSizeOfHeapReserve\t");
- fprintf_vma (file, i->SizeOfHeapReserve);
+ bfd_fprintf_vma (abfd, file, i->SizeOfHeapReserve);
fprintf (file, "\nSizeOfHeapCommit\t");
- fprintf_vma (file, i->SizeOfHeapCommit);
- fprintf (file, "\nLoaderFlags\t\t%08lx\n", i->LoaderFlags);
- fprintf (file, "NumberOfRvaAndSizes\t%08lx\n", i->NumberOfRvaAndSizes);
+ bfd_fprintf_vma (abfd, file, i->SizeOfHeapCommit);
+ fprintf (file, "\nLoaderFlags\t\t%08lx\n", (unsigned long) i->LoaderFlags);
+ fprintf (file, "NumberOfRvaAndSizes\t%08lx\n",
+ (unsigned long) i->NumberOfRvaAndSizes);
fprintf (file, "\nThe Data Directory\n");
for (j = 0; j < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; j++)
{
fprintf (file, "Entry %1x ", j);
- fprintf_vma (file, i->DataDirectory[j].VirtualAddress);
- fprintf (file, " %08lx ", i->DataDirectory[j].Size);
+ bfd_fprintf_vma (abfd, file, i->DataDirectory[j].VirtualAddress);
+ fprintf (file, " %08lx ", (unsigned long) i->DataDirectory[j].Size);
fprintf (file, "%s\n", dir_names[j]);
}
pe_print_idata (abfd, vfile);
pe_print_edata (abfd, vfile);
- pe_print_pdata (abfd, vfile);
+ if (bfd_coff_have_print_pdata (abfd))
+ bfd_coff_print_pdata (abfd, vfile);
+ else
+ pe_print_pdata (abfd, vfile);
pe_print_reloc (abfd, vfile);
return TRUE;
bfd_boolean
_bfd_XX_bfd_copy_private_bfd_data_common (bfd * ibfd, bfd * obfd)
{
+ pe_data_type *ipe, *ope;
+
/* One day we may try to grok other private data. */
if (ibfd->xvec->flavour != bfd_target_coff_flavour
|| obfd->xvec->flavour != bfd_target_coff_flavour)
return TRUE;
- pe_data (obfd)->pe_opthdr = pe_data (ibfd)->pe_opthdr;
- pe_data (obfd)->dll = pe_data (ibfd)->dll;
+ ipe = pe_data (ibfd);
+ ope = pe_data (obfd);
+
+ /* pe_opthdr is copied in copy_object. */
+ ope->dll = ipe->dll;
+
+ /* Don't copy input subsystem if output is different from input. */
+ if (obfd->xvec != ibfd->xvec)
+ ope->pe_opthdr.Subsystem = IMAGE_SUBSYSTEM_UNKNOWN;
/* For strip: if we removed .reloc, we'll make a real mess of things
if we don't remove this entry as well. */
if (! pe_data (obfd)->has_reloc_section)
{
- pe_data (obfd)->pe_opthdr.DataDirectory[5].VirtualAddress = 0;
- pe_data (obfd)->pe_opthdr.DataDirectory[5].Size = 0;
+ pe_data (obfd)->pe_opthdr.DataDirectory[PE_BASE_RELOCATION_TABLE].VirtualAddress = 0;
+ pe_data (obfd)->pe_opthdr.DataDirectory[PE_BASE_RELOCATION_TABLE].Size = 0;
}
return TRUE;
}
{
struct coff_link_hash_entry *h1;
struct bfd_link_info *info = pfinfo->info;
+ bfd_boolean result = TRUE;
/* There are a few fields that need to be filled in now while we
have symbol table access.
".idata$2", FALSE, FALSE, TRUE);
if (h1 != NULL)
{
- pe_data (abfd)->pe_opthdr.DataDirectory[1].VirtualAddress =
- (h1->root.u.def.value
- + h1->root.u.def.section->output_section->vma
- + h1->root.u.def.section->output_offset);
+ /* PR ld/2729: We cannot rely upon all the output sections having been
+ created properly, so check before referencing them. Issue a warning
+ message for any sections tht could not be found. */
+ if ((h1->root.type == bfd_link_hash_defined
+ || h1->root.type == bfd_link_hash_defweak)
+ && h1->root.u.def.section != NULL
+ && h1->root.u.def.section->output_section != NULL)
+ pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_TABLE].VirtualAddress =
+ (h1->root.u.def.value
+ + h1->root.u.def.section->output_section->vma
+ + h1->root.u.def.section->output_offset);
+ else
+ {
+ _bfd_error_handler
+ (_("%B: unable to fill in DataDictionary[1] because .idata$2 is missing"),
+ abfd);
+ result = FALSE;
+ }
+
h1 = coff_link_hash_lookup (coff_hash_table (info),
".idata$4", FALSE, FALSE, TRUE);
- pe_data (abfd)->pe_opthdr.DataDirectory[1].Size =
- ((h1->root.u.def.value
- + h1->root.u.def.section->output_section->vma
- + h1->root.u.def.section->output_offset)
- - pe_data (abfd)->pe_opthdr.DataDirectory[1].VirtualAddress);
+ if (h1 != NULL
+ && (h1->root.type == bfd_link_hash_defined
+ || h1->root.type == bfd_link_hash_defweak)
+ && h1->root.u.def.section != NULL
+ && h1->root.u.def.section->output_section != NULL)
+ pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_TABLE].Size =
+ ((h1->root.u.def.value
+ + h1->root.u.def.section->output_section->vma
+ + h1->root.u.def.section->output_offset)
+ - pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_TABLE].VirtualAddress);
+ else
+ {
+ _bfd_error_handler
+ (_("%B: unable to fill in DataDictionary[1] because .idata$4 is missing"),
+ abfd);
+ result = FALSE;
+ }
/* The import address table. This is the size/address of
.idata$5. */
h1 = coff_link_hash_lookup (coff_hash_table (info),
".idata$5", FALSE, FALSE, TRUE);
- pe_data (abfd)->pe_opthdr.DataDirectory[12].VirtualAddress =
- (h1->root.u.def.value
- + h1->root.u.def.section->output_section->vma
- + h1->root.u.def.section->output_offset);
+ if (h1 != NULL
+ && (h1->root.type == bfd_link_hash_defined
+ || h1->root.type == bfd_link_hash_defweak)
+ && h1->root.u.def.section != NULL
+ && h1->root.u.def.section->output_section != NULL)
+ pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE].VirtualAddress =
+ (h1->root.u.def.value
+ + h1->root.u.def.section->output_section->vma
+ + h1->root.u.def.section->output_offset);
+ else
+ {
+ _bfd_error_handler
+ (_("%B: unable to fill in DataDictionary[12] because .idata$5 is missing"),
+ abfd);
+ result = FALSE;
+ }
+
h1 = coff_link_hash_lookup (coff_hash_table (info),
".idata$6", FALSE, FALSE, TRUE);
- pe_data (abfd)->pe_opthdr.DataDirectory[12].Size =
- ((h1->root.u.def.value
- + h1->root.u.def.section->output_section->vma
- + h1->root.u.def.section->output_offset)
- - pe_data (abfd)->pe_opthdr.DataDirectory[12].VirtualAddress);
+ if (h1 != NULL
+ && (h1->root.type == bfd_link_hash_defined
+ || h1->root.type == bfd_link_hash_defweak)
+ && h1->root.u.def.section != NULL
+ && h1->root.u.def.section->output_section != NULL)
+ pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE].Size =
+ ((h1->root.u.def.value
+ + h1->root.u.def.section->output_section->vma
+ + h1->root.u.def.section->output_offset)
+ - pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_ADDRESS_TABLE].VirtualAddress);
+ else
+ {
+ _bfd_error_handler
+ (_("%B: unable to fill in DataDictionary[PE_IMPORT_ADDRESS_TABLE (12)] because .idata$6 is missing"),
+ abfd);
+ result = FALSE;
+ }
}
h1 = coff_link_hash_lookup (coff_hash_table (info),
"__tls_used", FALSE, FALSE, TRUE);
if (h1 != NULL)
{
- pe_data (abfd)->pe_opthdr.DataDirectory[9].VirtualAddress =
- (h1->root.u.def.value
- + h1->root.u.def.section->output_section->vma
- + h1->root.u.def.section->output_offset
- - pe_data (abfd)->pe_opthdr.ImageBase);
- pe_data (abfd)->pe_opthdr.DataDirectory[9].Size = 0x18;
+ if ((h1->root.type == bfd_link_hash_defined
+ || h1->root.type == bfd_link_hash_defweak)
+ && h1->root.u.def.section != NULL
+ && h1->root.u.def.section->output_section != NULL)
+ pe_data (abfd)->pe_opthdr.DataDirectory[PE_TLS_TABLE].VirtualAddress =
+ (h1->root.u.def.value
+ + h1->root.u.def.section->output_section->vma
+ + h1->root.u.def.section->output_offset
+ - pe_data (abfd)->pe_opthdr.ImageBase);
+ else
+ {
+ _bfd_error_handler
+ (_("%B: unable to fill in DataDictionary[9] because __tls_used is missing"),
+ abfd);
+ result = FALSE;
+ }
+
+ pe_data (abfd)->pe_opthdr.DataDirectory[PE_TLS_TABLE].Size = 0x18;
}
/* If we couldn't find idata$2, we either have an excessively
trivial program or are in DEEP trouble; we have to assume trivial
program.... */
- return TRUE;
+ return result;
}