#include "bfd.h"
#include "sysdep.h"
-#if defined (HOST_HPPAHPUX) || defined (HOST_HPPABSD)
+#if defined (HOST_HPPAHPUX) || defined (HOST_HPPABSD) || defined (HOST_HPPAOSF)
#include "libbfd.h"
#include "som.h"
static int log2 PARAMS ((unsigned int));
static bfd_reloc_status_type hppa_som_reloc PARAMS ((bfd *, arelent *,
asymbol *, PTR,
- asection *, bfd *));
+ asection *, bfd *,
+ char **));
static void som_initialize_reloc_queue PARAMS ((struct reloc_queue *));
static void som_reloc_queue_insert PARAMS ((unsigned char *, unsigned int,
struct reloc_queue *));
PARAMS ((bfd_arch_info_type *, bfd_reloc_code_real_type));
static char som_section_type PARAMS ((const char *));
static int som_decode_symclass PARAMS ((asymbol *));
+static boolean som_bfd_count_ar_symbols PARAMS ((bfd *, struct lst_header *,
+ symindex *));
+static boolean som_bfd_fill_in_ar_symbols PARAMS ((bfd *, struct lst_header *,
+ carsym **syms));
+static boolean som_slurp_armap PARAMS ((bfd *));
+static boolean som_write_armap PARAMS ((bfd *));
+static boolean som_slurp_extended_name_table PARAMS ((bfd *));
/* Map SOM section names to POSIX/BSD single-character symbol types.
-1
};
+/* These apparently are not in older versions of hpux reloc.h. */
+#ifndef R_DLT_REL
+#define R_DLT_REL 0x78
+#endif
+
+#ifndef R_AUX_UNWIND
+#define R_AUX_UNWIND 0xcf
+#endif
+
+#ifndef R_SEC_STMT
+#define R_SEC_STMT 0xd7
+#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_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_DLT_REL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DLT_REL"},
+ {R_DLT_REL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DLT_REL"},
{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_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
{R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
{R_TRANSLATED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_TRANSLATED"},
- {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
- {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
- {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
+ {R_AUX_UNWIND, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_AUX_UNWIND"},
{R_COMP1, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_COMP1"},
{R_COMP2, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_COMP2"},
{R_COMP3, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_COMP3"},
{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_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
- {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {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"},
unsigned int size;
struct reloc_queue *queue;
{
- if (!bcmp (p, queue[0].reloc, size)
+ if (queue[0].reloc && !bcmp (p, queue[0].reloc, size)
&& size == queue[0].size)
return 0;
- if (!bcmp (p, queue[1].reloc, size)
+ if (queue[1].reloc && !bcmp (p, queue[1].reloc, size)
&& size == queue[1].size)
return 1;
- if (!bcmp (p, queue[2].reloc, size)
+ if (queue[2].reloc && !bcmp (p, queue[2].reloc, size)
&& size == queue[2].size)
return 2;
- if (!bcmp (p, queue[3].reloc, size)
+ if (queue[3].reloc && !bcmp (p, queue[3].reloc, size)
&& size == queue[3].size)
return 3;
return -1;
}
static bfd_reloc_status_type
-hppa_som_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd)
+hppa_som_reloc (abfd, reloc_entry, symbol_in, data,
+ input_section, output_bfd, error_message)
bfd *abfd;
arelent *reloc_entry;
asymbol *symbol_in;
PTR data;
asection *input_section;
bfd *output_bfd;
+ char **error_message;
{
if (output_bfd)
{
final_types = (int **) bfd_alloc_by_size_t (abfd, sizeof (int *) * 3);
final_type = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types || !final_type)
+ {
+ bfd_error = no_memory;
+ return NULL;
+ }
/* The field selector may require additional relocations to be
generated. It's impossible to know at this moment if additional
case e_psel:
case e_lpsel:
case e_rpsel:
+ final_types[0] = final_type;
+ final_types[1] = NULL;
+ final_types[2] = NULL;
+ *final_type = base_type;
+ break;
+
case e_tsel:
case e_ltsel:
case e_rtsel:
- final_types[0] = final_type;
- final_types[1] = NULL;
+ final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types[0])
+ {
+ bfd_error = no_memory;
+ return NULL;
+ }
+ if (field == e_tsel)
+ *final_types[0] = R_FSEL;
+ else if (field == e_ltsel)
+ *final_types[0] = R_LSEL;
+ else
+ *final_types[0] = R_RSEL;
+ final_types[1] = final_type;
final_types[2] = NULL;
*final_type = base_type;
break;
case e_lssel:
case e_rssel:
final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types[0])
+ {
+ bfd_error = no_memory;
+ return NULL;
+ }
*final_types[0] = R_S_MODE;
final_types[1] = final_type;
final_types[2] = NULL;
case e_lsel:
case e_rsel:
final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types[0])
+ {
+ bfd_error = no_memory;
+ return NULL;
+ }
*final_types[0] = R_N_MODE;
final_types[1] = final_type;
final_types[2] = NULL;
case e_ldsel:
case e_rdsel:
final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types[0])
+ {
+ bfd_error = no_memory;
+ return NULL;
+ }
*final_types[0] = R_D_MODE;
final_types[1] = final_type;
final_types[2] = NULL;
case e_lrsel:
case e_rrsel:
final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types[0])
+ {
+ bfd_error = no_memory;
+ return NULL;
+ }
*final_types[0] = R_R_MODE;
final_types[1] = final_type;
final_types[2] = NULL;
if (field == e_psel
|| field == e_lpsel
|| field == e_rpsel)
- {
- /* A PLABEL relocation that has a size of 32 bits must
- be a R_DATA_PLABEL. All others are R_CODE_PLABELs. */
- if (format == 32)
- *final_type = R_DATA_PLABEL;
- else
- *final_type = R_CODE_PLABEL;
- }
- /* A relocatoin in the data space is always a full 32bits. */
+ {
+ /* A PLABEL relocation that has a size of 32 bits must
+ be a R_DATA_PLABEL. All others are R_CODE_PLABELs. */
+ if (format == 32)
+ *final_type = R_DATA_PLABEL;
+ else
+ *final_type = R_CODE_PLABEL;
+ }
+ /* PIC stuff. */
+ else if (field == e_tsel
+ || field == e_ltsel
+ || field == e_rtsel)
+ *final_type = R_DLT_REL;
+ /* A relocation in the data space is always a full 32bits. */
else if (format == 32)
*final_type = R_DATA_ONE_SYMBOL;
}
newname = bfd_alloc (abfd, strlen (sect->name) + 1);
+ if (!newname)
+ {
+ bfd_error = no_memory;
+ return NULL;
+ }
strcpy (newname, sect->name);
sect->name = newname;
bfd_error = no_memory;
return false;
}
- obj_som_file_hdr (abfd) = bfd_zalloc (abfd, sizeof (struct header));
+ obj_som_file_hdr (abfd)
+ = (struct header *) bfd_zalloc (abfd, sizeof (struct header));
if (obj_som_file_hdr (abfd) == NULL)
{
if ((*sym1)->flags & BSF_SECTION_SYM)
count1 = (int)(*sym1)->udata;
else
- count1 = (*som_symbol_data ((*sym1)))->reloc_count;
+ count1 = som_symbol_data (*sym1)->reloc_count;
if ((*sym2)->flags & BSF_SECTION_SYM)
count2 = (int)(*sym2)->udata;
else
- count2 = (*som_symbol_data ((*sym2)))->reloc_count;
+ count2 = som_symbol_data (*sym2)->reloc_count;
/* Return the appropriate value. */
if (count1 < count2)
syms[i]->udata = (PTR) 0;
}
else
- (*som_symbol_data (syms[i]))->reloc_count = 0;
+ som_symbol_data (syms[i])->reloc_count = 0;
}
/* Now that the counters are initialized, make a weighted count
}
/* A normal symbol. Increment the count. */
- (*som_symbol_data ((*reloc->sym_ptr_ptr)))->reloc_count += scale;
+ som_symbol_data (*reloc->sym_ptr_ptr)->reloc_count += scale;
}
}
if (syms[i]->flags & BSF_SECTION_SYM)
syms[i]->udata = (PTR) i;
else
- (*som_symbol_data (syms[i]))->index = i;
+ som_symbol_data (syms[i])->index = i;
}
}
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;
+ 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
case R_S_MODE:
case R_D_MODE:
case R_R_MODE:
+ case R_FSEL:
+ case R_LSEL:
+ case R_RSEL:
reloc_offset = bfd_reloc->address;
break;
case R_DATA_ONE_SYMBOL:
case R_DATA_PLABEL:
case R_CODE_PLABEL:
+ case R_DLT_REL:
/* Account for any addend. */
if (bfd_reloc->addend)
p = som_reloc_addend (abfd, bfd_reloc->addend, p,
case R_ENTRY:
{
int *descp
- = (int *) (*som_symbol_data ((*bfd_reloc->sym_ptr_ptr)))->unwind;
+ = (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);
}
break;
+ case R_FSEL:
+ case R_LSEL:
+ case R_RSEL:
+ bfd_put_8 (abfd, bfd_reloc->howto->type, 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. */
current_offset += sizeof (struct header);
/* Any auxiliary headers will follow the file header. Right now
- we have no auxiliary headers, so current_offset does not change. */
+ we support only the copyright and version headers. */
obj_som_file_hdr (abfd)->aux_header_location = current_offset;
obj_som_file_hdr (abfd)->aux_header_size = 0;
+ if (obj_som_version_hdr (abfd) != NULL)
+ {
+ unsigned int len;
+
+ bfd_seek (abfd, current_offset, SEEK_SET);
+
+ /* Write the aux_id structure and the string length. */
+ len = sizeof (struct aux_id) + sizeof (unsigned int);
+ obj_som_file_hdr (abfd)->aux_header_size += len;
+ current_offset += len;
+ if (bfd_write ((PTR) obj_som_version_hdr (abfd), len, 1, abfd) != len)
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+
+ /* Write the version string. */
+ len = obj_som_version_hdr (abfd)->header_id.length - sizeof (int);
+ obj_som_file_hdr (abfd)->aux_header_size += len;
+ current_offset += len;
+ if (bfd_write ((PTR) obj_som_version_hdr (abfd)->user_string,
+ len, 1, abfd) != len)
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+ }
+
+ if (obj_som_copyright_hdr (abfd) != NULL)
+ {
+ unsigned int len;
+
+ bfd_seek (abfd, current_offset, SEEK_SET);
+
+ /* Write the aux_id structure and the string length. */
+ len = sizeof (struct aux_id) + sizeof (unsigned int);
+ obj_som_file_hdr (abfd)->aux_header_size += len;
+ current_offset += len;
+ if (bfd_write ((PTR) obj_som_copyright_hdr (abfd), len, 1, abfd) != len)
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+
+ /* Write the copyright string. */
+ len = obj_som_copyright_hdr (abfd)->header_id.length - sizeof (int);
+ obj_som_file_hdr (abfd)->aux_header_size += len;
+ current_offset += len;
+ if (bfd_write ((PTR) obj_som_copyright_hdr (abfd)->copyright,
+ len, 1, abfd) != len)
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+ }
- /* Next comes the initialization pointers; again we have no
- initialization pointers, so current offset does not change. */
+ /* Next comes the initialization pointers; we have no initialization
+ pointers, so current offset does not change. */
obj_som_file_hdr (abfd)->init_array_location = current_offset;
obj_som_file_hdr (abfd)->init_array_total = 0;
locally. If BSF_FUNCTION is set for this symbol, then
assign it type ST_CODE (the HP linker requires undefined
external functions to have type ST_CODE rather than ST_ENTRY. */
- else if (((*som_symbol_data (bfd_syms[i]))->som_type
+ else if ((som_symbol_data (bfd_syms[i])->som_type
== SYMBOL_TYPE_UNKNOWN)
&& (bfd_syms[i]->section == &bfd_und_section)
&& (bfd_syms[i]->flags & BSF_FUNCTION))
/* Handle function symbols which were defined in this file.
They should have type ST_ENTRY. Also retrieve the argument
relocation bits from the SOM backend information. */
- else if (((*som_symbol_data (bfd_syms[i]))->som_type
+ else if ((som_symbol_data (bfd_syms[i])->som_type
== SYMBOL_TYPE_ENTRY)
- || (((*som_symbol_data (bfd_syms[i]))->som_type
+ || ((som_symbol_data (bfd_syms[i])->som_type
== SYMBOL_TYPE_CODE)
&& (bfd_syms[i]->flags & BSF_FUNCTION))
- || (((*som_symbol_data (bfd_syms[i]))->som_type
+ || ((som_symbol_data (bfd_syms[i])->som_type
== SYMBOL_TYPE_UNKNOWN)
&& (bfd_syms[i]->flags & BSF_FUNCTION)))
{
som_symtab[i].symbol_type = ST_ENTRY;
som_symtab[i].arg_reloc
- = (*som_symbol_data (bfd_syms[i]))->tc_data.hppa_arg_reloc;
+ = som_symbol_data (bfd_syms[i])->tc_data.hppa_arg_reloc;
}
/* If the type is unknown at this point, it should be
ST_DATA (functions were handled as special cases above). */
- else if ((*som_symbol_data (bfd_syms[i]))->som_type
+ else if (som_symbol_data (bfd_syms[i])->som_type
== SYMBOL_TYPE_UNKNOWN)
som_symtab[i].symbol_type = ST_DATA;
/* From now on it's a very simple mapping. */
- else if ((*som_symbol_data (bfd_syms[i]))->som_type
+ else if (som_symbol_data (bfd_syms[i])->som_type
== SYMBOL_TYPE_ABSOLUTE)
som_symtab[i].symbol_type = ST_ABSOLUTE;
- else if ((*som_symbol_data (bfd_syms[i]))->som_type
+ else if (som_symbol_data (bfd_syms[i])->som_type
== SYMBOL_TYPE_CODE)
som_symtab[i].symbol_type = ST_CODE;
- else if ((*som_symbol_data (bfd_syms[i]))->som_type
+ else if (som_symbol_data (bfd_syms[i])->som_type
== SYMBOL_TYPE_DATA)
som_symtab[i].symbol_type = ST_DATA;
- else if ((*som_symbol_data (bfd_syms[i]))->som_type
+ else if (som_symbol_data (bfd_syms[i])->som_type
== SYMBOL_TYPE_MILLICODE)
som_symtab[i].symbol_type = ST_MILLICODE;
- else if ((*som_symbol_data (bfd_syms[i]))->som_type
+ else if (som_symbol_data (bfd_syms[i])->som_type
== SYMBOL_TYPE_PLABEL)
som_symtab[i].symbol_type = ST_PLABEL;
- else if ((*som_symbol_data (bfd_syms[i]))->som_type
+ else if (som_symbol_data (bfd_syms[i])->som_type
== SYMBOL_TYPE_PRI_PROG)
som_symtab[i].symbol_type = ST_PRI_PROG;
- else if ((*som_symbol_data (bfd_syms[i]))->som_type
+ else if (som_symbol_data (bfd_syms[i])->som_type
== SYMBOL_TYPE_SEC_PROG)
som_symtab[i].symbol_type = ST_SEC_PROG;
}
rptr->address = offset;
rptr->howto = &som_hppa_howto_table[op];
rptr->addend = 0;
+ rptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
}
/* Set default input length to 0. Get the opcode class index
bfd *abfd;
asection *newsect;
{
- newsect->used_by_bfd = (struct som_section_data_struct *)
- bfd_zalloc (abfd, sizeof (struct som_section_data_struct));
+ newsect->used_by_bfd =
+ (PTR) bfd_zalloc (abfd, sizeof (struct som_section_data_struct));
+ if (!newsect->used_by_bfd)
+ {
+ bfd_error = no_memory;
+ return false;
+ }
newsect->alignment_power = 3;
/* Initialize the subspace_index field to -1 so that it does
void
bfd_som_set_section_attributes (section, defined, private, sort_key, spnum)
asection *section;
- char defined;
- char private;
+ int defined;
+ int private;
unsigned char sort_key;
int spnum;
{
asection *section;
asection *container;
int access;
- unsigned char sort_key;
+ unsigned int sort_key;
int quadrant;
{
struct subspace_dictionary_record *subspace_dict;
asymbol *symbol;
unsigned int type;
{
- (*som_symbol_data (symbol))->som_type = type;
+ som_symbol_data (symbol)->som_type = type;
}
/* Attach 64bits of unwind information to a symbol (which hopefully
asymbol *symbol;
char *unwind_desc;
{
- (*som_symbol_data (symbol))->unwind = unwind_desc;
+ som_symbol_data (symbol)->unwind = unwind_desc;
+}
+
+/* Attach an auxiliary header to the BFD backend so that it may be
+ written into the object file. */
+void
+bfd_som_attach_aux_hdr (abfd, type, string)
+ bfd *abfd;
+ int type;
+ char *string;
+{
+ if (type == VERSION_AUX_ID)
+ {
+ int len = strlen (string);
+ int pad = 0;
+
+ if (len % 4)
+ pad = (4 - (len % 4));
+ obj_som_version_hdr (abfd) = (struct user_string_aux_hdr *)
+ bfd_zalloc (abfd, sizeof (struct aux_id)
+ + sizeof (unsigned int) + len + pad);
+ if (!obj_som_version_hdr (abfd))
+ {
+ bfd_error = no_memory;
+ abort(); /* FIXME */
+ }
+ 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);
+ obj_som_version_hdr (abfd)->string_length = len;
+ strncpy (obj_som_version_hdr (abfd)->user_string, string, len);
+ }
+ else if (type == COPYRIGHT_AUX_ID)
+ {
+ int len = strlen (string);
+ int pad = 0;
+
+ if (len % 4)
+ pad = (4 - (len % 4));
+ obj_som_copyright_hdr (abfd) = (struct copyright_aux_hdr *)
+ bfd_zalloc (abfd, sizeof (struct aux_id)
+ + sizeof (unsigned int) + len + pad);
+ if (!obj_som_copyright_hdr (abfd))
+ {
+ bfd_error = no_error;
+ abort(); /* FIXME */
+ }
+ 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);
+ obj_som_copyright_hdr (abfd)->string_length = len;
+ strcpy (obj_som_copyright_hdr (abfd)->copyright, string);
+ }
+ else
+ abort ();
}
static boolean
ret->name = symbol->name;
}
+/* Count the number of symbols in the archive symbol table. Necessary
+ so that we can allocate space for all the carsyms at once. */
+
+static boolean
+som_bfd_count_ar_symbols (abfd, lst_header, count)
+ bfd *abfd;
+ struct lst_header *lst_header;
+ symindex *count;
+{
+ unsigned int i;
+ unsigned int hash_table[lst_header->hash_size];
+ file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
+
+ /* Don't forget to initialize the counter! */
+ *count = 0;
+
+ /* Read in the hash table. The has table is an array of 32bit file offsets
+ which point to the hash chains. */
+ if (bfd_read ((PTR) hash_table, lst_header->hash_size, 4, abfd)
+ != lst_header->hash_size * 4)
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+
+ /* Walk each chain counting the number of symbols found on that particular
+ chain. */
+ for (i = 0; i < lst_header->hash_size; i++)
+ {
+ struct lst_symbol_record lst_symbol;
+
+ /* An empty chain has zero as it's file offset. */
+ if (hash_table[i] == 0)
+ continue;
+
+ /* Seek to the first symbol in this hash chain. */
+ if (bfd_seek (abfd, lst_filepos + hash_table[i], SEEK_SET) < 0)
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+
+ /* Read in this symbol and update the counter. */
+ if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
+ != sizeof (lst_symbol))
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+ (*count)++;
+
+ /* Now iterate through the rest of the symbols on this chain. */
+ while (lst_symbol.next_entry)
+ {
+
+ /* Seek to the next symbol. */
+ if (bfd_seek (abfd, lst_filepos + lst_symbol.next_entry, SEEK_SET)
+ < 0)
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+
+ /* Read the symbol in and update the counter. */
+ if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
+ != sizeof (lst_symbol))
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+ (*count)++;
+ }
+ }
+ return true;
+}
+
+/* Fill in the canonical archive symbols (SYMS) from the archive described
+ by ABFD and LST_HEADER. */
+
+static boolean
+som_bfd_fill_in_ar_symbols (abfd, lst_header, syms)
+ bfd *abfd;
+ struct lst_header *lst_header;
+ carsym **syms;
+{
+ unsigned int i, len;
+ carsym *set = syms[0];
+ unsigned int hash_table[lst_header->hash_size];
+ struct som_entry som_dict[lst_header->module_count];
+ file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
+
+ /* Read in the hash table. The has table is an array of 32bit file offsets
+ which point to the hash chains. */
+ if (bfd_read ((PTR) hash_table, lst_header->hash_size, 4, abfd)
+ != lst_header->hash_size * 4)
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+
+ /* Seek to and read in the SOM dictionary. We will need this to fill
+ in the carsym's filepos field. */
+ if (bfd_seek (abfd, lst_filepos + lst_header->dir_loc, SEEK_SET) < 0)
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+
+ if (bfd_read ((PTR) som_dict, lst_header->module_count,
+ sizeof (struct som_entry), abfd)
+ != lst_header->module_count * sizeof (struct som_entry))
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+
+ /* Walk each chain filling in the carsyms as we go along. */
+ for (i = 0; i < lst_header->hash_size; i++)
+ {
+ struct lst_symbol_record lst_symbol;
+
+ /* An empty chain has zero as it's file offset. */
+ if (hash_table[i] == 0)
+ continue;
+
+ /* Seek to and read the first symbol on the chain. */
+ if (bfd_seek (abfd, lst_filepos + hash_table[i], SEEK_SET) < 0)
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+
+ if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
+ != sizeof (lst_symbol))
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+
+ /* Get the name of the symbol, first get the length which is stored
+ as a 32bit integer just before the symbol.
+
+ One might ask why we don't just read in the entire string table
+ and index into it. Well, according to the SOM ABI the string
+ index can point *anywhere* in the archive to save space, so just
+ using the string table would not be safe. */
+ if (bfd_seek (abfd, lst_filepos + lst_header->string_loc
+ + lst_symbol.name.n_strx - 4, SEEK_SET) < 0)
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+
+ if (bfd_read (&len, 1, 4, abfd) != 4)
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+
+ /* Allocate space for the name and null terminate it too. */
+ set->name = bfd_zalloc (abfd, len + 1);
+ if (!set->name)
+ {
+ bfd_error = no_memory;
+ return false;
+ }
+ if (bfd_read (set->name, 1, len, abfd) != len)
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+ set->name[len] = 0;
+
+ /* Fill in the file offset. Note that the "location" field points
+ to the SOM itself, not the ar_hdr in front of it. */
+ set->file_offset = som_dict[lst_symbol.som_index].location
+ - sizeof (struct ar_hdr);
+
+ /* Go to the next symbol. */
+ set++;
+
+ /* Iterate through the rest of the chain. */
+ while (lst_symbol.next_entry)
+ {
+ /* Seek to the next symbol and read it in. */
+ if (bfd_seek (abfd, lst_filepos + lst_symbol.next_entry, SEEK_SET)
+ < 0)
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+
+ if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
+ != sizeof (lst_symbol))
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+
+ /* Seek to the name length & string and read them in. */
+ if (bfd_seek (abfd, lst_filepos + lst_header->string_loc
+ + lst_symbol.name.n_strx - 4, SEEK_SET) < 0)
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+
+ if (bfd_read (&len, 1, 4, abfd) != 4)
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+
+ /* Allocate space for the name and null terminate it too. */
+ set->name = bfd_zalloc (abfd, len + 1);
+ if (!set->name)
+ {
+ bfd_error = no_memory;
+ return false;
+ }
+ if (bfd_read (set->name, 1, len, abfd) != len)
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+ set->name[len] = 0;
+
+ /* Fill in the file offset. Note that the "location" field points
+ to the SOM itself, not the ar_hdr in front of it. */
+ set->file_offset = som_dict[lst_symbol.som_index].location
+ - sizeof (struct ar_hdr);
+
+ /* Go on to the next symbol. */
+ set++;
+ }
+ }
+ /* If we haven't died by now, then we successfully read the entire
+ archive symbol table. */
+ return true;
+}
+
+/* Read in the LST from the archive. */
+static boolean
+som_slurp_armap (abfd)
+ bfd *abfd;
+{
+ struct lst_header lst_header;
+ struct ar_hdr ar_header;
+ unsigned int parsed_size;
+ struct artdata *ardata = bfd_ardata (abfd);
+ char nextname[17];
+ int i = bfd_read ((PTR) nextname, 1, 16, abfd);
+
+ /* Special cases. */
+ if (i == 0)
+ return true;
+ if (i != 16)
+ return false;
+
+ if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) < 0)
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+
+ /* For archives without .o files there is no symbol table. */
+ if (strncmp (nextname, "/ ", 16))
+ {
+ bfd_has_map (abfd) = false;
+ return true;
+ }
+
+ /* Read in and sanity check the archive header. */
+ if (bfd_read ((PTR) &ar_header, 1, sizeof (struct ar_hdr), abfd)
+ != sizeof (struct ar_hdr))
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+
+ if (strncmp (ar_header.ar_fmag, ARFMAG, 2))
+ {
+ bfd_error = malformed_archive;
+ return NULL;
+ }
+
+ /* How big is the archive symbol table entry? */
+ errno = 0;
+ parsed_size = strtol (ar_header.ar_size, NULL, 10);
+ if (errno != 0)
+ {
+ bfd_error = malformed_archive;
+ return NULL;
+ }
+
+ /* Save off the file offset of the first real user data. */
+ ardata->first_file_filepos = bfd_tell (abfd) + parsed_size;
+
+ /* Read in the library symbol table. We'll make heavy use of this
+ in just a minute. */
+ if (bfd_read ((PTR) & lst_header, 1, sizeof (struct lst_header), abfd)
+ != sizeof (struct lst_header))
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+
+ /* Sanity check. */
+ if (lst_header.a_magic != LIBMAGIC)
+ {
+ bfd_error = malformed_archive;
+ return NULL;
+ }
+
+ /* Count the number of symbols in the library symbol table. */
+ if (som_bfd_count_ar_symbols (abfd, &lst_header, &ardata->symdef_count)
+ == false)
+ return false;
+
+ /* Get back to the start of the library symbol table. */
+ if (bfd_seek (abfd, ardata->first_file_filepos - parsed_size
+ + sizeof (struct lst_header), SEEK_SET) < 0)
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+
+ /* Initializae the cache and allocate space for the library symbols. */
+ ardata->cache = 0;
+ ardata->symdefs = (carsym *) bfd_alloc (abfd,
+ (ardata->symdef_count
+ * sizeof (carsym)));
+ if (!ardata->symdefs)
+ {
+ bfd_error = no_memory;
+ return false;
+ }
+
+ /* Now fill in the canonical archive symbols. */
+ if (som_bfd_fill_in_ar_symbols (abfd, &lst_header, &ardata->symdefs)
+ == false)
+ return false;
+
+ /* Notify the generic archive code that we have a symbol map. */
+ bfd_has_map (abfd) = true;
+ return true;
+}
+
+/* Write out the LST for the archive. Not supported yet. */
+static boolean
+som_write_armap (abfd)
+ bfd *abfd;
+{
+ return false;
+}
+
+/* Apparently the extened names are never used, even though they appear
+ in the SOM ABI. Hmmm. */
+static boolean
+som_slurp_extended_name_table (abfd)
+ bfd *abfd;
+{
+ bfd_ardata (abfd)->extended_names = NULL;
+ return true;
+}
+
/* End of miscellaneous support functions. */
#define som_bfd_debug_info_start bfd_void
#define som_bfd_debug_info_end bfd_void
#define som_bfd_debug_info_accumulate (PROTO(void,(*),(bfd*, struct sec *))) bfd_void
-#define som_openr_next_archived_file bfd_generic_openr_next_archived_file
-#define som_generic_stat_arch_elt bfd_generic_stat_arch_elt
-#define som_slurp_armap bfd_false
-#define som_slurp_extended_name_table _bfd_slurp_extended_name_table
-#define som_truncate_arname (void (*)())bfd_nullvoidptr
-#define som_write_armap 0
+#define som_openr_next_archived_file bfd_generic_openr_next_archived_file
+#define som_generic_stat_arch_elt bfd_generic_stat_arch_elt
+#define som_truncate_arname bfd_bsd_truncate_arname
#define som_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
#define som_close_and_cleanup bfd_generic_close_and_cleanup
#define som_bfd_get_relocated_section_contents \
bfd_generic_get_relocated_section_contents
#define som_bfd_relax_section bfd_generic_relax_section
-#define som_bfd_seclet_link bfd_generic_seclet_link
#define som_bfd_make_debug_symbol \
((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
+#define som_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
+#define som_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define som_bfd_final_link _bfd_generic_final_link
/* Core file support is in the hpux-core backend. */
#define som_core_file_failing_command _bfd_dummy_core_file_failing_command
(PTR) 0
};
-#endif /* HOST_HPPAHPUX || HOST_HPPABSD */
+#endif /* HOST_HPPAHPUX || HOST_HPPABSD || HOST_HPPAOSF */