1 /*
2  * Copyright (c) 2006-2024 RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author          Notes
8  * 2018/08/29     Bernard         first version
9  * 2021/04/23     chunyexixiaoyu  distinguish 32-bit and 64-bit
10  */
11 
12 #ifndef DL_ELF_H__
13 #define DL_ELF_H__
14 
15 typedef rt_uint8_t              Elf_Byte;
16 
17 typedef rt_uint32_t             Elf32_Addr;    /* Unsigned program address */
18 typedef rt_uint32_t             Elf32_Off;     /* Unsigned file offset */
19 typedef rt_int32_t              Elf32_Sword;   /* Signed large integer */
20 typedef rt_uint32_t             Elf32_Word;    /* Unsigned large integer */
21 typedef rt_uint16_t             Elf32_Half;    /* Unsigned medium integer */
22 
23 typedef rt_uint64_t             Elf64_Addr;
24 typedef rt_uint16_t             Elf64_Half;
25 typedef rt_int16_t              Elf64_SHalf;
26 typedef rt_uint64_t             Elf64_Off;
27 typedef rt_int32_t              Elf64_Sword;
28 typedef rt_uint32_t             Elf64_Word;
29 typedef rt_uint64_t             Elf64_Xword;
30 typedef rt_int64_t              Elf64_Sxword;
31 typedef rt_uint16_t             Elf64_Section;
32 
33 /* e_ident[] magic number */
34 #define ELFMAG0                 0x7f           /* e_ident[EI_MAG0] */
35 #define ELFMAG1                 'E'            /* e_ident[EI_MAG1] */
36 #define ELFMAG2                 'L'            /* e_ident[EI_MAG2] */
37 #define ELFMAG3                 'F'            /* e_ident[EI_MAG3] */
38 #define RTMMAG                  "\177RTM"      /* magic */
39 #define ELFMAG                  "\177ELF"      /* magic */
40 #define SELFMAG                 4              /* size of magic */
41 
42 #define EI_CLASS                4              /* file class */
43 #define EI_NIDENT               16             /* Size of e_ident[] */
44 
45 /* e_ident[] file class */
46 #define ELFCLASSNONE            0              /* invalid */
47 #define ELFCLASS32              1              /* 32-bit objs */
48 #define ELFCLASS64              2              /* 64-bit objs */
49 #define ELFCLASSNUM             3              /* number of classes */
50 
51 /* e_ident[] data encoding */
52 #define ELFDATANONE             0              /* invalid */
53 #define ELFDATA2LSB             1              /* Little-Endian */
54 #define ELFDATA2MSB             2              /* Big-Endian */
55 #define ELFDATANUM              3              /* number of data encode defines */
56 
57 /* e_ident */
58 #define IS_ELF(ehdr)            ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
59                                  (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
60                                  (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
61                                  (ehdr).e_ident[EI_MAG3] == ELFMAG3)
62 
63 #define ET_NONE                 0              /* No file type */
64 #define ET_REL                  1              /* Relocatable file */
65 #define ET_EXEC                 2              /* Executable file */
66 #define ET_DYN                  3              /* Shared object file */
67 #define ET_CORE                 4              /* Core file */
68 
69 /* ELF Header */
70 typedef struct elfhdr
71 {
72     unsigned char e_ident[EI_NIDENT];          /* ELF Identification */
73     Elf32_Half    e_type;                      /* object file type */
74     Elf32_Half    e_machine;                   /* machine */
75     Elf32_Word    e_version;                   /* object file version */
76     Elf32_Addr    e_entry;                     /* virtual entry point */
77     Elf32_Off     e_phoff;                     /* program header table offset */
78     Elf32_Off     e_shoff;                     /* section header table offset */
79     Elf32_Word    e_flags;                     /* processor-specific flags */
80     Elf32_Half    e_ehsize;                    /* ELF header size */
81     Elf32_Half    e_phentsize;                 /* program header entry size */
82     Elf32_Half    e_phnum;                     /* number of program header entries */
83     Elf32_Half    e_shentsize;                 /* section header entry size */
84     Elf32_Half    e_shnum;                     /* number of section header entries */
85     Elf32_Half    e_shstrndx;                  /* section header table's "section
86                                                   header string table" entry offset */
87 } Elf32_Ehdr;
88 
89 typedef struct elf64_hdr
90 {
91     unsigned char     e_ident[EI_NIDENT];        /* ELF Identification */
92     Elf64_Half        e_type;                    /* object file type */
93     Elf64_Half        e_machine;                 /* machine */
94     Elf64_Word        e_version;                 /* object file version */
95     Elf64_Addr        e_entry;                   /* virtual entry point */
96     Elf64_Off         e_phoff;                   /* program header table offset */
97     Elf64_Off         e_shoff;                   /* section header table offset */
98     Elf64_Word        e_flags;                   /* processor-specific flags */
99     Elf64_Half        e_ehsize;                  /* ELF header size */
100     Elf64_Half        e_phentsize;               /* program header entry size */
101     Elf64_Half        e_phnum;                   /* number of program header entries */
102     Elf64_Half        e_shentsize;               /* section header entry size */
103     Elf64_Half        e_shnum;                   /* number of section header entries */
104     Elf64_Half        e_shstrndx;                /* section header table's "section
105                                                 header string table" entry offset */
106 } Elf64_Ehdr;
107 
108 /* Section Header */
109 typedef struct
110 {
111     Elf32_Word sh_name;                        /* name - index into section header
112                                                   string table section */
113     Elf32_Word sh_type;                        /* type */
114     Elf32_Word sh_flags;                       /* flags */
115     Elf32_Addr sh_addr;                        /* address */
116     Elf32_Off  sh_offset;                      /* file offset */
117     Elf32_Word sh_size;                        /* section size */
118     Elf32_Word sh_link;                        /* section header table index link */
119     Elf32_Word sh_info;                        /* extra information */
120     Elf32_Word sh_addralign;                   /* address alignment */
121     Elf32_Word sh_entsize;                     /* section entry size */
122 } Elf32_Shdr;
123 
124 typedef struct
125 {
126     Elf64_Word        sh_name;                   /* Section name (string tbl index) */
127     Elf64_Word        sh_type;                   /* Section type */
128     Elf64_Xword       sh_flags;                  /* Section flags */
129     Elf64_Addr        sh_addr;                   /* Section virtual addr at execution */
130     Elf64_Off         sh_offset;                 /* Section file offset */
131     Elf64_Xword       sh_size;                   /* Section size in bytes */
132     Elf64_Word        sh_link;                   /* Link to another section */
133     Elf64_Word        sh_info;                   /* Additional section information */
134     Elf64_Xword       sh_addralign;              /* Section alignment */
135     Elf64_Xword       sh_entsize;                /* Entry size if section holds table */
136 } Elf64_Shdr;
137 
138 /* Section names */
139 #define ELF_BSS                 ".bss"         /* uninitialized data */
140 #define ELF_DATA                ".data"        /* initialized data */
141 #define ELF_DEBUG               ".debug"       /* debug */
142 #define ELF_DYNAMIC             ".dynamic"     /* dynamic linking information */
143 #define ELF_DYNSTR              ".dynstr"      /* dynamic string table */
144 #define ELF_DYNSYM              ".dynsym"      /* dynamic symbol table */
145 #define ELF_FINI                ".fini"        /* termination code */
146 #define ELF_GOT                 ".got"         /* global offset table */
147 #define ELF_HASH                ".hash"        /* symbol hash table */
148 #define ELF_INIT                ".init"        /* initialization code */
149 #define ELF_REL_DATA            ".rel.data"    /* relocation data */
150 #define ELF_REL_FINI            ".rel.fini"    /* relocation termination code */
151 #define ELF_REL_INIT            ".rel.init"    /* relocation initialization code */
152 #define ELF_REL_DYN             ".rel.dyn"     /* relocaltion dynamic link info */
153 #define ELF_REL_RODATA          ".rel.rodata"  /* relocation read-only data */
154 #define ELF_REL_TEXT            ".rel.text"    /* relocation code */
155 #define ELF_RODATA              ".rodata"      /* read-only data */
156 #define ELF_SHSTRTAB            ".shstrtab"    /* section header string table */
157 #define ELF_STRTAB              ".strtab"      /* string table */
158 #define ELF_SYMTAB              ".symtab"      /* symbol table */
159 #define ELF_TEXT                ".text"        /* code */
160 #define ELF_RTMSYMTAB           "RTMSymTab"
161 
162 /* Symbol Table Entry */
163 typedef struct elf32_sym
164 {
165     Elf32_Word    st_name;                     /* name - index into string table */
166     Elf32_Addr    st_value;                    /* symbol value */
167     Elf32_Word    st_size;                     /* symbol size */
168     unsigned char st_info;                     /* type and binding */
169     unsigned char st_other;                    /* 0 - no defined meaning */
170     Elf32_Half    st_shndx;                    /* section header index */
171 } Elf32_Sym;
172 
173 typedef struct
174 {
175     Elf64_Word        st_name;                   /* Symbol name (string tbl index) */
176     unsigned char     st_info;                   /* Symbol type and binding */
177     unsigned char     st_other;                  /* Symbol visibility */
178     Elf64_Section     st_shndx;                  /* Section index */
179     Elf64_Addr        st_value;                  /* Symbol value */
180     Elf64_Xword       st_size;                   /* Symbol size */
181 } Elf64_Sym;
182 
183 #define STB_LOCAL               0              /* BIND */
184 #define STB_GLOBAL              1
185 #define STB_WEAK                2
186 #define STB_NUM                 3
187 
188 #define STB_LOPROC              13             /* processor specific range */
189 #define STB_HIPROC              15
190 
191 #define STT_NOTYPE              0              /* symbol type is unspecified */
192 #define STT_OBJECT              1              /* data object */
193 #define STT_FUNC                2              /* code object */
194 #define STT_SECTION             3              /* symbol identifies an ELF section */
195 #define STT_FILE                4              /* symbol's name is file name */
196 #define STT_COMMON              5              /* common data object */
197 #define STT_TLS                 6              /* thread-local data object */
198 #define STT_NUM                 7              /* # defined types in generic range */
199 #define STT_LOOS                10             /* OS specific range */
200 #define STT_HIOS                12
201 #define STT_LOPROC              13             /* processor specific range */
202 #define STT_HIPROC              15
203 
204 #define STN_UNDEF               0              /* undefined */
205 
206 #define ELF_ST_BIND(info)       ((info) >> 4)
207 #define ELF_ST_TYPE(info)       ((info) & 0xf)
208 #define ELF_ST_INFO(bind, type) (((bind)<<4)+((type)&0xf))
209 
210 /* Relocation entry with implicit addend */
211 typedef struct
212 {
213     Elf32_Addr r_offset;                       /* offset of relocation */
214     Elf32_Word r_info;                         /* symbol table index and type */
215 } Elf32_Rel;
216 
217 typedef struct
218 {
219     Elf64_Addr   r_offset;                     /* Address */
220     Elf64_Xword  r_info;                       /* Relocation type and symbol index */
221 } Elf64_Rel;
222 
223 /* Relocation entry with explicit addend */
224 typedef struct
225 {
226     Elf32_Addr  r_offset;                      /* offset of relocation */
227     Elf32_Word  r_info;                        /* symbol table index and type */
228     Elf32_Sword r_addend;
229 } Elf32_Rela;
230 
231 typedef struct
232 {
233     Elf64_Addr      r_offset;                  /* Address */
234     Elf64_Xword     r_info;                    /* Relocation type and symbol index */
235     Elf64_Sxword    r_addend;                  /* Addend */
236 } Elf64_Rela;
237 
238 /* Extract relocation info - r_info */
239 #define ELF32_R_SYM(i)          ((i) >> 8)
240 #define ELF32_R_TYPE(i)         ((unsigned char) (i))
241 #define ELF32_R_INFO(s,t)       (((s) << 8) + (unsigned char)(t))
242 
243 #define ELF64_R_SYM(i)                        ((i) >> 32)
244 #define ELF64_R_TYPE(i)                        ((i) & 0xffffffff)
245 #define ELF64_R_INFO(sym,type)                ((((Elf64_Xword) (sym)) << 32) + (type))
246 
247 /*
248  * Relocation type for arm
249  */
250 #define R_ARM_NONE              0
251 #define R_ARM_PC24              1
252 #define R_ARM_ABS32             2
253 #define R_ARM_REL32             3
254 #define R_ARM_THM_CALL          10
255 #define R_ARM_GLOB_DAT          21
256 #define R_ARM_JUMP_SLOT         22
257 #define R_ARM_RELATIVE          23
258 #define R_ARM_GOT_BREL          26
259 #define R_ARM_PLT32             27
260 #define R_ARM_CALL              28
261 #define R_ARM_JUMP24            29
262 #define R_ARM_THM_JUMP24        30
263 #define R_ARM_V4BX              40
264 
265 /*
266  * Relocation type for x86
267  */
268 #define R_386_NONE              0
269 #define R_386_32                1
270 #define R_386_PC32              2
271 #define R_386_GOT32             3
272 #define R_386_PLT32             4
273 #define R_386_COPY              5
274 #define R_386_GLOB_DAT          6
275 #define R_386_JMP_SLOT          7
276 #define R_386_RELATIVE          8
277 #define R_386_GOTOFF            9
278 #define R_386_GOTPC             10
279 
280 /* Program Header */
281 typedef struct
282 {
283     Elf32_Word p_type;                         /* segment type */
284     Elf32_Off  p_offset;                       /* segment offset */
285     Elf32_Addr p_vaddr;                        /* virtual address of segment */
286     Elf32_Addr p_paddr;                        /* physical address - ignored? */
287     Elf32_Word p_filesz;                       /* number of bytes in file for seg. */
288     Elf32_Word p_memsz;                        /* number of bytes in mem. for seg. */
289     Elf32_Word p_flags;                        /* flags */
290     Elf32_Word p_align;                        /* memory alignment */
291 } Elf32_Phdr;
292 
293 typedef struct
294 {
295     Elf64_Word   p_type;                       /* Segment type */
296     Elf64_Word   p_flags;                      /* Segment flags */
297     Elf64_Off    p_offset;                     /* Segment file offset */
298     Elf64_Addr   p_vaddr;                      /* Segment virtual address */
299     Elf64_Addr   p_paddr;                      /* Segment physical address */
300     Elf64_Xword  p_filesz;                     /* Segment size in file */
301     Elf64_Xword  p_memsz;                      /* Segment size in memory */
302     Elf64_Xword  p_align;                      /* Segment alignment */
303 } Elf64_Phdr;
304 
305 /* p_type */
306 #define PT_NULL                 0
307 #define PT_LOAD                 1
308 #define PT_DYNAMIC              2
309 #define PT_INTERP               3
310 #define PT_NOTE                 4
311 #define PT_SHLIB                5
312 #define PT_PHDR                 6
313 #define PT_TLS                  7
314 #define PT_NUM                  8
315 #define PT_LOOS                 0x60000000
316 #define PT_HIOS                 0x6fffffff
317 #define PT_LOPROC               0x70000000
318 #define PT_HIPROC               0x7fffffff
319 
320 /* p_flags */
321 #define PF_X                    1
322 #define PF_W                    2
323 #define PF_R                    4
324 
325 /* sh_type */
326 #define SHT_NULL                0              /* inactive */
327 #define SHT_PROGBITS            1              /* program defined information */
328 #define SHT_SYMTAB              2              /* symbol table section */
329 #define SHT_STRTAB              3              /* string table section */
330 #define SHT_RELA                4              /* relocation section with addends*/
331 #define SHT_HASH                5              /* symbol hash table section */
332 #define SHT_DYNAMIC             6              /* dynamic section */
333 #define SHT_NOTE                7              /* note section */
334 #define SHT_NOBITS              8              /* no space section */
335 #define SHT_REL                 9              /* relocation section without addends */
336 #define SHT_SHLIB               10             /* reserved - purpose unknown */
337 #define SHT_DYNSYM              11             /* dynamic symbol table section */
338 #define SHT_NUM                 12             /* number of section types */
339 #define SHT_LOPROC              0x70000000     /* reserved range for processor */
340 #define SHT_HIPROC              0x7fffffff     /* specific section header types */
341 #define SHT_LOUSER              0x80000000     /* reserved range for application */
342 #define SHT_HIUSER              0xffffffff     /* specific indexes */
343 
344 /* Section Attribute Flags - sh_flags */
345 #define SHF_WRITE               0x1            /* Writable */
346 #define SHF_ALLOC               0x2            /* occupies memory */
347 #define SHF_EXECINSTR           0x4            /* executable */
348 #define SHF_MASKPROC            0xf0000000     /* reserved bits for processor */
349 /* specific section attributes */
350 
351 #define IS_PROG(s)        (s.sh_type == SHT_PROGBITS)
352 #define IS_NOPROG(s)      (s.sh_type == SHT_NOBITS)
353 #define IS_REL(s)         (s.sh_type == SHT_REL)
354 #define IS_RELA(s)        (s.sh_type == SHT_RELA)
355 #define IS_ALLOC(s)       (s.sh_flags == SHF_ALLOC)
356 #define IS_AX(s)          ((s.sh_flags & SHF_ALLOC) && (s.sh_flags & SHF_EXECINSTR))
357 #define IS_AW(s)          ((s.sh_flags & SHF_ALLOC) && (s.sh_flags & SHF_WRITE))
358 
359 #if (defined(__arm__) || defined(__i386__) || (__riscv_xlen == 32))
360 #define elf_module        ((Elf32_Ehdr *)module_ptr)
361 #define shdr              ((Elf32_Shdr *)((rt_uint8_t *)module_ptr + elf_module->e_shoff))
362 #define phdr              ((Elf32_Phdr *)((rt_uint8_t *)module_ptr + elf_module->e_phoff))
363 
364 typedef Elf32_Sym       Elf_Sym;
365 typedef Elf32_Rel       Elf_Rel;
366 typedef Elf32_Addr      Elf_Addr;
367 #elif (defined(__aarch64__) || defined(__x86_64__) || (__riscv_xlen == 64))
368 #define elf_module        ((Elf64_Ehdr *)module_ptr)
369 #define shdr              ((Elf64_Shdr *)((rt_uint8_t *)module_ptr + elf_module->e_shoff))
370 #define phdr              ((Elf64_Phdr *)((rt_uint8_t *)module_ptr + elf_module->e_phoff))
371 
372 typedef Elf64_Sym       Elf_Sym;
373 typedef Elf64_Rela      Elf_Rel;
374 typedef Elf64_Addr      Elf_Addr;
375 #endif
376 
377 int dlmodule_relocate(struct rt_dlmodule *module, Elf_Rel *rel, Elf_Addr sym_val);
378 rt_err_t dlmodule_load_shared_object(struct rt_dlmodule *module, void *module_ptr);
379 rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule *module, void *module_ptr);
380 
381 #endif
382