aboutsummaryrefslogtreecommitdiff
path: root/ldelf
diff options
context:
space:
mode:
authorJerome Forissier <jerome@forissier.org>2020-07-21 10:55:11 +0200
committerJérôme Forissier <jerome@forissier.org>2020-08-06 11:10:44 +0200
commit01b02a1626cda5cda6fa202ba58220e512c82653 (patch)
treec442cd07859d3a95f830aeed13da6f3163140f6c /ldelf
parent9d224046e71083e0fe3e8c26c22f729399c2c950 (diff)
ldelf, libutee: rework support of DT_INIT_ARRAY/DT_FINI_ARRAY
Now that we have the standard function dl_iterate_phdr() in libutee, we can use it to process the initialization and finalization arrays in the ELF files and deprecate the ad-hoc structure __init_fini_info introduced in commit dd655cb9906c ("ldelf, ta: add support for DT_INIT_ARRAY and DT_FINI_ARRAY") [1]. Unfortunately, removing __init_fini_info is not an option if we want to ensure backward compatibility. This concerns only TAs which use ELF initialization and/or finalization functions. [1] Released in version 3.9.0. Signed-off-by: Jerome Forissier <jerome@forissier.org> Acked-by: Etienne Carriere <etienne.carriere@linaro.org> Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Diffstat (limited to 'ldelf')
-rw-r--r--ldelf/ta_elf.c58
-rw-r--r--ldelf/ta_elf.h2
2 files changed, 54 insertions, 6 deletions
diff --git a/ldelf/ta_elf.c b/ldelf/ta_elf.c
index ff221dd0..66801a61 100644
--- a/ldelf/ta_elf.c
+++ b/ldelf/ta_elf.c
@@ -1145,9 +1145,9 @@ void ta_elf_finalize_load_main(uint64_t *entry)
assert(elf->is_main);
- res = ta_elf_set_init_fini_info(elf->is_32bit);
+ res = ta_elf_set_init_fini_info_compat(elf->is_32bit);
if (res)
- err(res, "ta_elf_set_init_fini_info");
+ err(res, "ta_elf_set_init_fini_info_compat");
res = ta_elf_set_elf_phdr_info(elf->is_32bit);
if (res)
err(res, "ta_elf_set_elf_phdr_info");
@@ -1431,7 +1431,7 @@ TEE_Result ta_elf_add_library(const TEE_UUID *uuid)
DMSG("ELF (%pUl) at %#"PRIxVA,
(void *)&elf->uuid, elf->load_addr);
- res = ta_elf_set_init_fini_info(ta->is_32bit);
+ res = ta_elf_set_init_fini_info_compat(ta->is_32bit);
if (res)
return res;
@@ -1515,6 +1515,51 @@ static void elf_get_init_fini_array(struct ta_elf *elf, vaddr_t *init,
}
}
+/*
+ * Deprecated by __elf_phdr_info below. Kept for compatibility.
+ *
+ * Pointers to ELF initialization and finalization functions are extracted by
+ * ldelf and stored on the TA heap, then exported to the TA via the global
+ * symbol __init_fini_info. libutee in OP-TEE 3.9.0 uses this mechanism.
+ */
+
+struct __init_fini {
+ uint32_t flags;
+ uint16_t init_size;
+ uint16_t fini_size;
+
+ void (**init)(void); /* @init_size entries */
+ void (**fini)(void); /* @fini_size entries */
+};
+
+#define __IFS_VALID BIT(0)
+#define __IFS_INIT_HAS_RUN BIT(1)
+#define __IFS_FINI_HAS_RUN BIT(2)
+
+struct __init_fini_info {
+ uint32_t reserved;
+ uint16_t size;
+ uint16_t pad;
+ struct __init_fini *ifs; /* @size entries */
+};
+
+/* 32-bit variants for a 64-bit ldelf to access a 32-bit TA */
+
+struct __init_fini32 {
+ uint32_t flags;
+ uint16_t init_size;
+ uint16_t fini_size;
+ uint32_t init;
+ uint32_t fini;
+};
+
+struct __init_fini_info32 {
+ uint32_t reserved;
+ uint16_t size;
+ uint16_t pad;
+ uint32_t ifs;
+};
+
static TEE_Result realloc_ifs(vaddr_t va, size_t cnt, bool is_32bit)
{
struct __init_fini_info32 *info32 = (struct __init_fini_info32 *)va;
@@ -1604,7 +1649,7 @@ static void fill_ifs(vaddr_t va, size_t idx, struct ta_elf *elf, bool is_32bit)
* Set or update __init_fini_info in the TA with information from the ELF
* queue
*/
-TEE_Result ta_elf_set_init_fini_info(bool is_32bit)
+TEE_Result ta_elf_set_init_fini_info_compat(bool is_32bit)
{
struct __init_fini_info *info = NULL;
TEE_Result res = TEE_SUCCESS;
@@ -1615,7 +1660,10 @@ TEE_Result ta_elf_set_init_fini_info(bool is_32bit)
res = ta_elf_resolve_sym("__init_fini_info", &info_va, NULL, NULL);
if (res) {
if (res == TEE_ERROR_ITEM_NOT_FOUND) {
- /* Older TA */
+ /*
+ * Not an error, only TAs linked against libutee from
+ * OP-TEE 3.9.0 have this symbol.
+ */
return TEE_SUCCESS;
}
return res;
diff --git a/ldelf/ta_elf.h b/ldelf/ta_elf.h
index 2a558d1b..853b21d4 100644
--- a/ldelf/ta_elf.h
+++ b/ldelf/ta_elf.h
@@ -119,7 +119,7 @@ static inline void ta_elf_stack_trace_a64(uint64_t fp __unused,
TEE_Result ta_elf_resolve_sym(const char *name, vaddr_t *val,
struct ta_elf **found_elf, struct ta_elf *elf);
TEE_Result ta_elf_add_library(const TEE_UUID *uuid);
-TEE_Result ta_elf_set_init_fini_info(bool is_32bit);
+TEE_Result ta_elf_set_init_fini_info_compat(bool is_32bit);
TEE_Result ta_elf_set_elf_phdr_info(bool is_32bit);
#endif /*TA_ELF_H*/