1/* 2 * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2003-2012, 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 26static const char* sSearchPathSubDir = NULL; 27 28 29static const char* 30get_program_path() 31{ 32 return gProgramImage != NULL ? gProgramImage->path : NULL; 33} 34 35 36static int32 37count_regions(const char* imagePath, char const* buff, int phnum, int phentsize) 38{ 39 elf_phdr* pheaders; 40 int32 count = 0; 41 int i; 42 43 for (i = 0; i < phnum; i++) { 44 pheaders = (elf_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%" B_PRIx32 "\n", 82 imagePath, pheaders->p_type); 83 break; 84 } 85 } 86 87 return count; 88} 89 90 91static status_t 92parse_program_headers(image_t* image, uint64_t imageOffset, char* buff, 93 int phnum, int phentsize) 94{ 95 elf_phdr* pheader; 96 int regcount; 97 int i; 98 99 regcount = 0; 100 for (i = 0; i < phnum; i++) { 101 pheader = (elf_phdr*)(buff + i * phentsize); 102 103 switch (pheader->p_type) { 104 case PT_NULL: 105 /* NOP header */ 106 break; 107 case PT_LOAD: 108 if (pheader->p_memsz == pheader->p_filesz) { 109 /* 110 * everything in one area 111 */ 112 image->regions[regcount].start = pheader->p_vaddr; 113 image->regions[regcount].size = pheader->p_memsz; 114 image->regions[regcount].vmstart 115 = PAGE_BASE(pheader->p_vaddr); 116 image->regions[regcount].vmsize 117 = TO_PAGE_SIZE(pheader->p_memsz 118 + PAGE_OFFSET(pheader->p_vaddr)); 119 image->regions[regcount].fdstart 120 = imageOffset + pheader->p_offset; 121 image->regions[regcount].fdsize = pheader->p_filesz; 122 image->regions[regcount].delta = 0; 123 image->regions[regcount].flags = 0; 124 if (pheader->p_flags & PF_WRITE) { 125 // this is a writable segment 126 image->regions[regcount].flags |= RFLAG_RW; 127 } 128 } else { 129 /* 130 * may require splitting 131 */ 132 addr_t A = TO_PAGE_SIZE(pheader->p_vaddr 133 + pheader->p_memsz); 134 addr_t B = TO_PAGE_SIZE(pheader->p_vaddr 135 + pheader->p_filesz); 136 137 image->regions[regcount].start = pheader->p_vaddr; 138 image->regions[regcount].size = pheader->p_filesz; 139 image->regions[regcount].vmstart 140 = PAGE_BASE(pheader->p_vaddr); 141 image->regions[regcount].vmsize 142 = TO_PAGE_SIZE(pheader->p_filesz 143 + PAGE_OFFSET(pheader->p_vaddr)); 144 image->regions[regcount].fdstart 145 = imageOffset + pheader->p_offset; 146 image->regions[regcount].fdsize = pheader->p_filesz; 147 image->regions[regcount].delta = 0; 148 image->regions[regcount].flags = 0; 149 if (pheader->p_flags & PF_WRITE) { 150 // this is a writable segment 151 image->regions[regcount].flags |= RFLAG_RW; 152 } 153 154 if (A != B) { 155 /* 156 * yeah, it requires splitting 157 */ 158 regcount += 1; 159 image->regions[regcount].start = pheader->p_vaddr; 160 image->regions[regcount].size 161 = pheader->p_memsz - pheader->p_filesz; 162 image->regions[regcount].vmstart 163 = image->regions[regcount-1].vmstart 164 + image->regions[regcount-1].vmsize; 165 image->regions[regcount].vmsize 166 = TO_PAGE_SIZE(pheader->p_memsz 167 + PAGE_OFFSET(pheader->p_vaddr)) 168 - image->regions[regcount-1].vmsize; 169 image->regions[regcount].fdstart = 0; 170 image->regions[regcount].fdsize = 0; 171 image->regions[regcount].delta = 0; 172 image->regions[regcount].flags = RFLAG_ANON; 173 if (pheader->p_flags & PF_WRITE) { 174 // this is a writable segment 175 image->regions[regcount].flags |= RFLAG_RW; 176 } 177 } 178 } 179 regcount += 1; 180 break; 181 case PT_DYNAMIC: 182 image->dynamic_ptr = pheader->p_vaddr; 183 break; 184 case PT_INTERP: 185 // should check here for appropiate interpreter 186 break; 187 case PT_NOTE: 188 // unsupported 189 break; 190 case PT_SHLIB: 191 // undefined semantics 192 break; 193 case PT_PHDR: 194 // we don't use it 195 break; 196 case PT_STACK: 197 // we don't use it 198 break; 199 default: 200 FATAL("%s: Unhandled pheader type in parse 0x%" B_PRIx32 "\n", 201 image->path, pheader->p_type); 202 return B_BAD_DATA; 203 } 204 } 205 206 return B_OK; 207} 208 209 210static bool 211assert_dynamic_loadable(image_t* image) 212{ 213 uint32 i; 214 215 if (!image->dynamic_ptr) 216 return true; 217 218 for (i = 0; i < image->num_regions; i++) { 219 if (image->dynamic_ptr >= image->regions[i].start 220 && image->dynamic_ptr 221 < image->regions[i].start + image->regions[i].size) { 222 return true; 223 } 224 } 225 226 return false; 227} 228 229 230static bool 231parse_dynamic_segment(image_t* image) 232{ 233 elf_dyn* d; 234 int i; 235 int sonameOffset = -1; 236 237 image->symhash = 0; 238 image->syms = 0; 239 image->strtab = 0; 240 241 d = (elf_dyn*)image->dynamic_ptr; 242 if (!d) 243 return true; 244 245 for (i = 0; d[i].d_tag != DT_NULL; i++) { 246 switch (d[i].d_tag) { 247 case DT_NEEDED: 248 image->num_needed += 1; 249 break; 250 case DT_HASH: 251 image->symhash 252 = (uint32*)(d[i].d_un.d_ptr + image->regions[0].delta); 253 break; 254 case DT_STRTAB: 255 image->strtab 256 = (char*)(d[i].d_un.d_ptr + image->regions[0].delta); 257 break; 258 case DT_SYMTAB: 259 image->syms = (elf_sym*) 260 (d[i].d_un.d_ptr + image->regions[0].delta); 261 break; 262 case DT_REL: 263 image->rel = (elf_rel*) 264 (d[i].d_un.d_ptr + image->regions[0].delta); 265 break; 266 case DT_RELSZ: 267 image->rel_len = d[i].d_un.d_val; 268 break; 269 case DT_RELA: 270 image->rela = (elf_rela*) 271 (d[i].d_un.d_ptr + image->regions[0].delta); 272 break; 273 case DT_RELASZ: 274 image->rela_len = d[i].d_un.d_val; 275 break; 276 case DT_JMPREL: 277 // procedure linkage table relocations 278 image->pltrel = (elf_rel*) 279 (d[i].d_un.d_ptr + image->regions[0].delta); 280 break; 281 case DT_PLTRELSZ: 282 image->pltrel_len = d[i].d_un.d_val; 283 break; 284 case DT_INIT: 285 image->init_routine 286 = (d[i].d_un.d_ptr + image->regions[0].delta); 287 break; 288 case DT_FINI: 289 image->term_routine 290 = (d[i].d_un.d_ptr + image->regions[0].delta); 291 break; 292 case DT_SONAME: 293 sonameOffset = d[i].d_un.d_val; 294 break; 295 case DT_VERSYM: 296 image->symbol_versions = (elf_versym*) 297 (d[i].d_un.d_ptr + image->regions[0].delta); 298 break; 299 case DT_VERDEF: 300 image->version_definitions = (elf_verdef*) 301 (d[i].d_un.d_ptr + image->regions[0].delta); 302 break; 303 case DT_VERDEFNUM: 304 image->num_version_definitions = d[i].d_un.d_val; 305 break; 306 case DT_VERNEED: 307 image->needed_versions = (elf_verneed*) 308 (d[i].d_un.d_ptr + image->regions[0].delta); 309 break; 310 case DT_VERNEEDNUM: 311 image->num_needed_versions = d[i].d_un.d_val; 312 break; 313 case DT_SYMBOLIC: 314 image->flags |= RFLAG_SYMBOLIC; 315 break; 316 case DT_FLAGS: 317 { 318 uint32 flags = d[i].d_un.d_val; 319 if ((flags & DF_SYMBOLIC) != 0) 320 image->flags |= RFLAG_SYMBOLIC; 321 break; 322 } 323 default: 324 continue; 325 326 // TODO: Implement: 327 // DT_RELENT: The size of a DT_REL entry. 328 // DT_RELAENT: The size of a DT_RELA entry. 329 // DT_SYMENT: The size of a symbol table entry. 330 // DT_PLTREL: The type of the PLT relocation entries (DT_JMPREL). 331 // DT_BIND_NOW/DF_BIND_NOW: No lazy binding allowed. 332 // DT_INIT_ARRAY[SZ], DT_FINI_ARRAY[SZ]: Initialization/termination 333 // function arrays. 334 // DT_PREINIT_ARRAY[SZ]: Preinitialization function array. 335 // DT_RUNPATH: Library search path (supersedes DT_RPATH). 336 // DT_TEXTREL/DF_TEXTREL: Indicates whether text relocations are 337 // required (for optimization purposes only). 338 } 339 } 340 341 // lets make sure we found all the required sections 342 if (!image->symhash || !image->syms || !image->strtab) 343 return false; 344 345 if (sonameOffset >= 0) 346 strlcpy(image->name, STRING(image, sonameOffset), sizeof(image->name)); 347 348 return true; 349} 350 351 352// #pragma mark - 353 354status_t 355parse_fat_header(int fd, const char* path, elf_ehdr* eheader, 356 uint64_t* imageOffset, uint64_t* imageSize, int32* _pheaderSize, 357 int32* _sheaderSize) 358{ 359 FATELF_header fatHeader; 360 ssize_t length; 361 362 length = _kern_read(fd, 0, &fatHeader, sizeof(fatHeader)); 363 if (length != sizeof(fatHeader)) { 364 FATAL("%s: Could not read FATELF header\n", path); 365 return length; 366 } 367 368 if (B_LENDIAN_TO_HOST_INT32(fatHeader.magic) != FATELF_MAGIC) 369 return B_NOT_AN_EXECUTABLE; 370 371 for (uint8_t i = 0; i < fatHeader.num_records; i++) { 372 FATELF_record fatRecord; 373 374 length = _kern_read(fd, FATELF_DISK_FORMAT_SIZE(i), &fatRecord, 375 sizeof(fatRecord)); 376 if (length != sizeof(fatRecord)) { 377 FATAL("%s: Could not read FATELF record at index %" B_PRIu8 "\n", 378 path, i); 379 return length; 380 } 381 382 // FATELF_NOTE: This code currently simply validates that the 383 // machine type, word size, and byte order directly match. 384 // 385 // This could perform much smarter checking when working with 386 // upward-compatible ABI variations and instruction sets; ie, 387 // ARMv6+hardfloat binaries could be linked against ARMv7 libraries, 388 // avoiding the need to load a duplicate set of system libraries. 389 if (!ELF_MACHINE_OK(B_LENDIAN_TO_HOST_INT16(fatRecord.machine))) 390 continue; 391 392 if (fatRecord.word_size != ELF_CLASS) 393 continue; 394 395 if (fatRecord.byte_order != ELF_DATA) 396 continue; 397 398 *imageOffset = B_LENDIAN_TO_HOST_INT64(fatRecord.offset); 399 *imageSize = B_LENDIAN_TO_HOST_INT64(fatRecord.size); 400 401 length = _kern_read(fd, *imageOffset, eheader, sizeof(*eheader)); 402 if (length != sizeof(*eheader)) { 403 FATAL("%s: Short ELF header read for FATELF record %" B_PRIu8 "\n", 404 path, i); 405 return B_NOT_AN_EXECUTABLE; 406 } 407 408 return parse_elf_header(eheader, _pheaderSize, _sheaderSize); 409 } 410 411 return B_MISMATCHING_ARCHITECTURE; 412} 413 414status_t 415parse_elf_header(elf_ehdr* eheader, int32* _pheaderSize, 416 int32* _sheaderSize) 417{ 418 if (memcmp(eheader->e_ident, ELF_MAGIC, 4) != 0) 419 return B_NOT_AN_EXECUTABLE; 420 421 if (eheader->e_ident[EI_CLASS] != ELF_CLASS) 422 return B_MISMATCHING_ARCHITECTURE; 423 424 if (eheader->e_ident[EI_DATA] != ELF_DATA) 425 return B_MISMATCHING_ARCHITECTURE; 426 427 if (eheader->e_ident[EI_OSABI] != ELFOSABI_HAIKU) 428 return B_MISMATCHING_PLATFORM; 429 430 if (!ELF_MACHINE_OK(eheader->e_machine)) 431 return B_MISMATCHING_ARCHITECTURE; 432 433 if (eheader->e_phoff == 0) 434 return B_NOT_AN_EXECUTABLE; 435 436 if (eheader->e_phentsize < sizeof(elf_phdr)) 437 return B_NOT_AN_EXECUTABLE; 438 439 *_pheaderSize = eheader->e_phentsize * eheader->e_phnum; 440 *_sheaderSize = eheader->e_shentsize * eheader->e_shnum; 441 442 if (*_pheaderSize <= 0 || *_sheaderSize <= 0) 443 return B_NOT_AN_EXECUTABLE; 444 445 return B_OK; 446} 447 448 449status_t 450load_image(char const* name, image_type type, const char* rpath, 451 image_t** _image) 452{ 453 int32 pheaderSize, sheaderSize; 454 char path[PATH_MAX]; 455 ssize_t length; 456 char pheaderBuffer[4096]; 457 uint64_t imageOffset; 458 uint64_t fatImageSize; 459 int32 numRegions; 460 image_t* found; 461 image_t* image; 462 status_t status; 463 int fd; 464 465 elf_ehdr eheader; 466 467 // Have we already loaded that image? Don't check for add-ons -- we always 468 // reload them. 469 if (type != B_ADD_ON_IMAGE) { 470 found = find_loaded_image_by_name(name, APP_OR_LIBRARY_TYPE); 471 472 if (found == NULL && type != B_APP_IMAGE && gProgramImage != NULL) { 473 // Special case for add-ons that link against the application 474 // executable, with the executable not having a soname set. 475 if (const char* lastSlash = strrchr(name, '/')) { 476 if (strcmp(gProgramImage->name, lastSlash + 1) == 0) 477 found = gProgramImage; 478 } 479 } 480 481 if (found) { 482 atomic_add(&found->ref_count, 1); 483 *_image = found; 484 KTRACE("rld: load_container(\"%s\", type: %d, rpath: \"%s\") " 485 "already loaded", name, type, rpath); 486 return B_OK; 487 } 488 } 489 490 KTRACE("rld: load_container(\"%s\", type: %d, rpath: \"%s\")", name, type, 491 rpath); 492 493 strlcpy(path, name, sizeof(path)); 494 495 // find and open the file 496 fd = open_executable(path, type, rpath, get_program_path(), 497 sSearchPathSubDir); 498 if (fd < 0) { 499 FATAL("Cannot open file %s: %s\n", name, strerror(fd)); 500 KTRACE("rld: load_container(\"%s\"): failed to open file", name); 501 return fd; 502 } 503 504 // normalize the image path 505 status = _kern_normalize_path(path, true, path); 506 if (status != B_OK) 507 goto err1; 508 509 // Test again if this image has been registered already - this time, 510 // we can check the full path, not just its name as noted. 511 // You could end up loading an image twice with symbolic links, else. 512 if (type != B_ADD_ON_IMAGE) { 513 found = find_loaded_image_by_name(path, APP_OR_LIBRARY_TYPE); 514 if (found) { 515 atomic_add(&found->ref_count, 1); 516 *_image = found; 517 _kern_close(fd); 518 KTRACE("rld: load_container(\"%s\"): already loaded after all", 519 name); 520 return B_OK; 521 } 522 } 523 524 length = _kern_read(fd, 0, &eheader, sizeof(eheader)); 525 if (length != sizeof(eheader)) { 526 status = B_NOT_AN_EXECUTABLE; 527 FATAL("%s: Troubles reading ELF header\n", path); 528 goto err1; 529 } 530 531 imageOffset = 0x0; 532 fatImageSize = 0x0; 533 status = parse_elf_header(&eheader, &pheaderSize, &sheaderSize); 534 if (status == B_NOT_AN_EXECUTABLE) { 535 status = parse_fat_header(fd, path, &eheader, &imageOffset, 536 &fatImageSize, &pheaderSize, &sheaderSize); 537 538 if (status != B_OK) { 539 FATAL("%s: Incorrect ELF header\n", path); 540 goto err1; 541 } 542 } 543 544 // ToDo: what to do about this restriction?? 545 if (pheaderSize > (int)sizeof(pheaderBuffer)) { 546 FATAL("%s: Cannot handle program headers bigger than %lu\n", 547 path, sizeof(pheaderBuffer)); 548 status = B_UNSUPPORTED; 549 goto err1; 550 } 551 552 length = _kern_read(fd, imageOffset + eheader.e_phoff, pheaderBuffer, 553 pheaderSize); 554 if (length != pheaderSize) { 555 FATAL("%s: Could not read program headers: %s\n", path, 556 strerror(length)); 557 status = B_BAD_DATA; 558 goto err1; 559 } 560 561 numRegions = count_regions(path, pheaderBuffer, eheader.e_phnum, 562 eheader.e_phentsize); 563 if (numRegions <= 0) { 564 FATAL("%s: Troubles parsing Program headers, numRegions = %" B_PRId32 565 "\n", path, numRegions); 566 status = B_BAD_DATA; 567 goto err1; 568 } 569 570 image = create_image(name, path, numRegions); 571 if (image == NULL) { 572 FATAL("%s: Failed to allocate image_t object\n", path); 573 status = B_NO_MEMORY; 574 goto err1; 575 } 576 577 status = parse_program_headers(image, imageOffset, pheaderBuffer, 578 eheader.e_phnum, eheader.e_phentsize); 579 if (status < B_OK) 580 goto err2; 581 582 if (!assert_dynamic_loadable(image)) { 583 FATAL("%s: Dynamic segment must be loadable (implementation " 584 "restriction)\n", image->path); 585 status = B_UNSUPPORTED; 586 goto err2; 587 } 588 589 status = map_image(fd, path, image, type == B_APP_IMAGE); 590 if (status < B_OK) { 591 FATAL("%s: Could not map image: %s\n", image->path, strerror(status)); 592 status = B_ERROR; 593 goto err2; 594 } 595 596 if (!parse_dynamic_segment(image)) { 597 FATAL("%s: Troubles handling dynamic section\n", image->path); 598 status = B_BAD_DATA; 599 goto err3; 600 } 601 602 if (eheader.e_entry != 0) 603 image->entry_point = eheader.e_entry + image->regions[0].delta; 604 605 analyze_image_haiku_version_and_abi(fd, image, eheader, sheaderSize, 606 pheaderBuffer, sizeof(pheaderBuffer)); 607 608 // If this is the executable image, we init the search path 609 // subdir, if the compiler version doesn't match ours. 610 if (type == B_APP_IMAGE) { 611 #if __GNUC__ == 2 612 if ((image->abi & B_HAIKU_ABI_MAJOR) == B_HAIKU_ABI_GCC_4) 613 sSearchPathSubDir = "gcc4"; 614 #elif __GNUC__ == 4 615 if ((image->abi & B_HAIKU_ABI_MAJOR) == B_HAIKU_ABI_GCC_2) 616 sSearchPathSubDir = "gcc2"; 617 #endif 618 } 619 620 // init gcc version dependent image flags 621 // symbol resolution strategy 622 if (image->abi == B_HAIKU_ABI_GCC_2_ANCIENT) 623 image->find_undefined_symbol = find_undefined_symbol_beos; 624 625 // init version infos 626 status = init_image_version_infos(image); 627 628 image->type = type; 629 register_image(image, fd, path); 630 image_event(image, IMAGE_EVENT_LOADED); 631 632 _kern_close(fd); 633 634 enqueue_loaded_image(image); 635 636 *_image = image; 637 638 KTRACE("rld: load_container(\"%s\"): done: id: %ld (ABI: %#lx)", name, 639 image->id, image->abi); 640 641 return B_OK; 642 643err3: 644 unmap_image(image); 645err2: 646 delete_image_struct(image); 647err1: 648 _kern_close(fd); 649 650 KTRACE("rld: load_container(\"%s\"): failed: %s", name, 651 strerror(status)); 652 653 return status; 654} 655