/* bfd back-end for HP PA-RISC SOM objects.
- Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995
+ 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., 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"
-#if defined (HOST_HPPAHPUX) || defined (HOST_HPPABSD) || defined (HOST_HPPAOSF)
+#if defined (HOST_HPPAHPUX) || defined (HOST_HPPABSD) || defined (HOST_HPPAOSF) || defined(HOST_HPPAMPEIX)
#include "libbfd.h"
#include "som.h"
-#include <stdio.h>
-#include <sys/types.h>
#include <sys/param.h>
#include <signal.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 */
#define CPU_PA_RISC1_1 0x210
#endif /* CPU_PA_RISC1_1 */
+#ifndef CPU_PA_RISC2_0
+#define CPU_PA_RISC2_0 0x214
+#endif /* CPU_PA_RISC2_0 */
+
#ifndef _PA_RISC1_0_ID
#define _PA_RISC1_0_ID CPU_PA_RISC1_0
#endif /* _PA_RISC1_0_ID */
#define _PA_RISC1_1_ID CPU_PA_RISC1_1
#endif /* _PA_RISC1_1_ID */
+#ifndef _PA_RISC2_0_ID
+#define _PA_RISC2_0_ID CPU_PA_RISC2_0
+#endif /* _PA_RISC2_0_ID */
+
#ifndef _PA_RISC_MAXID
#define _PA_RISC_MAXID 0x2FF
#endif /* _PA_RISC_MAXID */
unsigned int arg_reloc;
unsigned int symbol_info;
unsigned int symbol_value;
+ unsigned int priv_level;
};
/* Forward declarations */
static boolean som_mkobject PARAMS ((bfd *));
static const bfd_target * som_object_setup PARAMS ((bfd *,
struct header *,
- struct som_exec_auxhdr *));
-static boolean setup_sections PARAMS ((bfd *, struct header *));
+ struct som_exec_auxhdr *,
+ unsigned long));
+static boolean setup_sections PARAMS ((bfd *, struct header *, unsigned long));
static const bfd_target * som_object_p PARAMS ((bfd *));
static boolean som_write_object_contents PARAMS ((bfd *));
static boolean som_slurp_string_table PARAMS ((bfd *));
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_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,
unsigned int *));
static boolean som_write_symbol_strings PARAMS ((bfd *, unsigned long,
asymbol **, unsigned int,
- unsigned *));
+ unsigned *,
+ COMPUNIT *));
static boolean som_begin_writing PARAMS ((bfd *));
static reloc_howto_type * som_bfd_reloc_type_lookup
PARAMS ((bfd *, bfd_reloc_code_real_type));
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 *));
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 */
0, "", /* 0x2e */
0, "", /* 0x2f */
/* R_PCREL_CALL */
1, "L4=RD8<b+=Sb=",/* 0x3b */
0, "L4=RD8<b+=Sd=",/* 0x3c */
1, "L4=RD8<b+=Sd=",/* 0x3d */
- /* R_RESERVED */
+ /* R_SHORT_PCREL_MODE */
0, "", /* 0x3e */
+ /* R_LONG_PCREL_MODE */
0, "", /* 0x3f */
/* R_ABS_CALL */
0, "L4=RD=Sb=", /* 0x40 */
4, "Ve=", /* 0xcd */
/* R_TRANSLATED */
0, "", /* 0xce */
- /* R_RESERVED */
- 0, "", /* 0xcf */
+ /* R_AUX_UNWIND */
+ 0, "Sd=Vf=Ef=", /* 0xcf */
/* R_COMP1 */
0, "Ob=", /* 0xd0 */
/* R_COMP2 */
1, "P", /* 0xd4 */
2, "P", /* 0xd5 */
3, "P", /* 0xd6 */
- /* R_RESERVED */
+ /* R_SEC_STMT */
0, "", /* 0xd7 */
+ /* R_N0SEL */
0, "", /* 0xd8 */
+ /* R_N1SEL */
0, "", /* 0xd9 */
- 0, "", /* 0xda */
- 0, "", /* 0xdb */
+ /* R_LINETAB */
+ 0, "Eb=Sd=Ve=", /* 0xda */
+ /* R_LINETAB_ESC */
+ 0, "Eb=Mb=", /* 0xdb */
+ /* R_LTP_OVERRIDE */
0, "", /* 0xdc */
- 0, "", /* 0xdd */
+ /* R_COMMENT */
+ 0, "Ob=Ve=", /* 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 NO_PCREL_MODES
+#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, 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 *) * 3);
- 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)
- {
- 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_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])
- {
- 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_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])
- {
- 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_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])
- {
- 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_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])
- {
- 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_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])
- {
- 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 (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 (abfd, sizeof (int));
+ if (!final_types[0])
+ return NULL;
+ *final_types[0] = R_N0SEL;
+ final_types[1] = (int *) bfd_alloc (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 (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[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;
+ if (format == 32)
+ *final_types[4] = R_DATA_EXPR;
+ else
+ *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_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
*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 (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[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;
+ if (format == 32)
+ *final_types[4] = R_DATA_EXPR;
+ else
+ *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:
/* Right now we can default all these. */
break;
+
+ case R_HPPA_PCREL_CALL:
+ {
+#ifndef NO_PCREL_MODES
+ /* If we have short and long pcrel modes, then generate the proper
+ mode selector, then the pcrel relocation. Redundant selectors
+ will be eliminted as the relocs are sized and emitted. */
+ final_types[0] = (int *) bfd_alloc (abfd, sizeof (int));
+ if (!final_types[0])
+ return NULL;
+ if (format == 17)
+ *final_types[0] = R_SHORT_PCREL_MODE;
+ else
+ *final_types[0] = R_LONG_PCREL_MODE;
+ final_types[1] = final_type;
+ final_types[2] = NULL;
+ *final_type = base_type;
+#endif
+ break;
+ }
}
return final_types;
}
initialization in the BFD. */
static const bfd_target *
-som_object_setup (abfd, file_hdrp, aux_hdrp)
+som_object_setup (abfd, file_hdrp, aux_hdrp, current_offset)
bfd *abfd;
struct header *file_hdrp;
struct som_exec_auxhdr *aux_hdrp;
+ unsigned long current_offset;
{
asection *section;
int found;
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;
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!
}
else
{
- bfd_get_start_address (abfd) = aux_hdrp->exec_entry;
+ bfd_get_start_address (abfd) = aux_hdrp->exec_entry + current_offset;
obj_som_exec_data (abfd)->exec_flags = aux_hdrp->exec_flags;
}
obj_som_symtab (abfd) = (som_symbol_type *) NULL;
obj_som_sorted_syms (abfd) = NULL;
obj_som_stringtab_size (abfd) = file_hdrp->symbol_strings_size;
- obj_som_sym_filepos (abfd) = file_hdrp->symbol_location;
- obj_som_str_filepos (abfd) = file_hdrp->symbol_strings_location;
- obj_som_reloc_filepos (abfd) = file_hdrp->fixup_request_location;
+ obj_som_sym_filepos (abfd) = file_hdrp->symbol_location + current_offset;
+ obj_som_str_filepos (abfd) = (file_hdrp->symbol_strings_location
+ + current_offset);
+ obj_som_reloc_filepos (abfd) = (file_hdrp->fixup_request_location
+ + current_offset);
obj_som_exec_data (abfd)->system_id = file_hdrp->system_id;
return abfd->xvec;
associated subspaces. */
static boolean
-setup_sections (abfd, file_hdr)
+setup_sections (abfd, file_hdr, current_offset)
bfd *abfd;
struct header *file_hdr;
+ unsigned long current_offset;
{
char *space_strings;
unsigned int space_index, i;
/* 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)
+ if (bfd_seek (abfd, current_offset + file_hdr->space_strings_location,
+ SEEK_SET) < 0)
goto error_return;
if (bfd_read (space_strings, 1, file_hdr->space_strings_size, abfd)
!= file_hdr->space_strings_size)
char *newname;
/* Read the space dictionary element */
- if (bfd_seek (abfd, file_hdr->space_location
- + space_index * sizeof space, SEEK_SET) < 0)
+ if (bfd_seek (abfd,
+ (current_offset + file_hdr->space_location
+ + space_index * sizeof space),
+ SEEK_SET) < 0)
goto error_return;
if (bfd_read (&space, 1, sizeof space, abfd) != sizeof space)
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,
+ if (bfd_seek (abfd,
+ (current_offset + file_hdr->subspace_location
+ + space.subspace_index * sizeof subspace),
SEEK_SET) < 0)
goto error_return;
if (bfd_read (&subspace, 1, sizeof subspace, abfd) != sizeof subspace)
goto error_return;
/* Seek back to the start of the subspaces for loop below */
- if (bfd_seek (abfd, file_hdr->subspace_location
- + space.subspace_index * sizeof subspace,
+ if (bfd_seek (abfd,
+ (current_offset + file_hdr->subspace_location
+ + space.subspace_index * sizeof subspace),
SEEK_SET) < 0)
goto error_return;
/* Setup the start address and file loc from the first subspace record */
space_asect->vma = subspace.subspace_start;
- space_asect->filepos = subspace.file_loc_init_value;
+ space_asect->filepos = subspace.file_loc_init_value + current_offset;
space_asect->alignment_power = log2 (subspace.alignment);
if (space_asect->alignment_power == -1)
goto error_return;
subspace_asect->vma = subspace.subspace_start;
subspace_asect->_cooked_size = subspace.subspace_length;
subspace_asect->_raw_size = subspace.subspace_length;
- subspace_asect->filepos = subspace.file_loc_init_value;
+ subspace_asect->filepos = (subspace.file_loc_init_value
+ + current_offset);
subspace_asect->alignment_power = log2 (subspace.alignment);
if (subspace_asect->alignment_power == -1)
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. */
- subspace_sections = (asection **) malloc (total_subspaces
- * sizeof (asection *));
+ subspace_sections = (asection **) bfd_malloc (total_subspaces
+ * sizeof (asection *));
if (subspace_sections == NULL)
goto error_return;
{
struct header file_hdr;
struct som_exec_auxhdr aux_hdr;
+ unsigned long current_offset = 0;
+ struct lst_header lst_header;
+ struct som_entry som_entry;
+#define ENTRY_SIZE sizeof(struct som_entry)
if (bfd_read ((PTR) & file_hdr, 1, FILE_HDR_SIZE, abfd) != FILE_HDR_SIZE)
{
#ifdef SHL_MAGIC
case SHL_MAGIC:
#endif
-#ifdef EXECLIBMAGIC
- case EXECLIBMAGIC:
-#endif
#ifdef SHARED_MAGIC_CNX
case SHARED_MAGIC_CNX:
#endif
break;
+
+#ifdef EXECLIBMAGIC
+ case EXECLIBMAGIC:
+ /* Read the lst header and determine where the SOM directory begins */
+
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) < 0)
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+ if (bfd_read ((PTR) & lst_header, 1, SLSTHDR, abfd) != SLSTHDR)
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+ /* Position to and read the first directory entry */
+
+ if (bfd_seek (abfd, lst_header.dir_loc, SEEK_SET) < 0)
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+ if (bfd_read ((PTR) & som_entry, 1, ENTRY_SIZE, abfd) != ENTRY_SIZE)
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+ /* Now position to the first SOM */
+
+ if (bfd_seek (abfd, som_entry.location, SEEK_SET) < 0)
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+ current_offset = som_entry.location;
+
+ /* And finally, re-read the som header */
+
+ if (bfd_read ((PTR) & file_hdr, 1, FILE_HDR_SIZE, abfd) != FILE_HDR_SIZE)
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+ break;
+#endif
+
default:
bfd_set_error (bfd_error_wrong_format);
return 0;
}
}
- if (!setup_sections (abfd, &file_hdr))
+ if (!setup_sections (abfd, &file_hdr, current_offset))
{
/* setup_sections does not bubble up a bfd error code. */
bfd_set_error (bfd_error_bad_value);
}
/* This appears to be a valid SOM object. Do some initialization. */
- return som_object_setup (abfd, &file_hdr, &aux_hdr);
+ return som_object_setup (abfd, &file_hdr, &aux_hdr, current_offset);
}
/* Create a SOM object. */
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
subsection = subsection->next)
{
int reloc_offset, current_rounding_mode;
+#ifndef NO_PCREL_MODES
+ int current_call_mode;
+#endif
/* Find a subspace of this space. */
if (!som_is_subspace (subsection)
reloc_offset = 0;
som_initialize_reloc_queue (reloc_queue);
current_rounding_mode = R_N_MODE;
+#ifndef NO_PCREL_MODES
+ current_call_mode = R_SHORT_PCREL_MODE;
+#endif
/* Translate each BFD relocation into one or more SOM
relocations. */
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:
+#ifndef NO_PCREL_MODES
+ case R_SHORT_PCREL_MODE:
+ case R_LONG_PCREL_MODE:
+#endif
reloc_offset = bfd_reloc->address;
break;
}
break;
+#ifndef NO_PCREL_MODES
+ case R_LONG_PCREL_MODE:
+ case R_SHORT_PCREL_MODE:
+ if (bfd_reloc->howto->type != current_call_mode)
+ {
+ bfd_put_8 (abfd, bfd_reloc->howto->type, p);
+ subspace_reloc_size += 1;
+ p += 1;
+ current_call_mode = bfd_reloc->howto->type;
+ }
+ break;
+#endif
+
case R_EXIT:
case R_ALT_ENTRY:
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:
+ case R_DATA_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;
/* Write out the symbol string table. */
static boolean
-som_write_symbol_strings (abfd, current_offset, syms, num_syms, string_sizep)
+som_write_symbol_strings (abfd, current_offset, syms, num_syms, string_sizep,
+ compilation_unit)
bfd *abfd;
unsigned long current_offset;
asymbol **syms;
unsigned int num_syms;
unsigned int *string_sizep;
+ COMPUNIT *compilation_unit;
{
unsigned int i;
unsigned char tmp_space[SOM_TMP_BUFSIZE];
unsigned char *p;
unsigned int strings_size = 0;
+ unsigned char *comp[4];
+
+ /* This gets a bit gruesome because of the compilation unit. The
+ strings within the compilation unit are part of the symbol
+ strings, but don't have symbol_dictionary entries. So, manually
+ write them and update the compliation unit header. On input, the
+ compilation unit header contains local copies of the strings.
+ Move them aside. */
+ if (compilation_unit)
+ {
+ comp[0] = compilation_unit->name.n_name;
+ comp[1] = compilation_unit->language_name.n_name;
+ comp[2] = compilation_unit->product_id.n_name;
+ comp[3] = compilation_unit->version_id.n_name;
+ }
memset (tmp_space, 0, SOM_TMP_BUFSIZE);
p = tmp_space;
if (bfd_seek (abfd, current_offset, SEEK_SET) < 0)
return false;
+ if (compilation_unit)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ int length = strlen (comp[i]);
+
+ /* If there is not enough room for the next entry, then dump
+ the current buffer contents now. */
+ if (p - tmp_space + 5 + length > SOM_TMP_BUFSIZE)
+ {
+ if (bfd_write ((PTR) &tmp_space[0], p - tmp_space, 1, abfd)
+ != p - tmp_space)
+ return false;
+ /* Reset to beginning of the buffer space. */
+ p = tmp_space;
+ }
+
+ /* First element in a string table entry is the length of
+ the string. This must always be 4 byte aligned. This is
+ also an appropriate time to fill in the string index
+ field in the symbol table entry. */
+ bfd_put_32 (abfd, length, p);
+ strings_size += 4;
+ p += 4;
+
+ /* Next comes the string itself + a null terminator. */
+ strcpy (p, comp[i]);
+
+ switch (i)
+ {
+ case 0:
+ obj_som_compilation_unit (abfd)->name.n_strx = strings_size;
+ break;
+ case 1:
+ obj_som_compilation_unit (abfd)->language_name.n_strx =
+ strings_size;
+ break;
+ case 2:
+ obj_som_compilation_unit (abfd)->product_id.n_strx =
+ strings_size;
+ break;
+ case 3:
+ obj_som_compilation_unit (abfd)->version_id.n_strx =
+ strings_size;
+ break;
+ }
+
+ p += length + 1;
+ strings_size += length + 1;
+
+ /* Always align up to the next word boundary. */
+ while (strings_size % 4)
+ {
+ bfd_put_8 (abfd, 0, p);
+ strings_size++;
+ p++;
+ }
+ }
+ }
+
for (i = 0; i < num_syms; i++)
{
int length = strlen (syms[i]->name);
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);
-
- /* 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;
-
- /* Next is the compiler records. We do not use these. */
+ /* Next is the compilation unit. */
obj_som_file_hdr (abfd)->compiler_location = current_offset;
obj_som_file_hdr (abfd)->compiler_total = 0;
+ if (obj_som_compilation_unit (abfd))
+ {
+ obj_som_file_hdr (abfd)->compiler_total = 1;
+ current_offset += COMPUNITSZ;
+ }
/* Now compute the file positions for the loadable subspaces, taking
care to make sure everything stays properly aligned. */
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,
+ obj_som_compilation_unit (abfd))
+ == 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));
- 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)
/* 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;
+ /* 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. */
section = section->next;
}
+ /* Write the compilation unit record if there is one. */
+ if (obj_som_compilation_unit (abfd))
+ {
+ location = obj_som_file_hdr (abfd)->compiler_location;
+ if (bfd_seek (abfd, location, SEEK_SET) < 0)
+ return false;
+
+ if (bfd_write ((PTR) obj_som_compilation_unit (abfd),
+ COMPUNITSZ, 1, abfd) != COMPUNITSZ)
+ return false;
+ }
+
/* 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) == pa20)
+ obj_som_file_hdr(abfd)->system_id = CPU_PA_RISC2_0;
else if (bfd_get_mach (abfd) == pa11)
obj_som_file_hdr(abfd)->system_id = CPU_PA_RISC1_1;
else
/* Now write the exec header. */
if (abfd->flags & (EXEC_P | DYNAMIC))
{
- long tmp;
+ long tmp, som_length;
struct som_exec_auxhdr *exec_header;
exec_header = obj_som_exec_hdr (abfd);
exec_header->exec_bsize = 0;
exec_header->exec_dsize = tmp;
+ /* Now perform some sanity checks. The idea is to catch bogons now and
+ inform the user, instead of silently generating a bogus file. */
+ som_length = obj_som_file_hdr (abfd)->som_length;
+ if (exec_header->exec_tfile + exec_header->exec_tsize > som_length
+ || exec_header->exec_dfile + exec_header->exec_dsize > som_length)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
if (bfd_seek (abfd, obj_som_file_hdr (abfd)->aux_header_location,
SEEK_SET) < 0)
return false;
&& (sym->flags & BSF_FUNCTION)))
{
info->symbol_type = ST_ENTRY;
- info->arg_reloc = som_symbol_data (sym)->tc_data.hppa_arg_reloc;
+ info->arg_reloc = som_symbol_data (sym)->tc_data.ap.hppa_arg_reloc;
+ info->priv_level= som_symbol_data (sym)->tc_data.ap.hppa_priv_level;
}
- /* 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)
/* 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_symtab[i].symbol_scope = info.symbol_scope;
som_symtab[i].arg_reloc = info.arg_reloc;
som_symtab[i].symbol_info = info.symbol_info;
- som_symtab[i].symbol_value = info.symbol_value;
+ som_symtab[i].xleast = 3;
+ som_symtab[i].symbol_value = info.symbol_value | info.priv_level;
}
/* Everything is ready, seek to the right location and
}
/* Allocate and read in the string table. */
- stringtab = bfd_zalloc (abfd, 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 *)
- bfd_zalloc (abfd, 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)
som_symbol_data (sym)->som_type = SYMBOL_TYPE_PLABEL;
else
som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
- som_symbol_data (sym)->tc_data.hppa_arg_reloc = bufp->arg_reloc;
+ som_symbol_data (sym)->tc_data.ap.hppa_arg_reloc = bufp->arg_reloc;
/* Some reasonable defaults. */
sym->symbol.the_bfd = abfd;
case ST_ENTRY:
case ST_MILLICODE:
sym->symbol.flags |= BSF_FUNCTION;
+ som_symbol_data (sym)->tc_data.ap.hppa_priv_level =
+ sym->symbol.value & 0x3;
sym->symbol.value &= ~0x3;
break;
case ST_CODE:
case ST_PRI_PROG:
case ST_SEC_PROG:
+ som_symbol_data (sym)->tc_data.ap.hppa_priv_level =
+ sym->symbol.value & 0x3;
sym->symbol.value &= ~0x3;
- /* If the symbol's scope is ST_UNSAT, then these are
+ /* If the symbol's scope is SS_UNSAT, then these are
undefined function symbols. */
if (bufp->symbol_scope == SS_UNSAT)
sym->symbol.flags |= BSF_FUNCTION;
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;
}
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.
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);
}
/* 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 = malloc (section->_raw_size);
+ section->contents = bfd_malloc (section->_raw_size);
if (section->contents == NULL)
return -1;
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,
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,
/* 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;
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.ap.hppa_arg_reloc =
+ input_symbol->tc_data.ap.hppa_arg_reloc;
+
+ return true;
+}
+
/* Copy any private info we understand from the input section
to the output section. */
static boolean
= (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,
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);
return true;
}
+/* Attach an compilation unit header to the BFD backend so that it may be
+ written into the object file. */
+
+boolean
+bfd_som_attach_compilation_unit (abfd, name, language_name, product_id,
+ version_id)
+ bfd *abfd;
+ const char *name;
+ const char *language_name;
+ const char *product_id;
+ const char *version_id;
+{
+ COMPUNIT *n = (COMPUNIT *) bfd_zalloc (abfd, COMPUNITSZ);
+ if (n == NULL)
+ return false;
+
+#define STRDUP(f) \
+ if (f != NULL) \
+ { \
+ n->f.n_name = bfd_alloc (abfd, strlen (f) + 1); \
+ if (n->f.n_name == NULL) \
+ return false; \
+ strcpy (n->f.n_name, f); \
+ }
+
+ STRDUP (name);
+ STRDUP (language_name);
+ STRDUP (product_id);
+ STRDUP (version_id);
+
+#undef STRDUP
+
+ obj_som_compilation_unit (abfd) = n;
+
+ return true;
+}
+
static boolean
som_get_section_contents (abfd, section, location, offset, count)
bfd *abfd;
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)
| (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 *) 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. */
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)
- {
- bfd_set_error (bfd_error_no_memory);
- 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;
/* 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;
curr_lst_sym->memory_resident = 0;
curr_lst_sym->is_common = bfd_is_com_section (sym->symbol.section);
curr_lst_sym->dup_common = 0;
- curr_lst_sym->xleast = 0;
+ curr_lst_sym->xleast = 3;
curr_lst_sym->arg_reloc = info.arg_reloc;
curr_lst_sym->name.n_strx = p - strings + 4;
curr_lst_sym->qualifier_name.n_strx = 0;
curr_lst_sym->symbol_info = info.symbol_info;
- curr_lst_sym->symbol_value = info.symbol_value;
+ curr_lst_sym->symbol_value = info.symbol_value | info.priv_level;
curr_lst_sym->symbol_descriptor = 0;
curr_lst_sym->reserved = 0;
curr_lst_sym->som_index = som_index;
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. */
/* 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_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
#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
+#define som_bfd_gc_sections bfd_generic_gc_sections
+
+
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 */
BFD_JUMP_TABLE_LINK (som),
BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+ NULL,
+
(PTR) 0
};