From 590662481cd0c539d7b599830e4c4b73d51f3c4d Mon Sep 17 00:00:00 2001 From: Kim Knuttila Date: Fri, 1 Dec 1995 01:01:42 +0000 Subject: [PATCH] PowerPC DLL Support --- bfd/ChangeLog | 14 ++++ bfd/coff-ppc.c | 174 +++++++++++++++++++++++++++++++++---------------- bfd/coffcode.h | 28 ++++++++ 3 files changed, 159 insertions(+), 57 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 5986cb96a8b..60624ef12c8 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,17 @@ +Thu Nov 30 19:32:26 1995 Kim Knuttila + + * 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 * elf.c (_bfd_elf_make_section_from_shdr): Don't set lma based on diff --git a/bfd/coff-ppc.c b/bfd/coff-ppc.c index 25deb99e6d7..379ef4e3406 100644 --- a/bfd/coff-ppc.c +++ b/bfd/coff-ppc.c @@ -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; } diff --git a/bfd/coffcode.h b/bfd/coffcode.h index 6dc48e57655..d76882a3dc6 100644 --- a/bfd/coffcode.h +++ b/bfd/coffcode.h @@ -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 -- 2.30.2