aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-mips.c
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1996-07-09 16:28:04 +0000
committerIan Lance Taylor <ian@airs.com>1996-07-09 16:28:04 +0000
commiteb52b9dc1d48b0abeefac6708a0244e431c5fb45 (patch)
tree839d82345e2fe94088894f967fe104c759eb6551 /bfd/elf32-mips.c
parent719de0ea8cda7b3c2ed9d6d4f06fb3a0380130b5 (diff)
downloadgdb-eb52b9dc1d48b0abeefac6708a0244e431c5fb45.zip
gdb-eb52b9dc1d48b0abeefac6708a0244e431c5fb45.tar.gz
gdb-eb52b9dc1d48b0abeefac6708a0244e431c5fb45.tar.bz2
From Kazumoto Kojima <kkojima@kk.info.kanagawa-u.ac.jp>:
* elf32-mips.c (struct mips_elf_link_hash_table): Add new fields use_rld_obj_head and rld_value. (mips_elf_link_hash_table_create): Initialize new fields. (mips_elf_add_symbol_hook): Mark __rld_obj_head symbol as dynamic. (mips_elf_create_dynamic_sections): Create .rld_map section. If __rld_obj_head symbol not seen, create an __rld_map symbol. (mips_elf_size_dynamic_sections): Make space in .rld_map section. Create a DT_MIPS_RLD_MAP entry rather than a DT_DEBUG entry. (mips_elf_finish_dynamic_symbol): Save value of __rld_map or __rld_obj_head symbol. (mips_elf_finish_dynamic_sections): Handle DT_MIPS_RLD_MAP.
Diffstat (limited to 'bfd/elf32-mips.c')
-rw-r--r--bfd/elf32-mips.c114
1 files changed, 112 insertions, 2 deletions
diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c
index 040eb0b..bf72091 100644
--- a/bfd/elf32-mips.c
+++ b/bfd/elf32-mips.c
@@ -2697,6 +2697,11 @@ struct mips_elf_link_hash_table
bfd_size_type procedure_count;
/* The size of the .compact_rel section (if SGI_COMPAT). */
bfd_size_type compact_rel_size;
+ /* This flag indicates that the value of DT_MIPS_RLD_MAP dynamic
+ entry is set to the address of __rld_obj_head as in Irix 5. */
+ boolean use_rld_obj_head;
+ /* This is the value of the __rld_map or __rld_obj_head symbol. */
+ bfd_vma rld_value;
};
/* Look up an entry in a MIPS ELF linker hash table. */
@@ -2784,6 +2789,8 @@ mips_elf_link_hash_table_create (abfd)
ret->dynsym_sec_strindex[i] = (bfd_size_type) -1;
ret->procedure_count = 0;
ret->compact_rel_size = 0;
+ ret->use_rld_obj_head = false;
+ ret->rld_value = 0;
return &ret->root.root;
}
@@ -2878,6 +2885,31 @@ mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
break;
}
+ if (SGI_COMPAT (abfd)
+ && ! info->shared
+ && info->hash->creator == abfd->xvec
+ && strcmp (*namep, "__rld_obj_head") == 0)
+ {
+ struct elf_link_hash_entry *h;
+
+ /* Mark __rld_obj_head as dynamic. */
+ h = NULL;
+ if (! (_bfd_generic_link_add_one_symbol
+ (info, abfd, *namep, BSF_GLOBAL, *secp,
+ (bfd_vma) *valp, (const char *) NULL, false,
+ get_elf_backend_data (abfd)->collect,
+ (struct bfd_link_hash_entry **) &h)))
+ return false;
+ h->elf_link_hash_flags &=~ ELF_LINK_NON_ELF;
+ h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->type = STT_OBJECT;
+
+ if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ return false;
+
+ mips_elf_hash_table (info)->use_rld_obj_head = true;
+ }
+
return true;
}
@@ -4651,6 +4683,17 @@ mips_elf_create_dynamic_sections (abfd, info)
return false;
}
+ if (SGI_COMPAT (abfd)
+ && !info->shared
+ && bfd_get_section_by_name (abfd, ".rld_map") == NULL)
+ {
+ s = bfd_make_section (abfd, ".rld_map");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags & ~SEC_READONLY)
+ || ! bfd_set_section_alignment (abfd, s, 2))
+ return false;
+ }
+
if (SGI_COMPAT (abfd))
{
for (namep = mips_elf_dynsym_rtproc_names; *namep != NULL; namep++)
@@ -4707,6 +4750,30 @@ mips_elf_create_dynamic_sections (abfd, info)
if (! bfd_elf32_link_record_dynamic_symbol (info, h))
return false;
+
+ if (! mips_elf_hash_table (info)->use_rld_obj_head)
+ {
+ /* __rld_map is a four byte word located in the .data section
+ and is filled in by the rtld to contain a pointer to
+ the _r_debug structure. Its symbol value will be set in
+ mips_elf_finish_dynamic_symbol. */
+ s = bfd_get_section_by_name (abfd, ".rld_map");
+ BFD_ASSERT (s != NULL);
+
+ h = NULL;
+ if (! (_bfd_generic_link_add_one_symbol
+ (info, abfd, "__rld_map", BSF_GLOBAL, s,
+ (bfd_vma) 0, (const char *) NULL, false,
+ get_elf_backend_data (abfd)->collect,
+ (struct bfd_link_hash_entry **) &h)))
+ return false;
+ h->elf_link_hash_flags &=~ ELF_LINK_NON_ELF;
+ h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->type = STT_OBJECT;
+
+ if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ return false;
+ }
}
return true;
@@ -5238,6 +5305,14 @@ mips_elf_size_dynamic_sections (output_bfd, info)
of .text section. So put a dummy. XXX */
s->_raw_size += MIPS_FUNCTION_STUB_SIZE;
}
+ else if (! info->shared
+ && ! mips_elf_hash_table (info)->use_rld_obj_head
+ && strncmp (name, ".rld_map", 8) == 0)
+ {
+ /* We add a room for __rld_map. It will be filled in by the
+ rtld to contain a pointer to the _r_debug structure. */
+ s->_raw_size += 4;
+ }
else if (SGI_COMPAT (output_bfd)
&& strncmp (name, ".compact_rel", 12) == 0)
s->_raw_size += mips_elf_hash_table (info)->compact_rel_size;
@@ -5280,8 +5355,16 @@ mips_elf_size_dynamic_sections (output_bfd, info)
dynamic linker and used by the debugger. */
if (! info->shared)
{
- if (! bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0))
- return false;
+ if (SGI_COMPAT (output_bfd))
+ {
+ /* SGI object has the equivalence of DT_DEBUG in the
+ DT_MIPS_RLD_MAP entry. */
+ if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_RLD_MAP, 0))
+ return false;
+ }
+ else
+ if (! bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0))
+ return false;
}
if (reltext)
@@ -5591,6 +5674,28 @@ mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
}
}
+ if (SGI_COMPAT (output_bfd)
+ && ! info->shared)
+ {
+ if (! mips_elf_hash_table (info)->use_rld_obj_head
+ && strcmp (name, "__rld_map") == 0)
+ {
+ asection *s = bfd_get_section_by_name (dynobj, ".rld_map");
+ BFD_ASSERT (s != NULL);
+ sym->st_value = s->output_section->vma + s->output_offset;
+ bfd_put_32 (output_bfd, (bfd_vma) 0, s->contents);
+ if (mips_elf_hash_table (info)->rld_value == 0)
+ mips_elf_hash_table (info)->rld_value = sym->st_value;
+ }
+ 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);
+ mips_elf_hash_table (info)->rld_value = sym->st_value;
+ }
+ }
+
return true;
}
@@ -5755,6 +5860,11 @@ mips_elf_finish_dynamic_sections (output_bfd, info)
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
break;
+ case DT_MIPS_RLD_MAP:
+ dyn.d_un.d_ptr = mips_elf_hash_table (info)->rld_value;
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+
}
}
}