PowerPC DLL Support

This commit is contained in:
Kim Knuttila 1995-12-01 01:01:42 +00:00
parent cee52482d3
commit 590662481c
3 changed files with 159 additions and 57 deletions

View File

@ -1,3 +1,17 @@
Thu Nov 30 19:32:26 1995 Kim Knuttila <krk@cygnus.com>
* coff-ppc.c: Added macros to tidy up toc cell treatment. Numerous
uses as well. Added a new howto to deal with TOCREL16 relocs that
are TOCDEFN as well.
(coff_ppc_relocate_section): Expanded treatment of ADDR32NB relocs
to handle RVA relocs from dlltool.
(ppc_coff_rtype2howto): TOCDEFN reloc addition.
(coff_ppc_rtype_to_howto): TOCDEFN reloc addition.
(ppc_coff_reloc_type_lookup): TOCDEFN reloc addition.
* coffcode.h (coff_set_alignment_hook): check idata$X sections
to get the right section alignment.
Thu Nov 30 16:48:18 1995 Ian Lance Taylor <ian@cygnus.com>
* elf.c (_bfd_elf_make_section_from_shdr): Don't set lma based on

View File

@ -50,6 +50,23 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "libcoff.h"
/* The toc is a set of bfd_vma fields. We use the fact that valid */
/* addresses are even (i.e. the bit representing "1" is off) to allow */
/* us to encode a little extra information in the field */
/* - Unallocated addresses are intialized to 1. */
/* - Allocated addresses are even numbers. */
/* The first time we actually write a reference to the toc in the bfd, */
/* we want to record that fact in a fixup file (if it is asked for), so */
/* we keep track of whether or not an address has been written by marking */
/* the low order bit with a "1" upon writing */
#define SET_UNALLOCATED(x) ((x) = 1)
#define IS_UNALLOCATED(x) ((x) == 1)
#define IS_WRITTEN(x) ((x) & 1)
#define MARK_AS_WRITTEN(x) ((x) |= 1)
#define MAKE_ADDR_AGAIN(x) ((x) &= ~1)
/* In order not to add an int to every hash table item for every coff
linker, we define our own hash table, derived from the coff one */
@ -119,7 +136,7 @@ ppc_coff_link_hash_newfunc (entry, table, string)
if (ret)
{
/* Initialize the local fields. */
ret->toc_offset = 1;
SET_UNALLOCATED(ret->toc_offset);
ret->symbol_is_glue = 0;
ret->glue_insn = 0;
strcpy(ret->eye_catcher, EYE);
@ -238,6 +255,8 @@ ppc_coff_link_hash_table_create (abfd)
#define IMAGE_REL_PPC_REFLO 0x0011
#define IMAGE_REL_PPC_PAIR 0x0012
/* This is essentially the same as tocrel16, with TOCDEFN assumed */
#define IMAGE_REL_PPC_TOCREL16_DEFN 0x0013
/* Flag bits in IMAGE_RELOCATION.TYPE */
@ -693,7 +712,25 @@ static reloc_howto_type ppc_coff_howto_table[] =
true, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
false) /* pcrel_offset */
false), /* pcrel_offset */
/* IMAGE_REL_PPC_TOCREL16_DEFN 0x0013 */
/* 16-bit offset from TOC base, without causing a definition */
/* Used: */
HOWTO ( (IMAGE_REL_PPC_TOCREL16 | IMAGE_REL_PPC_TOCDEFN), /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
0, /* special_function */
"TOCREL16, TOCDEFN", /* name */
false, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
};
@ -850,10 +887,12 @@ ppc_record_toc_entry(abfd, info, sec, sym, toc_kind)
return false;
obj_coff_local_toc_table(abfd) = local_syms;
for (i = 0; i < obj_raw_syment_count(abfd); ++i)
local_syms[i] = 1;
{
SET_UNALLOCATED(local_syms[i]);
}
}
if (local_syms[sym] == 1)
if (IS_UNALLOCATED(local_syms[sym]))
{
local_syms[sym] = global_toc_size;
ret_val = global_toc_size;
@ -889,7 +928,7 @@ ppc_record_toc_entry(abfd, info, sec, sym, toc_kind)
/* check to see if there's a toc slot allocated. If not, do it
here. It will be used in relocate_section */
if (h->toc_offset == 1)
if (IS_UNALLOCATED(h->toc_offset))
{
h->toc_offset = global_toc_size;
ret_val = global_toc_size;
@ -975,10 +1014,12 @@ ppc_record_data_in_toc_entry(abfd, info, sec, sym, toc_kind)
return false;
obj_coff_local_toc_table(abfd) = local_syms;
for (i = 0; i < obj_raw_syment_count(abfd); ++i)
local_syms[i] = 1;
{
SET_UNALLOCATED(local_syms[i]);
}
}
if (local_syms[sym] == 1)
if (IS_UNALLOCATED(local_syms[sym]))
{
local_syms[sym] = global_toc_size;
ret_val = global_toc_size;
@ -1007,7 +1048,7 @@ ppc_record_data_in_toc_entry(abfd, info, sec, sym, toc_kind)
/* check to see if there's a toc slot allocated. If not, do it
here. It will be used in relocate_section */
if (h->toc_offset == 1)
if (IS_UNALLOCATED(h->toc_offset))
{
#if 0
h->toc_offset = global_toc_size;
@ -1348,13 +1389,13 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
local_toc_table = obj_coff_local_toc_table(input_bfd);
our_toc_offset = local_toc_table[symndx];
if ((our_toc_offset & 1) != 0)
if (IS_WRITTEN(our_toc_offset))
{
/* if it has been written out, it is marked with the
1 bit. Fix up our offset, but do not write it out
again.
*/
our_toc_offset &= ~1;
MAKE_ADDR_AGAIN(our_toc_offset);
#ifdef TOC_DEBUG
fprintf(stderr,
@ -1381,7 +1422,7 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
val,
toc_section->contents + our_toc_offset);
local_toc_table[symndx] |= 1;
MARK_AS_WRITTEN(local_toc_table[symndx]);
fixit = true;
}
}
@ -1392,7 +1433,7 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
if ((r_flags & IMAGE_REL_PPC_TOCDEFN)
== IMAGE_REL_PPC_TOCDEFN
&& our_toc_offset == 1)
&& IS_UNALLOCATED(our_toc_offset))
{
/* This is unbelievable cheese. Some knowledgable asm
hacker has decided to use r2 as a base for loading
@ -1423,13 +1464,13 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
record_toc(toc_section, our_toc_offset, pub, strdup(name));
}
else if ((our_toc_offset & 1) != 0)
else if (IS_WRITTEN(our_toc_offset))
{
/* if it has been written out, it is marked with the
1 bit. Fix up our offset, but do not write it out
again.
*/
our_toc_offset &= ~1;
MAKE_ADDR_AGAIN(our_toc_offset);
#ifdef TOC_DEBUG
fprintf(stderr,
"Not writing out toc_offset of %d for %s\n",
@ -1457,7 +1498,7 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
val,
toc_section->contents + our_toc_offset);
h->toc_offset |= 1;
MARK_AS_WRITTEN(h->toc_offset);
/* The tricky part is that this is the address that */
/* needs a .reloc entry for it */
fixit = true;
@ -1594,44 +1635,45 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
target = "__idata4_magic__";
else if (strcmp(".idata$5", name) == 0)
target = "__idata5_magic__";
else
abort();
myh = 0;
myh = coff_link_hash_lookup (coff_hash_table (info),
target,
false, false, true);
if (myh == 0)
if (target != 0)
{
fprintf(stderr, "Missing idata magic cookies, "
"this cannot work anyway...\n");
abort();
}
myh = 0;
val = myh->root.u.def.value +
sec->output_section->vma + sec->output_offset;
if (first_thunk_address == 0)
{
int idata5offset;
myh = coff_link_hash_lookup (coff_hash_table (info),
"__idata5_magic__",
target,
false, false, true);
first_thunk_address = myh->root.u.def.value +
sec->output_section->vma +
sec->output_offset -
pe_data(output_bfd)->pe_opthdr.ImageBase;
idata5offset = myh->root.u.def.value;
myh = coff_link_hash_lookup (coff_hash_table (info),
"__idata6_magic__",
false, false, true);
thunk_size = myh->root.u.def.value - idata5offset;
myh = coff_link_hash_lookup (coff_hash_table (info),
"__idata4_magic__",
false, false, true);
import_table_size = myh->root.u.def.value;
if (myh == 0)
{
fprintf(stderr, "Missing idata magic cookies, "
"this cannot work anyway...\n");
abort();
}
val = myh->root.u.def.value +
sec->output_section->vma + sec->output_offset;
if (first_thunk_address == 0)
{
int idata5offset;
myh = coff_link_hash_lookup (coff_hash_table (info),
"__idata5_magic__",
false, false, true);
first_thunk_address = myh->root.u.def.value +
sec->output_section->vma +
sec->output_offset -
pe_data(output_bfd)->pe_opthdr.ImageBase;
idata5offset = myh->root.u.def.value;
myh = coff_link_hash_lookup (coff_hash_table (info),
"__idata6_magic__",
false, false, true);
thunk_size = myh->root.u.def.value - idata5offset;
myh = coff_link_hash_lookup (coff_hash_table (info),
"__idata4_magic__",
false, false, true);
import_table_size = myh->root.u.def.value;
}
}
}
@ -1841,7 +1883,7 @@ ppc_process_before_allocation (abfd, info)
asection *sec;
struct internal_reloc *i, *rel;
#if DEBUG_RELOC
#ifdef DEBUG_RELOC
fprintf(stderr,
"ppc_process_before_allocation: BFD %s\n",
bfd_get_filename(abfd));
@ -2175,7 +2217,7 @@ ppc_coff_rtype2howto (relent, internal)
For now, we just strip this stuff to find the type, and ignore it other
than that.
*/
reloc_howto_type *howto;
unsigned short r_type = EXTRACT_TYPE (internal->r_type);
unsigned short r_flags = EXTRACT_FLAGS(internal->r_type);
unsigned short junk = EXTRACT_JUNK (internal->r_type);
@ -2220,26 +2262,35 @@ ppc_coff_rtype2howto (relent, internal)
case IMAGE_REL_PPC_ADDR16:
case IMAGE_REL_PPC_REL24:
case IMAGE_REL_PPC_ADDR24:
case IMAGE_REL_PPC_TOCREL16:
case IMAGE_REL_PPC_ADDR32:
case IMAGE_REL_PPC_IFGLUE:
case IMAGE_REL_PPC_ADDR32NB:
case IMAGE_REL_PPC_SECTION:
case IMAGE_REL_PPC_SECREL:
DUMP_RELOC2(ppc_coff_howto_table[r_type].name, internal);
howto = ppc_coff_howto_table + r_type;
break;
case IMAGE_REL_PPC_IMGLUE:
DUMP_RELOC2(ppc_coff_howto_table[r_type].name, internal);
howto = ppc_coff_howto_table + r_type;
break;
case IMAGE_REL_PPC_TOCREL16:
DUMP_RELOC2(ppc_coff_howto_table[r_type].name, internal);
if (r_flags & IMAGE_REL_PPC_TOCDEFN)
howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16_DEFN;
else
howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16;
break;
default:
fprintf(stderr,
"Warning: Unsupported reloc %s [%d] used -- it may not work.\n",
ppc_coff_howto_table[r_type].name,
r_type);
howto = ppc_coff_howto_table + r_type;
break;
}
relent->howto = ppc_coff_howto_table + r_type;
relent->howto = howto;
}
@ -2309,29 +2360,38 @@ coff_ppc_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
case IMAGE_REL_PPC_ADDR32NB:
DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
*addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
howto = ppc_coff_howto_table + r_type;
break;
case IMAGE_REL_PPC_TOCREL16:
DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
if (r_flags & IMAGE_REL_PPC_TOCDEFN)
howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16_DEFN;
else
howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16;
break;
case IMAGE_REL_PPC_ADDR16:
case IMAGE_REL_PPC_REL24:
case IMAGE_REL_PPC_ADDR24:
case IMAGE_REL_PPC_TOCREL16:
case IMAGE_REL_PPC_ADDR32:
case IMAGE_REL_PPC_IFGLUE:
case IMAGE_REL_PPC_SECTION:
case IMAGE_REL_PPC_SECREL:
DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
howto = ppc_coff_howto_table + r_type;
break;
case IMAGE_REL_PPC_IMGLUE:
DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
howto = ppc_coff_howto_table + r_type;
break;
default:
fprintf(stderr,
"Warning: Unsupported reloc %s [%d] used -- it may not work.\n",
ppc_coff_howto_table[r_type].name,
r_type);
howto = ppc_coff_howto_table + r_type;
break;
}
howto = ppc_coff_howto_table + r_type;
return howto;
}
@ -2353,19 +2413,19 @@ ppc_coff_reloc_type_lookup (abfd, code)
fprintf(stderr, "ppc_coff_reloc_type_lookup for %s\n",
bfd_get_reloc_code_name(code));
#endif
switch (code)
{
HOW2MAP(BFD_RELOC_32_GOTOFF, IMAGE_REL_PPC_IMGLUE);
HOW2MAP(BFD_RELOC_16_GOT_PCREL, IMAGE_REL_PPC_IFGLUE);
HOW2MAP(BFD_RELOC_16, IMAGE_REL_PPC_ADDR16);
HOW2MAP(BFD_RELOC_PPC_B26, IMAGE_REL_PPC_REL24);
HOW2MAP(BFD_RELOC_PPC_BA26, IMAGE_REL_PPC_ADDR24);
HOW2MAP(BFD_RELOC_PPC_TOC16, IMAGE_REL_PPC_TOCREL16);
HOW2MAP(BFD_RELOC_16_GOTOFF, IMAGE_REL_PPC_TOCREL16_DEFN);
HOW2MAP(BFD_RELOC_32, IMAGE_REL_PPC_ADDR32);
HOW2MAP(BFD_RELOC_RVA, IMAGE_REL_PPC_ADDR32NB);
default:
fprintf(stderr,
"\treturning NULL\n");
return NULL;
}

View File

@ -959,6 +959,34 @@ coff_set_alignment_hook (abfd, section, scnhdr)
ELIFALIGN_SET (hdr->s_flags, IMAGE_SCN_ALIGN_4BYTES, 2)
ELIFALIGN_SET (hdr->s_flags, IMAGE_SCN_ALIGN_2BYTES, 1)
ELIFALIGN_SET (hdr->s_flags, IMAGE_SCN_ALIGN_1BYTES, 0)
#ifdef POWERPC_LE_PE
if (strcmp (section->name, ".idata$2") == 0)
{
fprintf(stderr, "Setting alignment for .idata$4\n");
section->alignment_power = 0;
}
else if (strcmp (section->name, ".idata$3") == 0)
{
fprintf(stderr, "Setting alignment for .idata$4\n");
section->alignment_power = 0;
}
else if (strcmp (section->name, ".idata$4") == 0)
{
fprintf(stderr, "Setting alignment for .idata$4\n");
section->alignment_power = 2;
}
else if (strcmp (section->name, ".idata$5") == 0)
{
fprintf(stderr, "Setting alignment for .idata$5\n");
section->alignment_power = 2;
}
else if (strcmp (section->name, ".idata$6") == 0)
{
fprintf(stderr, "Setting alignment for .idata$6\n");
section->alignment_power = 1;
}
#endif
}
#undef ALIGN_SET
#undef ELIFALIGN_SET