more changes from Utah, see log for details

This commit is contained in:
Ken Raeburn 1993-09-03 20:12:51 +00:00
parent ee8cb54804
commit 3a70b01d63

View file

@ -1655,21 +1655,23 @@ elf_hppa_reloc_type_lookup (arch, code)
void
DEFUN (elf_hppa_tc_symbol, (abfd, symbolP, sym_idx),
bfd * abfd AND
elf32_symbol_type * symbolP AND
elf_symbol_type * symbolP AND
int sym_idx)
{
symext_chainS *symextP;
unsigned int arg_reloc;
/* Only functions can have argument relocations. */
if (!(symbolP->symbol.flags & BSF_FUNCTION))
return;
if (!((symbolP->symbol.flags & BSF_EXPORT) ||
(symbolP->symbol.flags & BSF_GLOBAL)))
return;
arg_reloc = symbolP->tc_data.hppa_arg_reloc;
/* If there are no argument relocation bits, then no relocation is
necessary. Do not add this to the symextn section. */
if (arg_reloc == 0)
return;
symextP = (symext_chainS *) bfd_alloc (abfd, sizeof (symext_chainS) * 2);
symextP[0].entry = ELF32_HPPA_SX_WORD (HPPA_SXT_SYMNDX, sym_idx);
@ -1800,7 +1802,7 @@ elf32_hppa_get_sym_extn (abfd, sym, type)
break;
case HPPA_SXT_ARG_RELOC:
{
elf32_symbol_type *esymP = (elf32_symbol_type *) sym;
elf_symbol_type *esymP = (elf_symbol_type *) sym;
retval = (symext_entryS) esymP->tc_data.hppa_arg_reloc;
break;
@ -1812,58 +1814,67 @@ elf32_hppa_get_sym_extn (abfd, sym, type)
return retval;
}
typedef struct Elf32_hppa_Stub_description_struct
typedef struct elf32_hppa_stub_name_list_struct
{
bfd *this_bfd; /* bfd to which this stub */
/* applies */
/* name of this stub */
asymbol *sym;
/* stub description for this stub */
struct elf32_hppa_stub_description_struct *stub_desc;
/* pointer into stub contents */
int *stub_secp;
/* size of this stub */
unsigned size;
/* next stub name entry */
struct elf32_hppa_stub_name_list_struct *next;
} elf32_hppa_stub_name_list;
typedef struct elf32_hppa_stub_description_struct
{
struct elf32_hppa_stub_description_struct *next;
bfd *this_bfd; /* bfd to which this stub applies */
asection *stub_sec; /* stub section for this bfd */
unsigned relocs_allocated_cnt; /* count of relocations for this stub section */
unsigned real_size;
unsigned allocated_size;
int *stub_secp; /* pointer to the next available location in the buffer */
char *stub_contents; /* contents of the stubs for this bfd */
elf32_hppa_stub_name_list *stub_listP;
}
elf32_hppa_stub_description;
Elf32_hppa_Stub_description;
typedef struct Elf32_hppa_Stub_list_struct
{
Elf32_hppa_Stub_description *stub;
struct Elf32_hppa_Stub_list_struct *next;
} Elf32_hppa_Stub_list;
static Elf32_hppa_Stub_list *elf_hppa_stub_rootP;
static elf32_hppa_stub_description *elf_hppa_stub_rootP;
/* Locate the stub section information for the given bfd. */
static Elf32_hppa_Stub_description *
static elf32_hppa_stub_description *
find_stubs (abfd, stub_sec)
bfd *abfd;
asection *stub_sec;
{
Elf32_hppa_Stub_list *stubP;
elf32_hppa_stub_description *stubP;
for (stubP = elf_hppa_stub_rootP; stubP; stubP = stubP->next)
{
if (stubP->stub->this_bfd == abfd
&& stubP->stub->stub_sec == stub_sec)
return stubP->stub;
if (stubP->this_bfd == abfd
&& stubP->stub_sec == stub_sec)
return stubP;
}
return (Elf32_hppa_Stub_description *) NULL;
return (elf32_hppa_stub_description *) NULL;
}
static Elf32_hppa_Stub_description *
static elf32_hppa_stub_description *
new_stub (abfd, stub_sec)
bfd *abfd;
asection *stub_sec;
{
Elf32_hppa_Stub_description *stub = find_stubs (abfd, stub_sec);
elf32_hppa_stub_description *stub = find_stubs (abfd, stub_sec);
if (stub)
return stub;
stub = (Elf32_hppa_Stub_description *) bfd_zalloc (abfd, sizeof (Elf32_hppa_Stub_description));
stub = (elf32_hppa_stub_description *) bfd_zalloc (abfd, sizeof (elf32_hppa_stub_description));
if (stub)
{
stub->this_bfd = abfd;
stub->stub_sec = stub_sec;
stub->real_size = 0;
@ -1871,37 +1882,82 @@ new_stub (abfd, stub_sec)
stub->stub_contents = NULL;
stub->stub_secp = NULL;
return stub;
}
static void
add_stub (stub)
Elf32_hppa_Stub_description *stub;
{
Elf32_hppa_Stub_list *new_entry;
new_entry = (Elf32_hppa_Stub_list *) bfd_zalloc (stub->this_bfd, sizeof (Elf32_hppa_Stub_list));
if (new_entry)
{
new_entry->stub = stub;
if (elf_hppa_stub_rootP)
{
new_entry->next = elf_hppa_stub_rootP;
elf_hppa_stub_rootP = new_entry;
}
else
{
new_entry->next = (Elf32_hppa_Stub_list *) NULL;
elf_hppa_stub_rootP = new_entry;
}
stub->next = elf_hppa_stub_rootP;
elf_hppa_stub_rootP = stub;
}
else
{
bfd_error = no_memory;
bfd_perror ("add_stub");
bfd_perror ("new_stub");
}
return stub;
}
/* Locate the stub by the given name. */
static elf32_hppa_stub_name_list *
find_stub_by_name (abfd, stub_sec, name)
bfd *abfd;
asection *stub_sec;
char *name;
{
elf32_hppa_stub_description *stub = find_stubs (abfd, stub_sec);
if (stub)
{
elf32_hppa_stub_name_list *name_listP;
for (name_listP = stub->stub_listP; name_listP; name_listP = name_listP->next)
{
if (!strcmp (name_listP->sym->name, name))
return name_listP;
}
}
return 0;
}
/* Locate the stub by the given name. */
static elf32_hppa_stub_name_list *
add_stub_by_name(abfd, stub_sec, sym)
bfd *abfd;
asection *stub_sec;
asymbol *sym;
{
elf32_hppa_stub_description *stub = find_stubs (abfd, stub_sec);
elf32_hppa_stub_name_list *stub_entry;
if (!stub)
stub = new_stub(abfd, stub_sec);
if (stub)
{
stub_entry = (elf32_hppa_stub_name_list *)
bfd_zalloc (abfd, sizeof (elf32_hppa_stub_name_list));
if (stub_entry)
{
stub_entry->size = 0;
stub_entry->sym = sym;
stub_entry->stub_desc = stub;
/* First byte of this stub is the pointer to
the next available location in the stub buffer. */
stub_entry->stub_secp = stub->stub_secp;
if (stub->stub_listP)
stub_entry->next = stub->stub_listP;
else
stub_entry->next = NULL;
stub->stub_listP = stub_entry;
return stub_entry;
}
else
{
bfd_error = no_memory;
bfd_perror("add_stub_by_name");
}
}
return (elf32_hppa_stub_name_list *)NULL;
}
#define ARGUMENTS 0
@ -1966,15 +2022,15 @@ static CONST char retval_mismatches[6][6] =
/* CALLER NONE */
{NO_ARG_RELOC, NO_ARG_RELOC, NO_ARG_RELOC, ARG_RELOC_ERR, NO_ARG_RELOC, NO_ARG_RELOC},
/* CALLER GR */
{NO_ARG_RELOC, NO_ARG_RELOC, R_TO_FR, ARG_RELOC_ERR, R01_TO_FR, ARG_RELOC_ERR},
{NO_ARG_RELOC, NO_ARG_RELOC, FR_TO_R, ARG_RELOC_ERR, FR_TO_R01, ARG_RELOC_ERR},
/* CALLER FR */
{NO_ARG_RELOC, FR_TO_R, NO_ARG_RELOC, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR},
{NO_ARG_RELOC, R_TO_FR, NO_ARG_RELOC, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR},
/* CALLER FU */
{ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR},
/* CALLER DBL01 */
{NO_ARG_RELOC, FR_TO_R01, NO_ARG_RELOC, ARG_RELOC_ERR, NO_ARG_RELOC, ARG_RELOC_ERR},
{NO_ARG_RELOC, R01_TO_FR, NO_ARG_RELOC, ARG_RELOC_ERR, NO_ARG_RELOC, ARG_RELOC_ERR},
/* CALLER DBL23 */
{NO_ARG_RELOC, FR_TO_R23, NO_ARG_RELOC, ARG_RELOC_ERR, ARG_RELOC_ERR, NO_ARG_RELOC},
{NO_ARG_RELOC, R23_TO_FR, NO_ARG_RELOC, ARG_RELOC_ERR, ARG_RELOC_ERR, NO_ARG_RELOC},
};
static int
@ -1996,13 +2052,16 @@ type_of_mismatch (caller_bits, callee_bits, type)
#define EXTRACT_ARBITS(ar,which) ((ar) >> (8-(which*2))) & 3
#define NEW_INSTRUCTION(desc,insn) \
*((desc)->stub_secp)++ = (insn); \
(desc)->real_size += sizeof(int); \
bfd_set_section_size((desc)->this_bfd,(desc)->stub_sec,(desc)->real_size);
#define NEW_INSTRUCTION(entry,insn) \
*((entry)->stub_desc->stub_secp)++ = (insn); \
(entry)->stub_desc->real_size += sizeof(int); \
(entry)->size += sizeof(int); \
bfd_set_section_size((entry)->stub_desc->this_bfd, \
(entry)->stub_desc->stub_sec, \
(entry)->stub_desc->real_size);
#define CURRENT_STUB_OFFSET(desc) \
((int)(desc)->stub_secp - (int)(desc)->stub_contents - 4)
#define CURRENT_STUB_OFFSET(entry) \
((int)(entry)->stub_desc->stub_secp - (int)(entry)->stub_desc->stub_contents - 4)
static boolean stubs_finished = false;
@ -2011,7 +2070,7 @@ hppa_elf_stub_finish (output_bfd)
bfd *output_bfd;
{
extern bfd_error_vector_type bfd_error_vector;
Elf32_hppa_Stub_list *stub_list = elf_hppa_stub_rootP;
elf32_hppa_stub_description *stub_list = elf_hppa_stub_rootP;
/* All the stubs have been built. Finish up building */
/* stub section. Apply relocations to the section. */
@ -2020,14 +2079,14 @@ hppa_elf_stub_finish (output_bfd)
for (; stub_list; stub_list = stub_list->next)
{
if (stub_list->stub->real_size)
if (stub_list->real_size)
{
bfd *stub_bfd = stub_list->stub->this_bfd;
bfd *stub_bfd = stub_list->this_bfd;
asection *stub_sec = bfd_get_section_by_name (stub_bfd, ".hppa_linker_stubs");
bfd_size_type reloc_size;
arelent **reloc_vector;
BFD_ASSERT (stub_sec == stub_list->stub->stub_sec);
BFD_ASSERT (stub_sec == stub_list->stub_sec);
reloc_size = bfd_get_reloc_upper_bound (stub_bfd, stub_sec);
reloc_vector = (arelent **) alloca (reloc_size);
@ -2050,7 +2109,7 @@ hppa_elf_stub_finish (output_bfd)
bfd_reloc_status_type r =
bfd_perform_relocation (stub_bfd,
*parent,
stub_list->stub->stub_contents,
stub_list->stub_contents,
stub_sec, 0);
@ -2078,9 +2137,9 @@ hppa_elf_stub_finish (output_bfd)
bfd_set_section_contents (output_bfd,
stub_sec,
stub_list->stub->stub_contents,
stub_list->stub_contents,
0,
stub_list->stub->real_size);
stub_list->real_size);
free (reloc_vector);
}
@ -2093,7 +2152,7 @@ hppa_elf_stub_branch_reloc (stub_desc, /* the bfd */
output_bfd, /* the output bfd */
target_sym, /* the target symbol */
offset) /* the offset within the stub buffer (pre-calculated) */
Elf32_hppa_Stub_description *stub_desc;
elf32_hppa_stub_description *stub_desc;
bfd *output_bfd;
asymbol *target_sym;
int offset;
@ -2141,7 +2200,7 @@ hppa_elf_stub_reloc (stub_desc, /* the bfd */
target_sym, /* the target symbol */
offset, /* the offset within the stub buffer (pre-calculated) */
type)
Elf32_hppa_Stub_description *stub_desc;
elf32_hppa_stub_description *stub_desc;
bfd *output_bfd;
asymbol *target_sym;
int offset;
@ -2196,12 +2255,13 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types)
int stub_types[5];
{
asection *stub_sec = bfd_get_section_by_name (abfd, ".hppa_linker_stubs");
Elf32_hppa_Stub_description *stub_desc = find_stubs (abfd, stub_sec);
elf32_hppa_stub_description *stub_desc = find_stubs (abfd, stub_sec);
asymbol *stub_sym = NULL;
asymbol *target_sym = reloc_entry->sym_ptr_ptr[0];
asection *output_text_section = bfd_get_section_by_name (output_bfd, ".text");
int i;
char stub_sym_name[128];
elf32_hppa_stub_name_list *stub_entry;
if (!stub_sec)
{
@ -2214,16 +2274,12 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types)
stub_sec->output_offset = 0;
bfd_set_section_alignment (abfd, stub_sec, 2);
stub_desc = new_stub (abfd, stub_sec);
add_stub (stub_desc);
}
/* make sure we have a stub descriptor structure */
if (!stub_desc)
{
stub_desc = new_stub (abfd, stub_sec);
add_stub (stub_desc);
}
/* allocate some space to write the stub */
@ -2241,17 +2297,32 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types)
stub_desc->stub_secp = (int *) (stub_desc->stub_contents + stub_desc->real_size);
/* create a symbol to point to this stub */
stub_sym = bfd_make_empty_symbol (abfd);
sprintf (stub_sym_name,
"_stub_%s_%02d_%02d_%02d_%02d_%02d\000",
"_stub_%s_%02d_%02d_%02d_%02d_%02d",
reloc_entry->sym_ptr_ptr[0]->name,
stub_types[0], stub_types[1], stub_types[2], stub_types[3], stub_types[4]);
stub_entry = find_stub_by_name(abfd, stub_sec, stub_sym_name);
if (stub_entry)
{
stub_sym = stub_entry->sym;
/* redirect the original relocation from the old symbol (a function) */
/* to the stub (the stub calls the function). */
/* XXX do we need to change the relocation type? */
reloc_entry->sym_ptr_ptr = (asymbol **) bfd_zalloc (stub_desc->this_bfd, sizeof (asymbol *));
reloc_entry->sym_ptr_ptr[0] = stub_sym;
}
else
{
/* Stub does not already exist. Create a new stub. */
/* Create a new symbol to point to this stub */
stub_sym = bfd_make_empty_symbol (abfd);
stub_sym->name = bfd_zalloc (abfd, strlen (stub_sym_name) + 1);
strcpy ((char *) stub_sym->name, stub_sym_name);
stub_sym->value = (int) stub_desc->stub_secp - (int) stub_desc->stub_contents;
stub_sym->section = stub_sec;
stub_sym->flags = BSF_LOCAL | BSF_FUNCTION;
stub_entry = add_stub_by_name(abfd, stub_sec, stub_sym);
/* redirect the original relocation from the old symbol (a function) */
/* to the stub (the stub calls the function). */
@ -2261,7 +2332,7 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types)
/* generate the beginning common section for all stubs */
NEW_INSTRUCTION (stub_desc, ADDI_8_SP);
NEW_INSTRUCTION (stub_entry, ADDI_8_SP);
/* generate the code to move the arguments around */
for (i = ARG0; i < ARG3; i++)
@ -2275,20 +2346,20 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types)
switch (i)
{
case ARG0:
NEW_INSTRUCTION (stub_desc, STWS_ARG0_M8SP);
NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG0);
NEW_INSTRUCTION (stub_entry, STWS_ARG0_M8SP);
NEW_INSTRUCTION (stub_entry, FLDWS_M8SP_FARG0);
break;
case ARG1:
NEW_INSTRUCTION (stub_desc, STWS_ARG1_M8SP);
NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG1);
NEW_INSTRUCTION (stub_entry, STWS_ARG1_M8SP);
NEW_INSTRUCTION (stub_entry, FLDWS_M8SP_FARG1);
break;
case ARG2:
NEW_INSTRUCTION (stub_desc, STWS_ARG2_M8SP);
NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG2);
NEW_INSTRUCTION (stub_entry, STWS_ARG2_M8SP);
NEW_INSTRUCTION (stub_entry, FLDWS_M8SP_FARG2);
break;
case ARG3:
NEW_INSTRUCTION (stub_desc, STWS_ARG3_M8SP);
NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG3);
NEW_INSTRUCTION (stub_entry, STWS_ARG3_M8SP);
NEW_INSTRUCTION (stub_entry, FLDWS_M8SP_FARG3);
break;
}
continue;
@ -2297,9 +2368,9 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types)
switch (i)
{
case ARG0:
NEW_INSTRUCTION(stub_desc, STWS_ARG0_M4SP);
NEW_INSTRUCTION(stub_desc, STWS_ARG1_M8SP);
NEW_INSTRUCTION(stub_desc, FLDDS_M8SP_FARG1);
NEW_INSTRUCTION(stub_entry, STWS_ARG0_M4SP);
NEW_INSTRUCTION(stub_entry, STWS_ARG1_M8SP);
NEW_INSTRUCTION(stub_entry, FLDDS_M8SP_FARG1);
break;
default:
AR_WARN(stub_types[i],i);
@ -2311,9 +2382,9 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types)
switch (i)
{
case ARG2:
NEW_INSTRUCTION(stub_desc, STWS_ARG2_M4SP);
NEW_INSTRUCTION(stub_desc, STWS_ARG3_M8SP);
NEW_INSTRUCTION(stub_desc, FLDDS_M8SP_FARG3);
NEW_INSTRUCTION(stub_entry, STWS_ARG2_M4SP);
NEW_INSTRUCTION(stub_entry, STWS_ARG3_M8SP);
NEW_INSTRUCTION(stub_entry, FLDDS_M8SP_FARG3);
break;
default:
AR_WARN(stub_types[i],i);
@ -2325,20 +2396,20 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types)
switch (i)
{
case ARG0:
NEW_INSTRUCTION (stub_desc, FSTWS_FARG0_M8SP);
NEW_INSTRUCTION (stub_desc, LDWS_M4SP_ARG0);
NEW_INSTRUCTION (stub_entry, FSTWS_FARG0_M8SP);
NEW_INSTRUCTION (stub_entry, LDWS_M4SP_ARG0);
break;
case ARG1:
NEW_INSTRUCTION (stub_desc, FSTWS_FARG1_M8SP);
NEW_INSTRUCTION (stub_desc, LDWS_M4SP_ARG1);
NEW_INSTRUCTION (stub_entry, FSTWS_FARG1_M8SP);
NEW_INSTRUCTION (stub_entry, LDWS_M4SP_ARG1);
break;
case ARG2:
NEW_INSTRUCTION (stub_desc, FSTWS_FARG2_M8SP);
NEW_INSTRUCTION (stub_desc, LDWS_M4SP_ARG2);
NEW_INSTRUCTION (stub_entry, FSTWS_FARG2_M8SP);
NEW_INSTRUCTION (stub_entry, LDWS_M4SP_ARG2);
break;
case ARG3:
NEW_INSTRUCTION (stub_desc, FSTWS_FARG3_M8SP);
NEW_INSTRUCTION (stub_desc, LDWS_M4SP_ARG3);
NEW_INSTRUCTION (stub_entry, FSTWS_FARG3_M8SP);
NEW_INSTRUCTION (stub_entry, LDWS_M4SP_ARG3);
break;
}
continue;
@ -2347,9 +2418,9 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types)
switch (i)
{
case ARG0:
NEW_INSTRUCTION(stub_desc, FSTDS_FARG1_M8SP);
NEW_INSTRUCTION(stub_desc, LDWS_M4SP_ARG0);
NEW_INSTRUCTION(stub_desc, LDWS_M8SP_ARG1);
NEW_INSTRUCTION(stub_entry, FSTDS_FARG1_M8SP);
NEW_INSTRUCTION(stub_entry, LDWS_M4SP_ARG0);
NEW_INSTRUCTION(stub_entry, LDWS_M8SP_ARG1);
break;
default:
AR_WARN(stub_types[i],i);
@ -2361,9 +2432,9 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types)
switch (i)
{
case ARG2:
NEW_INSTRUCTION(stub_desc, FSTDS_FARG3_M8SP);
NEW_INSTRUCTION(stub_desc, LDWS_M4SP_ARG2);
NEW_INSTRUCTION(stub_desc, LDWS_M8SP_ARG3);
NEW_INSTRUCTION(stub_entry, FSTDS_FARG3_M8SP);
NEW_INSTRUCTION(stub_entry, LDWS_M4SP_ARG2);
NEW_INSTRUCTION(stub_entry, LDWS_M8SP_ARG3);
break;
default:
AR_WARN(stub_types[i],i);
@ -2375,30 +2446,33 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types)
}
}
NEW_INSTRUCTION (stub_desc, ADDI_M8_SP);
NEW_INSTRUCTION (stub_entry, ADDI_M8_SP);
/* generate the branch to the target routine */
NEW_INSTRUCTION (stub_desc, STW_RP_M8SP); /* First, save the return address */
NEW_INSTRUCTION (stub_entry, STW_RP_M8SP); /* First, save the return address */
/* Branch to the target function. */
/* (Make it a long call, so we do not */
/* have to worry about generating a */
/* long call stub.) */
NEW_INSTRUCTION(stub_desc, LDIL_XXX_31);
hppa_elf_stub_reloc (stub_desc,
NEW_INSTRUCTION(stub_entry, LDIL_XXX_31);
hppa_elf_stub_reloc (stub_entry->stub_desc,
abfd, /* the output bfd */
target_sym, /* the target symbol */
CURRENT_STUB_OFFSET(stub_desc), /* offset in stub buffer */
CURRENT_STUB_OFFSET(stub_entry), /* offset in stub buffer */
R_HPPA_L21);
NEW_INSTRUCTION(stub_desc,BLE_XXX_0_31);
hppa_elf_stub_reloc (stub_desc,
NEW_INSTRUCTION(stub_entry,BLE_XXX_0_31);
hppa_elf_stub_reloc (stub_entry->stub_desc,
abfd, /* the output bfd */
target_sym, /* the target symbol */
CURRENT_STUB_OFFSET(stub_desc), /* offset in stub buffer */
CURRENT_STUB_OFFSET(stub_entry), /* offset in stub buffer */
R_HPPA_ABS_CALL_R17);
NEW_INSTRUCTION(stub_desc,COPY_31_2);
NEW_INSTRUCTION(stub_entry,COPY_31_2);
/* generate the code to move the return value around */
NEW_INSTRUCTION (stub_entry, LDW_M8SP_RP); /* restore return address */
i = RETVAL;
if (stub_types[i] != NO_ARG_RELOC)
{
@ -2406,39 +2480,38 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types)
switch (stub_types[i])
{
case R_TO_FR:
NEW_INSTRUCTION (stub_desc, STWS_RET0_M8SP);
NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FRET0);
NEW_INSTRUCTION (stub_entry, STWS_RET0_M8SP);
NEW_INSTRUCTION (stub_entry, FLDWS_M8SP_FRET0);
break;
case FR_TO_R:
NEW_INSTRUCTION (stub_desc, FSTWS_FRET0_M8SP);
NEW_INSTRUCTION (stub_desc, LDWS_M4SP_RET0);
NEW_INSTRUCTION (stub_entry, FSTWS_FRET0_M8SP);
NEW_INSTRUCTION (stub_entry, LDWS_M4SP_RET0);
break;
}
}
/* generate the ending common section for all stubs */
NEW_INSTRUCTION (stub_desc, LDW_M8SP_RP); /* restore return address */
/* XXX: can we assume this is a save return? */
NEW_INSTRUCTION (stub_desc, BV_N_0RP);
NEW_INSTRUCTION (stub_entry, BV_N_0RP);
}
return stub_sym;
}
int
hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types)
hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types, caller_ar)
bfd *abfd;
arelent *reloc_entry;
int stub_types[5];
symext_entryS caller_ar;
{
/* If the symbol is still undefined, there is */
/* no way to know if a stub is required. */
if (reloc_entry->sym_ptr_ptr[0] && reloc_entry->sym_ptr_ptr[0]->section != &bfd_und_section)
{
symext_entryS caller_ar = (symext_entryS) ELF32_HPPA_R_ARG_RELOC (reloc_entry->addend);
symext_entryS callee_ar = elf32_hppa_get_sym_extn (abfd,
reloc_entry->sym_ptr_ptr[0],
HPPA_SXT_ARG_RELOC);
@ -2519,6 +2592,8 @@ hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types)
|| stub_types[4])
{
#ifdef DETECT_STUBS
int i;
fprintf (stderr, "Stub needed for %s @ %s+0x%x: callee/caller ar=0x%x/0x%x ",
reloc_entry->sym_ptr_ptr[0]->name,
abfd->filename, reloc_entry->address,
@ -2552,13 +2627,13 @@ hppa_elf_build_long_branch_stub (abfd, output_bfd, reloc_entry, symbol, data)
unsigned *data;
{
asection *stub_sec = bfd_get_section_by_name (abfd, ".hppa_linker_stubs");
Elf32_hppa_Stub_description *stub_desc = find_stubs (abfd, stub_sec);
elf32_hppa_stub_description *stub_desc = find_stubs (abfd, stub_sec);
asymbol *stub_sym = NULL;
asymbol *target_sym = reloc_entry->sym_ptr_ptr[0];
asymbol *return_sym = NULL;
asection *output_text_section = bfd_get_section_by_name (output_bfd, ".text");
char stub_sym_name[128];
int milli = false;
elf32_hppa_stub_name_list *stub_entry;
if (!stub_sec)
{
@ -2625,14 +2700,10 @@ hppa_elf_build_long_branch_stub (abfd, output_bfd, reloc_entry, symbol, data)
bfd_set_section_alignment (abfd, stub_sec, 2);
stub_desc = new_stub (abfd, stub_sec);
add_stub (stub_desc);
}
if (!stub_desc)
{
stub_desc = new_stub (abfd, stub_sec);
add_stub (stub_desc);
}
/* allocate some space to write the stub */
@ -2650,25 +2721,31 @@ hppa_elf_build_long_branch_stub (abfd, output_bfd, reloc_entry, symbol, data)
stub_desc->stub_secp = (int *) (stub_desc->stub_contents + stub_desc->real_size);
sprintf (stub_sym_name,
"_lb_stub_%s", reloc_entry->sym_ptr_ptr[0]->name);
stub_entry = find_stub_by_name(abfd, stub_sec, stub_sym_name);
if (stub_entry)
{
stub_sym = stub_entry->sym;
/* redirect the original relocation from the old symbol (a function) */
/* to the stub (the stub calls the function). */
/* XXX do we need to change the relocation type? */
reloc_entry->sym_ptr_ptr = (asymbol **) bfd_zalloc (stub_desc->this_bfd, sizeof (asymbol *));
reloc_entry->sym_ptr_ptr[0] = stub_sym;
reloc_entry->howto = bfd_reloc_type_lookup (abfd, R_HPPA_STUB_CALL_17);
}
else
{
/* Stub does not already exist. Create a new stub. */
/* create a symbol to point to this stub */
stub_sym = bfd_make_empty_symbol (abfd);
sprintf (stub_sym_name,
"_lb_stub_%s\000", reloc_entry->sym_ptr_ptr[0]->name);
stub_sym->name = bfd_zalloc (abfd, strlen (stub_sym_name) + 1);
strcpy ((char *) stub_sym->name, stub_sym_name);
stub_sym->value = (int) stub_desc->stub_secp - (int) stub_desc->stub_contents;
stub_sym->section = stub_sec;
stub_sym->flags = BSF_LOCAL | BSF_FUNCTION;
/* create a symbol to point to the return location */
return_sym = bfd_make_empty_symbol (abfd);
sprintf (stub_sym_name,
"_lb_rtn_%s\000", reloc_entry->sym_ptr_ptr[0]->name);
return_sym->name = bfd_zalloc (abfd, strlen (stub_sym_name) + 1);
strcpy ((char *) return_sym->name, stub_sym_name);
return_sym->value = reloc_entry->address + 8;
return_sym->section = stub_sec;
return_sym->flags = BSF_LOCAL | BSF_FUNCTION;
stub_entry = add_stub_by_name(abfd, stub_sec, stub_sym);
/* redirect the original relocation from the old symbol (a function) */
/* to the stub (the stub calls the function). */
@ -2687,53 +2764,54 @@ hppa_elf_build_long_branch_stub (abfd, output_bfd, reloc_entry, symbol, data)
/* 1. initialization for the call. */
NEW_INSTRUCTION(stub_desc, LDSID_31_RP);
NEW_INSTRUCTION(stub_desc, MTSP_RP_SR0);
NEW_INSTRUCTION(stub_entry, LDSID_31_RP);
NEW_INSTRUCTION(stub_entry, MTSP_RP_SR0);
if ( !milli )
{
NEW_INSTRUCTION(stub_desc, COPY_31_2);
NEW_INSTRUCTION(stub_entry, COPY_31_2);
NEW_INSTRUCTION(stub_desc, LDIL_XXX_31);
NEW_INSTRUCTION(stub_entry, LDIL_XXX_31);
hppa_elf_stub_reloc (stub_desc,
abfd, /* the output bfd */
target_sym, /* the target symbol */
CURRENT_STUB_OFFSET(stub_desc), /* offset in stub buffer */
CURRENT_STUB_OFFSET(stub_entry), /* offset in stub buffer */
R_HPPA_L21);
/* 2. Make the call. */
NEW_INSTRUCTION(stub_desc,BE_N_XXX_0_31);
NEW_INSTRUCTION(stub_entry,BE_N_XXX_0_31);
hppa_elf_stub_reloc (stub_desc,
abfd, /* the output bfd */
target_sym, /* the target symbol */
CURRENT_STUB_OFFSET(stub_desc), /* offset in stub buffer */
CURRENT_STUB_OFFSET(stub_entry), /* offset in stub buffer */
R_HPPA_ABS_CALL_R17);
/* 3. Branch back to the original location. */
/* (accomplished with the COPY_31_2 instruction) */
}
else
{
NEW_INSTRUCTION(stub_desc, STW_31_M24SP);
NEW_INSTRUCTION(stub_desc, LDIL_XXX_RP);
NEW_INSTRUCTION(stub_entry, STW_31_M24SP);
NEW_INSTRUCTION(stub_entry, LDIL_XXX_RP);
hppa_elf_stub_reloc (stub_desc,
abfd, /* the output bfd */
target_sym, /* the target symbol */
CURRENT_STUB_OFFSET(stub_desc), /* offset in stub buffer */
CURRENT_STUB_OFFSET(stub_entry), /* offset in stub buffer */
R_HPPA_L21);
/* 2. Make the call. */
NEW_INSTRUCTION(stub_desc,BLE_XXX_0_RP);
NEW_INSTRUCTION(stub_entry,BLE_XXX_0_RP);
hppa_elf_stub_reloc (stub_desc,
abfd, /* the output bfd */
target_sym, /* the target symbol */
CURRENT_STUB_OFFSET(stub_desc), /* offset in stub buffer */
CURRENT_STUB_OFFSET(stub_entry), /* offset in stub buffer */
R_HPPA_ABS_CALL_R17);
NEW_INSTRUCTION(stub_desc,COPY_31_2);
NEW_INSTRUCTION(stub_entry,COPY_31_2);
/* 3. Branch back to the original location. */
NEW_INSTRUCTION(stub_desc, LDW_M24SP_RP);
NEW_INSTRUCTION(stub_desc, BV_N_0RP);
NEW_INSTRUCTION(stub_entry, LDW_M24SP_RP);
NEW_INSTRUCTION(stub_entry, BV_N_0RP);
}
}
return stub_sym;
@ -2824,24 +2902,27 @@ hppa_elf_stub_check (abfd, output_bfd, input_section, reloc_entry, symbol, hit_d
case R_HPPA_PCREL_CALL_LR21: /* LR(Symbol - PC, Addend) 21 */
case R_HPPA_PCREL_CALL_RR14: /* RR(Symbol - PC, Addend) 14 */
case R_HPPA_PCREL_CALL_RR17: /* RR(Symbol - PC, Addend) 17 */
if (hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types))
{
symext_entryS caller_ar = (symext_entryS) ELF32_HGPPA_R_ARG_RELOC (reloc_entry->addend);
if (hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types, caller_ar))
{
/* generate a stub */
return hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry,
stub_types);
return hppa_elf_build_arg_reloc_stub (abfd, output_bfd,
reloc_entry, stub_types);
}
if (hppa_elf_long_branch_needed_p (abfd, input_section, reloc_entry, symbol,*(unsigned *)hit_data))
if (hppa_elf_long_branch_needed_p (abfd, input_section, reloc_entry,
symbol, *(unsigned *)hit_data))
{
/* generate a stub */
return hppa_elf_build_long_branch_stub (abfd, output_bfd,
reloc_entry, symbol,
(unsigned *)hit_data);
}
}
break;
default:
break;
}
return reloc_entry->sym_ptr_ptr[0];
}
@ -2863,10 +2944,10 @@ hppa_look_for_stubs_in_section (stub_bfd, abfd, output_bfd, asec, syms, new_sym_
int new_cnt = 0;
int new_max = 0;
/* Relocations are in different places depending on whether this is */
/* an output section or an input section. Also, the relocations are */
/* in different forms. Sigh. */
/* Luckily, we have bfd_canonicalize_reloc() to straighten this out for us. */
/* Relocations are in different places depending on whether this is
an output section or an input section. Also, the relocations are
in different forms. Sigh. Luckily, we have
bfd_canonicalize_reloc() to straighten this out for us. */
/* if ( asec->orelocation || asec->relocation ) { */
if (asec->reloc_count > 0)
@ -2927,11 +3008,13 @@ hppa_look_for_stubs_in_section (stub_bfd, abfd, output_bfd, asec, syms, new_sym_
case R_HPPA_PCREL_CALL_LR21: /* LR(Symbol - PC, Addend) 21 */
case R_HPPA_PCREL_CALL_RR14: /* RR(Symbol - PC, Addend) 14 */
case R_HPPA_PCREL_CALL_RR17: /* RR(Symbol - PC, Addend) 17 */
if (hppa_elf_arg_reloc_needed_p (abfd, rle, stub_types))
{
symext_entryS caller_ar = (symext_entryS) ELF32_HPPA_R_ARG_RELOC (rle->addend);
if (hppa_elf_arg_reloc_needed_p (abfd, rle, stub_types,
caller_ar))
{
/* generate a stub */
/* keep track of the new symbol */
asymbol *r;
if (new_cnt == new_max)
@ -2939,27 +3022,29 @@ hppa_look_for_stubs_in_section (stub_bfd, abfd, output_bfd, asec, syms, new_sym_
new_max += STUB_SYM_BUFFER_INC;
new_syms = (asymbol *) realloc (new_syms, new_max * sizeof (asymbol));
}
r = hppa_elf_build_arg_reloc_stub (stub_bfd, output_bfd, rle,
stub_types);
r = hppa_elf_build_arg_reloc_stub (stub_bfd, output_bfd,
rle, stub_types);
new_syms[new_cnt++] = *r;
}
/* We need to retrieve the section contents to check for */
/* long branch stubs. */
/* We need to retrieve the section contents to check for
plabel stubs. */
{
unsigned insn;
bfd_get_section_contents(abfd, asec, &insn, rle->address, sizeof(insn));
if (hppa_elf_long_branch_needed_p (abfd, asec, rle, rle->sym_ptr_ptr[0], insn))
bfd_get_section_contents (abfd, asec, &insn, rle->address,
sizeof(insn));
if (hppa_elf_long_branch_needed_p (abfd, asec, rle,
rle->sym_ptr_ptr[0],
insn))
{
/* generate a stub */
/* keep track of the new symbol */
asymbol *r;
if (new_cnt == new_max)
{
new_max += STUB_SYM_BUFFER_INC;
new_syms = (asymbol *) realloc (new_syms, new_max * sizeof (asymbol));
new_syms = (asymbol *) realloc (new_syms, (new_max * sizeof (asymbol)));
}
r = hppa_elf_build_long_branch_stub (stub_bfd,
output_bfd,
@ -2969,6 +3054,48 @@ hppa_look_for_stubs_in_section (stub_bfd, abfd, output_bfd, asec, syms, new_sym_
new_syms[new_cnt++] = *r;
}
}
}
break;
/* Plabels are designed to allow code pointers to be
passed between spaces. These relocations correspond
to the P%, LP%, and RP% field selectors. */
case R_HPPA_PLABEL_32: /* F(Plabel(Symbol,Addend),0) 32 */
case R_HPPA_PLABEL_11: /* F(Plabel(Symbol,Addend),0) 11 */
case R_HPPA_PLABEL_14: /* F(Plabel(Symbol,Addend),0) 14 */
case R_HPPA_PLABEL_L21: /* L(Plabel(Symbol,Addend),0) 21 */
case R_HPPA_PLABEL_R11: /* R(Plabel(Symbol,Addend),0) 11 */
case R_HPPA_PLABEL_R14: /* R(Plabel(Symbol,Addend),0) 14 */
/* We need to retrieve the section contents to check for
long branch stubs. */
{
/* On a plabel relocation, assume the arguments of the
caller are set up in general registers. */
/* 0x155 = ARGW0=CR,ARGW1=GR,ARGW2=GR,RETVAL=GR */
symext_entryS caller_ar = (symext_entryS) 0x155;
if (hppa_elf_arg_reloc_needed_p (abfd, rle, stub_types,
caller_ar))
{
/* generate a plabel stub */
/* keep track of the new symbol */
asymbol *r;
if (new_cnt == new_max)
{
new_max += STUB_SYM_BUFFER_INC;
new_syms = (asymbol *) realloc (new_syms,
(new_max
* sizeof (asymbol)));
}
r = hppa_elf_build_arg_reloc_stub (stub_bfd,
output_bfd,
rle,
stub_types);
new_syms[new_cnt++] = *r;
}
}
break;
default:
@ -3026,7 +3153,7 @@ DEFUN (hppa_elf_get_section_contents, (abfd, section, location, offset, count),
/* section contents in memory rather than on disk. */
if (strcmp (section->name, ".hppa_linker_stubs") == 0)
{
Elf32_hppa_Stub_description *stub_desc = find_stubs (abfd, section);
elf32_hppa_stub_description *stub_desc = find_stubs (abfd, section);
if (count == 0)
return true;
@ -3053,7 +3180,8 @@ DEFUN (hppa_elf_get_section_contents, (abfd, section, location, offset, count),
return (true);
}
else
return bfd_generic_get_section_contents (abfd, section, location, offset, count);
return bfd_generic_get_section_contents (abfd, section, location, offset,
count);
}
static void
@ -3097,7 +3225,7 @@ static int elf32_hppa_symextn_map_size;
static boolean
DEFUN (elf32_hppa_backend_symbol_table_processing, (abfd, esyms,symcnt),
bfd * abfd AND
elf32_symbol_type *esyms AND
elf_symbol_type *esyms AND
int symcnt)
{
Elf32_Internal_Shdr *symextn_hdr = bfd_elf_find_section (abfd, SYMEXTN_SECTION_NAME);
@ -3340,5 +3468,6 @@ DEFUN (elf32_hppa_backend_section_from_bfd_section, (abfd, hdr, asect),
#define TARGET_BIG_SYM bfd_elf32_hppa_vec
#define TARGET_BIG_NAME "elf32-hppa"
#define ELF_ARCH bfd_arch_hppa
#define ELF_MAXPAGESIZE 0x1000
#include "elf32-target.h"