bug-hurd
[Top][All Lists]
Advanced

[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())



reply via email to

[Prev in Thread] Current Thread [Next in Thread]