aboutsummaryrefslogtreecommitdiff
path: root/bfd/elflink.c
diff options
context:
space:
mode:
authorMichael Meissner <gnu@the-meissners.org>1996-01-22 16:43:35 +0000
committerMichael Meissner <gnu@the-meissners.org>1996-01-22 16:43:35 +0000
commit3b3753b874c1af8b5f24183294720a79b056bfcb (patch)
treeda9fa9db6994a9b0be484270c8842317d2471d3e /bfd/elflink.c
parent2d422c42341b356ed0a04e22060fca59dedfcf03 (diff)
downloadgdb-3b3753b874c1af8b5f24183294720a79b056bfcb.zip
gdb-3b3753b874c1af8b5f24183294720a79b056bfcb.tar.gz
gdb-3b3753b874c1af8b5f24183294720a79b056bfcb.tar.bz2
snapshot of eabi relocation support.
Diffstat (limited to 'bfd/elflink.c')
-rw-r--r--bfd/elflink.c169
1 files changed, 167 insertions, 2 deletions
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 3c08a4a..00e840c 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -15,14 +15,14 @@ GNU General Public License for more details.
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"
#include "bfdlink.h"
#include "libbfd.h"
#define ARCH_SIZE 0
-#include "libelf.h"
+#include "elf-bfd.h"
boolean
_bfd_elf_create_got_section (abfd, info)
@@ -77,6 +77,7 @@ _bfd_elf_create_got_section (abfd, info)
return true;
}
+
/* Create dynamic sections when linking against a dynamic object. */
@@ -163,6 +164,7 @@ _bfd_elf_create_dynamic_sections (abfd, info)
return true;
}
+
/* Record a new dynamic symbol. We record the dynamic symbols as we
read the input files, since we need to have a list of all of them
@@ -202,3 +204,166 @@ _bfd_elf_link_record_dynamic_symbol (info, h)
return true;
}
+
+/* Create a special linker section, or return a pointer to a linker section already created */
+
+elf_linker_section_t *
+_bfd_elf_create_linker_section (abfd, info, which, defaults)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ enum elf_linker_section_enum which;
+ elf_linker_section_t *defaults;
+{
+ bfd *dynobj = elf_hash_table (info)->dynobj;
+ elf_linker_section_t *lsect;
+
+ /* Record the first bfd section that needs the special section */
+ if (!dynobj)
+ dynobj = elf_hash_table (info)->dynobj = abfd;
+
+ /* If this is the first time, create the section */
+ lsect = elf_linker_section (dynobj, which);
+ if (!lsect)
+ {
+ asection *s;
+ static elf_linker_section_t zero_section;
+
+ lsect = (elf_linker_section_t *)
+ bfd_alloc (dynobj, sizeof (elf_linker_section_t));
+
+ *lsect = *defaults;
+ elf_linker_section (dynobj, which) = lsect;
+ lsect->which = which;
+ lsect->hole_written_p = false;
+
+ /* See if the sections already exist */
+ lsect->section = s = bfd_get_section_by_name (dynobj, lsect->name);
+ if (!s)
+ {
+ lsect->section = s = bfd_make_section (dynobj, lsect->name);
+
+ if (s == NULL)
+ return (elf_linker_section_t *)0;
+
+ bfd_set_section_flags (dynobj, s, defaults->flags);
+ bfd_set_section_alignment (dynobj, s, lsect->alignment);
+ }
+ else if (bfd_get_section_alignment (dynobj, s) < lsect->alignment)
+ bfd_set_section_alignment (dynobj, s, lsect->alignment);
+
+ s->_raw_size = align_power (s->_raw_size, lsect->alignment);
+
+ /* Is there a hole we have to provide? If so check whether the segment is
+ too big already */
+ if (lsect->hole_size)
+ {
+ lsect->hole_offset = s->_raw_size;
+ s->_raw_size += lsect->hole_size;
+ if (lsect->hole_offset > lsect->max_hole_offset)
+ {
+ (*_bfd_error_handler) ("%s: Section %s is already to large to put hole of %ld bytes in",
+ bfd_get_filename (abfd),
+ lsect->name,
+ (long)lsect->hole_size);
+
+ bfd_set_error (bfd_error_bad_value);
+ return (elf_linker_section_t *)0;
+ }
+ }
+
+#ifdef DEBUG
+ fprintf (stderr, "Creating section %s, current size = %ld\n",
+ lsect->name, (long)s->_raw_size);
+#endif
+
+ if (lsect->sym_name)
+ {
+ struct elf_link_hash_entry *h = NULL;
+#ifdef DEBUG
+ fprintf (stderr, "Adding %s to section %s\n",
+ lsect->sym_name,
+ lsect->name);
+#endif
+ if (!(_bfd_generic_link_add_one_symbol (info,
+ abfd,
+ lsect->sym_name,
+ BSF_GLOBAL,
+ s,
+ ((lsect->hole_size)
+ ? s->_raw_size - lsect->hole_size + lsect->sym_offset
+ : lsect->sym_offset),
+ (const char *) NULL,
+ false,
+ get_elf_backend_data (abfd)->collect,
+ (struct bfd_link_hash_entry **) &h)))
+ return (elf_linker_section_t *)0;
+
+ h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_DYNAMIC;
+ h->type = STT_OBJECT;
+ lsect->sym_hash = h;
+
+ if (info->shared
+ && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+ return (elf_linker_section_t *)0;
+ }
+ }
+
+ /* Find the related sections if they have been created */
+ if (lsect->bss_name && !lsect->bss_section)
+ lsect->bss_section = bfd_get_section_by_name (dynobj, lsect->bss_name);
+
+ if (lsect->rel_name && !lsect->rel_section)
+ lsect->rel_section = bfd_get_section_by_name (dynobj, lsect->rel_name);
+
+ return lsect;
+}
+
+
+/* Find a linker generated pointer with a given addend and type. */
+
+elf_linker_section_pointers_t *
+_bfd_elf_find_pointer_linker_section (linker_pointers, addend, which)
+ elf_linker_section_pointers_t *linker_pointers;
+ bfd_signed_vma addend;
+ elf_linker_section_enum_t which;
+{
+ for ( ; linker_pointers != NULL; linker_pointers = linker_pointers->next)
+ {
+ if (which == linker_pointers->which && addend == linker_pointers->addend)
+ return linker_pointers;
+ }
+
+ return (elf_linker_section_pointers_t *)0;
+}
+
+
+/* Make the .rela section corresponding to the generated linker section. */
+
+boolean
+_bfd_elf_make_linker_section_rela (dynobj, lsect, alignment)
+ bfd *dynobj;
+ elf_linker_section_t *lsect;
+ int alignment;
+{
+ if (lsect->rel_section)
+ return true;
+
+ lsect->rel_section = bfd_get_section_by_name (dynobj, lsect->rel_name);
+ if (lsect->rel_section == NULL)
+ {
+ lsect->rel_section = bfd_make_section (dynobj, lsect->rel_name);
+ if (lsect->rel_section == NULL
+ || ! bfd_set_section_flags (dynobj,
+ lsect->rel_section,
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_READONLY))
+ || ! bfd_set_section_alignment (dynobj, lsect->rel_section, alignment))
+ return false;
+ }
+
+ return true;
+}
+