• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Institute of Parallel And Distributed Systems (IPADS), Shanghai Jiao Tong University (SJTU)
3  * Licensed under the Mulan PSL v2.
4  * You can use this software according to the terms and conditions of the Mulan PSL v2.
5  * You may obtain a copy of Mulan PSL v2 at:
6  *     http://license.coscl.org.cn/MulanPSL2
7  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8  * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9  * PURPOSE.
10  * See the Mulan PSL v2 for more details.
11  */
12 #ifndef LIBCHCOREELF_H
13 #define LIBCHCOREELF_H
14 
15 #include <chcore/type.h>
16 #include <chcore/memory.h>
17 #include <errno.h>
18 #include <stddef.h>
19 #include <unistd.h>
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 
25 /*
26  * ELF format according to
27  * https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
28  */
29 
30 #define EI_MAG_SIZE 4
31 
32 #define PT_NULL    0x00000000
33 #define PT_LOAD    0x00000001
34 #define PT_DYNAMIC 0x00000002
35 #define PT_INTERP  0x00000003
36 #define PT_NOTE    0x00000004
37 #define PT_SHLIB   0x00000005
38 #define PT_PHDR    0x00000006
39 #define PT_LOOS    0x60000000
40 #define PT_HIOS    0x6fffffff
41 #define PT_LOPROC  0x70000000
42 #define PT_HIRPOC  0x7fffffff
43 
44 #define PF_ALL 0x7
45 #define PF_X   0x1
46 #define PF_W   0x2
47 #define PF_R   0x4
48 
49 /*
50  * This part of ELF header is endianness-independent.
51  */
52 struct elf_indent {
53     u8 ei_magic[4];
54     u8 ei_class;
55     u8 ei_data;
56     u8 ei_version;
57     u8 ei_osabi;
58     u8 ei_abiversion;
59     u8 ei_pad[7];
60 };
61 
62 /*
63  * ELF header format. One should check the `e_indent` to decide the endianness.
64  */
65 struct elf_header {
66     struct elf_indent e_indent;
67     u16 e_type;
68     u16 e_machine;
69     u32 e_version;
70     u64 e_entry;
71     u64 e_phoff;
72     u64 e_shoff;
73     u32 e_flags;
74     u16 e_ehsize;
75     u16 e_phentsize;
76     u16 e_phnum;
77     u16 e_shentsize;
78     u16 e_shnum;
79     u16 e_shstrndx;
80 };
81 
82 /*
83  * 32-Bit of the elf_header. Check the `e_indent` first to decide.
84  */
85 struct elf_header_32 {
86     struct elf_indent e_indent;
87     u16 e_type;
88     u16 e_machine;
89     u32 e_version;
90     u32 e_entry;
91     u32 e_phoff;
92     u32 e_shoff;
93     u32 e_flags;
94     u16 e_ehsize;
95     u16 e_phentsize;
96     u16 e_phnum;
97     u16 e_shentsize;
98     u16 e_shnum;
99     u16 e_shstrndx;
100 };
101 
102 struct elf_program_header {
103     u32 p_type;
104     u32 p_flags;
105     u64 p_offset;
106     u64 p_vaddr;
107     u64 p_paddr;
108     u64 p_filesz;
109     u64 p_memsz;
110     u64 p_align;
111 };
112 
113 struct elf_program_header_32 {
114     u32 p_type;
115     u32 p_offset;
116     u32 p_vaddr;
117     u32 p_paddr;
118     u32 p_filesz;
119     u32 p_memsz;
120     u32 p_flags;
121     u32 p_align;
122 };
123 
124 struct elf_section_header {
125     u32 sh_name;
126     u32 sh_type;
127     u64 sh_flags;
128     u64 sh_addr;
129     u64 sh_offset;
130     u64 sh_size;
131     u32 sh_link;
132     u32 sh_info;
133     u64 sh_addralign;
134     u64 sh_entsize;
135 };
136 
137 struct elf_section_header_32 {
138     u32 sh_name;
139     u32 sh_type;
140     u32 sh_flags;
141     u32 sh_addr;
142     u32 sh_offset;
143     u32 sh_size;
144     u32 sh_link;
145     u32 sh_info;
146     u32 sh_addralign;
147     u32 sh_entsize;
148 };
149 
150 /**
151  * This struct represents **all** header content of an ELF file, including
152  * ELF header, program headers, and section headers.
153  */
154 struct elf_file {
155     struct elf_header header;
156     struct elf_program_header *p_headers;
157     struct elf_section_header *s_headers;
158 };
159 
160 #define ELF_PATH_LEN 255
161 
162 /**
163  * This struct represents some useful metadata coming from header of an
164  * ELF file.
165  */
166 struct process_metadata {
167     /**
168      * start virtual address of area containing program headers
169      * This value can be used for AT_PHDR auxv entry.
170      */
171     vaddr_t phdr_addr;
172     /** size of a program header, can be used for AT_PHENT */
173     size_t phentsize;
174     /** number of program headers, can be used for AT_PHNUM */
175     size_t phnum;
176     /** flags defined in ELF header */
177     int flags;
178     /** entrypoint */
179     vaddr_t entry;
180     /** type of the ELF file (EXEC, DYN, etc) */
181     unsigned int type;
182 };
183 
184 /**
185  * This struct represents a loadable(PT_LOAD) segment in an ELF file.
186  * It contains some metadata and the actual content of the segment, and
187  * those data can be used to map this segment into an address space.
188  */
189 struct user_elf_seg {
190     /** cap of a PMO holding all content of the segment in memory */
191     cap_t elf_pmo;
192     /** in-memory size of the segment(p_memsz) */
193     size_t seg_sz;
194     /** start virtual address the segment should be mapped at */
195     vaddr_t p_vaddr;
196     /**
197      * permission should be used when mapping the segment
198      * It has been translated from ELF format into ChCore VMR permission.
199      */
200     vmr_prop_t perm;
201 };
202 
203 /**
204  * This struct represents an ELF file which has been completed loaded into
205  * user's address space. It contains selected metadata of the ELF file, and all
206  * of the loadable segments (PT_LOAD) of the ELF file.
207  *
208  * For metadata, we only store some necessary information in @elf_meta from
209  * struct elf_header. For segments, each PT_LOAD segment is represented using a
210  * struct user_elf_seg, which contains the PMO storing the content of the
211  * segment, and users can use the PMO to map the segment into their address
212  * space or other process's address space.
213  */
214 struct user_elf {
215     /** number of loadable segments in the ELF file */
216     int segs_nr;
217     struct user_elf_seg *user_elf_segs;
218     char path[ELF_PATH_LEN + 1];
219     struct process_metadata elf_meta;
220 };
221 
222 /**
223  * @brief free all resources used by an user_elf struct, including memory and pmos
224  *
225  * @param user_elf
226  */
227 void free_user_elf(struct user_elf *user_elf);
228 
229 /**
230  * @brief Load header of an ELF file from a file, can be used for detecting
231  * dynamically linked ELF file with very low overhead.
232  *
233  * @param path [In]
234  * @param elf_header [Out] returning pointer to newly loaded header if
235  * successfully load and parse its content. The ownership of this pointer is
236  * transfered to the caller, so the caller should free it after use.
237  * @return 0 if success, otherwise -errno is returned. All memory resources
238  * consumed by this function are guaranteed to be freed if not success.
239  */
240 int load_elf_header_from_fs(const char *path, struct elf_header **elf_header);
241 
242 /**
243  * @brief Load the remaining content of an ELF file according to metadata in elf_header,
244  * and parse it into an user_elf struct.
245  *
246  * @param path [In]
247  * @param elf_header [In] this function only borrow the pointer, and will not free it. It's
248  * the caller's responsibility to control the life cycle of this pointer.
249  * @param elf [Out] returning pointer to newly loaded user_elf struct if success. The ownership
250  * of this pointer is transfered to the caller, so the caller should free it after use.
251  * @return 0 if success, otherwise -errno is returned. All memory resources consumed by this
252  * function are guaranteed to be freed if not success.
253  */
254 int load_elf_by_header_from_fs(const char *path, struct elf_header *elf_header,
255                                struct user_elf **elf);
256 
257 /**
258  * @brief Load an ELF file and parse it into an user_elf struct.
259  *
260  * @param path [In]
261  * @param elf [Out] returning pointer to newly loaded user_elf struct if success. The ownership
262  * of this pointer is transfered to the caller, so the caller should free it after use.
263  * @return 0 if success, otherwise -errno is returned. All memory resources consumed by this
264  * function are guaranteed to be freed if not success.
265  */
266 int load_elf_from_fs(const char *path, struct user_elf **elf);
267 
268 /**
269  * @brief Read content of an ELF file already stored in memory, and parse it into an user_elf struct.
270  *
271  * @param code [In] pointer to the memory range storing the ELF file. It's the caller's responsibility
272  * to ensure the memory range is valid. Otherwise the behavior is undefined.
273  * @param elf [Out] returning pointer to newly loaded user_elf struct if success. The ownership
274  * of this pointer is transfered to the caller, so the caller should free it after use.
275  * @return 0 if success, otherwise -errno is returned. All memory resources consumed by this
276  * function are guaranteed to be freed if not success.
277  */
278 int load_elf_from_mem(const char *code, struct user_elf **elf);
279 
280 #ifdef __cplusplus
281 }
282 #endif
283 
284 #endif /* LIBCHCOREELF_H */