1 /*
2 * Copyright 2018, Jérôme Duval, jerome.duval@gmail.com.
3 * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
4 * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de.
5 * Distributed under the terms of the MIT License.
6 *
7 * Copyright 2001, Travis Geiselbrecht. All rights reserved.
8 * Distributed under the terms of the NewOS License.
9 */
10
11 /*! Contains the ELF loader */
12
13
14 #include <elf.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 <BytePointer.h>
28 #include <commpage.h>
29 #include <driver_settings.h>
30 #include <boot/kernel_args.h>
31 #include <debug.h>
32 #include <image_defs.h>
33 #include <kernel.h>
34 #include <kimage.h>
35 #include <syscalls.h>
36 #include <team.h>
37 #include <thread.h>
38 #include <runtime_loader.h>
39 #include <util/AutoLock.h>
40 #include <StackOrHeapArray.h>
41 #include <vfs.h>
42 #include <vm/vm.h>
43 #include <vm/vm_types.h>
44 #include <vm/VMAddressSpace.h>
45 #include <vm/VMArea.h>
46
47 #include <arch/cpu.h>
48 #include <arch/elf.h>
49 #include <elf_priv.h>
50 #include <boot/elf.h>
51
52 //#define TRACE_ELF
53 #ifdef TRACE_ELF
54 # define TRACE(x) dprintf x
55 #else
56 # define TRACE(x) ;
57 #endif
58
59
60 namespace {
61
62 #define IMAGE_HASH_SIZE 16
63
64 struct ImageHashDefinition {
65 typedef struct elf_image_info ValueType;
66 typedef image_id KeyType;
67
Hash__anona0a4a1630111::ImageHashDefinition68 size_t Hash(ValueType* entry) const
69 { return HashKey(entry->id); }
GetLink__anona0a4a1630111::ImageHashDefinition70 ValueType*& GetLink(ValueType* entry) const
71 { return entry->next; }
72
HashKey__anona0a4a1630111::ImageHashDefinition73 size_t HashKey(KeyType key) const
74 {
75 return (size_t)key;
76 }
77
Compare__anona0a4a1630111::ImageHashDefinition78 bool Compare(KeyType key, ValueType* entry) const
79 {
80 return key == entry->id;
81 }
82 };
83
84 typedef BOpenHashTable<ImageHashDefinition> ImageHash;
85
86 } // namespace
87
88
89 #ifndef ELF32_COMPAT
90
91 static ImageHash *sImagesHash;
92
93 static struct elf_image_info *sKernelImage = NULL;
94 static mutex sImageMutex = MUTEX_INITIALIZER("kimages_lock");
95 // guards sImagesHash
96 static mutex sImageLoadMutex = MUTEX_INITIALIZER("kimages_load_lock");
97 // serializes loading/unloading add-ons locking order
98 // sImageLoadMutex -> sImageMutex
99 static bool sLoadElfSymbols = false;
100 static bool sInitialized = false;
101
102
103 static elf_sym *elf_find_symbol(struct elf_image_info *image, const char *name,
104 const elf_version_info *version, bool lookupDefault);
105
106
107 static void
unregister_elf_image(struct elf_image_info * image)108 unregister_elf_image(struct elf_image_info *image)
109 {
110 unregister_image(team_get_kernel_team(), image->id);
111 sImagesHash->Remove(image);
112 }
113
114
115 static void
register_elf_image(struct elf_image_info * image)116 register_elf_image(struct elf_image_info *image)
117 {
118 extended_image_info imageInfo;
119
120 memset(&imageInfo, 0, sizeof(imageInfo));
121 imageInfo.basic_info.id = image->id;
122 imageInfo.basic_info.type = B_SYSTEM_IMAGE;
123 strlcpy(imageInfo.basic_info.name, image->name,
124 sizeof(imageInfo.basic_info.name));
125
126 imageInfo.basic_info.text = (void *)image->text_region.start;
127 imageInfo.basic_info.text_size = image->text_region.size;
128 imageInfo.basic_info.data = (void *)image->data_region.start;
129 imageInfo.basic_info.data_size = image->data_region.size;
130
131 if (image->text_region.id >= 0) {
132 // evaluate the API/ABI version symbols
133
134 // Haiku API version
135 imageInfo.basic_info.api_version = 0;
136 elf_sym* symbol = elf_find_symbol(image,
137 B_SHARED_OBJECT_HAIKU_VERSION_VARIABLE_NAME, NULL, true);
138 if (symbol != NULL && symbol->st_shndx != SHN_UNDEF
139 && symbol->st_value > 0
140 && symbol->Type() == STT_OBJECT
141 && symbol->st_size >= sizeof(uint32)) {
142 addr_t symbolAddress = symbol->st_value + image->text_region.delta;
143 if (symbolAddress >= image->text_region.start
144 && symbolAddress - image->text_region.start + sizeof(uint32)
145 <= image->text_region.size) {
146 imageInfo.basic_info.api_version = *(uint32*)symbolAddress;
147 }
148 }
149
150 // Haiku ABI
151 imageInfo.basic_info.abi = 0;
152 symbol = elf_find_symbol(image,
153 B_SHARED_OBJECT_HAIKU_ABI_VARIABLE_NAME, NULL, true);
154 if (symbol != NULL && symbol->st_shndx != SHN_UNDEF
155 && symbol->st_value > 0
156 && symbol->Type() == STT_OBJECT
157 && symbol->st_size >= sizeof(uint32)) {
158 addr_t symbolAddress = symbol->st_value + image->text_region.delta;
159 if (symbolAddress >= image->text_region.start
160 && symbolAddress - image->text_region.start + sizeof(uint32)
161 <= image->text_region.size) {
162 imageInfo.basic_info.api_version = *(uint32*)symbolAddress;
163 }
164 }
165 } else {
166 // in-memory image -- use the current values
167 imageInfo.basic_info.api_version = B_HAIKU_VERSION;
168 imageInfo.basic_info.abi = B_HAIKU_ABI;
169 }
170
171 image->id = register_image(team_get_kernel_team(), &imageInfo,
172 sizeof(imageInfo));
173 sImagesHash->Insert(image);
174 }
175
176
177 /*! Note, you must lock the image mutex when you call this function. */
178 static struct elf_image_info *
find_image_at_address(addr_t address)179 find_image_at_address(addr_t address)
180 {
181 #if KDEBUG
182 if (!debug_debugger_running())
183 ASSERT_LOCKED_MUTEX(&sImageMutex);
184 #endif
185
186 ImageHash::Iterator iterator(sImagesHash);
187
188 // get image that may contain the address
189
190 while (iterator.HasNext()) {
191 struct elf_image_info* image = iterator.Next();
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 return image;
198 }
199
200 return NULL;
201 }
202
203
204 static int
dump_address_info(int argc,char ** argv)205 dump_address_info(int argc, char **argv)
206 {
207 const char *symbol, *imageName;
208 bool exactMatch;
209 addr_t address, baseAddress;
210
211 if (argc < 2) {
212 kprintf("usage: ls <address>\n");
213 return 0;
214 }
215
216 address = strtoul(argv[1], NULL, 16);
217
218 status_t error;
219
220 if (IS_KERNEL_ADDRESS(address)) {
221 error = elf_debug_lookup_symbol_address(address, &baseAddress, &symbol,
222 &imageName, &exactMatch);
223 } else {
224 error = elf_debug_lookup_user_symbol_address(
225 debug_get_debugged_thread()->team, address, &baseAddress, &symbol,
226 &imageName, &exactMatch);
227 }
228
229 if (error == B_OK) {
230 kprintf("%p = %s + 0x%lx (%s)%s\n", (void*)address, symbol,
231 address - baseAddress, imageName, exactMatch ? "" : " (nearest)");
232 } else
233 kprintf("There is no image loaded at this address!\n");
234
235 return 0;
236 }
237
238
239 static struct elf_image_info *
find_image(image_id id)240 find_image(image_id id)
241 {
242 return sImagesHash->Lookup(id);
243 }
244
245
246 static struct elf_image_info *
find_image_by_vnode(void * vnode)247 find_image_by_vnode(void *vnode)
248 {
249 MutexLocker locker(sImageMutex);
250
251 ImageHash::Iterator iterator(sImagesHash);
252 while (iterator.HasNext()) {
253 struct elf_image_info* image = iterator.Next();
254 if (image->vnode == vnode)
255 return image;
256 }
257
258 return NULL;
259 }
260
261
262 #endif // ELF32_COMPAT
263
264
265 static struct elf_image_info *
create_image_struct()266 create_image_struct()
267 {
268 struct elf_image_info *image
269 = (struct elf_image_info *)malloc(sizeof(struct elf_image_info));
270 if (image == NULL)
271 return NULL;
272
273 memset(image, 0, sizeof(struct elf_image_info));
274
275 image->text_region.id = -1;
276 image->data_region.id = -1;
277 image->ref_count = 1;
278
279 return image;
280 }
281
282
283 static void
delete_elf_image(struct elf_image_info * image)284 delete_elf_image(struct elf_image_info *image)
285 {
286 if (image->text_region.id >= 0)
287 delete_area(image->text_region.id);
288
289 if (image->data_region.id >= 0)
290 delete_area(image->data_region.id);
291
292 if (image->vnode)
293 vfs_put_vnode(image->vnode);
294
295 free(image->versions);
296 free(image->debug_symbols);
297 free((void*)image->debug_string_table);
298 free(image->elf_header);
299 free(image->name);
300 free(image);
301 }
302
303
304 static const char *
get_symbol_type_string(elf_sym * symbol)305 get_symbol_type_string(elf_sym *symbol)
306 {
307 switch (symbol->Type()) {
308 case STT_FUNC:
309 return "func";
310 case STT_OBJECT:
311 return " obj";
312 case STT_FILE:
313 return "file";
314 default:
315 return "----";
316 }
317 }
318
319
320 static const char *
get_symbol_bind_string(elf_sym * symbol)321 get_symbol_bind_string(elf_sym *symbol)
322 {
323 switch (symbol->Bind()) {
324 case STB_LOCAL:
325 return "loc ";
326 case STB_GLOBAL:
327 return "glob";
328 case STB_WEAK:
329 return "weak";
330 default:
331 return "----";
332 }
333 }
334
335
336 #ifndef ELF32_COMPAT
337
338
339 /*! Searches a symbol (pattern) in all kernel images */
340 static int
dump_symbol(int argc,char ** argv)341 dump_symbol(int argc, char **argv)
342 {
343 if (argc != 2 || !strcmp(argv[1], "--help")) {
344 kprintf("usage: %s <symbol-name>\n", argv[0]);
345 return 0;
346 }
347
348 struct elf_image_info *image = NULL;
349 const char *pattern = argv[1];
350
351 void* symbolAddress = NULL;
352
353 ImageHash::Iterator iterator(sImagesHash);
354 while (iterator.HasNext()) {
355 image = iterator.Next();
356 if (image->num_debug_symbols > 0) {
357 // search extended debug symbol table (contains static symbols)
358 for (uint32 i = 0; i < image->num_debug_symbols; i++) {
359 elf_sym *symbol = &image->debug_symbols[i];
360 const char *name = image->debug_string_table + symbol->st_name;
361
362 if (symbol->st_value > 0 && strstr(name, pattern) != 0) {
363 symbolAddress
364 = (void*)(symbol->st_value + image->text_region.delta);
365 kprintf("%p %5lu %s:%s\n", symbolAddress,
366 (long unsigned int)(symbol->st_size),
367 image->name, name);
368 }
369 }
370 } else {
371 // search standard symbol lookup table
372 for (uint32 i = 0; i < HASHTABSIZE(image); i++) {
373 for (uint32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
374 j = HASHCHAINS(image)[j]) {
375 elf_sym *symbol = &image->syms[j];
376 const char *name = SYMNAME(image, symbol);
377
378 if (symbol->st_value > 0 && strstr(name, pattern) != 0) {
379 symbolAddress = (void*)(symbol->st_value
380 + image->text_region.delta);
381 kprintf("%p %5lu %s:%s\n", symbolAddress,
382 (long unsigned int)(symbol->st_size),
383 image->name, name);
384 }
385 }
386 }
387 }
388 }
389
390 if (symbolAddress != NULL)
391 set_debug_variable("_", (addr_t)symbolAddress);
392
393 return 0;
394 }
395
396
397 static int
dump_symbols(int argc,char ** argv)398 dump_symbols(int argc, char **argv)
399 {
400 struct elf_image_info *image = NULL;
401 uint32 i;
402
403 // if the argument looks like a hex number, treat it as such
404 if (argc > 1) {
405 if (isdigit(argv[1][0])) {
406 addr_t num = strtoul(argv[1], NULL, 0);
407
408 if (IS_KERNEL_ADDRESS(num)) {
409 // find image at address
410
411 ImageHash::Iterator iterator(sImagesHash);
412 while (iterator.HasNext()) {
413 elf_image_info* current = iterator.Next();
414 if (current->text_region.start <= num
415 && current->text_region.start
416 + current->text_region.size >= num) {
417 image = current;
418 break;
419 }
420 }
421
422 if (image == NULL) {
423 kprintf("No image covers %#" B_PRIxADDR " in the kernel!\n",
424 num);
425 }
426 } else {
427 image = sImagesHash->Lookup(num);
428 if (image == NULL) {
429 kprintf("image %#" B_PRIxADDR " doesn't exist in the "
430 "kernel!\n", num);
431 }
432 }
433 } else {
434 // look for image by name
435 ImageHash::Iterator iterator(sImagesHash);
436 while (iterator.HasNext()) {
437 elf_image_info* current = iterator.Next();
438 if (!strcmp(current->name, argv[1])) {
439 image = current;
440 break;
441 }
442 }
443
444 if (image == NULL)
445 kprintf("No image \"%s\" found in kernel!\n", argv[1]);
446 }
447 } else {
448 kprintf("usage: %s image_name/image_id/address_in_image\n", argv[0]);
449 return 0;
450 }
451
452 if (image == NULL)
453 return -1;
454
455 // dump symbols
456
457 kprintf("Symbols of image %" B_PRId32 " \"%s\":\n", image->id, image->name);
458 kprintf("%-*s Type Size Name\n", B_PRINTF_POINTER_WIDTH, "Address");
459
460 if (image->num_debug_symbols > 0) {
461 // search extended debug symbol table (contains static symbols)
462 for (i = 0; i < image->num_debug_symbols; i++) {
463 elf_sym *symbol = &image->debug_symbols[i];
464
465 if (symbol->st_value == 0 || symbol->st_size
466 >= image->text_region.size + image->data_region.size)
467 continue;
468
469 kprintf("%0*lx %s/%s %5ld %s\n", B_PRINTF_POINTER_WIDTH,
470 symbol->st_value + image->text_region.delta,
471 get_symbol_type_string(symbol), get_symbol_bind_string(symbol),
472 (long unsigned int)(symbol->st_size),
473 image->debug_string_table + symbol->st_name);
474 }
475 } else {
476 int32 j;
477
478 // search standard symbol lookup table
479 for (i = 0; i < HASHTABSIZE(image); i++) {
480 for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
481 j = HASHCHAINS(image)[j]) {
482 elf_sym *symbol = &image->syms[j];
483
484 if (symbol->st_value == 0 || symbol->st_size
485 >= image->text_region.size + image->data_region.size)
486 continue;
487
488 kprintf("%08lx %s/%s %5ld %s\n",
489 symbol->st_value + image->text_region.delta,
490 get_symbol_type_string(symbol),
491 get_symbol_bind_string(symbol),
492 (long unsigned int)(symbol->st_size),
493 SYMNAME(image, symbol));
494 }
495 }
496 }
497
498 return 0;
499 }
500
501
502 static void
dump_elf_region(struct elf_region * region,const char * name)503 dump_elf_region(struct elf_region *region, const char *name)
504 {
505 kprintf(" %s.id %" B_PRId32 "\n", name, region->id);
506 kprintf(" %s.start %#" B_PRIxADDR "\n", name, region->start);
507 kprintf(" %s.size %#" B_PRIxSIZE "\n", name, region->size);
508 kprintf(" %s.delta %ld\n", name, region->delta);
509 }
510
511
512 static void
dump_image_info(struct elf_image_info * image)513 dump_image_info(struct elf_image_info *image)
514 {
515 kprintf("elf_image_info at %p:\n", image);
516 kprintf(" next %p\n", image->next);
517 kprintf(" id %" B_PRId32 "\n", image->id);
518 dump_elf_region(&image->text_region, "text");
519 dump_elf_region(&image->data_region, "data");
520 kprintf(" dynamic_section %#" B_PRIxADDR "\n", image->dynamic_section);
521 kprintf(" needed %p\n", image->needed);
522 kprintf(" symhash %p\n", image->symhash);
523 kprintf(" syms %p\n", image->syms);
524 kprintf(" strtab %p\n", image->strtab);
525 kprintf(" rel %p\n", image->rel);
526 kprintf(" rel_len %#x\n", image->rel_len);
527 kprintf(" rela %p\n", image->rela);
528 kprintf(" rela_len %#x\n", image->rela_len);
529 kprintf(" pltrel %p\n", image->pltrel);
530 kprintf(" pltrel_len %#x\n", image->pltrel_len);
531
532 kprintf(" debug_symbols %p (%" B_PRIu32 ")\n",
533 image->debug_symbols, image->num_debug_symbols);
534 }
535
536
537 static int
dump_image(int argc,char ** argv)538 dump_image(int argc, char **argv)
539 {
540 struct elf_image_info *image;
541
542 // if the argument looks like a hex number, treat it as such
543 if (argc > 1) {
544 addr_t num = strtoul(argv[1], NULL, 0);
545
546 if (IS_KERNEL_ADDRESS(num)) {
547 // semi-hack
548 dump_image_info((struct elf_image_info *)num);
549 } else {
550 image = sImagesHash->Lookup(num);
551 if (image == NULL) {
552 kprintf("image %#" B_PRIxADDR " doesn't exist in the kernel!\n",
553 num);
554 } else
555 dump_image_info(image);
556 }
557 return 0;
558 }
559
560 kprintf("loaded kernel images:\n");
561
562 ImageHash::Iterator iterator(sImagesHash);
563
564 while (iterator.HasNext()) {
565 image = iterator.Next();
566 kprintf("%p (%" B_PRId32 ") %s\n", image, image->id, image->name);
567 }
568
569 return 0;
570 }
571
572
573 // Currently unused
574 /*static
575 void dump_symbol(struct elf_image_info *image, elf_sym *sym)
576 {
577
578 kprintf("symbol at %p, in image %p\n", sym, image);
579
580 kprintf(" name index %d, '%s'\n", sym->st_name, SYMNAME(image, sym));
581 kprintf(" st_value 0x%x\n", sym->st_value);
582 kprintf(" st_size %d\n", sym->st_size);
583 kprintf(" st_info 0x%x\n", sym->st_info);
584 kprintf(" st_other 0x%x\n", sym->st_other);
585 kprintf(" st_shndx %d\n", sym->st_shndx);
586 }
587 */
588
589
590 #endif // ELF32_COMPAT
591
592
593 static uint32
elf_hash(const char * _name)594 elf_hash(const char* _name)
595 {
596 const uint8* name = (const uint8*)_name;
597
598 uint32 h = 0;
599 while (*name != '\0') {
600 h = (h << 4) + *name++;
601 h ^= (h >> 24) & 0xf0;
602 }
603 return (h & 0x0fffffff);
604 }
605
606
607 static elf_sym *
elf_find_symbol(struct elf_image_info * image,const char * name,const elf_version_info * lookupVersion,bool lookupDefault)608 elf_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
715 static status_t
elf_parse_dynamic_section(struct elf_image_info * image)716 elf_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
819 #ifndef ELF32_COMPAT
820
821
822 static status_t
assert_defined_image_version(elf_image_info * dependentImage,elf_image_info * image,const elf_version_info & neededVersion,bool weak)823 assert_defined_image_version(elf_image_info* dependentImage,
824 elf_image_info* image, const elf_version_info& neededVersion, bool weak)
825 {
826 // If the image doesn't have version definitions, we print a warning and
827 // succeed. Weird, but that's how glibc does it. Not unlikely we'll fail
828 // later when resolving versioned symbols.
829 if (image->version_definitions == NULL) {
830 dprintf("%s: No version information available (required by %s)\n",
831 image->name, dependentImage->name);
832 return B_OK;
833 }
834
835 // iterate through the defined versions to find the given one
836 BytePointer<elf_verdef> definition(image->version_definitions);
837 for (uint32 i = 0; i < image->num_version_definitions; i++) {
838 uint32 versionIndex = VER_NDX(definition->vd_ndx);
839 elf_version_info& info = image->versions[versionIndex];
840
841 if (neededVersion.hash == info.hash
842 && strcmp(neededVersion.name, info.name) == 0) {
843 return B_OK;
844 }
845
846 definition += definition->vd_next;
847 }
848
849 // version not found -- fail, if not weak
850 if (!weak) {
851 dprintf("%s: version \"%s\" not found (required by %s)\n", image->name,
852 neededVersion.name, dependentImage->name);
853 return B_MISSING_SYMBOL;
854 }
855
856 return B_OK;
857 }
858
859
860 static status_t
init_image_version_infos(elf_image_info * image)861 init_image_version_infos(elf_image_info* image)
862 {
863 // First find out how many version infos we need -- i.e. get the greatest
864 // version index from the defined and needed versions (they use the same
865 // index namespace).
866 uint32 maxIndex = 0;
867
868 if (image->version_definitions != NULL) {
869 BytePointer<elf_verdef> definition(image->version_definitions);
870 for (uint32 i = 0; i < image->num_version_definitions; i++) {
871 if (definition->vd_version != 1) {
872 dprintf("Unsupported version definition revision: %u\n",
873 definition->vd_version);
874 return B_BAD_VALUE;
875 }
876
877 uint32 versionIndex = VER_NDX(definition->vd_ndx);
878 if (versionIndex > maxIndex)
879 maxIndex = versionIndex;
880
881 definition += definition->vd_next;
882 }
883 }
884
885 if (image->needed_versions != NULL) {
886 BytePointer<elf_verneed> needed(image->needed_versions);
887 for (uint32 i = 0; i < image->num_needed_versions; i++) {
888 if (needed->vn_version != 1) {
889 dprintf("Unsupported version needed revision: %u\n",
890 needed->vn_version);
891 return B_BAD_VALUE;
892 }
893
894 BytePointer<elf_vernaux> vernaux(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 += vernaux->vna_next;
901 }
902
903 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 BytePointer<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 BytePointer<elf_verdaux> verdaux(definition
928 + 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 += definition->vd_next;
938 }
939 }
940
941 // needed versions
942 if (image->needed_versions != NULL) {
943 BytePointer<elf_verneed> needed(image->needed_versions);
944 for (uint32 i = 0; i < image->num_needed_versions; i++) {
945 const char* fileName = STRING(image, needed->vn_file);
946
947 BytePointer<elf_vernaux> vernaux(needed + needed->vn_aux);
948 for (uint32 k = 0; k < needed->vn_cnt; k++) {
949 uint32 versionIndex = VER_NDX(vernaux->vna_other);
950 elf_version_info& info = image->versions[versionIndex];
951 info.hash = vernaux->vna_hash;
952 info.name = STRING(image, vernaux->vna_name);
953 info.file_name = fileName;
954
955 vernaux += vernaux->vna_next;
956 }
957
958 needed += needed->vn_next;
959 }
960 }
961
962 return B_OK;
963 }
964
965
966 static status_t
check_needed_image_versions(elf_image_info * image)967 check_needed_image_versions(elf_image_info* image)
968 {
969 if (image->needed_versions == NULL)
970 return B_OK;
971
972 BytePointer<elf_verneed> needed(image->needed_versions);
973 for (uint32 i = 0; i < image->num_needed_versions; i++) {
974 elf_image_info* dependency = sKernelImage;
975
976 BytePointer<elf_vernaux> vernaux(needed + needed->vn_aux);
977 for (uint32 k = 0; k < needed->vn_cnt; k++) {
978 uint32 versionIndex = VER_NDX(vernaux->vna_other);
979 elf_version_info& info = image->versions[versionIndex];
980
981 status_t error = assert_defined_image_version(image, dependency,
982 info, (vernaux->vna_flags & VER_FLG_WEAK) != 0);
983 if (error != B_OK)
984 return error;
985
986 vernaux += vernaux->vna_next;
987 }
988
989 needed += needed->vn_next;
990 }
991
992 return B_OK;
993 }
994
995
996 #endif // ELF32_COMPAT
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 */
1002 status_t
elf_resolve_symbol(struct elf_image_info * image,elf_sym * symbol,struct elf_image_info * sharedImage,elf_addr * _symbolAddress)1003 elf_resolve_symbol(struct elf_image_info *image, elf_sym *symbol,
1004 struct elf_image_info *sharedImage, elf_addr *_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 */
1077 static int
elf_relocate(struct elf_image_info * image,struct elf_image_info * resolveImage)1078 elf_relocate(struct elf_image_info* image, struct elf_image_info* resolveImage)
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, resolveImage, 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, resolveImage, 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, resolveImage,
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, resolveImage, image->rela,
1115 image->rela_len);
1116 if (status < B_OK)
1117 return status;
1118 }
1119
1120 return status;
1121 }
1122
1123
1124 static int
verify_eheader(elf_ehdr * elfHeader)1125 verify_eheader(elf_ehdr *elfHeader)
1126 {
1127 if (memcmp(elfHeader->e_ident, ELFMAG, 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
1143 #ifndef ELF32_COMPAT
1144
1145
1146 static void
unload_elf_image(struct elf_image_info * image)1147 unload_elf_image(struct elf_image_info *image)
1148 {
1149 if (atomic_add(&image->ref_count, -1) > 1)
1150 return;
1151
1152 TRACE(("unload image %" B_PRId32 ", %s\n", image->id, image->name));
1153
1154 unregister_elf_image(image);
1155 delete_elf_image(image);
1156 }
1157
1158
1159 static status_t
load_elf_symbol_table(int fd,struct elf_image_info * image)1160 load_elf_symbol_table(int fd, struct elf_image_info *image)
1161 {
1162 elf_ehdr *elfHeader = image->elf_header;
1163 elf_sym *symbolTable = NULL;
1164 elf_shdr *stringHeader = NULL;
1165 uint32 numSymbols = 0;
1166 char *stringTable;
1167 status_t status;
1168 ssize_t length;
1169 int32 i;
1170
1171 // get section headers
1172
1173 ssize_t size = elfHeader->e_shnum * elfHeader->e_shentsize;
1174 elf_shdr *sectionHeaders = (elf_shdr *)malloc(size);
1175 if (sectionHeaders == NULL) {
1176 dprintf("error allocating space for section headers\n");
1177 return B_NO_MEMORY;
1178 }
1179
1180 length = read_pos(fd, elfHeader->e_shoff, sectionHeaders, size);
1181 if (length < size) {
1182 TRACE(("error reading in program headers\n"));
1183 status = B_ERROR;
1184 goto error1;
1185 }
1186
1187 // find symbol table in section headers
1188
1189 for (i = 0; i < elfHeader->e_shnum; i++) {
1190 if (sectionHeaders[i].sh_type == SHT_SYMTAB) {
1191 stringHeader = §ionHeaders[sectionHeaders[i].sh_link];
1192
1193 if (stringHeader->sh_type != SHT_STRTAB) {
1194 TRACE(("doesn't link to string table\n"));
1195 status = B_BAD_DATA;
1196 goto error1;
1197 }
1198
1199 // read in symbol table
1200 size = sectionHeaders[i].sh_size;
1201 symbolTable = (elf_sym *)malloc(size);
1202 if (symbolTable == NULL) {
1203 status = B_NO_MEMORY;
1204 goto error1;
1205 }
1206
1207 length
1208 = read_pos(fd, sectionHeaders[i].sh_offset, symbolTable, size);
1209 if (length < size) {
1210 TRACE(("error reading in symbol table\n"));
1211 status = B_ERROR;
1212 goto error2;
1213 }
1214
1215 numSymbols = size / sizeof(elf_sym);
1216 break;
1217 }
1218 }
1219
1220 if (symbolTable == NULL) {
1221 TRACE(("no symbol table\n"));
1222 status = B_BAD_VALUE;
1223 goto error1;
1224 }
1225
1226 // read in string table
1227
1228 stringTable = (char *)malloc(size = stringHeader->sh_size);
1229 if (stringTable == NULL) {
1230 status = B_NO_MEMORY;
1231 goto error2;
1232 }
1233
1234 length = read_pos(fd, stringHeader->sh_offset, stringTable, size);
1235 if (length < size) {
1236 TRACE(("error reading in string table\n"));
1237 status = B_ERROR;
1238 goto error3;
1239 }
1240
1241 TRACE(("loaded %" B_PRId32 " debug symbols\n", numSymbols));
1242
1243 // insert tables into image
1244 image->debug_symbols = symbolTable;
1245 image->num_debug_symbols = numSymbols;
1246 image->debug_string_table = stringTable;
1247
1248 free(sectionHeaders);
1249 return B_OK;
1250
1251 error3:
1252 free(stringTable);
1253 error2:
1254 free(symbolTable);
1255 error1:
1256 free(sectionHeaders);
1257
1258 return status;
1259 }
1260
1261
1262 static status_t
insert_preloaded_image(preloaded_elf_image * preloadedImage,bool kernel)1263 insert_preloaded_image(preloaded_elf_image *preloadedImage, bool kernel)
1264 {
1265 status_t status;
1266
1267 status = verify_eheader(&preloadedImage->elf_header);
1268 if (status != B_OK)
1269 return status;
1270
1271 elf_image_info *image = create_image_struct();
1272 if (image == NULL)
1273 return B_NO_MEMORY;
1274
1275 image->name = strdup(preloadedImage->name);
1276 image->dynamic_section = preloadedImage->dynamic_section.start;
1277
1278 image->text_region.id = preloadedImage->text_region.id;
1279 image->text_region.start = preloadedImage->text_region.start;
1280 image->text_region.size = preloadedImage->text_region.size;
1281 image->text_region.delta = preloadedImage->text_region.delta;
1282 image->data_region.id = preloadedImage->data_region.id;
1283 image->data_region.start = preloadedImage->data_region.start;
1284 image->data_region.size = preloadedImage->data_region.size;
1285 image->data_region.delta = preloadedImage->data_region.delta;
1286
1287 status = elf_parse_dynamic_section(image);
1288 if (status != B_OK)
1289 goto error1;
1290
1291 status = init_image_version_infos(image);
1292 if (status != B_OK)
1293 goto error1;
1294
1295 if (!kernel) {
1296 status = check_needed_image_versions(image);
1297 if (status != B_OK)
1298 goto error1;
1299
1300 status = elf_relocate(image, sKernelImage);
1301 if (status != B_OK)
1302 goto error1;
1303 } else
1304 sKernelImage = image;
1305
1306 // copy debug symbols to the kernel heap
1307 if (preloadedImage->debug_symbols != NULL) {
1308 int32 debugSymbolsSize = sizeof(elf_sym)
1309 * preloadedImage->num_debug_symbols;
1310 image->debug_symbols = (elf_sym*)malloc(debugSymbolsSize);
1311 if (image->debug_symbols != NULL) {
1312 memcpy(image->debug_symbols, preloadedImage->debug_symbols,
1313 debugSymbolsSize);
1314 }
1315 }
1316 image->num_debug_symbols = preloadedImage->num_debug_symbols;
1317
1318 // copy debug string table to the kernel heap
1319 if (preloadedImage->debug_string_table != NULL) {
1320 image->debug_string_table = (char*)malloc(
1321 preloadedImage->debug_string_table_size);
1322 if (image->debug_string_table != NULL) {
1323 memcpy((void*)image->debug_string_table,
1324 preloadedImage->debug_string_table,
1325 preloadedImage->debug_string_table_size);
1326 }
1327 }
1328
1329 register_elf_image(image);
1330 preloadedImage->id = image->id;
1331 // modules_init() uses this information to get the preloaded images
1332
1333 // we now no longer need to write to the text area anymore
1334 set_area_protection(image->text_region.id,
1335 B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA);
1336
1337 return B_OK;
1338
1339 error1:
1340 delete_elf_image(image);
1341
1342 preloadedImage->id = -1;
1343
1344 return status;
1345 }
1346
1347
1348 // #pragma mark - userland symbol lookup
1349
1350
1351 class UserSymbolLookup {
1352 public:
Default()1353 static UserSymbolLookup& Default()
1354 {
1355 return sLookup;
1356 }
1357
Init(Team * team)1358 status_t Init(Team* team)
1359 {
1360 // find the runtime loader debug area
1361 VMArea* area;
1362 for (VMAddressSpace::AreaIterator it
1363 = team->address_space->GetAreaIterator();
1364 (area = it.Next()) != NULL;) {
1365 if (strcmp(area->name, RUNTIME_LOADER_DEBUG_AREA_NAME) == 0)
1366 break;
1367 }
1368
1369 if (area == NULL)
1370 return B_ERROR;
1371
1372 // copy the runtime loader data structure
1373 if (!_Read((runtime_loader_debug_area*)area->Base(), fDebugArea))
1374 return B_BAD_ADDRESS;
1375
1376 fTeam = team;
1377 return B_OK;
1378 }
1379
LookupSymbolAddress(addr_t address,addr_t * _baseAddress,const char ** _symbolName,const char ** _imageName,bool * _exactMatch)1380 status_t LookupSymbolAddress(addr_t address, addr_t *_baseAddress,
1381 const char **_symbolName, const char **_imageName, bool *_exactMatch)
1382 {
1383 // Note, that this function doesn't find all symbols that we would like
1384 // to find. E.g. static functions do not appear in the symbol table
1385 // as function symbols, but as sections without name and size. The
1386 // .symtab section together with the .strtab section, which apparently
1387 // differ from the tables referred to by the .dynamic section, also
1388 // contain proper names and sizes for those symbols. Therefore, to get
1389 // completely satisfying results, we would need to read those tables
1390 // from the shared object.
1391
1392 // get the image for the address
1393 image_t image;
1394 status_t error = _FindImageAtAddress(address, image);
1395 if (error != B_OK) {
1396 // commpage requires special treatment since kernel stores symbol
1397 // information
1398 addr_t commPageAddress = (addr_t)fTeam->commpage_address;
1399 if (address >= commPageAddress
1400 && address < commPageAddress + COMMPAGE_SIZE) {
1401 if (*_imageName)
1402 *_imageName = "commpage";
1403 address -= (addr_t)commPageAddress;
1404 error = elf_debug_lookup_symbol_address(address, _baseAddress,
1405 _symbolName, NULL, _exactMatch);
1406 if (_baseAddress)
1407 *_baseAddress += (addr_t)fTeam->commpage_address;
1408 }
1409 return error;
1410 }
1411
1412 strlcpy(fImageName, image.name, sizeof(fImageName));
1413
1414 // symbol hash table size
1415 uint32 hashTabSize;
1416 if (!_Read(image.symhash, hashTabSize))
1417 return B_BAD_ADDRESS;
1418
1419 // remote pointers to hash buckets and chains
1420 const uint32* hashBuckets = image.symhash + 2;
1421 const uint32* hashChains = image.symhash + 2 + hashTabSize;
1422
1423 const elf_region_t& textRegion = image.regions[0];
1424
1425 // search the image for the symbol
1426 elf_sym symbolFound;
1427 addr_t deltaFound = INT_MAX;
1428 bool exactMatch = false;
1429
1430 // to get rid of the erroneous "uninitialized" warnings
1431 symbolFound.st_name = 0;
1432 symbolFound.st_value = 0;
1433
1434 for (uint32 i = 0; i < hashTabSize; i++) {
1435 uint32 bucket;
1436 if (!_Read(&hashBuckets[i], bucket))
1437 return B_BAD_ADDRESS;
1438
1439 for (uint32 j = bucket; j != STN_UNDEF;
1440 _Read(&hashChains[j], j) ? 0 : j = STN_UNDEF) {
1441
1442 elf_sym symbol;
1443 if (!_Read(image.syms + j, symbol))
1444 continue;
1445
1446 // The symbol table contains not only symbols referring to
1447 // functions and data symbols within the shared object, but also
1448 // referenced symbols of other shared objects, as well as
1449 // section and file references. We ignore everything but
1450 // function and data symbols that have an st_value != 0 (0
1451 // seems to be an indication for a symbol defined elsewhere
1452 // -- couldn't verify that in the specs though).
1453 if ((symbol.Type() != STT_FUNC && symbol.Type() != STT_OBJECT)
1454 || symbol.st_value == 0
1455 || symbol.st_value + symbol.st_size + textRegion.delta
1456 > textRegion.vmstart + textRegion.size) {
1457 continue;
1458 }
1459
1460 // skip symbols starting after the given address
1461 addr_t symbolAddress = symbol.st_value + textRegion.delta;
1462 if (symbolAddress > address)
1463 continue;
1464 addr_t symbolDelta = address - symbolAddress;
1465
1466 if (symbolDelta < deltaFound) {
1467 deltaFound = symbolDelta;
1468 symbolFound = symbol;
1469
1470 if (symbolDelta >= 0 && symbolDelta < symbol.st_size) {
1471 // exact match
1472 exactMatch = true;
1473 break;
1474 }
1475 }
1476 }
1477 }
1478
1479 if (_imageName)
1480 *_imageName = fImageName;
1481
1482 if (_symbolName) {
1483 *_symbolName = NULL;
1484
1485 if (deltaFound < INT_MAX) {
1486 if (_ReadString(image, symbolFound.st_name, fSymbolName,
1487 sizeof(fSymbolName))) {
1488 *_symbolName = fSymbolName;
1489 } else {
1490 // we can't get its name, so forget the symbol
1491 deltaFound = INT_MAX;
1492 }
1493 }
1494 }
1495
1496 if (_baseAddress) {
1497 if (deltaFound < INT_MAX)
1498 *_baseAddress = symbolFound.st_value + textRegion.delta;
1499 else
1500 *_baseAddress = textRegion.vmstart;
1501 }
1502
1503 if (_exactMatch)
1504 *_exactMatch = exactMatch;
1505
1506 return B_OK;
1507 }
1508
_FindImageAtAddress(addr_t address,image_t & image)1509 status_t _FindImageAtAddress(addr_t address, image_t& image)
1510 {
1511 image_queue_t imageQueue;
1512 if (!_Read(fDebugArea.loaded_images, imageQueue))
1513 return B_BAD_ADDRESS;
1514
1515 image_t* imageAddress = imageQueue.head;
1516 while (imageAddress != NULL) {
1517 if (!_Read(imageAddress, image))
1518 return B_BAD_ADDRESS;
1519
1520 if (image.regions[0].vmstart <= address
1521 && address < image.regions[0].vmstart + image.regions[0].size) {
1522 return B_OK;
1523 }
1524
1525 imageAddress = image.next;
1526 }
1527
1528 return B_ENTRY_NOT_FOUND;
1529 }
1530
_ReadString(const image_t & image,uint32 offset,char * buffer,size_t bufferSize)1531 bool _ReadString(const image_t& image, uint32 offset, char* buffer,
1532 size_t bufferSize)
1533 {
1534 const char* address = image.strtab + offset;
1535
1536 if (!IS_USER_ADDRESS(address))
1537 return false;
1538
1539 if (debug_debugger_running()) {
1540 return debug_strlcpy(B_CURRENT_TEAM, buffer, address, bufferSize)
1541 >= 0;
1542 }
1543 return user_strlcpy(buffer, address, bufferSize) >= 0;
1544 }
1545
1546 template<typename T> bool _Read(const T* address, T& data);
1547 // gcc 2.95.3 doesn't like it defined in-place
1548
1549 private:
1550 Team* fTeam;
1551 runtime_loader_debug_area fDebugArea;
1552 char fImageName[B_OS_NAME_LENGTH];
1553 char fSymbolName[256];
1554 static UserSymbolLookup sLookup;
1555 };
1556
1557
1558 template<typename T>
1559 bool
_Read(const T * address,T & data)1560 UserSymbolLookup::_Read(const T* address, T& data)
1561 {
1562 if (!IS_USER_ADDRESS(address))
1563 return false;
1564
1565 if (debug_debugger_running())
1566 return debug_memcpy(B_CURRENT_TEAM, &data, address, sizeof(T)) == B_OK;
1567 return user_memcpy(&data, address, sizeof(T)) == B_OK;
1568 }
1569
1570
1571 UserSymbolLookup UserSymbolLookup::sLookup;
1572 // doesn't need construction, but has an Init() method
1573
1574
1575 // #pragma mark - public kernel API
1576
1577
1578 status_t
get_image_symbol(image_id id,const char * name,int32 symbolClass,void ** _symbol)1579 get_image_symbol(image_id id, const char *name, int32 symbolClass,
1580 void **_symbol)
1581 {
1582 struct elf_image_info *image;
1583 elf_sym *symbol;
1584 status_t status = B_OK;
1585
1586 TRACE(("get_image_symbol(%s)\n", name));
1587
1588 mutex_lock(&sImageMutex);
1589
1590 image = find_image(id);
1591 if (image == NULL) {
1592 status = B_BAD_IMAGE_ID;
1593 goto done;
1594 }
1595
1596 symbol = elf_find_symbol(image, name, NULL, true);
1597 if (symbol == NULL || symbol->st_shndx == SHN_UNDEF) {
1598 status = B_ENTRY_NOT_FOUND;
1599 goto done;
1600 }
1601
1602 // TODO: support the "symbolClass" parameter!
1603
1604 TRACE(("found: %lx (%lx + %lx)\n",
1605 symbol->st_value + image->text_region.delta,
1606 symbol->st_value, image->text_region.delta));
1607
1608 *_symbol = (void *)(symbol->st_value + image->text_region.delta);
1609
1610 done:
1611 mutex_unlock(&sImageMutex);
1612 return status;
1613 }
1614
1615
1616 // #pragma mark - kernel private API
1617
1618
1619 /*! Looks up a symbol by address in all images loaded in kernel space.
1620 Note, if you need to call this function outside a debugger, make
1621 sure you fix locking and the way it returns its information, first!
1622 */
1623 status_t
elf_debug_lookup_symbol_address(addr_t address,addr_t * _baseAddress,const char ** _symbolName,const char ** _imageName,bool * _exactMatch)1624 elf_debug_lookup_symbol_address(addr_t address, addr_t *_baseAddress,
1625 const char **_symbolName, const char **_imageName, bool *_exactMatch)
1626 {
1627 struct elf_image_info *image;
1628 elf_sym *symbolFound = NULL;
1629 const char *symbolName = NULL;
1630 addr_t deltaFound = INT_MAX;
1631 bool exactMatch = false;
1632 status_t status;
1633
1634 TRACE(("looking up %p\n", (void *)address));
1635
1636 if (!sInitialized)
1637 return B_ERROR;
1638
1639 //mutex_lock(&sImageMutex);
1640
1641 image = find_image_at_address(address);
1642 // get image that may contain the address
1643
1644 if (image != NULL) {
1645 addr_t symbolDelta;
1646 uint32 i;
1647 int32 j;
1648
1649 TRACE((" image %p, base = %p, size = %p\n", image,
1650 (void *)image->text_region.start, (void *)image->text_region.size));
1651
1652 if (image->debug_symbols != NULL) {
1653 // search extended debug symbol table (contains static symbols)
1654
1655 TRACE((" searching debug symbols...\n"));
1656
1657 for (i = 0; i < image->num_debug_symbols; i++) {
1658 elf_sym *symbol = &image->debug_symbols[i];
1659
1660 if (symbol->st_value == 0 || symbol->st_size
1661 >= image->text_region.size + image->data_region.size)
1662 continue;
1663
1664 symbolDelta
1665 = address - (symbol->st_value + image->text_region.delta);
1666 if (symbolDelta >= 0 && symbolDelta < symbol->st_size)
1667 exactMatch = true;
1668
1669 if (exactMatch || symbolDelta < deltaFound) {
1670 deltaFound = symbolDelta;
1671 symbolFound = symbol;
1672 symbolName = image->debug_string_table + symbol->st_name;
1673
1674 if (exactMatch)
1675 break;
1676 }
1677 }
1678 } else {
1679 // search standard symbol lookup table
1680
1681 TRACE((" searching standard symbols...\n"));
1682
1683 for (i = 0; i < HASHTABSIZE(image); i++) {
1684 for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
1685 j = HASHCHAINS(image)[j]) {
1686 elf_sym *symbol = &image->syms[j];
1687
1688 if (symbol->st_value == 0
1689 || symbol->st_size >= image->text_region.size
1690 + image->data_region.size)
1691 continue;
1692
1693 symbolDelta = address - (long)(symbol->st_value
1694 + image->text_region.delta);
1695 if (symbolDelta >= 0 && symbolDelta < symbol->st_size)
1696 exactMatch = true;
1697
1698 if (exactMatch || symbolDelta < deltaFound) {
1699 deltaFound = symbolDelta;
1700 symbolFound = symbol;
1701 symbolName = SYMNAME(image, symbol);
1702
1703 if (exactMatch)
1704 goto symbol_found;
1705 }
1706 }
1707 }
1708 }
1709 }
1710 symbol_found:
1711
1712 if (symbolFound != NULL) {
1713 if (_symbolName)
1714 *_symbolName = symbolName;
1715 if (_imageName)
1716 *_imageName = image->name;
1717 if (_baseAddress)
1718 *_baseAddress = symbolFound->st_value + image->text_region.delta;
1719 if (_exactMatch)
1720 *_exactMatch = exactMatch;
1721
1722 status = B_OK;
1723 } else if (image != NULL) {
1724 TRACE(("symbol not found!\n"));
1725
1726 if (_symbolName)
1727 *_symbolName = NULL;
1728 if (_imageName)
1729 *_imageName = image->name;
1730 if (_baseAddress)
1731 *_baseAddress = image->text_region.start;
1732 if (_exactMatch)
1733 *_exactMatch = false;
1734
1735 status = B_OK;
1736 } else {
1737 TRACE(("image not found!\n"));
1738 status = B_ENTRY_NOT_FOUND;
1739 }
1740
1741 // Note, theoretically, all information we return back to our caller
1742 // would have to be locked - but since this function is only called
1743 // from the debugger, it's safe to do it this way
1744
1745 //mutex_unlock(&sImageMutex);
1746
1747 return status;
1748 }
1749
1750
1751 /*! Tries to find a matching user symbol for the given address.
1752 Note that the given team's address space must already be in effect.
1753 */
1754 status_t
elf_debug_lookup_user_symbol_address(Team * team,addr_t address,addr_t * _baseAddress,const char ** _symbolName,const char ** _imageName,bool * _exactMatch)1755 elf_debug_lookup_user_symbol_address(Team* team, addr_t address,
1756 addr_t *_baseAddress, const char **_symbolName, const char **_imageName,
1757 bool *_exactMatch)
1758 {
1759 if (team == NULL || team == team_get_kernel_team())
1760 return B_BAD_VALUE;
1761
1762 UserSymbolLookup& lookup = UserSymbolLookup::Default();
1763 status_t error = lookup.Init(team);
1764 if (error != B_OK)
1765 return error;
1766
1767 return lookup.LookupSymbolAddress(address, _baseAddress, _symbolName,
1768 _imageName, _exactMatch);
1769 }
1770
1771
1772 /*! Looks up a symbol in all kernel images. Note, this function is thought to
1773 be used in the kernel debugger, and therefore doesn't perform any locking.
1774 */
1775 addr_t
elf_debug_lookup_symbol(const char * searchName)1776 elf_debug_lookup_symbol(const char* searchName)
1777 {
1778 struct elf_image_info *image = NULL;
1779
1780 ImageHash::Iterator iterator(sImagesHash);
1781 while (iterator.HasNext()) {
1782 image = iterator.Next();
1783 if (image->num_debug_symbols > 0) {
1784 // search extended debug symbol table (contains static symbols)
1785 for (uint32 i = 0; i < image->num_debug_symbols; i++) {
1786 elf_sym *symbol = &image->debug_symbols[i];
1787 const char *name = image->debug_string_table + symbol->st_name;
1788
1789 if (symbol->st_value > 0 && !strcmp(name, searchName))
1790 return symbol->st_value + image->text_region.delta;
1791 }
1792 } else {
1793 // search standard symbol lookup table
1794 for (uint32 i = 0; i < HASHTABSIZE(image); i++) {
1795 for (uint32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
1796 j = HASHCHAINS(image)[j]) {
1797 elf_sym *symbol = &image->syms[j];
1798 const char *name = SYMNAME(image, symbol);
1799
1800 if (symbol->st_value > 0 && !strcmp(name, searchName))
1801 return symbol->st_value + image->text_region.delta;
1802 }
1803 }
1804 }
1805 }
1806
1807 return 0;
1808 }
1809
1810
1811 status_t
elf_lookup_kernel_symbol(const char * name,elf_symbol_info * info)1812 elf_lookup_kernel_symbol(const char* name, elf_symbol_info* info)
1813 {
1814 // find the symbol
1815 elf_sym* foundSymbol = elf_find_symbol(sKernelImage, name, NULL, false);
1816 if (foundSymbol == NULL)
1817 return B_MISSING_SYMBOL;
1818
1819 info->address = foundSymbol->st_value + sKernelImage->text_region.delta;
1820 info->size = foundSymbol->st_size;
1821 return B_OK;
1822 }
1823
1824
1825 #endif // ELF32_COMPAT
1826
1827
1828 status_t
elf_load_user_image(const char * path,Team * team,uint32 flags,addr_t * entry)1829 elf_load_user_image(const char *path, Team *team, uint32 flags, addr_t *entry)
1830 {
1831 elf_ehdr elfHeader;
1832 char baseName[B_OS_NAME_LENGTH];
1833 status_t status;
1834 ssize_t length;
1835
1836 TRACE(("elf_load: entry path '%s', team %p\n", path, team));
1837
1838 int fd = _kern_open(-1, path, O_RDONLY, 0);
1839 if (fd < 0)
1840 return fd;
1841 FileDescriptorCloser fdCloser(fd);
1842
1843 struct stat st;
1844 status = _kern_read_stat(fd, NULL, false, &st, sizeof(st));
1845 if (status != B_OK)
1846 return status;
1847
1848 // read and verify the ELF header
1849
1850 length = _kern_read(fd, 0, &elfHeader, sizeof(elfHeader));
1851 if (length < B_OK)
1852 return length;
1853
1854 if (length != sizeof(elfHeader)) {
1855 // short read
1856 return B_NOT_AN_EXECUTABLE;
1857 }
1858 status = verify_eheader(&elfHeader);
1859 if (status < B_OK)
1860 return status;
1861
1862 #ifdef ELF_LOAD_USER_IMAGE_TEST_EXECUTABLE
1863 if ((flags & ELF_LOAD_USER_IMAGE_TEST_EXECUTABLE) != 0)
1864 return B_OK;
1865 #endif
1866
1867 struct elf_image_info* image;
1868 image = create_image_struct();
1869 if (image == NULL)
1870 return B_NO_MEMORY;
1871 CObjectDeleter<elf_image_info, void, delete_elf_image> imageDeleter(image);
1872
1873 struct ElfHeaderUnsetter {
1874 ElfHeaderUnsetter(elf_image_info* image)
1875 : fImage(image)
1876 {
1877 }
1878 ~ElfHeaderUnsetter()
1879 {
1880 fImage->elf_header = NULL;
1881 }
1882
1883 elf_image_info* fImage;
1884 } headerUnsetter(image);
1885 image->elf_header = &elfHeader;
1886
1887 // read program header
1888
1889 elf_phdr *programHeaders = (elf_phdr *)malloc(
1890 elfHeader.e_phnum * elfHeader.e_phentsize);
1891 if (programHeaders == NULL) {
1892 dprintf("error allocating space for program headers\n");
1893 return B_NO_MEMORY;
1894 }
1895 MemoryDeleter headersDeleter(programHeaders);
1896
1897 TRACE(("reading in program headers at 0x%lx, length 0x%x\n",
1898 elfHeader.e_phoff, elfHeader.e_phnum * elfHeader.e_phentsize));
1899 length = _kern_read(fd, elfHeader.e_phoff, programHeaders,
1900 elfHeader.e_phnum * elfHeader.e_phentsize);
1901 if (length < B_OK) {
1902 dprintf("error reading in program headers\n");
1903 return length;
1904 }
1905 if (length != elfHeader.e_phnum * elfHeader.e_phentsize) {
1906 dprintf("short read while reading in program headers\n");
1907 return B_ERROR;
1908 }
1909
1910 // construct a nice name for the region we have to create below
1911 {
1912 int32 length;
1913
1914 const char *leaf = strrchr(path, '/');
1915 if (leaf == NULL)
1916 leaf = path;
1917 else
1918 leaf++;
1919
1920 length = strlen(leaf);
1921 if (length > B_OS_NAME_LENGTH - 16)
1922 snprintf(baseName, B_OS_NAME_LENGTH, "...%s", leaf + length + 16 - B_OS_NAME_LENGTH);
1923 else
1924 strcpy(baseName, leaf);
1925 }
1926
1927 // map the program's segments into memory, initially with rw access
1928 // correct area protection will be set after relocation
1929
1930 BStackOrHeapArray<area_id, 8> mappedAreas(elfHeader.e_phnum);
1931 if (!mappedAreas.IsValid())
1932 return B_NO_MEMORY;
1933
1934 extended_image_info imageInfo;
1935 memset(&imageInfo, 0, sizeof(imageInfo));
1936
1937 addr_t delta = 0;
1938 uint32 addressSpec = B_RANDOMIZED_BASE_ADDRESS;
1939 for (int i = 0; i < elfHeader.e_phnum; i++) {
1940 char regionName[B_OS_NAME_LENGTH];
1941 char *regionAddress;
1942 char *originalRegionAddress;
1943 area_id id;
1944
1945 mappedAreas[i] = -1;
1946
1947 if (programHeaders[i].p_type == PT_DYNAMIC) {
1948 image->dynamic_section = programHeaders[i].p_vaddr;
1949 continue;
1950 }
1951
1952 if (programHeaders[i].p_type != PT_LOAD)
1953 continue;
1954
1955 regionAddress = (char *)(ROUNDDOWN(programHeaders[i].p_vaddr,
1956 B_PAGE_SIZE) + delta);
1957 originalRegionAddress = regionAddress;
1958
1959 if (programHeaders[i].p_flags & PF_WRITE) {
1960 // rw/data segment
1961 size_t memUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1962 + programHeaders[i].p_memsz;
1963 size_t fileUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1964 + programHeaders[i].p_filesz;
1965
1966 memUpperBound = ROUNDUP(memUpperBound, B_PAGE_SIZE);
1967 fileUpperBound = ROUNDUP(fileUpperBound, B_PAGE_SIZE);
1968
1969 snprintf(regionName, B_OS_NAME_LENGTH, "%s_seg%drw", baseName, i);
1970
1971 id = vm_map_file(team->id, regionName, (void **)®ionAddress,
1972 addressSpec, fileUpperBound,
1973 B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP, false,
1974 fd, ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
1975 if (id < B_OK) {
1976 dprintf("error mapping file data: %s!\n", strerror(id));
1977 return B_NOT_AN_EXECUTABLE;
1978 }
1979 mappedAreas[i] = id;
1980
1981 imageInfo.basic_info.data = regionAddress;
1982 imageInfo.basic_info.data_size = memUpperBound;
1983
1984 image->data_region.start = (addr_t)regionAddress;
1985 image->data_region.size = memUpperBound;
1986
1987 // clean garbage brought by mmap (the region behind the file,
1988 // at least parts of it are the bss and have to be zeroed)
1989 addr_t start = (addr_t)regionAddress
1990 + (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1991 + programHeaders[i].p_filesz;
1992 size_t amount = fileUpperBound
1993 - (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1994 - (programHeaders[i].p_filesz);
1995 arch_cpu_enable_user_access();
1996 memset((void *)start, 0, amount);
1997 arch_cpu_disable_user_access();
1998
1999 // Check if we need extra storage for the bss - we have to do this if
2000 // the above region doesn't already comprise the memory size, too.
2001
2002 if (memUpperBound != fileUpperBound) {
2003 size_t bssSize = memUpperBound - fileUpperBound;
2004
2005 snprintf(regionName, B_OS_NAME_LENGTH, "%s_bss%d", baseName, i);
2006
2007 regionAddress += fileUpperBound;
2008 virtual_address_restrictions virtualRestrictions = {};
2009 virtualRestrictions.address = regionAddress;
2010 virtualRestrictions.address_specification = B_EXACT_ADDRESS;
2011 physical_address_restrictions physicalRestrictions = {};
2012 id = create_area_etc(team->id, regionName, bssSize, B_NO_LOCK,
2013 B_READ_AREA | B_WRITE_AREA, 0, 0, &virtualRestrictions,
2014 &physicalRestrictions, (void**)®ionAddress);
2015 if (id < B_OK) {
2016 dprintf("error allocating bss area: %s!\n", strerror(id));
2017 return B_NOT_AN_EXECUTABLE;
2018 }
2019 }
2020 } else {
2021 // assume ro/text segment
2022 snprintf(regionName, B_OS_NAME_LENGTH, "%s_seg%dro", baseName, i);
2023
2024 size_t segmentSize = ROUNDUP(programHeaders[i].p_memsz
2025 + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
2026
2027 id = vm_map_file(team->id, regionName, (void **)®ionAddress,
2028 addressSpec, segmentSize,
2029 B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP, false, fd,
2030 ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
2031 if (id < B_OK) {
2032 dprintf("error mapping file text: %s!\n", strerror(id));
2033 return B_NOT_AN_EXECUTABLE;
2034 }
2035
2036 mappedAreas[i] = id;
2037
2038 imageInfo.basic_info.text = regionAddress;
2039 imageInfo.basic_info.text_size = segmentSize;
2040
2041 image->text_region.start = (addr_t)regionAddress;
2042 image->text_region.size = segmentSize;
2043 }
2044
2045 if (addressSpec != B_EXACT_ADDRESS) {
2046 addressSpec = B_EXACT_ADDRESS;
2047 delta = regionAddress - originalRegionAddress;
2048 }
2049 }
2050
2051 image->data_region.delta = delta;
2052 image->text_region.delta = delta;
2053
2054 // modify the dynamic ptr by the delta of the regions
2055 image->dynamic_section += image->text_region.delta;
2056
2057 arch_cpu_enable_user_access();
2058 status = elf_parse_dynamic_section(image);
2059 if (status != B_OK) {
2060 arch_cpu_disable_user_access();
2061 return status;
2062 }
2063
2064 status = elf_relocate(image, image);
2065 if (status != B_OK) {
2066 arch_cpu_disable_user_access();
2067 return status;
2068 }
2069
2070 arch_cpu_disable_user_access();
2071
2072 // set correct area protection
2073 for (int i = 0; i < elfHeader.e_phnum; i++) {
2074 if (mappedAreas[i] == -1)
2075 continue;
2076
2077 uint32 protection = 0;
2078
2079 if (programHeaders[i].p_flags & PF_EXECUTE)
2080 protection |= B_EXECUTE_AREA;
2081 if (programHeaders[i].p_flags & PF_WRITE)
2082 protection |= B_WRITE_AREA;
2083 if (programHeaders[i].p_flags & PF_READ)
2084 protection |= B_READ_AREA;
2085
2086 status = vm_set_area_protection(team->id, mappedAreas[i], protection,
2087 true);
2088 if (status != B_OK)
2089 return status;
2090 }
2091
2092 // register the loaded image
2093 imageInfo.basic_info.type = B_LIBRARY_IMAGE;
2094 imageInfo.basic_info.device = st.st_dev;
2095 imageInfo.basic_info.node = st.st_ino;
2096 strlcpy(imageInfo.basic_info.name, path, sizeof(imageInfo.basic_info.name));
2097
2098 imageInfo.basic_info.api_version = B_HAIKU_VERSION;
2099 imageInfo.basic_info.abi = B_HAIKU_ABI;
2100 // TODO: Get the actual values for the shared object. Currently only
2101 // the runtime loader is loaded, so this is good enough for the time
2102 // being.
2103
2104 imageInfo.text_delta = delta;
2105 imageInfo.symbol_table = image->syms;
2106 imageInfo.symbol_hash = image->symhash;
2107 imageInfo.string_table = image->strtab;
2108
2109 imageInfo.basic_info.id = register_image(team, &imageInfo,
2110 sizeof(imageInfo));
2111 if (imageInfo.basic_info.id >= 0 && team_get_current_team_id() == team->id)
2112 user_debug_image_created(&imageInfo.basic_info);
2113 // Don't care, if registering fails. It's not crucial.
2114
2115 TRACE(("elf_load: done!\n"));
2116
2117 *entry = elfHeader.e_entry + delta;
2118 return B_OK;
2119 }
2120
2121
2122 #ifndef ELF32_COMPAT
2123
2124 image_id
load_kernel_add_on(const char * path)2125 load_kernel_add_on(const char *path)
2126 {
2127 elf_phdr *programHeaders;
2128 elf_ehdr *elfHeader;
2129 struct elf_image_info *image;
2130 const char *fileName;
2131 void *reservedAddress;
2132 size_t reservedSize;
2133 status_t status;
2134 ssize_t length;
2135 bool textSectionWritable = false;
2136 int executableHeaderCount = 0;
2137
2138 TRACE(("elf_load_kspace: entry path '%s'\n", path));
2139
2140 int fd = _kern_open(-1, path, O_RDONLY, 0);
2141 if (fd < 0)
2142 return fd;
2143
2144 struct vnode *vnode;
2145 status = vfs_get_vnode_from_fd(fd, true, &vnode);
2146 if (status < B_OK)
2147 goto error0;
2148
2149 // get the file name
2150 fileName = strrchr(path, '/');
2151 if (fileName == NULL)
2152 fileName = path;
2153 else
2154 fileName++;
2155
2156 // Prevent someone else from trying to load this image
2157 mutex_lock(&sImageLoadMutex);
2158
2159 // make sure it's not loaded already. Search by vnode
2160 image = find_image_by_vnode(vnode);
2161 if (image) {
2162 atomic_add(&image->ref_count, 1);
2163 goto done;
2164 }
2165
2166 elfHeader = (elf_ehdr *)malloc(sizeof(*elfHeader));
2167 if (!elfHeader) {
2168 status = B_NO_MEMORY;
2169 goto error;
2170 }
2171
2172 length = _kern_read(fd, 0, elfHeader, sizeof(*elfHeader));
2173 if (length < B_OK) {
2174 status = length;
2175 goto error1;
2176 }
2177 if (length != sizeof(*elfHeader)) {
2178 // short read
2179 status = B_NOT_AN_EXECUTABLE;
2180 goto error1;
2181 }
2182 status = verify_eheader(elfHeader);
2183 if (status < B_OK)
2184 goto error1;
2185
2186 image = create_image_struct();
2187 if (!image) {
2188 status = B_NO_MEMORY;
2189 goto error1;
2190 }
2191 image->vnode = vnode;
2192 image->elf_header = elfHeader;
2193 image->name = strdup(path);
2194 vnode = NULL;
2195
2196 programHeaders = (elf_phdr *)malloc(elfHeader->e_phnum
2197 * elfHeader->e_phentsize);
2198 if (programHeaders == NULL) {
2199 dprintf("%s: error allocating space for program headers\n", fileName);
2200 status = B_NO_MEMORY;
2201 goto error2;
2202 }
2203
2204 TRACE(("reading in program headers at 0x%lx, length 0x%x\n",
2205 elfHeader->e_phoff, elfHeader->e_phnum * elfHeader->e_phentsize));
2206
2207 length = _kern_read(fd, elfHeader->e_phoff, programHeaders,
2208 elfHeader->e_phnum * elfHeader->e_phentsize);
2209 if (length < B_OK) {
2210 status = length;
2211 TRACE(("%s: error reading in program headers\n", fileName));
2212 goto error3;
2213 }
2214 if (length != elfHeader->e_phnum * elfHeader->e_phentsize) {
2215 TRACE(("%s: short read while reading in program headers\n", fileName));
2216 status = B_ERROR;
2217 goto error3;
2218 }
2219
2220 // determine how much space we need for all loaded segments
2221
2222 reservedSize = 0;
2223 length = 0;
2224
2225 for (int32 i = 0; i < elfHeader->e_phnum; i++) {
2226 size_t end;
2227
2228 if (programHeaders[i].p_type != PT_LOAD)
2229 continue;
2230
2231 length += ROUNDUP(programHeaders[i].p_memsz
2232 + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
2233
2234 end = ROUNDUP(programHeaders[i].p_memsz + programHeaders[i].p_vaddr,
2235 B_PAGE_SIZE);
2236 if (end > reservedSize)
2237 reservedSize = end;
2238
2239 if (programHeaders[i].IsExecutable())
2240 executableHeaderCount++;
2241 }
2242
2243 // Check whether the segments have an unreasonable amount of unused space
2244 // inbetween.
2245 if ((ssize_t)reservedSize > length + 8 * 1024) {
2246 status = B_BAD_DATA;
2247 goto error1;
2248 }
2249
2250 // reserve that space and allocate the areas from that one
2251 if (vm_reserve_address_range(VMAddressSpace::KernelID(), &reservedAddress,
2252 B_ANY_KERNEL_ADDRESS, reservedSize, 0) < B_OK) {
2253 status = B_NO_MEMORY;
2254 goto error3;
2255 }
2256
2257 image->data_region.size = 0;
2258 image->text_region.size = 0;
2259
2260 for (int32 i = 0; i < elfHeader->e_phnum; i++) {
2261 char regionName[B_OS_NAME_LENGTH];
2262 elf_region *region;
2263
2264 TRACE(("looking at program header %" B_PRId32 "\n", i));
2265
2266 switch (programHeaders[i].p_type) {
2267 case PT_LOAD:
2268 break;
2269 case PT_DYNAMIC:
2270 image->dynamic_section = programHeaders[i].p_vaddr;
2271 continue;
2272 case PT_INTERP:
2273 // should check here for appropriate interpreter
2274 continue;
2275 case PT_PHDR:
2276 case PT_STACK:
2277 // we don't use it
2278 continue;
2279 case PT_EH_FRAME:
2280 // not implemented yet, but can be ignored
2281 continue;
2282 case PT_ARM_UNWIND:
2283 continue;
2284 case PT_RISCV_ATTRIBUTES:
2285 // TODO: check ABI compatibility attributes
2286 continue;
2287 default:
2288 dprintf("%s: unhandled pheader type %#" B_PRIx32 "\n", fileName,
2289 programHeaders[i].p_type);
2290 continue;
2291 }
2292
2293 // we're here, so it must be a PT_LOAD segment
2294
2295 // Usually add-ons have two PT_LOAD headers: one for .data one or .text.
2296 // x86 and PPC may differ in permission bits for .data's PT_LOAD header
2297 // x86 is usually RW, PPC is RWE
2298
2299 // Some add-ons may have .text and .data concatenated in a single
2300 // PT_LOAD RWE header and we must map that to .text.
2301 if (programHeaders[i].IsReadWrite()
2302 && (!programHeaders[i].IsExecutable()
2303 || executableHeaderCount > 1)) {
2304 // this is the writable segment
2305 if (image->data_region.size != 0) {
2306 // we've already created this segment
2307 continue;
2308 }
2309 region = &image->data_region;
2310
2311 snprintf(regionName, B_OS_NAME_LENGTH, "%s_data", fileName);
2312 } else if (programHeaders[i].IsExecutable()) {
2313 // this is the non-writable segment
2314 if (image->text_region.size != 0) {
2315 // we've already created this segment
2316 continue;
2317 }
2318 region = &image->text_region;
2319
2320 // some programs may have .text and .data concatenated in a
2321 // single PT_LOAD section which is readable/writable/executable
2322 textSectionWritable = programHeaders[i].IsReadWrite();
2323 snprintf(regionName, B_OS_NAME_LENGTH, "%s_text", fileName);
2324 } else {
2325 dprintf("%s: weird program header flags %#" B_PRIx32 "\n", fileName,
2326 programHeaders[i].p_flags);
2327 continue;
2328 }
2329
2330 region->start = (addr_t)reservedAddress + ROUNDDOWN(
2331 programHeaders[i].p_vaddr, B_PAGE_SIZE);
2332 region->size = ROUNDUP(programHeaders[i].p_memsz
2333 + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
2334 region->id = create_area(regionName, (void **)®ion->start,
2335 B_EXACT_ADDRESS, region->size, B_FULL_LOCK,
2336 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
2337 if (region->id < B_OK) {
2338 dprintf("%s: error allocating area: %s\n", fileName,
2339 strerror(region->id));
2340 status = B_NOT_AN_EXECUTABLE;
2341 goto error4;
2342 }
2343 region->delta = -ROUNDDOWN(programHeaders[i].p_vaddr, B_PAGE_SIZE);
2344
2345 TRACE(("elf_load_kspace: created area \"%s\" at %p\n",
2346 regionName, (void *)region->start));
2347
2348 length = _kern_read(fd, programHeaders[i].p_offset,
2349 (void *)(region->start + (programHeaders[i].p_vaddr % B_PAGE_SIZE)),
2350 programHeaders[i].p_filesz);
2351 if (length < B_OK) {
2352 status = length;
2353 dprintf("%s: error reading in segment %" B_PRId32 "\n", fileName,
2354 i);
2355 goto error5;
2356 }
2357 }
2358
2359 image->data_region.delta += image->data_region.start;
2360 image->text_region.delta += image->text_region.start;
2361
2362 // modify the dynamic ptr by the delta of the regions
2363 image->dynamic_section += image->text_region.delta;
2364
2365 status = elf_parse_dynamic_section(image);
2366 if (status < B_OK)
2367 goto error5;
2368
2369 status = init_image_version_infos(image);
2370 if (status != B_OK)
2371 goto error5;
2372
2373 status = check_needed_image_versions(image);
2374 if (status != B_OK)
2375 goto error5;
2376
2377 status = elf_relocate(image, sKernelImage);
2378 if (status < B_OK)
2379 goto error5;
2380
2381 // We needed to read in the contents of the "text" area, but
2382 // now we can protect it read-only/execute, unless this is a
2383 // special image with concatenated .text and .data, when it
2384 // will also need write access.
2385 set_area_protection(image->text_region.id,
2386 B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA
2387 | (textSectionWritable ? B_KERNEL_WRITE_AREA : 0));
2388
2389 // There might be a hole between the two segments, and we don't need to
2390 // reserve this any longer
2391 vm_unreserve_address_range(VMAddressSpace::KernelID(), reservedAddress,
2392 reservedSize);
2393
2394 if (sLoadElfSymbols)
2395 load_elf_symbol_table(fd, image);
2396
2397 free(programHeaders);
2398 mutex_lock(&sImageMutex);
2399 register_elf_image(image);
2400 mutex_unlock(&sImageMutex);
2401
2402 done:
2403 _kern_close(fd);
2404 mutex_unlock(&sImageLoadMutex);
2405
2406 return image->id;
2407
2408 error5:
2409 error4:
2410 vm_unreserve_address_range(VMAddressSpace::KernelID(), reservedAddress,
2411 reservedSize);
2412 error3:
2413 free(programHeaders);
2414 error2:
2415 delete_elf_image(image);
2416 elfHeader = NULL;
2417 error1:
2418 free(elfHeader);
2419 error:
2420 mutex_unlock(&sImageLoadMutex);
2421 error0:
2422 dprintf("Could not load kernel add-on \"%s\": %s\n", path,
2423 strerror(status));
2424
2425 if (vnode)
2426 vfs_put_vnode(vnode);
2427 _kern_close(fd);
2428
2429 return status;
2430 }
2431
2432
2433 status_t
unload_kernel_add_on(image_id id)2434 unload_kernel_add_on(image_id id)
2435 {
2436 MutexLocker _(sImageLoadMutex);
2437 MutexLocker _2(sImageMutex);
2438
2439 elf_image_info *image = find_image(id);
2440 if (image == NULL)
2441 return B_BAD_IMAGE_ID;
2442
2443 unload_elf_image(image);
2444 return B_OK;
2445 }
2446
2447
2448 struct elf_image_info*
elf_get_kernel_image()2449 elf_get_kernel_image()
2450 {
2451 return sKernelImage;
2452 }
2453
2454
2455 status_t
elf_get_image_info_for_address(addr_t address,image_info * info)2456 elf_get_image_info_for_address(addr_t address, image_info* info)
2457 {
2458 MutexLocker _(sImageMutex);
2459 struct elf_image_info* elfInfo = find_image_at_address(address);
2460 if (elfInfo == NULL)
2461 return B_ENTRY_NOT_FOUND;
2462
2463 info->id = elfInfo->id;
2464 info->type = B_SYSTEM_IMAGE;
2465 info->sequence = 0;
2466 info->init_order = 0;
2467 info->init_routine = NULL;
2468 info->term_routine = NULL;
2469 info->device = -1;
2470 info->node = -1;
2471 // TODO: We could actually fill device/node in.
2472 strlcpy(info->name, elfInfo->name, sizeof(info->name));
2473 info->text = (void*)elfInfo->text_region.start;
2474 info->data = (void*)elfInfo->data_region.start;
2475 info->text_size = elfInfo->text_region.size;
2476 info->data_size = elfInfo->data_region.size;
2477
2478 return B_OK;
2479 }
2480
2481
2482 image_id
elf_create_memory_image(const char * imageName,addr_t text,size_t textSize,addr_t data,size_t dataSize)2483 elf_create_memory_image(const char* imageName, addr_t text, size_t textSize,
2484 addr_t data, size_t dataSize)
2485 {
2486 // allocate the image
2487 elf_image_info* image = create_image_struct();
2488 if (image == NULL)
2489 return B_NO_MEMORY;
2490 MemoryDeleter imageDeleter(image);
2491
2492 // allocate symbol and string tables -- we allocate an empty symbol table,
2493 // so that elf_debug_lookup_symbol_address() won't try the dynamic symbol
2494 // table, which we don't have.
2495 elf_sym* symbolTable = (elf_sym*)malloc(0);
2496 char* stringTable = (char*)malloc(1);
2497 MemoryDeleter symbolTableDeleter(symbolTable);
2498 MemoryDeleter stringTableDeleter(stringTable);
2499 if (symbolTable == NULL || stringTable == NULL)
2500 return B_NO_MEMORY;
2501
2502 // the string table always contains the empty string
2503 stringTable[0] = '\0';
2504
2505 image->debug_symbols = symbolTable;
2506 image->num_debug_symbols = 0;
2507 image->debug_string_table = stringTable;
2508
2509 // dup image name
2510 image->name = strdup(imageName);
2511 if (image->name == NULL)
2512 return B_NO_MEMORY;
2513
2514 // data and text region
2515 image->text_region.id = -1;
2516 image->text_region.start = text;
2517 image->text_region.size = textSize;
2518 image->text_region.delta = 0;
2519
2520 image->data_region.id = -1;
2521 image->data_region.start = data;
2522 image->data_region.size = dataSize;
2523 image->data_region.delta = 0;
2524
2525 mutex_lock(&sImageMutex);
2526 register_elf_image(image);
2527 image_id imageID = image->id;
2528 mutex_unlock(&sImageMutex);
2529
2530 // keep the allocated memory
2531 imageDeleter.Detach();
2532 symbolTableDeleter.Detach();
2533 stringTableDeleter.Detach();
2534
2535 return imageID;
2536 }
2537
2538
2539 status_t
elf_add_memory_image_symbol(image_id id,const char * name,addr_t address,size_t size,int32 type)2540 elf_add_memory_image_symbol(image_id id, const char* name, addr_t address,
2541 size_t size, int32 type)
2542 {
2543 MutexLocker _(sImageMutex);
2544
2545 // get the image
2546 struct elf_image_info* image = find_image(id);
2547 if (image == NULL)
2548 return B_ENTRY_NOT_FOUND;
2549
2550 // get the current string table size
2551 size_t stringTableSize = 1;
2552 if (image->num_debug_symbols > 0) {
2553 for (int32 i = image->num_debug_symbols - 1; i >= 0; i--) {
2554 int32 nameIndex = image->debug_symbols[i].st_name;
2555 if (nameIndex != 0) {
2556 stringTableSize = nameIndex
2557 + strlen(image->debug_string_table + nameIndex) + 1;
2558 break;
2559 }
2560 }
2561 }
2562
2563 // enter the name in the string table
2564 char* stringTable = (char*)image->debug_string_table;
2565 size_t stringIndex = 0;
2566 if (name != NULL) {
2567 size_t nameSize = strlen(name) + 1;
2568 stringIndex = stringTableSize;
2569 stringTableSize += nameSize;
2570 stringTable = (char*)realloc((char*)image->debug_string_table,
2571 stringTableSize);
2572 if (stringTable == NULL)
2573 return B_NO_MEMORY;
2574 image->debug_string_table = stringTable;
2575 memcpy(stringTable + stringIndex, name, nameSize);
2576 }
2577
2578 // resize the symbol table
2579 int32 symbolCount = image->num_debug_symbols + 1;
2580 elf_sym* symbolTable = (elf_sym*)realloc(
2581 (elf_sym*)image->debug_symbols, sizeof(elf_sym) * symbolCount);
2582 if (symbolTable == NULL)
2583 return B_NO_MEMORY;
2584 image->debug_symbols = symbolTable;
2585
2586 // enter the symbol
2587 elf_sym& symbol = symbolTable[symbolCount - 1];
2588 symbol.SetInfo(STB_GLOBAL,
2589 type == B_SYMBOL_TYPE_DATA ? STT_OBJECT : STT_FUNC);
2590 symbol.st_name = stringIndex;
2591 symbol.st_value = address;
2592 symbol.st_size = size;
2593 symbol.st_other = 0;
2594 symbol.st_shndx = 0;
2595 image->num_debug_symbols++;
2596
2597 return B_OK;
2598 }
2599
2600
2601 /*! Reads the symbol and string table for the kernel image with the given ID.
2602 \a _symbolCount and \a _stringTableSize are both in- and output parameters.
2603 When called they call the size of the buffers given by \a symbolTable and
2604 \a stringTable respectively. When the function returns successfully, they
2605 will contain the actual sizes (which can be greater than the original ones).
2606 The function will copy as much as possible into the buffers. For only
2607 getting the required buffer sizes, it can be invoked with \c NULL buffers.
2608 On success \a _imageDelta will contain the offset to be added to the symbol
2609 values in the table to get the actual symbol addresses.
2610 */
2611 status_t
elf_read_kernel_image_symbols(image_id id,elf_sym * symbolTable,int32 * _symbolCount,char * stringTable,size_t * _stringTableSize,addr_t * _imageDelta,bool kernel)2612 elf_read_kernel_image_symbols(image_id id, elf_sym* symbolTable,
2613 int32* _symbolCount, char* stringTable, size_t* _stringTableSize,
2614 addr_t* _imageDelta, bool kernel)
2615 {
2616 // check params
2617 if (_symbolCount == NULL || _stringTableSize == NULL)
2618 return B_BAD_VALUE;
2619 if (!kernel) {
2620 if (!IS_USER_ADDRESS(_symbolCount) || !IS_USER_ADDRESS(_stringTableSize)
2621 || (_imageDelta != NULL && !IS_USER_ADDRESS(_imageDelta))
2622 || (symbolTable != NULL && !IS_USER_ADDRESS(symbolTable))
2623 || (stringTable != NULL && !IS_USER_ADDRESS(stringTable))) {
2624 return B_BAD_ADDRESS;
2625 }
2626 }
2627
2628 // get buffer sizes
2629 int32 maxSymbolCount;
2630 size_t maxStringTableSize;
2631 if (kernel) {
2632 maxSymbolCount = *_symbolCount;
2633 maxStringTableSize = *_stringTableSize;
2634 } else {
2635 if (user_memcpy(&maxSymbolCount, _symbolCount, sizeof(maxSymbolCount))
2636 != B_OK
2637 || user_memcpy(&maxStringTableSize, _stringTableSize,
2638 sizeof(maxStringTableSize)) != B_OK) {
2639 return B_BAD_ADDRESS;
2640 }
2641 }
2642
2643 // find the image
2644 MutexLocker _(sImageMutex);
2645 struct elf_image_info* image = find_image(id);
2646 if (image == NULL)
2647 return B_ENTRY_NOT_FOUND;
2648
2649 // get the tables and infos
2650 addr_t imageDelta = image->text_region.delta;
2651 const elf_sym* symbols;
2652 int32 symbolCount;
2653 const char* strings;
2654
2655 if (image->debug_symbols != NULL) {
2656 symbols = image->debug_symbols;
2657 symbolCount = image->num_debug_symbols;
2658 strings = image->debug_string_table;
2659 } else {
2660 symbols = image->syms;
2661 symbolCount = image->symhash[1];
2662 strings = image->strtab;
2663 }
2664
2665 // The string table size isn't stored in the elf_image_info structure. Find
2666 // out by iterating through all symbols.
2667 size_t stringTableSize = 0;
2668 for (int32 i = 0; i < symbolCount; i++) {
2669 size_t index = symbols[i].st_name;
2670 if (index > stringTableSize)
2671 stringTableSize = index;
2672 }
2673 stringTableSize += strlen(strings + stringTableSize) + 1;
2674 // add size of the last string
2675
2676 // copy symbol table
2677 int32 symbolsToCopy = min_c(symbolCount, maxSymbolCount);
2678 if (symbolTable != NULL && symbolsToCopy > 0) {
2679 if (kernel) {
2680 memcpy(symbolTable, symbols, sizeof(elf_sym) * symbolsToCopy);
2681 } else if (user_memcpy(symbolTable, symbols,
2682 sizeof(elf_sym) * symbolsToCopy) != B_OK) {
2683 return B_BAD_ADDRESS;
2684 }
2685 }
2686
2687 // copy string table
2688 size_t stringsToCopy = min_c(stringTableSize, maxStringTableSize);
2689 if (stringTable != NULL && stringsToCopy > 0) {
2690 if (kernel) {
2691 memcpy(stringTable, strings, stringsToCopy);
2692 } else {
2693 if (user_memcpy(stringTable, strings, stringsToCopy)
2694 != B_OK) {
2695 return B_BAD_ADDRESS;
2696 }
2697 }
2698 }
2699
2700 // copy sizes
2701 if (kernel) {
2702 *_symbolCount = symbolCount;
2703 *_stringTableSize = stringTableSize;
2704 if (_imageDelta != NULL)
2705 *_imageDelta = imageDelta;
2706 } else {
2707 if (user_memcpy(_symbolCount, &symbolCount, sizeof(symbolCount)) != B_OK
2708 || user_memcpy(_stringTableSize, &stringTableSize,
2709 sizeof(stringTableSize)) != B_OK
2710 || (_imageDelta != NULL && user_memcpy(_imageDelta, &imageDelta,
2711 sizeof(imageDelta)) != B_OK)) {
2712 return B_BAD_ADDRESS;
2713 }
2714 }
2715
2716 return B_OK;
2717 }
2718
2719
2720 status_t
elf_init(kernel_args * args)2721 elf_init(kernel_args* args)
2722 {
2723 struct preloaded_image* image;
2724
2725 image_init();
2726
2727 if (void* handle = load_driver_settings("kernel")) {
2728 sLoadElfSymbols = get_driver_boolean_parameter(handle, "load_symbols",
2729 false, false);
2730
2731 unload_driver_settings(handle);
2732 }
2733
2734 sImagesHash = new(std::nothrow) ImageHash();
2735 if (sImagesHash == NULL)
2736 return B_NO_MEMORY;
2737 status_t init = sImagesHash->Init(IMAGE_HASH_SIZE);
2738 if (init != B_OK)
2739 return init;
2740
2741 // Build a image structure for the kernel, which has already been loaded.
2742 // The preloaded_images were already prepared by the VM.
2743 image = args->kernel_image;
2744 if (insert_preloaded_image(static_cast<preloaded_elf_image *>(image),
2745 true) < B_OK)
2746 panic("could not create kernel image.\n");
2747
2748 // Build image structures for all preloaded images.
2749 for (image = args->preloaded_images; image != NULL; image = image->next)
2750 insert_preloaded_image(static_cast<preloaded_elf_image *>(image),
2751 false);
2752
2753 add_debugger_command("ls", &dump_address_info,
2754 "lookup symbol for a particular address");
2755 add_debugger_command("symbols", &dump_symbols, "dump symbols for image");
2756 add_debugger_command("symbol", &dump_symbol, "search symbol in images");
2757 add_debugger_command_etc("image", &dump_image, "dump image info",
2758 "Prints info about the specified image.\n"
2759 " <image> - pointer to the semaphore structure, or ID\n"
2760 " of the image to print info for.\n", 0);
2761
2762 sInitialized = true;
2763 return B_OK;
2764 }
2765
2766
2767 // #pragma mark -
2768
2769
2770 /*! Reads the symbol and string table for the kernel image with the given ID.
2771 \a _symbolCount and \a _stringTableSize are both in- and output parameters.
2772 When called they call the size of the buffers given by \a symbolTable and
2773 \a stringTable respectively. When the function returns successfully, they
2774 will contain the actual sizes (which can be greater than the original ones).
2775 The function will copy as much as possible into the buffers. For only
2776 getting the required buffer sizes, it can be invoked with \c NULL buffers.
2777 On success \a _imageDelta will contain the offset to be added to the symbol
2778 values in the table to get the actual symbol addresses.
2779 */
2780 status_t
_user_read_kernel_image_symbols(image_id id,elf_sym * symbolTable,int32 * _symbolCount,char * stringTable,size_t * _stringTableSize,addr_t * _imageDelta)2781 _user_read_kernel_image_symbols(image_id id, elf_sym* symbolTable,
2782 int32* _symbolCount, char* stringTable, size_t* _stringTableSize,
2783 addr_t* _imageDelta)
2784 {
2785 return elf_read_kernel_image_symbols(id, symbolTable, _symbolCount,
2786 stringTable, _stringTableSize, _imageDelta, false);
2787 }
2788
2789 #endif // ELF32_COMPAT
2790
2791