Implemented IMGLUE reloc + dumping

This commit is contained in:
Kim Knuttila 1995-11-13 12:54:05 +00:00
parent 863fe9d059
commit 93b6a3f8e2
2 changed files with 335 additions and 95 deletions

View File

@ -1,3 +1,18 @@
Mon Nov 13 07:31:35 1995 Kim Knuttila <krk@cygnus.com>
* coff-ppc.c (ppc_coff_link_hash_entry): added support for inline
glue for the relocs: IMGLUE and IFGLUE.
(record_toc): new function - tracks toc contents
(ppc_mark_symbol_as_glue): new function - supports the IMGLUE reloc
(coff_ppc_relocate_section): Added support and fixes for IMGLUE/IFGLUE
(ppc_coff_rtype2howto): removed invalid IMGLUE hack
(coff_ppc_rtype_to_howto): removed invalid IMGLUE hack
* peicode.h (coff_swap_scnhdr_out): Fixed invalid strcmp for ".reldata"
(pe_print_idata): New function - formats the idata section data
(pe_print_pdata): New function - formats the pdata section data
(pe_print_private_bfd_data): calls to above
Sun Nov 12 12:23:24 1995 Stan Shebs <shebs@andros.cygnus.com>
* Makefile.in (bfd_libs_here, etc): Provide empty definitions.

View File

@ -26,6 +26,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Current State:
- objdump works
- relocs generated by gas
- ld will link files, but they do not run.
- dlltool will not produce correct output in some .reloc cases, and will
not produce the right glue code for dll function calls.
*/
@ -47,6 +50,126 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "libcoff.h"
/* 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 */
/* PE linker hash table entries. */
struct ppc_coff_link_hash_entry
{
struct coff_link_hash_entry root; /* First entry, as required */
/* As we wonder around the relocs, we'll keep the assigned toc_offset
here */
bfd_vma toc_offset; /* Our addition, as required */
int symbol_is_glue;
unsigned long int glue_insn;
char eye_catcher[8];
};
/* Need a 7 char string for an eye catcher */
#define EYE "krkjunk"
#define CHECK_EYE(addr) \
if (strcmp(addr, EYE) != 0) \
{ \
fprintf(stderr,\
"File %s, line %d, Hash check failure, bad eye %8s\n", \
__FILE__, __LINE__, addr); \
abort(); \
}
/* PE linker hash table. */
struct ppc_coff_link_hash_table
{
struct coff_link_hash_table root; /* First entry, as required */
};
static struct bfd_hash_entry *ppc_coff_link_hash_newfunc
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
const char *));
/* Routine to create an entry in the link hash table. */
static struct bfd_hash_entry *
ppc_coff_link_hash_newfunc (entry, table, string)
struct bfd_hash_entry *entry;
struct bfd_hash_table *table;
const char *string;
{
struct ppc_coff_link_hash_entry *ret =
(struct ppc_coff_link_hash_entry *) entry;
/* Allocate the structure if it has not already been allocated by a
subclass. */
if (ret == (struct ppc_coff_link_hash_entry *) NULL)
ret = (struct ppc_coff_link_hash_entry *)
bfd_hash_allocate (table,
sizeof (struct ppc_coff_link_hash_entry));
if (ret == (struct ppc_coff_link_hash_entry *) NULL)
return NULL;
/* Call the allocation method of the superclass. */
ret = ((struct ppc_coff_link_hash_entry *)
_bfd_coff_link_hash_newfunc ((struct bfd_hash_entry *) ret,
table, string));
if (ret)
{
/* Initialize the local fields. */
ret->toc_offset = 1;
ret->symbol_is_glue = 0;
ret->glue_insn = 0;
strcpy(ret->eye_catcher, EYE);
}
return (struct bfd_hash_entry *) ret;
}
/* Initialize a PE linker hash table. */
static boolean
ppc_coff_link_hash_table_init (table, abfd, newfunc)
struct ppc_coff_link_hash_table *table;
bfd *abfd;
struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
struct bfd_hash_table *,
const char *));
{
return _bfd_coff_link_hash_table_init (&table->root, abfd, newfunc);
}
/* Create a PE linker hash table. */
static struct bfd_link_hash_table *
ppc_coff_link_hash_table_create (abfd)
bfd *abfd;
{
struct ppc_coff_link_hash_table *ret;
ret = ((struct ppc_coff_link_hash_table *)
bfd_alloc (abfd, sizeof (struct ppc_coff_link_hash_table)));
if (ret == NULL)
{
bfd_set_error (bfd_error_no_memory);
return NULL;
}
if (! ppc_coff_link_hash_table_init (ret, abfd,
ppc_coff_link_hash_newfunc))
{
bfd_release (abfd, ret);
return (struct bfd_link_hash_table *) NULL;
}
return &ret->root.root;
}
/* Now, tailor coffcode.h to use our hash stuff */
#define coff_bfd_link_hash_table_create ppc_coff_link_hash_table_create
/* The nt loader points the toc register to &toc + 32768, in order to */
/* use the complete range of a 16-bit displacement (I guess). We have */
/* to adjust for this when we fix up loads displaced off the toc reg. */
@ -581,6 +704,7 @@ static reloc_howto_type ppc_coff_howto_table[] =
/* Some really cheezy macros that can be turned on to test stderr :-) */
#define DEBUG_RELOC
#ifdef DEBUG_RELOC
#define UN_IMPL(x) \
@ -638,6 +762,43 @@ enum toc_type
toc_64
};
struct list_ele
{
struct list_ele *next;
bfd_vma addr;
int offset;
const char *name;
};
extern struct list_ele *head;
extern struct list_ele *tail;
static void
record_toc(toc_section, our_toc_offset, name)
asection *toc_section;
int our_toc_offset;
const char *name;
{
/* add this entry to our toc addr-offset-name list */
struct list_ele *t;
t = malloc(sizeof(struct list_ele));
t->next = 0;
t->offset = our_toc_offset;
t->name = name;
t->addr = toc_section->output_offset + our_toc_offset;
if (head == 0)
{
head = t;
tail = t;
}
else
{
tail->next = t;
tail = t;
}
}
/* record a toc offset against a symbol */
static int
ppc_record_toc_entry(abfd, info, sec, sym, toc_kind)
@ -653,7 +814,7 @@ ppc_record_toc_entry(abfd, info, sec, sym, toc_kind)
int element_size;
int data;
int offset;
struct coff_link_hash_entry *h;
struct ppc_coff_link_hash_entry *h;
struct coff_symbol_struct *target;
int ret_val;
const char *name;
@ -662,7 +823,11 @@ ppc_record_toc_entry(abfd, info, sec, sym, toc_kind)
h = 0;
h = obj_coff_sym_hashes (abfd)[sym];
h = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (abfd)[sym]);
if (h != 0)
{
CHECK_EYE(h->eye_catcher);
}
if (h == 0)
{
@ -707,7 +872,7 @@ ppc_record_toc_entry(abfd, info, sec, sym, toc_kind)
}
else
{
name = h->root.root.string;
name = h->root.root.root.string;
/* check to see if there's a toc slot allocated. If not, do it
here. It will be used in relocate_section */
@ -736,6 +901,25 @@ ppc_record_toc_entry(abfd, info, sec, sym, toc_kind)
return ret_val;
}
/* record a toc offset against a symbol */
static void
ppc_mark_symbol_as_glue(abfd, sym, rel)
bfd *abfd;
int sym;
struct internal_reloc *rel;
{
struct ppc_coff_link_hash_entry *h;
h = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (abfd)[sym]);
CHECK_EYE(h->eye_catcher);
h->symbol_is_glue = 1;
h->glue_insn = bfd_get_32 (abfd, (bfd_byte *) &rel->r_vaddr);
return;
}
/* Provided the symbol, returns the value reffed */
static long get_symbol_value PARAMS ((asymbol *));
@ -882,7 +1066,7 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
for (; rel < relend; rel++)
{
long symndx;
struct coff_link_hash_entry *h;
struct ppc_coff_link_hash_entry *h;
struct internal_syment *sym;
bfd_vma val;
@ -895,20 +1079,20 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
unsigned short junk = EXTRACT_JUNK (rel->r_type);
#ifdef DEBUG_RELOC
/* now examine flags */
if (r_flags != 0)
{
fprintf (stderr, "Reloc with flags found!");
if ( r_flags & IMAGE_REL_PPC_NEG )
fprintf (stderr, " NEG");
if ( r_flags & IMAGE_REL_PPC_BRTAKEN )
fprintf (stderr, " BRTAKEN");
if ( r_flags & IMAGE_REL_PPC_BRNTAKEN )
fprintf (stderr, " BRNTAKEN");
if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
fprintf (stderr, " TOCDEFN");
fprintf(stderr, "\n");
}
/* now examine flags */
if (r_flags != 0)
{
fprintf (stderr, "Reloc with flags found!");
if ( r_flags & IMAGE_REL_PPC_NEG )
fprintf (stderr, " NEG");
if ( r_flags & IMAGE_REL_PPC_BRTAKEN )
fprintf (stderr, " BRTAKEN");
if ( r_flags & IMAGE_REL_PPC_BRNTAKEN )
fprintf (stderr, " BRNTAKEN");
if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
fprintf (stderr, " TOCDEFN");
fprintf(stderr, "\n");
}
#endif
symndx = rel->r_symndx;
@ -924,7 +1108,13 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
}
else
{
h = obj_coff_sym_hashes (input_bfd)[symndx];
h = (struct ppc_coff_link_hash_entry *)
(obj_coff_sym_hashes (input_bfd)[symndx]);
if (h != 0)
{
CHECK_EYE(h->eye_catcher);
}
sym = syms + symndx;
}
@ -947,18 +1137,20 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
}
else
{
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
CHECK_EYE(h->eye_catcher);
if (h->root.root.type == bfd_link_hash_defined
|| h->root.root.type == bfd_link_hash_defweak)
{
sec = h->root.u.def.section;
val = (h->root.u.def.value
sec = h->root.root.u.def.section;
val = (h->root.root.u.def.value
+ sec->output_section->vma
+ sec->output_offset);
}
else
{
if (! ((*info->callbacks->undefined_symbol)
(info, h->root.root.string, input_bfd, input_section,
(info, h->root.root.root.string, input_bfd, input_section,
rel->r_vaddr - input_section->vma)))
return false;
}
@ -1001,6 +1193,17 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
}
}
#if 0
if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
{
/* Somehow, we are to assume that the toc has already been
done for this one, and the offset is the value of
the symbol? */
fprintf(stderr,
"Symbol value %d\n", val);
}
#endif
/*
* Amazing bit tricks present. As we may have seen earlier, we
* use the 1 bit to tell us whether or not a toc offset has been
@ -1036,6 +1239,7 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
else
{
/* write out the toc entry */
record_toc(toc_section, our_toc_offset, strdup(name));
#ifdef TOC_DEBUG
fprintf(stderr,
"Writing out toc_offset toc_section (%p,%p)+%d val %d for %s\n",
@ -1056,8 +1260,9 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
}
else
{
const char *name = h->root.root.string;
const char *name = h->root.root.root.string;
our_toc_offset = h->toc_offset;
if ((our_toc_offset & 1) != 0)
{
/* if it has been written out, it is marked with the
@ -1072,6 +1277,8 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
}
else
{
record_toc(toc_section, our_toc_offset, strdup(name));
#ifdef TOC_DEBUG
/* write out the toc entry */
fprintf(stderr,
@ -1133,40 +1340,26 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
}
break;
case IMAGE_REL_PPC_IFGLUE:
/* To solve this, we need to know whether or not the symbol */
/* appearing on the call instruction is a function included */
/* in the link or not. If it is, then we leave the nop instruction */
/* alone, and the reloc is done. */
{
/* To solve this, we need to know whether or not the symbol */
/* appearing on the call instruction is a glue function or not. */
/* A glue function must announce itself via a IMGLUE reloc, and */
/* the reloc contains the required toc restore instruction */
bfd_vma x;
const char *my_name;
DUMP_RELOC2(howto->name, rel);
/* Actually, for dll support on NT, this is likely not necessary at
all. For any library function, a glue code stub must be supplied
to the linker, and the glue will take care of the toc reload */
DUMP_RELOC2(howto->name, rel);
#if 0
if (h == 0)
{
/* this better be a static function */
fprintf(stderr,
"It's a static function.... \n");
}
else
{
/* this is an externally visible function */
/* is it present? */
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
{
fprintf(stderr,
"The function is present. \n");
;
}
else
{
fprintf(stderr,
"The function is not present. \n");
}
}
#endif
if (h != 0)
{
my_name = h->root.root.root.string;
if (h->symbol_is_glue == 1)
{
x = bfd_get_32(input_bfd, loc);
bfd_put_32(input_bfd, h->glue_insn, loc);
}
}
}
break;
case IMAGE_REL_PPC_SECREL:
/* Unimplemented: codeview debugging information */
@ -1180,13 +1373,14 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
symbol */
break;
case IMAGE_REL_PPC_ABSOLUTE:
case IMAGE_REL_PPC_IMGLUE:
{
const char *my_name;
if (h == 0)
my_name = (syms+symndx)->_n._n_name;
else
my_name = h->root.root.string;
{
my_name = h->root.root.root.string;
}
fprintf(stderr,
"Warning: unsupported reloc %s <file %s, section %s>\n",
@ -1198,6 +1392,23 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
rel->r_symndx, my_name, rel->r_vaddr, rel->r_vaddr);
}
break;
case IMAGE_REL_PPC_IMGLUE:
{
/* There is nothing to do now. This reloc was noted in the first
pass over the relocs, and the glue instruction extracted */
const char *my_name;
if (h->symbol_is_glue == 1)
break;
my_name = h->root.root.root.string;
fprintf(stderr,
"Warning: previously missed IMGLUE reloc %s <file %s, section %s>\n",
howto->name,
bfd_get_filename(input_bfd),
input_section->name);
break;
}
break;
case IMAGE_REL_PPC_ADDR32NB:
{
@ -1213,7 +1424,7 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
{
char *target = 0;
name = h->root.root.string;
name = h->root.root.root.string;
if (strcmp(".idata$2", name) == 0)
target = "__idata2_magic__";
else if (strcmp(".idata$4", name) == 0)
@ -1234,15 +1445,18 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
abort();
}
val = myh->root.u.def.value + sec->output_section->vma + sec->output_offset;
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;
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),
@ -1258,9 +1472,10 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
}
rstat = _bfd_relocate_contents (howto,
input_bfd,
val - pe_data(output_bfd)->pe_opthdr.ImageBase,
loc);
input_bfd,
val -
pe_data(output_bfd)->pe_opthdr.ImageBase,
loc);
}
break;
@ -1316,7 +1531,7 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
if (symndx == -1)
name = "*ABS*";
else if (h != NULL)
name = h->root.root.string;
name = h->root.root.root.string;
else if (sym == NULL)
name = "*unknown*";
else if (sym->_n._n_n._n_zeroes == 0
@ -1360,6 +1575,26 @@ long int import_table_size;
long int first_thunk_address;
long int thunk_size;
struct list_ele *head;
struct list_ele *tail;
void
dump_toc(vfile)
void *vfile;
{
FILE *file = vfile;
struct list_ele *t;
fprintf(file,
" Offset Offset Name if present\n");
for(t = head; t != 0; t=t->next)
{
fprintf(file,
" %2x %04lx %s\n",
t->offset - 32768, t->offset, t->name);
}
}
boolean
ppc_allocate_toc_section (info)
@ -1455,20 +1690,20 @@ ppc_process_before_allocation (abfd, info)
unsigned short junk = EXTRACT_JUNK (rel->r_type);
#ifdef DEBUG_RELOC
/* now examine flags */
if (r_flags != 0)
{
fprintf (stderr, "Reloc with flags found!");
if ( r_flags & IMAGE_REL_PPC_NEG )
fprintf (stderr, " NEG");
if ( r_flags & IMAGE_REL_PPC_BRTAKEN )
fprintf (stderr, " BRTAKEN");
if ( r_flags & IMAGE_REL_PPC_BRNTAKEN )
fprintf (stderr, " BRNTAKEN");
if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
fprintf (stderr, " TOCDEFN");
fprintf(stderr, "\n");
}
/* now examine flags */
if (r_flags != 0)
{
fprintf (stderr, "Reloc with flags found!");
if ( r_flags & IMAGE_REL_PPC_NEG )
fprintf (stderr, " NEG");
if ( r_flags & IMAGE_REL_PPC_BRTAKEN )
fprintf (stderr, " BRTAKEN");
if ( r_flags & IMAGE_REL_PPC_BRNTAKEN )
fprintf (stderr, " BRNTAKEN");
if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
fprintf (stderr, " TOCDEFN");
fprintf(stderr, "\n");
}
#endif
DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
@ -1479,6 +1714,9 @@ ppc_process_before_allocation (abfd, info)
toc_offset = ppc_record_toc_entry(abfd, info, sec,
rel->r_symndx, default_toc);
break;
case IMAGE_REL_PPC_IMGLUE:
ppc_mark_symbol_as_glue(abfd, rel->r_symndx, rel);
break;
default:
break;
}
@ -1779,8 +2017,6 @@ ppc_coff_rtype2howto (relent, internal)
break;
case IMAGE_REL_PPC_IMGLUE:
DUMP_RELOC2(ppc_coff_howto_table[r_type].name, internal);
/* IMGLUE relocs have big numbers in them. Don't know what for yet. */
internal->r_vaddr = 0; /* make it zero for now */
break;
default:
fprintf(stderr,
@ -1876,8 +2112,6 @@ fprintf(stderr,
break;
case IMAGE_REL_PPC_IMGLUE:
DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
/* IMGLUE relocs have big numbers in them. Don't know what for yet. */
rel->r_vaddr = 0; /* make it zero for now */
break;
default:
fprintf(stderr,
@ -2112,12 +2346,3 @@ TARGET_BIG_SYM =
};
#endif