diff options
author | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-09-14 13:35:50 +0200 |
---|---|---|
committer | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-09-17 11:39:55 +0200 |
commit | 86f60379f71ec6d0aa3b93eaacc55bc5f453bda5 (patch) | |
tree | 395ccb92281d5d198892ba478ffe5dbb0af23f42 /ddb | |
parent | ffd4f3c8239b41d3fe9fa14403eb063e02b6a222 (diff) |
ddb: add support for ELF symbol tables
* ddb/db_elf.c: New file.
* ddb/db_elf.h: Likewise.
* Makefrag.am (libkernel_a_SOURCES): Add db_elf.{c,h}.
* ddb/db_sym.c (dummy_db_sym_init): New stub db_sym_init function.
(db_sym_switch): Add ELF functions.
* ddb/db_sym.h (SYMTAB_ELF): New macro.
(elf_db_sym_init): New declaration.
* i386/i386at/model_dep.c (c_boot_entry): Get ELF section header
information from the multiboot structure, and call elf_db_sym_init.
Diffstat (limited to 'ddb')
-rw-r--r-- | ddb/db_elf.c | 232 | ||||
-rw-r--r-- | ddb/db_elf.h | 52 | ||||
-rw-r--r-- | ddb/db_sym.c | 14 | ||||
-rw-r--r-- | ddb/db_sym.h | 9 |
4 files changed, 306 insertions, 1 deletions
diff --git a/ddb/db_elf.c b/ddb/db_elf.c new file mode 100644 index 0000000..10e7162 --- /dev/null +++ b/ddb/db_elf.c @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2014 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ + +#if MACH_KDB + +/* + * Symbol table routines for ELF format files. + */ + +#include <string.h> +#include <mach/std_types.h> +#include <mach/exec/elf.h> +#include <machine/db_machdep.h> /* data types */ +#include <machine/vm_param.h> +#include <ddb/db_output.h> +#include <ddb/db_sym.h> +#include <ddb/db_elf.h> + +#ifndef DB_NO_ELF + +struct db_symtab_elf { + int type; + Elf32_Sym *start; + Elf32_Sym *end; + char *strings; + char *map_pointer; /* symbols are for this map only, + if not null */ + char name[SYMTAB_NAME_LEN]; + /* symtab name */ +}; + +boolean_t +elf_db_sym_init (unsigned shdr_num, + vm_size_t shdr_size, + vm_offset_t shdr_addr, + unsigned shdr_shndx, + char *name, + char *task_addr) +{ + Elf32_Shdr *shdr, *symtab, *strtab; + const char *shstrtab; + int i; + + if (shdr_num == 0) + return FALSE; + + if (shdr_size != sizeof *shdr) + return FALSE; + + shdr = (Elf32_Shdr *) shdr_addr; + + if (shdr[shdr_shndx].sh_type != SHT_STRTAB) + return FALSE; + + shstrtab = (const char *) phystokv (shdr[shdr_shndx].sh_addr); + + symtab = strtab = NULL; + for (i = 0; i < shdr_num; i++) + switch (shdr[i].sh_type) { + case SHT_SYMTAB: + if (symtab) + db_printf ("Ignoring additional ELF symbol table at %d\n", i); + else + symtab = &shdr[i]; + break; + + case SHT_STRTAB: + if (strcmp (&shstrtab[shdr[i].sh_name], ".strtab") == 0) { + if (strtab) + db_printf ("Ignoring additional ELF string table at %d\n", i); + else + strtab = &shdr[i]; + } + break; + } + + if (symtab == NULL || strtab == NULL) + return FALSE; + + if (db_add_symbol_table (SYMTAB_ELF, + (char *) phystokv (symtab->sh_addr), + (char *) phystokv (symtab->sh_addr)+symtab->sh_size, + name, + (char *) phystokv (strtab->sh_addr), + task_addr)) { + db_printf ("Loaded ELF symbol table for %s (%d symbols)\n", + name, symtab->sh_size / sizeof (Elf32_Sym)); + return TRUE; + } + + return FALSE; +} + +/* + * lookup symbol by name + */ +db_sym_t +elf_db_lookup (db_symtab_t *stab, + char *symstr) +{ + struct db_symtab_elf *self = (struct db_symtab_elf *) stab; + Elf32_Sym *s; + + for (s = self->start; s < self->end; s++) + if (strcmp (symstr, &self->strings[s->st_name]) == 0) + return (db_sym_t) s; + + return NULL; +} + +db_sym_t +elf_db_search_symbol (db_symtab_t *stab, + db_addr_t off, + db_strategy_t strategy, + db_expr_t *diffp) /* in/out */ +{ + struct db_symtab_elf *self = (struct db_symtab_elf *) stab; + unsigned long diff = *diffp; + Elf32_Sym *s, *symp = NULL; + + for (s = self->start; s < self->end; s++) { + if (s->st_name == 0) + continue; + + if (strategy == DB_STGY_XTRN && (s->st_info & STB_GLOBAL) == 0) + continue; + + if (off >= s->st_value) { + if (s->st_info == STT_FUNC) + continue; + + if (off - s->st_value < diff) { + diff = off - s->st_value; + symp = s; + if (diff == 0 && (s->st_info & STB_GLOBAL)) + break; + } else if (off - s->st_value == diff) { + if (symp == NULL) + symp = s; + else if ((symp->st_info & STB_GLOBAL) == 0 + && (s->st_info & STB_GLOBAL) != 0) + symp = s; /* pick the external symbol */ + } + } + } + + if (symp == NULL) + *diffp = off; + else + *diffp = diff; + + return (db_sym_t) symp; +} + +/* + * Return the name and value for a symbol. + */ +void +elf_db_symbol_values (db_symtab_t *stab, + db_sym_t sym, + char **namep, + db_expr_t *valuep) +{ + struct db_symtab_elf *self = (struct db_symtab_elf *) stab; + Elf32_Sym *s = (Elf32_Sym *) sym; + + if (namep) + *namep = &self->strings[s->st_name]; + if (valuep) + *valuep = s->st_value; +} + +/* + * Find filename and lineno within, given the current pc. + */ +boolean_t +elf_db_line_at_pc (db_symtab_t *stab, + db_sym_t sym, + char **file, + int *line, + db_addr_t pc) +{ + /* XXX Parse DWARF information. */ + return FALSE; +} + +#endif /* DB_NO_ELF */ + +#endif /* MACH_KDB */ diff --git a/ddb/db_elf.h b/ddb/db_elf.h new file mode 100644 index 0000000..12b8286 --- /dev/null +++ b/ddb/db_elf.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2013 Free Software Foundation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _DDB_DB_ELF_H_ +#define _DDB_DB_ELF_H_ + +#include <ddb/db_sym.h> +#include <machine/db_machdep.h> + +extern boolean_t +elf_db_line_at_pc( + db_symtab_t *stab, + db_sym_t sym, + char **file, + int *line, + db_addr_t pc); + +extern db_sym_t +elf_db_lookup( + db_symtab_t *stab, + char * symstr); + +extern db_sym_t +elf_db_search_symbol( + db_symtab_t * symtab, + db_addr_t off, + db_strategy_t strategy, + db_expr_t *diffp); + +extern void +elf_db_symbol_values( + db_symtab_t *stab, + db_sym_t sym, + char **namep, + db_expr_t *valuep); + +#endif /* _DDB_DB_ELF_H_ */ diff --git a/ddb/db_sym.c b/ddb/db_sym.c index 7d97d15..0179137 100644 --- a/ddb/db_sym.c +++ b/ddb/db_sym.c @@ -38,6 +38,7 @@ #include <ddb/db_sym.h> #include <ddb/db_task_thread.h> #include <ddb/db_aout.h> +#include <ddb/db_elf.h> #include <vm/vm_map.h> /* vm_map_t */ @@ -507,6 +508,10 @@ void db_free_symbol(db_sym_t s) */ void dummy_db_free_symbol(db_sym_t symbol) { } +boolean_t dummy_db_sym_init(char *a, char *b, char *c, char *d) { + return FALSE; +} + struct db_sym_switch x_db[] = { @@ -521,7 +526,14 @@ struct db_sym_switch x_db[] = { { 0,}, /* Machdep, not inited here */ - { 0,} + { 0,}, + +#ifdef DB_NO_ELF + { 0,}, +#else /* DB_NO_ELF */ + { dummy_db_sym_init, elf_db_lookup, elf_db_search_symbol, + elf_db_line_at_pc, elf_db_symbol_values, dummy_db_free_symbol }, +#endif /* DB_NO_ELF */ }; diff --git a/ddb/db_sym.h b/ddb/db_sym.h index 2c3e10a..d8f3387 100644 --- a/ddb/db_sym.h +++ b/ddb/db_sym.h @@ -46,6 +46,7 @@ typedef struct { #define SYMTAB_AOUT 0 #define SYMTAB_COFF 1 #define SYMTAB_MACHDEP 2 +#define SYMTAB_ELF 3 char *start; /* symtab location */ char *end; char *private; /* optional machdep pointer */ @@ -243,6 +244,14 @@ extern boolean_t aout_db_sym_init( char *name, char *task_addr); +extern boolean_t elf_db_sym_init ( + unsigned shdr_num, + vm_size_t shdr_size, + vm_offset_t shdr_addr, + unsigned shdr_shndx, + char *name, + char *task_addr); + db_sym_t db_lookup(char *); db_sym_t |