summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2017-08-10 19:39:39 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2017-08-10 19:39:39 +0000
commitc5b1161eac7a9e74a903806fba19f36288845966 (patch)
tree6334a2f6bc3483792fc83ed111dca25acb2db2fc
parente55a17530b2fdc822fc5210e1c6702ed306d77b0 (diff)
With a CTF kernel, DDB's print command will now pretty-print symbols.
Casting a type is not yet supported. ok kettenis@, jasper@
-rw-r--r--sys/arch/sparc64/sparc64/openfirm.c4
-rw-r--r--sys/ddb/db_command.c8
-rw-r--r--sys/ddb/db_ctf.c335
-rw-r--r--sys/ddb/db_elf.c10
-rw-r--r--sys/ddb/db_expr.c4
-rw-r--r--sys/ddb/db_sym.h7
6 files changed, 321 insertions, 47 deletions
diff --git a/sys/arch/sparc64/sparc64/openfirm.c b/sys/arch/sparc64/sparc64/openfirm.c
index 14c3c30a0a0..d9e97bf1eaf 100644
--- a/sys/arch/sparc64/sparc64/openfirm.c
+++ b/sys/arch/sparc64/sparc64/openfirm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: openfirm.c,v 1.20 2017/05/30 15:39:05 mpi Exp $ */
+/* $OpenBSD: openfirm.c,v 1.21 2017/08/10 19:39:38 mpi Exp $ */
/* $NetBSD: openfirm.c,v 1.13 2001/06/21 00:08:02 eeh Exp $ */
/*
@@ -785,7 +785,7 @@ void OF_sym2val(cells)
symbol = (char *)(u_long)args->symbol;
if (obp_symbol_debug)
prom_printf("looking up symbol %s\r\n", symbol);
- args->result = (db_value_of_name(symbol, &value) == TRUE) ? 0 : -1;
+ args->result = (db_symbol_by_name(symbol, &value) != NULL) ? 0 : -1;
if (obp_symbol_debug)
prom_printf("%s is %lx\r\n", symbol, value);
args->value = ADR2CELL(value);
diff --git a/sys/ddb/db_command.c b/sys/ddb/db_command.c
index bece0279d5d..94bb0a837e2 100644
--- a/sys/ddb/db_command.c
+++ b/sys/ddb/db_command.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: db_command.c,v 1.72 2017/04/20 12:59:36 visa Exp $ */
+/* $OpenBSD: db_command.c,v 1.73 2017/08/10 19:39:38 mpi Exp $ */
/* $NetBSD: db_command.c,v 1.20 1996/03/30 22:30:05 christos Exp $ */
/*
@@ -79,6 +79,7 @@ db_addr_t db_next; /* next address to be examined
int db_cmd_search(char *, struct db_command *, struct db_command **);
void db_cmd_list(struct db_command *);
+void db_ctf_pprint_cmd(db_expr_t, int, db_expr_t,char *);
void db_map_print_cmd(db_expr_t, int, db_expr_t, char *);
void db_buf_print_cmd(db_expr_t, int, db_expr_t, char *);
void db_malloc_print_cmd(db_expr_t, int, db_expr_t, char *);
@@ -616,7 +617,12 @@ struct db_command db_command_table[] = {
/* this must be the first entry, if it exists */
{ "machine", NULL, 0, NULL},
#endif
+#ifdef DDBCTF
+ { "print", db_ctf_pprint_cmd, CS_OWN, NULL },
+ { "p", db_ctf_pprint_cmd, CS_OWN, NULL },
+#else
{ "print", db_print_cmd, 0, NULL },
+#endif
{ "examine", db_examine_cmd, CS_SET_DOT, NULL },
{ "x", db_examine_cmd, CS_SET_DOT, NULL },
{ "search", db_search_cmd, CS_OWN|CS_SET_DOT, NULL },
diff --git a/sys/ddb/db_ctf.c b/sys/ddb/db_ctf.c
index ff4dc9776b8..3c652d79263 100644
--- a/sys/ddb/db_ctf.c
+++ b/sys/ddb/db_ctf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: db_ctf.c,v 1.10 2017/05/30 15:39:05 mpi Exp $ */
+/* $OpenBSD: db_ctf.c,v 1.11 2017/08/10 19:39:38 mpi Exp $ */
/*
* Copyright (c) 2016 Jasper Lievisse Adriaanse <jasper@openbsd.org>
@@ -26,9 +26,11 @@
#include <machine/db_machdep.h>
#include <ddb/db_extern.h>
-#include <ddb/db_sym.h>
+#include <ddb/db_command.h>
#include <ddb/db_elf.h>
+#include <ddb/db_lex.h>
#include <ddb/db_output.h>
+#include <ddb/db_sym.h>
#include <sys/exec_elf.h>
#include <sys/ctf.h>
@@ -49,10 +51,14 @@ struct ddb_ctf {
struct ddb_ctf db_ctf;
-static const char *db_ctf_lookup_name(uint32_t);
+static const char *db_ctf_off2name(uint32_t);
static Elf_Sym *db_ctf_idx2sym(size_t *, uint8_t);
static char *db_ctf_decompress(const char *, size_t, off_t);
+const struct ctf_type *db_ctf_type_by_symbol(Elf_Sym *);
+const struct ctf_type *db_ctf_type_by_index(uint16_t);
+void db_ctf_pprint_struct(const struct ctf_type *, vaddr_t);
+
/*
* Entrypoint to verify CTF presence, initialize the header, decompress
* the data, etc.
@@ -96,33 +102,6 @@ db_ctf_init(void)
db_ctf.ctf_found = 1;
}
-void
-db_dump_ctf_header(void)
-{
- if (!db_ctf.ctf_found)
- return;
-
- db_printf("CTF header found at %p (%ld)\n", db_ctf.rawctf,
- db_ctf.rawctflen);
- db_printf("cth_magic: 0x%04x\n", db_ctf.cth->cth_magic);
- db_printf("cth_verion: %d\n", db_ctf.cth->cth_version);
- db_printf("cth_flags: 0x%02x", db_ctf.cth->cth_flags);
- if (db_ctf.cth->cth_flags & CTF_F_COMPRESS) {
- db_printf(" (compressed)");
- }
- db_printf("\n");
- db_printf("cth_parlabel: %s\n",
- db_ctf_lookup_name(db_ctf.cth->cth_parlabel));
- db_printf("cth_parname: %s\n",
- db_ctf_lookup_name(db_ctf.cth->cth_parname));
- db_printf("cth_lbloff: %d\n", db_ctf.cth->cth_lbloff);
- db_printf("cth_objtoff: %d\n", db_ctf.cth->cth_objtoff);
- db_printf("cth_funcoff: %d\n", db_ctf.cth->cth_funcoff);
- db_printf("cth_typeoff: %d\n", db_ctf.cth->cth_typeoff);
- db_printf("cth_stroff: %d\n", db_ctf.cth->cth_stroff);
- db_printf("cth_strlen: %d\n", db_ctf.cth->cth_strlen);
-}
-
/*
* Convert an index to a symbol name while ensuring the type is matched.
* It must be noted this only works if the CTF table has the same order
@@ -154,12 +133,12 @@ db_ctf_idx2sym(size_t *idx, uint8_t type)
int
db_ctf_func_numargs(Elf_Sym *st)
{
- Elf_Sym *symp, *stp = (Elf_Sym *)st;
+ Elf_Sym *symp;
uint16_t *fstart, *fend;
uint16_t *fsp, kind, vlen;
size_t i, idx = 0;
- if (!db_ctf.ctf_found || stp == NULL)
+ if (!db_ctf.ctf_found || st == NULL)
return -1;
fstart = (uint16_t *)(db_ctf.data + db_ctf.cth->cth_funcoff);
@@ -185,15 +164,259 @@ db_ctf_func_numargs(Elf_Sym *st)
for (i = 0; i < vlen; i++)
fsp++;
- if (symp == stp)
+ if (symp == st)
return vlen;
}
return -1;
}
+/*
+ * Return the length of the type record in the CTF section.
+ */
+uint32_t
+db_ctf_type_len(const struct ctf_type *ctt)
+{
+ uint16_t kind, vlen, i;
+ uint32_t tlen;
+ uint64_t size;
+
+ kind = CTF_INFO_KIND(ctt->ctt_info);
+ vlen = CTF_INFO_VLEN(ctt->ctt_info);
+
+ if (ctt->ctt_size <= CTF_MAX_SIZE) {
+ size = ctt->ctt_size;
+ tlen = sizeof(struct ctf_stype);
+ } else {
+ size = CTF_TYPE_LSIZE(ctt);
+ tlen = sizeof(struct ctf_type);
+ }
+
+ switch (kind) {
+ case CTF_K_UNKNOWN:
+ case CTF_K_FORWARD:
+ break;
+ case CTF_K_INTEGER:
+ tlen += sizeof(uint32_t);
+ break;
+ case CTF_K_FLOAT:
+ tlen += sizeof(uint32_t);
+ break;
+ case CTF_K_ARRAY:
+ tlen += sizeof(struct ctf_array);
+ break;
+ case CTF_K_FUNCTION:
+ tlen += (vlen + (vlen & 1)) * sizeof(uint16_t);
+ break;
+ case CTF_K_STRUCT:
+ case CTF_K_UNION:
+ if (size < CTF_LSTRUCT_THRESH) {
+ for (i = 0; i < vlen; i++) {
+ tlen += sizeof(struct ctf_member);
+ }
+ } else {
+ for (i = 0; i < vlen; i++) {
+ tlen += sizeof(struct ctf_lmember);
+ }
+ }
+ break;
+ case CTF_K_ENUM:
+ for (i = 0; i < vlen; i++) {
+ tlen += sizeof(struct ctf_enum);
+ }
+ break;
+ case CTF_K_POINTER:
+ case CTF_K_TYPEDEF:
+ case CTF_K_VOLATILE:
+ case CTF_K_CONST:
+ case CTF_K_RESTRICT:
+ break;
+ default:
+ return 0;
+ }
+
+ return tlen;
+}
+
+void
+db_ctf_dump_object()
+{
+ uint32_t objtoff = db_ctf.cth->cth_objtoff;
+ size_t idx = 0, i = 0;
+ uint16_t *dsp;
+ Elf_Sym *st;
+ int l;
+ char *name;
+
+ while (objtoff < db_ctf.cth->cth_funcoff) {
+ dsp = (uint16_t *)(db_ctf.data + objtoff);
+
+ l = db_printf(" [%zu] %u", i++, *dsp);
+ if ((st = db_ctf_idx2sym(&idx, STT_OBJECT)) != NULL) {
+ db_symbol_values(st, &name, NULL);
+ db_printf("%*s %s (%zu)\n", (14 - l), "", name, idx);
+ } else
+ db_printf("\n");
+
+ objtoff += sizeof(*dsp);
+ }
+ db_printf("\n");
+}
+
+const struct ctf_type *
+db_ctf_type_by_symbol(Elf_Sym *st)
+{
+ Elf_Sym *symp;
+ uint32_t objtoff = db_ctf.cth->cth_objtoff;
+ uint16_t *dsp;
+ size_t idx = 0;
+
+ while (objtoff < db_ctf.cth->cth_funcoff) {
+ dsp = (uint16_t *)(db_ctf.data + objtoff);
+
+ symp = db_ctf_idx2sym(&idx, STT_OBJECT);
+ if (symp == NULL)
+ break;
+ if (symp == st)
+ return db_ctf_type_by_index(*dsp);
+
+ objtoff += sizeof(*dsp);
+ }
+
+ return NULL;
+}
+
+const struct ctf_type *
+db_ctf_type_by_index(uint16_t index)
+{
+ uint32_t offset = db_ctf.cth->cth_typeoff;
+ uint16_t idx = 1;
+
+ if (!db_ctf.ctf_found)
+ return NULL;
+
+ while (offset < db_ctf.cth->cth_stroff) {
+ const struct ctf_type *ctt;
+ uint32_t toff;
+
+ ctt = (struct ctf_type *)(db_ctf.data + offset);
+ if (idx == index)
+ return ctt;
+
+ toff = db_ctf_type_len(ctt);
+ if (toff == 0) {
+ db_printf("incorrect type at offset %u", offset);
+ break;
+ }
+ offset += toff;
+ idx++;
+ }
+
+ return NULL;
+}
+
+void
+db_ctf_pprintf(const struct ctf_type *ctt, vaddr_t addr)
+{
+ const struct ctf_type *ref;
+ uint16_t kind;
+ const char *name;
+
+ kind = CTF_INFO_KIND(ctt->ctt_info);
+
+ switch (kind) {
+ case CTF_K_FLOAT:
+ case CTF_K_ENUM:
+ case CTF_K_ARRAY:
+ case CTF_K_FUNCTION:
+ db_printf("%lu", *((unsigned long *)addr));
+ break;
+ case CTF_K_INTEGER:
+ db_printf("%d", *((int *)addr));
+ break;
+ case CTF_K_STRUCT:
+ case CTF_K_UNION:
+ db_ctf_pprint_struct(ctt, addr);
+ break;
+ case CTF_K_POINTER:
+ ref = db_ctf_type_by_index(ctt->ctt_type);
+ name = db_ctf_off2name(ref->ctt_name);
+ if (name != NULL)
+ db_printf("(%s *)", name);
+ db_printf("0x%lx", addr);
+ break;
+ case CTF_K_TYPEDEF:
+ case CTF_K_VOLATILE:
+ case CTF_K_CONST:
+ case CTF_K_RESTRICT:
+ ref = db_ctf_type_by_index(ctt->ctt_type);
+ db_ctf_pprintf(ref, addr);
+ break;
+ case CTF_K_UNKNOWN:
+ case CTF_K_FORWARD:
+ default:
+ break;
+ }
+}
+
+void
+db_ctf_pprint_struct(const struct ctf_type *ctt, vaddr_t addr)
+{
+ const char *name, *p = (const char *)ctt;
+ const struct ctf_type *ref;
+ uint32_t toff;
+ uint64_t size;
+ uint16_t i, vlen;
+
+ vlen = CTF_INFO_VLEN(ctt->ctt_info);
+
+ if (ctt->ctt_size <= CTF_MAX_SIZE) {
+ size = ctt->ctt_size;
+ toff = sizeof(struct ctf_stype);
+ } else {
+ size = CTF_TYPE_LSIZE(ctt);
+ toff = sizeof(struct ctf_type);
+ }
+
+ db_printf("{");
+ if (size < CTF_LSTRUCT_THRESH) {
+
+ for (i = 0; i < vlen; i++) {
+ struct ctf_member *ctm;
+
+ ctm = (struct ctf_member *)(p + toff);
+ toff += sizeof(struct ctf_member);
+
+ name = db_ctf_off2name(ctm->ctm_name);
+ if (name != NULL)
+ db_printf("%s = ", name);
+ ref = db_ctf_type_by_index(ctm->ctm_type);
+ db_ctf_pprintf(ref, addr + ctm->ctm_offset / 8);
+ if (i < vlen - 1)
+ db_printf(", ");
+ }
+ } else {
+ for (i = 0; i < vlen; i++) {
+ struct ctf_lmember *ctlm;
+
+ ctlm = (struct ctf_lmember *)(p + toff);
+ toff += sizeof(struct ctf_lmember);
+
+ name = db_ctf_off2name(ctlm->ctlm_name);
+ if (name != NULL)
+ db_printf("%s = ", name);
+ ref = db_ctf_type_by_index(ctlm->ctlm_type);
+ db_ctf_pprintf(ref, addr +
+ CTF_LMEM_OFFSET(ctlm) / 8);
+ if (i < vlen - 1)
+ db_printf(", ");
+ }
+ }
+ db_printf("}");
+}
+
static const char *
-db_ctf_lookup_name(uint32_t offset)
+db_ctf_off2name(uint32_t offset)
{
const char *name;
@@ -208,7 +431,7 @@ db_ctf_lookup_name(uint32_t offset)
name = db_ctf.data + db_ctf.cth->cth_stroff + CTF_NAME_OFFSET(offset);
if (*name == '\0')
- return "(anon)";
+ return NULL;
return name;
}
@@ -258,3 +481,45 @@ exit:
free(data, M_DEVBUF, sizeof(*data));
return NULL;
}
+
+/*
+ * print <symbol name>
+ */
+void
+db_ctf_pprint_cmd(db_expr_t addr, int have_addr, db_expr_t count,
+ char *modifiers)
+{
+ Elf_Sym *st;
+ const struct ctf_type *ctt;
+ int t;
+
+ if (!db_ctf.ctf_found)
+ return;
+
+ /*
+ * Read the struct name from the debugger input.
+ */
+ t = db_read_token();
+ if (t != tIDENT) {
+ db_printf("Bad symbol name\n");
+ db_flush_lex();
+ return;
+ }
+
+ if ((st = db_symbol_by_name(db_tok_string, &addr)) == NULL) {
+ db_printf("Symbol not found %s\n", db_tok_string);
+ db_flush_lex();
+ return;
+ }
+
+
+ if ((ctt = db_ctf_type_by_symbol(st)) == NULL) {
+ db_printf("Type not found %s\n", db_tok_string);
+ db_flush_lex();
+ return;
+ }
+
+ db_printf("%s:\t", db_tok_string);
+ db_ctf_pprintf(ctt, addr);
+ db_printf("\n");
+}
diff --git a/sys/ddb/db_elf.c b/sys/ddb/db_elf.c
index fe4872e9a25..dbf41c127af 100644
--- a/sys/ddb/db_elf.c
+++ b/sys/ddb/db_elf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: db_elf.c,v 1.26 2017/05/30 15:39:05 mpi Exp $ */
+/* $OpenBSD: db_elf.c,v 1.27 2017/08/10 19:39:38 mpi Exp $ */
/* $NetBSD: db_elf.c,v 1.13 2000/07/07 21:55:18 jhawk Exp $ */
/*-
@@ -431,14 +431,14 @@ db_elf_sym_forall(db_forall_func_t db_forall_func, void *arg)
}
}
-int
-db_value_of_name(char *name, db_expr_t *valuep)
+Elf_Sym *
+db_symbol_by_name(char *name, db_expr_t *valuep)
{
Elf_Sym *sym;
sym = db_elf_sym_lookup(name);
if (sym == NULL)
- return (0);
+ return (NULL);
db_symbol_values(sym, &name, valuep);
- return (1);
+ return (sym);
}
diff --git a/sys/ddb/db_expr.c b/sys/ddb/db_expr.c
index 387df7cb0b0..7c68b1ca1dd 100644
--- a/sys/ddb/db_expr.c
+++ b/sys/ddb/db_expr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: db_expr.c,v 1.13 2016/04/19 12:23:25 mpi Exp $ */
+/* $OpenBSD: db_expr.c,v 1.14 2017/08/10 19:39:38 mpi Exp $ */
/* $NetBSD: db_expr.c,v 1.5 1996/02/05 01:56:58 christos Exp $ */
/*
@@ -54,7 +54,7 @@ db_term(db_expr_t *valuep)
t = db_read_token();
if (t == tIDENT) {
- if (!db_value_of_name(db_tok_string, valuep)) {
+ if (db_symbol_by_name(db_tok_string, valuep) == NULL) {
db_error("Symbol not found\n");
/*NOTREACHED*/
}
diff --git a/sys/ddb/db_sym.h b/sys/ddb/db_sym.h
index df24cc1cfc7..50a5b2f4b24 100644
--- a/sys/ddb/db_sym.h
+++ b/sys/ddb/db_sym.h
@@ -65,7 +65,7 @@ extern unsigned int db_maxoff; /* like gdb's "max-symbolic-offset" */
int db_eqname(char *, char *, int);
/* strcmp, modulo leading char */
-int db_value_of_name(char *, db_expr_t *);
+Elf_Sym * db_symbol_by_name(char *, db_expr_t *);
/* find symbol value given name */
Elf_Sym * db_search_symbol(db_addr_t, db_strategy_t, db_expr_t *);
@@ -94,7 +94,10 @@ bool db_dwarf_line_at_pc(const char *, size_t, uintptr_t,
const char **, const char **, int *);
#ifdef DDBCTF
-int db_ctf_func_numargs(Elf_Sym *);
+struct ctf_type;
+
+int db_ctf_func_numargs(Elf_Sym *);
+const struct ctf_type *db_ctf_type_by_name(char *);
#endif
#endif /* _DDB_DB_SYM_H_ */