aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerome Forissier <jerome.forissier@linaro.org>2019-08-01 18:08:24 +0200
committerJérôme Forissier <jerome.forissier@linaro.org>2019-08-23 18:47:16 +0200
commitebef121c1f5cd813489c823c81834f83e7f5fb4e (patch)
tree031bfc745d3dec8315fdb49ef2549e44d829ebe8
parent791ee55c91758bc4e1379755024af64bc1a53189 (diff)
core, ldelf: add support for runtime loading of shared libraries
This commit prepares the introduction of libdl, a dynamic linking library which will allow TAs to load shared libraries at run time, and resolve symbols on demand. It adds the following function to the system PTA, inspired from the POSIX dlopen() and dlsym(): - system_dlopen(): takes a UUID and flags. Performs an upcall into ldelf which then uses the usual system PTA functions to load an map the requested library into the address space of the calling TA. - system_dlsym(): takes a UUID and a symbol name. The symbol is looked up in the library specified by UUID by calling into ldelf. If UUID is all zeros, all the mapped binaries are searched. Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org> Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org> Acked-by: Etienne Carriere <etienne.carriere@linaro.org>
-rw-r--r--core/arch/arm/include/kernel/user_ta.h1
-rw-r--r--core/arch/arm/kernel/user_ta.c1
-rw-r--r--core/arch/arm/pta/system.c175
-rw-r--r--ldelf/dl.c37
-rw-r--r--ldelf/dl.h16
-rw-r--r--ldelf/ftrace.c2
-rw-r--r--ldelf/include/ldelf.h34
-rw-r--r--ldelf/main.c18
-rw-r--r--ldelf/sub.mk1
-rw-r--r--ldelf/ta_elf.c64
-rw-r--r--ldelf/ta_elf.h6
-rw-r--r--ldelf/ta_elf_rel.c89
-rw-r--r--lib/libutee/include/pta_system.h22
13 files changed, 417 insertions, 49 deletions
diff --git a/core/arch/arm/include/kernel/user_ta.h b/core/arch/arm/include/kernel/user_ta.h
index 3e028123..72d3ac8b 100644
--- a/core/arch/arm/include/kernel/user_ta.h
+++ b/core/arch/arm/include/kernel/user_ta.h
@@ -48,6 +48,7 @@ struct user_ta_ctx {
#ifdef CFG_TA_FTRACE_SUPPORT
uaddr_t ftrace_entry_func;
#endif
+ uaddr_t dl_entry_func;
uaddr_t ldelf_stack_ptr;
bool is_32bit;
bool is_initializing;
diff --git a/core/arch/arm/kernel/user_ta.c b/core/arch/arm/kernel/user_ta.c
index 1ac48c53..9fff2c09 100644
--- a/core/arch/arm/kernel/user_ta.c
+++ b/core/arch/arm/kernel/user_ta.c
@@ -254,6 +254,7 @@ static TEE_Result init_with_ldelf(struct tee_ta_session *sess,
utc->ftrace_entry_func = arg->ftrace_entry;
sess->fbuf = arg->fbuf;
#endif
+ utc->dl_entry_func = arg->dl_entry;
out:
s = tee_ta_pop_current_session();
diff --git a/core/arch/arm/pta/system.c b/core/arch/arm/pta/system.c
index ea3f7847..733287bf 100644
--- a/core/arch/arm/pta/system.c
+++ b/core/arch/arm/pta/system.c
@@ -3,6 +3,7 @@
* Copyright (c) 2018-2019, Linaro Limited
*/
+#include <assert.h>
#include <crypto/crypto.h>
#include <kernel/handle.h>
#include <kernel/huk_subkey.h>
@@ -11,10 +12,12 @@
#include <kernel/pseudo_ta.h>
#include <kernel/user_ta.h>
#include <kernel/user_ta_store.h>
+#include <ldelf.h>
#include <mm/file.h>
#include <mm/fobj.h>
#include <mm/tee_mmu.h>
#include <pta_system.h>
+#include <string.h>
#include <tee_api_defines_extensions.h>
#include <tee_api_defines.h>
#include <util.h>
@@ -600,6 +603,174 @@ static TEE_Result system_remap(struct tee_ta_session *s, uint32_t param_types,
return res;
}
+/* ldelf has the same architecture/register width as the kernel */
+#ifdef ARM32
+static const bool is_arm32 = true;
+#else
+static const bool is_arm32;
+#endif
+
+static TEE_Result call_ldelf_dlopen(struct user_ta_ctx *utc, TEE_UUID *uuid,
+ uint32_t flags)
+{
+ uaddr_t usr_stack = utc->ldelf_stack_ptr;
+ TEE_Result res = TEE_ERROR_GENERIC;
+ struct dl_entry_arg *arg = NULL;
+ uint32_t panic_code = 0;
+ uint32_t panicked = 0;
+
+ assert(uuid);
+
+ usr_stack -= ROUNDUP(sizeof(*arg), STACK_ALIGNMENT);
+ arg = (struct dl_entry_arg *)usr_stack;
+
+ res = tee_mmu_check_access_rights(utc, TEE_MEMORY_ACCESS_READ |
+ TEE_MEMORY_ACCESS_WRITE |
+ TEE_MEMORY_ACCESS_ANY_OWNER,
+ (uaddr_t)arg, sizeof(*arg));
+ if (res) {
+ EMSG("ldelf stack is inaccessible!");
+ return res;
+ }
+
+ memset(arg, 0, sizeof(*arg));
+ arg->cmd = LDELF_DL_ENTRY_DLOPEN;
+ arg->dlopen.uuid = *uuid;
+ arg->dlopen.flags = flags;
+
+ res = thread_enter_user_mode((vaddr_t)arg, 0, 0, 0,
+ usr_stack, utc->dl_entry_func,
+ is_arm32, &panicked, &panic_code);
+ if (panicked) {
+ EMSG("ldelf dl_entry function panicked");
+ abort_print_current_ta();
+ res = TEE_ERROR_TARGET_DEAD;
+ }
+ if (!res)
+ res = arg->ret;
+
+ return res;
+}
+
+static TEE_Result call_ldelf_dlsym(struct user_ta_ctx *utc, TEE_UUID *uuid,
+ const char *sym, size_t maxlen, vaddr_t *val)
+{
+ uaddr_t usr_stack = utc->ldelf_stack_ptr;
+ TEE_Result res = TEE_ERROR_GENERIC;
+ struct dl_entry_arg *arg = NULL;
+ uint32_t panic_code = 0;
+ uint32_t panicked = 0;
+ size_t len = strnlen(sym, maxlen);
+
+ if (len == maxlen)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ usr_stack -= ROUNDUP(sizeof(*arg) + len + 1, STACK_ALIGNMENT);
+ arg = (struct dl_entry_arg *)usr_stack;
+
+ res = tee_mmu_check_access_rights(utc, TEE_MEMORY_ACCESS_READ |
+ TEE_MEMORY_ACCESS_WRITE |
+ TEE_MEMORY_ACCESS_ANY_OWNER,
+ (uaddr_t)arg,
+ sizeof(*arg) + len + 1);
+ if (res) {
+ EMSG("ldelf stack is inaccessible!");
+ return res;
+ }
+
+ memset(arg, 0, sizeof(*arg));
+ arg->cmd = LDELF_DL_ENTRY_DLSYM;
+ arg->dlsym.uuid = *uuid;
+ memcpy(arg->dlsym.symbol, sym, len);
+ arg->dlsym.symbol[len + 1] = '\0';
+
+ res = thread_enter_user_mode((vaddr_t)arg, 0, 0, 0,
+ usr_stack, utc->dl_entry_func,
+ is_arm32, &panicked, &panic_code);
+ if (panicked) {
+ EMSG("ldelf dl_entry function panicked");
+ abort_print_current_ta();
+ res = TEE_ERROR_TARGET_DEAD;
+ }
+ if (!res) {
+ res = arg->ret;
+ if (!res)
+ *val = arg->dlsym.val;
+ }
+
+ return res;
+}
+
+static TEE_Result system_dlopen(struct tee_ta_session *cs, uint32_t param_types,
+ TEE_Param params[TEE_NUM_PARAMS])
+{
+ uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
+ TEE_PARAM_TYPE_VALUE_INPUT,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+ TEE_Result res = TEE_ERROR_GENERIC;
+ struct tee_ta_session *s = NULL;
+ struct user_ta_ctx *utc = NULL;
+ TEE_UUID *uuid = NULL;
+ uint32_t flags = 0;
+
+ if (exp_pt != param_types)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ uuid = params[0].memref.buffer;
+ if (!uuid || params[0].memref.size != sizeof(*uuid))
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ flags = params[1].value.a;
+
+ utc = to_user_ta_ctx(cs->ctx);
+
+ s = tee_ta_pop_current_session();
+ res = call_ldelf_dlopen(utc, uuid, flags);
+ tee_ta_push_current_session(s);
+
+ return res;
+}
+
+static TEE_Result system_dlsym(struct tee_ta_session *cs, uint32_t param_types,
+ TEE_Param params[TEE_NUM_PARAMS])
+{
+ uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
+ TEE_PARAM_TYPE_MEMREF_INPUT,
+ TEE_PARAM_TYPE_VALUE_OUTPUT,
+ TEE_PARAM_TYPE_NONE);
+ TEE_Result res = TEE_ERROR_GENERIC;
+ struct tee_ta_session *s = NULL;
+ struct user_ta_ctx *utc = NULL;
+ const char *sym = NULL;
+ TEE_UUID *uuid = NULL;
+ size_t maxlen = 0;
+ vaddr_t va = 0;
+
+ if (exp_pt != param_types)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ uuid = params[0].memref.buffer;
+ if (uuid && params[0].memref.size != sizeof(*uuid))
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ sym = params[1].memref.buffer;
+ if (!sym)
+ return TEE_ERROR_BAD_PARAMETERS;
+ maxlen = params[1].memref.size;
+
+ utc = to_user_ta_ctx(cs->ctx);
+
+ s = tee_ta_pop_current_session();
+ res = call_ldelf_dlsym(utc, uuid, sym, maxlen, &va);
+ tee_ta_push_current_session(s);
+
+ if (!res)
+ reg_pair_from_64(va, &params[2].value.a, &params[2].value.b);
+
+ return res;
+}
+
static TEE_Result open_session(uint32_t param_types __unused,
TEE_Param params[TEE_NUM_PARAMS] __unused,
void **sess_ctx)
@@ -659,6 +830,10 @@ static TEE_Result invoke_command(void *sess_ctx, uint32_t cmd_id,
return system_set_prot(s, param_types, params);
case PTA_SYSTEM_REMAP:
return system_remap(s, param_types, params);
+ case PTA_SYSTEM_DLOPEN:
+ return system_dlopen(s, param_types, params);
+ case PTA_SYSTEM_DLSYM:
+ return system_dlsym(s, param_types, params);
default:
break;
}
diff --git a/ldelf/dl.c b/ldelf/dl.c
new file mode 100644
index 00000000..a5c52c90
--- /dev/null
+++ b/ldelf/dl.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2019, Linaro Limited
+ */
+#include <ldelf.h>
+#include <string.h>
+
+#include "dl.h"
+#include "ta_elf.h"
+
+TEE_Result dlopen_entry(struct dl_entry_arg *arg)
+{
+ TEE_UUID zero = { };
+
+ if (arg->dlopen.flags != (RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE))
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ if (!memcmp(&arg->dlopen.uuid, &zero, sizeof(zero)))
+ return TEE_SUCCESS;
+
+ return ta_elf_add_library(&arg->dlopen.uuid);
+}
+
+TEE_Result dlsym_entry(struct dl_entry_arg *arg)
+{
+ struct ta_elf *elf = NULL;
+ TEE_UUID zero = { };
+
+ if (memcmp(&arg->dlsym.uuid, &zero, sizeof(zero))) {
+ elf = ta_elf_find_elf(&arg->dlsym.uuid);
+ if (!elf)
+ return TEE_ERROR_ITEM_NOT_FOUND;
+ }
+
+ return ta_elf_resolve_sym(arg->dlsym.symbol, &arg->dlsym.val, elf);
+}
+
diff --git a/ldelf/dl.h b/ldelf/dl.h
new file mode 100644
index 00000000..66828a58
--- /dev/null
+++ b/ldelf/dl.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2019, Linaro Limited
+ */
+
+#ifndef LDELF_DL_H
+#define LDELF_DL_H
+
+#include <types_ext.h>
+#include <ldelf.h>
+
+TEE_Result dlopen_entry(struct dl_entry_arg *arg);
+TEE_Result dlsym_entry(struct dl_entry_arg *arg);
+
+#endif /*LDELF_DL_H*/
+
diff --git a/ldelf/ftrace.c b/ldelf/ftrace.c
index eef456d4..2da68efc 100644
--- a/ldelf/ftrace.c
+++ b/ldelf/ftrace.c
@@ -26,7 +26,7 @@ bool ftrace_init(struct ftrace_buf **fbuf_ptr)
int count = 0;
size_t fbuf_size = 0;
- res = ta_elf_resolve_sym("__ftrace_info", &val);
+ res = ta_elf_resolve_sym("__ftrace_info", &val, NULL);
if (res)
return false;
diff --git a/ldelf/include/ldelf.h b/ldelf/include/ldelf.h
index caad3283..d43d7445 100644
--- a/ldelf/include/ldelf.h
+++ b/ldelf/include/ldelf.h
@@ -23,6 +23,7 @@
* @dump_entry: [out] Dump TA mappings and stack trace
* @ftrace_entry: [out] Dump TA mappings and ftrace buffer
* @fbuf: [out] ftrace buffer pointer
+ * @dl_entry: [out] Dynamic linking interface (for libdl)
*/
struct ldelf_arg {
TEE_UUID uuid;
@@ -32,6 +33,7 @@ struct ldelf_arg {
uint64_t stack_ptr;
uint64_t dump_entry;
uint64_t ftrace_entry;
+ uint64_t dl_entry;
struct ftrace_buf *fbuf;
};
@@ -67,6 +69,38 @@ struct dump_entry_arg {
};
/*
+ * struct dl_entry_arg - argument for ldelf_arg::dl_entry()
+ */
+struct dl_entry_arg {
+ uint32_t cmd;
+ TEE_Result ret;
+ union {
+ struct {
+ TEE_UUID uuid; /* in */
+ uint32_t flags; /* in */
+ } dlopen;
+ struct {
+ TEE_UUID uuid; /* in */
+ vaddr_t val; /* out */
+ char symbol[]; /* in */
+ } dlsym;
+ };
+};
+
+/*
+ * Values for dl_entry_arg::cmd
+ */
+#define LDELF_DL_ENTRY_DLOPEN 0
+#define LDELF_DL_ENTRY_DLSYM 1
+
+/*
+ * Values for dl_entry_arg::dlopen::flags
+ */
+#define RTLD_NOW 2
+#define RTLD_GLOBAL 0x100
+#define RTLD_NODELETE 0x1000
+
+/*
* ldelf is loaded into memory by TEE Core. BSS is initialized and a
* stack is allocated and supplied in SP register. A struct ldelf_arg
* is placed in the stack and a pointer to the struct is provided in
diff --git a/ldelf/main.c b/ldelf/main.c
index 2290c783..24f42b1b 100644
--- a/ldelf/main.c
+++ b/ldelf/main.c
@@ -14,6 +14,7 @@
#include <types_ext.h>
#include <util.h>
+#include "dl.h"
#include "ftrace.h"
#include "sys.h"
#include "ta_elf.h"
@@ -102,6 +103,22 @@ static void __noreturn ftrace_dump(void *buf, size_t *blen)
}
#endif
+static void __noreturn dl_entry(struct dl_entry_arg *arg)
+{
+ switch (arg->cmd) {
+ case LDELF_DL_ENTRY_DLOPEN:
+ arg->ret = dlopen_entry(arg);
+ break;
+ case LDELF_DL_ENTRY_DLSYM:
+ arg->ret = dlsym_entry(arg);
+ break;
+ default:
+ arg->ret = TEE_ERROR_NOT_SUPPORTED;
+ }
+
+ sys_return_cleanup();
+}
+
/*
* ldelf()- Loads ELF into memory
* @arg: Argument passing to/from TEE Core
@@ -156,6 +173,7 @@ void ldelf(struct ldelf_arg *arg)
#else
arg->dump_entry = 0;
#endif
+ arg->dl_entry = (vaddr_t)(void *)dl_entry;
sys_return_cleanup();
}
diff --git a/ldelf/sub.mk b/ldelf/sub.mk
index 89abc469..d1f9ae9e 100644
--- a/ldelf/sub.mk
+++ b/ldelf/sub.mk
@@ -1,6 +1,7 @@
global-incdirs-y += include
srcs-$(CFG_ARM32_$(sm)) += start_a32.S
srcs-$(CFG_ARM64_$(sm)) += start_a64.S
+srcs-y += dl.c
srcs-y += main.c
srcs-y += sys.c
srcs-y += ta_elf.c
diff --git a/ldelf/ta_elf.c b/ldelf/ta_elf.c
index c45e4e50..733592e4 100644
--- a/ldelf/ta_elf.c
+++ b/ldelf/ta_elf.c
@@ -28,17 +28,12 @@ static vaddr_t ta_stack_size;
struct ta_elf_queue main_elf_queue = TAILQ_HEAD_INITIALIZER(main_elf_queue);
-static struct ta_elf *queue_elf(const TEE_UUID *uuid)
+static struct ta_elf *queue_elf_helper(const TEE_UUID *uuid)
{
- struct ta_elf *elf = NULL;
-
- TAILQ_FOREACH(elf, &main_elf_queue, link)
- if (!memcmp(uuid, &elf->uuid, sizeof(*uuid)))
- return NULL;
+ struct ta_elf *elf = calloc(1, sizeof(*elf));
- elf = calloc(1, sizeof(*elf));
if (!elf)
- err(TEE_ERROR_OUT_OF_MEMORY, "calloc");
+ return NULL;
TAILQ_INIT(&elf->segs);
@@ -47,6 +42,31 @@ static struct ta_elf *queue_elf(const TEE_UUID *uuid)
return elf;
}
+static struct ta_elf *queue_elf(const TEE_UUID *uuid)
+{
+ struct ta_elf *elf = ta_elf_find_elf(uuid);
+
+ if (elf)
+ return NULL;
+
+ elf = queue_elf_helper(uuid);
+ if (!elf)
+ err(TEE_ERROR_OUT_OF_MEMORY, "queue_elf_helper");
+
+ return elf;
+}
+
+struct ta_elf *ta_elf_find_elf(const TEE_UUID *uuid)
+{
+ struct ta_elf *elf = NULL;
+
+ TAILQ_FOREACH(elf, &main_elf_queue, link)
+ if (!memcmp(uuid, &elf->uuid, sizeof(*uuid)))
+ return elf;
+
+ return NULL;
+}
+
static TEE_Result e32_parse_ehdr(struct ta_elf *elf, Elf32_Ehdr *ehdr)
{
if (ehdr->e_ident[EI_VERSION] != EV_CURRENT ||
@@ -1147,3 +1167,31 @@ void ta_elf_stack_trace_a64(uint64_t fp, uint64_t sp, uint64_t pc)
print_stack_arm64(&state, ta_stack, ta_stack_size);
}
#endif
+
+TEE_Result ta_elf_add_library(const TEE_UUID *uuid)
+{
+ struct ta_elf *ta = TAILQ_FIRST(&main_elf_queue);
+ struct ta_elf *lib = ta_elf_find_elf(uuid);
+ struct ta_elf *elf = NULL;
+
+ if (lib)
+ return TEE_SUCCESS; /* Already mapped */
+
+ lib = queue_elf_helper(uuid);
+ if (!lib)
+ return TEE_ERROR_OUT_OF_MEMORY;
+
+ for (elf = lib; elf; elf = TAILQ_NEXT(elf, link))
+ ta_elf_load_dependency(elf, ta->is_32bit);
+
+ for (elf = lib; elf; elf = TAILQ_NEXT(elf, link)) {
+ ta_elf_relocate(elf);
+ ta_elf_finalize_mappings(elf);
+ }
+
+ for (elf = lib; elf; elf = TAILQ_NEXT(elf, link))
+ DMSG("ELF (%pUl) at %#"PRIxVA,
+ (void *)&elf->uuid, elf->load_addr);
+
+ return TEE_SUCCESS;
+}
diff --git a/ldelf/ta_elf.h b/ldelf/ta_elf.h
index 50e72274..373a2da0 100644
--- a/ldelf/ta_elf.h
+++ b/ldelf/ta_elf.h
@@ -7,6 +7,7 @@
#define TA_ELF_H
#include <ldelf.h>
+#include <stdarg.h>
#include <sys/queue.h>
#include <tee_api_types.h>
#include <types_ext.h>
@@ -77,6 +78,7 @@ typedef void (*print_func_t)(void *pctx, const char *fmt, va_list ap)
__printf(2, 0);
extern struct ta_elf_queue main_elf_queue;
+struct ta_elf *ta_elf_find_elf(const TEE_UUID *uuid);
void ta_elf_load_main(const TEE_UUID *uuid, uint32_t *is_32bit, uint64_t *sp,
uint32_t *ta_flags);
@@ -99,6 +101,8 @@ static inline void ta_elf_stack_trace_a64(uint64_t fp __unused,
uint64_t pc __unused) { }
#endif /*CFG_UNWIND*/
-TEE_Result ta_elf_resolve_sym(const char *name, vaddr_t *val);
+TEE_Result ta_elf_resolve_sym(const char *name, vaddr_t *val,
+ struct ta_elf *elf);
+TEE_Result ta_elf_add_library(const TEE_UUID *uuid);
#endif /*TA_ELF_H*/
diff --git a/ldelf/ta_elf_rel.c b/ldelf/ta_elf_rel.c
index 6aca0504..7110aa4d 100644
--- a/ldelf/ta_elf_rel.c
+++ b/ldelf/ta_elf_rel.c
@@ -50,56 +50,67 @@ static bool __resolve_sym(struct ta_elf *elf, unsigned int bind,
return true;
}
-TEE_Result ta_elf_resolve_sym(const char *name, vaddr_t *val)
+static TEE_Result resolve_sym_helper(uint32_t hash, const char *name,
+ vaddr_t *val, struct ta_elf *elf)
{
- uint32_t hash = elf_hash(name);
- struct ta_elf *elf = NULL;
+ /*
+ * Using uint32_t here for convenience because both Elf64_Word
+ * and Elf32_Word are 32-bit types
+ */
+ uint32_t *hashtab = elf->hashtab;
+ uint32_t nbuckets = hashtab[0];
+ uint32_t nchains = hashtab[1];
+ uint32_t *bucket = &hashtab[2];
+ uint32_t *chain = &bucket[nbuckets];
size_t n = 0;
- TAILQ_FOREACH(elf, &main_elf_queue, link) {
- /*
- * Using uint32_t here for convenience because both Elf64_Word
- * and Elf32_Word are 32-bit types
- */
- uint32_t *hashtab = elf->hashtab;
- uint32_t nbuckets = hashtab[0];
- uint32_t nchains = hashtab[1];
- uint32_t *bucket = &hashtab[2];
- uint32_t *chain = &bucket[nbuckets];
-
- if (elf->is_32bit) {
- Elf32_Sym *sym = elf->dynsymtab;
-
- for (n = bucket[hash % nbuckets]; n; n = chain[n]) {
- assert(n < nchains);
- if (__resolve_sym(elf,
- ELF32_ST_BIND(sym[n].st_info),
- sym[n].st_shndx,
- sym[n].st_name,
- sym[n].st_value, name, val))
- return TEE_SUCCESS;
- }
- } else {
- Elf64_Sym *sym = elf->dynsymtab;
-
- for (n = bucket[hash % nbuckets]; n; n = chain[n]) {
- assert(n < nchains);
- if (__resolve_sym(elf,
- ELF64_ST_BIND(sym[n].st_info),
- sym[n].st_shndx,
- sym[n].st_name,
- sym[n].st_value, name, val))
- return TEE_SUCCESS;
- }
+ if (elf->is_32bit) {
+ Elf32_Sym *sym = elf->dynsymtab;
+
+ for (n = bucket[hash % nbuckets]; n; n = chain[n]) {
+ assert(n < nchains);
+ if (__resolve_sym(elf,
+ ELF32_ST_BIND(sym[n].st_info),
+ sym[n].st_shndx,
+ sym[n].st_name,
+ sym[n].st_value, name, val))
+ return TEE_SUCCESS;
+ }
+ } else {
+ Elf64_Sym *sym = elf->dynsymtab;
+
+ for (n = bucket[hash % nbuckets]; n; n = chain[n]) {
+ assert(n < nchains);
+ if (__resolve_sym(elf,
+ ELF64_ST_BIND(sym[n].st_info),
+ sym[n].st_shndx,
+ sym[n].st_name,
+ sym[n].st_value, name, val))
+ return TEE_SUCCESS;
}
}
return TEE_ERROR_ITEM_NOT_FOUND;
}
+TEE_Result ta_elf_resolve_sym(const char *name, vaddr_t *val,
+ struct ta_elf *elf)
+{
+ uint32_t hash = elf_hash(name);
+
+ if (elf)
+ return resolve_sym_helper(hash, name, val, elf);
+
+ TAILQ_FOREACH(elf, &main_elf_queue, link)
+ if (!resolve_sym_helper(hash, name, val, elf))
+ return TEE_SUCCESS;
+
+ return TEE_ERROR_ITEM_NOT_FOUND;
+}
+
static void resolve_sym(const char *name, vaddr_t *val)
{
- TEE_Result res = ta_elf_resolve_sym(name, val);
+ TEE_Result res = ta_elf_resolve_sym(name, val, NULL);
if (res)
err(res, "Symbol %s not found", name);
diff --git a/lib/libutee/include/pta_system.h b/lib/libutee/include/pta_system.h
index 5e84b583..745e6dda 100644
--- a/lib/libutee/include/pta_system.h
+++ b/lib/libutee/include/pta_system.h
@@ -160,4 +160,26 @@
*/
#define PTA_SYSTEM_REMAP 9
+/*
+ * Load a shared library
+ *
+ * [in] memref[0]: the UUID of the shared library (@filename)
+ * [in] value[1].a: @flags, must be (RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE)
+ *
+ * Used by: (libdl) dlopen(const char *filename, int flags)
+ */
+#define PTA_SYSTEM_DLOPEN 10
+
+/*
+ * Resolve a symbol in a previously loaded shared library or in the whole TA
+ *
+ * [in] memref[0]: the UUID of the shared library, or the nil UUID to
+ * search the whole TA
+ * [in] memref[1]: symbol name (@symbol)
+ * [out] value[2]: address of the symbol or NULL
+ *
+ * Used by: (libdl) dlsym(void *handle, const char *symbol)
+ */
+#define PTA_SYSTEM_DLSYM 11
+
#endif /* __PTA_SYSTEM_H */