* som.c (som_object_setup): More heruistics to detect the
braindamaged HP OSF1 linker. (setup_sections): Don't forget to free subspace_sections if we get an error. (som_slurp_string_table): Allocate strings on this bfd's obstack rather than directly out of the heap. (som_slurp_symbol_table): Likewise for the saved copy of the canonical symbols. (som_slurp_reloc_table): Likewise for the saved copy of the canonical relocations. Free the native relocations when we're done with them.
This commit is contained in:
parent
ef6fb95dea
commit
9ea5de84ab
@ -1,3 +1,17 @@
|
||||
Wed Feb 1 01:32:14 1995 Jeff Law (law@snake.cs.utah.edu)
|
||||
|
||||
* som.c (som_object_setup): More heruistics to detect the
|
||||
braindamaged HP OSF1 linker.
|
||||
(setup_sections): Don't forget to free subspace_sections if we get
|
||||
an error.
|
||||
(som_slurp_string_table): Allocate strings on this bfd's obstack
|
||||
rather than directly out of the heap.
|
||||
(som_slurp_symbol_table): Likewise for the saved copy of the
|
||||
canonical symbols.
|
||||
(som_slurp_reloc_table): Likewise for the saved copy of the
|
||||
canonical relocations. Free the native relocations when we're
|
||||
done with them.
|
||||
|
||||
Tue Jan 31 21:53:28 1995 Doug Evans <dje@canuck.cygnus.com>
|
||||
|
||||
* libelf.h (struct elf_obj_tdata): New member program_header_size.
|
||||
|
246
bfd/som.c
246
bfd/som.c
@ -213,10 +213,11 @@ static unsigned char * som_reloc_call PARAMS ((bfd *, unsigned char *,
|
||||
static unsigned long som_count_spaces PARAMS ((bfd *));
|
||||
static unsigned long som_count_subspaces PARAMS ((bfd *));
|
||||
static int compare_syms PARAMS ((const void *, const void *));
|
||||
static int compare_subspaces PARAMS ((const void *, const void *));
|
||||
static unsigned long som_compute_checksum PARAMS ((bfd *));
|
||||
static boolean som_prep_headers PARAMS ((bfd *));
|
||||
static int som_sizeof_headers PARAMS ((bfd *, boolean));
|
||||
static boolean som_write_headers PARAMS ((bfd *));
|
||||
static boolean som_finish_writing 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 *));
|
||||
@ -1571,6 +1572,9 @@ som_object_setup (abfd, file_hdrp, aux_hdrp)
|
||||
struct header *file_hdrp;
|
||||
struct som_exec_auxhdr *aux_hdrp;
|
||||
{
|
||||
asection *section;
|
||||
int found;
|
||||
|
||||
/* som_mkobject will set bfd_error if som_mkobject fails. */
|
||||
if (som_mkobject (abfd) != true)
|
||||
return 0;
|
||||
@ -1627,7 +1631,18 @@ som_object_setup (abfd, file_hdrp, aux_hdrp)
|
||||
The new approach examines the entry field. If it's zero or not 4
|
||||
byte aligned then it's not a proper code address and we guess it's
|
||||
really the executable flags. */
|
||||
if (aux_hdrp->exec_entry == 0 || (aux_hdrp->exec_entry & 0x3) != 0)
|
||||
found = 0;
|
||||
for (section = abfd->sections; section; section = section->next)
|
||||
{
|
||||
if ((section->flags & SEC_CODE) == 0)
|
||||
continue;
|
||||
if (aux_hdrp->exec_entry >= section->vma
|
||||
&& aux_hdrp->exec_entry < section->vma + section->_cooked_size)
|
||||
found = 1;
|
||||
}
|
||||
if (aux_hdrp->exec_entry == 0
|
||||
|| (aux_hdrp->exec_entry & 0x3) != 0
|
||||
|| ! found)
|
||||
{
|
||||
bfd_get_start_address (abfd) = aux_hdrp->exec_flags;
|
||||
obj_som_exec_data (abfd)->exec_flags = aux_hdrp->exec_entry;
|
||||
@ -1668,8 +1683,9 @@ setup_sections (abfd, file_hdr)
|
||||
struct header *file_hdr;
|
||||
{
|
||||
char *space_strings;
|
||||
int space_index;
|
||||
unsigned int space_index, i;
|
||||
unsigned int total_subspaces = 0;
|
||||
asection **subspace_sections, *section;
|
||||
|
||||
/* First, read in space names */
|
||||
|
||||
@ -1779,8 +1795,17 @@ setup_sections (abfd, file_hdr)
|
||||
subspace.quadrant) == false)
|
||||
goto error_return;
|
||||
|
||||
/* Keep an easy mapping between subspaces and sections. */
|
||||
subspace_asect->target_index = total_subspaces++;
|
||||
/* Keep an easy mapping between subspaces and sections.
|
||||
Note we do not necessarily read the subspaces in the
|
||||
same order in which they appear in the object file.
|
||||
|
||||
So to make the target index come out correctly, we
|
||||
store the location of the subspace header in target
|
||||
index, then sort using the location of the subspace
|
||||
header as the key. Then we can assign correct
|
||||
subspace indices. */
|
||||
total_subspaces++;
|
||||
subspace_asect->target_index = bfd_tell (abfd) - sizeof (subspace);
|
||||
|
||||
/* Set SEC_READONLY and SEC_CODE/SEC_DATA as specified
|
||||
by the access_control_bits in the subspace header. */
|
||||
@ -1873,13 +1898,43 @@ setup_sections (abfd, file_hdr)
|
||||
space_asect->_raw_size = save_subspace.file_loc_init_value
|
||||
- space_asect->filepos + save_subspace.initialization_length;
|
||||
}
|
||||
/* Now that we've read in all the subspace records, we need to assign
|
||||
a target index to each subspace. */
|
||||
subspace_sections = (asection **) malloc (total_subspaces
|
||||
* sizeof (asection *));
|
||||
if (subspace_sections == NULL)
|
||||
goto error_return;
|
||||
|
||||
for (i = 0, section = abfd->sections; section; section = section->next)
|
||||
{
|
||||
if (!som_is_subspace (section))
|
||||
continue;
|
||||
|
||||
subspace_sections[i] = section;
|
||||
i++;
|
||||
}
|
||||
qsort (subspace_sections, total_subspaces,
|
||||
sizeof (asection *), compare_subspaces);
|
||||
|
||||
/* subspace_sections is now sorted in the order in which the subspaces
|
||||
appear in the object file. Assign an index to each one now. */
|
||||
for (i = 0; i < total_subspaces; i++)
|
||||
subspace_sections[i]->target_index = i;
|
||||
|
||||
if (space_strings != NULL)
|
||||
free (space_strings);
|
||||
|
||||
if (subspace_sections != NULL)
|
||||
free (subspace_sections);
|
||||
|
||||
return true;
|
||||
|
||||
error_return:
|
||||
if (space_strings != NULL)
|
||||
free (space_strings);
|
||||
|
||||
if (subspace_sections != NULL)
|
||||
free (subspace_sections);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2136,7 +2191,9 @@ som_is_space (section)
|
||||
|
||||
/* If the containing space isn't the same as the given section,
|
||||
then this isn't a space. */
|
||||
if (som_section_data (section)->copy_data->container != section)
|
||||
if (som_section_data (section)->copy_data->container != section
|
||||
&& (som_section_data (section)->copy_data->container->output_section
|
||||
!= section))
|
||||
return false;
|
||||
|
||||
/* OK. Must be a space. */
|
||||
@ -2156,7 +2213,9 @@ som_is_subspace (section)
|
||||
|
||||
/* If the containing space is the same as the given section,
|
||||
then this isn't a subspace. */
|
||||
if (som_section_data (section)->copy_data->container == section)
|
||||
if (som_section_data (section)->copy_data->container == section
|
||||
|| (som_section_data (section)->copy_data->container->output_section
|
||||
== section))
|
||||
return false;
|
||||
|
||||
/* OK. Must be a subspace. */
|
||||
@ -2171,7 +2230,9 @@ static boolean
|
||||
som_is_container (space, subspace)
|
||||
asection *space, *subspace;
|
||||
{
|
||||
return som_section_data (subspace)->copy_data->container == space;
|
||||
return (som_section_data (subspace)->copy_data->container == space
|
||||
|| (som_section_data (subspace)->copy_data->container->output_section
|
||||
== space));
|
||||
}
|
||||
|
||||
/* Count and return the number of spaces attached to the given BFD. */
|
||||
@ -2240,6 +2301,27 @@ compare_syms (arg1, arg2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return -1, 0, 1 indicating the relative ordering of subspace1
|
||||
and subspace. */
|
||||
|
||||
static int
|
||||
compare_subspaces (arg1, arg2)
|
||||
const PTR arg1;
|
||||
const PTR arg2;
|
||||
|
||||
{
|
||||
asection **subspace1 = (asection **) arg1;
|
||||
asection **subspace2 = (asection **) arg2;
|
||||
unsigned int count1, count2;
|
||||
|
||||
if ((*subspace1)->target_index < (*subspace2)->target_index)
|
||||
return -1;
|
||||
else if ((*subspace2)->target_index < (*subspace1)->target_index)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Perform various work in preparation for emitting the fixup stream. */
|
||||
|
||||
static void
|
||||
@ -2953,23 +3035,6 @@ som_begin_writing (abfd)
|
||||
obj_som_file_hdr (abfd)->symbol_total = num_syms;
|
||||
current_offset += num_syms * sizeof (struct symbol_dictionary_record);
|
||||
|
||||
/* Do prep work before handling fixups. */
|
||||
som_prep_for_fixups (abfd, syms, num_syms);
|
||||
|
||||
/* Next comes the fixup stream which starts on a word boundary. */
|
||||
if (current_offset % 4)
|
||||
current_offset += (4 - (current_offset % 4));
|
||||
obj_som_file_hdr (abfd)->fixup_request_location = current_offset;
|
||||
|
||||
/* Write the fixups and update fields in subspace headers which
|
||||
relate to the fixup stream. */
|
||||
if (som_write_fixups (abfd, current_offset, &total_reloc_size) == false)
|
||||
return false;
|
||||
|
||||
/* Record the total size of the fixup stream in the file header. */
|
||||
obj_som_file_hdr (abfd)->fixup_request_total = total_reloc_size;
|
||||
current_offset += total_reloc_size;
|
||||
|
||||
/* Next are the symbol strings.
|
||||
Align them to a word boundary. */
|
||||
if (current_offset % 4)
|
||||
@ -2977,8 +3042,7 @@ som_begin_writing (abfd)
|
||||
obj_som_file_hdr (abfd)->symbol_strings_location = current_offset;
|
||||
|
||||
/* Scribble out the symbol strings. */
|
||||
if (som_write_symbol_strings (abfd, current_offset,
|
||||
obj_som_sorted_syms (abfd),
|
||||
if (som_write_symbol_strings (abfd, current_offset, syms,
|
||||
num_syms, &strings_size)
|
||||
== false)
|
||||
return false;
|
||||
@ -3185,7 +3249,7 @@ som_begin_writing (abfd)
|
||||
obj_som_file_hdr (abfd)->loader_fixup_location = 0;
|
||||
obj_som_file_hdr (abfd)->loader_fixup_total = 0;
|
||||
|
||||
/* Done. Store the total size of the SOM. */
|
||||
/* Done. Store the total size of the SOM so far. */
|
||||
obj_som_file_hdr (abfd)->som_length = current_offset;
|
||||
|
||||
return true;
|
||||
@ -3194,7 +3258,7 @@ som_begin_writing (abfd)
|
||||
/* Finally, scribble out the various headers to the disk. */
|
||||
|
||||
static boolean
|
||||
som_write_headers (abfd)
|
||||
som_finish_writing (abfd)
|
||||
bfd *abfd;
|
||||
{
|
||||
int num_spaces = som_count_spaces (abfd);
|
||||
@ -3202,6 +3266,36 @@ som_write_headers (abfd)
|
||||
int subspace_index = 0;
|
||||
file_ptr location;
|
||||
asection *section;
|
||||
unsigned long current_offset;
|
||||
unsigned int total_reloc_size;
|
||||
|
||||
/* Do prep work before handling fixups. */
|
||||
som_prep_for_fixups (abfd,
|
||||
bfd_get_outsymbols (abfd),
|
||||
bfd_get_symcount (abfd));
|
||||
|
||||
current_offset = obj_som_file_hdr (abfd)->som_length;
|
||||
|
||||
/* At the end of the file is the fixup stream which starts on a
|
||||
word boundary. */
|
||||
if (current_offset % 4)
|
||||
current_offset += (4 - (current_offset % 4));
|
||||
obj_som_file_hdr (abfd)->fixup_request_location = current_offset;
|
||||
|
||||
/* Write the fixups and update fields in subspace headers which
|
||||
relate to the fixup stream. */
|
||||
if (som_write_fixups (abfd, current_offset, &total_reloc_size) == false)
|
||||
return false;
|
||||
|
||||
/* Record the total size of the fixup stream in the file header. */
|
||||
obj_som_file_hdr (abfd)->fixup_request_total = total_reloc_size;
|
||||
|
||||
obj_som_file_hdr (abfd)->som_length += total_reloc_size;
|
||||
|
||||
/* Now that the symbol table information is complete, build and
|
||||
write the symbol table. */
|
||||
if (som_build_and_write_symbol_table (abfd) == false)
|
||||
return false;
|
||||
|
||||
/* Subspaces are written first so that we can set up information
|
||||
about them in their containing spaces as the subspace is written. */
|
||||
@ -3503,11 +3597,10 @@ som_bfd_derive_misc_symbol_info (abfd, sym, info)
|
||||
/* Now handle the symbol's scope. Exported data which is not
|
||||
in the common section has scope SS_UNIVERSAL. Note scope
|
||||
of common symbols was handled earlier! */
|
||||
if (sym->flags & BSF_EXPORT && ! bfd_is_com_section (sym->section))
|
||||
info->symbol_scope = SS_UNIVERSAL;
|
||||
/* Any undefined symbol at this point has a scope SS_UNSAT. */
|
||||
else if (bfd_is_und_section (sym->section))
|
||||
if (bfd_is_und_section (sym->section))
|
||||
info->symbol_scope = SS_UNSAT;
|
||||
else if (sym->flags & BSF_EXPORT && ! bfd_is_com_section (sym->section))
|
||||
info->symbol_scope = SS_UNIVERSAL;
|
||||
/* Anything else which is not in the common section has scope
|
||||
SS_LOCAL. */
|
||||
else if (! bfd_is_com_section (sym->section))
|
||||
@ -3609,12 +3702,7 @@ som_write_object_contents (abfd)
|
||||
som_begin_writing (abfd);
|
||||
}
|
||||
|
||||
/* Now that the symbol table information is complete, build and
|
||||
write the symbol table. */
|
||||
if (som_build_and_write_symbol_table (abfd) == false)
|
||||
return false;
|
||||
|
||||
return (som_write_headers (abfd));
|
||||
return (som_finish_writing (abfd));
|
||||
}
|
||||
|
||||
|
||||
@ -3640,7 +3728,7 @@ som_slurp_string_table (abfd)
|
||||
}
|
||||
|
||||
/* Allocate and read in the string table. */
|
||||
stringtab = malloc (obj_som_stringtab_size (abfd));
|
||||
stringtab = bfd_zalloc (abfd, obj_som_stringtab_size (abfd));
|
||||
if (stringtab == NULL)
|
||||
{
|
||||
bfd_set_error (bfd_error_no_memory);
|
||||
@ -3747,7 +3835,7 @@ som_slurp_symbol_table (abfd)
|
||||
stringtab = obj_som_stringtab (abfd);
|
||||
|
||||
symbase = (som_symbol_type *)
|
||||
malloc (symbol_count * sizeof (som_symbol_type));
|
||||
bfd_zalloc (abfd, symbol_count * sizeof (som_symbol_type));
|
||||
if (symbase == NULL)
|
||||
{
|
||||
bfd_set_error (bfd_error_no_memory);
|
||||
@ -4158,6 +4246,73 @@ som_set_reloc_info (fixup, end, internal_relocs, section, symbols, just_count)
|
||||
if (! just_count)
|
||||
rptr->sym_ptr_ptr = &symbols[c];
|
||||
break;
|
||||
/* Argument relocation bits for a function call. */
|
||||
case 'R':
|
||||
if (! just_count)
|
||||
{
|
||||
unsigned int tmp = var ('R');
|
||||
rptr->addend = 0;
|
||||
|
||||
if ((som_hppa_howto_table[op].type == R_PCREL_CALL
|
||||
&& R_PCREL_CALL + 10 > op)
|
||||
|| (som_hppa_howto_table[op].type == R_ABS_CALL
|
||||
&& R_ABS_CALL + 10 > op))
|
||||
{
|
||||
/* Simple encoding. */
|
||||
if (tmp > 4)
|
||||
{
|
||||
tmp -= 5;
|
||||
rptr->addend |= 1;
|
||||
}
|
||||
if (tmp == 4)
|
||||
rptr->addend |= 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2;
|
||||
else if (tmp == 3)
|
||||
rptr->addend |= 1 << 8 | 1 << 6 | 1 << 4;
|
||||
else if (tmp == 2)
|
||||
rptr->addend |= 1 << 8 | 1 << 6;
|
||||
else if (tmp == 1)
|
||||
rptr->addend |= 1 << 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int tmp1, tmp2;
|
||||
|
||||
/* First part is easy -- low order two bits are
|
||||
directly copied, then shifted away. */
|
||||
rptr->addend = tmp & 0x3;
|
||||
tmp >>= 2;
|
||||
|
||||
/* Diving the result by 10 gives us the second
|
||||
part. If it is 9, then the first two words
|
||||
are a double precision paramater, else it is
|
||||
3 * the first arg bits + the 2nd arg bits. */
|
||||
tmp1 = tmp / 10;
|
||||
tmp -= tmp1 * 10;
|
||||
if (tmp1 == 9)
|
||||
rptr->addend += (0xe << 6);
|
||||
else
|
||||
{
|
||||
/* Get the two pieces. */
|
||||
tmp2 = tmp1 / 3;
|
||||
tmp1 -= tmp2 * 3;
|
||||
/* Put them in the addend. */
|
||||
rptr->addend += (tmp2 << 8) + (tmp1 << 6);
|
||||
}
|
||||
|
||||
/* What's left is the third part. It's unpacked
|
||||
just like the second. */
|
||||
if (tmp == 9)
|
||||
rptr->addend += (0xe << 2);
|
||||
else
|
||||
{
|
||||
tmp2 = tmp / 3;
|
||||
tmp -= tmp2 * 3;
|
||||
rptr->addend += (tmp2 << 4) + (tmp << 2);
|
||||
}
|
||||
}
|
||||
rptr->addend = HPPA_R_ADDEND (rptr->addend, 0);
|
||||
}
|
||||
break;
|
||||
/* Handle the linker expression stack. */
|
||||
case 'O':
|
||||
switch (op)
|
||||
@ -4210,6 +4365,9 @@ som_set_reloc_info (fixup, end, internal_relocs, section, symbols, just_count)
|
||||
rptr->addend = var ('T');
|
||||
else if (som_hppa_howto_table[op].type == R_EXIT)
|
||||
rptr->addend = var ('U');
|
||||
else if (som_hppa_howto_table[op].type == R_PCREL_CALL
|
||||
|| som_hppa_howto_table[op].type == R_ABS_CALL)
|
||||
;
|
||||
else
|
||||
rptr->addend = var ('V');
|
||||
rptr++;
|
||||
@ -4292,7 +4450,8 @@ som_slurp_reloc_table (abfd, section, symbols, just_count)
|
||||
if (section->relocation != (arelent *) NULL)
|
||||
return true;
|
||||
|
||||
internal_relocs = (arelent *) malloc (num_relocs * sizeof (arelent));
|
||||
internal_relocs = (arelent *)
|
||||
bfd_zalloc (abfd, (num_relocs * sizeof (arelent)));
|
||||
if (internal_relocs == (arelent *) NULL)
|
||||
{
|
||||
bfd_set_error (bfd_error_no_memory);
|
||||
@ -4303,6 +4462,9 @@ som_slurp_reloc_table (abfd, section, symbols, just_count)
|
||||
som_set_reloc_info (external_relocs, fixup_stream_size,
|
||||
internal_relocs, section, symbols, false);
|
||||
|
||||
/* We're done with the external relocations. Free them. */
|
||||
free (external_relocs);
|
||||
|
||||
/* Save our results and return success. */
|
||||
section->relocation = internal_relocs;
|
||||
return (true);
|
||||
|
Loading…
Reference in New Issue
Block a user