aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog27
-rw-r--r--bfd/elf32-mips.c371
2 files changed, 249 insertions, 149 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 1b146bf..eee678f 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,32 @@
1999-06-27 Mark Mitchell <mark@codesourcery.com>
+ * elf32-mips.c (MIPS_ELF_SRDATA_SECTION_NAME): New macro.
+ (MIPS_ELF_OPTIONS_SECTION_NAME): Likewise.
+ (MIPS_ELF_STUB_SECTION_NAME): Likewise.
+ (_bfd_mips_elf_section_from_shdr): Use them.
+ (_bfd_mips_elf_fake_sections): Likewise. Add .srdata to the list
+ of GP-relative sections.
+ (_bfd_mips_elf_set_section_contents): Use them.
+ (_bfd_mips_elf_section_processing): Share code between .sdata and
+ .lit4/.lit8 sections. Set appropriate flags for .srdata.
+ (mips_elf_additional_program_headers): Add handling for
+ PT_MIPS_OPTIONS segment on IRIX6.
+ (mips_elf_modify_segment_map): Likeiwse.
+ (mips_elf_final_link): Set EF_MIPS_CPIC when required by the ABI.
+ Include the options sections on IRIX6. Don't look for GP-relative
+ sections by name; use SHF_MIPS_GPREL instead.
+ (ELF_DYNAMIC_INTERPRETER): Adjust to use /usr/lib32/libc.so.1 for
+ the N32 ABI.
+ (mips_elf_create_dynamic_sections): Don't muck about with section
+ alignments and such on IRIX6.
+ (mips_elf_adjust_dynamic_symbol): Use MIPS_ELF_STUB_SECTION_NAME.
+ (mips_elf_size_dynamic_sections): Likewise. Adjust to handle the
+ fact that ELF_DYNAMIC_INTERPRETER is no longer a constant. Use
+ bfd_zalloc rather than bfd_alloc and memset.
+ (mips_elf_finish_dynamic_symbol): Use MIPS_ELF_STUB_SECTION_NAME.
+ Don't assert the existence of .rld_map on IRIX6.
+ (mips_elf_finish_dynamic_sections): Use MIPS_ELF_STUB_SECTION_NAME.
+
* elf32-mips.c (mips_elf_adjust_dynindx): Remove.
(mips_elf_size_dynamic_sections): Use _bfd_elf_link_adjust_dynindx
instead.
diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c
index 17c057b..c152e8a 100644
--- a/bfd/elf32-mips.c
+++ b/bfd/elf32-mips.c
@@ -170,6 +170,17 @@ struct mips_got_info
/* The name of the msym section. */
#define MIPS_ELF_MSYM_SECTION_NAME(abfd) ".msym"
+/* The name of the srdata section. */
+#define MIPS_ELF_SRDATA_SECTION_NAME(abfd) ".srdata"
+
+/* The name of the options section. */
+#define MIPS_ELF_OPTIONS_SECTION_NAME(abfd) \
+ (IRIX_COMPAT (abfd) == ict_irix6 ? ".MIPS.options" : ".options")
+
+/* The name of the stub section. */
+#define MIPS_ELF_STUB_SECTION_NAME(abfd) \
+ (IRIX_COMPAT (abfd) == ict_irix6 ? ".MIPS.stubs" : ".stub")
+
/* The number of local .got entries we reserve. */
#define MIPS_RESERVED_GOTNO (2)
@@ -2449,8 +2460,7 @@ _bfd_mips_elf_section_from_shdr (abfd, hdr, name)
return false;
break;
case SHT_MIPS_OPTIONS:
- if (strcmp (name, ".options") != 0
- && strcmp (name, ".MIPS.options") != 0)
+ if (strcmp (name, MIPS_ELF_OPTIONS_SECTION_NAME (abfd)) != 0)
return false;
break;
case SHT_MIPS_DWARF:
@@ -2627,6 +2637,7 @@ _bfd_mips_elf_fake_sections (abfd, hdr, sec)
#endif
}
else if (strcmp (name, ".got") == 0
+ || strcmp (name, MIPS_ELF_SRDATA_SECTION_NAME (abfd)) == 0
|| strcmp (name, ".sdata") == 0
|| strcmp (name, ".sbss") == 0
|| strcmp (name, ".lit4") == 0
@@ -2643,8 +2654,7 @@ _bfd_mips_elf_fake_sections (abfd, hdr, sec)
hdr->sh_flags |= SHF_MIPS_NOSTRIP;
/* The sh_info field is set in final_write_processing. */
}
- else if (strcmp (name, ".options") == 0
- || strcmp (name, ".MIPS.options") == 0)
+ else if (strcmp (name, MIPS_ELF_OPTIONS_SECTION_NAME (abfd)) == 0)
{
hdr->sh_type = SHT_MIPS_OPTIONS;
hdr->sh_entsize = 1;
@@ -2714,8 +2724,7 @@ _bfd_mips_elf_set_section_contents (abfd, section, location, offset, count)
file_ptr offset;
bfd_size_type count;
{
- if (strcmp (section->name, ".options") == 0
- || strcmp (section->name, ".MIPS.options") == 0)
+ if (strcmp (section->name, MIPS_ELF_OPTIONS_SECTION_NAME (abfd)) == 0)
{
bfd_byte *c;
@@ -2762,7 +2771,9 @@ _bfd_mips_elf_section_processing (abfd, hdr)
{
const char *name = bfd_get_section_name (abfd, hdr->bfd_section);
- if (strcmp (name, ".sdata") == 0)
+ if (strcmp (name, ".sdata") == 0
+ || strcmp (name, ".lit8") == 0
+ || strcmp (name, ".lit4") == 0)
{
hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
hdr->sh_type = SHT_PROGBITS;
@@ -2772,10 +2783,9 @@ _bfd_mips_elf_section_processing (abfd, hdr)
hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
hdr->sh_type = SHT_NOBITS;
}
- else if (strcmp (name, ".lit8") == 0
- || strcmp (name, ".lit4") == 0)
+ else if (strcmp (name, MIPS_ELF_SRDATA_SECTION_NAME (abfd)) == 0)
{
- hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
+ hdr->sh_flags |= SHF_ALLOC | SHF_MIPS_GPREL;
hdr->sh_type = SHT_PROGBITS;
}
else if (strcmp (name, ".compact_rel") == 0)
@@ -2981,26 +2991,27 @@ mips_elf_additional_program_headers (abfd)
bfd *abfd;
{
asection *s;
- int ret;
-
- ret = 0;
+ int ret = 0;
- if (! SGI_COMPAT (abfd))
- return ret;
+ if (!SGI_COMPAT (abfd))
+ return 0;
+ /* See if we need a PT_MIPS_REGINFO segment. */
s = bfd_get_section_by_name (abfd, ".reginfo");
- if (s != NULL && (s->flags & SEC_LOAD) != 0)
- {
- /* We need a PT_MIPS_REGINFO segment. */
- ++ret;
- }
+ if (s && (s->flags & SEC_LOAD))
+ ++ret;
- if (bfd_get_section_by_name (abfd, ".dynamic") != NULL
- && bfd_get_section_by_name (abfd, ".mdebug") != NULL)
- {
- /* We need a PT_MIPS_RTPROC segment. */
- ++ret;
- }
+ /* See if we need a PT_MIPS_OPTIONS segment. */
+ if (IRIX_COMPAT (abfd) == ict_irix6
+ && bfd_get_section_by_name (abfd,
+ MIPS_ELF_OPTIONS_SECTION_NAME (abfd)))
+ ++ret;
+
+ /* See if we need a PT_MIPS_RTPROC segment. */
+ if (IRIX_COMPAT (abfd) == ict_irix5
+ && bfd_get_section_by_name (abfd, ".dynamic")
+ && bfd_get_section_by_name (abfd, ".mdebug"))
+ ++ret;
return ret;
}
@@ -3047,114 +3058,154 @@ mips_elf_modify_segment_map (abfd)
}
}
- /* If there are .dynamic and .mdebug sections, we make a room for
- the RTPROC header. FIXME: Rewrite without section names. */
- if (bfd_get_section_by_name (abfd, ".interp") == NULL
- && bfd_get_section_by_name (abfd, ".dynamic") != NULL
- && bfd_get_section_by_name (abfd, ".mdebug") != NULL)
+ /* For IRIX 6, we don't have .mdebug sections, nor does anything but
+ .dynamic end up in PT_DYNAMIC. However, we do have to insert a
+ PT_OPTIONS segement immediately following the program header
+ table. */
+ if (IRIX_COMPAT (abfd) == ict_irix6)
{
- for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
- if (m->p_type == PT_MIPS_RTPROC)
+ asection *s;
+
+ for (s = abfd->sections; s; s = s->next)
+ if (elf_section_data (s)->this_hdr.sh_type == SHT_MIPS_OPTIONS)
break;
- if (m == NULL)
+
+ if (s)
{
- m = (struct elf_segment_map *) bfd_zalloc (abfd, sizeof *m);
+ struct elf_segment_map *options_segment;
+
+ for (m = elf_tdata (abfd)->segment_map; m; m = m->next)
+ if (m->p_type == PT_PHDR)
+ break;
+
+ /* There should always be a program header table. */
if (m == NULL)
return false;
- m->p_type = PT_MIPS_RTPROC;
-
- s = bfd_get_section_by_name (abfd, ".rtproc");
- if (s == NULL)
- {
- m->count = 0;
- m->p_flags = 0;
- m->p_flags_valid = 1;
- }
- else
+ options_segment = bfd_zalloc (abfd,
+ sizeof (struct elf_segment_map));
+ options_segment->next = m->next;
+ options_segment->p_type = PT_MIPS_OPTIONS;
+ options_segment->p_flags = PF_R;
+ options_segment->p_flags_valid = true;
+ options_segment->count = 1;
+ options_segment->sections[0] = s;
+ m->next = options_segment;
+ }
+ }
+ else
+ {
+ /* If there are .dynamic and .mdebug sections, we make a room
+ for the RTPROC header. FIXME: Rewrite without section names. */
+ if (bfd_get_section_by_name (abfd, ".interp") == NULL
+ && bfd_get_section_by_name (abfd, ".dynamic") != NULL
+ && bfd_get_section_by_name (abfd, ".mdebug") != NULL)
+ {
+ for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+ if (m->p_type == PT_MIPS_RTPROC)
+ break;
+ if (m == NULL)
{
- m->count = 1;
- m->sections[0] = s;
- }
+ m = (struct elf_segment_map *) bfd_zalloc (abfd, sizeof *m);
+ if (m == NULL)
+ return false;
- /* We want to put it after the DYNAMIC segment. */
- pm = &elf_tdata (abfd)->segment_map;
- while (*pm != NULL && (*pm)->p_type != PT_DYNAMIC)
- pm = &(*pm)->next;
- if (*pm != NULL)
- pm = &(*pm)->next;
+ m->p_type = PT_MIPS_RTPROC;
- m->next = *pm;
- *pm = m;
+ s = bfd_get_section_by_name (abfd, ".rtproc");
+ if (s == NULL)
+ {
+ m->count = 0;
+ m->p_flags = 0;
+ m->p_flags_valid = 1;
+ }
+ else
+ {
+ m->count = 1;
+ m->sections[0] = s;
+ }
+
+ /* We want to put it after the DYNAMIC segment. */
+ pm = &elf_tdata (abfd)->segment_map;
+ while (*pm != NULL && (*pm)->p_type != PT_DYNAMIC)
+ pm = &(*pm)->next;
+ if (*pm != NULL)
+ pm = &(*pm)->next;
+
+ m->next = *pm;
+ *pm = m;
+ }
}
- }
- /* On Irix 5, the PT_DYNAMIC segment includes the .dynamic, .dynstr,
- .dynsym, and .hash sections, and everything in between. */
- for (pm = &elf_tdata (abfd)->segment_map; *pm != NULL; pm = &(*pm)->next)
- if ((*pm)->p_type == PT_DYNAMIC)
- break;
- m = *pm;
- if (m != NULL
- && m->count == 1
- && strcmp (m->sections[0]->name, ".dynamic") == 0)
- {
- static const char *sec_names[] =
- { ".dynamic", ".dynstr", ".dynsym", ".hash" };
- bfd_vma low, high;
- unsigned int i, c;
- struct elf_segment_map *n;
-
- low = 0xffffffff;
- high = 0;
- for (i = 0; i < sizeof sec_names / sizeof sec_names[0]; i++)
+ /* On Irix 5, the PT_DYNAMIC segment includes the .dynamic,
+ .dynstr, .dynsym, and .hash sections, and everything in
+ between. */
+ for (pm = &elf_tdata (abfd)->segment_map; *pm != NULL; pm = &(*pm)->next)
+ if ((*pm)->p_type == PT_DYNAMIC)
+ break;
+ m = *pm;
+ if (m != NULL
+ && m->count == 1
+ && strcmp (m->sections[0]->name, ".dynamic") == 0)
{
- s = bfd_get_section_by_name (abfd, sec_names[i]);
- if (s != NULL && (s->flags & SEC_LOAD) != 0)
+ static const char *sec_names[] =
+ { ".dynamic", ".dynstr", ".dynsym", ".hash" };
+ bfd_vma low, high;
+ unsigned int i, c;
+ struct elf_segment_map *n;
+
+ low = 0xffffffff;
+ high = 0;
+ for (i = 0; i < sizeof sec_names / sizeof sec_names[0]; i++)
{
- bfd_size_type sz;
-
- if (low > s->vma)
- low = s->vma;
- sz = s->_cooked_size;
- if (sz == 0)
- sz = s->_raw_size;
- if (high < s->vma + sz)
- high = s->vma + sz;
+ s = bfd_get_section_by_name (abfd, sec_names[i]);
+ if (s != NULL && (s->flags & SEC_LOAD) != 0)
+ {
+ bfd_size_type sz;
+
+ if (low > s->vma)
+ low = s->vma;
+ sz = s->_cooked_size;
+ if (sz == 0)
+ sz = s->_raw_size;
+ if (high < s->vma + sz)
+ high = s->vma + sz;
+ }
}
- }
- c = 0;
- for (s = abfd->sections; s != NULL; s = s->next)
- if ((s->flags & SEC_LOAD) != 0
- && s->vma >= low
- && ((s->vma
- + (s->_cooked_size != 0 ? s->_cooked_size : s->_raw_size))
- <= high))
- ++c;
-
- n = ((struct elf_segment_map *)
- bfd_zalloc (abfd, sizeof *n + (c - 1) * sizeof (asection *)));
- if (n == NULL)
- return false;
- *n = *m;
- n->count = c;
+ c = 0;
+ for (s = abfd->sections; s != NULL; s = s->next)
+ if ((s->flags & SEC_LOAD) != 0
+ && s->vma >= low
+ && ((s->vma
+ + (s->_cooked_size != 0 ? s->_cooked_size : s->_raw_size))
+ <= high))
+ ++c;
+
+ n = ((struct elf_segment_map *)
+ bfd_zalloc (abfd, sizeof *n + (c - 1) * sizeof (asection *)));
+ if (n == NULL)
+ return false;
+ *n = *m;
+ n->count = c;
- i = 0;
- for (s = abfd->sections; s != NULL; s = s->next)
- {
- if ((s->flags & SEC_LOAD) != 0
- && s->vma >= low
- && ((s->vma
- + (s->_cooked_size != 0 ? s->_cooked_size : s->_raw_size))
- <= high))
+ i = 0;
+ for (s = abfd->sections; s != NULL; s = s->next)
{
- n->sections[i] = s;
- ++i;
+ if ((s->flags & SEC_LOAD) != 0
+ && s->vma >= low
+ && ((s->vma
+ + (s->_cooked_size != 0 ?
+ s->_cooked_size : s->_raw_size))
+ <= high))
+ {
+ n->sections[i] = s;
+ ++i;
+ }
}
- }
- *pm = n;
+ *pm = n;
+ }
}
return true;
@@ -4121,22 +4172,36 @@ mips_elf_final_link (abfd, info)
HDRR *symhdr = &debug.symbolic_header;
PTR mdebug_handle = NULL;
- /* Drop the .options section, since it has special semantics which I
- haven't bothered to figure out. */
- for (secpp = &abfd->sections; *secpp != NULL; secpp = &(*secpp)->next)
+ /* If all the things we linked together were PIC, but we're
+ producing an executable (rather than a shared object), then the
+ resulting file is CPIC (i.e., it calls PIC code.) */
+ if (!info->shared && elf_elfheader (abfd)->e_flags & EF_MIPS_PIC)
{
- if (strcmp ((*secpp)->name, ".options") == 0)
- {
- for (p = (*secpp)->link_order_head; p != NULL; p = p->next)
- if (p->type == bfd_indirect_link_order)
- p->u.indirect.section->flags &=~ SEC_HAS_CONTENTS;
- (*secpp)->link_order_head = NULL;
- *secpp = (*secpp)->next;
- --abfd->section_count;
- break;
- }
+ elf_elfheader (abfd)->e_flags &= ~EF_MIPS_PIC;
+ elf_elfheader (abfd)->e_flags |= EF_MIPS_CPIC;
+
}
+ /* On IRIX5, we omit the .options section. On IRIX6, however, we
+ include it, even though we don't process it quite right. (Some
+ entries are supposed to be merged.) Empirically, we seem to be
+ better off including it then not. */
+ if (IRIX_COMPAT (abfd) == ict_irix5)
+ for (secpp = &abfd->sections; *secpp != NULL; secpp = &(*secpp)->next)
+ {
+ if (strcmp ((*secpp)->name, MIPS_ELF_OPTIONS_SECTION_NAME (abfd)) == 0)
+ {
+ for (p = (*secpp)->link_order_head; p != NULL; p = p->next)
+ if (p->type == bfd_indirect_link_order)
+ p->u.indirect.section->flags &=~ SEC_HAS_CONTENTS;
+ (*secpp)->link_order_head = NULL;
+ *secpp = (*secpp)->next;
+ --abfd->section_count;
+
+ break;
+ }
+ }
+
/* Get a value for the GP register. */
if (elf_gp (abfd) == 0)
{
@@ -4152,17 +4217,14 @@ mips_elf_final_link (abfd, info)
{
bfd_vma lo;
- /* Make up a value. */
+ /* Find the GP-relative section with the lowest offset. */
lo = (bfd_vma) -1;
for (o = abfd->sections; o != (asection *) NULL; o = o->next)
- {
- if (o->vma < lo
- && (strcmp (o->name, ".sbss") == 0
- || strcmp (o->name, ".sdata") == 0
- || strcmp (o->name, ".lit4") == 0
- || strcmp (o->name, ".lit8") == 0))
- lo = o->vma;
- }
+ if (o->vma < lo
+ && (elf_section_data (o)->this_hdr.sh_flags & SHF_MIPS_GPREL))
+ lo = o->vma;
+
+ /* And calculate GP relative to that. */
elf_gp (abfd) = lo + ELF_MIPS_GP_OFFSET (abfd);
}
else
@@ -5815,7 +5877,8 @@ mips_elf_link_output_symbol_hook (abfd, info, name, sym, input_sec)
/* The name of the dynamic interpreter. This is put in the .interp
section. */
-#define ELF_DYNAMIC_INTERPRETER "/usr/lib/libc.so.1"
+#define ELF_DYNAMIC_INTERPRETER(abfd) \
+ (ABI_N32_P (abfd) ? "/usr/lib32/libc.so.1" : "/usr/lib/libc.so.1")
/* Create dynamic sections when linking against a dynamic object. */
@@ -5872,7 +5935,11 @@ mips_elf_create_dynamic_sections (abfd, info)
return false;
}
- if (SGI_COMPAT (abfd))
+ /* On IRIX5, we adjust add some additional symbols and change the
+ alignments of several sections. There is no ABI documentation
+ indicating that this is necessary on IRIX6, nor any evidence that
+ the linker takes such action. */
+ if (IRIX_COMPAT (abfd) == ict_irix5)
{
for (namep = mips_elf_dynsym_rtproc_names; *namep != NULL; namep++)
{
@@ -6679,7 +6746,8 @@ mips_elf_adjust_dynamic_symbol (info, h)
if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
{
/* We need .stub section. */
- s = bfd_get_section_by_name (dynobj, ".stub");
+ s = bfd_get_section_by_name (dynobj,
+ MIPS_ELF_STUB_SECTION_NAME (dynobj));
BFD_ASSERT (s != NULL);
h->root.u.def.section = s;
@@ -6819,8 +6887,10 @@ mips_elf_size_dynamic_sections (output_bfd, info)
{
s = bfd_get_section_by_name (dynobj, ".interp");
BFD_ASSERT (s != NULL);
- s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
- s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
+ s->_raw_size
+ = strlen (ELF_DYNAMIC_INTERPRETER (output_bfd)) + 1;
+ s->contents
+ = (unsigned char *) ELF_DYNAMIC_INTERPRETER (output_bfd);
}
}
@@ -6929,7 +6999,7 @@ mips_elf_size_dynamic_sections (output_bfd, info)
i = elf_hash_table (info)->dynsymcount - g->global_gotsym;
s->_raw_size += i * 4;
}
- else if (strncmp (name, ".stub", 5) == 0)
+ else if (strcmp (name, MIPS_ELF_STUB_SECTION_NAME (output_bfd)) == 0)
{
/* Irix rld assumes that the function stub isn't at the end
of .text section. So put a dummy. XXX */
@@ -6964,13 +7034,12 @@ mips_elf_size_dynamic_sections (output_bfd, info)
}
/* Allocate memory for the section contents. */
- s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
+ s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
if (s->contents == NULL && s->_raw_size != 0)
{
bfd_set_error (bfd_error_no_memory);
return false;
}
- memset (s->contents, 0, s->_raw_size);
}
if (elf_hash_table (info)->dynamic_sections_created)
@@ -7203,7 +7272,8 @@ mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
BFD_ASSERT (h->dynindx != -1);
- s = bfd_get_section_by_name (dynobj, ".stub");
+ s = bfd_get_section_by_name (dynobj,
+ MIPS_ELF_STUB_SECTION_NAME (dynobj));
BFD_ASSERT (s != NULL);
/* Fill the stub. */
@@ -7333,8 +7403,10 @@ mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
else if (mips_elf_hash_table (info)->use_rld_obj_head
&& strcmp (name, "__rld_obj_head") == 0)
{
- asection *s = bfd_get_section_by_name (dynobj, ".rld_map");
- BFD_ASSERT (s != NULL);
+ /* IRIX6 does not use a .rld_map section. */
+ if (IRIX_COMPAT (output_bfd) == ict_irix5)
+ BFD_ASSERT (bfd_get_section_by_name (dynobj, ".rld_map")
+ != NULL);
mips_elf_hash_table (info)->rld_value = sym->st_value;
}
}
@@ -7673,7 +7745,8 @@ mips_elf_finish_dynamic_sections (output_bfd, info)
s->contents));
/* Clean up a dummy stub function entry in .text. */
- s = bfd_get_section_by_name (dynobj, ".stub");
+ s = bfd_get_section_by_name (dynobj,
+ MIPS_ELF_STUB_SECTION_NAME (dynobj));
if (s != NULL)
{
file_ptr dummy_offset;