diff options
author | Jerome Forissier <jerome@forissier.org> | 2020-07-21 10:55:11 +0200 |
---|---|---|
committer | Jérôme Forissier <jerome@forissier.org> | 2020-08-06 11:10:44 +0200 |
commit | 01b02a1626cda5cda6fa202ba58220e512c82653 (patch) | |
tree | c442cd07859d3a95f830aeed13da6f3163140f6c /ldelf | |
parent | 9d224046e71083e0fe3e8c26c22f729399c2c950 (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.c | 58 | ||||
-rw-r--r-- | ldelf/ta_elf.h | 2 |
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*/ |