1999-09-11 Donn Terry <donn@interix.com>

* peigen.c (add_data_entry): Declare.
	(pei_swap_aouthdr_out): Get image size right.  Set linker version
	more intuitively.
	(pei_swap_scnhdr_out): Test for UNINIT section, not .bss.
	(pe_print_idata): Code cleanup, print more info, get rid of (now)
	extraneous ImageBase.
	(pe_print_edata): Likewise.
	(pe_print_pdata): Likewise.  Print exception entries.
	(pe_print_reloc): Likewise.  Print MIPS_JMPADDR.
	(tbl): Make const, add "UNKNOWN".
	(_bfd_pe_print_private_bfd_data_common): Print timestamp.
	(_bfd_pe_bfd_copy_private_bfd_data_common): Don't copy deleted
	section data directory.
	(_bfd_pe_bfd_copy_private_section_data): Copy pe_flags.
This commit is contained in:
Ian Lance Taylor 1999-09-12 00:22:01 +00:00
parent 7d2b58d612
commit 5933bdc9a1
2 changed files with 164 additions and 95 deletions

View File

@ -7,6 +7,21 @@
1999-09-11 Donn Terry <donn@interix.com> 1999-09-11 Donn Terry <donn@interix.com>
* peigen.c (add_data_entry): Declare.
(pei_swap_aouthdr_out): Get image size right. Set linker version
more intuitively.
(pei_swap_scnhdr_out): Test for UNINIT section, not .bss.
(pe_print_idata): Code cleanup, print more info, get rid of (now)
extraneous ImageBase.
(pe_print_edata): Likewise.
(pe_print_pdata): Likewise. Print exception entries.
(pe_print_reloc): Likewise. Print MIPS_JMPADDR.
(tbl): Make const, add "UNKNOWN".
(_bfd_pe_print_private_bfd_data_common): Print timestamp.
(_bfd_pe_bfd_copy_private_bfd_data_common): Don't copy deleted
section data directory.
(_bfd_pe_bfd_copy_private_section_data): Copy pe_flags.
* libpei.h (_bfd_pe_bfd_get_symbol_info): Declare. * libpei.h (_bfd_pe_bfd_get_symbol_info): Declare.
* peigen.c (_bfd_pe_bfd_get_symbol_info): New function. * peigen.c (_bfd_pe_bfd_get_symbol_info): New function.
* peicode.h (coff_get_symbol_info): Define. * peicode.h (coff_get_symbol_info): Define.

View File

@ -78,7 +78,10 @@ PE/PEI rearrangement (and code added): Donn Terry
anybody wants to revive the code, you will have to figure out how anybody wants to revive the code, you will have to figure out how
to handle those issues. */ to handle those issues. */
boolean in_reloc_p PARAMS((bfd *, reloc_howto_type *)); 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));
/**********************************************************************/ /**********************************************************************/
@ -497,7 +500,10 @@ _bfd_pei_swap_aouthdr_in (abfd, aouthdr_ext1, aouthdr_int1)
} }
static void add_data_entry (abfd, aout, idx, name, base) /* A support function for below. */
static void
add_data_entry (abfd, aout, idx, name, base)
bfd *abfd; bfd *abfd;
struct internal_extra_pe_aouthdr *aout; struct internal_extra_pe_aouthdr *aout;
int idx; int idx;
@ -600,7 +606,12 @@ _bfd_pei_swap_aouthdr_out (abfd, in, out)
dsize += rounded; dsize += rounded;
if (sec->flags & SEC_CODE) if (sec->flags & SEC_CODE)
tsize += rounded; tsize += rounded;
isize += SA(rounded); /* The image size is the total VIRTUAL size (which is what is
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. */
isize += SA (FA (pei_section_data (abfd, sec)->virt_size));
} }
aouthdr_in->dsize = dsize; aouthdr_in->dsize = dsize;
@ -611,13 +622,13 @@ _bfd_pei_swap_aouthdr_out (abfd, in, out)
extra->SizeOfHeaders = abfd->sections->filepos; extra->SizeOfHeaders = abfd->sections->filepos;
bfd_h_put_16(abfd, aouthdr_in->magic, (bfd_byte *) aouthdr_out->standard.magic); bfd_h_put_16(abfd, aouthdr_in->magic, (bfd_byte *) aouthdr_out->standard.magic);
#ifdef POWERPC_LE_PE #define LINKER_VERSION 256 /* That is, 2.56 */
/* this little piece of magic sets the "linker version" field to 2.60 */
bfd_h_put_16(abfd, 2 + 60 * 256, (bfd_byte *) aouthdr_out->standard.vstamp); /* This piece of magic sets the "linker version" field to
#else LINKER_VERSION. */
/* this little piece of magic sets the "linker version" field to 2.55 */ bfd_h_put_16 (abfd,
bfd_h_put_16(abfd, 2 + 55 * 256, (bfd_byte *) aouthdr_out->standard.vstamp); LINKER_VERSION / 100 + (LINKER_VERSION % 100) * 256,
#endif (bfd_byte *) aouthdr_out->standard.vstamp);
PUT_AOUTHDR_TSIZE (abfd, aouthdr_in->tsize, (bfd_byte *) aouthdr_out->standard.tsize); PUT_AOUTHDR_TSIZE (abfd, aouthdr_in->tsize, (bfd_byte *) aouthdr_out->standard.tsize);
PUT_AOUTHDR_DSIZE (abfd, aouthdr_in->dsize, (bfd_byte *) aouthdr_out->standard.dsize); PUT_AOUTHDR_DSIZE (abfd, aouthdr_in->dsize, (bfd_byte *) aouthdr_out->standard.dsize);
@ -855,11 +866,11 @@ _bfd_pei_swap_scnhdr_out (abfd, in, out)
& 0xffffffff), & 0xffffffff),
(bfd_byte *) scnhdr_ext->s_vaddr); (bfd_byte *) scnhdr_ext->s_vaddr);
/* NT wants the size data to be rounded up to the next NT_FILE_ALIGNMENT /* NT wants the size data to be rounded up to the next
value except for the BSS section, its s_size should be 0 */ NT_FILE_ALIGNMENT, but zero if it has no content (as in .bss,
sometimes). */
if ((scnhdr_int->s_flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA) != 0)
if (strcmp (scnhdr_int->s_name, _BSS) == 0)
{ {
ps = scnhdr_int->s_size; ps = scnhdr_int->s_size;
ss = 0; ss = 0;
@ -874,6 +885,7 @@ _bfd_pei_swap_scnhdr_out (abfd, in, out)
(bfd_byte *) scnhdr_ext->s_size); (bfd_byte *) scnhdr_ext->s_size);
/* s_paddr in PE is really the virtual size. */
PUT_SCNHDR_PADDR (abfd, ps, (bfd_byte *) scnhdr_ext->s_paddr); PUT_SCNHDR_PADDR (abfd, ps, (bfd_byte *) scnhdr_ext->s_paddr);
PUT_SCNHDR_SCNPTR (abfd, scnhdr_int->s_scnptr, PUT_SCNHDR_SCNPTR (abfd, scnhdr_int->s_scnptr,
@ -1002,7 +1014,7 @@ static char * dir_names[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] =
/**********************************************************************/ /**********************************************************************/
static boolean static boolean
pe_print_idata(abfd, vfile) pe_print_idata (abfd, vfile)
bfd *abfd; bfd *abfd;
PTR vfile; PTR vfile;
{ {
@ -1019,7 +1031,6 @@ pe_print_idata(abfd, vfile)
bfd_size_type dataoff; bfd_size_type dataoff;
bfd_size_type secsize; bfd_size_type secsize;
bfd_size_type i; bfd_size_type i;
bfd_size_type start, stop;
int onaline = 20; int onaline = 20;
pe_data_type *pe = pe_data (abfd); pe_data_type *pe = pe_data (abfd);
@ -1032,9 +1043,12 @@ pe_print_idata(abfd, vfile)
if (datasize == 0) if (datasize == 0)
return true; return true;
fprintf (file, _("\nThe import table is the .idata section\n"));
} }
else else
{ {
/* idata buried in some other section: e.g. KERNEL32.DLL. */
bfd_vma addr, size; bfd_vma addr, size;
addr = extra->DataDirectory[1].VirtualAddress; addr = extra->DataDirectory[1].VirtualAddress;
@ -1045,19 +1059,21 @@ pe_print_idata(abfd, vfile)
for (section = abfd->sections; section != NULL; section = section->next) for (section = abfd->sections; section != NULL; section = section->next)
{ {
if (section->vma - extra->ImageBase <= addr if (addr >= section->vma
&& ((section->vma - extra->ImageBase && addr < section->vma + bfd_section_size(abfd,section))
+ bfd_section_size (abfd, section)) break;
>= addr + size))
break;
} }
if (section == NULL) if (section == NULL)
return true; {
fprintf (file,
_("\nThere is an import table, but the section containing it could not be found\n"));
return true;
}
/* For some reason the import table size is not reliable. The fprintf (file, _("\nThere is an import table in %s at 0x%lx\n"),
import data will extend past the indicated size, and before section->name, (unsigned long)addr);
the indicated address. */
dataoff = addr - (section->vma - extra->ImageBase); dataoff = addr - section->vma;
datasize = size; datasize = size;
} }
@ -1123,11 +1139,9 @@ pe_print_idata(abfd, vfile)
if (! bfd_get_section_contents (abfd, section, (PTR) data, 0, secsize)) if (! bfd_get_section_contents (abfd, section, (PTR) data, 0, secsize))
return false; return false;
adj = (extra->ImageBase - section->vma) & 0xffffffff; adj = - section->vma;
start = dataoff; for (i = 0; i < datasize; i += onaline)
stop = dataoff + datasize;
for (i = start; i < stop; i += onaline)
{ {
bfd_vma hint_addr; bfd_vma hint_addr;
bfd_vma time_stamp; bfd_vma time_stamp;
@ -1142,30 +1156,29 @@ pe_print_idata(abfd, vfile)
" %08lx\t", " %08lx\t",
(unsigned long int) (i + section->vma + dataoff)); (unsigned long int) (i + section->vma + dataoff));
if (i+20 > stop) if (i + 20 > datasize)
{ {
/* check stuff */ /* check stuff */
; ;
} }
hint_addr = bfd_get_32(abfd, data+i); hint_addr = bfd_get_32 (abfd, data + i + dataoff);
time_stamp = bfd_get_32(abfd, data+i+4); time_stamp = bfd_get_32 (abfd, data + i + 4 + dataoff);
forward_chain = bfd_get_32(abfd, data+i+8); forward_chain = bfd_get_32 (abfd, data + i + 8 + dataoff);
dll_name = bfd_get_32(abfd, data+i+12); dll_name = bfd_get_32 (abfd, data + i + 12 + dataoff);
first_thunk = bfd_get_32(abfd, data+i+16); first_thunk = bfd_get_32 (abfd, data + i + 16 + dataoff);
fprintf(file, "%08lx %08lx %08lx %08lx %08lx\n", fprintf (file, "%08lx %08lx %08lx %08lx %08lx\n",
hint_addr, hint_addr,
time_stamp, time_stamp,
forward_chain, forward_chain,
dll_name, dll_name,
first_thunk); first_thunk);
if (hint_addr == 0 && first_thunk == 0) if (hint_addr == 0 && first_thunk == 0)
break; break;
/* the image base is present in the section->vma */ dll = (char *) data + dll_name - section->vma + dataoff;
dll = (char *) data + dll_name + adj;
fprintf(file, _("\n\tDLL Name: %s\n"), dll); fprintf(file, _("\n\tDLL Name: %s\n"), dll);
if (hint_addr != 0) if (hint_addr != 0)
@ -1174,7 +1187,7 @@ pe_print_idata(abfd, vfile)
idx = hint_addr + adj; idx = hint_addr + adj;
for (j = 0; j < stop; j += 4) for (j = 0; j < datasize; j += 4)
{ {
unsigned long member = bfd_get_32 (abfd, data + idx + j); unsigned long member = bfd_get_32 (abfd, data + idx + j);
@ -1213,7 +1226,7 @@ pe_print_idata(abfd, vfile)
idx2 = first_thunk + adj; idx2 = first_thunk + adj;
for (j=0;j<stop;j+=4) for (j = 0; j < datasize; j += 4)
{ {
int ordinal; int ordinal;
char *member_name; char *member_name;
@ -1306,9 +1319,11 @@ pe_print_edata (abfd, vfile)
{ {
datasize = bfd_section_size (abfd, section); datasize = bfd_section_size (abfd, section);
dataoff = 0; dataoff = 0;
fprintf (file, _("\nThe export table is the .edata section\n"));
} }
else else
{ {
/* edata is buried in some other section: e.g. NTDLL.DLL. */
bfd_vma addr, size; bfd_vma addr, size;
addr = extra->DataDirectory[0].VirtualAddress; addr = extra->DataDirectory[0].VirtualAddress;
@ -1319,17 +1334,22 @@ pe_print_edata (abfd, vfile)
for (section = abfd->sections; section != NULL; section = section->next) for (section = abfd->sections; section != NULL; section = section->next)
{ {
if (section->vma - extra->ImageBase <= addr if (addr >= section->vma
&& ((section->vma - extra->ImageBase && addr < section->vma + bfd_section_size (abfd, section))
+ bfd_section_size (abfd, section)) break;
>= addr + size))
break;
} }
if (section == NULL) if (section == NULL)
return true; {
fprintf (file,
_("\nThere is an export table, but the section containing it could not be found\n"));
return true;
}
fprintf (file, _("\nThere is an export table in %s at 0x%lx\n"),
section->name, (unsigned long) addr);
datasize = size; datasize = size;
dataoff = addr - (section->vma - extra->ImageBase); dataoff = addr - section->vma;
} }
data = (bfd_byte *) bfd_malloc (datasize); data = (bfd_byte *) bfd_malloc (datasize);
@ -1353,7 +1373,7 @@ pe_print_edata (abfd, vfile)
edt.npt_addr = bfd_get_32(abfd, data+32); edt.npt_addr = bfd_get_32(abfd, data+32);
edt.ot_addr = bfd_get_32(abfd, data+36); edt.ot_addr = bfd_get_32(abfd, data+36);
adj = (extra->ImageBase - (section->vma + dataoff)) & 0xffffffff; adj = - (section->vma + dataoff);
/* Dump the EDT first first */ /* Dump the EDT first first */
fprintf(file, fprintf(file,
@ -1406,7 +1426,7 @@ pe_print_edata (abfd, vfile)
fprintf (file, "\n"); fprintf (file, "\n");
/* The next table to find si the Export Address Table. It's basically /* The next table to find is the Export Address Table. It's basically
a list of pointers that either locate a function in this dll, or a list of pointers that either locate a function in this dll, or
forward the call to another dll. Something like: forward the call to another dll. Something like:
typedef union typedef union
@ -1424,8 +1444,8 @@ pe_print_edata (abfd, vfile)
{ {
bfd_vma eat_member = bfd_get_32 (abfd, bfd_vma eat_member = bfd_get_32 (abfd,
data + edt.eat_addr + (i * 4) + adj); data + edt.eat_addr + (i * 4) + adj);
bfd_vma eat_actual = (extra->ImageBase + eat_member) & 0xffffffff; bfd_vma eat_actual = eat_member;
bfd_vma edata_start = bfd_get_section_vma (abfd,section) + dataoff; bfd_vma edata_start = bfd_get_section_vma (abfd, section);
bfd_vma edata_end = edata_start + datasize; bfd_vma edata_end = edata_start + datasize;
if (eat_member == 0) if (eat_member == 0)
@ -1435,17 +1455,18 @@ pe_print_edata (abfd, vfile)
{ {
/* this rva is to a name (forwarding function) in our section */ /* this rva is to a name (forwarding function) in our section */
/* Should locate a function descriptor */ /* Should locate a function descriptor */
fprintf(file, fprintf (file,
"\t[%4ld] +base[%4ld] %04lx %s -- %s\n", "\t[%4ld] +base[%4ld] %04lx %s -- %s\n",
(long) i, (long) (i + edt.base), eat_member, (long) i, (long) (i + edt.base), eat_member,
"Forwarder RVA", data + eat_member + adj); _("Forwarder RVA"), data + eat_member + adj);
} }
else else
{ {
/* Should locate a function descriptor in the reldata section */ /* Should locate a function descriptor in the reldata section */
fprintf(file, fprintf (file,
"\t[%4ld] +base[%4ld] %04lx %s\n", "\t[%4ld] +base[%4ld] %04lx %s\n",
(long) i, (long) (i + edt.base), eat_member, "Export RVA"); (long) i, (long) (i + edt.base), eat_member,
_("Export RVA"));
} }
} }
@ -1490,20 +1511,22 @@ pe_print_pdata (abfd, vfile)
bfd_size_type start, stop; bfd_size_type start, stop;
int onaline = 20; int onaline = 20;
if (section == 0) if (section == NULL
return true; || coff_section_data (abfd, section) == NULL
|| pei_section_data (abfd, section) == NULL)
return true;
stop = bfd_section_size (abfd, section); stop = pei_section_data (abfd, section)->virt_size;
if ((stop % onaline) != 0) if ((stop % onaline) != 0)
fprintf (file, _("Warning, .pdata section size (%ld) is not a multiple of %d\n"), fprintf (file, _("Warning, .pdata section size (%ld) is not a multiple of %d\n"),
(long)stop, onaline); (long)stop, onaline);
fprintf(file, fprintf (file,
_("\nThe Function Table (interpreted .pdata section contents)\n")); _("\nThe Function Table (interpreted .pdata section contents)\n"));
fprintf(file, fprintf (file,
_(" vma:\t\tBegin End EH EH PrologEnd\n")); _(" vma:\t\tBegin End EH EH PrologEnd Exception\n"));
fprintf(file, fprintf (file,
_(" \t\tAddress Address Handler Data Address\n")); _(" \t\tAddress Address Handler Data Address Mask\n"));
if (bfd_section_size (abfd, section) == 0) if (bfd_section_size (abfd, section) == 0)
return true; return true;
@ -1527,10 +1550,11 @@ pe_print_pdata (abfd, vfile)
bfd_vma eh_handler; bfd_vma eh_handler;
bfd_vma eh_data; bfd_vma eh_data;
bfd_vma prolog_end_addr; bfd_vma prolog_end_addr;
int em_data;
if (i+20 > stop) if (i + 20 > stop)
break; break;
begin_addr = bfd_get_32(abfd, data+i); begin_addr = bfd_get_32(abfd, data+i);
end_addr = bfd_get_32(abfd, data+i+4); end_addr = bfd_get_32(abfd, data+i+4);
eh_handler = bfd_get_32(abfd, data+i+8); eh_handler = bfd_get_32(abfd, data+i+8);
@ -1548,12 +1572,17 @@ pe_print_pdata (abfd, vfile)
" %08lx\t", " %08lx\t",
(unsigned long int) (i + section->vma)); (unsigned long int) (i + section->vma));
fprintf(file, "%08lx %08lx %08lx %08lx %08lx", em_data = ((eh_handler & 0x1) << 2) | (prolog_end_addr & 0x3);
begin_addr, eh_handler &= 0xfffffffc;
end_addr, prolog_end_addr &= 0xfffffffc;
eh_handler,
eh_data, fprintf (file, "%08lx %08lx %08lx %08lx %08lx %x",
prolog_end_addr); begin_addr,
end_addr,
eh_handler,
eh_data,
prolog_end_addr,
em_data);
#ifdef POWERPC_LE_PE #ifdef POWERPC_LE_PE
if (eh_handler == 0 && eh_data != 0) if (eh_handler == 0 && eh_data != 0)
@ -1590,14 +1619,16 @@ pe_print_pdata (abfd, vfile)
return true; return true;
} }
static const char *tbl[6] = #define IMAGE_REL_BASED_HIGHADJ 4
static const char * const tbl[] =
{ {
"ABSOLUTE", "ABSOLUTE",
"HIGH", "HIGH",
"LOW", "LOW",
"HIGHLOW", "HIGHLOW",
"HIGHADJ", "HIGHADJ",
"MIPS_JMPADDR" "MIPS_JMPADDR",
"UNKNOWN", /* MUST be last */
}; };
static boolean static boolean
@ -1612,14 +1643,14 @@ pe_print_reloc (abfd, vfile)
bfd_size_type i; bfd_size_type i;
bfd_size_type start, stop; bfd_size_type start, stop;
if (section == 0) if (section == NULL)
return true; return true;
if (bfd_section_size (abfd, section) == 0) if (bfd_section_size (abfd, section) == 0)
return true; return true;
fprintf(file, fprintf (file,
_("\n\nPE File Base Relocations (interpreted .reloc section contents)\n")); _("\n\nPE File Base Relocations (interpreted .reloc section contents)\n"));
data = (bfd_byte *) bfd_malloc ((size_t) bfd_section_size (abfd, section)); data = (bfd_byte *) bfd_malloc ((size_t) bfd_section_size (abfd, section));
datasize = bfd_section_size (abfd, section); datasize = bfd_section_size (abfd, section);
@ -1659,17 +1690,29 @@ pe_print_reloc (abfd, vfile)
for (j = 0; j < number; ++j) for (j = 0; j < number; ++j)
{ {
unsigned short e = bfd_get_16(abfd, data + i + 8 + j*2); unsigned short e = bfd_get_16 (abfd, data + i + 8 + j * 2);
int t = (e & 0xF000) >> 12; unsigned int t = (e & 0xF000) >> 12;
int off = e & 0x0FFF; int off = e & 0x0FFF;
if (t > 5) if (t >= sizeof (tbl) / sizeof (tbl[0]))
abort(); t = (sizeof (tbl) / sizeof (tbl[0])) - 1;
fprintf(file, fprintf (file,
_("\treloc %4d offset %4x [%4lx] %s\n"), _("\treloc %4d offset %4x [%4lx] %s"),
j, off, (long) (off + virtual_address), tbl[t]); j, off, (long) (off + virtual_address), tbl[t]);
/* HIGHADJ takes an argument, but there's no documentation
on what it does, or what it means. Inferred from
DUMPBIN. */
if (t == IMAGE_REL_BASED_HIGHADJ)
{
fprintf (file, " (%4x)\n",
((unsigned int)
bfd_get_16 (abfd, data + i + 8 + j * 2 + 2)));
j++;
}
else
fprintf (file, "\n");
} }
i += size; i += size;
} }
@ -1709,6 +1752,8 @@ _bfd_pe_print_private_bfd_data_common (abfd, vfile)
PF (0x8000, "big endian"); PF (0x8000, "big endian");
#undef PF #undef PF
/* ctime implies '\n'. */
fprintf (file, "\nTime/Date\t\t%s", ctime (&pe->coff.timestamp));
fprintf (file,"\nImageBase\t\t"); fprintf (file,"\nImageBase\t\t");
fprintf_vma (file, i->ImageBase); fprintf_vma (file, i->ImageBase);
fprintf (file,"\nSectionAlignment\t"); fprintf (file,"\nSectionAlignment\t");
@ -1770,6 +1815,13 @@ _bfd_pe_bfd_copy_private_bfd_data_common (ibfd, obfd)
pe_data (obfd)->pe_opthdr = pe_data (ibfd)->pe_opthdr; pe_data (obfd)->pe_opthdr = pe_data (ibfd)->pe_opthdr;
pe_data (obfd)->dll = pe_data (ibfd)->dll; pe_data (obfd)->dll = pe_data (ibfd)->dll;
/* 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;
}
return true; return true;
} }
@ -1804,6 +1856,8 @@ _bfd_pe_bfd_copy_private_section_data (ibfd, isec, obfd, osec)
} }
pei_section_data (obfd, osec)->virt_size = pei_section_data (obfd, osec)->virt_size =
pei_section_data (ibfd, isec)->virt_size; pei_section_data (ibfd, isec)->virt_size;
pei_section_data (obfd, osec)->pe_flags =
pei_section_data (ibfd, isec)->pe_flags;
} }
return true; return true;