[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH] ddb: add support for ELF symbol tables
From: |
Samuel Thibault |
Subject: |
Re: [PATCH] ddb: add support for ELF symbol tables |
Date: |
Wed, 17 Sep 2014 02:00:57 +0200 |
User-agent: |
Mutt/1.5.21+34 (58baf7c9f32f) (2010-12-30) |
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 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
> 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())