bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] ddb: add support for ELF symbol tables


From: Justus Winter
Subject: [PATCH] ddb: add support for ELF symbol tables
Date: Sun, 14 Sep 2014 15:14:03 +0200

* 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.
---
 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




reply via email to

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