1 /* 2 * Copyright (c) 2010 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include <sys/types.h> 36 #include <sys/sysctl.h> 37 38 #include <ctype.h> 39 #include <devinfo.h> 40 #include <err.h> 41 #include <fcntl.h> 42 #include <kvm.h> 43 #include <limits.h> 44 #include <nlist.h> 45 #include <stdint.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <unistd.h> 50 #include <evtr.h> 51 #include <stdarg.h> 52 #include "symbols.h" 53 54 struct symdata { 55 TAILQ_ENTRY(symdata) link; 56 const char *symname; 57 char *symaddr; 58 char symtype; 59 }; 60 61 static TAILQ_HEAD(symlist, symdata) symlist; 62 static struct symdata *symcache; 63 static char *symbegin = (void *)(intptr_t)0; 64 static char *symend = (void *)(intptr_t)-1; 65 66 void 67 read_symbols(const char *file) 68 { 69 char buf[256]; 70 char cmd[256]; 71 size_t buflen = sizeof(buf); 72 FILE *fp; 73 struct symdata *sym; 74 char *s1; 75 char *s2; 76 char *s3; 77 78 TAILQ_INIT(&symlist); 79 80 if (file == NULL) { 81 if (sysctlbyname("kern.bootfile", buf, &buflen, NULL, 0) < 0) 82 file = "/boot/kernel"; 83 else 84 file = buf; 85 } 86 snprintf(cmd, sizeof(cmd), "nm -n %s", file); 87 if ((fp = popen(cmd, "r")) != NULL) { 88 while (fgets(buf, sizeof(buf), fp) != NULL) { 89 s1 = strtok(buf, " \t\n"); 90 s2 = strtok(NULL, " \t\n"); 91 s3 = strtok(NULL, " \t\n"); 92 if (s1 && s2 && s3) { 93 sym = malloc(sizeof(struct symdata)); 94 sym->symaddr = (char *)strtoul(s1, NULL, 16); 95 sym->symtype = s2[0]; 96 sym->symname = strdup(s3); 97 if (strcmp(s3, "kernbase") == 0) 98 symbegin = sym->symaddr; 99 if (strcmp(s3, "end") == 0) 100 symend = sym->symaddr; 101 TAILQ_INSERT_TAIL(&symlist, sym, link); 102 } 103 } 104 pclose(fp); 105 } 106 symcache = TAILQ_FIRST(&symlist); 107 } 108 109 const char * 110 address_to_symbol(void *kptr, struct save_ctx *ctx) 111 { 112 char *buf = ctx->save_buf; 113 int size = sizeof(ctx->save_buf); 114 115 if (symcache == NULL || 116 (char *)kptr < symbegin || (char *)kptr >= symend 117 ) { 118 snprintf(buf, size, "%p", kptr); 119 return(buf); 120 } 121 while ((char *)symcache->symaddr < (char *)kptr) { 122 if (TAILQ_NEXT(symcache, link) == NULL) 123 break; 124 symcache = TAILQ_NEXT(symcache, link); 125 } 126 while ((char *)symcache->symaddr > (char *)kptr) { 127 if (symcache != TAILQ_FIRST(&symlist)) 128 symcache = TAILQ_PREV(symcache, symlist, link); 129 } 130 snprintf(buf, size, "%s+%d", symcache->symname, 131 (int)((char *)kptr - symcache->symaddr)); 132 return(buf); 133 } 134