Support interworking for thumb-pe and arm-pe targets.

This commit is contained in:
Nick Clifton
1998-03-25 23:48:55 +00:00
parent 98f1f62cb4
commit 38c574bbd3
4 changed files with 262 additions and 122 deletions

View File

@ -1,5 +1,5 @@
/* Support for the generic parts of most COFF variants, for BFD.
Copyright 1995, 1996, 1997 Free Software Foundation, Inc.
Copyright 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
Written by Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
@ -285,16 +285,12 @@ coff_swap_filehdr_in (abfd, src, dst)
filehdr_dst->f_flags = bfd_h_get_16(abfd, (bfd_byte *)filehdr_src-> f_flags);
filehdr_dst->f_symptr = bfd_h_get_32 (abfd, (bfd_byte *) filehdr_src->f_symptr);
/* Other people's tools sometimes generate headers
with an nsyms but a zero symptr. */
if (filehdr_dst->f_nsyms && filehdr_dst->f_symptr)
{
filehdr_dst->f_flags |= HAS_SYMS;
}
else
/* Other people's tools sometimes generate headers with an nsyms but
a zero symptr. */
if (filehdr_dst->f_nsyms != 0 && filehdr_dst->f_symptr == 0)
{
filehdr_dst->f_nsyms = 0;
filehdr_dst->f_flags &= ~HAS_SYMS;
filehdr_dst->f_flags |= F_LSYMS;
}
filehdr_dst->f_opthdr = bfd_h_get_16(abfd,
@ -778,38 +774,38 @@ coff_swap_aouthdr_in (abfd, aouthdr_ext1, aouthdr_int1)
GET_AOUTHDR_DATA_START (abfd, (bfd_byte *) aouthdr_ext->data_start);
a = &aouthdr_int->pe;
a->ImageBase = bfd_h_get_32 (abfd, src->ImageBase);
a->SectionAlignment = bfd_h_get_32 (abfd, src->SectionAlignment);
a->FileAlignment = bfd_h_get_32 (abfd, src->FileAlignment);
a->ImageBase = bfd_h_get_32 (abfd, (bfd_byte *) src->ImageBase);
a->SectionAlignment = bfd_h_get_32 (abfd, (bfd_byte *) src->SectionAlignment);
a->FileAlignment = bfd_h_get_32 (abfd, (bfd_byte *) src->FileAlignment);
a->MajorOperatingSystemVersion =
bfd_h_get_16 (abfd, src->MajorOperatingSystemVersion);
bfd_h_get_16 (abfd, (bfd_byte *) src->MajorOperatingSystemVersion);
a->MinorOperatingSystemVersion =
bfd_h_get_16 (abfd, src->MinorOperatingSystemVersion);
a->MajorImageVersion = bfd_h_get_16 (abfd, src->MajorImageVersion);
a->MinorImageVersion = bfd_h_get_16 (abfd, src->MinorImageVersion);
a->MajorSubsystemVersion = bfd_h_get_16 (abfd, src->MajorSubsystemVersion);
a->MinorSubsystemVersion = bfd_h_get_16 (abfd, src->MinorSubsystemVersion);
a->Reserved1 = bfd_h_get_32 (abfd, src->Reserved1);
a->SizeOfImage = bfd_h_get_32 (abfd, src->SizeOfImage);
a->SizeOfHeaders = bfd_h_get_32 (abfd, src->SizeOfHeaders);
a->CheckSum = bfd_h_get_32 (abfd, src->CheckSum);
a->Subsystem = bfd_h_get_16 (abfd, src->Subsystem);
a->DllCharacteristics = bfd_h_get_16 (abfd, src->DllCharacteristics);
a->SizeOfStackReserve = bfd_h_get_32 (abfd, src->SizeOfStackReserve);
a->SizeOfStackCommit = bfd_h_get_32 (abfd, src->SizeOfStackCommit);
a->SizeOfHeapReserve = bfd_h_get_32 (abfd, src->SizeOfHeapReserve);
a->SizeOfHeapCommit = bfd_h_get_32 (abfd, src->SizeOfHeapCommit);
a->LoaderFlags = bfd_h_get_32 (abfd, src->LoaderFlags);
a->NumberOfRvaAndSizes = bfd_h_get_32 (abfd, src->NumberOfRvaAndSizes);
bfd_h_get_16 (abfd, (bfd_byte *) src->MinorOperatingSystemVersion);
a->MajorImageVersion = bfd_h_get_16 (abfd, (bfd_byte *) src->MajorImageVersion);
a->MinorImageVersion = bfd_h_get_16 (abfd, (bfd_byte *) src->MinorImageVersion);
a->MajorSubsystemVersion = bfd_h_get_16 (abfd, (bfd_byte *) src->MajorSubsystemVersion);
a->MinorSubsystemVersion = bfd_h_get_16 (abfd, (bfd_byte *) src->MinorSubsystemVersion);
a->Reserved1 = bfd_h_get_32 (abfd, (bfd_byte *) src->Reserved1);
a->SizeOfImage = bfd_h_get_32 (abfd, (bfd_byte *) src->SizeOfImage);
a->SizeOfHeaders = bfd_h_get_32 (abfd, (bfd_byte *) src->SizeOfHeaders);
a->CheckSum = bfd_h_get_32 (abfd, (bfd_byte *) src->CheckSum);
a->Subsystem = bfd_h_get_16 (abfd, (bfd_byte *) src->Subsystem);
a->DllCharacteristics = bfd_h_get_16 (abfd, (bfd_byte *) src->DllCharacteristics);
a->SizeOfStackReserve = bfd_h_get_32 (abfd, (bfd_byte *) src->SizeOfStackReserve);
a->SizeOfStackCommit = bfd_h_get_32 (abfd, (bfd_byte *) src->SizeOfStackCommit);
a->SizeOfHeapReserve = bfd_h_get_32 (abfd, (bfd_byte *) src->SizeOfHeapReserve);
a->SizeOfHeapCommit = bfd_h_get_32 (abfd, (bfd_byte *) src->SizeOfHeapCommit);
a->LoaderFlags = bfd_h_get_32 (abfd, (bfd_byte *) src->LoaderFlags);
a->NumberOfRvaAndSizes = bfd_h_get_32 (abfd, (bfd_byte *) src->NumberOfRvaAndSizes);
{
int idx;
for (idx=0; idx < 16; idx++)
{
a->DataDirectory[idx].VirtualAddress =
bfd_h_get_32 (abfd, src->DataDirectory[idx][0]);
bfd_h_get_32 (abfd, (bfd_byte *) src->DataDirectory[idx][0]);
a->DataDirectory[idx].Size =
bfd_h_get_32 (abfd, src->DataDirectory[idx][1]);
bfd_h_get_32 (abfd, (bfd_byte *) src->DataDirectory[idx][1]);
}
}
@ -1138,13 +1134,13 @@ coff_swap_scnhdr_out (abfd, in, out)
int flags = scnhdr_int->s_flags;
if (strcmp (scnhdr_int->s_name, ".data") == 0 ||
strcmp (scnhdr_int->s_name, ".CRT") == 0 ||
strcmp (scnhdr_int->s_name, ".rsrc") == 0 ||
strcmp (scnhdr_int->s_name, ".bss") == 0)
flags |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
else if (strcmp (scnhdr_int->s_name, ".text") == 0)
flags |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE;
else if (strcmp (scnhdr_int->s_name, ".reloc") == 0)
flags = SEC_DATA| IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE;
flags = (SEC_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
| IMAGE_SCN_MEM_SHARED);
else if (strcmp (scnhdr_int->s_name, ".idata") == 0)
flags = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | SEC_DATA;
else if (strcmp (scnhdr_int->s_name, ".rdata") == 0
@ -1164,9 +1160,12 @@ coff_swap_scnhdr_out (abfd, in, out)
else if (strncmp (scnhdr_int->s_name, ".drectve", 8) == 0)
flags = IMAGE_SCN_LNK_INFO | IMAGE_SCN_LNK_REMOVE ;
else if (strncmp (scnhdr_int->s_name, ".stab", 5) == 0)
flags |= IMAGE_SCN_LNK_INFO | IMAGE_SCN_MEM_DISCARDABLE;
flags |= (IMAGE_SCN_LNK_INFO | IMAGE_SCN_MEM_DISCARDABLE
| IMAGE_SCN_MEM_SHARED | IMAGE_SCN_MEM_READ);
else if (strcmp (scnhdr_int->s_name, ".rsrc") == 0)
flags |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_SHARED;
else
flags = IMAGE_SCN_MEM_READ;
flags |= IMAGE_SCN_MEM_READ;
bfd_h_put_32(abfd, flags, (bfd_byte *) scnhdr_ext->s_flags);
}
@ -1225,12 +1224,15 @@ pe_print_idata(abfd, vfile)
FILE *file = (FILE *) vfile;
bfd_byte *data = 0;
asection *section = bfd_get_section_by_name (abfd, ".idata");
unsigned long adj;
#ifdef POWERPC_LE_PE
asection *rel_section = bfd_get_section_by_name (abfd, ".reldata");
#endif
bfd_size_type datasize = 0;
bfd_size_type datasize;
bfd_size_type dataoff;
bfd_size_type secsize;
bfd_size_type i;
bfd_size_type start, stop;
int onaline = 20;
@ -1238,8 +1240,41 @@ pe_print_idata(abfd, vfile)
pe_data_type *pe = pe_data (abfd);
struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr;
if (section == 0)
return true;
if (section != NULL)
{
datasize = bfd_section_size (abfd, section);
dataoff = 0;
if (datasize == 0)
return true;
}
else
{
bfd_vma addr, size;
addr = extra->DataDirectory[1].VirtualAddress;
size = extra->DataDirectory[1].Size;
if (addr == 0 || size == 0)
return true;
for (section = abfd->sections; section != NULL; section = section->next)
{
if (section->vma - extra->ImageBase <= addr
&& ((section->vma - extra->ImageBase
+ bfd_section_size (abfd, section))
>= addr + size))
break;
}
if (section == NULL)
return true;
/* For some reason the import table size is not reliable. The
import data will extend past the indicated size, and before
the indicated address. */
dataoff = addr - (section->vma - extra->ImageBase);
datasize = size;
}
#ifdef POWERPC_LE_PE
if (rel_section != 0 && bfd_section_size (abfd, rel_section) != 0)
@ -1291,27 +1326,22 @@ pe_print_idata(abfd, vfile)
fprintf(file,
"\nThe Import Tables (interpreted .idata section contents)\n");
fprintf(file,
" vma: Hint Time Forward DLL First\n");
" vma: Hint Time Forward DLL First\n");
fprintf(file,
" Table Stamp Chain Name Thunk\n");
" Table Stamp Chain Name Thunk\n");
if (bfd_section_size (abfd, section) == 0)
return true;
data = (bfd_byte *) bfd_malloc ((size_t) bfd_section_size (abfd, section));
datasize = bfd_section_size (abfd, section);
if (data == NULL && datasize != 0)
secsize = bfd_section_size (abfd, section);
data = (bfd_byte *) bfd_malloc (secsize);
if (data == NULL && secsize != 0)
return false;
bfd_get_section_contents (abfd,
section,
(PTR) data, 0,
bfd_section_size (abfd, section));
if (! bfd_get_section_contents (abfd, section, (PTR) data, 0, secsize))
return false;
start = 0;
stop = bfd_section_size (abfd, section);
adj = (extra->ImageBase - section->vma) & 0xffffffff;
start = dataoff;
stop = dataoff + datasize;
for (i = start; i < stop; i += onaline)
{
bfd_vma hint_addr;
@ -1322,11 +1352,10 @@ pe_print_idata(abfd, vfile)
int idx;
int j;
char *dll;
int adj = (extra->ImageBase - section->vma) & 0xffffffff;
fprintf (file,
" %04lx\t",
(unsigned long int) (i + section->vma));
" %08lx\t",
(unsigned long int) (i + section->vma + dataoff));
if (i+20 > stop)
{
@ -1347,33 +1376,52 @@ pe_print_idata(abfd, vfile)
dll_name,
first_thunk);
if (hint_addr ==0)
{
break;
}
if (hint_addr == 0 && first_thunk == 0)
break;
/* the image base is present in the section->vma */
dll = (char *) data + dll_name + adj;
fprintf(file, "\n\tDLL Name: %s\n", dll);
fprintf(file, "\tvma: Ordinal Member-Name\n");
idx = hint_addr + adj;
for (j=0;j<stop;j+=4)
if (hint_addr != 0)
{
int ordinal;
char *member_name;
bfd_vma member = bfd_get_32(abfd, data + idx + j);
if (member == 0)
break;
ordinal = bfd_get_16(abfd,
data + member + adj);
member_name = (char *) data + member + adj + 2;
fprintf(file, "\t%04lx\t %4d %s\n",
member, ordinal, member_name);
fprintf (file, "\tvma: Hint/Ord Member-Name\n");
idx = hint_addr + adj;
for (j = 0; j < stop; j += 4)
{
unsigned long member = bfd_get_32 (abfd, data + idx + j);
if (member == 0)
break;
if (member & 0x80000000)
fprintf (file, "\t%04lx\t %4lu", member,
member & 0x7fffffff);
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",
bfd_get_32 (abfd, data + first_thunk + adj + j));
fprintf (file, "\n");
}
}
if (hint_addr != first_thunk)
if (hint_addr != first_thunk && time_stamp == 0)
{
int differ = 0;
int idx2;
@ -1384,15 +1432,27 @@ pe_print_idata(abfd, vfile)
{
int ordinal;
char *member_name;
bfd_vma hint_member = bfd_get_32(abfd, data + idx + j);
bfd_vma iat_member = bfd_get_32(abfd, data + idx2 + j);
if (hint_member != iat_member)
bfd_vma hint_member;
bfd_vma iat_member;
if (time_stamp != 0)
{
}
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: Ordinal Member-Name\n");
fprintf (file,
"\tThe Import Address Table (difference found)\n");
fprintf(file, "\tvma: Hint/Ord Member-Name\n");
differ = 1;
}
if (iat_member == 0)
@ -1408,9 +1468,9 @@ pe_print_idata(abfd, vfile)
fprintf(file, "\t%04lx\t %4d %s\n",
iat_member, ordinal, member_name);
}
break;
}
if (hint_member == 0)
if (hint_addr != 0 && hint_member == 0)
break;
}
if (differ == 0)
@ -1438,7 +1498,8 @@ pe_print_edata (abfd, vfile)
bfd_byte *data = 0;
asection *section = bfd_get_section_by_name (abfd, ".edata");
bfd_size_type datasize = 0;
bfd_size_type datasize;
bfd_size_type dataoff;
bfd_size_type i;
int adj;
@ -1460,20 +1521,43 @@ pe_print_edata (abfd, vfile)
pe_data_type *pe = pe_data (abfd);
struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr;
if (section == 0)
return true;
if (section != NULL)
{
datasize = bfd_section_size (abfd, section);
dataoff = 0;
}
else
{
bfd_vma addr, size;
data = (bfd_byte *) bfd_malloc ((size_t) bfd_section_size (abfd,
section));
datasize = bfd_section_size (abfd, section);
addr = extra->DataDirectory[0].VirtualAddress;
size = extra->DataDirectory[0].Size;
if (addr == 0 || size == 0)
return true;
for (section = abfd->sections; section != NULL; section = section->next)
{
if (section->vma - extra->ImageBase <= addr
&& ((section->vma - extra->ImageBase
+ bfd_section_size (abfd, section))
>= addr + size))
break;
}
if (section == NULL)
return true;
datasize = size;
dataoff = addr - (section->vma - extra->ImageBase);
}
data = (bfd_byte *) bfd_malloc (datasize);
if (data == NULL && datasize != 0)
return false;
bfd_get_section_contents (abfd,
section,
(PTR) data, 0,
bfd_section_size (abfd, section));
if (! bfd_get_section_contents (abfd, section, (PTR) data, dataoff,
datasize))
return false;
/* Go get Export Directory Table */
edt.export_flags = bfd_get_32(abfd, data+0);
@ -1488,7 +1572,7 @@ pe_print_edata (abfd, vfile)
edt.npt_addr = bfd_get_32(abfd, data+32);
edt.ot_addr = bfd_get_32(abfd, data+36);
adj = (extra->ImageBase - section->vma) & 0xffffffff;
adj = (extra->ImageBase - (section->vma + dataoff)) & 0xffffffff;
/* Dump the EDT first first */
@ -1558,12 +1642,11 @@ pe_print_edata (abfd, vfile)
for (i = 0; i < edt.num_functions; ++i)
{
bfd_vma eat_member = bfd_get_32(abfd,
data + edt.eat_addr + (i*4) + adj);
bfd_vma eat_member = bfd_get_32 (abfd,
data + edt.eat_addr + (i * 4) + adj);
bfd_vma eat_actual = (extra->ImageBase + eat_member) & 0xffffffff;
bfd_vma edata_start = bfd_get_section_vma(abfd,section);
bfd_vma edata_end = edata_start + bfd_section_size (abfd, section);
bfd_vma edata_start = bfd_get_section_vma (abfd,section) + dataoff;
bfd_vma edata_end = edata_start + datasize;
if (eat_member == 0)
continue;
@ -1827,6 +1910,24 @@ pe_print_private_bfd_data (abfd, vfile)
pe_data_type *pe = pe_data (abfd);
struct internal_extra_pe_aouthdr *i = &pe->pe_opthdr;
/* The MS dumpbin program reportedly ands with 0xff0f before
printing the characteristics field. Not sure why. No reason to
emulate it here. */
fprintf (file, "\nCharacteristics 0x%x\n", pe->real_flags);
#undef PF
#define PF(x, y) if (pe->real_flags & x) { fprintf (file, "\t%s\n", y); }
PF (F_RELFLG, "relocations stripped");
PF (F_EXEC, "executable");
PF (F_LNNO, "line numbers stripped");
PF (F_LSYMS, "symbols stripped");
PF (0x80, "little endian");
PF (F_AR32WR, "32 bit words");
PF (0x200, "debugging information removed");
PF (0x1000, "system file");
PF (F_DLL, "DLL");
PF (0x8000, "big endian");
#undef PF
fprintf (file,"\nImageBase\t\t");
fprintf_vma (file, i->ImageBase);
fprintf (file,"\nSectionAlignment\t");
@ -1870,7 +1971,8 @@ pe_print_private_bfd_data (abfd, vfile)
pe_print_pdata(abfd, vfile);
pe_print_reloc(abfd, vfile);
return true;
fputc ('\n', file);
return coff_arm_bfd_print_private_bfd_data (abfd, vfile);
}
static boolean
@ -1933,6 +2035,9 @@ pe_mkobject_hook (abfd, filehdr, aouthdr)
}
#endif
if (! coff_arm_bfd_set_private_flags (abfd, internal_f->f_flags))
coff_data (abfd) ->flags = 0;
return (PTR) pe;
}
@ -1956,7 +2061,7 @@ pe_bfd_copy_private_bfd_data (ibfd, obfd)
pe_data (obfd)->pe_opthdr = pe_data (ibfd)->pe_opthdr;
pe_data (obfd)->dll = pe_data (ibfd)->dll;
return true;
return coff_arm_bfd_copy_private_bfd_data (ibfd, obfd);
}
#ifdef COFF_IMAGE_WITH_PE