/* Support for the generic parts of PE/PEI; the common executable parts.
- Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
Free Software Foundation, Inc.
Written by Cygnus Solutions.
-This file is part of BFD, the Binary File Descriptor library.
+ 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
-(at your option) any later version.
+ 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
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Most of this hacked by Steve Chamberlain <sac@cygnus.com>.
PE/PEI rearrangement (and code added): Donn Terry
- Softway Systems, Inc.
-*/
+ Softway Systems, Inc. */
/* Hey look, some documentation [and in a place you expect to find it]!
FIXME: Please add more docs here so the next poor fool that has to hack
on this code has a chance of getting something accomplished without
- wasting too much time.
-*/
+ 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+. */
static void add_data_entry
PARAMS ((bfd *, struct internal_extra_pe_aouthdr *, int, char *, bfd_vma));
-static boolean pe_print_pdata PARAMS ((bfd *, PTR));
-static boolean pe_print_reloc PARAMS ((bfd *, PTR));
-static boolean pe_print_idata PARAMS ((bfd *, PTR));
-static boolean pe_print_edata PARAMS ((bfd *, PTR));
+static bfd_boolean pe_print_pdata PARAMS ((bfd *, PTR));
+static bfd_boolean pe_print_reloc PARAMS ((bfd *, PTR));
+static bfd_boolean pe_print_idata PARAMS ((bfd *, PTR));
+static bfd_boolean pe_print_edata PARAMS ((bfd *, PTR));
\f
void
struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr;
PEAOUTHDR *aouthdr_out = (PEAOUTHDR *) out;
bfd_vma sa, fa, ib;
+ IMAGE_DATA_DIRECTORY idata2, idata5;
+
if (pe->force_minimum_alignment)
{
if (!extra->FileAlignment)
fa = extra->FileAlignment;
ib = extra->ImageBase;
+ idata2 = pe->pe_opthdr.DataDirectory[1];
+ idata5 = pe->pe_opthdr.DataDirectory[12];
+
if (aouthdr_in->tsize)
{
aouthdr_in->text_start -= ib;
#define SA(x) (((x) + sa -1 ) & (- sa))
/* We like to have the sizes aligned. */
-
aouthdr_in->bsize = FA (aouthdr_in->bsize);
extra->NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
- /* first null out all data directory entries .. */
- memset (extra->DataDirectory, sizeof (extra->DataDirectory), 0);
+ /* First null out all data directory entries. */
+ memset (extra->DataDirectory, 0, sizeof (extra->DataDirectory));
add_data_entry (abfd, extra, 0, ".edata", ib);
-
- /* Don't call add_data_entry for .idata$2 or .idata$5. It's done in
- bfd_coff_final_link where all the required information is
- available. */
-
- /* However, until other .idata fixes are made (pending patch), the
- entry for .idata is needed for backwards compatability. FIXME. */
- add_data_entry (abfd, extra, 1, ".idata", ib);
-
add_data_entry (abfd, extra, 2, ".rsrc", ib);
-
add_data_entry (abfd, extra, 3, ".pdata", ib);
+ /* In theory we do not need to call add_data_entry for .idata$2 or
+ .idata$5. It will be done in bfd_coff_final_link where all the
+ required information is available. If however, we are not going
+ to perform a final link, eg because we have been invoked by objcopy
+ or strip, then we need to make sure that these Data Directory
+ entries are initialised properly.
+
+ 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;
+
+ if (extra->DataDirectory[1].VirtualAddress == 0)
+ /* Until other .idata fixes are made (pending patch), the entry for
+ .idata is needed for backwards compatability. FIXME. */
+ add_data_entry (abfd, extra, 1, ".idata", ib);
+
/* For some reason, the virtual size (which is what's set by
add_data_entry) for .reloc is not the same as the size recorded
in this slot by MSVC; it doesn't seem to cause problems (so far),
aouthdr_out->standard.text_start);
#ifndef COFF_WITH_pep
- /* PE32+ does not have data_start member! */
+ /* PE32+ does not have data_start member! */
PUT_AOUTHDR_DATA_START (abfd, aouthdr_in->data_start,
aouthdr_out->standard.data_start);
#endif
sometimes). */
if ((scnhdr_int->s_flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA) != 0)
{
- ps = scnhdr_int->s_size;
- ss = 0;
+ if (bfd_pe_executable_p (abfd))
+ {
+ ps = scnhdr_int->s_size;
+ ss = 0;
+ }
+ else
+ {
+ ps = 0;
+ ss = scnhdr_int->s_size;
+ }
}
else
{
- ps = scnhdr_int->s_paddr;
+ if (bfd_pe_executable_p (abfd))
+ ps = scnhdr_int->s_paddr;
+ else
+ ps = 0;
+
ss = scnhdr_int->s_size;
}
}
if (coff_data (abfd)->link_info
- && ! coff_data (abfd)->link_info->relocateable
+ && ! coff_data (abfd)->link_info->relocatable
&& ! coff_data (abfd)->link_info->shared
&& strcmp (scnhdr_int->s_name, ".text") == 0)
{
PPC- specific code. */
#endif
-static boolean
+static bfd_boolean
pe_print_idata (abfd, vfile)
bfd *abfd;
PTR vfile;
/* Maybe the extra header isn't there. Look for the section. */
section = bfd_get_section_by_name (abfd, ".idata");
if (section == NULL)
- return true;
+ return TRUE;
addr = section->vma;
datasize = bfd_section_size (abfd, section);
if (datasize == 0)
- return true;
+ return TRUE;
}
else
{
{
fprintf (file,
_("\nThere is an import table, but the section containing it could not be found\n"));
- return true;
+ return TRUE;
}
}
amt = bfd_section_size (abfd, rel_section);
data = (bfd_byte *) bfd_malloc (amt);
if (data == NULL && amt != 0)
- return false;
+ return FALSE;
bfd_get_section_contents (abfd, rel_section, (PTR) data, (bfd_vma) 0,
amt);
_("\nThe Import Tables (interpreted %s section contents)\n"),
section->name);
fprintf (file,
- _(" vma: Hint Time Forward DLL First\n"));
- fprintf (file,
- _(" Table Stamp Chain Name Thunk\n"));
+ _("\
+ vma: Hint Time Forward DLL First\n\
+ Table Stamp Chain Name Thunk\n"));
amt = dataoff + datasize;
data = (bfd_byte *) bfd_malloc (amt);
if (data == NULL)
- return false;
+ return FALSE;
/* Read the whole section. Some of the fields might be before dataoff. */
if (! bfd_get_section_contents (abfd, section, (PTR) data, (bfd_vma) 0, amt))
- return false;
+ return FALSE;
adj = section->vma - extra->ImageBase;
+ /* Print all image import descriptors. */
for (i = 0; i < datasize; i += onaline)
{
bfd_vma hint_addr;
bfd_size_type j;
char *dll;
- /* print (i + extra->DataDirectory[1].VirtualAddress) */
+ /* Print (i + extra->DataDirectory[1].VirtualAddress). */
fprintf (file, " %08lx\t", (unsigned long) (i + adj + dataoff));
#if 0
if (i + 20 > datasize)
if (hint_addr != 0)
{
- fprintf (file, _("\tvma: Hint/Ord Member-Name\n"));
+ bfd_byte *ft_data;
+ asection *ft_section;
+ bfd_vma ft_addr;
+ bfd_size_type ft_datasize;
+ int ft_idx;
+ int ft_allocated = 0;
+
+ fprintf (file, _("\tvma: Hint/Ord Member-Name Bound-To\n"));
idx = hint_addr - adj;
+
+ ft_addr = first_thunk + extra->ImageBase;
+ ft_data = data;
+ ft_idx = first_thunk - adj;
+ ft_allocated = 0;
+
+ if (first_thunk != hint_addr)
+ {
+ /* Find the section which contains the first thunk. */
+ for (ft_section = abfd->sections;
+ ft_section != NULL;
+ ft_section = ft_section->next)
+ {
+ ft_datasize = bfd_section_size (abfd, ft_section);
+ if (ft_addr >= ft_section->vma
+ && ft_addr < ft_section->vma + ft_datasize)
+ break;
+ }
+
+ if (ft_section == NULL)
+ {
+ fprintf (file,
+ _("\nThere is a first thunk, but the section containing it could not be found\n"));
+ continue;
+ }
+
+ /* Now check to see if this section is the same as our current
+ section. If it is not then we will have to load its data in. */
+ if (ft_section == section)
+ {
+ ft_data = data;
+ ft_idx = first_thunk - adj;
+ }
+ else
+ {
+ ft_idx = first_thunk - (ft_section->vma - extra->ImageBase);
+ ft_data = (bfd_byte *) bfd_malloc (datasize);
+ if (ft_data == NULL)
+ continue;
+
+ /* Read datasize bfd_bytes starting at offset ft_idx. */
+ if (! bfd_get_section_contents (abfd, ft_section,
+ (PTR) ft_data,
+ (bfd_vma) ft_idx,
+ datasize))
+ {
+ free (ft_data);
+ continue;
+ }
+
+ ft_idx = 0;
+ ft_allocated = 1;
+ }
+ }
+ /* Print HintName vector entries. */
for (j = 0; j < datasize; j += 4)
{
unsigned long member = bfd_get_32 (abfd, data + idx + j);
+ /* Print single IMAGE_IMPORT_BY_NAME vector. */
if (member == 0)
break;
+
if (member & 0x80000000)
- fprintf (file, "\t%04lx\t %4lu", member,
- member & 0x7fffffff);
+ fprintf (file, "\t%04lx\t %4lu <none>",
+ member, member & 0x7fffffff);
else
{
int ordinal;
}
/* If the time stamp is not zero, the import address
- table holds actual addresses. */
+ table holds actual addresses. */
if (time_stamp != 0
&& first_thunk != 0
&& first_thunk != hint_addr)
fprintf (file, "\t%04lx",
- (long) bfd_get_32 (abfd, data + first_thunk - adj + j));
+ (long) bfd_get_32 (abfd, ft_data + ft_idx + j));
fprintf (file, "\n");
}
- }
-
- if (hint_addr != first_thunk && time_stamp == 0)
- {
- int differ = 0;
- int idx2;
-
- idx2 = first_thunk - adj;
- for (j = 0; j < datasize; j += 4)
- {
- int ordinal;
- char *member_name;
- bfd_vma hint_member = 0;
- bfd_vma iat_member;
-
- if (hint_addr != 0)
- hint_member = bfd_get_32 (abfd, data + idx + j);
- iat_member = bfd_get_32 (abfd, data + idx2 + j);
-
- if (hint_addr == 0 && iat_member == 0)
- break;
-
- if (hint_addr == 0 || hint_member != iat_member)
- {
- if (differ == 0)
- {
- fprintf (file,
- _("\tThe Import Address Table (difference found)\n"));
- fprintf (file, _("\tvma: Hint/Ord Member-Name\n"));
- differ = 1;
- }
-
- if (iat_member == 0)
- fprintf (file,
- _("\t>>> Ran out of IAT members!\n"));
- else
- {
- ordinal = bfd_get_16 (abfd, data + iat_member - adj);
- member_name = (char *) data + iat_member - adj + 2;
- fprintf (file, "\t%04lx\t %4d %s\n",
- (unsigned long) iat_member,
- ordinal,
- member_name);
- }
- }
-
- if (hint_addr != 0 && hint_member == 0)
- break;
- }
-
- if (differ == 0)
- fprintf (file,
- _("\tThe Import Address Table is identical\n"));
+ if (ft_allocated)
+ free (ft_data);
}
fprintf (file, "\n");
free (data);
- return true;
+ return TRUE;
}
-static boolean
+static bfd_boolean
pe_print_edata (abfd, vfile)
bfd *abfd;
PTR vfile;
/* Maybe the extra header isn't there. Look for the section. */
section = bfd_get_section_by_name (abfd, ".edata");
if (section == NULL)
- return true;
+ return TRUE;
addr = section->vma;
datasize = bfd_section_size (abfd, section);
if (datasize == 0)
- return true;
+ return TRUE;
}
else
{
{
fprintf (file,
_("\nThere is an export table, but the section containing it could not be found\n"));
- return true;
+ return TRUE;
}
}
data = (bfd_byte *) bfd_malloc (datasize);
if (data == NULL)
- return false;
+ return FALSE;
if (! bfd_get_section_contents (abfd, section, (PTR) data,
(file_ptr) dataoff, datasize))
- return false;
+ return FALSE;
/* Go get Export Directory Table. */
edt.export_flags = bfd_get_32 (abfd, data + 0);
free (data);
- return true;
+ return TRUE;
}
/* This really is architecture dependent. On IA-64, a .pdata entry
specify the start and end address of the code range the entry
covers and the address of the corresponding unwind info data. */
-static boolean
+static bfd_boolean
pe_print_pdata (abfd, vfile)
bfd *abfd;
PTR vfile;
if (section == NULL
|| coff_section_data (abfd, section) == NULL
|| pei_section_data (abfd, section) == NULL)
- return true;
+ return TRUE;
stop = pei_section_data (abfd, section)->virt_size;
if ((stop % onaline) != 0)
fprintf (file,
_(" vma:\t\t\tBegin Address End Address Unwind Info\n"));
#else
- fprintf (file,
- _(" vma:\t\tBegin End EH EH PrologEnd Exception\n"));
- fprintf (file,
- _(" \t\tAddress Address Handler Data Address Mask\n"));
+ fprintf (file, _("\
+ vma:\t\tBegin End EH EH PrologEnd Exception\n\
+ \t\tAddress Address Handler Data Address Mask\n"));
#endif
datasize = bfd_section_size (abfd, section);
if (datasize == 0)
- return true;
+ return TRUE;
data = (bfd_byte *) bfd_malloc (datasize);
if (data == NULL && datasize != 0)
- return false;
+ return FALSE;
bfd_get_section_contents (abfd, section, (PTR) data, (bfd_vma) 0,
datasize);
free (data);
- return true;
+ return TRUE;
}
#define IMAGE_REL_BASED_HIGHADJ 4
"UNKNOWN", /* MUST be last */
};
-static boolean
+static bfd_boolean
pe_print_reloc (abfd, vfile)
bfd *abfd;
PTR vfile;
bfd_size_type start, stop;
if (section == NULL)
- return true;
+ return TRUE;
if (bfd_section_size (abfd, section) == 0)
- return true;
+ return TRUE;
fprintf (file,
_("\n\nPE File Base Relocations (interpreted .reloc section contents)\n"));
datasize = bfd_section_size (abfd, section);
data = (bfd_byte *) bfd_malloc (datasize);
if (data == NULL && datasize != 0)
- return false;
+ return FALSE;
bfd_get_section_contents (abfd, section, (PTR) data, (bfd_vma) 0,
datasize);
free (data);
- return true;
+ return TRUE;
}
/* Print out the program headers. */
-boolean
+bfd_boolean
_bfd_XX_print_private_bfd_data_common (abfd, vfile)
bfd *abfd;
PTR vfile;
pe_print_pdata (abfd, vfile);
pe_print_reloc (abfd, vfile);
- return true;
+ return TRUE;
}
/* Copy any private info we understand from the input bfd
to the output bfd. */
-boolean
+bfd_boolean
_bfd_XX_bfd_copy_private_bfd_data_common (ibfd, obfd)
bfd *ibfd, *obfd;
{
/* 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;
+ return TRUE;
pe_data (obfd)->pe_opthdr = pe_data (ibfd)->pe_opthdr;
pe_data (obfd)->dll = pe_data (ibfd)->dll;
pe_data (obfd)->pe_opthdr.DataDirectory[5].VirtualAddress = 0;
pe_data (obfd)->pe_opthdr.DataDirectory[5].Size = 0;
}
- return true;
+ return TRUE;
}
/* Copy private section data. */
-boolean
+bfd_boolean
_bfd_XX_bfd_copy_private_section_data (ibfd, isec, obfd, osec)
bfd *ibfd;
asection *isec;
{
if (bfd_get_flavour (ibfd) != bfd_target_coff_flavour
|| bfd_get_flavour (obfd) != bfd_target_coff_flavour)
- return true;
+ return TRUE;
if (coff_section_data (ibfd, isec) != NULL
&& pei_section_data (ibfd, isec) != NULL)
bfd_size_type amt = sizeof (struct coff_section_tdata);
osec->used_by_bfd = (PTR) bfd_zalloc (obfd, amt);
if (osec->used_by_bfd == NULL)
- return false;
+ return FALSE;
}
if (pei_section_data (obfd, osec) == NULL)
bfd_size_type amt = sizeof (struct pei_section_tdata);
coff_section_data (obfd, osec)->tdata = (PTR) bfd_zalloc (obfd, amt);
if (coff_section_data (obfd, osec)->tdata == NULL)
- return false;
+ return FALSE;
}
pei_section_data (obfd, osec)->virt_size =
pei_section_data (ibfd, isec)->pe_flags;
}
- return true;
+ return TRUE;
}
void
/* Handle the .idata section and other things that need symbol table
access. */
-boolean
+bfd_boolean
_bfd_XXi_final_link_postscript (abfd, pfinfo)
bfd *abfd;
struct coff_final_link_info *pfinfo;
/* The import directory. This is the address of .idata$2, with size
of .idata$2 + .idata$3. */
h1 = coff_link_hash_lookup (coff_hash_table (info),
- ".idata$2", false, false, true);
+ ".idata$2", FALSE, FALSE, TRUE);
if (h1 != NULL)
{
pe_data (abfd)->pe_opthdr.DataDirectory[1].VirtualAddress =
+ h1->root.u.def.section->output_section->vma
+ h1->root.u.def.section->output_offset);
h1 = coff_link_hash_lookup (coff_hash_table (info),
- ".idata$4", false, false, true);
+ ".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
/* 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);
+ ".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);
h1 = coff_link_hash_lookup (coff_hash_table (info),
- ".idata$6", false, false, true);
+ ".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);
+ - pe_data (abfd)->pe_opthdr.DataDirectory[12].VirtualAddress);
}
-
+
/* 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 TRUE;
}