* som.c (som_write_fixups): New function.
This commit is contained in:
parent
aff9779048
commit
9d0dea6fca
2 changed files with 257 additions and 1 deletions
|
@ -1,6 +1,7 @@
|
|||
Sat Nov 13 15:27:15 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
|
||||
|
||||
* som.c (som_prep_for_fixups): New function.
|
||||
(som_write_fixups): New function.
|
||||
|
||||
Fri Nov 12 15:29:36 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
|
||||
|
||||
|
|
257
bfd/som.c
257
bfd/som.c
|
@ -67,6 +67,12 @@
|
|||
((__m_num) >= _PA_RISC1_1_ID && (__m_num) <= _PA_RISC_MAXID))
|
||||
#endif /* _PA_RISC_ID */
|
||||
|
||||
/* Size (in chars) of the temporary buffers used during fixup and string
|
||||
table writes. */
|
||||
|
||||
#define SOM_TMP_BUFSIZE 8192
|
||||
|
||||
|
||||
/* SOM allows any one of the four previous relocations to be reused
|
||||
with a "R_PREV_FIXUP" relocation entry. Since R_PREV_FIXUP
|
||||
relocations are always a single byte, using a R_PREV_FIXUP instead
|
||||
|
@ -162,7 +168,7 @@ static int som_sizeof_headers PARAMS ((bfd *, boolean));
|
|||
static boolean som_write_headers PARAMS ((bfd *));
|
||||
static boolean som_build_and_write_symbol_table PARAMS ((bfd *));
|
||||
static void som_prep_for_fixups PARAMS ((bfd *, asymbol **, unsigned long));
|
||||
|
||||
static boolean som_write_fixups PARAMS ((bfd *, unsigned long, unsigned int *));
|
||||
|
||||
static reloc_howto_type som_hppa_howto_table[] =
|
||||
{
|
||||
|
@ -1540,6 +1546,255 @@ som_prep_for_fixups (abfd, syms, num_syms)
|
|||
}
|
||||
}
|
||||
|
||||
static boolean
|
||||
som_write_fixups (abfd, current_offset, total_reloc_sizep)
|
||||
bfd *abfd;
|
||||
unsigned long current_offset;
|
||||
unsigned int *total_reloc_sizep;
|
||||
{
|
||||
unsigned int i, j;
|
||||
unsigned char *tmp_space, *p;
|
||||
unsigned int total_reloc_size = 0;
|
||||
unsigned int subspace_reloc_size = 0;
|
||||
unsigned int num_spaces = obj_som_file_hdr (abfd)->space_total;
|
||||
asection *section = abfd->sections;
|
||||
|
||||
/* Get a chunk of memory that we can use as buffer space, then throw
|
||||
away. */
|
||||
tmp_space = alloca (SOM_TMP_BUFSIZE);
|
||||
bzero (tmp_space, SOM_TMP_BUFSIZE);
|
||||
p = tmp_space;
|
||||
|
||||
/* All the fixups for a particular subspace are emitted in a single
|
||||
stream. All the subspaces for a particular space are emitted
|
||||
as a single stream.
|
||||
|
||||
So, to get all the locations correct one must iterate through all the
|
||||
spaces, for each space iterate through its subspaces and output a
|
||||
fixups stream. */
|
||||
for (i = 0; i < num_spaces; i++)
|
||||
{
|
||||
asection *subsection;
|
||||
|
||||
/* Find a space. */
|
||||
while (som_section_data (section)->is_space == 0)
|
||||
section = section->next;
|
||||
|
||||
/* Now iterate through each of its subspaces. */
|
||||
for (subsection = abfd->sections;
|
||||
subsection != NULL;
|
||||
subsection = subsection->next)
|
||||
{
|
||||
int reloc_offset;
|
||||
|
||||
/* Find a subspace of this space. */
|
||||
if (som_section_data (subsection)->is_subspace == 0
|
||||
|| som_section_data (subsection)->containing_space != section)
|
||||
continue;
|
||||
|
||||
/* If this subspace had no relocations, then we're finished
|
||||
with it. */
|
||||
if (subsection->reloc_count <= 0)
|
||||
{
|
||||
som_section_data (subsection)->subspace_dict.fixup_request_index
|
||||
= -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* This subspace has some relocations. Put the relocation stream
|
||||
index into the subspace record. */
|
||||
som_section_data (subsection)->subspace_dict.fixup_request_index
|
||||
= total_reloc_size;
|
||||
|
||||
/* To make life easier start over with a clean slate for
|
||||
each subspace. Seek to the start of the relocation stream
|
||||
for this subspace in preparation for writing out its fixup
|
||||
stream. */
|
||||
if (bfd_seek (abfd, current_offset + total_reloc_size, SEEK_SET) != 0)
|
||||
{
|
||||
bfd_error = system_call_error;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Buffer space has already been allocated. Just perform some
|
||||
initialization here. */
|
||||
p = tmp_space;
|
||||
subspace_reloc_size = 0;
|
||||
reloc_offset = 0;
|
||||
som_initialize_reloc_queue (reloc_queue);
|
||||
|
||||
/* Translate each BFD relocation into one or more SOM
|
||||
relocations. */
|
||||
for (j = 0; j < subsection->reloc_count; j++)
|
||||
{
|
||||
arelent *bfd_reloc = subsection->orelocation[j];
|
||||
unsigned int skip;
|
||||
int sym_num;
|
||||
|
||||
/* Get the symbol number. Remember it's stored in a
|
||||
special place for section symbols. */
|
||||
if ((*bfd_reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
|
||||
sym_num = (int) (*bfd_reloc->sym_ptr_ptr)->udata;
|
||||
else
|
||||
sym_num = (*som_symbol_data ((*bfd_reloc->sym_ptr_ptr)))->index;
|
||||
|
||||
/* If there is not enough room for the next couple relocations,
|
||||
then dump the current buffer contents now. Also reinitialize
|
||||
the relocation queue.
|
||||
|
||||
FIXME. We assume here that no BFD relocation will expand
|
||||
to more than 100 bytes of SOM relocations. This should (?!?)
|
||||
be quite safe. */
|
||||
if (p - tmp_space + 100 > SOM_TMP_BUFSIZE)
|
||||
{
|
||||
if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
|
||||
!= p - tmp_space)
|
||||
{
|
||||
bfd_error = system_call_error;
|
||||
return false;
|
||||
}
|
||||
p = tmp_space;
|
||||
som_initialize_reloc_queue (reloc_queue);
|
||||
}
|
||||
|
||||
/* Emit R_NO_RELOCATION fixups to map any bytes which were
|
||||
skipped. */
|
||||
skip = bfd_reloc->address - reloc_offset;
|
||||
p = som_reloc_skip (abfd, skip, p,
|
||||
&subspace_reloc_size, reloc_queue);
|
||||
|
||||
/* Update reloc_offset for the next iteration.
|
||||
|
||||
Note R_ENTRY and R_EXIT relocations are just markers,
|
||||
they do not consume input bytes. */
|
||||
if (bfd_reloc->howto->type != R_ENTRY
|
||||
&& bfd_reloc->howto->type != R_EXIT)
|
||||
reloc_offset = bfd_reloc->address + 4;
|
||||
else
|
||||
reloc_offset = bfd_reloc->address;
|
||||
|
||||
|
||||
/* Now the actual relocation we care about. */
|
||||
switch (bfd_reloc->howto->type)
|
||||
{
|
||||
case R_PCREL_CALL:
|
||||
case R_ABS_CALL:
|
||||
p = som_reloc_call (abfd, p, &subspace_reloc_size,
|
||||
bfd_reloc, sym_num, reloc_queue);
|
||||
break;
|
||||
|
||||
case R_CODE_ONE_SYMBOL:
|
||||
case R_DP_RELATIVE:
|
||||
/* Account for any addend. */
|
||||
if (bfd_reloc->addend)
|
||||
p = som_reloc_addend (abfd, bfd_reloc->addend, p,
|
||||
&subspace_reloc_size, reloc_queue);
|
||||
|
||||
if (sym_num < 0x20)
|
||||
{
|
||||
bfd_put_8 (abfd, bfd_reloc->howto->type + sym_num, p);
|
||||
subspace_reloc_size += 1;
|
||||
p += 1;
|
||||
}
|
||||
else if (sym_num < 0x100)
|
||||
{
|
||||
bfd_put_8 (abfd, bfd_reloc->howto->type + 32, p);
|
||||
bfd_put_8 (abfd, sym_num, p + 1);
|
||||
p = try_prev_fixup (abfd, &subspace_reloc_size, p,
|
||||
2, reloc_queue);
|
||||
}
|
||||
else if (sym_num < 0x10000000)
|
||||
{
|
||||
bfd_put_8 (abfd, bfd_reloc->howto->type + 33, p);
|
||||
bfd_put_8 (abfd, sym_num >> 16, p + 1);
|
||||
bfd_put_16 (abfd, sym_num, p + 2);
|
||||
p = try_prev_fixup (abfd, &subspace_reloc_size,
|
||||
p, 4, reloc_queue);
|
||||
}
|
||||
else
|
||||
abort ();
|
||||
break;
|
||||
|
||||
case R_DATA_ONE_SYMBOL:
|
||||
case R_DATA_PLABEL:
|
||||
case R_CODE_PLABEL:
|
||||
/* Account for any addend. */
|
||||
if (bfd_reloc->addend)
|
||||
p = som_reloc_addend (abfd, bfd_reloc->addend, p,
|
||||
&subspace_reloc_size, reloc_queue);
|
||||
|
||||
if (sym_num < 0x100)
|
||||
{
|
||||
bfd_put_8 (abfd, bfd_reloc->howto->type, p);
|
||||
bfd_put_8 (abfd, sym_num, p + 1);
|
||||
p = try_prev_fixup (abfd, &subspace_reloc_size, p,
|
||||
2, reloc_queue);
|
||||
}
|
||||
else if (sym_num < 0x10000000)
|
||||
{
|
||||
bfd_put_8 (abfd, bfd_reloc->howto->type + 1, p);
|
||||
bfd_put_8 (abfd, sym_num >> 16, p + 1);
|
||||
bfd_put_16 (abfd, sym_num, p + 2);
|
||||
p = try_prev_fixup (abfd, &subspace_reloc_size,
|
||||
p, 4, reloc_queue);
|
||||
}
|
||||
else
|
||||
abort ();
|
||||
break;
|
||||
|
||||
case R_ENTRY:
|
||||
{
|
||||
int *descp
|
||||
= (int *) (*som_symbol_data ((*bfd_reloc->sym_ptr_ptr)))->unwind;
|
||||
bfd_put_8 (abfd, R_ENTRY, p);
|
||||
bfd_put_32 (abfd, descp[0], p + 1);
|
||||
bfd_put_32 (abfd, descp[1], p + 5);
|
||||
p = try_prev_fixup (abfd, &subspace_reloc_size,
|
||||
p, 9, reloc_queue);
|
||||
break;
|
||||
}
|
||||
|
||||
case R_EXIT:
|
||||
bfd_put_8 (abfd, R_EXIT, p);
|
||||
subspace_reloc_size += 1;
|
||||
p += 1;
|
||||
break;
|
||||
|
||||
/* Put a "R_RESERVED" relocation in the stream if
|
||||
we hit something we do not understand. The linker
|
||||
will complain loudly if this ever happens. */
|
||||
default:
|
||||
bfd_put_8 (abfd, 0xff, p);
|
||||
subspace_reloc_size += 1;
|
||||
p += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Last BFD relocation for a subspace has been processed.
|
||||
Map the rest of the subspace with R_NO_RELOCATION fixups. */
|
||||
p = som_reloc_skip (abfd, bfd_section_size (abfd, subsection)
|
||||
- reloc_offset,
|
||||
p, &subspace_reloc_size, reloc_queue);
|
||||
|
||||
/* Scribble out the relocations. */
|
||||
if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
|
||||
!= p - tmp_space)
|
||||
{
|
||||
bfd_error = system_call_error;
|
||||
return false;
|
||||
}
|
||||
p = tmp_space;
|
||||
|
||||
total_reloc_size += subspace_reloc_size;
|
||||
som_section_data (subsection)->subspace_dict.fixup_request_quantity
|
||||
= subspace_reloc_size;
|
||||
}
|
||||
section = section->next;
|
||||
}
|
||||
*total_reloc_sizep = total_reloc_size;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Finally, scribble out the various headers to the disk. */
|
||||
|
||||
static boolean
|
||||
|
|
Loading…
Reference in a new issue