1/* $NetBSD: elf32.c,v 1.9 2011/02/05 13:32:32 yamt 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.9 2011/02/05 13:32:32 yamt 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 uintptr_t sa, ea; 170 int i, off; 171 Elf_Byte st; 172 173 switch (find) { 174 case LOCK_BYNAME: 175 case LOCK_BYADDR: 176 st = STT_OBJECT; 177 break; 178 case FUNC_BYNAME: 179 case FUNC_BYADDR: 180 st = STT_FUNC; 181 break; 182 default: 183 return -1; 184 } 185 186 187#ifdef dump_core 188 static int lastptr[FIND_MAX]; 189 for (i = lastptr[find];;) { 190#else 191 for (i = 0; i < nsyms; i++) { 192#endif 193 switch (find) { 194 case LOCK_BYNAME: 195 case FUNC_BYNAME: 196 if (ELF_ST_TYPE(symp[i].st_info) != st) 197 break; 198 if (strcmp(&strp[symp[i].st_name], name) != 0) 199 break; 200 *start = (uintptr_t)symp[i].st_value; 201 *end = *start + (uintptr_t)symp[i].st_size; 202 goto found; 203 204 case LOCK_BYADDR: 205 case FUNC_BYADDR: 206 if (ELF_ST_TYPE(symp[i].st_info) != st) 207 break; 208 sa = (uintptr_t)symp[i].st_value; 209 ea = sa + (uintptr_t)symp[i].st_size - 1; 210 if (*start < sa || *start > ea) 211 break; 212 off = (int)(*start - sa); 213 *start = sa; 214 if (end != NULL) 215 *end = ea; 216 if (name == NULL) 217 goto found; 218 if (off == 0) 219 strlcpy(name, &strp[symp[i].st_name], 220 NAME_SIZE); 221 else 222 snprintf(name, NAME_SIZE, "%s+%x", 223 &strp[symp[i].st_name], off); 224 goto found; 225 226 default: 227 break; 228 } 229 230#ifdef dump_core 231 if (++i >= nsyms) 232 i = 0; 233 if (i == lastptr[find]) 234 return -1; 235#endif 236 } 237 238 return -1; 239 240 found: 241#ifdef dump_core 242 lastptr[find] = i; 243#endif 244 return 0; 245} 246