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