1/* $NetBSD: elf32.c,v 1.8 2009/04/16 06:14:13 lukem Exp $ */ 2 3/*- 4 * Copyright (c) 2006 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Andrew Doran. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32/* 33 * Copyright (c) 1996 Christopher G. Demetriou 34 * All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. All advertising materials mentioning features or use of this software 45 * must display the following acknowledgement: 46 * This product includes software developed for the 47 * NetBSD Project. See http://www.NetBSD.org/ for 48 * information about NetBSD. 49 * 4. The name of the author may not be used to endorse or promote products 50 * derived from this software without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 53 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 54 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 55 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 56 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 57 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 58 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 59 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 60 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 61 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62 * 63 * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>> 64 */ 65 66#include <sys/cdefs.h> 67#if !defined(lint) 68__RCSID("$NetBSD: elf32.c,v 1.8 2009/04/16 06:14:13 lukem Exp $"); 69#endif 70 71#ifndef ELFSIZE 72#define ELFSIZE 32 73#endif 74 75#include <sys/param.h> 76#include <sys/exec_elf.h> 77#include <sys/queue.h> 78 79#include <dev/lockstat.h> 80 81#include <stdio.h> 82#include <stdlib.h> 83#include <string.h> 84#include <unistd.h> 85#include <err.h> 86 87#include "extern.h" 88 89#if (ELFSIZE == 32) 90#define NAME(x) x##32 91#elif (ELFSIZE == 64) 92#define NAME(x) x##64 93#endif 94 95static int nsyms; 96static Elf_Sym *symp; 97static char *strp; 98 99int 100NAME(loadsym)(int fd) 101{ 102 Elf_Shdr symhdr, strhdr; 103 Elf_Ehdr ehdr; 104 size_t sz; 105 off_t off; 106 int i; 107 108 /* 109 * Read the ELF header and make sure it's OK. 110 */ 111 if (pread(fd, &ehdr, sizeof(ehdr), 0) != sizeof(ehdr)) 112 return -1; 113 114 if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 || 115 ehdr.e_ident[EI_CLASS] != ELFCLASS) 116 return -1; 117 118 switch (ehdr.e_machine) { 119 ELFDEFNNAME(MACHDEP_ID_CASES) 120 default: 121 return -1; 122 } 123 124 /* 125 * Find the symbol table header, and make sure the binary isn't 126 * stripped. 127 */ 128 off = ehdr.e_shoff; 129 for (i = 0; i < ehdr.e_shnum; i++, off += sizeof(symhdr)) { 130 sz = pread(fd, &symhdr, sizeof(symhdr), off); 131 if (sz != sizeof(symhdr)) 132 err(EXIT_FAILURE, "pread (section headers)"); 133 if (symhdr.sh_type == SHT_SYMTAB) 134 break; 135 } 136 if (i == ehdr.e_shnum || symhdr.sh_offset == 0) 137 err(EXIT_FAILURE, "namelist is stripped"); 138 139 /* 140 * Pull in the string table header, and then read in both the symbol 141 * table and string table proper. 142 * 143 * XXX We can't use mmap(), as /dev/ksyms doesn't support mmap yet. 144 */ 145 off = ehdr.e_shoff + symhdr.sh_link * sizeof(symhdr); 146 if (pread(fd, &strhdr, sizeof(strhdr), off) != sizeof(strhdr)) 147 err(EXIT_FAILURE, "pread"); 148 149 if ((symp = malloc(symhdr.sh_size)) == NULL) 150 err(EXIT_FAILURE, "malloc (symbol table)"); 151 sz = pread(fd, symp, symhdr.sh_size, symhdr.sh_offset); 152 if (sz != symhdr.sh_size) 153 err(EXIT_FAILURE, "pread (symbol table)"); 154 155 if ((strp = malloc(strhdr.sh_size)) == NULL) 156 err(EXIT_FAILURE, "malloc (string table)"); 157 sz = pread(fd, strp, strhdr.sh_size, strhdr.sh_offset); 158 if (sz != strhdr.sh_size) 159 err(EXIT_FAILURE, "pread (string table)"); 160 161 nsyms = (int)(symhdr.sh_size / sizeof(Elf_Sym)); 162 163 return 0; 164} 165 166int 167NAME(findsym)(findsym_t find, char *name, uintptr_t *start, uintptr_t *end) 168{ 169 static int lastptr[FIND_MAX]; 170 uintptr_t sa, ea; 171 int i, rv, off; 172 Elf_Byte st; 173 174 switch (find) { 175 case LOCK_BYNAME: 176 case LOCK_BYADDR: 177 st = STT_OBJECT; 178 break; 179 case FUNC_BYNAME: 180 case FUNC_BYADDR: 181 st = STT_FUNC; 182 break; 183 default: 184 return -1; 185 } 186 187 rv = -1; 188 189#ifdef dump_core 190 for (i = lastptr[find];;) { 191#else 192 for (i = 0; i < nsyms; i++) { 193#endif 194 switch (find) { 195 case LOCK_BYNAME: 196 case FUNC_BYNAME: 197 if (ELF_ST_TYPE(symp[i].st_info) != st) 198 break; 199 if (strcmp(&strp[symp[i].st_name], name) != 0) 200 break; 201 *start = (uintptr_t)symp[i].st_value; 202 *end = *start + (uintptr_t)symp[i].st_size; 203 goto found; 204 205 case LOCK_BYADDR: 206 case FUNC_BYADDR: 207 if (ELF_ST_TYPE(symp[i].st_info) != st) 208 break; 209 sa = (uintptr_t)symp[i].st_value; 210 ea = sa + (uintptr_t)symp[i].st_size - 1; 211 if (*start < sa || *start > ea) 212 break; 213 off = (int)(*start - sa); 214 *start = sa; 215 if (end != NULL) 216 *end = ea; 217 if (name == NULL) 218 goto found; 219 if (off == 0) 220 strlcpy(name, &strp[symp[i].st_name], 221 NAME_SIZE); 222 else 223 snprintf(name, NAME_SIZE, "%s+%x", 224 &strp[symp[i].st_name], off); 225 goto found; 226 227 default: 228 break; 229 } 230 231#ifdef dump_core 232 if (++i >= nsyms) 233 i = 0; 234 if (i == lastptr[find]) 235 return -1; 236#endif 237 } 238 239 return -1; 240 241 found: 242 lastptr[find] = i; 243 return 0; 244} 245