Justus Winter, le Sun 14 Sep 2014 15:14:03 +0200, a écrit :
> * 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.Ack, thank you so much for this! :D > --- > Makefrag.am | 2 + > ddb/db_elf.c | 232 > ++++++++++++++++++++++++++++++++++++++++++++++++ > ddb/db_elf.h | 52 +++++++++++ > ddb/db_sym.c | 14 ++- > ddb/db_sym.h | 9 ++ > i386/i386at/model_dep.c | 27 ++++++ > 6 files changed, 335 insertions(+), 1 deletion(-) > create mode 100644 ddb/db_elf.c > create mode 100644 ddb/db_elf.h > > diff --git a/Makefrag.am b/Makefrag.am > index d6dd77f..5e98b21 100644 > --- a/Makefrag.am > +++ b/Makefrag.am > @@ -25,6 +25,8 @@ libkernel_a_SOURCES += \ > ddb/db_access.h \ > ddb/db_aout.c \ > ddb/db_aout.h \ > + ddb/db_elf.c \ > + ddb/db_elf.h \ > ddb/db_break.c \ > ddb/db_break.h \ > ddb/db_command.c \ > 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 [email protected] > + * 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 > diff --git a/i386/i386at/model_dep.c b/i386/i386at/model_dep.c > index 209cfb1..bc34c9b 100644 > --- a/i386/i386at/model_dep.c > +++ b/i386/i386at/model_dep.c > @@ -82,7 +82,16 @@ > #if MACH_KDB > #include <ddb/db_sym.h> > #include <i386/db_interface.h> > + > +/* a.out symbol table */ > static vm_offset_t kern_sym_start, kern_sym_end; > + > +/* ELF section header */ > +static unsigned elf_shdr_num; > +static vm_size_t elf_shdr_size; > +static vm_offset_t elf_shdr_addr; > +static unsigned elf_shdr_shndx; > + > #else /* MACH_KDB */ > #define kern_sym_start 0 > #define kern_sym_end 0 > @@ -570,6 +579,17 @@ void c_boot_entry(vm_offset_t bi) > kern_sym_start, kern_sym_end, > symtab_size, strtab_size); > } > + > + if ((boot_info.flags & MULTIBOOT_ELF_SHDR) > + && boot_info.syms.e.num) > + { > + elf_shdr_num = boot_info.syms.e.num; > + elf_shdr_size = boot_info.syms.e.size; > + elf_shdr_addr = (vm_offset_t)phystokv(boot_info.syms.e.addr); > + elf_shdr_shndx = boot_info.syms.e.shndx; > + > + printf("ELF section header table at %08lx\n", elf_shdr_addr); > + } > #endif /* MACH_KDB */ > #endif /* MACH_XEN */ > > @@ -588,6 +608,13 @@ void c_boot_entry(vm_offset_t bi) > { > aout_db_sym_init((char *)kern_sym_start, (char *)kern_sym_end, > "mach", (char *)0); > } > + > + if (elf_shdr_num) > + { > + elf_db_sym_init(elf_shdr_num,elf_shdr_size, > + elf_shdr_addr, elf_shdr_shndx, > + "mach", NULL); > + } > #endif /* MACH_KDB */ > > machine_slot[0].is_cpu = TRUE; > -- > 2.1.0 > > -- Samuel /* Amuse the user. */ printk( " \\|/ ____ \\|/\n" " \"@'/ ,. \\`@\"\n" " /_| \\__/ |_\\\n" " \\__U_/\n"); (From linux/arch/sparc/kernel/traps.c:die_if_kernel())
