1 /* 2 * Copyright (c) 2001, 2003 Anders Magnusson (ragge@ludd.luth.se). 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /* 29 * Code to deal with in-kernel symbol table management + /dev/ksyms. 30 * 31 * For each loaded module the symbol table info is kept track of by a 32 * struct, placed in a circular list. The first entry is the kernel 33 * symbol table. 34 */ 35 36 /* 37 * TODO: 38 * Change the ugly way of adding new symbols (comes with linker) 39 * Add kernel locking stuff. 40 * (Ev) add support for poll. 41 * (Ev) fix support for mmap. 42 * 43 * Export ksyms internal logic for use in post-mortem debuggers? 44 * Need to move struct symtab to ksyms.h for that. 45 */ 46 47 #include <sys/cdefs.h> 48 __KERNEL_RCSID(0, "$NetBSD: kern_ksyms.c,v 1.34 2008/01/04 11:28:13 ad Exp $"); 49 50 #ifdef _KERNEL 51 #include "opt_ddb.h" 52 #include "opt_ddbparam.h" /* for SYMTAB_SPACE */ 53 #endif 54 55 #include <sys/param.h> 56 #include <sys/errno.h> 57 #include <sys/queue.h> 58 #include <sys/exec.h> 59 #include <sys/systm.h> 60 #include <sys/conf.h> 61 #include <sys/device.h> 62 #include <sys/malloc.h> 63 #include <sys/proc.h> 64 65 #include <machine/elf_machdep.h> /* XXX */ 66 #define ELFSIZE ARCH_ELFSIZE 67 68 #include <sys/exec_elf.h> 69 #include <sys/ksyms.h> 70 71 #include <lib/libkern/libkern.h> 72 73 #ifdef DDB 74 #include <ddb/db_output.h> 75 #endif 76 77 #include "ksyms.h" 78 79 static int ksymsinited = 0; 80 81 #if NKSYMS 82 static void ksyms_hdr_init(void *hdraddr); 83 static void ksyms_sizes_calc(void); 84 static int ksyms_isopen; 85 static int ksyms_maxlen; 86 #endif 87 88 #ifdef KSYMS_DEBUG 89 #define FOLLOW_CALLS 1 90 #define FOLLOW_MORE_CALLS 2 91 #define FOLLOW_DEVKSYMS 4 92 static int ksyms_debug; 93 #endif 94 95 #ifdef SYMTAB_SPACE 96 #define SYMTAB_FILLER "|This is the symbol table!" 97 98 char db_symtab[SYMTAB_SPACE] = SYMTAB_FILLER; 99 int db_symtabsize = SYMTAB_SPACE; 100 #endif 101 102 /* 103 * Store the different symbol tables in a double-linked list. 104 */ 105 struct symtab { 106 CIRCLEQ_ENTRY(symtab) sd_queue; 107 const char *sd_name; /* Name of this table */ 108 Elf_Sym *sd_symstart; /* Address of symbol table */ 109 char *sd_strstart; /* Address of corresponding string table */ 110 int sd_usroffset; /* Real address for userspace */ 111 int sd_symsize; /* Size in bytes of symbol table */ 112 int sd_strsize; /* Size of string table */ 113 int *sd_symnmoff; /* Used when calculating the name offset */ 114 }; 115 116 static CIRCLEQ_HEAD(, symtab) symtab_queue = 117 CIRCLEQ_HEAD_INITIALIZER(symtab_queue); 118 119 static struct symtab kernel_symtab; 120 121 #define USE_PTREE 122 #ifdef USE_PTREE 123 /* 124 * Patricia-tree-based lookup structure for the in-kernel global symbols. 125 * Based on a design by Mikael Sundstrom, msm@sm.luth.se. 126 */ 127 struct ptree { 128 int16_t bitno; 129 int16_t lr[2]; 130 } *symb; 131 static int16_t baseidx; 132 static int treex = 1; 133 134 #define P_BIT(key, bit) ((key[bit >> 3] >> (bit & 7)) & 1) 135 #define STRING(idx) (kernel_symtab.sd_symstart[idx].st_name + \ 136 kernel_symtab.sd_strstart) 137 138 static int 139 ksyms_verify(void *symstart, void *strstart) 140 { 141 #if defined(DIAGNOSTIC) || defined(DEBUG) 142 if (symstart == NULL) 143 printf("ksyms: Symbol table not found\n"); 144 if (strstart == NULL) 145 printf("ksyms: String table not found\n"); 146 if (symstart == NULL || strstart == NULL) 147 printf("ksyms: Perhaps the kernel is stripped?\n"); 148 #endif 149 if (symstart == NULL || strstart == NULL) 150 return 0; 151 KASSERT(symstart <= strstart); 152 return 1; 153 } 154 155 /* 156 * Walk down the tree until a terminal node is found. 157 */ 158 static int 159 symbol_traverse(const char *key) 160 { 161 int16_t nb, rbit = baseidx; 162 163 while (rbit > 0) { 164 nb = symb[rbit].bitno; 165 rbit = symb[rbit].lr[P_BIT(key, nb)]; 166 } 167 return -rbit; 168 } 169 170 static int 171 ptree_add(char *key, int val) 172 { 173 int idx; 174 int nix, cix, bit, rbit, sb, lastrbit, svbit = 0, ix; 175 char *m, *k; 176 177 if (baseidx == 0) { 178 baseidx = -val; 179 return 0; /* First element */ 180 } 181 182 /* Get string to match against */ 183 idx = symbol_traverse(key); 184 185 /* Find first mismatching bit */ 186 m = STRING(idx); 187 k = key; 188 if (strcmp(m, k) == 0) 189 return 1; 190 191 for (cix = 0; *m && *k && *m == *k; m++, k++, cix += 8) 192 ; 193 ix = ffs((int)*m ^ (int)*k) - 1; 194 cix += ix; 195 196 /* Create new node */ 197 nix = treex++; 198 bit = P_BIT(key, cix); 199 symb[nix].bitno = cix; 200 symb[nix].lr[bit] = -val; 201 202 /* Find where to insert node */ 203 rbit = baseidx; 204 lastrbit = 0; 205 for (;;) { 206 if (rbit < 0) 207 break; 208 sb = symb[rbit].bitno; 209 if (sb > cix) 210 break; 211 if (sb == cix) 212 printf("symb[rbit].bitno == cix!!!\n"); 213 lastrbit = rbit; 214 svbit = P_BIT(key, sb); 215 rbit = symb[rbit].lr[svbit]; 216 } 217 218 /* Do the actual insertion */ 219 if (lastrbit == 0) { 220 /* first element */ 221 symb[nix].lr[!bit] = baseidx; 222 baseidx = nix; 223 } else { 224 symb[nix].lr[!bit] = rbit; 225 symb[lastrbit].lr[svbit] = nix; 226 } 227 return 0; 228 } 229 230 static int 231 ptree_find(const char *key) 232 { 233 int idx; 234 235 if (baseidx == 0) 236 return 0; 237 idx = symbol_traverse(key); 238 239 if (strcmp(key, STRING(idx)) == 0) 240 return idx; 241 return 0; 242 } 243 244 static void 245 ptree_gen(char *off, struct symtab *tab) 246 { 247 Elf_Sym *sym; 248 int i, nsym; 249 250 if (off != NULL) 251 symb = (struct ptree *)ALIGN(off); 252 else 253 symb = malloc((tab->sd_symsize/sizeof(Elf_Sym)) * 254 sizeof(struct ptree), M_DEVBUF, M_WAITOK); 255 symb--; /* sym index won't be 0 */ 256 257 sym = tab->sd_symstart; 258 if ((nsym = tab->sd_symsize/sizeof(Elf_Sym)) > INT16_MAX) { 259 printf("Too many symbols for tree, skipping %d symbols\n", 260 nsym-INT16_MAX); 261 nsym = INT16_MAX; 262 } 263 for (i = 1; i < nsym; i++) { 264 if (ELF_ST_BIND(sym[i].st_info) != STB_GLOBAL) 265 continue; 266 ptree_add(tab->sd_strstart+sym[i].st_name, i); 267 } 268 } 269 #endif /* USE_PTREE */ 270 271 /* 272 * Finds a certain symbol name in a certain symbol table. 273 */ 274 static Elf_Sym * 275 findsym(const char *name, struct symtab *table) 276 { 277 Elf_Sym *start = table->sd_symstart; 278 int i, sz = table->sd_symsize/sizeof(Elf_Sym); 279 char *np; 280 char *realstart = table->sd_strstart - table->sd_usroffset; 281 282 #ifdef USE_PTREE 283 if (table == &kernel_symtab && (i = ptree_find(name)) != 0) 284 return &start[i]; 285 #endif 286 287 for (i = 0; i < sz; i++) { 288 np = realstart + start[i].st_name; 289 if (name[0] == np[0] && name[1] == np[1] && 290 strcmp(name, np) == 0) 291 return &start[i]; 292 } 293 return NULL; 294 } 295 296 /* 297 * The "attach" is in reality done in ksyms_init(). 298 */ 299 void ksymsattach(int); 300 void 301 ksymsattach(int arg) 302 { 303 304 #ifdef USE_PTREE 305 if (baseidx == 0) 306 ptree_gen(0, &kernel_symtab); 307 #endif 308 309 } 310 311 /* 312 * Add a symbol table. 313 * This is intended for use when the symbol table and its corresponding 314 * string table are easily available. If they are embedded in an ELF 315 * image, use addsymtab_elf() instead. 316 * 317 * name - Symbol's table name. 318 * symstart, symsize - Address and size of the symbol table. 319 * strstart, strsize - Address and size of the string table. 320 * tab - Symbol table to be updated with this information. 321 * newstart - Address to which the symbol table has to be copied during 322 * shrinking. If NULL, it is not moved. 323 */ 324 static void 325 addsymtab(const char *name, 326 void *symstart, size_t symsize, 327 void *strstart, size_t strsize, 328 struct symtab *tab, 329 void *newstart) 330 { 331 void *send; 332 Elf_Sym *sym, *nsym; 333 int i, n, g; 334 char *str; 335 336 if (newstart == NULL) 337 newstart = symstart; 338 KASSERT(newstart <= symstart && symstart <= strstart); 339 340 tab->sd_symstart = (Elf_Sym *)symstart; 341 tab->sd_symsize = symsize; 342 tab->sd_strstart = strstart; 343 tab->sd_strsize = strsize; 344 tab->sd_name = name; 345 send = tab->sd_strstart + tab->sd_strsize; 346 347 #ifdef KSYMS_DEBUG 348 printf("newstart %p sym %p symsz %d str %p strsz %d send %p\n", 349 newstart, symstart, symsize, strstart, strsize, send); 350 #endif 351 352 /* 353 * Pack symbol table by removing all file name references 354 * and overwrite the elf header. 355 */ 356 sym = tab->sd_symstart; 357 nsym = (Elf_Sym *)newstart; 358 str = tab->sd_strstart; 359 for (g = i = n = 0; i < tab->sd_symsize/sizeof(Elf_Sym); i++) { 360 if (i == 0) { 361 nsym[n++] = sym[i]; 362 continue; 363 } 364 /* 365 * Remove useless symbols. 366 * Should actually remove all typeless symbols. 367 */ 368 if (sym[i].st_name == 0) 369 continue; /* Skip nameless entries */ 370 if (sym[i].st_shndx == SHN_UNDEF) 371 continue; /* Skip external references */ 372 if (ELF_ST_TYPE(sym[i].st_info) == STT_FILE) 373 continue; /* Skip filenames */ 374 if (ELF_ST_TYPE(sym[i].st_info) == STT_NOTYPE && 375 sym[i].st_value == 0 && 376 strcmp(str + sym[i].st_name, "*ABS*") == 0) 377 continue; /* XXX */ 378 if (ELF_ST_TYPE(sym[i].st_info) == STT_NOTYPE && 379 strcmp(str + sym[i].st_name, "gcc2_compiled.") == 0) 380 continue; /* XXX */ 381 382 #ifndef DDB 383 /* Only need global symbols */ 384 if (ELF_ST_BIND(sym[i].st_info) != STB_GLOBAL) 385 continue; 386 #endif 387 388 /* Save symbol. Set it as an absolute offset */ 389 nsym[n] = sym[i]; 390 nsym[n].st_shndx = SHN_ABS; 391 if (ELF_ST_BIND(nsym[n].st_info) == STB_GLOBAL) 392 g++; 393 #if NKSYMS 394 { 395 int j; 396 j = strlen(nsym[n].st_name + tab->sd_strstart) + 1; 397 if (j > ksyms_maxlen) 398 ksyms_maxlen = j; 399 } 400 #endif 401 n++; 402 403 } 404 tab->sd_symstart = nsym; 405 tab->sd_symsize = n * sizeof(Elf_Sym); 406 407 #ifdef notyet 408 /* 409 * Remove left-over strings. 410 */ 411 sym = tab->sd_symstart; 412 str = (void *)tab->sd_symstart + tab->sd_symsize; 413 str[0] = 0; 414 n = 1; 415 for (i = 1; i < tab->sd_symsize/sizeof(Elf_Sym); i++) { 416 strcpy(str + n, tab->sd_strstart + sym[i].st_name); 417 sym[i].st_name = n; 418 n += strlen(str+n) + 1; 419 } 420 tab->sd_strstart = str; 421 tab->sd_strsize = n; 422 423 #ifdef KSYMS_DEBUG 424 printf("str %p strsz %d send %p\n", str, n, send); 425 #endif 426 #endif 427 428 CIRCLEQ_INSERT_HEAD(&symtab_queue, tab, sd_queue); 429 430 #ifdef notyet 431 #ifdef USE_PTREE 432 /* Try to use the freed space, if possible */ 433 if (send - str - n > g * sizeof(struct ptree)) 434 ptree_gen(str + n, tab); 435 #endif 436 #endif 437 } 438 439 /* 440 * Add a symbol table named name. 441 * This is intended for use when the kernel loader enters the table. 442 */ 443 static void 444 addsymtab_elf(const char *name, Elf_Ehdr *ehdr, struct symtab *tab) 445 { 446 int i, j; 447 char *start = (char *)ehdr; 448 Elf_Shdr *shdr; 449 char *symstart = NULL, *strstart = NULL; 450 size_t symsize = 0, strsize = 0; 451 452 /* Find the symbol table and the corresponding string table. */ 453 shdr = (Elf_Shdr *)(start + ehdr->e_shoff); 454 for (i = 1; i < ehdr->e_shnum; i++) { 455 if (shdr[i].sh_type != SHT_SYMTAB) 456 continue; 457 if (shdr[i].sh_offset == 0) 458 continue; 459 symstart = start + shdr[i].sh_offset; 460 symsize = shdr[i].sh_size; 461 j = shdr[i].sh_link; 462 if (shdr[j].sh_offset == 0) 463 continue; /* Can this happen? */ 464 strstart = start + shdr[j].sh_offset; 465 strsize = shdr[j].sh_size; 466 break; 467 } 468 469 if (!ksyms_verify(symstart, strstart)) 470 return; 471 472 addsymtab(name, symstart, symsize, strstart, strsize, tab, start); 473 } 474 475 /* 476 * Setup the kernel symbol table stuff. 477 */ 478 void 479 ksyms_init(int symsize, void *start, void *end) 480 { 481 Elf_Ehdr *ehdr; 482 483 #ifdef SYMTAB_SPACE 484 if (symsize <= 0 && 485 strncmp(db_symtab, SYMTAB_FILLER, sizeof(SYMTAB_FILLER))) { 486 symsize = db_symtabsize; 487 start = db_symtab; 488 end = db_symtab + db_symtabsize; 489 } 490 #endif 491 if (symsize <= 0) { 492 printf("[ Kernel symbol table missing! ]\n"); 493 return; 494 } 495 496 /* Sanity check */ 497 if (ALIGNED_POINTER(start, long) == 0) { 498 printf("[ Kernel symbol table has bad start address %p ]\n", 499 start); 500 return; 501 } 502 503 ehdr = (Elf_Ehdr *)start; 504 505 /* check if this is a valid ELF header */ 506 /* No reason to verify arch type, the kernel is actually running! */ 507 if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) || 508 ehdr->e_ident[EI_CLASS] != ELFCLASS || 509 ehdr->e_version > 1) { 510 #ifdef notyet /* DDB */ 511 if (ddb_init(symsize, start, end)) 512 return; /* old-style symbol table */ 513 #endif 514 printf("[ Kernel symbol table invalid! ]\n"); 515 return; /* nothing to do */ 516 } 517 518 #if NKSYMS 519 /* Loaded header will be scratched in addsymtab */ 520 ksyms_hdr_init(start); 521 #endif 522 523 addsymtab_elf("netbsd", ehdr, &kernel_symtab); 524 525 #if NKSYMS 526 ksyms_sizes_calc(); 527 #endif 528 529 ksymsinited = 1; 530 531 #ifdef DEBUG 532 printf("Loaded initial symtab at %p, strtab at %p, # entries %ld\n", 533 kernel_symtab.sd_symstart, kernel_symtab.sd_strstart, 534 (long)kernel_symtab.sd_symsize/sizeof(Elf_Sym)); 535 #endif 536 } 537 538 /* 539 * Setup the kernel symbol table stuff. 540 * Use this when the address of the symbol and string tables are known; 541 * otherwise use ksyms_init with an ELF image. 542 * We need to pass a minimal ELF header which will later be completed by 543 * ksyms_hdr_init and handed off to userland through /dev/ksyms. We use 544 * a void *rather than a pointer to avoid exposing the Elf_Ehdr type. 545 */ 546 void 547 ksyms_init_explicit(void *ehdr, void *symstart, size_t symsize, 548 void *strstart, size_t strsize) 549 { 550 551 if (!ksyms_verify(symstart, strstart)) 552 return; 553 554 #if NKSYMS 555 ksyms_hdr_init(ehdr); 556 #endif 557 558 addsymtab("netbsd", symstart, symsize, strstart, strsize, 559 &kernel_symtab, NULL); 560 561 #if NKSYMS 562 ksyms_sizes_calc(); 563 #endif 564 565 ksymsinited = 1; 566 } 567 568 /* 569 * Get the value associated with a symbol. 570 * "mod" is the module name, or null if any module. 571 * "sym" is the symbol name. 572 * "val" is a pointer to the corresponding value, if call succeeded. 573 * Returns 0 if success or ENOENT if no such entry. 574 */ 575 int 576 ksyms_getval(const char *mod, const char *sym, unsigned long *val, int type) 577 { 578 struct symtab *st; 579 Elf_Sym *es; 580 581 if (ksymsinited == 0) 582 return ENOENT; 583 584 #ifdef KSYMS_DEBUG 585 if (ksyms_debug & FOLLOW_CALLS) 586 printf("ksyms_getval: mod %s sym %s valp %p\n", mod, sym, val); 587 #endif 588 589 CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) { 590 if (mod && strcmp(st->sd_name, mod)) 591 continue; 592 if ((es = findsym(sym, st)) == NULL) 593 continue; 594 if (es->st_shndx == SHN_UNDEF) 595 continue; 596 597 /* Skip if bad binding */ 598 if (type == KSYMS_EXTERN && 599 ELF_ST_BIND(es->st_info) != STB_GLOBAL) 600 continue; 601 602 if (val) 603 *val = es->st_value; 604 return 0; 605 } 606 return ENOENT; 607 } 608 609 /* 610 * Get "mod" and "symbol" associated with an address. 611 * Returns 0 if success or ENOENT if no such entry. 612 */ 613 int 614 ksyms_getname(const char **mod, const char **sym, vaddr_t v, int f) 615 { 616 struct symtab *st; 617 Elf_Sym *les, *es = NULL; 618 vaddr_t laddr = 0; 619 const char *lmod = NULL; 620 char *stable = NULL; 621 int type, i, sz; 622 623 if (ksymsinited == 0) 624 return ENOENT; 625 626 CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) { 627 sz = st->sd_symsize/sizeof(Elf_Sym); 628 for (i = 0; i < sz; i++) { 629 les = st->sd_symstart + i; 630 type = ELF_ST_TYPE(les->st_info); 631 632 if ((f & KSYMS_PROC) && (type != STT_FUNC)) 633 continue; 634 635 if (type == STT_NOTYPE) 636 continue; 637 638 if (((f & KSYMS_ANY) == 0) && 639 (type != STT_FUNC) && (type != STT_OBJECT)) 640 continue; 641 642 if ((les->st_value <= v) && (les->st_value > laddr)) { 643 laddr = les->st_value; 644 es = les; 645 lmod = st->sd_name; 646 stable = st->sd_strstart - st->sd_usroffset; 647 } 648 } 649 } 650 if (es == NULL) 651 return ENOENT; 652 if ((f & KSYMS_EXACT) && (v != es->st_value)) 653 return ENOENT; 654 if (mod) 655 *mod = lmod; 656 if (sym) 657 *sym = stable + es->st_name; 658 return 0; 659 } 660 661 #if NKSYMS 662 static int symsz, strsz; 663 664 /* 665 * In case we exposing the symbol table to the userland using the pseudo- 666 * device /dev/ksyms, it is easier to provide all the tables as one. 667 * However, it means we have to change all the st_name fields for the 668 * symbols so they match the ELF image that the userland will read 669 * through the device. 670 * 671 * The actual (correct) value of st_name is preserved through a global 672 * offset stored in the symbol table structure. 673 */ 674 675 static void 676 ksyms_sizes_calc(void) 677 { 678 struct symtab *st; 679 int i; 680 681 symsz = strsz = 0; 682 CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) { 683 if (st != &kernel_symtab) { 684 for (i = 0; i < st->sd_symsize/sizeof(Elf_Sym); i++) 685 st->sd_symstart[i].st_name = 686 strsz + st->sd_symnmoff[i]; 687 st->sd_usroffset = strsz; 688 } 689 symsz += st->sd_symsize; 690 strsz += st->sd_strsize; 691 } 692 } 693 #endif /* NKSYMS */ 694 695 /* 696 * Temporary work structure for dynamic loaded symbol tables. 697 * Will go away when in-kernel linker is in place. 698 */ 699 700 struct syminfo { 701 size_t cursyms; 702 size_t curnamep; 703 size_t maxsyms; 704 size_t maxnamep; 705 Elf_Sym *syms; 706 int *symnmoff; 707 char *symnames; 708 }; 709 710 711 /* 712 * Add a symbol to the temporary save area for symbols. 713 * This routine will go away when the in-kernel linker is in place. 714 */ 715 static void 716 addsym(struct syminfo *info, const Elf_Sym *sym, const char *name, 717 const char *mod) 718 { 719 int len, mlen; 720 721 #ifdef KSYMS_DEBUG 722 if (ksyms_debug & FOLLOW_MORE_CALLS) 723 printf("addsym: name %s val %lx\n", name, (long)sym->st_value); 724 #endif 725 len = strlen(name) + 1; 726 if (mod) 727 mlen = 1 + strlen(mod); 728 else 729 mlen = 0; 730 if (info->cursyms == info->maxsyms || 731 (len + mlen + info->curnamep) > info->maxnamep) { 732 printf("addsym: too many symbols, skipping '%s'\n", name); 733 return; 734 } 735 strlcpy(&info->symnames[info->curnamep], name, 736 info->maxnamep - info->curnamep); 737 if (mlen) { 738 info->symnames[info->curnamep + len - 1] = '.'; 739 strlcpy(&info->symnames[info->curnamep + len], mod, 740 info->maxnamep - (info->curnamep + len)); 741 len += mlen; 742 } 743 info->syms[info->cursyms] = *sym; 744 info->syms[info->cursyms].st_name = info->curnamep; 745 info->symnmoff[info->cursyms] = info->curnamep; 746 info->curnamep += len; 747 #if NKSYMS 748 if (len > ksyms_maxlen) 749 ksyms_maxlen = len; 750 #endif 751 info->cursyms++; 752 } 753 /* 754 * Adds a symbol table. 755 * "name" is the module name, "start" and "size" is where the symbol table 756 * is located, and "type" is in which binary format the symbol table is. 757 * New memory for keeping the symbol table is allocated in this function. 758 * Returns 0 if success and EEXIST if the module name is in use. 759 */ 760 static int 761 specialsym(const char *symname) 762 { 763 return !strcmp(symname, "_bss_start") || 764 !strcmp(symname, "__bss_start") || 765 !strcmp(symname, "_bss_end__") || 766 !strcmp(symname, "__bss_end__") || 767 !strcmp(symname, "_edata") || 768 !strcmp(symname, "_end") || 769 !strcmp(symname, "__end") || 770 !strcmp(symname, "__end__") || 771 !strncmp(symname, "__start_link_set_", 17) || 772 !strncmp(symname, "__stop_link_set_", 16); 773 } 774 775 int 776 ksyms_addsymtab(const char *mod, void *symstart, vsize_t symsize, 777 char *strstart, vsize_t strsize) 778 { 779 Elf_Sym *sym = symstart; 780 struct symtab *st; 781 unsigned long rval; 782 int i; 783 char *name; 784 struct syminfo info; 785 786 #ifdef KSYMS_DEBUG 787 if (ksyms_debug & FOLLOW_CALLS) 788 printf("ksyms_addsymtab: mod %s symsize %lx strsize %lx\n", 789 mod, symsize, strsize); 790 #endif 791 792 #if NKSYMS 793 /* 794 * Do not try to add a symbol table while someone is reading 795 * from /dev/ksyms. 796 */ 797 while (ksyms_isopen != 0) 798 tsleep(&ksyms_isopen, PWAIT, "ksyms", 0); 799 #endif 800 801 /* Check if this symtab already loaded */ 802 CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) { 803 if (strcmp(mod, st->sd_name) == 0) 804 return EEXIST; 805 } 806 807 /* 808 * XXX - Only add a symbol if it do not exist already. 809 * This is because of a flaw in the current LKM implementation, 810 * these loops will be removed once the in-kernel linker is in place. 811 */ 812 memset(&info, 0, sizeof(info)); 813 for (i = 0; i < symsize/sizeof(Elf_Sym); i++) { 814 char * const symname = strstart + sym[i].st_name; 815 if (sym[i].st_name == 0) 816 continue; /* Just ignore */ 817 818 /* check validity of the symbol */ 819 /* XXX - save local symbols if DDB */ 820 if (ELF_ST_BIND(sym[i].st_info) != STB_GLOBAL) 821 continue; 822 823 /* Check if the symbol exists */ 824 if (ksyms_getval(NULL, symname, &rval, KSYMS_EXTERN) == 0) { 825 /* Check (and complain) about differing values */ 826 if (sym[i].st_value != rval && 827 sym[i].st_shndx != SHN_UNDEF) { 828 if (specialsym(symname)) { 829 info.maxsyms++; 830 info.maxnamep += strlen(symname) + 1 + 831 strlen(mod) + 1; 832 } else { 833 printf("%s: symbol '%s' redeclared with" 834 " different value (%lx != %lx)\n", 835 mod, symname, 836 rval, (long)sym[i].st_value); 837 } 838 } 839 } else { 840 /* 841 * Count this symbol 842 */ 843 info.maxsyms++; 844 info.maxnamep += strlen(symname) + 1; 845 } 846 } 847 848 /* 849 * Now that we know the sizes, malloc the structures. 850 */ 851 info.syms = malloc(sizeof(Elf_Sym)*info.maxsyms, M_DEVBUF, M_WAITOK); 852 info.symnames = malloc(info.maxnamep, M_DEVBUF, M_WAITOK); 853 info.symnmoff = malloc(sizeof(int)*info.maxsyms, M_DEVBUF, M_WAITOK); 854 855 /* 856 * Now that we have the symbols, actually fill in the structures. 857 */ 858 for (i = 0; i < symsize/sizeof(Elf_Sym); i++) { 859 char * const symname = strstart + sym[i].st_name; 860 if (sym[i].st_name == 0) 861 continue; /* Just ignore */ 862 863 /* check validity of the symbol */ 864 /* XXX - save local symbols if DDB */ 865 if (ELF_ST_BIND(sym[i].st_info) != STB_GLOBAL) 866 continue; 867 868 /* Check if the symbol exists */ 869 if (ksyms_getval(NULL, symname, &rval, KSYMS_EXTERN) == 0) { 870 if ((sym[i].st_value != rval) && specialsym(symname)) { 871 addsym(&info, &sym[i], symname, mod); 872 } 873 } else 874 /* Ok, save this symbol */ 875 addsym(&info, &sym[i], symname, NULL); 876 } 877 878 st = malloc(sizeof(struct symtab), M_DEVBUF, M_WAITOK); 879 i = strlen(mod) + 1; 880 name = malloc(i, M_DEVBUF, M_WAITOK); 881 strlcpy(name, mod, i); 882 st->sd_name = name; 883 st->sd_symnmoff = info.symnmoff; 884 st->sd_symstart = info.syms; 885 st->sd_symsize = sizeof(Elf_Sym)*info.maxsyms; 886 st->sd_strstart = info.symnames; 887 st->sd_strsize = info.maxnamep; 888 889 /* Make them absolute references */ 890 sym = st->sd_symstart; 891 for (i = 0; i < st->sd_symsize/sizeof(Elf_Sym); i++) 892 sym[i].st_shndx = SHN_ABS; 893 894 CIRCLEQ_INSERT_TAIL(&symtab_queue, st, sd_queue); 895 #if NKSYMS 896 ksyms_sizes_calc(); 897 #endif 898 return 0; 899 } 900 901 /* 902 * Remove a symbol table specified by name. 903 * Returns 0 if success, EBUSY if device open and ENOENT if no such name. 904 */ 905 int 906 ksyms_delsymtab(const char *mod) 907 { 908 struct symtab *st; 909 int found = 0; 910 911 #if NKSYMS 912 /* 913 * Do not try to delete a symbol table while someone is reading 914 * from /dev/ksyms. 915 */ 916 while (ksyms_isopen != 0) 917 tsleep(&ksyms_isopen, PWAIT, "ksyms", 0); 918 #endif 919 920 CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) { 921 if (strcmp(mod, st->sd_name) == 0) { 922 found = 1; 923 break; 924 } 925 } 926 if (found == 0) 927 return ENOENT; 928 CIRCLEQ_REMOVE(&symtab_queue, st, sd_queue); 929 free(st->sd_symstart, M_DEVBUF); 930 free(st->sd_strstart, M_DEVBUF); 931 free(st->sd_symnmoff, M_DEVBUF); 932 /* XXXUNCONST LINTED - const castaway */ 933 free(__UNCONST(st->sd_name), M_DEVBUF); 934 free(st, M_DEVBUF); 935 #if NKSYMS 936 ksyms_sizes_calc(); 937 #endif 938 return 0; 939 } 940 941 int 942 ksyms_rensymtab(const char *old, const char *new) 943 { 944 struct symtab *st, *oldst = NULL; 945 char *newstr; 946 947 CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) { 948 if (strcmp(old, st->sd_name) == 0) 949 oldst = st; 950 if (strcmp(new, st->sd_name) == 0) 951 return (EEXIST); 952 } 953 if (oldst == NULL) 954 return (ENOENT); 955 956 newstr = malloc(strlen(new)+1, M_DEVBUF, M_WAITOK); 957 if (!newstr) 958 return (ENOMEM); 959 strcpy(newstr, new); 960 /*XXXUNCONST*/ 961 free(__UNCONST(oldst->sd_name), M_DEVBUF); 962 oldst->sd_name = newstr; 963 964 return (0); 965 } 966 967 #ifdef DDB 968 /* 969 * Keep sifting stuff here, to avoid export of ksyms internals. 970 */ 971 int 972 ksyms_sift(char *mod, char *sym, int mode) 973 { 974 struct symtab *st; 975 char *sb; 976 int i, sz; 977 978 if (ksymsinited == 0) 979 return ENOENT; 980 981 CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) { 982 if (mod && strcmp(mod, st->sd_name)) 983 continue; 984 sb = st->sd_strstart; 985 986 sz = st->sd_symsize/sizeof(Elf_Sym); 987 for (i = 0; i < sz; i++) { 988 Elf_Sym *les = st->sd_symstart + i; 989 char c; 990 991 if (strstr(sb + les->st_name - st->sd_usroffset, sym) 992 == NULL) 993 continue; 994 995 if (mode == 'F') { 996 switch (ELF_ST_TYPE(les->st_info)) { 997 case STT_OBJECT: 998 c = '+'; 999 break; 1000 case STT_FUNC: 1001 c = '*'; 1002 break; 1003 case STT_SECTION: 1004 c = '&'; 1005 break; 1006 case STT_FILE: 1007 c = '/'; 1008 break; 1009 default: 1010 c = ' '; 1011 break; 1012 } 1013 db_printf("%s%c ", sb + les->st_name - 1014 st->sd_usroffset, c); 1015 } else 1016 db_printf("%s ", sb + les->st_name - 1017 st->sd_usroffset); 1018 } 1019 } 1020 return ENOENT; 1021 } 1022 #endif /* DDB */ 1023 1024 #if NKSYMS 1025 /* 1026 * Static allocated ELF header. 1027 * Basic info is filled in at attach, sizes at open. 1028 */ 1029 #define SYMTAB 1 1030 #define STRTAB 2 1031 #define SHSTRTAB 3 1032 #define NSECHDR 4 1033 1034 #define NPRGHDR 2 1035 #define SHSTRSIZ 28 1036 1037 static struct ksyms_hdr { 1038 Elf_Ehdr kh_ehdr; 1039 Elf_Phdr kh_phdr[NPRGHDR]; 1040 Elf_Shdr kh_shdr[NSECHDR]; 1041 char kh_strtab[SHSTRSIZ]; 1042 } ksyms_hdr; 1043 1044 1045 static void 1046 ksyms_hdr_init(void *hdraddr) 1047 { 1048 1049 /* Copy the loaded elf exec header */ 1050 memcpy(&ksyms_hdr.kh_ehdr, hdraddr, sizeof(Elf_Ehdr)); 1051 1052 /* Set correct program/section header sizes, offsets and numbers */ 1053 ksyms_hdr.kh_ehdr.e_phoff = offsetof(struct ksyms_hdr, kh_phdr[0]); 1054 ksyms_hdr.kh_ehdr.e_phentsize = sizeof(Elf_Phdr); 1055 ksyms_hdr.kh_ehdr.e_phnum = NPRGHDR; 1056 ksyms_hdr.kh_ehdr.e_shoff = offsetof(struct ksyms_hdr, kh_shdr[0]); 1057 ksyms_hdr.kh_ehdr.e_shentsize = sizeof(Elf_Shdr); 1058 ksyms_hdr.kh_ehdr.e_shnum = NSECHDR; 1059 ksyms_hdr.kh_ehdr.e_shstrndx = NSECHDR - 1; /* Last section */ 1060 1061 /* 1062 * Keep program headers zeroed (unused). 1063 * The section headers are hand-crafted. 1064 * First section is section zero. 1065 */ 1066 1067 /* Second section header; ".symtab" */ 1068 ksyms_hdr.kh_shdr[SYMTAB].sh_name = 1; /* Section 3 offset */ 1069 ksyms_hdr.kh_shdr[SYMTAB].sh_type = SHT_SYMTAB; 1070 ksyms_hdr.kh_shdr[SYMTAB].sh_offset = sizeof(struct ksyms_hdr); 1071 /* ksyms_hdr.kh_shdr[SYMTAB].sh_size = filled in at open */ 1072 ksyms_hdr.kh_shdr[SYMTAB].sh_link = 2; /* Corresponding strtab */ 1073 ksyms_hdr.kh_shdr[SYMTAB].sh_info = 0; /* XXX */ 1074 ksyms_hdr.kh_shdr[SYMTAB].sh_addralign = sizeof(long); 1075 ksyms_hdr.kh_shdr[SYMTAB].sh_entsize = sizeof(Elf_Sym); 1076 1077 /* Third section header; ".strtab" */ 1078 ksyms_hdr.kh_shdr[STRTAB].sh_name = 9; /* Section 3 offset */ 1079 ksyms_hdr.kh_shdr[STRTAB].sh_type = SHT_STRTAB; 1080 /* ksyms_hdr.kh_shdr[STRTAB].sh_offset = filled in at open */ 1081 /* ksyms_hdr.kh_shdr[STRTAB].sh_size = filled in at open */ 1082 /* ksyms_hdr.kh_shdr[STRTAB].sh_link = kept zero */ 1083 ksyms_hdr.kh_shdr[STRTAB].sh_info = 0; 1084 ksyms_hdr.kh_shdr[STRTAB].sh_addralign = sizeof(char); 1085 ksyms_hdr.kh_shdr[STRTAB].sh_entsize = 0; 1086 1087 /* Fourth section, ".shstrtab" */ 1088 ksyms_hdr.kh_shdr[SHSTRTAB].sh_name = 17; /* This section name offset */ 1089 ksyms_hdr.kh_shdr[SHSTRTAB].sh_type = SHT_STRTAB; 1090 ksyms_hdr.kh_shdr[SHSTRTAB].sh_offset = 1091 offsetof(struct ksyms_hdr, kh_strtab); 1092 ksyms_hdr.kh_shdr[SHSTRTAB].sh_size = SHSTRSIZ; 1093 ksyms_hdr.kh_shdr[SHSTRTAB].sh_addralign = sizeof(char); 1094 1095 /* Set section names */ 1096 strlcpy(&ksyms_hdr.kh_strtab[1], ".symtab", 1097 sizeof(ksyms_hdr.kh_strtab) - 1); 1098 strlcpy(&ksyms_hdr.kh_strtab[9], ".strtab", 1099 sizeof(ksyms_hdr.kh_strtab) - 9); 1100 strlcpy(&ksyms_hdr.kh_strtab[17], ".shstrtab", 1101 sizeof(ksyms_hdr.kh_strtab) - 17); 1102 }; 1103 1104 static int 1105 ksymsopen(dev_t dev, int oflags, int devtype, struct lwp *l) 1106 { 1107 1108 if (minor(dev)) 1109 return ENXIO; 1110 if (ksymsinited == 0) 1111 return ENXIO; 1112 1113 ksyms_hdr.kh_shdr[SYMTAB].sh_size = symsz; 1114 ksyms_hdr.kh_shdr[STRTAB].sh_offset = symsz + 1115 ksyms_hdr.kh_shdr[SYMTAB].sh_offset; 1116 ksyms_hdr.kh_shdr[STRTAB].sh_size = strsz; 1117 ksyms_isopen = 1; 1118 1119 #ifdef KSYMS_DEBUG 1120 if (ksyms_debug & FOLLOW_DEVKSYMS) 1121 printf("ksymsopen: symsz 0x%x strsz 0x%x\n", symsz, strsz); 1122 #endif 1123 1124 return 0; 1125 } 1126 1127 static int 1128 ksymsclose(dev_t dev, int oflags, int devtype, struct lwp *l) 1129 { 1130 1131 #ifdef KSYMS_DEBUG 1132 if (ksyms_debug & FOLLOW_DEVKSYMS) 1133 printf("ksymsclose\n"); 1134 #endif 1135 1136 ksyms_isopen = 0; 1137 wakeup(&ksyms_isopen); 1138 return 0; 1139 } 1140 1141 #define HDRSIZ sizeof(struct ksyms_hdr) 1142 1143 static int 1144 ksymsread(dev_t dev, struct uio *uio, int ioflag) 1145 { 1146 struct symtab *st; 1147 size_t filepos, inpos, off; 1148 1149 #ifdef KSYMS_DEBUG 1150 if (ksyms_debug & FOLLOW_DEVKSYMS) 1151 printf("ksymsread: offset 0x%llx resid 0x%zx\n", 1152 (long long)uio->uio_offset, uio->uio_resid); 1153 #endif 1154 1155 off = uio->uio_offset; 1156 if (off >= (strsz + symsz + HDRSIZ)) 1157 return 0; /* End of symtab */ 1158 /* 1159 * First: Copy out the ELF header. 1160 */ 1161 if (off < HDRSIZ) 1162 uiomove((char *)&ksyms_hdr + off, HDRSIZ - off, uio); 1163 1164 /* 1165 * Copy out the symbol table. 1166 */ 1167 filepos = HDRSIZ; 1168 CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) { 1169 if (uio->uio_resid == 0) 1170 return 0; 1171 if (uio->uio_offset <= st->sd_symsize + filepos) { 1172 inpos = uio->uio_offset - filepos; 1173 uiomove((char *)st->sd_symstart + inpos, 1174 st->sd_symsize - inpos, uio); 1175 } 1176 filepos += st->sd_symsize; 1177 } 1178 1179 if (filepos != HDRSIZ + symsz) 1180 panic("ksymsread: unsunc"); 1181 1182 /* 1183 * Copy out the string table 1184 */ 1185 CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) { 1186 if (uio->uio_resid == 0) 1187 return 0; 1188 if (uio->uio_offset <= st->sd_strsize + filepos) { 1189 inpos = uio->uio_offset - filepos; 1190 uiomove((char *)st->sd_strstart + inpos, 1191 st->sd_strsize - inpos, uio); 1192 } 1193 filepos += st->sd_strsize; 1194 } 1195 return 0; 1196 } 1197 1198 static int 1199 ksymswrite(dev_t dev, struct uio *uio, int ioflag) 1200 { 1201 1202 return EROFS; 1203 } 1204 1205 static int 1206 ksymsioctl(dev_t dev, u_long cmd, void *data, int fflag, struct lwp *l) 1207 { 1208 struct ksyms_gsymbol *kg = (struct ksyms_gsymbol *)data; 1209 struct symtab *st; 1210 Elf_Sym *sym = NULL; 1211 unsigned long val; 1212 int error = 0; 1213 char *str = NULL; 1214 1215 if (cmd == KIOCGVALUE || cmd == KIOCGSYMBOL) 1216 str = malloc(ksyms_maxlen, M_DEVBUF, M_WAITOK); 1217 1218 switch (cmd) { 1219 case KIOCGVALUE: 1220 /* 1221 * Use the in-kernel symbol lookup code for fast 1222 * retreival of a value. 1223 */ 1224 if ((error = copyinstr(kg->kg_name, str, ksyms_maxlen, NULL))) 1225 break; 1226 if ((error = ksyms_getval(NULL, str, &val, KSYMS_EXTERN))) 1227 break; 1228 error = copyout(&val, kg->kg_value, sizeof(long)); 1229 break; 1230 1231 case KIOCGSYMBOL: 1232 /* 1233 * Use the in-kernel symbol lookup code for fast 1234 * retreival of a symbol. 1235 */ 1236 if ((error = copyinstr(kg->kg_name, str, ksyms_maxlen, NULL))) 1237 break; 1238 CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) { 1239 if ((sym = findsym(str, st)) == NULL) /* from userland */ 1240 continue; 1241 1242 /* Skip if bad binding */ 1243 if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL) { 1244 sym = NULL; 1245 continue; 1246 } 1247 break; 1248 } 1249 /* 1250 * XXX which value of sym->st_name should be returned? The real 1251 * one, or the one that matches what reading /dev/ksyms get? 1252 * 1253 * Currently, we're returning the /dev/ksyms one. 1254 */ 1255 if (sym != NULL) 1256 error = copyout(sym, kg->kg_sym, sizeof(Elf_Sym)); 1257 else 1258 error = ENOENT; 1259 break; 1260 1261 case KIOCGSIZE: 1262 /* 1263 * Get total size of symbol table. 1264 */ 1265 *(int *)data = strsz + symsz + HDRSIZ; 1266 break; 1267 1268 default: 1269 error = ENOTTY; 1270 break; 1271 } 1272 1273 if (cmd == KIOCGVALUE || cmd == KIOCGSYMBOL) 1274 free(str, M_DEVBUF); 1275 1276 return error; 1277 } 1278 1279 const struct cdevsw ksyms_cdevsw = { 1280 ksymsopen, ksymsclose, ksymsread, ksymswrite, ksymsioctl, 1281 nullstop, notty, nopoll, nommap, nullkqfilter, DV_DULL 1282 }; 1283 #endif /* NKSYMS */ 1284