* 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:
Jeff Law 1995-02-01 08:35:40 +00:00
parent ef6fb95dea
commit 9ea5de84ab
2 changed files with 218 additions and 42 deletions

View File

@ -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
View File

@ -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);