1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3  * Copyright (c) 2019, Linaro Limited
4  * Copyright (c) 2022-2023, Arm Limited
5  */
6 
7 #ifndef TA_ELF_H
8 #define TA_ELF_H
9 
10 #include <ldelf.h>
11 #include <stdarg.h>
12 #include <sys/queue.h>
13 #include <tee_api_types.h>
14 #include <types_ext.h>
15 
16 struct segment {
17 	size_t offset;
18 	size_t vaddr;
19 	size_t filesz;
20 	size_t memsz;
21 	size_t flags;
22 	size_t align;
23 	bool remapped_writeable;
24 	TAILQ_ENTRY(segment) link;
25 };
26 
27 TAILQ_HEAD(segment_head, segment);
28 
29 struct ta_elf {
30 	bool is_main;
31 	bool is_32bit;	/* Initialized from Elf32_Ehdr/Elf64_Ehdr */
32 	bool is_legacy;
33 	bool bti_enabled;
34 
35 	vaddr_t load_addr;
36 	vaddr_t max_addr;
37 	vaddr_t max_offs;
38 
39 	vaddr_t ehdr_addr;
40 
41 	/* Initialized from Elf32_Ehdr/Elf64_Ehdr */
42 	vaddr_t e_entry;
43 	vaddr_t e_phoff;
44 	vaddr_t e_shoff;
45 	unsigned int e_phnum;
46 	unsigned int e_shnum;
47 	unsigned int e_phentsize;
48 	unsigned int e_shentsize;
49 
50 	void *phdr;
51 	void *shdr;
52 	/*
53 	 * dynsymtab and dynstr are used for external symbols, they may hold
54 	 * other symbols too.
55 	 */
56 	void *dynsymtab;
57 	size_t num_dynsyms;
58 	const char *dynstr;
59 	size_t dynstr_size;
60 
61 	/* DT_HASH hash table for faster resolution of external symbols */
62 	void *hashtab;
63 	/* DT_GNU_HASH table as an alternative to DT_HASH */
64 	void *gnu_hashtab;
65 	size_t gnu_hashtab_size;
66 
67 	/* DT_SONAME */
68 	char *soname;
69 
70 	struct segment_head segs;
71 
72 	vaddr_t exidx_start;
73 	size_t exidx_size;
74 
75 	/* Thread Local Storage */
76 
77 	size_t tls_mod_id;
78 	/* PT_TLS segment */
79 	vaddr_t tls_start;
80 	size_t tls_filesz; /* Covers the .tdata section */
81 	size_t tls_memsz; /* Covers the .tdata and .tbss sections */
82 #ifdef ARM64
83 	/* Offset of the copy of the TLS block in the TLS area of the TCB */
84 	size_t tls_tcb_offs;
85 #endif
86 
87 	/* PT_GNU_PROPERTY segment */
88 	vaddr_t prop_start;
89 	size_t prop_align;
90 	size_t prop_memsz;
91 
92 	uint32_t handle;
93 
94 	struct ta_head *head;
95 
96 	TEE_UUID uuid;
97 	TAILQ_ENTRY(ta_elf) link;
98 };
99 
100 TAILQ_HEAD(ta_elf_queue, ta_elf);
101 
102 /* Format of the DT_GNU_HASH entry in the ELF dynamic section */
103 struct gnu_hashtab {
104 	uint32_t nbuckets;
105 	uint32_t symoffset;
106 	uint32_t bloom_size;
107 	uint32_t bloom_shift;
108 	/*
109 	 * Followed by:
110 	 *
111 	 * uint{32,64}_t bloom[bloom_size];
112 	 * uint32_t buckets[nbuckets];
113 	 * uint32_t chain[];
114 	 */
115 };
116 
117 typedef void (*print_func_t)(void *pctx, const char *fmt, va_list ap)
118 	__printf(2, 0);
119 
120 extern struct ta_elf_queue main_elf_queue;
121 struct ta_elf *ta_elf_find_elf(const TEE_UUID *uuid);
122 
123 void ta_elf_load_main(const TEE_UUID *uuid, uint32_t *is_32bit, uint64_t *sp,
124 		      uint32_t *ta_flags);
125 void ta_elf_finalize_load_main(uint64_t *entry, uint64_t *load_addr);
126 void ta_elf_load_dependency(struct ta_elf *elf, bool is_32bit);
127 void ta_elf_relocate(struct ta_elf *elf);
128 void ta_elf_finalize_mappings(struct ta_elf *elf);
129 
130 void ta_elf_print_mappings(void *pctx, print_func_t print_func,
131 			   struct ta_elf_queue *elf_queue, size_t num_maps,
132 			   struct dump_map *maps, vaddr_t mpool_base);
133 
134 #ifdef CFG_UNWIND
135 void ta_elf_stack_trace_a32(uint32_t regs[16]);
136 void ta_elf_stack_trace_a64(uint64_t fp, uint64_t sp, uint64_t pc);
137 void ta_elf_stack_trace_riscv(uint64_t fp, uint64_t pc);
138 #else
ta_elf_stack_trace_a32(uint32_t regs[16]__unused)139 static inline void ta_elf_stack_trace_a32(uint32_t regs[16] __unused) { }
ta_elf_stack_trace_a64(uint64_t fp __unused,uint64_t sp __unused,uint64_t pc __unused)140 static inline void ta_elf_stack_trace_a64(uint64_t fp __unused,
141 					  uint64_t sp __unused,
142 					  uint64_t pc __unused) { }
ta_elf_stack_trace_riscv(uint64_t fp __unused,uint64_t pc __unused)143 static inline void ta_elf_stack_trace_riscv(uint64_t fp __unused,
144 					    uint64_t pc __unused) { }
145 #endif /*CFG_UNWIND*/
146 
147 TEE_Result ta_elf_resolve_sym(const char *name, vaddr_t *val,
148 			      struct ta_elf **found_elf, struct ta_elf *elf);
149 TEE_Result ta_elf_add_library(const TEE_UUID *uuid);
150 TEE_Result ta_elf_set_init_fini_info_compat(bool is_32bit);
151 TEE_Result ta_elf_set_elf_phdr_info(bool is_32bit);
152 
153 #endif /*TA_ELF_H*/
154