aboutsummaryrefslogtreecommitdiff
path: root/bfd/som.c
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>1995-07-03 23:27:25 +0000
committerJeff Law <law@redhat.com>1995-07-03 23:27:25 +0000
commitc40439a219ba23c42dd614b78d2c1b5c9d4bc44e (patch)
tree4202b958a8b9b8f2b9fa902611fa972263ac7bd5 /bfd/som.c
parent3a6eecd42f626f171e1f597a682fbe45a83f564d (diff)
downloadgdb-c40439a219ba23c42dd614b78d2c1b5c9d4bc44e.zip
gdb-c40439a219ba23c42dd614b78d2c1b5c9d4bc44e.tar.gz
gdb-c40439a219ba23c42dd614b78d2c1b5c9d4bc44e.tar.bz2
* som.c (hppa_som_gen_reloc_type): New argument "sym_diff",
nonzero when we're generating relocations for an expression using the difference of two symbols. All callers changed. Handle difference of symbols for both R_HPPA and R_COMPLEX cases. (som_write_fixups): Handle R_COMP1, R_COMP2 and R_CODE_EXPR fixups.
Diffstat (limited to 'bfd/som.c')
-rw-r--r--bfd/som.c126
1 files changed, 123 insertions, 3 deletions
diff --git a/bfd/som.c b/bfd/som.c
index f97a7fe..e43e394 100644
--- a/bfd/som.c
+++ b/bfd/som.c
@@ -167,6 +167,8 @@ static asymbol * som_make_empty_symbol 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 *));
@@ -254,6 +256,7 @@ 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.
@@ -1394,15 +1397,16 @@ hppa_som_reloc (abfd, reloc_entry, symbol_in, data,
and a field selector, return one or more appropriate SOM relocations. */
int **
-hppa_som_gen_reloc_type (abfd, base_type, format, field)
+hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff)
bfd *abfd;
int base_type;
int format;
enum hppa_reloc_field_selector_type_alt field;
+ int sym_diff;
{
int *final_type, **final_types;
- final_types = (int **) bfd_alloc_by_size_t (abfd, sizeof (int *) * 3);
+ final_types = (int **) bfd_alloc_by_size_t (abfd, sizeof (int *) * 6);
final_type = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
if (!final_types || !final_type)
{
@@ -1507,8 +1511,29 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field)
switch (base_type)
{
case R_HPPA:
+ /* The difference of two symbols needs *very* special handling. */
+ if (sym_diff)
+ {
+ final_types[0] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[1] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[2] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[3] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types[0] || !final_types[1] || !final_types[2])
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return NULL;
+ }
+ *final_types[0] = R_FSEL;
+ *final_types[1] = R_COMP2;
+ *final_types[2] = R_COMP2;
+ *final_types[3] = R_COMP1;
+ final_types[4] = final_type;
+ *final_types[4] = R_CODE_EXPR;
+ final_types[5] = NULL;
+ break;
+ }
/* PLABELs get their own relocation type. */
- if (field == e_psel
+ else if (field == e_psel
|| field == e_lpsel
|| field == e_rpsel)
{
@@ -1538,6 +1563,31 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field)
*final_type = R_DATA_PLABEL;
break;
+ case R_HPPA_COMPLEX:
+ /* The difference of two symbols needs *very* special handling. */
+ if (sym_diff)
+ {
+ final_types[0] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[1] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[2] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[3] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types[0] || !final_types[1] || !final_types[2])
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return NULL;
+ }
+ *final_types[1] = R_FSEL;
+ *final_types[1] = R_COMP2;
+ *final_types[2] = R_COMP2;
+ *final_types[3] = R_COMP1;
+ final_types[4] = final_type;
+ *final_types[4] = R_CODE_EXPR;
+ final_types[5] = NULL;
+ break;
+ }
+ else
+ break;
+
case R_HPPA_NONE:
case R_HPPA_ABS_CALL:
case R_HPPA_PCREL_CALL:
@@ -2556,6 +2606,8 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep)
case R_FSEL:
case R_LSEL:
case R_RSEL:
+ case R_COMP1:
+ case R_COMP2:
reloc_offset = bfd_reloc->address;
break;
@@ -2690,6 +2742,37 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep)
p += 1;
break;
+ case R_COMP1:
+ /* The only time we generate R_COMP1, R_COMP2 and
+ R_CODE_EXPR relocs is for the difference of two
+ symbols. Hence we can cheat here. */
+ bfd_put_8 (abfd, bfd_reloc->howto->type, p);
+ bfd_put_8 (abfd, 0x44, p + 1);
+ p = try_prev_fixup (abfd, &subspace_reloc_size,
+ p, 2, reloc_queue);
+ break;
+
+ case R_COMP2:
+ /* The only time we generate R_COMP1, R_COMP2 and
+ R_CODE_EXPR relocs is for the difference of two
+ symbols. Hence we can cheat here. */
+ bfd_put_8 (abfd, bfd_reloc->howto->type, p);
+ bfd_put_8 (abfd, 0x80, p + 1);
+ bfd_put_8 (abfd, sym_num >> 16, p + 2);
+ bfd_put_16 (abfd, sym_num, p + 3);
+ p = try_prev_fixup (abfd, &subspace_reloc_size,
+ p, 5, reloc_queue);
+ break;
+
+ case R_CODE_EXPR:
+ /* The only time we generate R_COMP1, R_COMP2 and
+ R_CODE_EXPR relocs is for the difference of two
+ symbols. Hence we can cheat here. */
+ bfd_put_8 (abfd, bfd_reloc->howto->type, p);
+ subspace_reloc_size += 1;
+ p += 1;
+ 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. */
@@ -4185,8 +4268,11 @@ som_set_reloc_info (fixup, end, internal_relocs, section, symbols, just_count)
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);
}
@@ -4574,6 +4660,31 @@ som_new_section_hook (abfd, newsect)
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 = isymbol;
+ struct som_symbol *output_symbol = osymbol;
+
+ /* One day we may try to grok other private data. */
+ if (ibfd->xvec->flavour != bfd_target_som_flavour
+ || obfd->xvec->flavour != bfd_target_som_flavour)
+ return false;
+
+ /* The only private information we need to copy is the argument relocation
+ bits. */
+ output_symbol->tc_data.hppa_arg_reloc = input_symbol->tc_data.hppa_arg_reloc;
+
+ return true;
+}
+
/* Copy any private info we understand from the input section
to the output section. */
static boolean
@@ -5813,6 +5924,15 @@ som_bfd_free_cached_info (abfd)
/* 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_openr_next_archived_file bfd_generic_openr_next_archived_file