/* bfd back-end for HP PA-RISC SOM objects.
- Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ Free Software Foundation, Inc.
Contributed by the Center for Software Science at the
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "bfd.h"
#include "sysdep.h"
static void som_print_symbol PARAMS ((bfd *, PTR,
asymbol *, bfd_print_symbol_type));
static boolean som_new_section_hook PARAMS ((bfd *, asection *));
+static boolean som_bfd_copy_private_symbol_data PARAMS ((bfd *, asymbol *,
+ bfd *, asymbol *));
static boolean som_bfd_copy_private_section_data PARAMS ((bfd *, asection *,
bfd *, asection *));
static boolean som_bfd_copy_private_bfd_data PARAMS ((bfd *, bfd *));
+#define som_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
+#define som_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
static boolean som_bfd_is_local_label PARAMS ((bfd *, asymbol *));
static boolean som_set_section_contents PARAMS ((bfd *, sec_ptr, PTR,
file_ptr, bfd_size_type));
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 *));
asymbol **, unsigned int,
unsigned *));
static boolean som_begin_writing PARAMS ((bfd *));
-static const reloc_howto_type * som_bfd_reloc_type_lookup
+static reloc_howto_type * som_bfd_reloc_type_lookup
PARAMS ((bfd *, bfd_reloc_code_real_type));
static char som_section_type PARAMS ((const char *));
static int som_decode_symclass PARAMS ((asymbol *));
static boolean som_is_subspace PARAMS ((asection *));
static boolean som_is_container PARAMS ((asection *, asection *));
static boolean som_bfd_free_cached_info PARAMS ((bfd *));
+static boolean som_bfd_link_split_section PARAMS ((bfd *, asection *));
/* Map SOM section names to POSIX/BSD single-character symbol types.
1, "Lb4*=Mb1+L*=", /* 0x2b */
2, "Lb4*=Md1+4*=", /* 0x2c */
3, "Ld1+=Me1+=", /* 0x2d */
- /* R_RESERVED */
+ /* R_SHORT_PCREL_MODE */
0, "", /* 0x2e */
+ /* R_LONG_PCREL_MODE */
0, "", /* 0x2f */
/* R_PCREL_CALL */
0, "L4=RD=Sb=", /* 0x30 */
1, "P", /* 0xd4 */
2, "P", /* 0xd5 */
3, "P", /* 0xd6 */
- /* R_RESERVED */
+ /* R_SEC_STMT */
0, "", /* 0xd7 */
+ /* R_N0SEL */
0, "", /* 0xd8 */
+ /* R_N1SEL */
0, "", /* 0xd9 */
+ /* R_LINETAB */
0, "", /* 0xda */
+ /* R_LINETAB_ESC */
0, "", /* 0xdb */
+ /* R_LTP_OVERRIDE */
0, "", /* 0xdc */
+ /* R_COMMENT */
0, "", /* 0xdd */
+ /* R_RESERVED */
0, "", /* 0xde */
0, "", /* 0xdf */
0, "", /* 0xe0 */
-1
};
-/* These apparently are not in older versions of hpux reloc.h. */
+/* These apparently are not in older versions of hpux reloc.h (hpux7). */
#ifndef R_DLT_REL
#define R_DLT_REL 0x78
#endif
#define R_SEC_STMT 0xd7
#endif
+/* And these first appeared in hpux10. */
+#ifndef R_SHORT_PCREL_MODE
+#define R_SHORT_PCREL_MODE 0x3e
+#endif
+
+#ifndef R_LONG_PCREL_MODE
+#define R_LONG_PCREL_MODE 0x3f
+#endif
+
+#ifndef R_N0SEL
+#define R_N0SEL 0xd8
+#endif
+
+#ifndef R_N1SEL
+#define R_N1SEL 0xd9
+#endif
+
+#ifndef R_LINETAB
+#define R_LINETAB 0xda
+#endif
+
+#ifndef R_LINETAB_ESC
+#define R_LINETAB_ESC 0xdb
+#endif
+
+#ifndef R_LTP_OVERRIDE
+#define R_LTP_OVERRIDE 0xdc
+#endif
+
+#ifndef R_COMMENT
+#define R_COMMENT 0xdd
+#endif
+
static reloc_howto_type som_hppa_howto_table[] =
{
{R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
{R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
{R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
{R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
- {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
- {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_SHORT_PCREL_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_SHORT_PCREL_MODE"},
+ {R_LONG_PCREL_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_LONG_PCREL_MODE"},
{R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
{R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
{R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
{R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
{R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
{R_SEC_STMT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_SEC_STMT"},
- {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
- {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
- {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
- {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
- {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
- {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_N0SEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_N0SEL"},
+ {R_N1SEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_N1SEL"},
+ {R_LINETAB, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_LINETAB"},
+ {R_LINETAB_ESC, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_LINETAB_ESC"},
+ {R_LTP_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_LTP_OVERRIDE"},
+ {R_COMMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_COMMENT"},
{R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
{R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
{R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
and a field selector, return one or more appropriate SOM relocations. */
int **
-hppa_som_gen_reloc_type (abfd, base_type, format, field)
+hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff)
bfd *abfd;
int base_type;
int format;
enum hppa_reloc_field_selector_type_alt field;
+ int sym_diff;
{
int *final_type, **final_types;
- final_types = (int **) bfd_alloc_by_size_t (abfd, sizeof (int *) * 3);
+ final_types = (int **) bfd_alloc_by_size_t (abfd, sizeof (int *) * 6);
final_type = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
if (!final_types || !final_type)
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
+ return NULL;
/* The field selector may require additional relocations to be
generated. It's impossible to know at this moment if additional
case e_rtsel:
final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
if (!final_types[0])
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
+ return NULL;
if (field == e_tsel)
*final_types[0] = R_FSEL;
else if (field == e_ltsel)
case e_rssel:
final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
if (!final_types[0])
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
+ return NULL;
*final_types[0] = R_S_MODE;
final_types[1] = final_type;
final_types[2] = NULL;
case e_rsel:
final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
if (!final_types[0])
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
+ return NULL;
*final_types[0] = R_N_MODE;
final_types[1] = final_type;
final_types[2] = NULL;
case e_rdsel:
final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
if (!final_types[0])
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
+ return NULL;
*final_types[0] = R_D_MODE;
final_types[1] = final_type;
final_types[2] = NULL;
case e_rrsel:
final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
if (!final_types[0])
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
+ return NULL;
*final_types[0] = R_R_MODE;
final_types[1] = final_type;
final_types[2] = NULL;
*final_type = base_type;
break;
+
+ case e_nsel:
+ final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types[0])
+ return NULL;
+ *final_types[0] = R_N1SEL;
+ final_types[1] = final_type;
+ final_types[2] = NULL;
+ *final_type = base_type;
+ break;
+
+ case e_nlsel:
+ case e_nlrsel:
+ final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types[0])
+ return NULL;
+ *final_types[0] = R_N0SEL;
+ final_types[1] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types[1])
+ return NULL;
+ if (field == e_nlsel)
+ *final_types[1] = R_N_MODE;
+ else
+ *final_types[1] = R_R_MODE;
+ final_types[2] = final_type;
+ final_types[3] = NULL;
+ *final_type = base_type;
+ break;
}
switch (base_type)
{
case R_HPPA:
+ /* The difference of two symbols needs *very* special handling. */
+ if (sym_diff)
+ {
+ final_types[0] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[1] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[2] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[3] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types[0] || !final_types[1] || !final_types[2])
+ return NULL;
+ if (field == e_fsel)
+ *final_types[0] = R_FSEL;
+ else if (field == e_rsel)
+ *final_types[0] = R_RSEL;
+ else if (field == e_lsel)
+ *final_types[0] = R_LSEL;
+ *final_types[1] = R_COMP2;
+ *final_types[2] = R_COMP2;
+ *final_types[3] = R_COMP1;
+ final_types[4] = final_type;
+ *final_types[4] = R_CODE_EXPR;
+ final_types[5] = NULL;
+ break;
+ }
/* PLABELs get their own relocation type. */
- if (field == e_psel
+ else if (field == e_psel
|| field == e_lpsel
|| field == e_rpsel)
{
*final_type = R_DATA_PLABEL;
break;
+ case R_HPPA_COMPLEX:
+ /* The difference of two symbols needs *very* special handling. */
+ if (sym_diff)
+ {
+ final_types[0] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[1] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[2] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[3] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types[0] || !final_types[1] || !final_types[2])
+ return NULL;
+ if (field == e_fsel)
+ *final_types[0] = R_FSEL;
+ else if (field == e_rsel)
+ *final_types[0] = R_RSEL;
+ else if (field == e_lsel)
+ *final_types[0] = R_LSEL;
+ *final_types[1] = R_COMP2;
+ *final_types[2] = R_COMP2;
+ *final_types[3] = R_COMP1;
+ final_types[4] = final_type;
+ *final_types[4] = R_CODE_EXPR;
+ final_types[5] = NULL;
+ break;
+ }
+ else
+ break;
+
case R_HPPA_NONE:
case R_HPPA_ABS_CALL:
case R_HPPA_PCREL_CALL:
howto table. */
/*ARGSUSED*/
-static const reloc_howto_type *
+static reloc_howto_type *
som_bfd_reloc_type_lookup (abfd, code)
bfd *abfd;
bfd_reloc_code_real_type code;
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;
obj_som_exec_data (abfd) = (struct som_exec_data *)
bfd_zalloc (abfd, sizeof (struct som_exec_data ));
if (obj_som_exec_data (abfd) == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
+ return NULL;
/* The braindamaged OSF1 linker switched exec_flags and exec_entry!
- It seems rather backward that the OSF1 linker which is much
- older than any HPUX linker I've got uses a newer SOM version
- id... But that's what I've found by experimentation. */
- if (file_hdrp->version_id == NEW_VERSION_ID)
+ We used to identify OSF1 binaries based on NEW_VERSION_ID, but
+ apparently the latest HPUX linker is using NEW_VERSION_ID now.
+
+ It's about time, OSF has used the new id since at least 1992;
+ HPUX didn't start till nearly 1995!.
+
+ 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. */
+ 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;
obj_som_exec_data (abfd)->exec_flags = aux_hdrp->exec_flags;
}
- bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 0);
+ bfd_default_set_arch_mach (abfd, bfd_arch_hppa, pa10);
bfd_get_symcount (abfd) = file_hdrp->symbol_total;
/* Initialize the saved symbol table and string table to NULL.
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 */
- space_strings = malloc (file_hdr->space_strings_size);
+ space_strings = bfd_malloc (file_hdr->space_strings_size);
if (!space_strings && file_hdr->space_strings_size != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
if (bfd_seek (abfd, file_hdr->space_strings_location, SEEK_SET) < 0)
goto error_return;
space.space_number) == false)
goto error_return;
+ /* If the space has no subspaces, then we're done. */
+ if (space.subspace_quantity == 0)
+ continue;
+
/* Now, read in the first subspace for this space */
if (bfd_seek (abfd, file_hdr->subspace_location
+ space.subspace_index * sizeof subspace,
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. */
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 **) bfd_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;
}
abfd->tdata.som_data = (struct som_data_struct *)
bfd_zalloc (abfd, sizeof (struct som_data_struct));
if (abfd->tdata.som_data == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
return true;
}
/* Make and attach a file header to the BFD. */
file_hdr = (struct header *) bfd_zalloc (abfd, sizeof (struct header));
if (file_hdr == NULL)
-
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
obj_som_file_hdr (abfd) = file_hdr;
if (abfd->flags & (EXEC_P | DYNAMIC))
obj_som_exec_hdr (abfd) = (struct som_exec_auxhdr *)
bfd_zalloc (abfd, sizeof (struct som_exec_auxhdr));
if (obj_som_exec_hdr (abfd) == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
if (abfd->flags & D_PAGED)
file_hdr->a_magic = DEMAND_MAGIC;
= (struct space_dictionary_record *)
bfd_zalloc (abfd, sizeof (struct space_dictionary_record));
if (som_section_data (section)->space_dict == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
/* Set space attributes. Note most attributes of SOM spaces
are set based on the subspaces it contains. */
som_section_data (section)->space_dict->loader_fix_index = -1;
= (struct subspace_dictionary_record *)
bfd_zalloc (abfd, sizeof (struct subspace_dictionary_record));
if (som_section_data (section)->subspace_dict == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
/* Set subspace attributes. Basic stuff is done here, additional
attributes are filled in later as more information becomes
/* 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. */
/* 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. */
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. */
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
later relocation. */
switch (bfd_reloc->howto->type)
{
- /* This only needs to handle relocations that may be
- made by hppa_som_gen_reloc. */
case R_ENTRY:
case R_ALT_ENTRY:
case R_EXIT:
case R_FSEL:
case R_LSEL:
case R_RSEL:
+ case R_COMP1:
+ case R_COMP2:
+ case R_BEGIN_BRTAB:
+ case R_END_BRTAB:
+ case R_BEGIN_TRY:
+ case R_END_TRY:
+ case R_N0SEL:
+ case R_N1SEL:
reloc_offset = bfd_reloc->address;
break;
case R_DATA_PLABEL:
case R_CODE_PLABEL:
case R_DLT_REL:
- /* Account for any addend. */
- if (bfd_reloc->addend)
+ /* Account for any addend using R_DATA_OVERRIDE. */
+ if (bfd_reloc->howto->type != R_DATA_ONE_SYMBOL
+ && bfd_reloc->addend)
p = som_reloc_addend (abfd, bfd_reloc->addend, p,
&subspace_reloc_size, reloc_queue);
case R_FSEL:
case R_LSEL:
case R_RSEL:
+ case R_BEGIN_BRTAB:
+ case R_END_BRTAB:
+ case R_BEGIN_TRY:
+ case R_N0SEL:
+ case R_N1SEL:
+ bfd_put_8 (abfd, bfd_reloc->howto->type, p);
+ subspace_reloc_size += 1;
+ p += 1;
+ break;
+
+ case R_END_TRY:
+ /* The end of a exception handling region. The reloc's
+ addend contains the offset of the exception handling
+ code. */
+ if (bfd_reloc->addend == 0)
+ bfd_put_8 (abfd, bfd_reloc->howto->type, p);
+ else if (bfd_reloc->addend < 1024)
+ {
+ bfd_put_8 (abfd, bfd_reloc->howto->type + 1, p);
+ bfd_put_8 (abfd, bfd_reloc->addend / 4, p + 1);
+ p = try_prev_fixup (abfd, &subspace_reloc_size,
+ p, 2, reloc_queue);
+ }
+ else
+ {
+ bfd_put_8 (abfd, bfd_reloc->howto->type + 2, p);
+ bfd_put_8 (abfd, (bfd_reloc->addend / 4) >> 16, p + 1);
+ bfd_put_16 (abfd, bfd_reloc->addend / 4, p + 2);
+ p = try_prev_fixup (abfd, &subspace_reloc_size,
+ p, 4, reloc_queue);
+ }
+ break;
+
+ case R_COMP1:
+ /* The only time we generate R_COMP1, R_COMP2 and
+ R_CODE_EXPR relocs is for the difference of two
+ symbols. Hence we can cheat here. */
+ bfd_put_8 (abfd, bfd_reloc->howto->type, p);
+ bfd_put_8 (abfd, 0x44, p + 1);
+ p = try_prev_fixup (abfd, &subspace_reloc_size,
+ p, 2, reloc_queue);
+ break;
+
+ case R_COMP2:
+ /* The only time we generate R_COMP1, R_COMP2 and
+ R_CODE_EXPR relocs is for the difference of two
+ symbols. Hence we can cheat here. */
+ bfd_put_8 (abfd, bfd_reloc->howto->type, p);
+ bfd_put_8 (abfd, 0x80, p + 1);
+ bfd_put_8 (abfd, sym_num >> 16, p + 2);
+ bfd_put_16 (abfd, sym_num, p + 3);
+ p = try_prev_fixup (abfd, &subspace_reloc_size,
+ p, 5, reloc_queue);
+ break;
+
+ case R_CODE_EXPR:
+ /* The only time we generate R_COMP1, R_COMP2 and
+ R_CODE_EXPR relocs is for the difference of two
+ symbols. Hence we can cheat here. */
bfd_put_8 (abfd, bfd_reloc->howto->type, p);
subspace_reloc_size += 1;
p += 1;
unsigned long current_offset = 0;
int strings_size = 0;
unsigned int total_reloc_size = 0;
- unsigned long num_spaces, num_subspaces, num_syms, i;
+ unsigned long num_spaces, num_subspaces, i;
asection *section;
- asymbol **syms = bfd_get_outsymbols (abfd);
unsigned int total_subspaces = 0;
struct som_exec_auxhdr *exec_header = NULL;
obj_som_file_hdr (abfd)->space_strings_size = strings_size;
current_offset += strings_size;
- /* Next is the symbol table. These are fixed length records.
-
- Count the number of symbols to determine how much room is needed
- in the object file for the symbol table.
-
- The names of the symbols are stored in a separate string table,
- and the index for each symbol name into the string table is computed
- below. Therefore, it is not possible to write the symobl table
- at this time. */
- num_syms = bfd_get_symcount (abfd);
- obj_som_file_hdr (abfd)->symbol_location = current_offset;
- 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)
- current_offset += (4 - (current_offset % 4));
- 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),
- num_syms, &strings_size)
- == false)
- return false;
-
- /* Record total string table size in header and update the
- current offset. */
- obj_som_file_hdr (abfd)->symbol_strings_size = strings_size;
- current_offset += strings_size;
-
/* Next is the compiler records. We do not use these. */
obj_som_file_hdr (abfd)->compiler_location = current_offset;
obj_som_file_hdr (abfd)->compiler_total = 0;
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;
/* 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);
- int i;
+ asymbol **syms = bfd_get_outsymbols (abfd);
+ int i, num_syms, strings_size;
int subspace_index = 0;
file_ptr location;
asection *section;
+ unsigned long current_offset;
+ unsigned int total_reloc_size;
+
+ /* Next is the symbol table. These are fixed length records.
+
+ Count the number of symbols to determine how much room is needed
+ in the object file for the symbol table.
+
+ The names of the symbols are stored in a separate string table,
+ and the index for each symbol name into the string table is computed
+ below. Therefore, it is not possible to write the symbol table
+ at this time.
+
+ These used to be output before the subspace contents, but they
+ were moved here to work around a stupid bug in the hpux linker
+ (fixed in hpux10). */
+ current_offset = obj_som_file_hdr (abfd)->som_length;
+
+ /* Make sure we're on a word boundary. */
+ if (current_offset % 4)
+ current_offset += (4 - (current_offset % 4));
+
+ num_syms = bfd_get_symcount (abfd);
+ obj_som_file_hdr (abfd)->symbol_location = current_offset;
+ obj_som_file_hdr (abfd)->symbol_total = num_syms;
+ current_offset += num_syms * sizeof (struct symbol_dictionary_record);
+
+ /* Next are the symbol strings.
+ Align them to a word boundary. */
+ if (current_offset % 4)
+ current_offset += (4 - (current_offset % 4));
+ obj_som_file_hdr (abfd)->symbol_strings_location = current_offset;
+
+ /* Scribble out the symbol strings. */
+ if (som_write_symbol_strings (abfd, current_offset, syms,
+ num_syms, &strings_size)
+ == false)
+ return false;
+
+ /* Record total string table size in header and update the
+ current offset. */
+ obj_som_file_hdr (abfd)->symbol_strings_size = strings_size;
+ current_offset += strings_size;
+
+ /* Do prep work before handling fixups. */
+ som_prep_for_fixups (abfd,
+ bfd_get_outsymbols (abfd),
+ bfd_get_symcount (abfd));
+
+ /* 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;
+
+ /* Done. Store the total size of the SOM. */
+ obj_som_file_hdr (abfd)->som_length = current_offset + 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. */
section = section->next;
}
- /* FIXME. This should really be conditional based on whether or not
- PA1.1 instructions/registers have been used.
-
- Setting of the system_id has to happen very late now that copying of
+ /* Setting of the system_id has to happen very late now that copying of
BFD private data happens *after* section contents are set. */
if (abfd->flags & (EXEC_P | DYNAMIC))
obj_som_file_hdr(abfd)->system_id = obj_som_exec_data (abfd)->system_id;
+ else if (bfd_get_mach (abfd) == pa11)
+ obj_som_file_hdr(abfd)->system_id = CPU_PA_RISC1_1;
else
obj_som_file_hdr(abfd)->system_id = CPU_PA_RISC1_0;
info->arg_reloc = som_symbol_data (sym)->tc_data.hppa_arg_reloc;
}
- /* If the type is unknown at this point, it should be ST_DATA or
- ST_CODE (function/ST_ENTRY symbols were handled as special
- cases above). */
+ /* For unknown symbols, set their type to ST_DATA.
+
+ We used to set the symbol type based on the section this symbol
+ was in (ST_DATA for DATA sections, ST_CODE for CODE sections).
+ Strictly speaking, this is the right approach. However, the
+ linker chokes if we have an R_DATA_ONE_SYMBOL reloc involving
+ an ST_CODE symbol in a shared library, which happens for
+ exception handling tables.
+
+ I tried an alternate approach to generating exception handling
+ tables using PUSH_SYM and DATA_EXPR relocs, but that fails to
+ relocate exception handling tables in shared libraries.
+
+ What a pain. */
else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN)
- {
- if (sym->section->flags & SEC_CODE)
- info->symbol_type = ST_CODE;
- else
- info->symbol_type = ST_DATA;
- }
+ info->symbol_type = ST_DATA;
/* From now on it's a very simple mapping. */
else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ABSOLUTE)
/* 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))
/* Compute total symbol table size and allocate a chunk of memory
to hold the symbol table as we build it. */
symtab_size = num_syms * sizeof (struct symbol_dictionary_record);
- som_symtab = (struct symbol_dictionary_record *) malloc (symtab_size);
+ som_symtab = (struct symbol_dictionary_record *) bfd_malloc (symtab_size);
if (som_symtab == NULL && symtab_size != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
memset (som_symtab, 0, symtab_size);
/* Walk over each symbol. */
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));
}
\f
}
/* Allocate and read in the string table. */
- stringtab = malloc (obj_som_stringtab_size (abfd));
+ stringtab = bfd_malloc (obj_som_stringtab_size (abfd));
if (stringtab == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
+ memset (stringtab, 0, obj_som_stringtab_size (abfd));
if (bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET) < 0)
return false;
stringtab = obj_som_stringtab (abfd);
- symbase = (som_symbol_type *)
- malloc (symbol_count * sizeof (som_symbol_type));
+ symbase = ((som_symbol_type *)
+ bfd_malloc (symbol_count * sizeof (som_symbol_type)));
if (symbase == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
+ memset (symbase, 0, symbol_count * sizeof (som_symbol_type));
/* Read in the external SOM representation. */
- buf = malloc (symbol_count * symsize);
+ buf = bfd_malloc (symbol_count * symsize);
if (buf == NULL && symbol_count * symsize != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
if (bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET) < 0)
goto error_return;
if (bfd_read (buf, symbol_count * symsize, 1, abfd)
Note $START$ is a magic code symbol, NOT a section symbol. */
if (sym->symbol.name[0] == '$'
&& sym->symbol.name[strlen (sym->symbol.name) - 1] == '$'
- && strcmp (sym->symbol.name, "$START$"))
+ && !strcmp (sym->symbol.name, sym->symbol.section->name))
sym->symbol.flags |= BSF_SECTION_SYM;
else if (!strncmp (sym->symbol.name, "L$0\002", 4))
{
sym++;
}
+ /* We modify the symbol count to record the number of BFD symbols we
+ created. */
+ bfd_get_symcount (abfd) = sym - symbase;
+
/* Save our results and return success. */
obj_som_symtab (abfd) = symbase;
successful_return:
som_symbol_type *new =
(som_symbol_type *) bfd_zalloc (abfd, sizeof (som_symbol_type));
if (new == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return 0;
- }
+ return 0;
new->symbol.the_bfd = abfd;
return &new->symbol;
asymbol **symbols;
boolean just_count;
{
- unsigned int op, varname;
+ unsigned int op, varname, deallocate_contents = 0;
unsigned char *end_fixups = &fixup[end];
const struct fixup_format *fp;
char *cp;
the stack. */
else if (islower (c))
{
+ int bits = (c - 'a') * 8;
for (v = 0; c > 'a'; --c)
v = (v << 8) | *fixup++;
+ if (varname == 'V')
+ v = sign_extend (v, bits);
push (v);
}
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)
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 if (som_hppa_howto_table[op].type == R_DATA_ONE_SYMBOL)
+ {
+ unsigned addend = var ('V');
+
+ /* Try what was specified in R_DATA_OVERRIDE first
+ (if anything). Then the hard way using the
+ section contents. */
+ rptr->addend = var ('V');
+
+ if (rptr->addend == 0 && !section->contents)
+ {
+ /* Got to read the damn contents first. We don't
+ bother saving the contents (yet). Add it one
+ day if the need arises. */
+ section->contents = bfd_malloc (section->_raw_size);
+ if (section->contents == NULL)
+ return -1;
+
+ deallocate_contents = 1;
+ bfd_get_section_contents (section->owner,
+ section,
+ section->contents,
+ 0,
+ section->_raw_size);
+ }
+ else if (rptr->addend == 0)
+ rptr->addend = bfd_get_32 (section->owner,
+ (section->contents
+ + offset - var ('L')));
+
+ }
else
rptr->addend = var ('V');
rptr++;
memset (stack, 0, sizeof (stack));
}
}
+ if (deallocate_contents)
+ free (section->contents);
+
return count;
#undef var
parsed. We must do so now to know how many relocations exist. */
if (section->reloc_count == -1)
{
- external_relocs = (char *) malloc (fixup_stream_size);
+ external_relocs = (char *) bfd_malloc (fixup_stream_size);
if (external_relocs == (char *) NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
/* Read in the external forms. */
if (bfd_seek (abfd,
obj_som_reloc_filepos (abfd) + section->rel_filepos,
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);
- return false;
- }
+ return false;
/* Process and internalize the relocations. */
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);
+ som_section_data (section)->reloc_stream = NULL;
+
/* Save our results and return success. */
section->relocation = internal_relocs;
return (true);
if (asect->flags & SEC_RELOC)
{
if (! som_slurp_reloc_table (abfd, asect, NULL, true))
- return false;
- return (asect->reloc_count + 1) * sizeof (arelent);
+ return -1;
+ return (asect->reloc_count + 1) * sizeof (arelent *);
}
/* There are no relocations. */
return 0;
newsect->used_by_bfd =
(PTR) bfd_zalloc (abfd, sizeof (struct som_section_data_struct));
if (!newsect->used_by_bfd)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
newsect->alignment_power = 3;
/* We allow more than three sections internally */
return true;
}
+/* Copy any private info we understand from the input symbol
+ to the output symbol. */
+
+static boolean
+som_bfd_copy_private_symbol_data (ibfd, isymbol, obfd, osymbol)
+ bfd *ibfd;
+ asymbol *isymbol;
+ bfd *obfd;
+ asymbol *osymbol;
+{
+ struct som_symbol *input_symbol = (struct som_symbol *) isymbol;
+ struct som_symbol *output_symbol = (struct som_symbol *) osymbol;
+
+ /* One day we may try to grok other private data. */
+ if (ibfd->xvec->flavour != bfd_target_som_flavour
+ || obfd->xvec->flavour != bfd_target_som_flavour)
+ return false;
+
+ /* The only private information we need to copy is the argument relocation
+ bits. */
+ output_symbol->tc_data.hppa_arg_reloc = input_symbol->tc_data.hppa_arg_reloc;
+
+ return true;
+}
+
/* Copy any private info we understand from the input section
to the output section. */
static boolean
if (ibfd->xvec->flavour != bfd_target_som_flavour
|| obfd->xvec->flavour != bfd_target_som_flavour
|| (!som_is_space (isection) && !som_is_subspace (isection)))
- return false;
+ return true;
som_section_data (osection)->copy_data
= (struct som_copyable_section_data_struct *)
bfd_zalloc (obfd, sizeof (struct som_copyable_section_data_struct));
if (som_section_data (osection)->copy_data == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
memcpy (som_section_data (osection)->copy_data,
som_section_data (isection)->copy_data,
/* One day we may try to grok other private data. */
if (ibfd->xvec->flavour != bfd_target_som_flavour
|| obfd->xvec->flavour != bfd_target_som_flavour)
- return false;
+ return true;
/* Allocate some memory to hold the data we need. */
obj_som_exec_data (obfd) = (struct som_exec_data *)
bfd_zalloc (obfd, sizeof (struct som_exec_data));
if (obj_som_exec_data (obfd) == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
/* Now copy the data. */
memcpy (obj_som_exec_data (obfd), obj_som_exec_data (ibfd),
bfd_zalloc (section->owner,
sizeof (struct som_copyable_section_data_struct));
if (som_section_data (section)->copy_data == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
}
som_section_data (section)->copy_data->sort_key = sort_key;
som_section_data (section)->copy_data->is_defined = defined;
bfd_zalloc (section->owner,
sizeof (struct som_copyable_section_data_struct));
if (som_section_data (section)->copy_data == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
}
som_section_data (section)->copy_data->sort_key = sort_key;
som_section_data (section)->copy_data->access_control_bits = access;
bfd_zalloc (abfd, sizeof (struct aux_id)
+ sizeof (unsigned int) + len + pad);
if (!obj_som_version_hdr (abfd))
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
obj_som_version_hdr (abfd)->header_id.type = VERSION_AUX_ID;
obj_som_version_hdr (abfd)->header_id.length = len + pad;
obj_som_version_hdr (abfd)->header_id.length += sizeof (int);
bfd_zalloc (abfd, sizeof (struct aux_id)
+ sizeof (unsigned int) + len + pad);
if (!obj_som_copyright_hdr (abfd))
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
obj_som_copyright_hdr (abfd)->header_id.type = COPYRIGHT_AUX_ID;
obj_som_copyright_hdr (abfd)->header_id.length = len + pad;
obj_som_copyright_hdr (abfd)->header_id.length += sizeof (int);
CONST char **functionname_ptr;
unsigned int *line_ptr;
{
- fprintf (stderr, "som_find_nearest_line unimplemented\n");
- fflush (stderr);
- abort ();
return (false);
}
bfd *abfd;
boolean reloc;
{
- fprintf (stderr, "som_sizeof_headers unimplemented\n");
+ (*_bfd_error_handler) ("som_sizeof_headers unimplemented");
fflush (stderr);
abort ();
return (0);
if (!(symbol->flags & (BSF_GLOBAL|BSF_LOCAL)))
return '?';
- if (bfd_is_abs_section (symbol->section))
+ if (bfd_is_abs_section (symbol->section)
+ || (som_symbol_data (symbol) != NULL
+ && som_symbol_data (symbol)->som_type == SYMBOL_TYPE_ABSOLUTE))
c = 'a';
else if (symbol->section)
c = som_section_type (symbol->section->name);
file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
hash_table =
- (unsigned int *) malloc (lst_header->hash_size * sizeof (unsigned int));
+ (unsigned int *) bfd_malloc (lst_header->hash_size
+ * sizeof (unsigned int));
if (hash_table == NULL && lst_header->hash_size != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
/* Don't forget to initialize the counter! */
*count = 0;
file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
hash_table =
- (unsigned int *) malloc (lst_header->hash_size * sizeof (unsigned int));
+ (unsigned int *) bfd_malloc (lst_header->hash_size
+ * sizeof (unsigned int));
if (hash_table == NULL && lst_header->hash_size != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
som_dict =
- (struct som_entry *) malloc (lst_header->module_count
- * sizeof (struct som_entry));
+ (struct som_entry *) bfd_malloc (lst_header->module_count
+ * sizeof (struct som_entry));
if (som_dict == NULL && lst_header->module_count != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
/* Read in the hash table. The has table is an array of 32bit file offsets
which point to the hash chains. */
/* Allocate space for the name and null terminate it too. */
set->name = bfd_zalloc (abfd, len + 1);
if (!set->name)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
if (bfd_read (set->name, 1, len, abfd) != len)
goto error_return;
/* Allocate space for the name and null terminate it too. */
set->name = bfd_zalloc (abfd, len + 1);
if (!set->name)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
if (bfd_read (set->name, 1, len, abfd) != len)
goto error_return;
(ardata->symdef_count
* sizeof (carsym)));
if (!ardata->symdefs)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
/* Now fill in the canonical archive symbols. */
if (som_bfd_fill_in_ar_symbols (abfd, &lst_header, &ardata->symdefs)
unsigned int maxname = abfd->xvec->ar_max_namelen;
hash_table =
- (unsigned int *) malloc (lst.hash_size * sizeof (unsigned int));
+ (unsigned int *) bfd_malloc (lst.hash_size * sizeof (unsigned int));
if (hash_table == NULL && lst.hash_size != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
som_dict =
- (struct som_entry *) malloc (lst.module_count
- * sizeof (struct som_entry));
+ (struct som_entry *) bfd_malloc (lst.module_count
+ * sizeof (struct som_entry));
if (som_dict == NULL && lst.module_count != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
last_hash_entry =
((struct lst_symbol_record **)
- malloc (lst.hash_size * sizeof (struct lst_symbol_record *)));
+ bfd_malloc (lst.hash_size * sizeof (struct lst_symbol_record *)));
if (last_hash_entry == NULL && lst.hash_size != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
/* Lots of fields are file positions relative to the start
of the lst record. So save its location. */
unsigned int thislen;
if (!normal)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
thislen = strlen (normal);
if (thislen > maxname)
extended_name_length += thislen + 1;
curr_som_offset = (curr_som_offset + 0x1) & ~0x1;
/* FIXME should be done with buffers just like everything else... */
- lst_syms = malloc (nsyms * sizeof (struct lst_symbol_record));
+ lst_syms = bfd_malloc (nsyms * sizeof (struct lst_symbol_record));
if (lst_syms == NULL && nsyms != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
- strings = malloc (string_size);
+ goto error_return;
+ strings = bfd_malloc (string_size);
if (strings == NULL && string_size != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
p = strings;
curr_lst_sym = lst_syms;
/* Keep track of where each SOM will finally reside; then look
at the next BFD. */
curr_som_offset += arelt_size (curr_bfd) + sizeof (struct ar_hdr);
+
+ /* A particular object in the archive may have an odd length; the
+ linker requires objects begin on an even boundary. So round
+ up the current offset as necessary. */
+ curr_som_offset = (curr_som_offset + 0x1) & ~0x1;
curr_bfd = curr_bfd->next;
som_index++;
}
lst_size = sizeof (struct lst_header);
/* Start building the LST header. */
+ /* FIXME: Do we need to examine each element to determine the
+ largest id number? */
lst.system_id = CPU_PA_RISC1_0;
lst.a_magic = LIBMAGIC;
lst.version_id = VERSION_ID;
/* End of miscellaneous support functions. */
+/* Linker support functions. */
+static boolean
+som_bfd_link_split_section (abfd, sec)
+ bfd *abfd;
+ asection *sec;
+{
+ return (som_is_subspace (sec) && sec->_raw_size > 240000);
+}
+
#define som_close_and_cleanup som_bfd_free_cached_info
+#define som_read_ar_hdr _bfd_generic_read_ar_hdr
#define som_openr_next_archived_file bfd_generic_openr_next_archived_file
+#define som_get_elt_at_index _bfd_generic_get_elt_at_index
#define som_generic_stat_arch_elt bfd_generic_stat_arch_elt
#define som_truncate_arname bfd_bsd_truncate_arname
#define som_slurp_extended_name_table _bfd_slurp_extended_name_table
#define som_update_armap_timestamp bfd_true
+#define som_bfd_print_private_bfd_data _bfd_generic_bfd_print_private_bfd_data
#define som_get_lineno _bfd_nosymbols_get_lineno
#define som_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define som_read_minisymbols _bfd_generic_read_minisymbols
+#define som_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
+#define som_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
#define som_bfd_get_relocated_section_contents \
bfd_generic_get_relocated_section_contents
#define som_bfd_link_add_symbols _bfd_generic_link_add_symbols
#define som_bfd_final_link _bfd_generic_final_link
+
const bfd_target som_vec =
{
"som", /* name */
bfd_target_som_flavour,
- true, /* target byte order */
- true, /* target headers byte order */
+ BFD_ENDIAN_BIG, /* target byte order */
+ BFD_ENDIAN_BIG, /* target headers byte order */
(HAS_RELOC | EXEC_P | /* object flags */
HAS_LINENO | HAS_DEBUG |
HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | DYNAMIC),
0,
'/', /* ar_pad_char */
14, /* ar_max_namelen */
- 3, /* minimum alignment */
bfd_getb64, bfd_getb_signed_64, bfd_putb64,
bfd_getb32, bfd_getb_signed_32, bfd_putb32,
bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */