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 */