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