Changeset 742fc98e in mainline for uspace/lib/c/generic/elf/elf_mod.c
- Timestamp:
- 2018-05-01T19:03:38Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 6e33c2f, 924786bf
- Parents:
- 009c485
- git-author:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-05-01 19:03:38)
- git-committer:
- GitHub <noreply@…> (2018-05-01 19:03:38)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/elf/elf_mod.c
r009c485 r742fc98e 58 58 #include <str_error.h> 59 59 #include <stdlib.h> 60 #include <macros.h> 60 61 61 62 #include <elf/elf_load.h> … … 73 74 }; 74 75 75 static unsigned int elf_load_module(elf_ld_t *elf , size_t so_bias);76 static unsigned int elf_load_module(elf_ld_t *elf); 76 77 static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry); 77 78 static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry); … … 86 87 * 87 88 * @param file ELF file. 88 * @param so_bias Bias to use if the file is a shared object.89 89 * @param info Pointer to a structure for storing information 90 90 * extracted from the binary. … … 93 93 * 94 94 */ 95 int elf_load_file(int file, size_t so_bias,eld_flags_t flags, elf_finfo_t *info)95 int elf_load_file(int file, eld_flags_t flags, elf_finfo_t *info) 96 96 { 97 97 elf_ld_t elf; … … 110 110 elf.flags = flags; 111 111 112 int ret = elf_load_module(&elf , so_bias);112 int ret = elf_load_module(&elf); 113 113 114 114 vfs_put(ofile); … … 116 116 } 117 117 118 int elf_load_file_name(const char *path, size_t so_bias, eld_flags_t flags, 119 elf_finfo_t *info) 118 int elf_load_file_name(const char *path, eld_flags_t flags, elf_finfo_t *info) 120 119 { 121 120 int file; 122 121 errno_t rc = vfs_lookup(path, 0, &file); 123 122 if (rc == EOK) { 124 int ret = elf_load_file(file, so_bias,flags, info);123 int ret = elf_load_file(file, flags, info); 125 124 vfs_put(file); 126 125 return ret; … … 137 136 * 138 137 * @param elf Pointer to loader state buffer. 139 * @param so_bias Bias to use if the file is a shared object.140 138 * @return EE_OK on success or EE_xx error code. 141 139 */ 142 static unsigned int elf_load_module(elf_ld_t *elf , size_t so_bias)140 static unsigned int elf_load_module(elf_ld_t *elf) 143 141 { 144 142 elf_header_t header_buf; … … 154 152 return EE_IO; 155 153 } 156 157 elf->header = header;158 154 159 155 /* Identify ELF */ … … 188 184 } 189 185 186 if (header->e_phoff == 0) { 187 DPRINTF("Program header table is not present!\n"); 188 return EE_UNSUPPORTED; 189 } 190 191 /* Read program header table. 192 * Normally, there are very few program headers, so don't bother 193 * with allocating memory dynamically. 194 */ 195 const int phdr_cap = 16; 196 elf_segment_header_t phdr[phdr_cap]; 197 size_t phdr_len = header->e_phnum * header->e_phentsize; 198 199 if (phdr_len > sizeof(phdr)) { 200 DPRINTF("more than %d program headers\n", phdr_cap); 201 return EE_UNSUPPORTED; 202 } 203 204 pos = header->e_phoff; 205 rc = vfs_read(elf->fd, &pos, phdr, phdr_len, &nr); 206 if (rc != EOK || nr != phdr_len) { 207 DPRINTF("Read error.\n"); 208 return EE_IO; 209 } 210 211 uintptr_t module_base = UINTPTR_MAX; 212 uintptr_t module_top = 0; 213 uintptr_t base_offset = UINTPTR_MAX; 214 215 /* Walk through PT_LOAD headers, to find out the size of the module. */ 216 for (i = 0; i < header->e_phnum; i++) { 217 if (phdr[i].p_type != PT_LOAD) 218 continue; 219 220 if (module_base > phdr[i].p_vaddr) { 221 module_base = phdr[i].p_vaddr; 222 base_offset = phdr[i].p_offset; 223 } 224 module_top = max(module_top, phdr[i].p_vaddr + phdr[i].p_memsz); 225 } 226 227 if (base_offset != 0) { 228 DPRINTF("ELF headers not present in the text segment.\n"); 229 return EE_INVALID; 230 } 231 190 232 /* Shared objects can be loaded with a bias */ 191 if (header->e_type == ET_DYN) 192 elf->bias = so_bias; 193 else 233 if (header->e_type != ET_DYN) { 194 234 elf->bias = 0; 235 } else { 236 if (module_base != 0) { 237 DPRINTF("Unexpected shared object format.\n"); 238 return EE_INVALID; 239 } 240 241 /* Attempt to allocate a span of memory large enough for the 242 * shared object. 243 */ 244 // FIXME: This is not reliable when we're running 245 // multi-threaded. Even if this part succeeds, later 246 // allocation can fail because another thread took the 247 // space in the meantime. This is only relevant for 248 // dlopen() though. 249 void *area = as_area_create(AS_AREA_ANY, module_top, 250 AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE | 251 AS_AREA_LATE_RESERVE, AS_AREA_UNPAGED); 252 253 if (area == AS_MAP_FAILED) { 254 DPRINTF("Can't find suitable memory area.\n"); 255 return EE_MEMORY; 256 } 257 258 elf->bias = (uintptr_t) area; 259 as_area_destroy(area); 260 } 261 262 /* Load all loadable segments. */ 263 for (i = 0; i < header->e_phnum; i++) { 264 if (phdr[i].p_type != PT_LOAD) 265 continue; 266 267 ret = load_segment(elf, &phdr[i]); 268 if (ret != EE_OK) 269 return ret; 270 } 271 272 void *base = (void *) module_base + elf->bias; 273 elf->info->base = base; 195 274 196 275 /* Ensure valid TLS info even if there is no TLS header. */ … … 205 284 /* Walk through all segment headers and process them. */ 206 285 for (i = 0; i < header->e_phnum; i++) { 207 elf_segment_header_t segment_hdr; 208 209 pos = header->e_phoff + i * sizeof(elf_segment_header_t); 210 rc = vfs_read(elf->fd, &pos, &segment_hdr, 211 sizeof(elf_segment_header_t), &nr); 212 if (rc != EOK || nr != sizeof(elf_segment_header_t)) { 213 DPRINTF("Read error.\n"); 214 return EE_IO; 215 } 216 217 ret = segment_header(elf, &segment_hdr); 286 if (phdr[i].p_type == PT_LOAD) 287 continue; 288 289 ret = segment_header(elf, &phdr[i]); 218 290 if (ret != EE_OK) 219 291 return ret; … … 270 342 case PT_NOTE: 271 343 break; 272 case PT_LOAD:273 return load_segment(elf, entry);274 break;275 344 case PT_INTERP: 276 345 elf->info->interp = 277 346 (void *)((uint8_t *)entry->p_vaddr + elf->bias); 278 347 279 // FIXME: This actually won't work, because the text segment is280 // not loaded yet.281 #if 0282 348 if (elf->info->interp[entry->p_filesz - 1] != '\0') { 283 349 DPRINTF("Unterminated ELF interp string.\n"); … … 285 351 } 286 352 DPRINTF("interpreter: \"%s\"\n", elf->info->interp); 287 #endif288 353 break; 289 354 case PT_DYNAMIC:
Note:
See TracChangeset
for help on using the changeset viewer.