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 void
DEFUN (elf_hppa_tc_symbol, (abfd, symbolP, sym_idx), DEFUN (elf_hppa_tc_symbol, (abfd, symbolP, sym_idx),
bfd * abfd AND bfd * abfd AND
elf32_symbol_type * symbolP AND elf_symbol_type * symbolP AND
int sym_idx) int sym_idx)
{ {
symext_chainS *symextP; symext_chainS *symextP;
unsigned int arg_reloc; unsigned int arg_reloc;
/* Only functions can have argument relocations. */
if (!(symbolP->symbol.flags & BSF_FUNCTION)) if (!(symbolP->symbol.flags & BSF_FUNCTION))
return; return;
if (!((symbolP->symbol.flags & BSF_EXPORT) ||
(symbolP->symbol.flags & BSF_GLOBAL)))
return;
arg_reloc = symbolP->tc_data.hppa_arg_reloc; 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 = (symext_chainS *) bfd_alloc (abfd, sizeof (symext_chainS) * 2);
symextP[0].entry = ELF32_HPPA_SX_WORD (HPPA_SXT_SYMNDX, sym_idx); 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; break;
case HPPA_SXT_ARG_RELOC: 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; retval = (symext_entryS) esymP->tc_data.hppa_arg_reloc;
break; break;
@ -1812,58 +1814,67 @@ elf32_hppa_get_sym_extn (abfd, sym, type)
return retval; return retval;
} }
typedef struct elf32_hppa_stub_name_list_struct
{
/* 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 typedef struct elf32_hppa_stub_description_struct
{ {
bfd *this_bfd; /* bfd to which this stub */ struct elf32_hppa_stub_description_struct *next;
/* applies */ bfd *this_bfd; /* bfd to which this stub applies */
asection *stub_sec; /* stub section for this bfd */ asection *stub_sec; /* stub section for this bfd */
unsigned relocs_allocated_cnt; /* count of relocations for this stub section */ unsigned relocs_allocated_cnt; /* count of relocations for this stub section */
unsigned real_size; unsigned real_size;
unsigned allocated_size; unsigned allocated_size;
int *stub_secp; /* pointer to the next available location in the buffer */ int *stub_secp; /* pointer to the next available location in the buffer */
char *stub_contents; /* contents of the stubs for this bfd */ 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; static elf32_hppa_stub_description *elf_hppa_stub_rootP;
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;
/* Locate the stub section information for the given bfd. */ /* Locate the stub section information for the given bfd. */
static Elf32_hppa_Stub_description * static elf32_hppa_stub_description *
find_stubs (abfd, stub_sec) find_stubs (abfd, stub_sec)
bfd *abfd; bfd *abfd;
asection *stub_sec; asection *stub_sec;
{ {
Elf32_hppa_Stub_list *stubP; elf32_hppa_stub_description *stubP;
for (stubP = elf_hppa_stub_rootP; stubP; stubP = stubP->next) for (stubP = elf_hppa_stub_rootP; stubP; stubP = stubP->next)
{ {
if (stubP->stub->this_bfd == abfd if (stubP->this_bfd == abfd
&& stubP->stub->stub_sec == stub_sec) && stubP->stub_sec == stub_sec)
return stubP->stub; 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) new_stub (abfd, stub_sec)
bfd *abfd; bfd *abfd;
asection *stub_sec; 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) if (stub)
return 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->this_bfd = abfd;
stub->stub_sec = stub_sec; stub->stub_sec = stub_sec;
stub->real_size = 0; stub->real_size = 0;
@ -1871,37 +1882,82 @@ new_stub (abfd, stub_sec)
stub->stub_contents = NULL; stub->stub_contents = NULL;
stub->stub_secp = NULL; stub->stub_secp = NULL;
return stub; stub->next = elf_hppa_stub_rootP;
} elf_hppa_stub_rootP = 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;
}
} }
else else
{ {
bfd_error = no_memory; 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 #define ARGUMENTS 0
@ -1966,15 +2022,15 @@ static CONST char retval_mismatches[6][6] =
/* CALLER NONE */ /* CALLER NONE */
{NO_ARG_RELOC, NO_ARG_RELOC, NO_ARG_RELOC, ARG_RELOC_ERR, NO_ARG_RELOC, NO_ARG_RELOC}, {NO_ARG_RELOC, NO_ARG_RELOC, NO_ARG_RELOC, ARG_RELOC_ERR, NO_ARG_RELOC, NO_ARG_RELOC},
/* CALLER GR */ /* 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 */ /* 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 */ /* CALLER FU */
{ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR}, {ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR},
/* CALLER DBL01 */ /* 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 */ /* 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 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 EXTRACT_ARBITS(ar,which) ((ar) >> (8-(which*2))) & 3
#define NEW_INSTRUCTION(desc,insn) \ #define NEW_INSTRUCTION(entry,insn) \
*((desc)->stub_secp)++ = (insn); \ *((entry)->stub_desc->stub_secp)++ = (insn); \
(desc)->real_size += sizeof(int); \ (entry)->stub_desc->real_size += sizeof(int); \
bfd_set_section_size((desc)->this_bfd,(desc)->stub_sec,(desc)->real_size); (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) \ #define CURRENT_STUB_OFFSET(entry) \
((int)(desc)->stub_secp - (int)(desc)->stub_contents - 4) ((int)(entry)->stub_desc->stub_secp - (int)(entry)->stub_desc->stub_contents - 4)
static boolean stubs_finished = false; static boolean stubs_finished = false;
@ -2011,7 +2070,7 @@ hppa_elf_stub_finish (output_bfd)
bfd *output_bfd; bfd *output_bfd;
{ {
extern bfd_error_vector_type bfd_error_vector; 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 */ /* All the stubs have been built. Finish up building */
/* stub section. Apply relocations to the section. */ /* 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) 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"); asection *stub_sec = bfd_get_section_by_name (stub_bfd, ".hppa_linker_stubs");
bfd_size_type reloc_size; bfd_size_type reloc_size;
arelent **reloc_vector; 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_size = bfd_get_reloc_upper_bound (stub_bfd, stub_sec);
reloc_vector = (arelent **) alloca (reloc_size); reloc_vector = (arelent **) alloca (reloc_size);
@ -2050,7 +2109,7 @@ hppa_elf_stub_finish (output_bfd)
bfd_reloc_status_type r = bfd_reloc_status_type r =
bfd_perform_relocation (stub_bfd, bfd_perform_relocation (stub_bfd,
*parent, *parent,
stub_list->stub->stub_contents, stub_list->stub_contents,
stub_sec, 0); stub_sec, 0);
@ -2078,9 +2137,9 @@ hppa_elf_stub_finish (output_bfd)
bfd_set_section_contents (output_bfd, bfd_set_section_contents (output_bfd,
stub_sec, stub_sec,
stub_list->stub->stub_contents, stub_list->stub_contents,
0, 0,
stub_list->stub->real_size); stub_list->real_size);
free (reloc_vector); free (reloc_vector);
} }
@ -2093,7 +2152,7 @@ hppa_elf_stub_branch_reloc (stub_desc, /* the bfd */
output_bfd, /* the output bfd */ output_bfd, /* the output bfd */
target_sym, /* the target symbol */ target_sym, /* the target symbol */
offset) /* the offset within the stub buffer (pre-calculated) */ offset) /* the offset within the stub buffer (pre-calculated) */
Elf32_hppa_Stub_description *stub_desc; elf32_hppa_stub_description *stub_desc;
bfd *output_bfd; bfd *output_bfd;
asymbol *target_sym; asymbol *target_sym;
int offset; int offset;
@ -2141,7 +2200,7 @@ hppa_elf_stub_reloc (stub_desc, /* the bfd */
target_sym, /* the target symbol */ target_sym, /* the target symbol */
offset, /* the offset within the stub buffer (pre-calculated) */ offset, /* the offset within the stub buffer (pre-calculated) */
type) type)
Elf32_hppa_Stub_description *stub_desc; elf32_hppa_stub_description *stub_desc;
bfd *output_bfd; bfd *output_bfd;
asymbol *target_sym; asymbol *target_sym;
int offset; int offset;
@ -2196,12 +2255,13 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types)
int stub_types[5]; int stub_types[5];
{ {
asection *stub_sec = bfd_get_section_by_name (abfd, ".hppa_linker_stubs"); 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 *stub_sym = NULL;
asymbol *target_sym = reloc_entry->sym_ptr_ptr[0]; asymbol *target_sym = reloc_entry->sym_ptr_ptr[0];
asection *output_text_section = bfd_get_section_by_name (output_bfd, ".text"); asection *output_text_section = bfd_get_section_by_name (output_bfd, ".text");
int i; int i;
char stub_sym_name[128]; char stub_sym_name[128];
elf32_hppa_stub_name_list *stub_entry;
if (!stub_sec) 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; stub_sec->output_offset = 0;
bfd_set_section_alignment (abfd, stub_sec, 2); bfd_set_section_alignment (abfd, stub_sec, 2);
stub_desc = new_stub (abfd, stub_sec); stub_desc = new_stub (abfd, stub_sec);
add_stub (stub_desc);
} }
/* make sure we have a stub descriptor structure */ /* make sure we have a stub descriptor structure */
if (!stub_desc) if (!stub_desc)
{
stub_desc = new_stub (abfd, stub_sec); stub_desc = new_stub (abfd, stub_sec);
add_stub (stub_desc);
}
/* allocate some space to write the stub */ /* 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); 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, 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, reloc_entry->sym_ptr_ptr[0]->name,
stub_types[0], stub_types[1], stub_types[2], stub_types[3], stub_types[4]); 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); stub_sym->name = bfd_zalloc (abfd, strlen (stub_sym_name) + 1);
strcpy ((char *) stub_sym->name, stub_sym_name); strcpy ((char *) stub_sym->name, stub_sym_name);
stub_sym->value = (int) stub_desc->stub_secp - (int) stub_desc->stub_contents; stub_sym->value = (int) stub_desc->stub_secp - (int) stub_desc->stub_contents;
stub_sym->section = stub_sec; stub_sym->section = stub_sec;
stub_sym->flags = BSF_LOCAL | BSF_FUNCTION; 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) */ /* redirect the original relocation from the old symbol (a function) */
/* to the stub (the stub calls the 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 */ /* 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 */ /* generate the code to move the arguments around */
for (i = ARG0; i < ARG3; i++) 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) switch (i)
{ {
case ARG0: case ARG0:
NEW_INSTRUCTION (stub_desc, STWS_ARG0_M8SP); NEW_INSTRUCTION (stub_entry, STWS_ARG0_M8SP);
NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG0); NEW_INSTRUCTION (stub_entry, FLDWS_M8SP_FARG0);
break; break;
case ARG1: case ARG1:
NEW_INSTRUCTION (stub_desc, STWS_ARG1_M8SP); NEW_INSTRUCTION (stub_entry, STWS_ARG1_M8SP);
NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG1); NEW_INSTRUCTION (stub_entry, FLDWS_M8SP_FARG1);
break; break;
case ARG2: case ARG2:
NEW_INSTRUCTION (stub_desc, STWS_ARG2_M8SP); NEW_INSTRUCTION (stub_entry, STWS_ARG2_M8SP);
NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG2); NEW_INSTRUCTION (stub_entry, FLDWS_M8SP_FARG2);
break; break;
case ARG3: case ARG3:
NEW_INSTRUCTION (stub_desc, STWS_ARG3_M8SP); NEW_INSTRUCTION (stub_entry, STWS_ARG3_M8SP);
NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG3); NEW_INSTRUCTION (stub_entry, FLDWS_M8SP_FARG3);
break; break;
} }
continue; continue;
@ -2297,9 +2368,9 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types)
switch (i) switch (i)
{ {
case ARG0: case ARG0:
NEW_INSTRUCTION(stub_desc, STWS_ARG0_M4SP); NEW_INSTRUCTION(stub_entry, STWS_ARG0_M4SP);
NEW_INSTRUCTION(stub_desc, STWS_ARG1_M8SP); NEW_INSTRUCTION(stub_entry, STWS_ARG1_M8SP);
NEW_INSTRUCTION(stub_desc, FLDDS_M8SP_FARG1); NEW_INSTRUCTION(stub_entry, FLDDS_M8SP_FARG1);
break; break;
default: default:
AR_WARN(stub_types[i],i); 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) switch (i)
{ {
case ARG2: case ARG2:
NEW_INSTRUCTION(stub_desc, STWS_ARG2_M4SP); NEW_INSTRUCTION(stub_entry, STWS_ARG2_M4SP);
NEW_INSTRUCTION(stub_desc, STWS_ARG3_M8SP); NEW_INSTRUCTION(stub_entry, STWS_ARG3_M8SP);
NEW_INSTRUCTION(stub_desc, FLDDS_M8SP_FARG3); NEW_INSTRUCTION(stub_entry, FLDDS_M8SP_FARG3);
break; break;
default: default:
AR_WARN(stub_types[i],i); 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) switch (i)
{ {
case ARG0: case ARG0:
NEW_INSTRUCTION (stub_desc, FSTWS_FARG0_M8SP); NEW_INSTRUCTION (stub_entry, FSTWS_FARG0_M8SP);
NEW_INSTRUCTION (stub_desc, LDWS_M4SP_ARG0); NEW_INSTRUCTION (stub_entry, LDWS_M4SP_ARG0);
break; break;
case ARG1: case ARG1:
NEW_INSTRUCTION (stub_desc, FSTWS_FARG1_M8SP); NEW_INSTRUCTION (stub_entry, FSTWS_FARG1_M8SP);
NEW_INSTRUCTION (stub_desc, LDWS_M4SP_ARG1); NEW_INSTRUCTION (stub_entry, LDWS_M4SP_ARG1);
break; break;
case ARG2: case ARG2:
NEW_INSTRUCTION (stub_desc, FSTWS_FARG2_M8SP); NEW_INSTRUCTION (stub_entry, FSTWS_FARG2_M8SP);
NEW_INSTRUCTION (stub_desc, LDWS_M4SP_ARG2); NEW_INSTRUCTION (stub_entry, LDWS_M4SP_ARG2);
break; break;
case ARG3: case ARG3:
NEW_INSTRUCTION (stub_desc, FSTWS_FARG3_M8SP); NEW_INSTRUCTION (stub_entry, FSTWS_FARG3_M8SP);
NEW_INSTRUCTION (stub_desc, LDWS_M4SP_ARG3); NEW_INSTRUCTION (stub_entry, LDWS_M4SP_ARG3);
break; break;
} }
continue; continue;
@ -2347,9 +2418,9 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types)
switch (i) switch (i)
{ {
case ARG0: case ARG0:
NEW_INSTRUCTION(stub_desc, FSTDS_FARG1_M8SP); NEW_INSTRUCTION(stub_entry, FSTDS_FARG1_M8SP);
NEW_INSTRUCTION(stub_desc, LDWS_M4SP_ARG0); NEW_INSTRUCTION(stub_entry, LDWS_M4SP_ARG0);
NEW_INSTRUCTION(stub_desc, LDWS_M8SP_ARG1); NEW_INSTRUCTION(stub_entry, LDWS_M8SP_ARG1);
break; break;
default: default:
AR_WARN(stub_types[i],i); 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) switch (i)
{ {
case ARG2: case ARG2:
NEW_INSTRUCTION(stub_desc, FSTDS_FARG3_M8SP); NEW_INSTRUCTION(stub_entry, FSTDS_FARG3_M8SP);
NEW_INSTRUCTION(stub_desc, LDWS_M4SP_ARG2); NEW_INSTRUCTION(stub_entry, LDWS_M4SP_ARG2);
NEW_INSTRUCTION(stub_desc, LDWS_M8SP_ARG3); NEW_INSTRUCTION(stub_entry, LDWS_M8SP_ARG3);
break; break;
default: default:
AR_WARN(stub_types[i],i); 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 */ /* 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. */ /* Branch to the target function. */
/* (Make it a long call, so we do not */ /* (Make it a long call, so we do not */
/* have to worry about generating a */ /* have to worry about generating a */
/* long call stub.) */ /* long call stub.) */
NEW_INSTRUCTION(stub_desc, LDIL_XXX_31); NEW_INSTRUCTION(stub_entry, LDIL_XXX_31);
hppa_elf_stub_reloc (stub_desc, hppa_elf_stub_reloc (stub_entry->stub_desc,
abfd, /* the output bfd */ abfd, /* the output bfd */
target_sym, /* the target symbol */ 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); R_HPPA_L21);
NEW_INSTRUCTION(stub_desc,BLE_XXX_0_31); NEW_INSTRUCTION(stub_entry,BLE_XXX_0_31);
hppa_elf_stub_reloc (stub_desc, hppa_elf_stub_reloc (stub_entry->stub_desc,
abfd, /* the output bfd */ abfd, /* the output bfd */
target_sym, /* the target symbol */ 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); 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 */ /* generate the code to move the return value around */
NEW_INSTRUCTION (stub_entry, LDW_M8SP_RP); /* restore return address */
i = RETVAL; i = RETVAL;
if (stub_types[i] != NO_ARG_RELOC) 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]) switch (stub_types[i])
{ {
case R_TO_FR: case R_TO_FR:
NEW_INSTRUCTION (stub_desc, STWS_RET0_M8SP); NEW_INSTRUCTION (stub_entry, STWS_RET0_M8SP);
NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FRET0); NEW_INSTRUCTION (stub_entry, FLDWS_M8SP_FRET0);
break; break;
case FR_TO_R: case FR_TO_R:
NEW_INSTRUCTION (stub_desc, FSTWS_FRET0_M8SP); NEW_INSTRUCTION (stub_entry, FSTWS_FRET0_M8SP);
NEW_INSTRUCTION (stub_desc, LDWS_M4SP_RET0); NEW_INSTRUCTION (stub_entry, LDWS_M4SP_RET0);
break; break;
} }
} }
/* generate the ending common section for all stubs */ /* 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? */ /* 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; return stub_sym;
} }
int 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; bfd *abfd;
arelent *reloc_entry; arelent *reloc_entry;
int stub_types[5]; int stub_types[5];
symext_entryS caller_ar;
{ {
/* If the symbol is still undefined, there is */ /* If the symbol is still undefined, there is */
/* no way to know if a stub is required. */ /* 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) 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, symext_entryS callee_ar = elf32_hppa_get_sym_extn (abfd,
reloc_entry->sym_ptr_ptr[0], reloc_entry->sym_ptr_ptr[0],
HPPA_SXT_ARG_RELOC); HPPA_SXT_ARG_RELOC);
@ -2519,6 +2592,8 @@ hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types)
|| stub_types[4]) || stub_types[4])
{ {
#ifdef DETECT_STUBS #ifdef DETECT_STUBS
int i;
fprintf (stderr, "Stub needed for %s @ %s+0x%x: callee/caller ar=0x%x/0x%x ", fprintf (stderr, "Stub needed for %s @ %s+0x%x: callee/caller ar=0x%x/0x%x ",
reloc_entry->sym_ptr_ptr[0]->name, reloc_entry->sym_ptr_ptr[0]->name,
abfd->filename, reloc_entry->address, abfd->filename, reloc_entry->address,
@ -2552,13 +2627,13 @@ hppa_elf_build_long_branch_stub (abfd, output_bfd, reloc_entry, symbol, data)
unsigned *data; unsigned *data;
{ {
asection *stub_sec = bfd_get_section_by_name (abfd, ".hppa_linker_stubs"); 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 *stub_sym = NULL;
asymbol *target_sym = reloc_entry->sym_ptr_ptr[0]; 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"); asection *output_text_section = bfd_get_section_by_name (output_bfd, ".text");
char stub_sym_name[128]; char stub_sym_name[128];
int milli = false; int milli = false;
elf32_hppa_stub_name_list *stub_entry;
if (!stub_sec) 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); bfd_set_section_alignment (abfd, stub_sec, 2);
stub_desc = new_stub (abfd, stub_sec); stub_desc = new_stub (abfd, stub_sec);
add_stub (stub_desc);
} }
if (!stub_desc) if (!stub_desc)
{
stub_desc = new_stub (abfd, stub_sec); stub_desc = new_stub (abfd, stub_sec);
add_stub (stub_desc);
}
/* allocate some space to write the stub */ /* 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); 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 */ /* create a symbol to point to this stub */
stub_sym = bfd_make_empty_symbol (abfd); 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); stub_sym->name = bfd_zalloc (abfd, strlen (stub_sym_name) + 1);
strcpy ((char *) stub_sym->name, stub_sym_name); strcpy ((char *) stub_sym->name, stub_sym_name);
stub_sym->value = (int) stub_desc->stub_secp - (int) stub_desc->stub_contents; stub_sym->value = (int) stub_desc->stub_secp - (int) stub_desc->stub_contents;
stub_sym->section = stub_sec; stub_sym->section = stub_sec;
stub_sym->flags = BSF_LOCAL | BSF_FUNCTION; stub_sym->flags = BSF_LOCAL | BSF_FUNCTION;
stub_entry = add_stub_by_name(abfd, stub_sec, stub_sym);
/* 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;
/* redirect the original relocation from the old symbol (a function) */ /* redirect the original relocation from the old symbol (a function) */
/* to the stub (the stub calls the 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. */ /* 1. initialization for the call. */
NEW_INSTRUCTION(stub_desc, LDSID_31_RP); NEW_INSTRUCTION(stub_entry, LDSID_31_RP);
NEW_INSTRUCTION(stub_desc, MTSP_RP_SR0); NEW_INSTRUCTION(stub_entry, MTSP_RP_SR0);
if ( !milli ) 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, hppa_elf_stub_reloc (stub_desc,
abfd, /* the output bfd */ abfd, /* the output bfd */
target_sym, /* the target symbol */ 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); R_HPPA_L21);
/* 2. Make the call. */ /* 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, hppa_elf_stub_reloc (stub_desc,
abfd, /* the output bfd */ abfd, /* the output bfd */
target_sym, /* the target symbol */ 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); R_HPPA_ABS_CALL_R17);
/* 3. Branch back to the original location. */ /* 3. Branch back to the original location. */
/* (accomplished with the COPY_31_2 instruction) */ /* (accomplished with the COPY_31_2 instruction) */
} }
else else
{ {
NEW_INSTRUCTION(stub_desc, STW_31_M24SP); NEW_INSTRUCTION(stub_entry, STW_31_M24SP);
NEW_INSTRUCTION(stub_desc, LDIL_XXX_RP); NEW_INSTRUCTION(stub_entry, LDIL_XXX_RP);
hppa_elf_stub_reloc (stub_desc, hppa_elf_stub_reloc (stub_desc,
abfd, /* the output bfd */ abfd, /* the output bfd */
target_sym, /* the target symbol */ 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); R_HPPA_L21);
/* 2. Make the call. */ /* 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, hppa_elf_stub_reloc (stub_desc,
abfd, /* the output bfd */ abfd, /* the output bfd */
target_sym, /* the target symbol */ 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); 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. */ /* 3. Branch back to the original location. */
NEW_INSTRUCTION(stub_desc, LDW_M24SP_RP); NEW_INSTRUCTION(stub_entry, LDW_M24SP_RP);
NEW_INSTRUCTION(stub_desc, BV_N_0RP); NEW_INSTRUCTION(stub_entry, BV_N_0RP);
}
} }
return stub_sym; return stub_sym;
@ -2809,10 +2887,10 @@ hppa_elf_stub_check (abfd, output_bfd, input_section, reloc_entry, symbol, hit_d
case R_HPPA_PCREL_CALL_14: /* Symbol - PC + Addend 14 */ case R_HPPA_PCREL_CALL_14: /* Symbol - PC + Addend 14 */
case R_HPPA_PCREL_CALL_17: /* Symbol - PC + Addend 17 */ case R_HPPA_PCREL_CALL_17: /* Symbol - PC + Addend 17 */
case R_HPPA_PCREL_CALL_12: /* Symbol - PC + Addend 12 */ case R_HPPA_PCREL_CALL_12: /* Symbol - PC + Addend 12 */
case R_HPPA_PCREL_CALL_L21:/* L (Symbol - PC, Addend) 21 */ case R_HPPA_PCREL_CALL_L21: /* L (Symbol - PC, Addend) 21 */
case R_HPPA_PCREL_CALL_R11:/* R (Symbol - PC, Addend) 11 */ case R_HPPA_PCREL_CALL_R11: /* R (Symbol - PC, Addend) 11 */
case R_HPPA_PCREL_CALL_R14:/* R (Symbol - PC, Addend) 14 */ case R_HPPA_PCREL_CALL_R14: /* R (Symbol - PC, Addend) 14 */
case R_HPPA_PCREL_CALL_R17:/* R (Symbol - PC, Addend) 17 */ case R_HPPA_PCREL_CALL_R17: /* R (Symbol - PC, Addend) 17 */
case R_HPPA_PCREL_CALL_LS21: /* LS(Symbol - PC, Addend) 21 */ case R_HPPA_PCREL_CALL_LS21: /* LS(Symbol - PC, Addend) 21 */
case R_HPPA_PCREL_CALL_RS11: /* RS(Symbol - PC, Addend) 11 */ case R_HPPA_PCREL_CALL_RS11: /* RS(Symbol - PC, Addend) 11 */
case R_HPPA_PCREL_CALL_RS14: /* RS(Symbol - PC, Addend) 14 */ case R_HPPA_PCREL_CALL_RS14: /* RS(Symbol - PC, Addend) 14 */
@ -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_LR21: /* LR(Symbol - PC, Addend) 21 */
case R_HPPA_PCREL_CALL_RR14: /* RR(Symbol - PC, Addend) 14 */ case R_HPPA_PCREL_CALL_RR14: /* RR(Symbol - PC, Addend) 14 */
case R_HPPA_PCREL_CALL_RR17: /* RR(Symbol - PC, Addend) 17 */ 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 */ /* generate a stub */
return hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, return hppa_elf_build_arg_reloc_stub (abfd, output_bfd,
stub_types); 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 */ /* generate a stub */
return hppa_elf_build_long_branch_stub (abfd, output_bfd, return hppa_elf_build_long_branch_stub (abfd, output_bfd,
reloc_entry, symbol, reloc_entry, symbol,
(unsigned *)hit_data); (unsigned *)hit_data);
} }
}
break; break;
default: default:
break; break;
} }
return reloc_entry->sym_ptr_ptr[0]; 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_cnt = 0;
int new_max = 0; int new_max = 0;
/* Relocations are in different places depending on whether this is */ /* Relocations are in different places depending on whether this is
/* an output section or an input section. Also, the relocations are */ an output section or an input section. Also, the relocations are
/* in different forms. Sigh. */ in different forms. Sigh. Luckily, we have
/* Luckily, we have bfd_canonicalize_reloc() to straighten this out for us. */ bfd_canonicalize_reloc() to straighten this out for us. */
/* if ( asec->orelocation || asec->relocation ) { */ /* if ( asec->orelocation || asec->relocation ) { */
if (asec->reloc_count > 0) 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_LR21: /* LR(Symbol - PC, Addend) 21 */
case R_HPPA_PCREL_CALL_RR14: /* RR(Symbol - PC, Addend) 14 */ case R_HPPA_PCREL_CALL_RR14: /* RR(Symbol - PC, Addend) 14 */
case R_HPPA_PCREL_CALL_RR17: /* RR(Symbol - PC, Addend) 17 */ 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 */ /* generate a stub */
/* keep track of the new symbol */ /* keep track of the new symbol */
asymbol *r; asymbol *r;
if (new_cnt == new_max) 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_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_arg_reloc_stub (stub_bfd, output_bfd, rle, r = hppa_elf_build_arg_reloc_stub (stub_bfd, output_bfd,
stub_types); rle, stub_types);
new_syms[new_cnt++] = *r; new_syms[new_cnt++] = *r;
} }
/* We need to retrieve the section contents to check for */ /* We need to retrieve the section contents to check for
/* long branch stubs. */ plabel stubs. */
{ {
unsigned insn; unsigned insn;
bfd_get_section_contents(abfd, asec, &insn, rle->address, sizeof(insn)); bfd_get_section_contents (abfd, asec, &insn, rle->address,
if (hppa_elf_long_branch_needed_p (abfd, asec, rle, rle->sym_ptr_ptr[0], insn)) sizeof(insn));
if (hppa_elf_long_branch_needed_p (abfd, asec, rle,
rle->sym_ptr_ptr[0],
insn))
{ {
/* generate a stub */ /* generate a stub */
/* keep track of the new symbol */ /* keep track of the new symbol */
asymbol *r; asymbol *r;
if (new_cnt == new_max) if (new_cnt == new_max)
{ {
new_max += STUB_SYM_BUFFER_INC; 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, r = hppa_elf_build_long_branch_stub (stub_bfd,
output_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; 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; break;
default: default:
@ -3026,7 +3153,7 @@ DEFUN (hppa_elf_get_section_contents, (abfd, section, location, offset, count),
/* section contents in memory rather than on disk. */ /* section contents in memory rather than on disk. */
if (strcmp (section->name, ".hppa_linker_stubs") == 0) 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) if (count == 0)
return true; return true;
@ -3053,7 +3180,8 @@ DEFUN (hppa_elf_get_section_contents, (abfd, section, location, offset, count),
return (true); return (true);
} }
else 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 static void
@ -3097,7 +3225,7 @@ static int elf32_hppa_symextn_map_size;
static boolean static boolean
DEFUN (elf32_hppa_backend_symbol_table_processing, (abfd, esyms,symcnt), DEFUN (elf32_hppa_backend_symbol_table_processing, (abfd, esyms,symcnt),
bfd * abfd AND bfd * abfd AND
elf32_symbol_type *esyms AND elf_symbol_type *esyms AND
int symcnt) int symcnt)
{ {
Elf32_Internal_Shdr *symextn_hdr = bfd_elf_find_section (abfd, SYMEXTN_SECTION_NAME); 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_SYM bfd_elf32_hppa_vec
#define TARGET_BIG_NAME "elf32-hppa" #define TARGET_BIG_NAME "elf32-hppa"
#define ELF_ARCH bfd_arch_hppa #define ELF_ARCH bfd_arch_hppa
#define ELF_MAXPAGESIZE 0x1000
#include "elf32-target.h" #include "elf32-target.h"