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.33 2007/04/02 16:44:44 christos 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 (ELF_ST_TYPE(sym[i].st_info) == STT_FILE) 371 continue; /* Skip filenames */ 372 if (ELF_ST_TYPE(sym[i].st_info) == STT_NOTYPE && 373 sym[i].st_value == 0 && 374 strcmp(str + sym[i].st_name, "*ABS*") == 0) 375 continue; /* XXX */ 376 if (ELF_ST_TYPE(sym[i].st_info) == STT_NOTYPE && 377 strcmp(str + sym[i].st_name, "gcc2_compiled.") == 0) 378 continue; /* XXX */ 379 380 #ifndef DDB 381 /* Only need global symbols */ 382 if (ELF_ST_BIND(sym[i].st_info) != STB_GLOBAL) 383 continue; 384 #endif 385 386 /* Save symbol. Set it as an absolute offset */ 387 nsym[n] = sym[i]; 388 nsym[n].st_shndx = SHN_ABS; 389 if (ELF_ST_BIND(nsym[n].st_info) == STB_GLOBAL) 390 g++; 391 #if NKSYMS 392 { 393 int j; 394 j = strlen(nsym[n].st_name + tab->sd_strstart) + 1; 395 if (j > ksyms_maxlen) 396 ksyms_maxlen = j; 397 } 398 #endif 399 n++; 400 401 } 402 tab->sd_symstart = nsym; 403 tab->sd_symsize = n * sizeof(Elf_Sym); 404 405 #ifdef notyet 406 /* 407 * Remove left-over strings. 408 */ 409 sym = tab->sd_symstart; 410 str = (void *)tab->sd_symstart + tab->sd_symsize; 411 str[0] = 0; 412 n = 1; 413 for (i = 1; i < tab->sd_symsize/sizeof(Elf_Sym); i++) { 414 strcpy(str + n, tab->sd_strstart + sym[i].st_name); 415 sym[i].st_name = n; 416 n += strlen(str+n) + 1; 417 } 418 tab->sd_strstart = str; 419 tab->sd_strsize = n; 420 421 #ifdef KSYMS_DEBUG 422 printf("str %p strsz %d send %p\n", str, n, send); 423 #endif 424 #endif 425 426 CIRCLEQ_INSERT_HEAD(&symtab_queue, tab, sd_queue); 427 428 #ifdef notyet 429 #ifdef USE_PTREE 430 /* Try to use the freed space, if possible */ 431 if (send - str - n > g * sizeof(struct ptree)) 432 ptree_gen(str + n, tab); 433 #endif 434 #endif 435 } 436 437 /* 438 * Add a symbol table named name. 439 * This is intended for use when the kernel loader enters the table. 440 */ 441 static void 442 addsymtab_elf(const char *name, Elf_Ehdr *ehdr, struct symtab *tab) 443 { 444 int i, j; 445 char *start = (char *)ehdr; 446 Elf_Shdr *shdr; 447 char *symstart = NULL, *strstart = NULL; 448 size_t symsize = 0, strsize = 0; 449 450 /* Find the symbol table and the corresponding string table. */ 451 shdr = (Elf_Shdr *)(start + ehdr->e_shoff); 452 for (i = 1; i < ehdr->e_shnum; i++) { 453 if (shdr[i].sh_type != SHT_SYMTAB) 454 continue; 455 if (shdr[i].sh_offset == 0) 456 continue; 457 symstart = start + shdr[i].sh_offset; 458 symsize = shdr[i].sh_size; 459 j = shdr[i].sh_link; 460 if (shdr[j].sh_offset == 0) 461 continue; /* Can this happen? */ 462 strstart = start + shdr[j].sh_offset; 463 strsize = shdr[j].sh_size; 464 break; 465 } 466 467 if (!ksyms_verify(symstart, strstart)) 468 return; 469 470 addsymtab(name, symstart, symsize, strstart, strsize, tab, start); 471 } 472 473 /* 474 * Setup the kernel symbol table stuff. 475 */ 476 void 477 ksyms_init(int symsize, void *start, void *end) 478 { 479 Elf_Ehdr *ehdr; 480 481 #ifdef SYMTAB_SPACE 482 if (symsize <= 0 && 483 strncmp(db_symtab, SYMTAB_FILLER, sizeof(SYMTAB_FILLER))) { 484 symsize = db_symtabsize; 485 start = db_symtab; 486 end = db_symtab + db_symtabsize; 487 } 488 #endif 489 if (symsize <= 0) { 490 printf("[ Kernel symbol table missing! ]\n"); 491 return; 492 } 493 494 /* Sanity check */ 495 if (ALIGNED_POINTER(start, long) == 0) { 496 printf("[ Kernel symbol table has bad start address %p ]\n", 497 start); 498 return; 499 } 500 501 ehdr = (Elf_Ehdr *)start; 502 503 /* check if this is a valid ELF header */ 504 /* No reason to verify arch type, the kernel is actually running! */ 505 if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) || 506 ehdr->e_ident[EI_CLASS] != ELFCLASS || 507 ehdr->e_version > 1) { 508 #ifdef notyet /* DDB */ 509 if (ddb_init(symsize, start, end)) 510 return; /* old-style symbol table */ 511 #endif 512 printf("[ Kernel symbol table invalid! ]\n"); 513 return; /* nothing to do */ 514 } 515 516 #if NKSYMS 517 /* Loaded header will be scratched in addsymtab */ 518 ksyms_hdr_init(start); 519 #endif 520 521 addsymtab_elf("netbsd", ehdr, &kernel_symtab); 522 523 #if NKSYMS 524 ksyms_sizes_calc(); 525 #endif 526 527 ksymsinited = 1; 528 529 #ifdef DEBUG 530 printf("Loaded initial symtab at %p, strtab at %p, # entries %ld\n", 531 kernel_symtab.sd_symstart, kernel_symtab.sd_strstart, 532 (long)kernel_symtab.sd_symsize/sizeof(Elf_Sym)); 533 #endif 534 } 535 536 /* 537 * Setup the kernel symbol table stuff. 538 * Use this when the address of the symbol and string tables are known; 539 * otherwise use ksyms_init with an ELF image. 540 * We need to pass a minimal ELF header which will later be completed by 541 * ksyms_hdr_init and handed off to userland through /dev/ksyms. We use 542 * a void *rather than a pointer to avoid exposing the Elf_Ehdr type. 543 */ 544 void 545 ksyms_init_explicit(void *ehdr, void *symstart, size_t symsize, 546 void *strstart, size_t strsize) 547 { 548 549 if (!ksyms_verify(symstart, strstart)) 550 return; 551 552 #if NKSYMS 553 ksyms_hdr_init(ehdr); 554 #endif 555 556 addsymtab("netbsd", symstart, symsize, strstart, strsize, 557 &kernel_symtab, NULL); 558 559 #if NKSYMS 560 ksyms_sizes_calc(); 561 #endif 562 563 ksymsinited = 1; 564 } 565 566 /* 567 * Get the value associated with a symbol. 568 * "mod" is the module name, or null if any module. 569 * "sym" is the symbol name. 570 * "val" is a pointer to the corresponding value, if call succeeded. 571 * Returns 0 if success or ENOENT if no such entry. 572 */ 573 int 574 ksyms_getval(const char *mod, const char *sym, unsigned long *val, int type) 575 { 576 struct symtab *st; 577 Elf_Sym *es; 578 579 if (ksymsinited == 0) 580 return ENOENT; 581 582 #ifdef KSYMS_DEBUG 583 if (ksyms_debug & FOLLOW_CALLS) 584 printf("ksyms_getval: mod %s sym %s valp %p\n", mod, sym, val); 585 #endif 586 587 CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) { 588 if (mod && strcmp(st->sd_name, mod)) 589 continue; 590 if ((es = findsym(sym, st)) == NULL) 591 continue; 592 593 /* Skip if bad binding */ 594 if (type == KSYMS_EXTERN && 595 ELF_ST_BIND(es->st_info) != STB_GLOBAL) 596 continue; 597 598 if (val) 599 *val = es->st_value; 600 return 0; 601 } 602 return ENOENT; 603 } 604 605 /* 606 * Get "mod" and "symbol" associated with an address. 607 * Returns 0 if success or ENOENT if no such entry. 608 */ 609 int 610 ksyms_getname(const char **mod, const char **sym, vaddr_t v, int f) 611 { 612 struct symtab *st; 613 Elf_Sym *les, *es = NULL; 614 vaddr_t laddr = 0; 615 const char *lmod = NULL; 616 char *stable = NULL; 617 int type, i, sz; 618 619 if (ksymsinited == 0) 620 return ENOENT; 621 622 CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) { 623 sz = st->sd_symsize/sizeof(Elf_Sym); 624 for (i = 0; i < sz; i++) { 625 les = st->sd_symstart + i; 626 type = ELF_ST_TYPE(les->st_info); 627 628 if ((f & KSYMS_PROC) && (type != STT_FUNC)) 629 continue; 630 631 if (type == STT_NOTYPE) 632 continue; 633 634 if (((f & KSYMS_ANY) == 0) && 635 (type != STT_FUNC) && (type != STT_OBJECT)) 636 continue; 637 638 if ((les->st_value <= v) && (les->st_value > laddr)) { 639 laddr = les->st_value; 640 es = les; 641 lmod = st->sd_name; 642 stable = st->sd_strstart - st->sd_usroffset; 643 } 644 } 645 } 646 if (es == NULL) 647 return ENOENT; 648 if ((f & KSYMS_EXACT) && (v != es->st_value)) 649 return ENOENT; 650 if (mod) 651 *mod = lmod; 652 if (sym) 653 *sym = stable + es->st_name; 654 return 0; 655 } 656 657 #if NKSYMS 658 static int symsz, strsz; 659 660 /* 661 * In case we exposing the symbol table to the userland using the pseudo- 662 * device /dev/ksyms, it is easier to provide all the tables as one. 663 * However, it means we have to change all the st_name fields for the 664 * symbols so they match the ELF image that the userland will read 665 * through the device. 666 * 667 * The actual (correct) value of st_name is preserved through a global 668 * offset stored in the symbol table structure. 669 */ 670 671 static void 672 ksyms_sizes_calc(void) 673 { 674 struct symtab *st; 675 int i; 676 677 symsz = strsz = 0; 678 CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) { 679 if (st != &kernel_symtab) { 680 for (i = 0; i < st->sd_symsize/sizeof(Elf_Sym); i++) 681 st->sd_symstart[i].st_name = 682 strsz + st->sd_symnmoff[i]; 683 st->sd_usroffset = strsz; 684 } 685 symsz += st->sd_symsize; 686 strsz += st->sd_strsize; 687 } 688 } 689 #endif /* NKSYMS */ 690 691 /* 692 * Temporary work structure for dynamic loaded symbol tables. 693 * Will go away when in-kernel linker is in place. 694 */ 695 696 struct syminfo { 697 size_t cursyms; 698 size_t curnamep; 699 size_t maxsyms; 700 size_t maxnamep; 701 Elf_Sym *syms; 702 int *symnmoff; 703 char *symnames; 704 }; 705 706 707 /* 708 * Add a symbol to the temporary save area for symbols. 709 * This routine will go away when the in-kernel linker is in place. 710 */ 711 static void 712 addsym(struct syminfo *info, const Elf_Sym *sym, const char *name, 713 const char *mod) 714 { 715 int len, mlen; 716 717 #ifdef KSYMS_DEBUG 718 if (ksyms_debug & FOLLOW_MORE_CALLS) 719 printf("addsym: name %s val %lx\n", name, (long)sym->st_value); 720 #endif 721 len = strlen(name) + 1; 722 if (mod) 723 mlen = 1 + strlen(mod); 724 else 725 mlen = 0; 726 if (info->cursyms == info->maxsyms || 727 (len + mlen + info->curnamep) > info->maxnamep) { 728 printf("addsym: too many symbols, skipping '%s'\n", name); 729 return; 730 } 731 strlcpy(&info->symnames[info->curnamep], name, 732 info->maxnamep - info->curnamep); 733 if (mlen) { 734 info->symnames[info->curnamep + len - 1] = '.'; 735 strlcpy(&info->symnames[info->curnamep + len], mod, 736 info->maxnamep - (info->curnamep + len)); 737 len += mlen; 738 } 739 info->syms[info->cursyms] = *sym; 740 info->syms[info->cursyms].st_name = info->curnamep; 741 info->symnmoff[info->cursyms] = info->curnamep; 742 info->curnamep += len; 743 #if NKSYMS 744 if (len > ksyms_maxlen) 745 ksyms_maxlen = len; 746 #endif 747 info->cursyms++; 748 } 749 /* 750 * Adds a symbol table. 751 * "name" is the module name, "start" and "size" is where the symbol table 752 * is located, and "type" is in which binary format the symbol table is. 753 * New memory for keeping the symbol table is allocated in this function. 754 * Returns 0 if success and EEXIST if the module name is in use. 755 */ 756 static int 757 specialsym(const char *symname) 758 { 759 return !strcmp(symname, "_bss_start") || 760 !strcmp(symname, "__bss_start") || 761 !strcmp(symname, "_bss_end__") || 762 !strcmp(symname, "__bss_end__") || 763 !strcmp(symname, "_edata") || 764 !strcmp(symname, "_end") || 765 !strcmp(symname, "__end") || 766 !strcmp(symname, "__end__") || 767 !strncmp(symname, "__start_link_set_", 17) || 768 !strncmp(symname, "__stop_link_set_", 16); 769 } 770 771 int 772 ksyms_addsymtab(const char *mod, void *symstart, vsize_t symsize, 773 char *strstart, vsize_t strsize) 774 { 775 Elf_Sym *sym = symstart; 776 struct symtab *st; 777 unsigned long rval; 778 int i; 779 char *name; 780 struct syminfo info; 781 782 #ifdef KSYMS_DEBUG 783 if (ksyms_debug & FOLLOW_CALLS) 784 printf("ksyms_addsymtab: mod %s symsize %lx strsize %lx\n", 785 mod, symsize, strsize); 786 #endif 787 788 #if NKSYMS 789 /* 790 * Do not try to add a symbol table while someone is reading 791 * from /dev/ksyms. 792 */ 793 while (ksyms_isopen != 0) 794 tsleep(&ksyms_isopen, PWAIT, "ksyms", 0); 795 #endif 796 797 /* Check if this symtab already loaded */ 798 CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) { 799 if (strcmp(mod, st->sd_name) == 0) 800 return EEXIST; 801 } 802 803 /* 804 * XXX - Only add a symbol if it do not exist already. 805 * This is because of a flaw in the current LKM implementation, 806 * these loops will be removed once the in-kernel linker is in place. 807 */ 808 memset(&info, 0, sizeof(info)); 809 for (i = 0; i < symsize/sizeof(Elf_Sym); i++) { 810 char * const symname = strstart + sym[i].st_name; 811 if (sym[i].st_name == 0) 812 continue; /* Just ignore */ 813 814 /* check validity of the symbol */ 815 /* XXX - save local symbols if DDB */ 816 if (ELF_ST_BIND(sym[i].st_info) != STB_GLOBAL) 817 continue; 818 819 /* Check if the symbol exists */ 820 if (ksyms_getval(NULL, symname, &rval, KSYMS_EXTERN) == 0) { 821 /* Check (and complain) about differing values */ 822 if (sym[i].st_value != rval) { 823 if (specialsym(symname)) { 824 info.maxsyms++; 825 info.maxnamep += strlen(symname) + 1 + 826 strlen(mod) + 1; 827 } else { 828 printf("%s: symbol '%s' redeclared with" 829 " different value (%lx != %lx)\n", 830 mod, symname, 831 rval, (long)sym[i].st_value); 832 } 833 } 834 } else { 835 /* 836 * Count this symbol 837 */ 838 info.maxsyms++; 839 info.maxnamep += strlen(symname) + 1; 840 } 841 } 842 843 /* 844 * Now that we know the sizes, malloc the structures. 845 */ 846 info.syms = malloc(sizeof(Elf_Sym)*info.maxsyms, M_DEVBUF, M_WAITOK); 847 info.symnames = malloc(info.maxnamep, M_DEVBUF, M_WAITOK); 848 info.symnmoff = malloc(sizeof(int)*info.maxsyms, M_DEVBUF, M_WAITOK); 849 850 /* 851 * Now that we have the symbols, actually fill in the structures. 852 */ 853 for (i = 0; i < symsize/sizeof(Elf_Sym); i++) { 854 char * const symname = strstart + sym[i].st_name; 855 if (sym[i].st_name == 0) 856 continue; /* Just ignore */ 857 858 /* check validity of the symbol */ 859 /* XXX - save local symbols if DDB */ 860 if (ELF_ST_BIND(sym[i].st_info) != STB_GLOBAL) 861 continue; 862 863 /* Check if the symbol exists */ 864 if (ksyms_getval(NULL, symname, &rval, KSYMS_EXTERN) == 0) { 865 if ((sym[i].st_value != rval) && specialsym(symname)) { 866 addsym(&info, &sym[i], symname, mod); 867 } 868 } else 869 /* Ok, save this symbol */ 870 addsym(&info, &sym[i], symname, NULL); 871 } 872 873 st = malloc(sizeof(struct symtab), M_DEVBUF, M_WAITOK); 874 i = strlen(mod) + 1; 875 name = malloc(i, M_DEVBUF, M_WAITOK); 876 strlcpy(name, mod, i); 877 st->sd_name = name; 878 st->sd_symnmoff = info.symnmoff; 879 st->sd_symstart = info.syms; 880 st->sd_symsize = sizeof(Elf_Sym)*info.maxsyms; 881 st->sd_strstart = info.symnames; 882 st->sd_strsize = info.maxnamep; 883 884 /* Make them absolute references */ 885 sym = st->sd_symstart; 886 for (i = 0; i < st->sd_symsize/sizeof(Elf_Sym); i++) 887 sym[i].st_shndx = SHN_ABS; 888 889 CIRCLEQ_INSERT_TAIL(&symtab_queue, st, sd_queue); 890 #if NKSYMS 891 ksyms_sizes_calc(); 892 #endif 893 return 0; 894 } 895 896 /* 897 * Remove a symbol table specified by name. 898 * Returns 0 if success, EBUSY if device open and ENOENT if no such name. 899 */ 900 int 901 ksyms_delsymtab(const char *mod) 902 { 903 struct symtab *st; 904 int found = 0; 905 906 #if NKSYMS 907 /* 908 * Do not try to delete a symbol table while someone is reading 909 * from /dev/ksyms. 910 */ 911 while (ksyms_isopen != 0) 912 tsleep(&ksyms_isopen, PWAIT, "ksyms", 0); 913 #endif 914 915 CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) { 916 if (strcmp(mod, st->sd_name) == 0) { 917 found = 1; 918 break; 919 } 920 } 921 if (found == 0) 922 return ENOENT; 923 CIRCLEQ_REMOVE(&symtab_queue, st, sd_queue); 924 free(st->sd_symstart, M_DEVBUF); 925 free(st->sd_strstart, M_DEVBUF); 926 free(st->sd_symnmoff, M_DEVBUF); 927 /* XXXUNCONST LINTED - const castaway */ 928 free(__UNCONST(st->sd_name), M_DEVBUF); 929 free(st, M_DEVBUF); 930 #if NKSYMS 931 ksyms_sizes_calc(); 932 #endif 933 return 0; 934 } 935 936 int 937 ksyms_rensymtab(const char *old, const char *new) 938 { 939 struct symtab *st, *oldst = NULL; 940 char *newstr; 941 942 CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) { 943 if (strcmp(old, st->sd_name) == 0) 944 oldst = st; 945 if (strcmp(new, st->sd_name) == 0) 946 return (EEXIST); 947 } 948 if (oldst == NULL) 949 return (ENOENT); 950 951 newstr = malloc(strlen(new)+1, M_DEVBUF, M_WAITOK); 952 if (!newstr) 953 return (ENOMEM); 954 strcpy(newstr, new); 955 /*XXXUNCONST*/ 956 free(__UNCONST(oldst->sd_name), M_DEVBUF); 957 oldst->sd_name = newstr; 958 959 return (0); 960 } 961 962 #ifdef DDB 963 /* 964 * Keep sifting stuff here, to avoid export of ksyms internals. 965 */ 966 int 967 ksyms_sift(char *mod, char *sym, int mode) 968 { 969 struct symtab *st; 970 char *sb; 971 int i, sz; 972 973 if (ksymsinited == 0) 974 return ENOENT; 975 976 CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) { 977 if (mod && strcmp(mod, st->sd_name)) 978 continue; 979 sb = st->sd_strstart; 980 981 sz = st->sd_symsize/sizeof(Elf_Sym); 982 for (i = 0; i < sz; i++) { 983 Elf_Sym *les = st->sd_symstart + i; 984 char c; 985 986 if (strstr(sb + les->st_name - st->sd_usroffset, sym) 987 == NULL) 988 continue; 989 990 if (mode == 'F') { 991 switch (ELF_ST_TYPE(les->st_info)) { 992 case STT_OBJECT: 993 c = '+'; 994 break; 995 case STT_FUNC: 996 c = '*'; 997 break; 998 case STT_SECTION: 999 c = '&'; 1000 break; 1001 case STT_FILE: 1002 c = '/'; 1003 break; 1004 default: 1005 c = ' '; 1006 break; 1007 } 1008 db_printf("%s%c ", sb + les->st_name - 1009 st->sd_usroffset, c); 1010 } else 1011 db_printf("%s ", sb + les->st_name - 1012 st->sd_usroffset); 1013 } 1014 } 1015 return ENOENT; 1016 } 1017 #endif /* DDB */ 1018 1019 #if NKSYMS 1020 /* 1021 * Static allocated ELF header. 1022 * Basic info is filled in at attach, sizes at open. 1023 */ 1024 #define SYMTAB 1 1025 #define STRTAB 2 1026 #define SHSTRTAB 3 1027 #define NSECHDR 4 1028 1029 #define NPRGHDR 2 1030 #define SHSTRSIZ 28 1031 1032 static struct ksyms_hdr { 1033 Elf_Ehdr kh_ehdr; 1034 Elf_Phdr kh_phdr[NPRGHDR]; 1035 Elf_Shdr kh_shdr[NSECHDR]; 1036 char kh_strtab[SHSTRSIZ]; 1037 } ksyms_hdr; 1038 1039 1040 static void 1041 ksyms_hdr_init(void *hdraddr) 1042 { 1043 1044 /* Copy the loaded elf exec header */ 1045 memcpy(&ksyms_hdr.kh_ehdr, hdraddr, sizeof(Elf_Ehdr)); 1046 1047 /* Set correct program/section header sizes, offsets and numbers */ 1048 ksyms_hdr.kh_ehdr.e_phoff = offsetof(struct ksyms_hdr, kh_phdr[0]); 1049 ksyms_hdr.kh_ehdr.e_phentsize = sizeof(Elf_Phdr); 1050 ksyms_hdr.kh_ehdr.e_phnum = NPRGHDR; 1051 ksyms_hdr.kh_ehdr.e_shoff = offsetof(struct ksyms_hdr, kh_shdr[0]); 1052 ksyms_hdr.kh_ehdr.e_shentsize = sizeof(Elf_Shdr); 1053 ksyms_hdr.kh_ehdr.e_shnum = NSECHDR; 1054 ksyms_hdr.kh_ehdr.e_shstrndx = NSECHDR - 1; /* Last section */ 1055 1056 /* 1057 * Keep program headers zeroed (unused). 1058 * The section headers are hand-crafted. 1059 * First section is section zero. 1060 */ 1061 1062 /* Second section header; ".symtab" */ 1063 ksyms_hdr.kh_shdr[SYMTAB].sh_name = 1; /* Section 3 offset */ 1064 ksyms_hdr.kh_shdr[SYMTAB].sh_type = SHT_SYMTAB; 1065 ksyms_hdr.kh_shdr[SYMTAB].sh_offset = sizeof(struct ksyms_hdr); 1066 /* ksyms_hdr.kh_shdr[SYMTAB].sh_size = filled in at open */ 1067 ksyms_hdr.kh_shdr[SYMTAB].sh_link = 2; /* Corresponding strtab */ 1068 ksyms_hdr.kh_shdr[SYMTAB].sh_info = 0; /* XXX */ 1069 ksyms_hdr.kh_shdr[SYMTAB].sh_addralign = sizeof(long); 1070 ksyms_hdr.kh_shdr[SYMTAB].sh_entsize = sizeof(Elf_Sym); 1071 1072 /* Third section header; ".strtab" */ 1073 ksyms_hdr.kh_shdr[STRTAB].sh_name = 9; /* Section 3 offset */ 1074 ksyms_hdr.kh_shdr[STRTAB].sh_type = SHT_STRTAB; 1075 /* ksyms_hdr.kh_shdr[STRTAB].sh_offset = filled in at open */ 1076 /* ksyms_hdr.kh_shdr[STRTAB].sh_size = filled in at open */ 1077 /* ksyms_hdr.kh_shdr[STRTAB].sh_link = kept zero */ 1078 ksyms_hdr.kh_shdr[STRTAB].sh_info = 0; 1079 ksyms_hdr.kh_shdr[STRTAB].sh_addralign = sizeof(char); 1080 ksyms_hdr.kh_shdr[STRTAB].sh_entsize = 0; 1081 1082 /* Fourth section, ".shstrtab" */ 1083 ksyms_hdr.kh_shdr[SHSTRTAB].sh_name = 17; /* This section name offset */ 1084 ksyms_hdr.kh_shdr[SHSTRTAB].sh_type = SHT_STRTAB; 1085 ksyms_hdr.kh_shdr[SHSTRTAB].sh_offset = 1086 offsetof(struct ksyms_hdr, kh_strtab); 1087 ksyms_hdr.kh_shdr[SHSTRTAB].sh_size = SHSTRSIZ; 1088 ksyms_hdr.kh_shdr[SHSTRTAB].sh_addralign = sizeof(char); 1089 1090 /* Set section names */ 1091 strlcpy(&ksyms_hdr.kh_strtab[1], ".symtab", 1092 sizeof(ksyms_hdr.kh_strtab) - 1); 1093 strlcpy(&ksyms_hdr.kh_strtab[9], ".strtab", 1094 sizeof(ksyms_hdr.kh_strtab) - 9); 1095 strlcpy(&ksyms_hdr.kh_strtab[17], ".shstrtab", 1096 sizeof(ksyms_hdr.kh_strtab) - 17); 1097 }; 1098 1099 static int 1100 ksymsopen(dev_t dev, int oflags, int devtype, struct lwp *l) 1101 { 1102 1103 if (minor(dev)) 1104 return ENXIO; 1105 if (ksymsinited == 0) 1106 return ENXIO; 1107 1108 ksyms_hdr.kh_shdr[SYMTAB].sh_size = symsz; 1109 ksyms_hdr.kh_shdr[STRTAB].sh_offset = symsz + 1110 ksyms_hdr.kh_shdr[SYMTAB].sh_offset; 1111 ksyms_hdr.kh_shdr[STRTAB].sh_size = strsz; 1112 ksyms_isopen = 1; 1113 1114 #ifdef KSYMS_DEBUG 1115 if (ksyms_debug & FOLLOW_DEVKSYMS) 1116 printf("ksymsopen: symsz 0x%x strsz 0x%x\n", symsz, strsz); 1117 #endif 1118 1119 return 0; 1120 } 1121 1122 static int 1123 ksymsclose(dev_t dev, int oflags, int devtype, struct lwp *l) 1124 { 1125 1126 #ifdef KSYMS_DEBUG 1127 if (ksyms_debug & FOLLOW_DEVKSYMS) 1128 printf("ksymsclose\n"); 1129 #endif 1130 1131 ksyms_isopen = 0; 1132 wakeup(&ksyms_isopen); 1133 return 0; 1134 } 1135 1136 #define HDRSIZ sizeof(struct ksyms_hdr) 1137 1138 static int 1139 ksymsread(dev_t dev, struct uio *uio, int ioflag) 1140 { 1141 struct symtab *st; 1142 size_t filepos, inpos, off; 1143 1144 #ifdef KSYMS_DEBUG 1145 if (ksyms_debug & FOLLOW_DEVKSYMS) 1146 printf("ksymsread: offset 0x%llx resid 0x%zx\n", 1147 (long long)uio->uio_offset, uio->uio_resid); 1148 #endif 1149 1150 off = uio->uio_offset; 1151 if (off >= (strsz + symsz + HDRSIZ)) 1152 return 0; /* End of symtab */ 1153 /* 1154 * First: Copy out the ELF header. 1155 */ 1156 if (off < HDRSIZ) 1157 uiomove((char *)&ksyms_hdr + off, HDRSIZ - off, uio); 1158 1159 /* 1160 * Copy out the symbol table. 1161 */ 1162 filepos = HDRSIZ; 1163 CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) { 1164 if (uio->uio_resid == 0) 1165 return 0; 1166 if (uio->uio_offset <= st->sd_symsize + filepos) { 1167 inpos = uio->uio_offset - filepos; 1168 uiomove((char *)st->sd_symstart + inpos, 1169 st->sd_symsize - inpos, uio); 1170 } 1171 filepos += st->sd_symsize; 1172 } 1173 1174 if (filepos != HDRSIZ + symsz) 1175 panic("ksymsread: unsunc"); 1176 1177 /* 1178 * Copy out the string table 1179 */ 1180 CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) { 1181 if (uio->uio_resid == 0) 1182 return 0; 1183 if (uio->uio_offset <= st->sd_strsize + filepos) { 1184 inpos = uio->uio_offset - filepos; 1185 uiomove((char *)st->sd_strstart + inpos, 1186 st->sd_strsize - inpos, uio); 1187 } 1188 filepos += st->sd_strsize; 1189 } 1190 return 0; 1191 } 1192 1193 static int 1194 ksymswrite(dev_t dev, struct uio *uio, int ioflag) 1195 { 1196 1197 return EROFS; 1198 } 1199 1200 static int 1201 ksymsioctl(dev_t dev, u_long cmd, void *data, int fflag, struct lwp *l) 1202 { 1203 struct ksyms_gsymbol *kg = (struct ksyms_gsymbol *)data; 1204 struct symtab *st; 1205 Elf_Sym *sym = NULL; 1206 unsigned long val; 1207 int error = 0; 1208 char *str = NULL; 1209 1210 if (cmd == KIOCGVALUE || cmd == KIOCGSYMBOL) 1211 str = malloc(ksyms_maxlen, M_DEVBUF, M_WAITOK); 1212 1213 switch (cmd) { 1214 case KIOCGVALUE: 1215 /* 1216 * Use the in-kernel symbol lookup code for fast 1217 * retreival of a value. 1218 */ 1219 if ((error = copyinstr(kg->kg_name, str, ksyms_maxlen, NULL))) 1220 break; 1221 if ((error = ksyms_getval(NULL, str, &val, KSYMS_EXTERN))) 1222 break; 1223 error = copyout(&val, kg->kg_value, sizeof(long)); 1224 break; 1225 1226 case KIOCGSYMBOL: 1227 /* 1228 * Use the in-kernel symbol lookup code for fast 1229 * retreival of a symbol. 1230 */ 1231 if ((error = copyinstr(kg->kg_name, str, ksyms_maxlen, NULL))) 1232 break; 1233 CIRCLEQ_FOREACH(st, &symtab_queue, sd_queue) { 1234 if ((sym = findsym(str, st)) == NULL) /* from userland */ 1235 continue; 1236 1237 /* Skip if bad binding */ 1238 if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL) { 1239 sym = NULL; 1240 continue; 1241 } 1242 break; 1243 } 1244 /* 1245 * XXX which value of sym->st_name should be returned? The real 1246 * one, or the one that matches what reading /dev/ksyms get? 1247 * 1248 * Currently, we're returning the /dev/ksyms one. 1249 */ 1250 if (sym != NULL) 1251 error = copyout(sym, kg->kg_sym, sizeof(Elf_Sym)); 1252 else 1253 error = ENOENT; 1254 break; 1255 1256 case KIOCGSIZE: 1257 /* 1258 * Get total size of symbol table. 1259 */ 1260 *(int *)data = strsz + symsz + HDRSIZ; 1261 break; 1262 1263 default: 1264 error = ENOTTY; 1265 break; 1266 } 1267 1268 if (cmd == KIOCGVALUE || cmd == KIOCGSYMBOL) 1269 free(str, M_DEVBUF); 1270 1271 return error; 1272 } 1273 1274 const struct cdevsw ksyms_cdevsw = { 1275 ksymsopen, ksymsclose, ksymsread, ksymswrite, ksymsioctl, 1276 nullstop, notty, nopoll, nommap, nullkqfilter, DV_DULL 1277 }; 1278 #endif /* NKSYMS */ 1279