/* bfd back-end for HP PA-RISC SOM objects.
- Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 97, 1998
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
#include "bfd.h"
#include "sysdep.h"
#include <machine/reg.h>
#include <sys/file.h>
#include <errno.h>
+#include <ctype.h>
/* Magic not defined in standard HP-UX header files until 8.0 */
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_bfd_is_local_label_name PARAMS ((bfd *, const char *));
static boolean som_set_section_contents PARAMS ((bfd *, sec_ptr, PTR,
file_ptr, bfd_size_type));
static boolean som_get_section_contents PARAMS ((bfd *, sec_ptr, PTR,
static unsigned int som_bfd_ar_symbol_hash PARAMS ((asymbol *));
static boolean som_bfd_ar_write_symbol_stuff PARAMS ((bfd *, unsigned int,
unsigned int,
- struct lst_header));
-static CONST char *normalize PARAMS ((CONST char *file));
+ struct lst_header,
+ unsigned int));
static boolean som_is_space PARAMS ((asection *));
static boolean som_is_subspace PARAMS ((asection *));
static boolean som_is_container PARAMS ((asection *, asection *));
and a field selector, return one or more appropriate SOM relocations. */
int **
-hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff)
+hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff, sym)
bfd *abfd;
int base_type;
int format;
enum hppa_reloc_field_selector_type_alt field;
int sym_diff;
+ asymbol *sym;
{
int *final_type, **final_types;
- final_types = (int **) bfd_alloc_by_size_t (abfd, sizeof (int *) * 6);
- final_type = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types = (int **) bfd_alloc (abfd, sizeof (int *) * 6);
+ final_type = (int *) bfd_alloc (abfd, sizeof (int));
if (!final_types || !final_type)
return NULL;
case e_tsel:
case e_ltsel:
case e_rtsel:
- final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[0] = (int *) bfd_alloc (abfd, sizeof (int));
if (!final_types[0])
return NULL;
if (field == e_tsel)
case e_lssel:
case e_rssel:
- final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[0] = (int *) bfd_alloc (abfd, sizeof (int));
if (!final_types[0])
return NULL;
*final_types[0] = R_S_MODE;
case e_lsel:
case e_rsel:
- final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[0] = (int *) bfd_alloc (abfd, sizeof (int));
if (!final_types[0])
return NULL;
*final_types[0] = R_N_MODE;
case e_ldsel:
case e_rdsel:
- final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[0] = (int *) bfd_alloc (abfd, sizeof (int));
if (!final_types[0])
return NULL;
*final_types[0] = R_D_MODE;
case e_lrsel:
case e_rrsel:
- final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[0] = (int *) bfd_alloc (abfd, sizeof (int));
if (!final_types[0])
return NULL;
*final_types[0] = R_R_MODE;
break;
case e_nsel:
- final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[0] = (int *) bfd_alloc (abfd, sizeof (int));
if (!final_types[0])
return NULL;
*final_types[0] = R_N1SEL;
case e_nlsel:
case e_nlrsel:
- final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[0] = (int *) bfd_alloc (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));
+ final_types[1] = (int *) bfd_alloc (abfd, sizeof (int));
if (!final_types[1])
return NULL;
if (field == e_nlsel)
/* 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));
+ final_types[0] = (int *)bfd_alloc (abfd, sizeof (int));
+ final_types[1] = (int *)bfd_alloc (abfd, sizeof (int));
+ final_types[2] = (int *)bfd_alloc (abfd, sizeof (int));
+ final_types[3] = (int *)bfd_alloc (abfd, sizeof (int));
if (!final_types[0] || !final_types[1] || !final_types[2])
return NULL;
if (field == e_fsel)
*final_types[2] = R_COMP2;
*final_types[3] = R_COMP1;
final_types[4] = final_type;
- *final_types[4] = R_CODE_EXPR;
+ if (format == 32)
+ *final_types[4] = R_DATA_EXPR;
+ else
+ *final_types[4] = R_CODE_EXPR;
final_types[5] = NULL;
break;
}
- else if (field == e_esel)
- {
- final_types[0] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
- *final_types[0] = R_COMP2;
- final_types[1] = final_type;
- *final_types[1] = R_DATA_EXPR;
- final_types[2] = NULL;
- break;;
- }
/* PLABELs get their own relocation type. */
else if (field == e_psel
|| field == e_lpsel
*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;
+ {
+ *final_type = R_DATA_ONE_SYMBOL;
+ /* If there's no SOM symbol type associated with this BFD
+ symbol, then set the symbol type to ST_DATA.
+
+ Only do this if the type is going to default later when
+ we write the object file.
+
+ This is done so that the linker never encounters an
+ R_DATA_ONE_SYMBOL reloc involving an ST_CODE symbol.
+
+ This allows the compiler to generate exception handling
+ tables.
+
+ Note that one day we may need to also emit BEGIN_BRTAB and
+ END_BRTAB to prevent the linker from optimizing away insns
+ in exception handling regions. */
+ if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
+ && (sym->flags & BSF_SECTION_SYM) == 0
+ && (sym->flags & BSF_FUNCTION) == 0
+ && ! bfd_is_com_section (sym->section))
+ som_symbol_data (sym)->som_type = SYMBOL_TYPE_DATA;
+ }
break;
+
case R_HPPA_GOTOFF:
/* More PLABEL special cases. */
if (field == e_psel
/* 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));
+ final_types[0] = (int *)bfd_alloc (abfd, sizeof (int));
+ final_types[1] = (int *)bfd_alloc (abfd, sizeof (int));
+ final_types[2] = (int *)bfd_alloc (abfd, sizeof (int));
+ final_types[3] = (int *)bfd_alloc (abfd, sizeof (int));
if (!final_types[0] || !final_types[1] || !final_types[2])
return NULL;
if (field == e_fsel)
*final_types[2] = R_COMP2;
*final_types[3] = R_COMP1;
final_types[4] = final_type;
- *final_types[4] = R_CODE_EXPR;
+ if (format == 32)
+ *final_types[4] = R_DATA_EXPR;
+ else
+ *final_types[4] = R_CODE_EXPR;
final_types[5] = NULL;
break;
}
return 0;
/* Set BFD flags based on what information is available in the SOM. */
- abfd->flags = NO_FLAGS;
+ abfd->flags = BFD_NO_FLAGS;
if (file_hdrp->symbol_total)
abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
goto error_return;
}
- /* Yow! there is no subspace within the space which actually
- has initialized information in it; this should never happen
- as far as I know. */
+ /* This can happen for a .o which defines symbols in otherwise
+ empty subspaces. */
if (!save_subspace.file_loc_init_value)
- goto error_return;
-
- /* Setup the sizes for the space section based upon the info in the
- last subspace of the space. */
- space_asect->_cooked_size = save_subspace.subspace_start
- - space_asect->vma + save_subspace.subspace_length;
- space_asect->_raw_size = save_subspace.file_loc_init_value
- - space_asect->filepos + save_subspace.initialization_length;
+ {
+ space_asect->_cooked_size = 0;
+ space_asect->_raw_size = 0;
+ }
+ else
+ {
+ /* Setup the sizes for the space section based upon the info in the
+ last subspace of the space. */
+ space_asect->_cooked_size = (save_subspace.subspace_start
+ - space_asect->vma
+ + save_subspace.subspace_length);
+ 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. */
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 the symbol's type based on the symbol's
+ section (ST_DATA for DATA sections, ST_CODE for CODE sections). */
else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN)
{
if (sym->section->flags & SEC_CODE)
else
info->symbol_type = ST_DATA;
}
+
+ else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN)
+ 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)
}
static boolean
-som_bfd_is_local_label (abfd, sym)
+som_bfd_is_local_label_name (abfd, name)
bfd *abfd;
- asymbol *sym;
+ const char *name;
{
- return (sym->name[0] == 'L' && sym->name[1] == '$');
+ return (name[0] == 'L' && name[1] == '$');
}
/* Count or process variable-length SOM fixup records.
bfd *abfd;
boolean reloc;
{
- (*_bfd_error_handler) ("som_sizeof_headers unimplemented");
+ (*_bfd_error_handler) (_("som_sizeof_headers unimplemented"));
fflush (stderr);
abort ();
return (0);
| (symbol->name[len-2] << 8) | symbol->name[len-1];
}
-static CONST char *
-normalize (file)
- CONST char *file;
-{
- CONST char *filename = strrchr (file, '/');
-
- if (filename != NULL)
- filename++;
- else
- filename = file;
- return filename;
-}
-
/* Do the bulk of the work required to write the SOM library
symbol table. */
static boolean
-som_bfd_ar_write_symbol_stuff (abfd, nsyms, string_size, lst)
+som_bfd_ar_write_symbol_stuff (abfd, nsyms, string_size, lst, elength)
bfd *abfd;
unsigned int nsyms, string_size;
struct lst_header lst;
+ unsigned elength;
{
file_ptr lst_filepos;
char *strings = NULL, *p;
unsigned int *hash_table = NULL;
struct som_entry *som_dict = NULL;
struct lst_symbol_record **last_hash_entry = NULL;
- unsigned int curr_som_offset, som_index, extended_name_length = 0;
- unsigned int maxname = abfd->xvec->ar_max_namelen;
+ unsigned int curr_som_offset, som_index = 0;
hash_table =
(unsigned int *) bfd_malloc (lst.hash_size * sizeof (unsigned int));
describes. We have to compute that information as we iterate
through the SOMs/symbols. */
som_index = 0;
- curr_som_offset = 8 + 2 * sizeof (struct ar_hdr) + lst.file_end;
-
- /* Yow! We have to know the size of the extended name table
- too. */
- for (curr_bfd = abfd->archive_head;
- curr_bfd != NULL;
- curr_bfd = curr_bfd->next)
- {
- CONST char *normal = normalize (curr_bfd->filename);
- unsigned int thislen;
- if (!normal)
- return false;
- thislen = strlen (normal);
- if (thislen > maxname)
- extended_name_length += thislen + 1;
- }
+ /* We add in the size of the archive header twice as the location
+ in the SOM dictionary is the actual offset of the SOM, not the
+ archive header before the SOM. */
+ curr_som_offset = 8 + 2 * sizeof (struct ar_hdr) + lst.file_end;
/* Make room for the archive header and the contents of the
- extended string table. */
- if (extended_name_length)
- curr_som_offset += extended_name_length + sizeof (struct ar_hdr);
+ extended string table. Note that elength includes the size
+ of the archive header for the extended name table! */
+ if (elength)
+ curr_som_offset += elength;
/* Make sure we're properly aligned. */
curr_som_offset = (curr_som_offset + 0x1) & ~0x1;
return false;
}
-/* SOM almost uses the SVR4 style extended name support, but not
- quite. */
-
-static boolean
-som_construct_extended_name_table (abfd, tabloc, tablen, name)
- bfd *abfd;
- char **tabloc;
- bfd_size_type *tablen;
- const char **name;
-{
- *name = "//";
- return _bfd_construct_extended_name_table (abfd, false, tabloc, tablen);
-}
-
/* Write out the LST for the archive.
You'll never believe this is really how armaps are handled in SOM... */
return false;
/* Build and write the armap. */
- if (som_bfd_ar_write_symbol_stuff (abfd, nsyms, stringsize, lst) == false)
+ if (som_bfd_ar_write_symbol_stuff (abfd, nsyms, stringsize, lst, elength)
+ == false)
return false;
/* Done. */
#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_construct_extended_name_table \
+ _bfd_archive_coff_construct_extended_name_table
#define som_update_armap_timestamp bfd_true
#define som_bfd_print_private_bfd_data _bfd_generic_bfd_print_private_bfd_data