1 /* 2 * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de. 4 * Distributed under the terms of the MIT License. 5 * 6 * Copyright 2001, Travis Geiselbrecht. All rights reserved. 7 * Distributed under the terms of the NewOS License. 8 */ 9 10 /*! Contains the ELF loader */ 11 12 13 #include <elf.h> 14 15 #include <OS.h> 16 17 #include <unistd.h> 18 #include <stdlib.h> 19 #include <string.h> 20 #include <stdio.h> 21 #include <ctype.h> 22 23 #include <algorithm> 24 25 #include <AutoDeleter.h> 26 #include <boot/kernel_args.h> 27 #include <debug.h> 28 #include <image_defs.h> 29 #include <kernel.h> 30 #include <kimage.h> 31 #include <syscalls.h> 32 #include <team.h> 33 #include <thread.h> 34 #include <runtime_loader.h> 35 #include <util/AutoLock.h> 36 #include <util/khash.h> 37 #include <vfs.h> 38 #include <vm/vm.h> 39 #include <vm/vm_types.h> 40 #include <vm/VMAddressSpace.h> 41 #include <vm/VMArea.h> 42 43 #include <arch/cpu.h> 44 #include <arch/elf.h> 45 #include <elf_priv.h> 46 #include <boot/elf.h> 47 48 //#define TRACE_ELF 49 #ifdef TRACE_ELF 50 # define TRACE(x) dprintf x 51 #else 52 # define TRACE(x) ; 53 #endif 54 55 56 #define IMAGE_HASH_SIZE 16 57 58 static hash_table *sImagesHash; 59 60 static struct elf_image_info *sKernelImage = NULL; 61 static mutex sImageMutex = MUTEX_INITIALIZER("kimages_lock"); 62 // guards sImagesHash 63 static mutex sImageLoadMutex = MUTEX_INITIALIZER("kimages_load_lock"); 64 // serializes loading/unloading add-ons locking order 65 // sImageLoadMutex -> sImageMutex 66 static bool sInitialized = false; 67 68 69 static elf_sym *elf_find_symbol(struct elf_image_info *image, const char *name, 70 const elf_version_info *version, bool lookupDefault); 71 72 73 /*! Calculates hash for an image using its ID */ 74 static uint32 75 image_hash(void *_image, const void *_key, uint32 range) 76 { 77 struct elf_image_info *image = (struct elf_image_info *)_image; 78 image_id id = (image_id)(addr_t)_key; 79 80 if (image != NULL) 81 return image->id % range; 82 83 return (uint32)id % range; 84 } 85 86 87 /*! Compares an image to a given ID */ 88 static int 89 image_compare(void *_image, const void *_key) 90 { 91 struct elf_image_info *image = (struct elf_image_info *)_image; 92 image_id id = (image_id)(addr_t)_key; 93 94 return id - image->id; 95 } 96 97 98 static void 99 unregister_elf_image(struct elf_image_info *image) 100 { 101 unregister_image(team_get_kernel_team(), image->id); 102 hash_remove(sImagesHash, image); 103 } 104 105 106 static void 107 register_elf_image(struct elf_image_info *image) 108 { 109 image_info imageInfo; 110 111 memset(&imageInfo, 0, sizeof(image_info)); 112 imageInfo.id = image->id; 113 imageInfo.type = B_SYSTEM_IMAGE; 114 strlcpy(imageInfo.name, image->name, sizeof(imageInfo.name)); 115 116 imageInfo.text = (void *)image->text_region.start; 117 imageInfo.text_size = image->text_region.size; 118 imageInfo.data = (void *)image->data_region.start; 119 imageInfo.data_size = image->data_region.size; 120 121 if (image->text_region.id >= 0) { 122 // evaluate the API/ABI version symbols 123 124 // Haiku API version 125 imageInfo.api_version = 0; 126 elf_sym* symbol = elf_find_symbol(image, 127 B_SHARED_OBJECT_HAIKU_VERSION_VARIABLE_NAME, NULL, true); 128 if (symbol != NULL && symbol->st_shndx != SHN_UNDEF 129 && symbol->st_value > 0 130 && symbol->Type() == STT_OBJECT 131 && symbol->st_size >= sizeof(uint32)) { 132 addr_t symbolAddress = symbol->st_value + image->text_region.delta; 133 if (symbolAddress >= image->text_region.start 134 && symbolAddress - image->text_region.start + sizeof(uint32) 135 <= image->text_region.size) { 136 imageInfo.api_version = *(uint32*)symbolAddress; 137 } 138 } 139 140 // Haiku ABI 141 imageInfo.abi = 0; 142 symbol = elf_find_symbol(image, 143 B_SHARED_OBJECT_HAIKU_ABI_VARIABLE_NAME, NULL, true); 144 if (symbol != NULL && symbol->st_shndx != SHN_UNDEF 145 && symbol->st_value > 0 146 && symbol->Type() == STT_OBJECT 147 && symbol->st_size >= sizeof(uint32)) { 148 addr_t symbolAddress = symbol->st_value + image->text_region.delta; 149 if (symbolAddress >= image->text_region.start 150 && symbolAddress - image->text_region.start + sizeof(uint32) 151 <= image->text_region.size) { 152 imageInfo.api_version = *(uint32*)symbolAddress; 153 } 154 } 155 } else { 156 // in-memory image -- use the current values 157 imageInfo.api_version = B_HAIKU_VERSION; 158 imageInfo.abi = B_HAIKU_ABI; 159 } 160 161 image->id = register_image(team_get_kernel_team(), &imageInfo, 162 sizeof(image_info)); 163 hash_insert(sImagesHash, image); 164 } 165 166 167 /*! Note, you must lock the image mutex when you call this function. */ 168 static struct elf_image_info * 169 find_image_at_address(addr_t address) 170 { 171 struct hash_iterator iterator; 172 struct elf_image_info *image; 173 174 #if KDEBUG 175 if (!debug_debugger_running()) 176 ASSERT_LOCKED_MUTEX(&sImageMutex); 177 #endif 178 179 hash_open(sImagesHash, &iterator); 180 181 // get image that may contain the address 182 183 while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) 184 != NULL) { 185 if ((address >= image->text_region.start && address 186 <= (image->text_region.start + image->text_region.size)) 187 || (address >= image->data_region.start 188 && address 189 <= (image->data_region.start + image->data_region.size))) 190 break; 191 } 192 193 hash_close(sImagesHash, &iterator, false); 194 return image; 195 } 196 197 198 static int 199 dump_address_info(int argc, char **argv) 200 { 201 const char *symbol, *imageName; 202 bool exactMatch; 203 addr_t address, baseAddress; 204 205 if (argc < 2) { 206 kprintf("usage: ls <address>\n"); 207 return 0; 208 } 209 210 address = strtoul(argv[1], NULL, 16); 211 212 status_t error; 213 214 if (IS_KERNEL_ADDRESS(address)) { 215 error = elf_debug_lookup_symbol_address(address, &baseAddress, &symbol, 216 &imageName, &exactMatch); 217 } else { 218 error = elf_debug_lookup_user_symbol_address( 219 debug_get_debugged_thread()->team, address, &baseAddress, &symbol, 220 &imageName, &exactMatch); 221 } 222 223 if (error == B_OK) { 224 kprintf("%p = %s + 0x%lx (%s)%s\n", (void*)address, symbol, 225 address - baseAddress, imageName, exactMatch ? "" : " (nearest)"); 226 } else 227 kprintf("There is no image loaded at this address!\n"); 228 229 return 0; 230 } 231 232 233 static struct elf_image_info * 234 find_image(image_id id) 235 { 236 return (elf_image_info *)hash_lookup(sImagesHash, (void *)(addr_t)id); 237 } 238 239 240 static struct elf_image_info * 241 find_image_by_vnode(void *vnode) 242 { 243 struct hash_iterator iterator; 244 struct elf_image_info *image; 245 246 mutex_lock(&sImageMutex); 247 hash_open(sImagesHash, &iterator); 248 249 while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) 250 != NULL) { 251 if (image->vnode == vnode) 252 break; 253 } 254 255 hash_close(sImagesHash, &iterator, false); 256 mutex_unlock(&sImageMutex); 257 258 return image; 259 } 260 261 262 static struct elf_image_info * 263 create_image_struct() 264 { 265 struct elf_image_info *image 266 = (struct elf_image_info *)malloc(sizeof(struct elf_image_info)); 267 if (image == NULL) 268 return NULL; 269 270 memset(image, 0, sizeof(struct elf_image_info)); 271 272 image->text_region.id = -1; 273 image->data_region.id = -1; 274 image->ref_count = 1; 275 276 return image; 277 } 278 279 280 static void 281 delete_elf_image(struct elf_image_info *image) 282 { 283 if (image->text_region.id >= 0) 284 delete_area(image->text_region.id); 285 286 if (image->data_region.id >= 0) 287 delete_area(image->data_region.id); 288 289 if (image->vnode) 290 vfs_put_vnode(image->vnode); 291 292 free(image->versions); 293 free(image->debug_symbols); 294 free((void*)image->debug_string_table); 295 free(image->elf_header); 296 free(image->name); 297 free(image); 298 } 299 300 301 static uint32 302 elf_hash(const char *name) 303 { 304 uint32 hash = 0; 305 uint32 temp; 306 307 while (*name) { 308 hash = (hash << 4) + (uint8)*name++; 309 if ((temp = hash & 0xf0000000) != 0) 310 hash ^= temp >> 24; 311 hash &= ~temp; 312 } 313 return hash; 314 } 315 316 317 static const char * 318 get_symbol_type_string(elf_sym *symbol) 319 { 320 switch (symbol->Type()) { 321 case STT_FUNC: 322 return "func"; 323 case STT_OBJECT: 324 return " obj"; 325 case STT_FILE: 326 return "file"; 327 default: 328 return "----"; 329 } 330 } 331 332 333 static const char * 334 get_symbol_bind_string(elf_sym *symbol) 335 { 336 switch (symbol->Bind()) { 337 case STB_LOCAL: 338 return "loc "; 339 case STB_GLOBAL: 340 return "glob"; 341 case STB_WEAK: 342 return "weak"; 343 default: 344 return "----"; 345 } 346 } 347 348 349 /*! Searches a symbol (pattern) in all kernel images */ 350 static int 351 dump_symbol(int argc, char **argv) 352 { 353 if (argc != 2 || !strcmp(argv[1], "--help")) { 354 kprintf("usage: %s <symbol-name>\n", argv[0]); 355 return 0; 356 } 357 358 struct elf_image_info *image = NULL; 359 struct hash_iterator iterator; 360 const char *pattern = argv[1]; 361 362 void* symbolAddress = NULL; 363 364 hash_open(sImagesHash, &iterator); 365 while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) 366 != NULL) { 367 if (image->num_debug_symbols > 0) { 368 // search extended debug symbol table (contains static symbols) 369 for (uint32 i = 0; i < image->num_debug_symbols; i++) { 370 elf_sym *symbol = &image->debug_symbols[i]; 371 const char *name = image->debug_string_table + symbol->st_name; 372 373 if (symbol->st_value > 0 && strstr(name, pattern) != 0) { 374 symbolAddress 375 = (void*)(symbol->st_value + image->text_region.delta); 376 kprintf("%p %5lu %s:%s\n", symbolAddress, symbol->st_size, 377 image->name, name); 378 } 379 } 380 } else { 381 // search standard symbol lookup table 382 for (uint32 i = 0; i < HASHTABSIZE(image); i++) { 383 for (uint32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF; 384 j = HASHCHAINS(image)[j]) { 385 elf_sym *symbol = &image->syms[j]; 386 const char *name = SYMNAME(image, symbol); 387 388 if (symbol->st_value > 0 && strstr(name, pattern) != 0) { 389 symbolAddress = (void*)(symbol->st_value 390 + image->text_region.delta); 391 kprintf("%p %5lu %s:%s\n", symbolAddress, 392 symbol->st_size, image->name, name); 393 } 394 } 395 } 396 } 397 } 398 hash_close(sImagesHash, &iterator, false); 399 400 if (symbolAddress != NULL) 401 set_debug_variable("_", (addr_t)symbolAddress); 402 403 return 0; 404 } 405 406 407 static int 408 dump_symbols(int argc, char **argv) 409 { 410 struct elf_image_info *image = NULL; 411 struct hash_iterator iterator; 412 uint32 i; 413 414 // if the argument looks like a hex number, treat it as such 415 if (argc > 1) { 416 if (isdigit(argv[1][0])) { 417 addr_t num = strtoul(argv[1], NULL, 0); 418 419 if (IS_KERNEL_ADDRESS(num)) { 420 // find image at address 421 422 hash_open(sImagesHash, &iterator); 423 while ((image = (elf_image_info *)hash_next(sImagesHash, 424 &iterator)) != NULL) { 425 if (image->text_region.start <= num 426 && image->text_region.start + image->text_region.size 427 >= num) 428 break; 429 } 430 hash_close(sImagesHash, &iterator, false); 431 432 if (image == NULL) { 433 kprintf("No image covers %#" B_PRIxADDR " in the kernel!\n", 434 num); 435 } 436 } else { 437 image = (elf_image_info *)hash_lookup(sImagesHash, (void *)num); 438 if (image == NULL) { 439 kprintf("image %#" B_PRIxADDR " doesn't exist in the " 440 "kernel!\n", num); 441 } 442 } 443 } else { 444 // look for image by name 445 hash_open(sImagesHash, &iterator); 446 while ((image = (elf_image_info *)hash_next(sImagesHash, 447 &iterator)) != NULL) { 448 if (!strcmp(image->name, argv[1])) 449 break; 450 } 451 hash_close(sImagesHash, &iterator, false); 452 453 if (image == NULL) 454 kprintf("No image \"%s\" found in kernel!\n", argv[1]); 455 } 456 } else { 457 kprintf("usage: %s image_name/image_id/address_in_image\n", argv[0]); 458 return 0; 459 } 460 461 if (image == NULL) 462 return -1; 463 464 // dump symbols 465 466 kprintf("Symbols of image %" B_PRId32 " \"%s\":\n", image->id, image->name); 467 kprintf("%-*s Type Size Name\n", B_PRINTF_POINTER_WIDTH, "Address"); 468 469 if (image->num_debug_symbols > 0) { 470 // search extended debug symbol table (contains static symbols) 471 for (i = 0; i < image->num_debug_symbols; i++) { 472 elf_sym *symbol = &image->debug_symbols[i]; 473 474 if (symbol->st_value == 0 || symbol->st_size 475 >= image->text_region.size + image->data_region.size) 476 continue; 477 478 kprintf("%0*lx %s/%s %5ld %s\n", B_PRINTF_POINTER_WIDTH, 479 symbol->st_value + image->text_region.delta, 480 get_symbol_type_string(symbol), get_symbol_bind_string(symbol), 481 symbol->st_size, image->debug_string_table + symbol->st_name); 482 } 483 } else { 484 int32 j; 485 486 // search standard symbol lookup table 487 for (i = 0; i < HASHTABSIZE(image); i++) { 488 for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; 489 j = HASHCHAINS(image)[j]) { 490 elf_sym *symbol = &image->syms[j]; 491 492 if (symbol->st_value == 0 || symbol->st_size 493 >= image->text_region.size + image->data_region.size) 494 continue; 495 496 kprintf("%08lx %s/%s %5ld %s\n", 497 symbol->st_value + image->text_region.delta, 498 get_symbol_type_string(symbol), 499 get_symbol_bind_string(symbol), 500 symbol->st_size, SYMNAME(image, symbol)); 501 } 502 } 503 } 504 505 return 0; 506 } 507 508 509 static void 510 dump_elf_region(struct elf_region *region, const char *name) 511 { 512 kprintf(" %s.id %" B_PRId32 "\n", name, region->id); 513 kprintf(" %s.start %#" B_PRIxADDR "\n", name, region->start); 514 kprintf(" %s.size %#" B_PRIxSIZE "\n", name, region->size); 515 kprintf(" %s.delta %ld\n", name, region->delta); 516 } 517 518 519 static void 520 dump_image_info(struct elf_image_info *image) 521 { 522 kprintf("elf_image_info at %p:\n", image); 523 kprintf(" next %p\n", image->next); 524 kprintf(" id %" B_PRId32 "\n", image->id); 525 dump_elf_region(&image->text_region, "text"); 526 dump_elf_region(&image->data_region, "data"); 527 kprintf(" dynamic_section %#" B_PRIxADDR "\n", image->dynamic_section); 528 kprintf(" needed %p\n", image->needed); 529 kprintf(" symhash %p\n", image->symhash); 530 kprintf(" syms %p\n", image->syms); 531 kprintf(" strtab %p\n", image->strtab); 532 kprintf(" rel %p\n", image->rel); 533 kprintf(" rel_len %#x\n", image->rel_len); 534 kprintf(" rela %p\n", image->rela); 535 kprintf(" rela_len %#x\n", image->rela_len); 536 kprintf(" pltrel %p\n", image->pltrel); 537 kprintf(" pltrel_len %#x\n", image->pltrel_len); 538 539 kprintf(" debug_symbols %p (%" B_PRIu32 ")\n", 540 image->debug_symbols, image->num_debug_symbols); 541 } 542 543 544 static int 545 dump_image(int argc, char **argv) 546 { 547 struct hash_iterator iterator; 548 struct elf_image_info *image; 549 550 // if the argument looks like a hex number, treat it as such 551 if (argc > 1) { 552 addr_t num = strtoul(argv[1], NULL, 0); 553 554 if (IS_KERNEL_ADDRESS(num)) { 555 // semi-hack 556 dump_image_info((struct elf_image_info *)num); 557 } else { 558 image = (elf_image_info *)hash_lookup(sImagesHash, (void *)num); 559 if (image == NULL) { 560 kprintf("image %#" B_PRIxADDR " doesn't exist in the kernel!\n", 561 num); 562 } else 563 dump_image_info(image); 564 } 565 return 0; 566 } 567 568 kprintf("loaded kernel images:\n"); 569 570 hash_open(sImagesHash, &iterator); 571 572 while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) 573 != NULL) { 574 kprintf("%p (%" B_PRId32 ") %s\n", image, image->id, image->name); 575 } 576 577 hash_close(sImagesHash, &iterator, false); 578 return 0; 579 } 580 581 582 // Currently unused 583 #if 0 584 static 585 void dump_symbol(struct elf_image_info *image, elf_sym *sym) 586 { 587 588 kprintf("symbol at %p, in image %p\n", sym, image); 589 590 kprintf(" name index %d, '%s'\n", sym->st_name, SYMNAME(image, sym)); 591 kprintf(" st_value 0x%x\n", sym->st_value); 592 kprintf(" st_size %d\n", sym->st_size); 593 kprintf(" st_info 0x%x\n", sym->st_info); 594 kprintf(" st_other 0x%x\n", sym->st_other); 595 kprintf(" st_shndx %d\n", sym->st_shndx); 596 } 597 #endif 598 599 600 static elf_sym * 601 elf_find_symbol(struct elf_image_info *image, const char *name, 602 const elf_version_info *lookupVersion, bool lookupDefault) 603 { 604 if (image->dynamic_section == 0 || HASHTABSIZE(image) == 0) 605 return NULL; 606 607 elf_sym* versionedSymbol = NULL; 608 uint32 versionedSymbolCount = 0; 609 610 uint32 hash = elf_hash(name) % HASHTABSIZE(image); 611 for (uint32 i = HASHBUCKETS(image)[hash]; i != STN_UNDEF; 612 i = HASHCHAINS(image)[i]) { 613 elf_sym* symbol = &image->syms[i]; 614 615 // consider only symbols with the right name and binding 616 if (symbol->st_shndx == SHN_UNDEF 617 || ((symbol->Bind() != STB_GLOBAL) && (symbol->Bind() != STB_WEAK)) 618 || strcmp(SYMNAME(image, symbol), name) != 0) { 619 continue; 620 } 621 622 // check the version 623 624 // Handle the simple cases -- the image doesn't have version 625 // information -- first. 626 if (image->symbol_versions == NULL) { 627 if (lookupVersion == NULL) { 628 // No specific symbol version was requested either, so the 629 // symbol is just fine. 630 return symbol; 631 } 632 633 // A specific version is requested. Since the only possible 634 // dependency is the kernel itself, the add-on was obviously linked 635 // against a newer kernel. 636 dprintf("Kernel add-on requires version support, but the kernel " 637 "is too old.\n"); 638 return NULL; 639 } 640 641 // The image has version information. Let's see what we've got. 642 uint32 versionID = image->symbol_versions[i]; 643 uint32 versionIndex = VER_NDX(versionID); 644 elf_version_info& version = image->versions[versionIndex]; 645 646 // skip local versions 647 if (versionIndex == VER_NDX_LOCAL) 648 continue; 649 650 if (lookupVersion != NULL) { 651 // a specific version is requested 652 653 // compare the versions 654 if (version.hash == lookupVersion->hash 655 && strcmp(version.name, lookupVersion->name) == 0) { 656 // versions match 657 return symbol; 658 } 659 660 // The versions don't match. We're still fine with the 661 // base version, if it is public and we're not looking for 662 // the default version. 663 if ((versionID & VER_NDX_FLAG_HIDDEN) == 0 664 && versionIndex == VER_NDX_GLOBAL 665 && !lookupDefault) { 666 // TODO: Revise the default version case! That's how 667 // FreeBSD implements it, but glibc doesn't handle it 668 // specially. 669 return symbol; 670 } 671 } else { 672 // No specific version requested, but the image has version 673 // information. This can happen in either of these cases: 674 // 675 // * The dependent object was linked against an older version 676 // of the now versioned dependency. 677 // * The symbol is looked up via find_image_symbol() or dlsym(). 678 // 679 // In the first case we return the base version of the symbol 680 // (VER_NDX_GLOBAL or VER_NDX_INITIAL), or, if that doesn't 681 // exist, the unique, non-hidden versioned symbol. 682 // 683 // In the second case we want to return the public default 684 // version of the symbol. The handling is pretty similar to the 685 // first case, with the exception that we treat VER_NDX_INITIAL 686 // as regular version. 687 688 // VER_NDX_GLOBAL is always good, VER_NDX_INITIAL is fine, if 689 // we don't look for the default version. 690 if (versionIndex == VER_NDX_GLOBAL 691 || (!lookupDefault && versionIndex == VER_NDX_INITIAL)) { 692 return symbol; 693 } 694 695 // If not hidden, remember the version -- we'll return it, if 696 // it is the only one. 697 if ((versionID & VER_NDX_FLAG_HIDDEN) == 0) { 698 versionedSymbolCount++; 699 versionedSymbol = symbol; 700 } 701 } 702 } 703 704 return versionedSymbolCount == 1 ? versionedSymbol : NULL; 705 } 706 707 708 static status_t 709 elf_parse_dynamic_section(struct elf_image_info *image) 710 { 711 elf_dyn *d; 712 ssize_t neededOffset = -1; 713 714 TRACE(("top of elf_parse_dynamic_section\n")); 715 716 image->symhash = 0; 717 image->syms = 0; 718 image->strtab = 0; 719 720 d = (elf_dyn *)image->dynamic_section; 721 if (!d) 722 return B_ERROR; 723 724 for (int32 i = 0; d[i].d_tag != DT_NULL; i++) { 725 switch (d[i].d_tag) { 726 case DT_NEEDED: 727 neededOffset = d[i].d_un.d_ptr + image->text_region.delta; 728 break; 729 case DT_HASH: 730 image->symhash = (uint32 *)(d[i].d_un.d_ptr 731 + image->text_region.delta); 732 break; 733 case DT_STRTAB: 734 image->strtab = (char *)(d[i].d_un.d_ptr 735 + image->text_region.delta); 736 break; 737 case DT_SYMTAB: 738 image->syms = (elf_sym *)(d[i].d_un.d_ptr 739 + image->text_region.delta); 740 break; 741 case DT_REL: 742 image->rel = (elf_rel *)(d[i].d_un.d_ptr 743 + image->text_region.delta); 744 break; 745 case DT_RELSZ: 746 image->rel_len = d[i].d_un.d_val; 747 break; 748 case DT_RELA: 749 image->rela = (elf_rela *)(d[i].d_un.d_ptr 750 + image->text_region.delta); 751 break; 752 case DT_RELASZ: 753 image->rela_len = d[i].d_un.d_val; 754 break; 755 case DT_JMPREL: 756 image->pltrel = (elf_rel *)(d[i].d_un.d_ptr 757 + image->text_region.delta); 758 break; 759 case DT_PLTRELSZ: 760 image->pltrel_len = d[i].d_un.d_val; 761 break; 762 case DT_PLTREL: 763 image->pltrel_type = d[i].d_un.d_val; 764 break; 765 case DT_VERSYM: 766 image->symbol_versions = (elf_versym*) 767 (d[i].d_un.d_ptr + image->text_region.delta); 768 break; 769 case DT_VERDEF: 770 image->version_definitions = (elf_verdef*) 771 (d[i].d_un.d_ptr + image->text_region.delta); 772 break; 773 case DT_VERDEFNUM: 774 image->num_version_definitions = d[i].d_un.d_val; 775 break; 776 case DT_VERNEED: 777 image->needed_versions = (elf_verneed*) 778 (d[i].d_un.d_ptr + image->text_region.delta); 779 break; 780 case DT_VERNEEDNUM: 781 image->num_needed_versions = d[i].d_un.d_val; 782 break; 783 case DT_SYMBOLIC: 784 image->symbolic = true; 785 break; 786 case DT_FLAGS: 787 { 788 uint32 flags = d[i].d_un.d_val; 789 if ((flags & DF_SYMBOLIC) != 0) 790 image->symbolic = true; 791 break; 792 } 793 794 default: 795 continue; 796 } 797 } 798 799 // lets make sure we found all the required sections 800 if (!image->symhash || !image->syms || !image->strtab) 801 return B_ERROR; 802 803 TRACE(("needed_offset = %ld\n", neededOffset)); 804 805 if (neededOffset >= 0) 806 image->needed = STRING(image, neededOffset); 807 808 return B_OK; 809 } 810 811 812 static status_t 813 assert_defined_image_version(elf_image_info* dependentImage, 814 elf_image_info* image, const elf_version_info& neededVersion, bool weak) 815 { 816 // If the image doesn't have version definitions, we print a warning and 817 // succeed. Weird, but that's how glibc does it. Not unlikely we'll fail 818 // later when resolving versioned symbols. 819 if (image->version_definitions == NULL) { 820 dprintf("%s: No version information available (required by %s)\n", 821 image->name, dependentImage->name); 822 return B_OK; 823 } 824 825 // iterate through the defined versions to find the given one 826 elf_verdef* definition = image->version_definitions; 827 for (uint32 i = 0; i < image->num_version_definitions; i++) { 828 uint32 versionIndex = VER_NDX(definition->vd_ndx); 829 elf_version_info& info = image->versions[versionIndex]; 830 831 if (neededVersion.hash == info.hash 832 && strcmp(neededVersion.name, info.name) == 0) { 833 return B_OK; 834 } 835 836 definition = (elf_verdef*) 837 ((uint8*)definition + definition->vd_next); 838 } 839 840 // version not found -- fail, if not weak 841 if (!weak) { 842 dprintf("%s: version \"%s\" not found (required by %s)\n", image->name, 843 neededVersion.name, dependentImage->name); 844 return B_MISSING_SYMBOL; 845 } 846 847 return B_OK; 848 } 849 850 851 static status_t 852 init_image_version_infos(elf_image_info* image) 853 { 854 // First find out how many version infos we need -- i.e. get the greatest 855 // version index from the defined and needed versions (they use the same 856 // index namespace). 857 uint32 maxIndex = 0; 858 859 if (image->version_definitions != NULL) { 860 elf_verdef* definition = image->version_definitions; 861 for (uint32 i = 0; i < image->num_version_definitions; i++) { 862 if (definition->vd_version != 1) { 863 dprintf("Unsupported version definition revision: %u\n", 864 definition->vd_version); 865 return B_BAD_VALUE; 866 } 867 868 uint32 versionIndex = VER_NDX(definition->vd_ndx); 869 if (versionIndex > maxIndex) 870 maxIndex = versionIndex; 871 872 definition = (elf_verdef*) 873 ((uint8*)definition + definition->vd_next); 874 } 875 } 876 877 if (image->needed_versions != NULL) { 878 elf_verneed* needed = image->needed_versions; 879 for (uint32 i = 0; i < image->num_needed_versions; i++) { 880 if (needed->vn_version != 1) { 881 dprintf("Unsupported version needed revision: %u\n", 882 needed->vn_version); 883 return B_BAD_VALUE; 884 } 885 886 elf_vernaux* vernaux 887 = (elf_vernaux*)((uint8*)needed + needed->vn_aux); 888 for (uint32 k = 0; k < needed->vn_cnt; k++) { 889 uint32 versionIndex = VER_NDX(vernaux->vna_other); 890 if (versionIndex > maxIndex) 891 maxIndex = versionIndex; 892 893 vernaux = (elf_vernaux*)((uint8*)vernaux + vernaux->vna_next); 894 } 895 896 needed = (elf_verneed*)((uint8*)needed + needed->vn_next); 897 } 898 } 899 900 if (maxIndex == 0) 901 return B_OK; 902 903 // allocate the version infos 904 image->versions 905 = (elf_version_info*)malloc(sizeof(elf_version_info) * (maxIndex + 1)); 906 if (image->versions == NULL) { 907 dprintf("Memory shortage in init_image_version_infos()\n"); 908 return B_NO_MEMORY; 909 } 910 image->num_versions = maxIndex + 1; 911 912 // init the version infos 913 914 // version definitions 915 if (image->version_definitions != NULL) { 916 elf_verdef* definition = image->version_definitions; 917 for (uint32 i = 0; i < image->num_version_definitions; i++) { 918 if (definition->vd_cnt > 0 919 && (definition->vd_flags & VER_FLG_BASE) == 0) { 920 elf_verdaux* verdaux 921 = (elf_verdaux*)((uint8*)definition + definition->vd_aux); 922 923 uint32 versionIndex = VER_NDX(definition->vd_ndx); 924 elf_version_info& info = image->versions[versionIndex]; 925 info.hash = definition->vd_hash; 926 info.name = STRING(image, verdaux->vda_name); 927 info.file_name = NULL; 928 } 929 930 definition = (elf_verdef*) 931 ((uint8*)definition + definition->vd_next); 932 } 933 } 934 935 // needed versions 936 if (image->needed_versions != NULL) { 937 elf_verneed* needed = image->needed_versions; 938 for (uint32 i = 0; i < image->num_needed_versions; i++) { 939 const char* fileName = STRING(image, needed->vn_file); 940 941 elf_vernaux* vernaux 942 = (elf_vernaux*)((uint8*)needed + needed->vn_aux); 943 for (uint32 k = 0; k < needed->vn_cnt; k++) { 944 uint32 versionIndex = VER_NDX(vernaux->vna_other); 945 elf_version_info& info = image->versions[versionIndex]; 946 info.hash = vernaux->vna_hash; 947 info.name = STRING(image, vernaux->vna_name); 948 info.file_name = fileName; 949 950 vernaux = (elf_vernaux*)((uint8*)vernaux + vernaux->vna_next); 951 } 952 953 needed = (elf_verneed*)((uint8*)needed + needed->vn_next); 954 } 955 } 956 957 return B_OK; 958 } 959 960 961 static status_t 962 check_needed_image_versions(elf_image_info* image) 963 { 964 if (image->needed_versions == NULL) 965 return B_OK; 966 967 elf_verneed* needed = image->needed_versions; 968 for (uint32 i = 0; i < image->num_needed_versions; i++) { 969 elf_image_info* dependency = sKernelImage; 970 971 elf_vernaux* vernaux 972 = (elf_vernaux*)((uint8*)needed + needed->vn_aux); 973 for (uint32 k = 0; k < needed->vn_cnt; k++) { 974 uint32 versionIndex = VER_NDX(vernaux->vna_other); 975 elf_version_info& info = image->versions[versionIndex]; 976 977 status_t error = assert_defined_image_version(image, dependency, 978 info, (vernaux->vna_flags & VER_FLG_WEAK) != 0); 979 if (error != B_OK) 980 return error; 981 982 vernaux = (elf_vernaux*)((uint8*)vernaux + vernaux->vna_next); 983 } 984 985 needed = (elf_verneed*)((uint8*)needed + needed->vn_next); 986 } 987 988 return B_OK; 989 } 990 991 992 /*! Resolves the \a symbol by linking against \a sharedImage if necessary. 993 Returns the resolved symbol's address in \a _symbolAddress. 994 */ 995 status_t 996 elf_resolve_symbol(struct elf_image_info *image, elf_sym *symbol, 997 struct elf_image_info *sharedImage, addr_t *_symbolAddress) 998 { 999 // Local symbols references are always resolved to the given symbol. 1000 if (symbol->Bind() == STB_LOCAL) { 1001 *_symbolAddress = symbol->st_value + image->text_region.delta; 1002 return B_OK; 1003 } 1004 1005 // Non-local symbols we try to resolve to the kernel image first. Unless 1006 // the image is linked symbolically, then vice versa. 1007 elf_image_info* firstImage = sharedImage; 1008 elf_image_info* secondImage = image; 1009 if (image->symbolic) 1010 std::swap(firstImage, secondImage); 1011 1012 const char *symbolName = SYMNAME(image, symbol); 1013 1014 // get the version info 1015 const elf_version_info* versionInfo = NULL; 1016 if (image->symbol_versions != NULL) { 1017 uint32 index = symbol - image->syms; 1018 uint32 versionIndex = VER_NDX(image->symbol_versions[index]); 1019 if (versionIndex >= VER_NDX_INITIAL) 1020 versionInfo = image->versions + versionIndex; 1021 } 1022 1023 // find the symbol 1024 elf_image_info* foundImage = firstImage; 1025 elf_sym* foundSymbol = elf_find_symbol(firstImage, symbolName, versionInfo, 1026 false); 1027 if (foundSymbol == NULL 1028 || foundSymbol->Bind() == STB_WEAK) { 1029 // Not found or found a weak definition -- try to resolve in the other 1030 // image. 1031 elf_sym* secondSymbol = elf_find_symbol(secondImage, symbolName, 1032 versionInfo, false); 1033 // If we found a symbol -- take it in case we didn't have a symbol 1034 // before or the new symbol is not weak. 1035 if (secondSymbol != NULL 1036 && (foundSymbol == NULL 1037 || secondSymbol->Bind() != STB_WEAK)) { 1038 foundImage = secondImage; 1039 foundSymbol = secondSymbol; 1040 } 1041 } 1042 1043 if (foundSymbol == NULL) { 1044 // Weak undefined symbols get a value of 0, if unresolved. 1045 if (symbol->Bind() == STB_WEAK) { 1046 *_symbolAddress = 0; 1047 return B_OK; 1048 } 1049 1050 dprintf("\"%s\": could not resolve symbol '%s'\n", image->name, 1051 symbolName); 1052 return B_MISSING_SYMBOL; 1053 } 1054 1055 // make sure they're the same type 1056 if (symbol->Type() != foundSymbol->Type()) { 1057 dprintf("elf_resolve_symbol: found symbol '%s' in image '%s' " 1058 "(requested by image '%s') but wrong type (%d vs. %d)\n", 1059 symbolName, foundImage->name, image->name, 1060 foundSymbol->Type(), symbol->Type()); 1061 return B_MISSING_SYMBOL; 1062 } 1063 1064 *_symbolAddress = foundSymbol->st_value + foundImage->text_region.delta; 1065 return B_OK; 1066 } 1067 1068 1069 /*! Until we have shared library support, just this links against the kernel */ 1070 static int 1071 elf_relocate(struct elf_image_info *image) 1072 { 1073 int status = B_NO_ERROR; 1074 1075 TRACE(("elf_relocate(%p (\"%s\"))\n", image, image->name)); 1076 1077 // deal with the rels first 1078 if (image->rel) { 1079 TRACE(("total %i rel relocs\n", image->rel_len / (int)sizeof(elf_rel))); 1080 1081 status = arch_elf_relocate_rel(image, sKernelImage, image->rel, 1082 image->rel_len); 1083 if (status < B_OK) 1084 return status; 1085 } 1086 1087 if (image->pltrel) { 1088 if (image->pltrel_type == DT_REL) { 1089 TRACE(("total %i plt-relocs\n", 1090 image->pltrel_len / (int)sizeof(elf_rel))); 1091 status = arch_elf_relocate_rel(image, sKernelImage, image->pltrel, 1092 image->pltrel_len); 1093 } else { 1094 TRACE(("total %i plt-relocs\n", 1095 image->pltrel_len / (int)sizeof(elf_rela))); 1096 status = arch_elf_relocate_rela(image, sKernelImage, 1097 (elf_rela *)image->pltrel, image->pltrel_len); 1098 } 1099 if (status < B_OK) 1100 return status; 1101 } 1102 1103 if (image->rela) { 1104 TRACE(("total %i rel relocs\n", 1105 image->rela_len / (int)sizeof(elf_rela))); 1106 1107 status = arch_elf_relocate_rela(image, sKernelImage, image->rela, 1108 image->rela_len); 1109 if (status < B_OK) 1110 return status; 1111 } 1112 1113 return status; 1114 } 1115 1116 1117 static int 1118 verify_eheader(elf_ehdr *elfHeader) 1119 { 1120 if (memcmp(elfHeader->e_ident, ELF_MAGIC, 4) != 0) 1121 return B_NOT_AN_EXECUTABLE; 1122 1123 if (elfHeader->e_ident[4] != ELF_CLASS) 1124 return B_NOT_AN_EXECUTABLE; 1125 1126 if (elfHeader->e_phoff == 0) 1127 return B_NOT_AN_EXECUTABLE; 1128 1129 if (elfHeader->e_phentsize < sizeof(elf_phdr)) 1130 return B_NOT_AN_EXECUTABLE; 1131 1132 return 0; 1133 } 1134 1135 1136 static void 1137 unload_elf_image(struct elf_image_info *image) 1138 { 1139 if (atomic_add(&image->ref_count, -1) > 1) 1140 return; 1141 1142 TRACE(("unload image %" B_PRId32 ", %s\n", image->id, image->name)); 1143 1144 unregister_elf_image(image); 1145 delete_elf_image(image); 1146 } 1147 1148 1149 static status_t 1150 load_elf_symbol_table(int fd, struct elf_image_info *image) 1151 { 1152 elf_ehdr *elfHeader = image->elf_header; 1153 elf_sym *symbolTable = NULL; 1154 elf_shdr *stringHeader = NULL; 1155 uint32 numSymbols = 0; 1156 char *stringTable; 1157 status_t status; 1158 ssize_t length; 1159 int32 i; 1160 1161 // get section headers 1162 1163 ssize_t size = elfHeader->e_shnum * elfHeader->e_shentsize; 1164 elf_shdr *sectionHeaders = (elf_shdr *)malloc(size); 1165 if (sectionHeaders == NULL) { 1166 dprintf("error allocating space for section headers\n"); 1167 return B_NO_MEMORY; 1168 } 1169 1170 length = read_pos(fd, elfHeader->e_shoff, sectionHeaders, size); 1171 if (length < size) { 1172 TRACE(("error reading in program headers\n")); 1173 status = B_ERROR; 1174 goto error1; 1175 } 1176 1177 // find symbol table in section headers 1178 1179 for (i = 0; i < elfHeader->e_shnum; i++) { 1180 if (sectionHeaders[i].sh_type == SHT_SYMTAB) { 1181 stringHeader = §ionHeaders[sectionHeaders[i].sh_link]; 1182 1183 if (stringHeader->sh_type != SHT_STRTAB) { 1184 TRACE(("doesn't link to string table\n")); 1185 status = B_BAD_DATA; 1186 goto error1; 1187 } 1188 1189 // read in symbol table 1190 size = sectionHeaders[i].sh_size; 1191 symbolTable = (elf_sym *)malloc(size); 1192 if (symbolTable == NULL) { 1193 status = B_NO_MEMORY; 1194 goto error1; 1195 } 1196 1197 length 1198 = read_pos(fd, sectionHeaders[i].sh_offset, symbolTable, size); 1199 if (length < size) { 1200 TRACE(("error reading in symbol table\n")); 1201 status = B_ERROR; 1202 goto error2; 1203 } 1204 1205 numSymbols = size / sizeof(elf_sym); 1206 break; 1207 } 1208 } 1209 1210 if (symbolTable == NULL) { 1211 TRACE(("no symbol table\n")); 1212 status = B_BAD_VALUE; 1213 goto error1; 1214 } 1215 1216 // read in string table 1217 1218 stringTable = (char *)malloc(size = stringHeader->sh_size); 1219 if (stringTable == NULL) { 1220 status = B_NO_MEMORY; 1221 goto error2; 1222 } 1223 1224 length = read_pos(fd, stringHeader->sh_offset, stringTable, size); 1225 if (length < size) { 1226 TRACE(("error reading in string table\n")); 1227 status = B_ERROR; 1228 goto error3; 1229 } 1230 1231 TRACE(("loaded %" B_PRId32 " debug symbols\n", numSymbols)); 1232 1233 // insert tables into image 1234 image->debug_symbols = symbolTable; 1235 image->num_debug_symbols = numSymbols; 1236 image->debug_string_table = stringTable; 1237 1238 free(sectionHeaders); 1239 return B_OK; 1240 1241 error3: 1242 free(stringTable); 1243 error2: 1244 free(symbolTable); 1245 error1: 1246 free(sectionHeaders); 1247 1248 return status; 1249 } 1250 1251 1252 static status_t 1253 insert_preloaded_image(preloaded_elf_image *preloadedImage, bool kernel) 1254 { 1255 status_t status; 1256 1257 status = verify_eheader(&preloadedImage->elf_header); 1258 if (status != B_OK) 1259 return status; 1260 1261 elf_image_info *image = create_image_struct(); 1262 if (image == NULL) 1263 return B_NO_MEMORY; 1264 1265 image->name = strdup(preloadedImage->name); 1266 image->dynamic_section = preloadedImage->dynamic_section.start; 1267 1268 image->text_region.id = preloadedImage->text_region.id; 1269 image->text_region.start = preloadedImage->text_region.start; 1270 image->text_region.size = preloadedImage->text_region.size; 1271 image->text_region.delta = preloadedImage->text_region.delta; 1272 image->data_region.id = preloadedImage->data_region.id; 1273 image->data_region.start = preloadedImage->data_region.start; 1274 image->data_region.size = preloadedImage->data_region.size; 1275 image->data_region.delta = preloadedImage->data_region.delta; 1276 1277 status = elf_parse_dynamic_section(image); 1278 if (status != B_OK) 1279 goto error1; 1280 1281 status = init_image_version_infos(image); 1282 if (status != B_OK) 1283 goto error1; 1284 1285 if (!kernel) { 1286 status = check_needed_image_versions(image); 1287 if (status != B_OK) 1288 goto error1; 1289 1290 status = elf_relocate(image); 1291 if (status != B_OK) 1292 goto error1; 1293 } else 1294 sKernelImage = image; 1295 1296 // copy debug symbols to the kernel heap 1297 if (preloadedImage->debug_symbols != NULL) { 1298 int32 debugSymbolsSize = sizeof(elf_sym) 1299 * preloadedImage->num_debug_symbols; 1300 image->debug_symbols = (elf_sym*)malloc(debugSymbolsSize); 1301 if (image->debug_symbols != NULL) { 1302 memcpy(image->debug_symbols, preloadedImage->debug_symbols, 1303 debugSymbolsSize); 1304 } 1305 } 1306 image->num_debug_symbols = preloadedImage->num_debug_symbols; 1307 1308 // copy debug string table to the kernel heap 1309 if (preloadedImage->debug_string_table != NULL) { 1310 image->debug_string_table = (char*)malloc( 1311 preloadedImage->debug_string_table_size); 1312 if (image->debug_string_table != NULL) { 1313 memcpy((void*)image->debug_string_table, 1314 preloadedImage->debug_string_table, 1315 preloadedImage->debug_string_table_size); 1316 } 1317 } 1318 1319 register_elf_image(image); 1320 preloadedImage->id = image->id; 1321 // modules_init() uses this information to get the preloaded images 1322 1323 // we now no longer need to write to the text area anymore 1324 set_area_protection(image->text_region.id, 1325 B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA); 1326 1327 return B_OK; 1328 1329 error1: 1330 delete_elf_image(image); 1331 1332 preloadedImage->id = -1; 1333 1334 return status; 1335 } 1336 1337 1338 // #pragma mark - userland symbol lookup 1339 1340 1341 class UserSymbolLookup { 1342 public: 1343 static UserSymbolLookup& Default() 1344 { 1345 return sLookup; 1346 } 1347 1348 status_t Init(Team* team) 1349 { 1350 // find the runtime loader debug area 1351 VMArea* area; 1352 for (VMAddressSpace::AreaIterator it 1353 = team->address_space->GetAreaIterator(); 1354 (area = it.Next()) != NULL;) { 1355 if (strcmp(area->name, RUNTIME_LOADER_DEBUG_AREA_NAME) == 0) 1356 break; 1357 } 1358 1359 if (area == NULL) 1360 return B_ERROR; 1361 1362 // copy the runtime loader data structure 1363 if (!_Read((runtime_loader_debug_area*)area->Base(), fDebugArea)) 1364 return B_BAD_ADDRESS; 1365 1366 return B_OK; 1367 } 1368 1369 status_t LookupSymbolAddress(addr_t address, addr_t *_baseAddress, 1370 const char **_symbolName, const char **_imageName, bool *_exactMatch) 1371 { 1372 // Note, that this function doesn't find all symbols that we would like 1373 // to find. E.g. static functions do not appear in the symbol table 1374 // as function symbols, but as sections without name and size. The 1375 // .symtab section together with the .strtab section, which apparently 1376 // differ from the tables referred to by the .dynamic section, also 1377 // contain proper names and sizes for those symbols. Therefore, to get 1378 // completely satisfying results, we would need to read those tables 1379 // from the shared object. 1380 1381 // get the image for the address 1382 image_t image; 1383 status_t error = _FindImageAtAddress(address, image); 1384 if (error != B_OK) 1385 return error; 1386 1387 strlcpy(fImageName, image.name, sizeof(fImageName)); 1388 1389 // symbol hash table size 1390 uint32 hashTabSize; 1391 if (!_Read(image.symhash, hashTabSize)) 1392 return B_BAD_ADDRESS; 1393 1394 // remote pointers to hash buckets and chains 1395 const uint32* hashBuckets = image.symhash + 2; 1396 const uint32* hashChains = image.symhash + 2 + hashTabSize; 1397 1398 const elf_region_t& textRegion = image.regions[0]; 1399 1400 // search the image for the symbol 1401 elf_sym symbolFound; 1402 addr_t deltaFound = INT_MAX; 1403 bool exactMatch = false; 1404 1405 // to get rid of the erroneous "uninitialized" warnings 1406 symbolFound.st_name = 0; 1407 symbolFound.st_value = 0; 1408 1409 for (uint32 i = 0; i < hashTabSize; i++) { 1410 uint32 bucket; 1411 if (!_Read(&hashBuckets[i], bucket)) 1412 return B_BAD_ADDRESS; 1413 1414 for (uint32 j = bucket; j != STN_UNDEF; 1415 _Read(&hashChains[j], j) ? 0 : j = STN_UNDEF) { 1416 1417 elf_sym symbol; 1418 if (!_Read(image.syms + j, symbol)) 1419 continue; 1420 1421 // The symbol table contains not only symbols referring to 1422 // functions and data symbols within the shared object, but also 1423 // referenced symbols of other shared objects, as well as 1424 // section and file references. We ignore everything but 1425 // function and data symbols that have an st_value != 0 (0 1426 // seems to be an indication for a symbol defined elsewhere 1427 // -- couldn't verify that in the specs though). 1428 if ((symbol.Type() != STT_FUNC && symbol.Type() != STT_OBJECT) 1429 || symbol.st_value == 0 1430 || symbol.st_value + symbol.st_size + textRegion.delta 1431 > textRegion.vmstart + textRegion.size) { 1432 continue; 1433 } 1434 1435 // skip symbols starting after the given address 1436 addr_t symbolAddress = symbol.st_value + textRegion.delta; 1437 if (symbolAddress > address) 1438 continue; 1439 addr_t symbolDelta = address - symbolAddress; 1440 1441 if (symbolDelta < deltaFound) { 1442 deltaFound = symbolDelta; 1443 symbolFound = symbol; 1444 1445 if (symbolDelta >= 0 && symbolDelta < symbol.st_size) { 1446 // exact match 1447 exactMatch = true; 1448 break; 1449 } 1450 } 1451 } 1452 } 1453 1454 if (_imageName) 1455 *_imageName = fImageName; 1456 1457 if (_symbolName) { 1458 *_symbolName = NULL; 1459 1460 if (deltaFound < INT_MAX) { 1461 if (_ReadString(image, symbolFound.st_name, fSymbolName, 1462 sizeof(fSymbolName))) { 1463 *_symbolName = fSymbolName; 1464 } else { 1465 // we can't get its name, so forget the symbol 1466 deltaFound = INT_MAX; 1467 } 1468 } 1469 } 1470 1471 if (_baseAddress) { 1472 if (deltaFound < INT_MAX) 1473 *_baseAddress = symbolFound.st_value + textRegion.delta; 1474 else 1475 *_baseAddress = textRegion.vmstart; 1476 } 1477 1478 if (_exactMatch) 1479 *_exactMatch = exactMatch; 1480 1481 return B_OK; 1482 } 1483 1484 status_t _FindImageAtAddress(addr_t address, image_t& image) 1485 { 1486 image_queue_t imageQueue; 1487 if (!_Read(fDebugArea.loaded_images, imageQueue)) 1488 return B_BAD_ADDRESS; 1489 1490 image_t* imageAddress = imageQueue.head; 1491 while (imageAddress != NULL) { 1492 if (!_Read(imageAddress, image)) 1493 return B_BAD_ADDRESS; 1494 1495 if (image.regions[0].vmstart <= address 1496 && address < image.regions[0].vmstart + image.regions[0].size) { 1497 return B_OK; 1498 } 1499 1500 imageAddress = image.next; 1501 } 1502 1503 return B_ENTRY_NOT_FOUND; 1504 } 1505 1506 bool _ReadString(const image_t& image, uint32 offset, char* buffer, 1507 size_t bufferSize) 1508 { 1509 const char* address = image.strtab + offset; 1510 1511 if (!IS_USER_ADDRESS(address)) 1512 return false; 1513 1514 if (debug_debugger_running()) { 1515 return debug_strlcpy(B_CURRENT_TEAM, buffer, address, bufferSize) 1516 >= 0; 1517 } 1518 return user_strlcpy(buffer, address, bufferSize) >= 0; 1519 } 1520 1521 template<typename T> bool _Read(const T* address, T& data); 1522 // gcc 2.95.3 doesn't like it defined in-place 1523 1524 private: 1525 runtime_loader_debug_area fDebugArea; 1526 char fImageName[B_OS_NAME_LENGTH]; 1527 char fSymbolName[256]; 1528 static UserSymbolLookup sLookup; 1529 }; 1530 1531 1532 template<typename T> 1533 bool 1534 UserSymbolLookup::_Read(const T* address, T& data) 1535 { 1536 if (!IS_USER_ADDRESS(address)) 1537 return false; 1538 1539 if (debug_debugger_running()) 1540 return debug_memcpy(B_CURRENT_TEAM, &data, address, sizeof(T)) == B_OK; 1541 return user_memcpy(&data, address, sizeof(T)) == B_OK; 1542 } 1543 1544 1545 UserSymbolLookup UserSymbolLookup::sLookup; 1546 // doesn't need construction, but has an Init() method 1547 1548 1549 // #pragma mark - public kernel API 1550 1551 1552 status_t 1553 get_image_symbol(image_id id, const char *name, int32 symbolClass, 1554 void **_symbol) 1555 { 1556 struct elf_image_info *image; 1557 elf_sym *symbol; 1558 status_t status = B_OK; 1559 1560 TRACE(("get_image_symbol(%s)\n", name)); 1561 1562 mutex_lock(&sImageMutex); 1563 1564 image = find_image(id); 1565 if (image == NULL) { 1566 status = B_BAD_IMAGE_ID; 1567 goto done; 1568 } 1569 1570 symbol = elf_find_symbol(image, name, NULL, true); 1571 if (symbol == NULL || symbol->st_shndx == SHN_UNDEF) { 1572 status = B_ENTRY_NOT_FOUND; 1573 goto done; 1574 } 1575 1576 // TODO: support the "symbolClass" parameter! 1577 1578 TRACE(("found: %lx (%lx + %lx)\n", 1579 symbol->st_value + image->text_region.delta, 1580 symbol->st_value, image->text_region.delta)); 1581 1582 *_symbol = (void *)(symbol->st_value + image->text_region.delta); 1583 1584 done: 1585 mutex_unlock(&sImageMutex); 1586 return status; 1587 } 1588 1589 1590 // #pragma mark - kernel private API 1591 1592 1593 /*! Looks up a symbol by address in all images loaded in kernel space. 1594 Note, if you need to call this function outside a debugger, make 1595 sure you fix locking and the way it returns its information, first! 1596 */ 1597 status_t 1598 elf_debug_lookup_symbol_address(addr_t address, addr_t *_baseAddress, 1599 const char **_symbolName, const char **_imageName, bool *_exactMatch) 1600 { 1601 struct elf_image_info *image; 1602 elf_sym *symbolFound = NULL; 1603 const char *symbolName = NULL; 1604 addr_t deltaFound = INT_MAX; 1605 bool exactMatch = false; 1606 status_t status; 1607 1608 TRACE(("looking up %p\n", (void *)address)); 1609 1610 if (!sInitialized) 1611 return B_ERROR; 1612 1613 //mutex_lock(&sImageMutex); 1614 1615 image = find_image_at_address(address); 1616 // get image that may contain the address 1617 1618 if (image != NULL) { 1619 addr_t symbolDelta; 1620 uint32 i; 1621 int32 j; 1622 1623 TRACE((" image %p, base = %p, size = %p\n", image, 1624 (void *)image->text_region.start, (void *)image->text_region.size)); 1625 1626 if (image->debug_symbols != NULL) { 1627 // search extended debug symbol table (contains static symbols) 1628 1629 TRACE((" searching debug symbols...\n")); 1630 1631 for (i = 0; i < image->num_debug_symbols; i++) { 1632 elf_sym *symbol = &image->debug_symbols[i]; 1633 1634 if (symbol->st_value == 0 || symbol->st_size 1635 >= image->text_region.size + image->data_region.size) 1636 continue; 1637 1638 symbolDelta 1639 = address - (symbol->st_value + image->text_region.delta); 1640 if (symbolDelta >= 0 && symbolDelta < symbol->st_size) 1641 exactMatch = true; 1642 1643 if (exactMatch || symbolDelta < deltaFound) { 1644 deltaFound = symbolDelta; 1645 symbolFound = symbol; 1646 symbolName = image->debug_string_table + symbol->st_name; 1647 1648 if (exactMatch) 1649 break; 1650 } 1651 } 1652 } else { 1653 // search standard symbol lookup table 1654 1655 TRACE((" searching standard symbols...\n")); 1656 1657 for (i = 0; i < HASHTABSIZE(image); i++) { 1658 for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; 1659 j = HASHCHAINS(image)[j]) { 1660 elf_sym *symbol = &image->syms[j]; 1661 1662 if (symbol->st_value == 0 1663 || symbol->st_size >= image->text_region.size 1664 + image->data_region.size) 1665 continue; 1666 1667 symbolDelta = address - (long)(symbol->st_value 1668 + image->text_region.delta); 1669 if (symbolDelta >= 0 && symbolDelta < symbol->st_size) 1670 exactMatch = true; 1671 1672 if (exactMatch || symbolDelta < deltaFound) { 1673 deltaFound = symbolDelta; 1674 symbolFound = symbol; 1675 symbolName = SYMNAME(image, symbol); 1676 1677 if (exactMatch) 1678 goto symbol_found; 1679 } 1680 } 1681 } 1682 } 1683 } 1684 symbol_found: 1685 1686 if (symbolFound != NULL) { 1687 if (_symbolName) 1688 *_symbolName = symbolName; 1689 if (_imageName) 1690 *_imageName = image->name; 1691 if (_baseAddress) 1692 *_baseAddress = symbolFound->st_value + image->text_region.delta; 1693 if (_exactMatch) 1694 *_exactMatch = exactMatch; 1695 1696 status = B_OK; 1697 } else if (image != NULL) { 1698 TRACE(("symbol not found!\n")); 1699 1700 if (_symbolName) 1701 *_symbolName = NULL; 1702 if (_imageName) 1703 *_imageName = image->name; 1704 if (_baseAddress) 1705 *_baseAddress = image->text_region.start; 1706 if (_exactMatch) 1707 *_exactMatch = false; 1708 1709 status = B_OK; 1710 } else { 1711 TRACE(("image not found!\n")); 1712 status = B_ENTRY_NOT_FOUND; 1713 } 1714 1715 // Note, theoretically, all information we return back to our caller 1716 // would have to be locked - but since this function is only called 1717 // from the debugger, it's safe to do it this way 1718 1719 //mutex_unlock(&sImageMutex); 1720 1721 return status; 1722 } 1723 1724 1725 /*! Tries to find a matching user symbol for the given address. 1726 Note that the given team's address space must already be in effect. 1727 */ 1728 status_t 1729 elf_debug_lookup_user_symbol_address(Team* team, addr_t address, 1730 addr_t *_baseAddress, const char **_symbolName, const char **_imageName, 1731 bool *_exactMatch) 1732 { 1733 if (team == NULL || team == team_get_kernel_team()) 1734 return B_BAD_VALUE; 1735 1736 UserSymbolLookup& lookup = UserSymbolLookup::Default(); 1737 status_t error = lookup.Init(team); 1738 if (error != B_OK) 1739 return error; 1740 1741 return lookup.LookupSymbolAddress(address, _baseAddress, _symbolName, 1742 _imageName, _exactMatch); 1743 } 1744 1745 1746 /*! Looks up a symbol in all kernel images. Note, this function is thought to 1747 be used in the kernel debugger, and therefore doesn't perform any locking. 1748 */ 1749 addr_t 1750 elf_debug_lookup_symbol(const char* searchName) 1751 { 1752 struct elf_image_info *image = NULL; 1753 struct hash_iterator iterator; 1754 1755 hash_open(sImagesHash, &iterator); 1756 while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) 1757 != NULL) { 1758 if (image->num_debug_symbols > 0) { 1759 // search extended debug symbol table (contains static symbols) 1760 for (uint32 i = 0; i < image->num_debug_symbols; i++) { 1761 elf_sym *symbol = &image->debug_symbols[i]; 1762 const char *name = image->debug_string_table + symbol->st_name; 1763 1764 if (symbol->st_value > 0 && !strcmp(name, searchName)) 1765 return symbol->st_value + image->text_region.delta; 1766 } 1767 } else { 1768 // search standard symbol lookup table 1769 for (uint32 i = 0; i < HASHTABSIZE(image); i++) { 1770 for (uint32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF; 1771 j = HASHCHAINS(image)[j]) { 1772 elf_sym *symbol = &image->syms[j]; 1773 const char *name = SYMNAME(image, symbol); 1774 1775 if (symbol->st_value > 0 && !strcmp(name, searchName)) 1776 return symbol->st_value + image->text_region.delta; 1777 } 1778 } 1779 } 1780 } 1781 hash_close(sImagesHash, &iterator, false); 1782 1783 return 0; 1784 } 1785 1786 1787 status_t 1788 elf_lookup_kernel_symbol(const char* name, elf_symbol_info* info) 1789 { 1790 // find the symbol 1791 elf_sym* foundSymbol = elf_find_symbol(sKernelImage, name, NULL, false); 1792 if (foundSymbol == NULL) 1793 return B_MISSING_SYMBOL; 1794 1795 info->address = foundSymbol->st_value + sKernelImage->text_region.delta; 1796 info->size = foundSymbol->st_size; 1797 return B_OK; 1798 } 1799 1800 1801 status_t 1802 elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry) 1803 { 1804 elf_ehdr elfHeader; 1805 elf_phdr *programHeaders = NULL; 1806 char baseName[B_OS_NAME_LENGTH]; 1807 status_t status; 1808 ssize_t length; 1809 int fd; 1810 int i; 1811 1812 TRACE(("elf_load: entry path '%s', team %p\n", path, team)); 1813 1814 fd = _kern_open(-1, path, O_RDONLY, 0); 1815 if (fd < 0) 1816 return fd; 1817 1818 struct stat st; 1819 status = _kern_read_stat(fd, NULL, false, &st, sizeof(st)); 1820 if (status != B_OK) 1821 return status; 1822 1823 // read and verify the ELF header 1824 1825 length = _kern_read(fd, 0, &elfHeader, sizeof(elfHeader)); 1826 if (length < B_OK) { 1827 status = length; 1828 goto error; 1829 } 1830 1831 if (length != sizeof(elfHeader)) { 1832 // short read 1833 status = B_NOT_AN_EXECUTABLE; 1834 goto error; 1835 } 1836 status = verify_eheader(&elfHeader); 1837 if (status < B_OK) 1838 goto error; 1839 1840 // read program header 1841 1842 programHeaders = (elf_phdr *)malloc( 1843 elfHeader.e_phnum * elfHeader.e_phentsize); 1844 if (programHeaders == NULL) { 1845 dprintf("error allocating space for program headers\n"); 1846 status = B_NO_MEMORY; 1847 goto error; 1848 } 1849 1850 TRACE(("reading in program headers at 0x%lx, length 0x%x\n", 1851 elfHeader.e_phoff, elfHeader.e_phnum * elfHeader.e_phentsize)); 1852 length = _kern_read(fd, elfHeader.e_phoff, programHeaders, 1853 elfHeader.e_phnum * elfHeader.e_phentsize); 1854 if (length < B_OK) { 1855 status = length; 1856 dprintf("error reading in program headers\n"); 1857 goto error; 1858 } 1859 if (length != elfHeader.e_phnum * elfHeader.e_phentsize) { 1860 dprintf("short read while reading in program headers\n"); 1861 status = -1; 1862 goto error; 1863 } 1864 1865 // construct a nice name for the region we have to create below 1866 { 1867 int32 length; 1868 1869 const char *leaf = strrchr(path, '/'); 1870 if (leaf == NULL) 1871 leaf = path; 1872 else 1873 leaf++; 1874 1875 length = strlen(leaf); 1876 if (length > B_OS_NAME_LENGTH - 8) 1877 sprintf(baseName, "...%s", leaf + length + 8 - B_OS_NAME_LENGTH); 1878 else 1879 strcpy(baseName, leaf); 1880 } 1881 1882 // map the program's segments into memory 1883 1884 image_info imageInfo; 1885 memset(&imageInfo, 0, sizeof(image_info)); 1886 1887 for (i = 0; i < elfHeader.e_phnum; i++) { 1888 char regionName[B_OS_NAME_LENGTH]; 1889 char *regionAddress; 1890 area_id id; 1891 1892 if (programHeaders[i].p_type != PT_LOAD) 1893 continue; 1894 1895 regionAddress = (char *)ROUNDDOWN(programHeaders[i].p_vaddr, 1896 B_PAGE_SIZE); 1897 if (programHeaders[i].p_flags & PF_WRITE) { 1898 // rw/data segment 1899 size_t memUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE) 1900 + programHeaders[i].p_memsz; 1901 size_t fileUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE) 1902 + programHeaders[i].p_filesz; 1903 1904 memUpperBound = ROUNDUP(memUpperBound, B_PAGE_SIZE); 1905 fileUpperBound = ROUNDUP(fileUpperBound, B_PAGE_SIZE); 1906 1907 sprintf(regionName, "%s_seg%drw", baseName, i); 1908 1909 id = vm_map_file(team->id, regionName, (void **)®ionAddress, 1910 B_EXACT_ADDRESS, fileUpperBound, 1911 B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP, false, 1912 fd, ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE)); 1913 if (id < B_OK) { 1914 dprintf("error mapping file data: %s!\n", strerror(id)); 1915 status = B_NOT_AN_EXECUTABLE; 1916 goto error; 1917 } 1918 1919 imageInfo.data = regionAddress; 1920 imageInfo.data_size = memUpperBound; 1921 1922 // clean garbage brought by mmap (the region behind the file, 1923 // at least parts of it are the bss and have to be zeroed) 1924 addr_t start = (addr_t)regionAddress 1925 + (programHeaders[i].p_vaddr % B_PAGE_SIZE) 1926 + programHeaders[i].p_filesz; 1927 size_t amount = fileUpperBound 1928 - (programHeaders[i].p_vaddr % B_PAGE_SIZE) 1929 - (programHeaders[i].p_filesz); 1930 memset((void *)start, 0, amount); 1931 1932 // Check if we need extra storage for the bss - we have to do this if 1933 // the above region doesn't already comprise the memory size, too. 1934 1935 if (memUpperBound != fileUpperBound) { 1936 size_t bssSize = memUpperBound - fileUpperBound; 1937 1938 snprintf(regionName, B_OS_NAME_LENGTH, "%s_bss%d", baseName, i); 1939 1940 regionAddress += fileUpperBound; 1941 virtual_address_restrictions virtualRestrictions = {}; 1942 virtualRestrictions.address = regionAddress; 1943 virtualRestrictions.address_specification = B_EXACT_ADDRESS; 1944 physical_address_restrictions physicalRestrictions = {}; 1945 id = create_area_etc(team->id, regionName, bssSize, B_NO_LOCK, 1946 B_READ_AREA | B_WRITE_AREA, 0, &virtualRestrictions, 1947 &physicalRestrictions, (void**)®ionAddress); 1948 if (id < B_OK) { 1949 dprintf("error allocating bss area: %s!\n", strerror(id)); 1950 status = B_NOT_AN_EXECUTABLE; 1951 goto error; 1952 } 1953 } 1954 } else { 1955 // assume ro/text segment 1956 snprintf(regionName, B_OS_NAME_LENGTH, "%s_seg%dro", baseName, i); 1957 1958 size_t segmentSize = ROUNDUP(programHeaders[i].p_memsz 1959 + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE); 1960 1961 id = vm_map_file(team->id, regionName, (void **)®ionAddress, 1962 B_EXACT_ADDRESS, segmentSize, 1963 B_READ_AREA | B_EXECUTE_AREA, REGION_PRIVATE_MAP, false, 1964 fd, ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE)); 1965 if (id < B_OK) { 1966 dprintf("error mapping file text: %s!\n", strerror(id)); 1967 status = B_NOT_AN_EXECUTABLE; 1968 goto error; 1969 } 1970 1971 imageInfo.text = regionAddress; 1972 imageInfo.text_size = segmentSize; 1973 } 1974 } 1975 1976 // register the loaded image 1977 imageInfo.type = B_LIBRARY_IMAGE; 1978 imageInfo.device = st.st_dev; 1979 imageInfo.node = st.st_ino; 1980 strlcpy(imageInfo.name, path, sizeof(imageInfo.name)); 1981 1982 imageInfo.api_version = B_HAIKU_VERSION; 1983 imageInfo.abi = B_HAIKU_ABI; 1984 // TODO: Get the actual values for the shared object. Currently only 1985 // the runtime loader is loaded, so this is good enough for the time 1986 // being. 1987 1988 imageInfo.id = register_image(team, &imageInfo, sizeof(image_info)); 1989 if (imageInfo.id >= 0 && team_get_current_team_id() == team->id) 1990 user_debug_image_created(&imageInfo); 1991 // Don't care, if registering fails. It's not crucial. 1992 1993 TRACE(("elf_load: done!\n")); 1994 1995 *entry = elfHeader.e_entry; 1996 status = B_OK; 1997 1998 error: 1999 free(programHeaders); 2000 _kern_close(fd); 2001 2002 return status; 2003 } 2004 2005 2006 image_id 2007 load_kernel_add_on(const char *path) 2008 { 2009 elf_phdr *programHeaders; 2010 elf_ehdr *elfHeader; 2011 struct elf_image_info *image; 2012 const char *fileName; 2013 void *reservedAddress; 2014 size_t reservedSize; 2015 status_t status; 2016 ssize_t length; 2017 bool textSectionWritable = false; 2018 int executableHeaderCount = 0; 2019 2020 TRACE(("elf_load_kspace: entry path '%s'\n", path)); 2021 2022 int fd = _kern_open(-1, path, O_RDONLY, 0); 2023 if (fd < 0) 2024 return fd; 2025 2026 struct vnode *vnode; 2027 status = vfs_get_vnode_from_fd(fd, true, &vnode); 2028 if (status < B_OK) 2029 goto error0; 2030 2031 // get the file name 2032 fileName = strrchr(path, '/'); 2033 if (fileName == NULL) 2034 fileName = path; 2035 else 2036 fileName++; 2037 2038 // Prevent someone else from trying to load this image 2039 mutex_lock(&sImageLoadMutex); 2040 2041 // make sure it's not loaded already. Search by vnode 2042 image = find_image_by_vnode(vnode); 2043 if (image) { 2044 atomic_add(&image->ref_count, 1); 2045 goto done; 2046 } 2047 2048 elfHeader = (elf_ehdr *)malloc(sizeof(*elfHeader)); 2049 if (!elfHeader) { 2050 status = B_NO_MEMORY; 2051 goto error; 2052 } 2053 2054 length = _kern_read(fd, 0, elfHeader, sizeof(*elfHeader)); 2055 if (length < B_OK) { 2056 status = length; 2057 goto error1; 2058 } 2059 if (length != sizeof(*elfHeader)) { 2060 // short read 2061 status = B_NOT_AN_EXECUTABLE; 2062 goto error1; 2063 } 2064 status = verify_eheader(elfHeader); 2065 if (status < B_OK) 2066 goto error1; 2067 2068 image = create_image_struct(); 2069 if (!image) { 2070 status = B_NO_MEMORY; 2071 goto error1; 2072 } 2073 image->vnode = vnode; 2074 image->elf_header = elfHeader; 2075 image->name = strdup(path); 2076 vnode = NULL; 2077 2078 programHeaders = (elf_phdr *)malloc(elfHeader->e_phnum 2079 * elfHeader->e_phentsize); 2080 if (programHeaders == NULL) { 2081 dprintf("%s: error allocating space for program headers\n", fileName); 2082 status = B_NO_MEMORY; 2083 goto error2; 2084 } 2085 2086 TRACE(("reading in program headers at 0x%lx, length 0x%x\n", 2087 elfHeader->e_phoff, elfHeader->e_phnum * elfHeader->e_phentsize)); 2088 2089 length = _kern_read(fd, elfHeader->e_phoff, programHeaders, 2090 elfHeader->e_phnum * elfHeader->e_phentsize); 2091 if (length < B_OK) { 2092 status = length; 2093 TRACE(("%s: error reading in program headers\n", fileName)); 2094 goto error3; 2095 } 2096 if (length != elfHeader->e_phnum * elfHeader->e_phentsize) { 2097 TRACE(("%s: short read while reading in program headers\n", fileName)); 2098 status = B_ERROR; 2099 goto error3; 2100 } 2101 2102 // determine how much space we need for all loaded segments 2103 2104 reservedSize = 0; 2105 length = 0; 2106 2107 for (int32 i = 0; i < elfHeader->e_phnum; i++) { 2108 size_t end; 2109 2110 if (programHeaders[i].p_type != PT_LOAD) 2111 continue; 2112 2113 length += ROUNDUP(programHeaders[i].p_memsz 2114 + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE); 2115 2116 end = ROUNDUP(programHeaders[i].p_memsz + programHeaders[i].p_vaddr, 2117 B_PAGE_SIZE); 2118 if (end > reservedSize) 2119 reservedSize = end; 2120 2121 if (programHeaders[i].IsExecutable()) 2122 executableHeaderCount++; 2123 } 2124 2125 // Check whether the segments have an unreasonable amount of unused space 2126 // inbetween. 2127 if ((ssize_t)reservedSize > length + 8 * 1024) { 2128 status = B_BAD_DATA; 2129 goto error1; 2130 } 2131 2132 // reserve that space and allocate the areas from that one 2133 if (vm_reserve_address_range(VMAddressSpace::KernelID(), &reservedAddress, 2134 B_ANY_KERNEL_ADDRESS, reservedSize, 0) < B_OK) { 2135 status = B_NO_MEMORY; 2136 goto error3; 2137 } 2138 2139 image->data_region.size = 0; 2140 image->text_region.size = 0; 2141 2142 for (int32 i = 0; i < elfHeader->e_phnum; i++) { 2143 char regionName[B_OS_NAME_LENGTH]; 2144 elf_region *region; 2145 2146 TRACE(("looking at program header %" B_PRId32 "\n", i)); 2147 2148 switch (programHeaders[i].p_type) { 2149 case PT_LOAD: 2150 break; 2151 case PT_DYNAMIC: 2152 image->dynamic_section = programHeaders[i].p_vaddr; 2153 continue; 2154 default: 2155 dprintf("%s: unhandled pheader type %#" B_PRIx32 "\n", fileName, 2156 programHeaders[i].p_type); 2157 continue; 2158 } 2159 2160 // we're here, so it must be a PT_LOAD segment 2161 2162 // Usually add-ons have two PT_LOAD headers: one for .data one or .text. 2163 // x86 and PPC may differ in permission bits for .data's PT_LOAD header 2164 // x86 is usually RW, PPC is RWE 2165 2166 // Some add-ons may have .text and .data concatenated in a single 2167 // PT_LOAD RWE header and we must map that to .text. 2168 if (programHeaders[i].IsReadWrite() 2169 && (!programHeaders[i].IsExecutable() 2170 || executableHeaderCount > 1)) { 2171 // this is the writable segment 2172 if (image->data_region.size != 0) { 2173 // we've already created this segment 2174 continue; 2175 } 2176 region = &image->data_region; 2177 2178 snprintf(regionName, B_OS_NAME_LENGTH, "%s_data", fileName); 2179 } else if (programHeaders[i].IsExecutable()) { 2180 // this is the non-writable segment 2181 if (image->text_region.size != 0) { 2182 // we've already created this segment 2183 continue; 2184 } 2185 region = &image->text_region; 2186 2187 // some programs may have .text and .data concatenated in a 2188 // single PT_LOAD section which is readable/writable/executable 2189 textSectionWritable = programHeaders[i].IsReadWrite(); 2190 snprintf(regionName, B_OS_NAME_LENGTH, "%s_text", fileName); 2191 } else { 2192 dprintf("%s: weird program header flags %#" B_PRIx32 "\n", fileName, 2193 programHeaders[i].p_flags); 2194 continue; 2195 } 2196 2197 region->start = (addr_t)reservedAddress + ROUNDDOWN( 2198 programHeaders[i].p_vaddr, B_PAGE_SIZE); 2199 region->size = ROUNDUP(programHeaders[i].p_memsz 2200 + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE); 2201 region->id = create_area(regionName, (void **)®ion->start, 2202 B_EXACT_ADDRESS, region->size, B_FULL_LOCK, 2203 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); 2204 if (region->id < B_OK) { 2205 dprintf("%s: error allocating area: %s\n", fileName, 2206 strerror(region->id)); 2207 status = B_NOT_AN_EXECUTABLE; 2208 goto error4; 2209 } 2210 region->delta = -ROUNDDOWN(programHeaders[i].p_vaddr, B_PAGE_SIZE); 2211 2212 TRACE(("elf_load_kspace: created area \"%s\" at %p\n", 2213 regionName, (void *)region->start)); 2214 2215 length = _kern_read(fd, programHeaders[i].p_offset, 2216 (void *)(region->start + (programHeaders[i].p_vaddr % B_PAGE_SIZE)), 2217 programHeaders[i].p_filesz); 2218 if (length < B_OK) { 2219 status = length; 2220 dprintf("%s: error reading in segment %" B_PRId32 "\n", fileName, 2221 i); 2222 goto error5; 2223 } 2224 } 2225 2226 image->data_region.delta += image->data_region.start; 2227 image->text_region.delta += image->text_region.start; 2228 2229 // modify the dynamic ptr by the delta of the regions 2230 image->dynamic_section += image->text_region.delta; 2231 2232 status = elf_parse_dynamic_section(image); 2233 if (status < B_OK) 2234 goto error5; 2235 2236 status = init_image_version_infos(image); 2237 if (status != B_OK) 2238 goto error5; 2239 2240 status = check_needed_image_versions(image); 2241 if (status != B_OK) 2242 goto error5; 2243 2244 status = elf_relocate(image); 2245 if (status < B_OK) 2246 goto error5; 2247 2248 // We needed to read in the contents of the "text" area, but 2249 // now we can protect it read-only/execute, unless this is a 2250 // special image with concatenated .text and .data, when it 2251 // will also need write access. 2252 set_area_protection(image->text_region.id, 2253 B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA 2254 | (textSectionWritable ? B_KERNEL_WRITE_AREA : 0)); 2255 2256 // There might be a hole between the two segments, and we don't need to 2257 // reserve this any longer 2258 vm_unreserve_address_range(VMAddressSpace::KernelID(), reservedAddress, 2259 reservedSize); 2260 2261 // ToDo: this should be enabled by kernel settings! 2262 if (1) 2263 load_elf_symbol_table(fd, image); 2264 2265 free(programHeaders); 2266 mutex_lock(&sImageMutex); 2267 register_elf_image(image); 2268 mutex_unlock(&sImageMutex); 2269 2270 done: 2271 _kern_close(fd); 2272 mutex_unlock(&sImageLoadMutex); 2273 2274 return image->id; 2275 2276 error5: 2277 error4: 2278 vm_unreserve_address_range(VMAddressSpace::KernelID(), reservedAddress, 2279 reservedSize); 2280 error3: 2281 free(programHeaders); 2282 error2: 2283 delete_elf_image(image); 2284 elfHeader = NULL; 2285 error1: 2286 free(elfHeader); 2287 error: 2288 mutex_unlock(&sImageLoadMutex); 2289 error0: 2290 dprintf("Could not load kernel add-on \"%s\": %s\n", path, 2291 strerror(status)); 2292 2293 if (vnode) 2294 vfs_put_vnode(vnode); 2295 _kern_close(fd); 2296 2297 return status; 2298 } 2299 2300 2301 status_t 2302 unload_kernel_add_on(image_id id) 2303 { 2304 MutexLocker _(sImageLoadMutex); 2305 MutexLocker _2(sImageMutex); 2306 2307 elf_image_info *image = find_image(id); 2308 if (image == NULL) 2309 return B_BAD_IMAGE_ID; 2310 2311 unload_elf_image(image); 2312 return B_OK; 2313 } 2314 2315 2316 struct elf_image_info* 2317 elf_get_kernel_image() 2318 { 2319 return sKernelImage; 2320 } 2321 2322 2323 status_t 2324 elf_get_image_info_for_address(addr_t address, image_info* info) 2325 { 2326 MutexLocker _(sImageMutex); 2327 struct elf_image_info* elfInfo = find_image_at_address(address); 2328 if (elfInfo == NULL) 2329 return B_ENTRY_NOT_FOUND; 2330 2331 info->id = elfInfo->id; 2332 info->type = B_SYSTEM_IMAGE; 2333 info->sequence = 0; 2334 info->init_order = 0; 2335 info->init_routine = NULL; 2336 info->term_routine = NULL; 2337 info->device = -1; 2338 info->node = -1; 2339 // TODO: We could actually fill device/node in. 2340 strlcpy(info->name, elfInfo->name, sizeof(info->name)); 2341 info->text = (void*)elfInfo->text_region.start; 2342 info->data = (void*)elfInfo->data_region.start; 2343 info->text_size = elfInfo->text_region.size; 2344 info->data_size = elfInfo->data_region.size; 2345 2346 return B_OK; 2347 } 2348 2349 2350 image_id 2351 elf_create_memory_image(const char* imageName, addr_t text, size_t textSize, 2352 addr_t data, size_t dataSize) 2353 { 2354 // allocate the image 2355 elf_image_info* image = create_image_struct(); 2356 if (image == NULL) 2357 return B_NO_MEMORY; 2358 MemoryDeleter imageDeleter(image); 2359 2360 // allocate symbol and string tables -- we allocate an empty symbol table, 2361 // so that elf_debug_lookup_symbol_address() won't try the dynamic symbol 2362 // table, which we don't have. 2363 elf_sym* symbolTable = (elf_sym*)malloc(0); 2364 char* stringTable = (char*)malloc(1); 2365 MemoryDeleter symbolTableDeleter(symbolTable); 2366 MemoryDeleter stringTableDeleter(stringTable); 2367 if (symbolTable == NULL || stringTable == NULL) 2368 return B_NO_MEMORY; 2369 2370 // the string table always contains the empty string 2371 stringTable[0] = '\0'; 2372 2373 image->debug_symbols = symbolTable; 2374 image->num_debug_symbols = 0; 2375 image->debug_string_table = stringTable; 2376 2377 // dup image name 2378 image->name = strdup(imageName); 2379 if (image->name == NULL) 2380 return B_NO_MEMORY; 2381 2382 // data and text region 2383 image->text_region.id = -1; 2384 image->text_region.start = text; 2385 image->text_region.size = textSize; 2386 image->text_region.delta = 0; 2387 2388 image->data_region.id = -1; 2389 image->data_region.start = data; 2390 image->data_region.size = dataSize; 2391 image->data_region.delta = 0; 2392 2393 mutex_lock(&sImageMutex); 2394 register_elf_image(image); 2395 image_id imageID = image->id; 2396 mutex_unlock(&sImageMutex); 2397 2398 // keep the allocated memory 2399 imageDeleter.Detach(); 2400 symbolTableDeleter.Detach(); 2401 stringTableDeleter.Detach(); 2402 2403 return imageID; 2404 } 2405 2406 2407 status_t 2408 elf_add_memory_image_symbol(image_id id, const char* name, addr_t address, 2409 size_t size, int32 type) 2410 { 2411 MutexLocker _(sImageMutex); 2412 2413 // get the image 2414 struct elf_image_info* image = find_image(id); 2415 if (image == NULL) 2416 return B_ENTRY_NOT_FOUND; 2417 2418 // get the current string table size 2419 size_t stringTableSize = 1; 2420 if (image->num_debug_symbols > 0) { 2421 for (int32 i = image->num_debug_symbols - 1; i >= 0; i--) { 2422 int32 nameIndex = image->debug_symbols[i].st_name; 2423 if (nameIndex != 0) { 2424 stringTableSize = nameIndex 2425 + strlen(image->debug_string_table + nameIndex) + 1; 2426 break; 2427 } 2428 } 2429 } 2430 2431 // enter the name in the string table 2432 char* stringTable = (char*)image->debug_string_table; 2433 size_t stringIndex = 0; 2434 if (name != NULL) { 2435 size_t nameSize = strlen(name) + 1; 2436 stringIndex = stringTableSize; 2437 stringTableSize += nameSize; 2438 stringTable = (char*)realloc((char*)image->debug_string_table, 2439 stringTableSize); 2440 if (stringTable == NULL) 2441 return B_NO_MEMORY; 2442 image->debug_string_table = stringTable; 2443 memcpy(stringTable + stringIndex, name, nameSize); 2444 } 2445 2446 // resize the symbol table 2447 int32 symbolCount = image->num_debug_symbols + 1; 2448 elf_sym* symbolTable = (elf_sym*)realloc( 2449 (elf_sym*)image->debug_symbols, sizeof(elf_sym) * symbolCount); 2450 if (symbolTable == NULL) 2451 return B_NO_MEMORY; 2452 image->debug_symbols = symbolTable; 2453 2454 // enter the symbol 2455 elf_sym& symbol = symbolTable[symbolCount - 1]; 2456 symbol.SetInfo(STB_GLOBAL, 2457 type == B_SYMBOL_TYPE_DATA ? STT_OBJECT : STT_FUNC); 2458 symbol.st_name = stringIndex; 2459 symbol.st_value = address; 2460 symbol.st_size = size; 2461 symbol.st_other = 0; 2462 symbol.st_shndx = 0; 2463 image->num_debug_symbols++; 2464 2465 return B_OK; 2466 } 2467 2468 2469 status_t 2470 elf_init(kernel_args *args) 2471 { 2472 struct preloaded_image *image; 2473 2474 image_init(); 2475 2476 sImagesHash = hash_init(IMAGE_HASH_SIZE, 0, image_compare, image_hash); 2477 if (sImagesHash == NULL) 2478 return B_NO_MEMORY; 2479 2480 // Build a image structure for the kernel, which has already been loaded. 2481 // The preloaded_images were already prepared by the VM. 2482 image = args->kernel_image; 2483 if (insert_preloaded_image(static_cast<preloaded_elf_image *>(image), 2484 true) < B_OK) 2485 panic("could not create kernel image.\n"); 2486 2487 // Build image structures for all preloaded images. 2488 for (image = args->preloaded_images; image != NULL; image = image->next) 2489 insert_preloaded_image(static_cast<preloaded_elf_image *>(image), 2490 false); 2491 2492 add_debugger_command("ls", &dump_address_info, 2493 "lookup symbol for a particular address"); 2494 add_debugger_command("symbols", &dump_symbols, "dump symbols for image"); 2495 add_debugger_command("symbol", &dump_symbol, "search symbol in images"); 2496 add_debugger_command_etc("image", &dump_image, "dump image info", 2497 "Prints info about the specified image.\n" 2498 " <image> - pointer to the semaphore structure, or ID\n" 2499 " of the image to print info for.\n", 0); 2500 2501 sInitialized = true; 2502 return B_OK; 2503 } 2504 2505 2506 // #pragma mark - 2507 2508 2509 /*! Reads the symbol and string table for the kernel image with the given ID. 2510 \a _symbolCount and \a _stringTableSize are both in- and output parameters. 2511 When called they call the size of the buffers given by \a symbolTable and 2512 \a stringTable respectively. When the function returns successfully, they 2513 will contain the actual sizes (which can be greater than the original ones). 2514 The function will copy as much as possible into the buffers. For only 2515 getting the required buffer sizes, it can be invoked with \c NULL buffers. 2516 On success \a _imageDelta will contain the offset to be added to the symbol 2517 values in the table to get the actual symbol addresses. 2518 */ 2519 status_t 2520 _user_read_kernel_image_symbols(image_id id, elf_sym* symbolTable, 2521 int32* _symbolCount, char* stringTable, size_t* _stringTableSize, 2522 addr_t* _imageDelta) 2523 { 2524 // check params 2525 if (_symbolCount == NULL || _stringTableSize == NULL) 2526 return B_BAD_VALUE; 2527 if (!IS_USER_ADDRESS(_symbolCount) || !IS_USER_ADDRESS(_stringTableSize) 2528 || (_imageDelta != NULL && !IS_USER_ADDRESS(_imageDelta)) 2529 || (symbolTable != NULL && !IS_USER_ADDRESS(symbolTable)) 2530 || (stringTable != NULL && !IS_USER_ADDRESS(stringTable))) { 2531 return B_BAD_ADDRESS; 2532 } 2533 2534 // get buffer sizes 2535 int32 maxSymbolCount; 2536 size_t maxStringTableSize; 2537 if (user_memcpy(&maxSymbolCount, _symbolCount, sizeof(maxSymbolCount)) 2538 != B_OK 2539 || user_memcpy(&maxStringTableSize, _stringTableSize, 2540 sizeof(maxStringTableSize)) != B_OK) { 2541 return B_BAD_ADDRESS; 2542 } 2543 2544 // find the image 2545 MutexLocker _(sImageMutex); 2546 struct elf_image_info* image = find_image(id); 2547 if (image == NULL) 2548 return B_ENTRY_NOT_FOUND; 2549 2550 // get the tables and infos 2551 addr_t imageDelta = image->text_region.delta; 2552 const elf_sym* symbols; 2553 int32 symbolCount; 2554 const char* strings; 2555 2556 if (image->debug_symbols != NULL) { 2557 symbols = image->debug_symbols; 2558 symbolCount = image->num_debug_symbols; 2559 strings = image->debug_string_table; 2560 } else { 2561 symbols = image->syms; 2562 symbolCount = image->symhash[1]; 2563 strings = image->strtab; 2564 } 2565 2566 // The string table size isn't stored in the elf_image_info structure. Find 2567 // out by iterating through all symbols. 2568 size_t stringTableSize = 0; 2569 for (int32 i = 0; i < symbolCount; i++) { 2570 size_t index = symbols[i].st_name; 2571 if (index > stringTableSize) 2572 stringTableSize = index; 2573 } 2574 stringTableSize += strlen(strings + stringTableSize) + 1; 2575 // add size of the last string 2576 2577 // copy symbol table 2578 int32 symbolsToCopy = min_c(symbolCount, maxSymbolCount); 2579 if (symbolTable != NULL && symbolsToCopy > 0) { 2580 if (user_memcpy(symbolTable, symbols, sizeof(elf_sym) * symbolsToCopy) 2581 != B_OK) { 2582 return B_BAD_ADDRESS; 2583 } 2584 } 2585 2586 // copy string table 2587 size_t stringsToCopy = min_c(stringTableSize, maxStringTableSize); 2588 if (stringTable != NULL && stringsToCopy > 0) { 2589 if (user_memcpy(stringTable, strings, stringsToCopy) 2590 != B_OK) { 2591 return B_BAD_ADDRESS; 2592 } 2593 } 2594 2595 // copy sizes 2596 if (user_memcpy(_symbolCount, &symbolCount, sizeof(symbolCount)) != B_OK 2597 || user_memcpy(_stringTableSize, &stringTableSize, 2598 sizeof(stringTableSize)) != B_OK 2599 || (_imageDelta != NULL && user_memcpy(_imageDelta, &imageDelta, 2600 sizeof(imageDelta)) != B_OK)) { 2601 return B_BAD_ADDRESS; 2602 } 2603 2604 return B_OK; 2605 } 2606