1 /* 2 * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2003-2008, Axel Dörfler, axeld@pinc-software.de. 4 * Distributed under the terms of the MIT License. 5 * 6 * Copyright 2002, Manuel J. Petit. All rights reserved. 7 * Copyright 2001, Travis Geiselbrecht. All rights reserved. 8 * Distributed under the terms of the NewOS License. 9 */ 10 11 #include "elf_load_image.h" 12 13 #include <stdio.h> 14 #include <string.h> 15 16 #include <syscalls.h> 17 18 #include "add_ons.h" 19 #include "elf_haiku_version.h" 20 #include "elf_symbol_lookup.h" 21 #include "elf_versioning.h" 22 #include "images.h" 23 #include "runtime_loader_private.h" 24 25 26 static const char* sSearchPathSubDir = NULL; 27 28 29 static const char* 30 get_program_path() 31 { 32 return gProgramImage != NULL ? gProgramImage->path : NULL; 33 } 34 35 36 static int32 37 count_regions(const char* imagePath, char const* buff, int phnum, int phentsize) 38 { 39 struct Elf32_Phdr* pheaders; 40 int32 count = 0; 41 int i; 42 43 for (i = 0; i < phnum; i++) { 44 pheaders = (struct Elf32_Phdr*)(buff + i * phentsize); 45 46 switch (pheaders->p_type) { 47 case PT_NULL: 48 // NOP header 49 break; 50 case PT_LOAD: 51 count += 1; 52 if (pheaders->p_memsz != pheaders->p_filesz) { 53 addr_t A = TO_PAGE_SIZE(pheaders->p_vaddr 54 + pheaders->p_memsz); 55 addr_t B = TO_PAGE_SIZE(pheaders->p_vaddr 56 + pheaders->p_filesz); 57 58 if (A != B) 59 count += 1; 60 } 61 break; 62 case PT_DYNAMIC: 63 // will be handled at some other place 64 break; 65 case PT_INTERP: 66 // should check here for appropiate interpreter 67 break; 68 case PT_NOTE: 69 // unsupported 70 break; 71 case PT_SHLIB: 72 // undefined semantics 73 break; 74 case PT_PHDR: 75 // we don't use it 76 break; 77 case PT_STACK: 78 // we don't use it 79 break; 80 default: 81 FATAL("%s: Unhandled pheader type in count 0x%lx\n", 82 imagePath, pheaders->p_type); 83 return B_BAD_DATA; 84 } 85 } 86 87 return count; 88 } 89 90 91 static status_t 92 parse_program_headers(image_t* image, char* buff, int phnum, int phentsize) 93 { 94 struct Elf32_Phdr* pheader; 95 int regcount; 96 int i; 97 98 regcount = 0; 99 for (i = 0; i < phnum; i++) { 100 pheader = (struct Elf32_Phdr*)(buff + i * phentsize); 101 102 switch (pheader->p_type) { 103 case PT_NULL: 104 /* NOP header */ 105 break; 106 case PT_LOAD: 107 if (pheader->p_memsz == pheader->p_filesz) { 108 /* 109 * everything in one area 110 */ 111 image->regions[regcount].start = pheader->p_vaddr; 112 image->regions[regcount].size = pheader->p_memsz; 113 image->regions[regcount].vmstart 114 = PAGE_BASE(pheader->p_vaddr); 115 image->regions[regcount].vmsize 116 = TO_PAGE_SIZE(pheader->p_memsz 117 + PAGE_OFFSET(pheader->p_vaddr)); 118 image->regions[regcount].fdstart = pheader->p_offset; 119 image->regions[regcount].fdsize = pheader->p_filesz; 120 image->regions[regcount].delta = 0; 121 image->regions[regcount].flags = 0; 122 if (pheader->p_flags & PF_WRITE) { 123 // this is a writable segment 124 image->regions[regcount].flags |= RFLAG_RW; 125 } 126 } else { 127 /* 128 * may require splitting 129 */ 130 addr_t A = TO_PAGE_SIZE(pheader->p_vaddr 131 + pheader->p_memsz); 132 addr_t B = TO_PAGE_SIZE(pheader->p_vaddr 133 + pheader->p_filesz); 134 135 image->regions[regcount].start = pheader->p_vaddr; 136 image->regions[regcount].size = pheader->p_filesz; 137 image->regions[regcount].vmstart 138 = PAGE_BASE(pheader->p_vaddr); 139 image->regions[regcount].vmsize 140 = TO_PAGE_SIZE(pheader->p_filesz 141 + PAGE_OFFSET(pheader->p_vaddr)); 142 image->regions[regcount].fdstart = pheader->p_offset; 143 image->regions[regcount].fdsize = pheader->p_filesz; 144 image->regions[regcount].delta = 0; 145 image->regions[regcount].flags = 0; 146 if (pheader->p_flags & PF_WRITE) { 147 // this is a writable segment 148 image->regions[regcount].flags |= RFLAG_RW; 149 } 150 151 if (A != B) { 152 /* 153 * yeah, it requires splitting 154 */ 155 regcount += 1; 156 image->regions[regcount].start = pheader->p_vaddr; 157 image->regions[regcount].size 158 = pheader->p_memsz - pheader->p_filesz; 159 image->regions[regcount].vmstart 160 = image->regions[regcount-1].vmstart 161 + image->regions[regcount-1].vmsize; 162 image->regions[regcount].vmsize 163 = TO_PAGE_SIZE(pheader->p_memsz 164 + PAGE_OFFSET(pheader->p_vaddr)) 165 - image->regions[regcount-1].vmsize; 166 image->regions[regcount].fdstart = 0; 167 image->regions[regcount].fdsize = 0; 168 image->regions[regcount].delta = 0; 169 image->regions[regcount].flags = RFLAG_ANON; 170 if (pheader->p_flags & PF_WRITE) { 171 // this is a writable segment 172 image->regions[regcount].flags |= RFLAG_RW; 173 } 174 } 175 } 176 regcount += 1; 177 break; 178 case PT_DYNAMIC: 179 image->dynamic_ptr = pheader->p_vaddr; 180 break; 181 case PT_INTERP: 182 // should check here for appropiate interpreter 183 break; 184 case PT_NOTE: 185 // unsupported 186 break; 187 case PT_SHLIB: 188 // undefined semantics 189 break; 190 case PT_PHDR: 191 // we don't use it 192 break; 193 case PT_STACK: 194 // we don't use it 195 break; 196 default: 197 FATAL("%s: Unhandled pheader type in parse 0x%lx\n", 198 image->path, pheader->p_type); 199 return B_BAD_DATA; 200 } 201 } 202 203 return B_OK; 204 } 205 206 207 static bool 208 assert_dynamic_loadable(image_t* image) 209 { 210 uint32 i; 211 212 if (!image->dynamic_ptr) 213 return true; 214 215 for (i = 0; i < image->num_regions; i++) { 216 if (image->dynamic_ptr >= image->regions[i].start 217 && image->dynamic_ptr 218 < image->regions[i].start + image->regions[i].size) { 219 return true; 220 } 221 } 222 223 return false; 224 } 225 226 227 static bool 228 parse_dynamic_segment(image_t* image) 229 { 230 struct Elf32_Dyn* d; 231 int i; 232 int sonameOffset = -1; 233 234 image->symhash = 0; 235 image->syms = 0; 236 image->strtab = 0; 237 238 d = (struct Elf32_Dyn*)image->dynamic_ptr; 239 if (!d) 240 return true; 241 242 for (i = 0; d[i].d_tag != DT_NULL; i++) { 243 switch (d[i].d_tag) { 244 case DT_NEEDED: 245 image->num_needed += 1; 246 break; 247 case DT_HASH: 248 image->symhash 249 = (uint32*)(d[i].d_un.d_ptr + image->regions[0].delta); 250 break; 251 case DT_STRTAB: 252 image->strtab 253 = (char*)(d[i].d_un.d_ptr + image->regions[0].delta); 254 break; 255 case DT_SYMTAB: 256 image->syms = (struct Elf32_Sym*) 257 (d[i].d_un.d_ptr + image->regions[0].delta); 258 break; 259 case DT_REL: 260 image->rel = (struct Elf32_Rel*) 261 (d[i].d_un.d_ptr + image->regions[0].delta); 262 break; 263 case DT_RELSZ: 264 image->rel_len = d[i].d_un.d_val; 265 break; 266 case DT_RELA: 267 image->rela = (struct Elf32_Rela*) 268 (d[i].d_un.d_ptr + image->regions[0].delta); 269 break; 270 case DT_RELASZ: 271 image->rela_len = d[i].d_un.d_val; 272 break; 273 case DT_JMPREL: 274 // procedure linkage table relocations 275 image->pltrel = (struct Elf32_Rel*) 276 (d[i].d_un.d_ptr + image->regions[0].delta); 277 break; 278 case DT_PLTRELSZ: 279 image->pltrel_len = d[i].d_un.d_val; 280 break; 281 case DT_INIT: 282 image->init_routine 283 = (d[i].d_un.d_ptr + image->regions[0].delta); 284 break; 285 case DT_FINI: 286 image->term_routine 287 = (d[i].d_un.d_ptr + image->regions[0].delta); 288 break; 289 case DT_SONAME: 290 sonameOffset = d[i].d_un.d_val; 291 break; 292 case DT_VERSYM: 293 image->symbol_versions = (Elf32_Versym*) 294 (d[i].d_un.d_ptr + image->regions[0].delta); 295 break; 296 case DT_VERDEF: 297 image->version_definitions = (Elf32_Verdef*) 298 (d[i].d_un.d_ptr + image->regions[0].delta); 299 break; 300 case DT_VERDEFNUM: 301 image->num_version_definitions = d[i].d_un.d_val; 302 break; 303 case DT_VERNEED: 304 image->needed_versions = (Elf32_Verneed*) 305 (d[i].d_un.d_ptr + image->regions[0].delta); 306 break; 307 case DT_VERNEEDNUM: 308 image->num_needed_versions = d[i].d_un.d_val; 309 break; 310 case DT_SYMBOLIC: 311 image->flags |= RFLAG_SYMBOLIC; 312 break; 313 case DT_FLAGS: 314 { 315 uint32 flags = d[i].d_un.d_val; 316 if ((flags & DF_SYMBOLIC) != 0) 317 image->flags |= RFLAG_SYMBOLIC; 318 break; 319 } 320 default: 321 continue; 322 323 // TODO: Implement: 324 // DT_RELENT: The size of a DT_REL entry. 325 // DT_RELAENT: The size of a DT_RELA entry. 326 // DT_SYMENT: The size of a symbol table entry. 327 // DT_PLTREL: The type of the PLT relocation entries (DT_JMPREL). 328 // DT_BIND_NOW/DF_BIND_NOW: No lazy binding allowed. 329 // DT_INIT_ARRAY[SZ], DT_FINI_ARRAY[SZ]: Initialization/termination 330 // function arrays. 331 // DT_PREINIT_ARRAY[SZ]: Preinitialization function array. 332 // DT_RUNPATH: Library search path (supersedes DT_RPATH). 333 // DT_TEXTREL/DF_TEXTREL: Indicates whether text relocations are 334 // required (for optimization purposes only). 335 } 336 } 337 338 // lets make sure we found all the required sections 339 if (!image->symhash || !image->syms || !image->strtab) 340 return false; 341 342 if (sonameOffset >= 0) 343 strlcpy(image->name, STRING(image, sonameOffset), sizeof(image->name)); 344 345 return true; 346 } 347 348 349 // #pragma mark - 350 351 352 status_t 353 parse_elf_header(struct Elf32_Ehdr* eheader, int32* _pheaderSize, 354 int32* _sheaderSize) 355 { 356 if (memcmp(eheader->e_ident, ELF_MAGIC, 4) != 0) 357 return B_NOT_AN_EXECUTABLE; 358 359 if (eheader->e_ident[4] != ELFCLASS32) 360 return B_NOT_AN_EXECUTABLE; 361 362 if (eheader->e_phoff == 0) 363 return B_NOT_AN_EXECUTABLE; 364 365 if (eheader->e_phentsize < sizeof(struct Elf32_Phdr)) 366 return B_NOT_AN_EXECUTABLE; 367 368 *_pheaderSize = eheader->e_phentsize * eheader->e_phnum; 369 *_sheaderSize = eheader->e_shentsize * eheader->e_shnum; 370 371 if (*_pheaderSize <= 0 || *_sheaderSize <= 0) 372 return B_NOT_AN_EXECUTABLE; 373 374 return B_OK; 375 } 376 377 378 status_t 379 load_image(char const* name, image_type type, const char* rpath, 380 image_t** _image) 381 { 382 int32 pheaderSize, sheaderSize; 383 char path[PATH_MAX]; 384 ssize_t length; 385 char pheaderBuffer[4096]; 386 int32 numRegions; 387 image_t* found; 388 image_t* image; 389 status_t status; 390 int fd; 391 392 struct Elf32_Ehdr eheader; 393 394 // Have we already loaded that image? Don't check for add-ons -- we always 395 // reload them. 396 if (type != B_ADD_ON_IMAGE) { 397 found = find_loaded_image_by_name(name, APP_OR_LIBRARY_TYPE); 398 399 if (found == NULL && type != B_APP_IMAGE && gProgramImage != NULL) { 400 // Special case for add-ons that link against the application 401 // executable, with the executable not having a soname set. 402 if (const char* lastSlash = strrchr(name, '/')) { 403 if (strcmp(gProgramImage->name, lastSlash + 1) == 0) 404 found = gProgramImage; 405 } 406 } 407 408 if (found) { 409 atomic_add(&found->ref_count, 1); 410 *_image = found; 411 KTRACE("rld: load_container(\"%s\", type: %d, rpath: \"%s\") " 412 "already loaded", name, type, rpath); 413 return B_OK; 414 } 415 } 416 417 KTRACE("rld: load_container(\"%s\", type: %d, rpath: \"%s\")", name, type, 418 rpath); 419 420 strlcpy(path, name, sizeof(path)); 421 422 // find and open the file 423 fd = open_executable(path, type, rpath, get_program_path(), 424 sSearchPathSubDir); 425 if (fd < 0) { 426 FATAL("Cannot open file %s: %s\n", name, strerror(fd)); 427 KTRACE("rld: load_container(\"%s\"): failed to open file", name); 428 return fd; 429 } 430 431 // normalize the image path 432 status = _kern_normalize_path(path, true, path); 433 if (status != B_OK) 434 goto err1; 435 436 // Test again if this image has been registered already - this time, 437 // we can check the full path, not just its name as noted. 438 // You could end up loading an image twice with symbolic links, else. 439 if (type != B_ADD_ON_IMAGE) { 440 found = find_loaded_image_by_name(path, APP_OR_LIBRARY_TYPE); 441 if (found) { 442 atomic_add(&found->ref_count, 1); 443 *_image = found; 444 _kern_close(fd); 445 KTRACE("rld: load_container(\"%s\"): already loaded after all", 446 name); 447 return B_OK; 448 } 449 } 450 451 length = _kern_read(fd, 0, &eheader, sizeof(eheader)); 452 if (length != sizeof(eheader)) { 453 status = B_NOT_AN_EXECUTABLE; 454 FATAL("%s: Troubles reading ELF header\n", path); 455 goto err1; 456 } 457 458 status = parse_elf_header(&eheader, &pheaderSize, &sheaderSize); 459 if (status < B_OK) { 460 FATAL("%s: Incorrect ELF header\n", path); 461 goto err1; 462 } 463 464 // ToDo: what to do about this restriction?? 465 if (pheaderSize > (int)sizeof(pheaderBuffer)) { 466 FATAL("%s: Cannot handle program headers bigger than %lu\n", 467 path, sizeof(pheaderBuffer)); 468 status = B_UNSUPPORTED; 469 goto err1; 470 } 471 472 length = _kern_read(fd, eheader.e_phoff, pheaderBuffer, pheaderSize); 473 if (length != pheaderSize) { 474 FATAL("%s: Could not read program headers: %s\n", path, 475 strerror(length)); 476 status = B_BAD_DATA; 477 goto err1; 478 } 479 480 numRegions = count_regions(path, pheaderBuffer, eheader.e_phnum, 481 eheader.e_phentsize); 482 if (numRegions <= 0) { 483 FATAL("%s: Troubles parsing Program headers, numRegions = %ld\n", 484 path, numRegions); 485 status = B_BAD_DATA; 486 goto err1; 487 } 488 489 image = create_image(name, path, numRegions); 490 if (image == NULL) { 491 FATAL("%s: Failed to allocate image_t object\n", path); 492 status = B_NO_MEMORY; 493 goto err1; 494 } 495 496 status = parse_program_headers(image, pheaderBuffer, eheader.e_phnum, 497 eheader.e_phentsize); 498 if (status < B_OK) 499 goto err2; 500 501 if (!assert_dynamic_loadable(image)) { 502 FATAL("%s: Dynamic segment must be loadable (implementation " 503 "restriction)\n", image->path); 504 status = B_UNSUPPORTED; 505 goto err2; 506 } 507 508 status = map_image(fd, path, image, type == B_APP_IMAGE); 509 if (status < B_OK) { 510 FATAL("%s: Could not map image: %s\n", image->path, strerror(status)); 511 status = B_ERROR; 512 goto err2; 513 } 514 515 if (!parse_dynamic_segment(image)) { 516 FATAL("%s: Troubles handling dynamic section\n", image->path); 517 status = B_BAD_DATA; 518 goto err3; 519 } 520 521 if (eheader.e_entry != 0) 522 image->entry_point = eheader.e_entry + image->regions[0].delta; 523 524 analyze_image_haiku_version_and_abi(fd, image, eheader, sheaderSize, 525 pheaderBuffer, sizeof(pheaderBuffer)); 526 527 // If this is the executable image, we init the search path 528 // subdir, if the compiler version doesn't match ours. 529 if (type == B_APP_IMAGE) { 530 #if __GNUC__ == 2 531 if ((image->abi & B_HAIKU_ABI_MAJOR) == B_HAIKU_ABI_GCC_4) 532 sSearchPathSubDir = "gcc4"; 533 #elif __GNUC__ == 4 534 if ((image->abi & B_HAIKU_ABI_MAJOR) == B_HAIKU_ABI_GCC_2) 535 sSearchPathSubDir = "gcc2"; 536 #endif 537 } 538 539 // init gcc version dependent image flags 540 // symbol resolution strategy 541 if (image->abi == B_HAIKU_ABI_GCC_2_ANCIENT) 542 image->find_undefined_symbol = find_undefined_symbol_beos; 543 544 // init version infos 545 status = init_image_version_infos(image); 546 547 image->type = type; 548 register_image(image, fd, path); 549 image_event(image, IMAGE_EVENT_LOADED); 550 551 _kern_close(fd); 552 553 enqueue_loaded_image(image); 554 555 *_image = image; 556 557 KTRACE("rld: load_container(\"%s\"): done: id: %ld (ABI: %#lx)", name, 558 image->id, image->abi); 559 560 return B_OK; 561 562 err3: 563 unmap_image(image); 564 err2: 565 delete_image_struct(image); 566 err1: 567 _kern_close(fd); 568 569 KTRACE("rld: load_container(\"%s\"): failed: %s", name, 570 strerror(status)); 571 572 return status; 573 } 574