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