summaryrefslogtreecommitdiffstats
path: root/cpukit/libdl/rtl-elf.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libdl/rtl-elf.c')
-rw-r--r--cpukit/libdl/rtl-elf.c95
1 files changed, 69 insertions, 26 deletions
diff --git a/cpukit/libdl/rtl-elf.c b/cpukit/libdl/rtl-elf.c
index 75b3d9c953..dd6d8617bb 100644
--- a/cpukit/libdl/rtl-elf.c
+++ b/cpukit/libdl/rtl-elf.c
@@ -1,10 +1,5 @@
-/*
- * COPYRIGHT (c) 2012-2019 Chris Johns <chrisj@rtems.org>
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
- */
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/**
* @file
*
@@ -15,6 +10,31 @@
* This is the RTL implementation.
*/
+/*
+ * COPYRIGHT (c) 2012-2019 Chris Johns <chrisj@rtems.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -158,12 +178,19 @@ rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj,
/*
* If the symbol type is STT_NOTYPE the symbol references a global
- * symbol. The gobal symbol table is searched to find it and that value
+ * symbol. The global symbol table is searched to find it and that value
* returned. If the symbol is local to the object module the section for the
* symbol is located and it's base added to the symbol's value giving an
* absolute location.
+ *
+ * If the symbols type of TLS return the symbols value. It is the
+ * offset from the thread's TLS area base. The offset is set by the
+ * linker for the base image and by the TLS allocator for loaded
+ * modules. There is no section and no absolute base.
*/
- if (ELF_ST_TYPE(sym->st_info) == STT_NOTYPE || sym->st_shndx == SHN_COMMON)
+ if (ELF_ST_TYPE (sym->st_info) == STT_NOTYPE ||
+ sym->st_shndx == SHN_COMMON ||
+ ELF_ST_TYPE (sym->st_info) == STT_TLS)
{
/*
* Search the object file then the global table for the symbol.
@@ -172,7 +199,7 @@ rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj,
if (!*symbol)
return false;
- *value = (Elf_Addr) (*symbol)->value;
+ *value = (Elf_Addr)(uintptr_t) (*symbol)->value;
return true;
}
@@ -182,7 +209,7 @@ rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj,
if (!sect)
return false;
- *value = sym->st_value + (Elf_Addr) sect->base;
+ *value = sym->st_value + (Elf_Addr)(uintptr_t) sect->base;
return true;
}
@@ -227,6 +254,13 @@ rtems_rtl_elf_reloc_parser (rtems_rtl_obj* obj,
rtems_rtl_elf_rel_status rs;
/*
+ * TLS are not parsed.
+ */
+ if (ELF_ST_TYPE (sym->st_info) == STT_TLS) {
+ return true;
+ }
+
+ /*
* Check the reloc record to see if a trampoline is needed.
*/
if (is_rela)
@@ -282,7 +316,7 @@ rtems_rtl_elf_reloc_parser (rtems_rtl_obj* obj,
* Find the symbol's object file. It cannot be NULL so ignore that result
* if returned, it means something is corrupted. We are in an iterator.
*/
- rtems_rtl_obj* sobj = rtems_rtl_find_obj_with_symbol (symbol);
+ rtems_rtl_obj* sobj = rtems_rtl_find_obj_with_symbol (symbol);
if (sobj != NULL)
{
/*
@@ -771,7 +805,7 @@ rtems_rtl_elf_tramp_resolve_reloc (rtems_rtl_unresolv_rec* rec,
}
if (unresolved || rs == rtems_rtl_elf_rel_tramp_add)
- tramp->obj->tramps_size += tramp->obj->tramp_size;
+ ++tramp->obj->tramp_slots;
if (rs == rtems_rtl_elf_rel_failure)
{
*failure = true;
@@ -784,7 +818,7 @@ rtems_rtl_elf_tramp_resolve_reloc (rtems_rtl_unresolv_rec* rec,
}
static bool
-rtems_rtl_elf_alloc_trampoline (rtems_rtl_obj* obj, size_t unresolved)
+rtems_rtl_elf_find_trampolines (rtems_rtl_obj* obj, size_t unresolved)
{
rtems_rtl_tramp_data td = { 0 };
td.obj = obj;
@@ -795,21 +829,20 @@ rtems_rtl_elf_alloc_trampoline (rtems_rtl_obj* obj, size_t unresolved)
if (td.failure)
return false;
rtems_rtl_trampoline_remove (obj);
- obj->tramp_relocs = obj->tramp_size == 0 ? 0 : obj->tramps_size / obj->tramp_size;
+ obj->tramp_relocs = obj->tramp_slots;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: tramp:elf: tramps: %zu count:%zu total:%zu\n",
+ printf ("rtl: tramp:elf: tramps: slots:%zu count:%zu total:%zu\n",
obj->tramp_relocs, td.count, td.total);
/*
* Add on enough space to handle the unresolved externals that need to be
* resolved at some point in time. They could all require fixups and
* trampolines.
*/
- obj->tramps_size += obj->tramp_size * unresolved;
+ obj->tramp_slots += unresolved;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: tramp:elf: slots: %zu (%zu)\n",
- obj->tramp_size == 0 ? 0 : obj->tramps_size / obj->tramp_size,
- obj->tramps_size);
- return rtems_rtl_obj_alloc_trampoline (obj);
+ printf ("rtl: tramp:elf: slots:%zu (%zu)\n",
+ obj->tramp_slots, obj->tramp_slots * obj->tramp_slot_size);
+ return true;
}
static bool
@@ -1151,7 +1184,7 @@ rtems_rtl_elf_symbols_load (rtems_rtl_obj* obj,
rtems_chain_set_off_chain (&osym->node);
memcpy (string, name, strlen (name) + 1);
osym->name = string;
- osym->value = (uint8_t*) value;
+ osym->value = (void*) (intptr_t) value;
osym->data = symbol.st_shndx;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
@@ -1696,7 +1729,7 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd)
/*
* Set the format's architecture's maximum tramp size.
*/
- obj->tramp_size = rtems_rtl_elf_relocate_tramp_max_size ();
+ obj->tramp_slot_size = rtems_rtl_elf_relocate_tramp_max_size ();
/*
* Parse the section information first so we have the memory map of the object
@@ -1745,13 +1778,23 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd)
if (!rtems_rtl_obj_alloc_sections (obj, fd, rtems_rtl_elf_arch_alloc, &ehdr))
return false;
- if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols_locate, &ehdr))
+ if (!rtems_rtl_elf_dependents (obj, &relocs))
return false;
- if (!rtems_rtl_elf_dependents (obj, &relocs))
+ if (!rtems_rtl_elf_find_trampolines (obj, relocs.unresolved))
return false;
- if (!rtems_rtl_elf_alloc_trampoline (obj, relocs.unresolved))
+ /*
+ * Resize the sections to allocate the trampoline memory as part of
+ * the text section.
+ */
+ if (rtems_rtl_obj_has_trampolines (obj))
+ {
+ if (!rtems_rtl_obj_resize_sections (obj))
+ return false;
+ }
+
+ if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols_locate, &ehdr))
return false;
/*