* Move mips_hi16_list to mips_elf_section_data
2023-12-19 9:35 mips hi16/lo16 reloc handling Alan Modra
@ 2023-12-19 9:35 ` Alan Modra
2023-12-19 9:35 ` coff-mips refhi list Alan Modra
1 sibling, 0 replies; 3+ messages in thread
From: Alan Modra @ 2023-12-19 9:35 UTC (permalink / raw)
To: binutils; +Cc: Maciej W . Rozycki, Chenghua Xu, Alan Modra
This patch is in response to fuzzing testcases that manage to cause
segfaults due to stale references to freed memory via mips_hi16.data.
A number of the error/warning handlers in ldmain.c use %C. This can
cause debug info to be parsed for the first time in order to print
file/function/line. If one of those warnings is triggered after some
hi16 relocs have been processed but before the matching lo16 reloc is
handled, *and* the debug info is corrupted with a lo16 reloc, then the
mips_hi16_list will be flushed with the result that printing a warning
changes linker output. It is also possible that corrupted debug info
adds to the hi16 list, with the result that when the linker handles a
later lo16 reloc in a text section, ld will segfault accessing
mips_hi16.data after the debug buffers have be freed. Both of these
problems are fixed by keeping a per-section mips_hi16_list rather than
a per-file list.
* elfxx-mips.c (struct mips_hi16): Move earlier, deleting
input_section field.
(struct _mips_elf_section_data): Add mips_hi16_list.
(struct mips_elf_obj_tdata): Delete mips_hi16_list.
(free_mips_hi16_list): New function.
(_bfd_mips_elf_free_cached_info): Adjust to suit new location
of mips_hi16_list.
(_bfd_mips_elf_hi16_reloc, _bfd_mips_elf_lo16_reloc): Likewise.
(_bfd_elf_mips_get_relocated_section_contents): Likewise.
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index bae8622fd34..00111553c30 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -222,6 +222,19 @@ struct mips_elf_traverse_got_arg
int value;
};
+/* Used to store a REL high-part relocation such as R_MIPS_HI16 or
+ R_MIPS_GOT16. DATA nominally points to the start of the section
+ contents, but note that gas may use multiple chunks of memory for a
+ section (with DATA + [offset,offset+frag_size) addressing a given
+ frag). A hi16 reloc might need a different "data" to a lo16. */
+
+struct mips_hi16
+{
+ struct mips_hi16 *next;
+ bfd_byte *data;
+ arelent rel;
+};
+
struct _mips_elf_section_data
{
struct bfd_elf_section_data elf;
@@ -229,6 +242,8 @@ struct _mips_elf_section_data
{
bfd_byte *tdata;
} u;
+
+ struct mips_hi16 *mips_hi16_list;
};
#define mips_elf_section_data(sec) \
@@ -549,19 +564,6 @@ struct mips_htab_traverse_info
bool error;
};
-/* Used to store a REL high-part relocation such as R_MIPS_HI16 or
- R_MIPS_GOT16. REL is the relocation, INPUT_SECTION is the section
- that contains the relocation field and DATA points to the start of
- INPUT_SECTION. */
-
-struct mips_hi16
-{
- struct mips_hi16 *next;
- bfd_byte *data;
- asection *input_section;
- arelent rel;
-};
-
/* MIPS ELF private object data. */
struct mips_elf_obj_tdata
@@ -597,8 +599,6 @@ struct mips_elf_obj_tdata
asymbol *elf_text_symbol;
asection *elf_data_section;
asection *elf_text_section;
-
- struct mips_hi16 *mips_hi16_list;
};
/* Get MIPS ELF private object data from BFD's tdata. */
@@ -1389,6 +1389,30 @@ struct mips_elf_find_line
struct ecoff_find_line i;
};
+/* Free the mips_hi16_list attached to S. Return true if there were
+ unmatched hi16 relocs. */
+
+static bool
+free_mips_hi16_list (asection *s)
+{
+ struct mips_hi16 *hi;
+ struct mips_hi16 **hip = &mips_elf_section_data (s)->mips_hi16_list;
+ bool ret = false;
+
+ while ((hi = *hip) != NULL)
+ {
+ *hip = hi->next;
+ /* See gas/config/tc-mips.c reloc_needs_lo_p. Not all hi16
+ relocs need lo16 relocs. */
+ if (hi->rel.howto->type == R_MIPS_HI16
+ || hi->rel.howto->type == R_MIPS16_HI16
+ || hi->rel.howto->type == R_MICROMIPS_HI16)
+ ret = true;
+ free (hi);
+ }
+ return ret;
+}
+
bool
_bfd_mips_elf_free_cached_info (bfd *abfd)
{
@@ -1399,14 +1423,12 @@ _bfd_mips_elf_free_cached_info (bfd *abfd)
&& (tdata = mips_elf_tdata (abfd)) != NULL)
{
BFD_ASSERT (tdata->root.object_id == MIPS_ELF_DATA);
- while (tdata->mips_hi16_list != NULL)
- {
- struct mips_hi16 *hi = tdata->mips_hi16_list;
- tdata->mips_hi16_list = hi->next;
- free (hi);
- }
if (tdata->find_line_info != NULL)
_bfd_ecoff_free_ecoff_debug_info (&tdata->find_line_info->d);
+ for (asection *s = abfd->sections; s; s = s->next)
+ if (free_mips_hi16_list (s))
+ _bfd_error_handler
+ (_("%pB(%pA): unmatched hi16 reloc"), abfd, s);
}
return _bfd_elf_free_cached_info (abfd);
}
@@ -2537,22 +2559,18 @@ _bfd_mips_elf_hi16_reloc (bfd *abfd, arelent *reloc_entry,
asection *input_section, bfd *output_bfd,
char **error_message ATTRIBUTE_UNUSED)
{
- struct mips_hi16 *n;
- struct mips_elf_obj_tdata *tdata;
-
if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
return bfd_reloc_outofrange;
- n = bfd_malloc (sizeof *n);
+ struct mips_hi16 *n = bfd_malloc (sizeof (*n));
if (n == NULL)
return bfd_reloc_outofrange;
- tdata = mips_elf_tdata (abfd);
- n->next = tdata->mips_hi16_list;
+ struct _mips_elf_section_data *sdata = mips_elf_section_data (input_section);
+ n->next = sdata->mips_hi16_list;
n->data = data;
- n->input_section = input_section;
n->rel = *reloc_entry;
- tdata->mips_hi16_list = n;
+ sdata->mips_hi16_list = n;
if (output_bfd != NULL)
reloc_entry->address += input_section->output_offset;
@@ -2590,64 +2608,66 @@ _bfd_mips_elf_lo16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
void *data, asection *input_section,
bfd *output_bfd, char **error_message)
{
- bfd_vma vallo;
- bfd_byte *location = (bfd_byte *) data + reloc_entry->address;
- struct mips_elf_obj_tdata *tdata;
+ struct _mips_elf_section_data *sdata = mips_elf_section_data (input_section);
- if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd, input_section,
- reloc_entry->address))
- return bfd_reloc_outofrange;
+ if (sdata->mips_hi16_list != NULL)
+ {
+ if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd, input_section,
+ reloc_entry->address))
+ return bfd_reloc_outofrange;
- _bfd_mips_elf_reloc_unshuffle (abfd, reloc_entry->howto->type, false,
- location);
- /* The high 16 bits of the addend are stored in the high insn, the
- low 16 bits in the low insn, but there is a catch: You can't
- just concatenate the high and low parts. The high part of the
- addend is adjusted for the fact that the low part is sign
- extended. For example, an addend of 0x38000 would have 0x0004 in
- the high part and 0x8000 (=0xff..f8000) in the low part.
- To extract the actual addend, calculate (a)
- ((hi & 0xffff) << 16) + ((lo & 0xffff) ^ 0x8000) - 0x8000.
- We will be applying (symbol + addend) & 0xffff to the low insn,
- and we want to apply (b) (symbol + addend + 0x8000) >> 16 to the
- high insn (the +0x8000 adjusting for when the applied low part is
- negative). Substituting (a) into (b) and recognising that
- (hi & 0xffff) is already in the high insn gives a high part
- addend adjustment of (lo & 0xffff) ^ 0x8000. */
- vallo = (bfd_get_32 (abfd, location) & 0xffff) ^ 0x8000;
- _bfd_mips_elf_reloc_shuffle (abfd, reloc_entry->howto->type, false,
- location);
+ bfd_byte *location = (bfd_byte *) data + reloc_entry->address;
+ _bfd_mips_elf_reloc_unshuffle (abfd, reloc_entry->howto->type, false,
+ location);
+ /* The high 16 bits of the addend are stored in the high insn, the
+ low 16 bits in the low insn, but there is a catch: You can't
+ just concatenate the high and low parts. The high part of the
+ addend is adjusted for the fact that the low part is sign
+ extended. For example, an addend of 0x38000 would have 0x0004 in
+ the high part and 0x8000 (=0xff..f8000) in the low part.
+ To extract the actual addend, calculate (a)
+ ((hi & 0xffff) << 16) + ((lo & 0xffff) ^ 0x8000) - 0x8000.
+ We will be applying (symbol + addend) & 0xffff to the low insn,
+ and we want to apply (b) (symbol + addend + 0x8000) >> 16 to the
+ high insn (the +0x8000 adjusting for when the applied low part is
+ negative). Substituting (a) into (b) and recognising that
+ (hi & 0xffff) is already in the high insn gives a high part
+ addend adjustment of (lo & 0xffff) ^ 0x8000. */
+ bfd_vma vallo = (bfd_get_32 (abfd, location) & 0xffff) ^ 0x8000;
+ _bfd_mips_elf_reloc_shuffle (abfd, reloc_entry->howto->type, false,
+ location);
- tdata = mips_elf_tdata (abfd);
- while (tdata->mips_hi16_list != NULL)
- {
- bfd_reloc_status_type ret;
- struct mips_hi16 *hi;
-
- hi = tdata->mips_hi16_list;
-
- /* R_MIPS*_GOT16 relocations are something of a special case. We
- want to install the addend in the same way as for a R_MIPS*_HI16
- relocation (with a rightshift of 16). However, since GOT16
- relocations can also be used with global symbols, their howto
- has a rightshift of 0. */
- if (hi->rel.howto->type == R_MIPS_GOT16)
- hi->rel.howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, R_MIPS_HI16, false);
- else if (hi->rel.howto->type == R_MIPS16_GOT16)
- hi->rel.howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, R_MIPS16_HI16, false);
- else if (hi->rel.howto->type == R_MICROMIPS_GOT16)
- hi->rel.howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, R_MICROMIPS_HI16, false);
-
- hi->rel.addend += vallo;
-
- ret = _bfd_mips_elf_generic_reloc (abfd, &hi->rel, symbol, hi->data,
- hi->input_section, output_bfd,
- error_message);
- if (ret != bfd_reloc_ok)
- return ret;
-
- tdata->mips_hi16_list = hi->next;
- free (hi);
+ while (sdata->mips_hi16_list != NULL)
+ {
+ bfd_reloc_status_type ret;
+ struct mips_hi16 *hi = sdata->mips_hi16_list;
+
+ /* R_MIPS*_GOT16 relocations are something of a special case.
+ We want to install the addend in the same way as for a
+ R_MIPS*_HI16 relocation (with a rightshift of 16).
+ However, since GOT16 relocations can also be used with
+ global symbols, their howto has a rightshift of 0. */
+ if (hi->rel.howto->type == R_MIPS_GOT16)
+ hi->rel.howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, R_MIPS_HI16,
+ false);
+ else if (hi->rel.howto->type == R_MIPS16_GOT16)
+ hi->rel.howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, R_MIPS16_HI16,
+ false);
+ else if (hi->rel.howto->type == R_MICROMIPS_GOT16)
+ hi->rel.howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, R_MICROMIPS_HI16,
+ false);
+
+ hi->rel.addend += vallo;
+
+ ret = _bfd_mips_elf_generic_reloc (abfd, &hi->rel, symbol, hi->data,
+ input_section, output_bfd,
+ error_message);
+ if (ret != bfd_reloc_ok)
+ return ret;
+
+ sdata->mips_hi16_list = hi->next;
+ free (hi);
+ }
}
return _bfd_mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
@@ -13333,24 +13353,8 @@ _bfd_elf_mips_get_relocated_section_contents
reloc_vector = (arelent **) bfd_malloc (reloc_size);
if (reloc_vector == NULL)
{
- struct mips_elf_obj_tdata *tdata;
- struct mips_hi16 **hip, *hi;
error_return:
- /* If we are going to return an error, remove entries on
- mips_hi16_list that point into this section's data. Data
- will typically be freed on return from this function. */
- tdata = mips_elf_tdata (abfd);
- hip = &tdata->mips_hi16_list;
- while ((hi = *hip) != NULL)
- {
- if (hi->input_section == input_section)
- {
- *hip = hi->next;
- free (hi);
- }
- else
- hip = &hi->next;
- }
+ free_mips_hi16_list (input_section);
if (orig_data == NULL)
free (data);
data = NULL;
^ permalink raw reply [flat|nested] 3+ messages in thread
* coff-mips refhi list
2023-12-19 9:35 mips hi16/lo16 reloc handling Alan Modra
2023-12-19 9:35 ` Move mips_hi16_list to mips_elf_section_data Alan Modra
@ 2023-12-19 9:35 ` Alan Modra
1 sibling, 0 replies; 3+ messages in thread
From: Alan Modra @ 2023-12-19 9:35 UTC (permalink / raw)
To: binutils; +Cc: Maciej W . Rozycki, Chenghua Xu, Alan Modra
Like "Move mips_hi16_list to mips_elf_section_data" but for coff.
Also makes mips_refhi_reloc and mips_reflo_reloc a little more elegant
in that they now make use of the generic reloc machinery in order to
apply the relocations.
* libecoff.h (struct mips_hi): Delete
(struct mips_h16): New.
(struct ecoff_tdata): Delete mips_refhi_list.
(struct ecoff_section_tdata): Put existing gp into a union.
Add mips_hi16_list.
* coff-alpha.c (alpha_relocate_section): Adjust section data access.
* coff-mips.c (mips_refhi_reloc): Delete dead code. Stash hi reloc
on ecoff_section_tdata.
(mips_reflo_reloc): Use new hi16 list. Apply hi reloc using
bfd_perform_relocation.
* ecoff.c (free_mips_hi16_list): New function.
(_bfd_ecoff_bfd_free_cached_info): Clear new hi16 list attached to
sections rather than bfd tdata.
diff --git a/bfd/coff-alpha.c b/bfd/coff-alpha.c
index 3403e13ef1b..0ccc377a950 100644
--- a/bfd/coff-alpha.c
+++ b/bfd/coff-alpha.c
@@ -1461,11 +1461,11 @@ alpha_relocate_section (bfd *output_bfd,
lita_sec->used_by_bfd = lita_sec_data;
}
- if (lita_sec_data->gp != 0)
+ if (lita_sec_data->u.gp != 0)
{
/* If we already assigned a gp to this section, we better
stick with that value. */
- gp = lita_sec_data->gp;
+ gp = lita_sec_data->u.gp;
}
else
{
@@ -1498,7 +1498,7 @@ alpha_relocate_section (bfd *output_bfd,
}
- lita_sec_data->gp = gp;
+ lita_sec_data->u.gp = gp;
}
_bfd_set_gp_value (output_bfd, gp);
diff --git a/bfd/coff-mips.c b/bfd/coff-mips.c
index fdc0771979d..1b5cc6ae10c 100644
--- a/bfd/coff-mips.c
+++ b/bfd/coff-mips.c
@@ -427,17 +427,11 @@ static bfd_reloc_status_type
mips_refhi_reloc (bfd *abfd,
arelent *reloc_entry,
asymbol *symbol,
- void * data,
+ void *data,
asection *input_section,
bfd *output_bfd,
char **error_message ATTRIBUTE_UNUSED)
{
- bfd_reloc_status_type ret;
- bfd_vma relocation;
- struct mips_hi *n;
-
- /* If we're relocating, and this an external symbol, we don't want
- to change anything. */
if (output_bfd != (bfd *) NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& reloc_entry->addend == 0)
@@ -446,36 +440,34 @@ mips_refhi_reloc (bfd *abfd,
return bfd_reloc_ok;
}
- ret = bfd_reloc_ok;
- if (bfd_is_und_section (symbol->section)
- && output_bfd == (bfd *) NULL)
- ret = bfd_reloc_undefined;
-
- if (bfd_is_com_section (symbol->section))
- relocation = 0;
- else
- relocation = symbol->value;
-
- relocation += symbol->section->output_section->vma;
- relocation += symbol->section->output_offset;
- relocation += reloc_entry->addend;
-
- if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
- return bfd_reloc_outofrange;
+ /* Is this the call via bfd_perform_relocation in mips_reflo_reloc?
+ If so, continue and apply the reloc. */
+ struct ecoff_section_tdata *sdata = input_section->used_by_bfd;
+ if (sdata != NULL
+ && sdata->u.mips_hi16_list != NULL
+ && reloc_entry == &sdata->u.mips_hi16_list->rel)
+ return bfd_reloc_continue;
+ if (sdata == NULL)
+ {
+ sdata = bfd_zalloc (abfd, sizeof (*sdata));
+ input_section->used_by_bfd = sdata;
+ if (sdata == NULL)
+ return bfd_reloc_outofrange;
+ }
/* Save the information, and let REFLO do the actual relocation. */
- n = (struct mips_hi *) bfd_malloc ((bfd_size_type) sizeof *n);
+ struct mips_hi16 *n = bfd_malloc (sizeof (*n));
if (n == NULL)
return bfd_reloc_outofrange;
- n->addr = (bfd_byte *) data + reloc_entry->address;
- n->addend = relocation;
- n->next = ecoff_data (abfd)->mips_refhi_list;
- ecoff_data (abfd)->mips_refhi_list = n;
+ n->data = data;
+ n->rel = *reloc_entry;
+ n->next = sdata->u.mips_hi16_list;
+ sdata->u.mips_hi16_list = n;
if (output_bfd != (bfd *) NULL)
reloc_entry->address += input_section->output_offset;
- return ret;
+ return bfd_reloc_ok;
}
/* Do a REFLO relocation. This is a straightforward 16 bit inplace
@@ -491,54 +483,37 @@ mips_reflo_reloc (bfd *abfd,
bfd *output_bfd,
char **error_message)
{
- if (ecoff_data (abfd)->mips_refhi_list != NULL)
+ bfd_size_type octets = (reloc_entry->address
+ * OCTETS_PER_BYTE (abfd, input_section));
+
+ if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
+ input_section, octets))
+ return bfd_reloc_outofrange;
+
+ struct ecoff_section_tdata* sdata = input_section->used_by_bfd;
+ if (sdata != NULL && sdata->u.mips_hi16_list != NULL)
{
- struct mips_hi *l;
+ struct mips_hi16 *hi;
+ bfd_byte *loc = (bfd_byte *) data + octets;
+ /* Adjustment for the high part addend. See longer explanation
+ in elfxx-mips.c _bfd_mips_elf_lo16_reloc. */
+ bfd_vma vallo = (bfd_get_32 (abfd, loc) & 0x8000) ^ 0x8000;
- l = ecoff_data (abfd)->mips_refhi_list;
- while (l != NULL)
+ while ((hi = sdata->u.mips_hi16_list) != NULL)
{
- unsigned long insn;
- unsigned long val;
- unsigned long vallo;
- struct mips_hi *next;
- bfd_size_type octets = (reloc_entry->address
- * OCTETS_PER_BYTE (abfd, input_section));
- bfd_byte *loc = (bfd_byte *) data + octets;
-
- if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
- input_section, octets))
- return bfd_reloc_outofrange;
-
- /* Do the REFHI relocation. Note that we actually don't
- need to know anything about the REFLO itself, except
- where to find the low 16 bits of the addend needed by the
- REFHI. */
- insn = bfd_get_32 (abfd, l->addr);
- vallo = bfd_get_32 (abfd, loc) & 0xffff;
- val = ((insn & 0xffff) << 16) + vallo;
- val += l->addend;
-
- /* The low order 16 bits are always treated as a signed
- value. Therefore, a negative value in the low order bits
- requires an adjustment in the high order bits. We need
- to make this adjustment in two ways: once for the bits we
- took from the data, and once for the bits we are putting
- back in to the data. */
- if ((vallo & 0x8000) != 0)
- val -= 0x10000;
- if ((val & 0x8000) != 0)
- val += 0x10000;
-
- insn = (insn &~ (unsigned) 0xffff) | ((val >> 16) & 0xffff);
- bfd_put_32 (abfd, (bfd_vma) insn, l->addr);
-
- next = l->next;
- free (l);
- l = next;
+ bfd_reloc_status_type ret;
+
+ /* Apply the REFHI relocation. */
+ hi->rel.addend += vallo;
+ ret = bfd_perform_relocation (abfd, &hi->rel, hi->data,
+ input_section, output_bfd,
+ error_message);
+ if (ret != bfd_reloc_ok)
+ return ret;
+
+ sdata->u.mips_hi16_list = hi->next;
+ free (hi);
}
-
- ecoff_data (abfd)->mips_refhi_list = NULL;
}
/* Now do the REFLO reloc in the usual way. */
diff --git a/bfd/ecoff.c b/bfd/ecoff.c
index 844f1a5247d..c8af3032e40 100644
--- a/bfd/ecoff.c
+++ b/bfd/ecoff.c
@@ -109,6 +109,29 @@ _bfd_ecoff_mkobject_hook (bfd *abfd, void * filehdr, void * aouthdr)
return (void *) ecoff;
}
+/* Free the mips_hi16_list attached to S. Return true if there were
+ unmatched hi16 relocs. */
+
+static bool
+free_mips_hi16_list (asection *s)
+{
+ struct ecoff_section_tdata* sdata = s->used_by_bfd;
+ if (sdata != NULL)
+ {
+ struct mips_hi16 *hi;
+ struct mips_hi16 **hip = &sdata->u.mips_hi16_list;
+ bool ret = *hip != NULL;
+
+ while ((hi = *hip) != NULL)
+ {
+ *hip = hi->next;
+ free (hi);
+ }
+ return ret;
+ }
+ return false;
+}
+
bool
_bfd_ecoff_bfd_free_cached_info (bfd *abfd)
{
@@ -118,13 +141,14 @@ _bfd_ecoff_bfd_free_cached_info (bfd *abfd)
|| bfd_get_format (abfd) == bfd_core)
&& (tdata = ecoff_data (abfd)) != NULL)
{
- while (tdata->mips_refhi_list != NULL)
+ _bfd_ecoff_free_ecoff_debug_info (&tdata->debug_info);
+ if (ecoff_backend (abfd)->arch == bfd_arch_mips)
{
- struct mips_hi *ref = tdata->mips_refhi_list;
- tdata->mips_refhi_list = ref->next;
- free (ref);
+ for (asection *s = abfd->sections; s; s = s->next)
+ if (free_mips_hi16_list (s))
+ _bfd_error_handler
+ (_("%pB(%pA): unmatched hi16 reloc"), abfd, s);
}
- _bfd_ecoff_free_ecoff_debug_info (&tdata->debug_info);
}
return _bfd_generic_bfd_free_cached_info (abfd);
}
diff --git a/bfd/libecoff.h b/bfd/libecoff.h
index 2267c7bc53b..96b8a9a4547 100644
--- a/bfd/libecoff.h
+++ b/bfd/libecoff.h
@@ -80,11 +80,11 @@ struct ecoff_backend_data
members of the embedded bfd_coff_backend_data struct. */
#define ECOFF_NO_LONG_SECTION_NAMES (false), _bfd_ecoff_no_long_sections
-struct mips_hi
+struct mips_hi16
{
- struct mips_hi *next;
- bfd_byte *addr;
- bfd_vma addend;
+ struct mips_hi16 *next;
+ bfd_byte *data;
+ arelent rel;
};
/* This is the target specific information kept for ECOFF files. */
@@ -151,9 +151,6 @@ typedef struct ecoff_tdata
particular ECOFF file. This is not valid until
ecoff_compute_section_file_positions is called. */
bool rdata_in_text;
-
- /* Used by coff-mips.c to track REFHI relocs for pairing with REFLO. */
- struct mips_hi *mips_refhi_list;
} ecoff_data_type;
/* Each canonical asymbol really looks like this. */
@@ -192,13 +189,18 @@ typedef struct ecoff_symbol_struct
struct ecoff_section_tdata
{
- /* When producing an executable (i.e., final, non-relocatable link)
- on the Alpha, we may need to use multiple global pointer values
- to span the entire .lita section. In essence, we allow each
- input .lita section to have its own gp value. To support this,
- we need to keep track of the gp values that we picked for each
- input .lita section . */
- bfd_vma gp;
+ union
+ {
+ /* When producing an executable (i.e., final, non-relocatable link)
+ on the Alpha, we may need to use multiple global pointer values
+ to span the entire .lita section. In essence, we allow each
+ input .lita section to have its own gp value. To support this,
+ we need to keep track of the gp values that we picked for each
+ input .lita section . */
+ bfd_vma gp;
+ /* Used by coff-mips.c to track hi16 relocs. */
+ struct mips_hi16 *mips_hi16_list;
+ } u;
};
/* An accessor macro for the ecoff_section_tdata structure. */
^ permalink raw reply [flat|nested] 3+ messages in thread