* som.c (som_reloc_call): New function.
This commit is contained in:
parent
2212ff9277
commit
7057b78fb8
|
@ -1,5 +1,7 @@
|
||||||
Fri Nov 12 15:29:36 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
|
Fri Nov 12 15:29:36 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
|
||||||
|
|
||||||
|
* som.c (som_reloc_call): New function.
|
||||||
|
|
||||||
* som.c (som_sizeof_headers): Add missing prototype.
|
* som.c (som_sizeof_headers): Add missing prototype.
|
||||||
(som_set_arch_mach): Do not abort.
|
(som_set_arch_mach): Do not abort.
|
||||||
|
|
||||||
|
|
117
bfd/som.c
117
bfd/som.c
|
@ -149,6 +149,10 @@ static unsigned char * som_reloc_skip PARAMS ((bfd *, unsigned int,
|
||||||
static unsigned char * som_reloc_addend PARAMS ((bfd *, int, unsigned char *,
|
static unsigned char * som_reloc_addend PARAMS ((bfd *, int, unsigned char *,
|
||||||
unsigned int *,
|
unsigned int *,
|
||||||
struct reloc_queue *));
|
struct reloc_queue *));
|
||||||
|
static unsigned char * som_reloc_call PARAMS ((bfd *, unsigned char *,
|
||||||
|
unsigned int *,
|
||||||
|
arelent *, int,
|
||||||
|
struct reloc_queue *));
|
||||||
static unsigned long som_count_spaces PARAMS ((bfd *));
|
static unsigned long som_count_spaces PARAMS ((bfd *));
|
||||||
static unsigned long som_count_subspaces PARAMS ((bfd *));
|
static unsigned long som_count_subspaces PARAMS ((bfd *));
|
||||||
static int compare_syms PARAMS ((asymbol **, asymbol **));
|
static int compare_syms PARAMS ((asymbol **, asymbol **));
|
||||||
|
@ -670,6 +674,119 @@ som_reloc_addend (abfd, addend, p, subspace_reloc_sizep, queue)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle a single function call relocation. */
|
||||||
|
|
||||||
|
static unsigned char *
|
||||||
|
som_reloc_call (abfd, p, subspace_reloc_sizep, bfd_reloc, sym_num, queue)
|
||||||
|
bfd *abfd;
|
||||||
|
unsigned char *p;
|
||||||
|
unsigned int *subspace_reloc_sizep;
|
||||||
|
arelent *bfd_reloc;
|
||||||
|
int sym_num;
|
||||||
|
struct reloc_queue *queue;
|
||||||
|
{
|
||||||
|
int arg_bits = HPPA_R_ARG_RELOC (bfd_reloc->addend);
|
||||||
|
int rtn_bits = arg_bits & 0x3;
|
||||||
|
int type, done = 0;
|
||||||
|
|
||||||
|
/* You'll never believe all this is necessary to handle relocations
|
||||||
|
for function calls. Having to compute and pack the argument
|
||||||
|
relocation bits is the real nightmare.
|
||||||
|
|
||||||
|
If you're interested in how this works, just forget it. You really
|
||||||
|
do not want to know about this braindamage. */
|
||||||
|
|
||||||
|
/* First see if this can be done with a "simple" relocation. Simple
|
||||||
|
relocations have a symbol number < 0x100 and have simple encodings
|
||||||
|
of argument relocations. */
|
||||||
|
|
||||||
|
if (sym_num < 0x100)
|
||||||
|
{
|
||||||
|
switch (arg_bits)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
type = 0;
|
||||||
|
break;
|
||||||
|
case 1 << 8:
|
||||||
|
case 1 << 8 | 1:
|
||||||
|
type = 1;
|
||||||
|
break;
|
||||||
|
case 1 << 8 | 1 << 6:
|
||||||
|
case 1 << 8 | 1 << 6 | 1:
|
||||||
|
type = 2;
|
||||||
|
break;
|
||||||
|
case 1 << 8 | 1 << 6 | 1 << 4:
|
||||||
|
case 1 << 8 | 1 << 6 | 1 << 4 | 1:
|
||||||
|
type = 3;
|
||||||
|
break;
|
||||||
|
case 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2:
|
||||||
|
case 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2 | 1:
|
||||||
|
type = 4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Not one of the easy encodings. This will have to be
|
||||||
|
handled by the more complex code below. */
|
||||||
|
type = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (type != -1)
|
||||||
|
{
|
||||||
|
/* Account for the return value too. */
|
||||||
|
if (rtn_bits)
|
||||||
|
type += 5;
|
||||||
|
|
||||||
|
/* Emit a 2 byte relocation. Then see if it can be handled
|
||||||
|
with a relocation which is already in the relocation queue. */
|
||||||
|
bfd_put_8 (abfd, bfd_reloc->howto->type + type, p);
|
||||||
|
bfd_put_8 (abfd, sym_num, p + 1);
|
||||||
|
p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
|
||||||
|
done = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this could not be handled with a simple relocation, then do a hard
|
||||||
|
one. Hard relocations occur if the symbol number was too high or if
|
||||||
|
the encoding of argument relocation bits is too complex. */
|
||||||
|
if (! done)
|
||||||
|
{
|
||||||
|
/* Don't ask about these magic sequences. I took them straight
|
||||||
|
from gas-1.36 which took them from the a.out man page. */
|
||||||
|
type = rtn_bits;
|
||||||
|
if ((arg_bits >> 6 & 0xf) == 0xe)
|
||||||
|
type += 9 * 40;
|
||||||
|
else
|
||||||
|
type += (3 * (arg_bits >> 8 & 3) + (arg_bits >> 6 & 3)) * 40;
|
||||||
|
if ((arg_bits >> 2 & 0xf) == 0xe)
|
||||||
|
type += 9 * 4;
|
||||||
|
else
|
||||||
|
type += (3 * (arg_bits >> 4 & 3) + (arg_bits >> 2 & 3)) * 4;
|
||||||
|
|
||||||
|
/* Output the first two bytes of the relocation. These describe
|
||||||
|
the length of the relocation and encoding style. */
|
||||||
|
bfd_put_8 (abfd, bfd_reloc->howto->type + 10
|
||||||
|
+ 2 * (sym_num >= 0x100) + (type >= 0x100),
|
||||||
|
p);
|
||||||
|
bfd_put_8 (abfd, type, p + 1);
|
||||||
|
|
||||||
|
/* Now output the symbol index and see if this bizarre relocation
|
||||||
|
just happened to be in the relocation queue. */
|
||||||
|
if (sym_num < 0x100)
|
||||||
|
{
|
||||||
|
bfd_put_8 (abfd, sym_num, p + 2);
|
||||||
|
p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bfd_put_8 (abfd, sym_num >> 16, p + 2);
|
||||||
|
bfd_put_16 (abfd, sym_num, p + 3);
|
||||||
|
p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 5, queue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Return the logarithm of X, base 2, considering X unsigned.
|
/* Return the logarithm of X, base 2, considering X unsigned.
|
||||||
Abort if X is not a power of two -- this should never happen (FIXME:
|
Abort if X is not a power of two -- this should never happen (FIXME:
|
||||||
It will happen on corrupt executables. GDB should give an error, not
|
It will happen on corrupt executables. GDB should give an error, not
|
||||||
|
|
Loading…
Reference in New Issue