Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153133779
D37899.id114629.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
D37899.id114629.diff
View Options
diff --git a/sys/ddb/db_command.c b/sys/ddb/db_command.c
--- a/sys/ddb/db_command.c
+++ b/sys/ddb/db_command.c
@@ -166,6 +166,7 @@
DB_CMD("capture", db_capture_cmd, CS_OWN|DB_CMD_MEMSAFE),
DB_CMD("textdump", db_textdump_cmd, CS_OWN|DB_CMD_MEMSAFE),
DB_CMD("findstack", db_findstack_cmd, 0),
+ DB_CMD("pprint", db_pprint_cmd, CS_OWN|DB_CMD_MEMSAFE),
};
struct db_command_table db_cmd_table = LIST_HEAD_INITIALIZER(db_cmd_table);
diff --git a/sys/ddb/db_ctf.h b/sys/ddb/db_ctf.h
new file mode 100644
--- /dev/null
+++ b/sys/ddb/db_ctf.h
@@ -0,0 +1,16 @@
+#ifndef _DDB_DB_CTF_H_
+#define _DDB_DB_CTF_H_
+
+#include <sys/types.h>
+#include <sys/ctf.h>
+
+#define DB_CTF_OBJTOFF_INVALID 0xffffffff
+
+bool db_ctf_loaded(void);
+
+const ctf_header_t *db_ctf_fetch_cth(void);
+struct ctf_type_v3 *db_ctf_sym_to_type(const Elf_Sym *sym);
+struct ctf_type_v3 *db_ctf_typeid_to_type(uint32_t typeid);
+const char *db_ctf_stroff_to_str(uint32_t off);
+
+#endif /* !_DDB_DB_CTF_H_ */
diff --git a/sys/ddb/db_ctf.c b/sys/ddb/db_ctf.c
new file mode 100644
--- /dev/null
+++ b/sys/ddb/db_ctf.c
@@ -0,0 +1,245 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 1983, 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ctype.h>
+#include <sys/linker.h>
+
+#include <ddb/db_ctf.h>
+#include <ddb/ddb.h>
+
+static struct ddb_ctf {
+ linker_ctf_t kernel_ctf;
+ bool loaded;
+} db_ctf;
+
+static void
+db_ctf_init(void *arg)
+{
+ int err;
+
+ memset((void *)&db_ctf, 0, sizeof(db_ctf));
+
+ err = linker_ctf_get_ddb(linker_kernel_file, &db_ctf.kernel_ctf);
+ if (err) {
+ printf("%s: linker_ctf_get_ddb error: %d\n", __func__, err);
+ return;
+ }
+
+ printf("%s: loaded kernel CTF info\n", __func__);
+
+ db_ctf.loaded = true;
+}
+
+SYSINIT(db_ctf, SI_SUB_KLD, SI_ORDER_FOURTH, db_ctf_init, NULL);
+
+bool
+db_ctf_loaded(void)
+{
+ return db_ctf.loaded;
+}
+
+const ctf_header_t *
+db_ctf_fetch_cth(void)
+{
+ return (const ctf_header_t *)db_ctf.kernel_ctf.ctftab;
+}
+
+static uint32_t
+sym_to_objtoff(const Elf_Sym *sym, const Elf_Sym *symtab,
+ const Elf_Sym *symtab_end)
+{
+ const ctf_header_t *hp = db_ctf_fetch_cth();
+ uint32_t objtoff = hp->cth_objtoff;
+ const size_t idwidth = 4;
+
+ /* Ignore non-object symbols */
+ if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT) {
+ return DB_CTF_OBJTOFF_INVALID;
+ }
+
+ /* Sanity check */
+ if (!(sym >= symtab && sym <= symtab_end)) {
+ return DB_CTF_OBJTOFF_INVALID;
+ }
+
+ for (const Elf_Sym *symp = symtab; symp < symtab_end; symp++) {
+ /* Make sure we do not go beyond the objtoff section */
+ if (objtoff >= hp->cth_funcoff) {
+ objtoff = DB_CTF_OBJTOFF_INVALID;
+ break;
+ }
+
+ if (symp->st_name == 0 || symp->st_shndx == SHN_UNDEF) {
+ continue;
+ }
+
+ if ((symp->st_shndx == SHN_ABS && symp->st_value == 0)) {
+ continue;
+ }
+
+ /* Skip non-object symbols */
+ if (ELF_ST_TYPE(symp->st_info) != STT_OBJECT) {
+ continue;
+ }
+
+ if (symp == sym) {
+ break;
+ }
+
+ objtoff += idwidth;
+ }
+
+ return objtoff;
+}
+
+struct ctf_type_v3 *
+db_ctf_typeid_to_type(uint32_t typeid)
+{
+ const ctf_header_t *hp = db_ctf_fetch_cth();
+ const uint8_t *ctfstart = (const uint8_t *)hp + sizeof(ctf_header_t);
+
+ uint32_t typeoff = hp->cth_typeoff;
+ uint32_t stroff = hp->cth_stroff;
+ /* CTF typeids start at 0x1 */
+ size_t cur_typeid = 1;
+
+ /* Find corresponding type */
+ while (typeoff < stroff) {
+ u_int vlen, kind, size;
+ size_t skiplen, type_struct_size;
+ struct ctf_type_v3 *t =
+ (struct ctf_type_v3 *)(__DECONST(uint8_t *, ctfstart) +
+ typeoff);
+
+ vlen = CTF_V3_INFO_VLEN(t->ctt_info);
+ kind = CTF_V3_INFO_KIND(t->ctt_info);
+ size = ((t->ctt_size == CTF_V3_LSIZE_SENT) ? CTF_TYPE_LSIZE(t) :
+ t->ctt_size);
+ type_struct_size = ((t->ctt_size == CTF_V3_LSIZE_SENT) ?
+ sizeof(struct ctf_type_v3) :
+ sizeof(struct ctf_stype_v3));
+
+ switch (kind) {
+ case CTF_K_INTEGER:
+ case CTF_K_FLOAT:
+ skiplen = sizeof(uint32_t);
+ break;
+ case CTF_K_ARRAY:
+ skiplen = sizeof(struct ctf_array_v3);
+ break;
+ case CTF_K_UNION:
+ case CTF_K_STRUCT:
+ skiplen = vlen *
+ ((size < CTF_V3_LSTRUCT_THRESH) ?
+ sizeof(struct ctf_member_v3) :
+ sizeof(struct ctf_lmember_v3));
+ break;
+ case CTF_K_ENUM:
+ skiplen = vlen * sizeof(struct ctf_enum);
+ break;
+ case CTF_K_FUNCTION:
+ skiplen = vlen * sizeof(uint32_t);
+ break;
+ case CTF_K_UNKNOWN:
+ case CTF_K_FORWARD:
+ case CTF_K_POINTER:
+ case CTF_K_TYPEDEF:
+ case CTF_K_VOLATILE:
+ case CTF_K_CONST:
+ case CTF_K_RESTRICT:
+ skiplen = 0;
+ break;
+ default:
+ db_printf("Error: invalid CTF type kind encountered\n");
+ return (NULL);
+ }
+
+ /* We found the type struct */
+ if (cur_typeid == typeid) {
+ break;
+ }
+
+ cur_typeid++;
+ typeoff += type_struct_size + skiplen;
+ }
+
+ if (typeoff < stroff) {
+ return (struct ctf_type_v3 *)(__DECONST(uint8_t *, ctfstart) +
+ typeoff);
+ } else { /* A type struct was not found */
+ return (NULL);
+ }
+}
+
+const char *
+db_ctf_stroff_to_str(uint32_t off)
+{
+ const ctf_header_t *hp = db_ctf_fetch_cth();
+ uint32_t stroff = hp->cth_stroff + off;
+
+ if (stroff >= (hp->cth_stroff + hp->cth_strlen)) {
+ return "invalid";
+ }
+
+ const char *ret = ((const char *)hp + sizeof(ctf_header_t)) + stroff;
+ if (*ret == '\0') {
+ return NULL;
+ }
+
+ return ret;
+}
+
+struct ctf_type_v3 *
+db_ctf_sym_to_type(const Elf_Sym *sym)
+{
+ uint32_t objtoff, typeid;
+ const Elf_Sym *symtab, *symtab_end;
+
+ if (sym == NULL) {
+ return (NULL);
+ }
+
+ symtab = db_ctf.kernel_ctf.symtab;
+ symtab_end = symtab + db_ctf.kernel_ctf.nsym;
+
+ objtoff = sym_to_objtoff(sym, symtab, symtab_end);
+ /* Sanity check - should not happen */
+ if (objtoff == DB_CTF_OBJTOFF_INVALID) {
+ db_printf("Could not find CTF object offset.");
+ return (NULL);
+ }
+
+ typeid = *(const uint32_t *)(db_ctf.kernel_ctf.ctftab +
+ sizeof(ctf_header_t) + objtoff);
+
+ return db_ctf_typeid_to_type(typeid);
+}
diff --git a/sys/ddb/db_pprint.c b/sys/ddb/db_pprint.c
new file mode 100644
--- /dev/null
+++ b/sys/ddb/db_pprint.c
@@ -0,0 +1,395 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 1983, 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ctype.h>
+#include <sys/linker.h>
+
+#include <ddb/ddb.h>
+#include <ddb/db_access.h>
+#include <ddb/db_ctf.h>
+#include <ddb/db_lex.h>
+#include <ddb/db_sym.h>
+
+#define DB_PPRINT_DEFAULT_DEPTH 1
+
+static void db_pprint_type(db_addr_t addr, struct ctf_type_v3 *type,
+ u_int depth);
+
+static u_int max_depth = DB_PPRINT_DEFAULT_DEPTH;
+
+static inline void
+db_pprint_int(db_addr_t addr, struct ctf_type_v3 *type)
+{
+ if (db_pager_quit) {
+ return;
+ }
+
+ size_t type_struct_size = ((type->ctt_size == CTF_V3_LSIZE_SENT) ?
+ sizeof(struct ctf_type_v3) :
+ sizeof(struct ctf_stype_v3));
+ uint32_t data = db_get_value((db_expr_t)type + type_struct_size,
+ sizeof(uint32_t), 0);
+
+ u_int bits = CTF_INT_BITS(data);
+ boolean_t sign = !!(CTF_INT_ENCODING(data) & CTF_INT_SIGNED);
+
+ if (bits > 64) {
+ db_printf("Invalid size '%d' found for integer type\n", bits);
+ return;
+ }
+
+ int nbytes = (bits / 8) ? (bits / 8) : 1;
+ db_printf("0x%lx", db_get_value(addr, nbytes, sign));
+}
+
+static inline void
+db_pprint_struct(db_addr_t addr, struct ctf_type_v3 *type, u_int depth)
+{
+ const char *mname;
+
+ size_t type_struct_size = ((type->ctt_size == CTF_V3_LSIZE_SENT) ?
+ sizeof(struct ctf_type_v3) :
+ sizeof(struct ctf_stype_v3));
+ size_t struct_size = ((type->ctt_size == CTF_V3_LSIZE_SENT) ?
+ CTF_TYPE_LSIZE(type) :
+ type->ctt_size);
+ u_int vlen = CTF_V3_INFO_VLEN(type->ctt_info);
+
+ if (db_pager_quit) {
+ return;
+ }
+
+ if (depth > max_depth) {
+ db_printf("{ ... }, ");
+ return;
+ }
+
+ db_printf("{\n");
+
+ if (struct_size < CTF_V3_LSTRUCT_THRESH) {
+ struct ctf_member_v3 *mp, *endp;
+
+ mp = (struct ctf_member_v3 *)((db_addr_t)type +
+ type_struct_size);
+ endp = mp + vlen;
+
+ for (; mp < endp; mp++) {
+ if (db_pager_quit) {
+ return;
+ }
+
+ struct ctf_type_v3 *mtype = db_ctf_typeid_to_type(
+ mp->ctm_type);
+ db_addr_t maddr = addr + mp->ctm_offset;
+
+ mname = db_ctf_stroff_to_str(mp->ctm_name);
+ if (mname) {
+ db_printf("%s = ", mname);
+ }
+
+ db_pprint_type(maddr, mtype, depth + 1);
+ db_printf(", ");
+ }
+ } else {
+ struct ctf_lmember_v3 *mp, *endp;
+ mp = (struct ctf_lmember_v3 *)((db_addr_t)type +
+ type_struct_size);
+ endp = mp + vlen;
+
+ for (; mp < endp; mp++) {
+ if (db_pager_quit) {
+ return;
+ }
+
+ struct ctf_type_v3 *mtype = db_ctf_typeid_to_type(
+ mp->ctlm_type);
+ db_addr_t maddr = addr + CTF_LMEM_OFFSET(mp);
+
+ mname = db_ctf_stroff_to_str(mp->ctlm_name);
+ if (mname) {
+ db_printf("%s = ", mname);
+ }
+
+ db_pprint_type(maddr, mtype, depth + 1);
+ db_printf(", ");
+ }
+ }
+
+ db_printf("\n}");
+}
+
+static inline void
+db_pprint_arr(db_addr_t addr, struct ctf_type_v3 *type, u_int depth)
+{
+ struct ctf_array_v3 *arr;
+ struct ctf_type_v3 *elem_type;
+ size_t elem_size;
+ size_t type_struct_size = ((type->ctt_size == CTF_V3_LSIZE_SENT) ?
+ sizeof(struct ctf_type_v3) :
+ sizeof(struct ctf_stype_v3));
+
+ arr = (struct ctf_array_v3 *)((db_addr_t)type + type_struct_size);
+ elem_type = db_ctf_typeid_to_type(arr->cta_contents);
+ elem_size = ((elem_type->ctt_size == CTF_V3_LSIZE_SENT) ?
+ CTF_TYPE_LSIZE(elem_type) :
+ elem_type->ctt_size);
+
+ db_addr_t elem_addr = addr;
+ db_addr_t end = addr + (arr->cta_nelems * elem_size);
+
+ db_printf("[");
+ for (; elem_addr < end; elem_addr += elem_size) {
+ if (db_pager_quit) {
+ return;
+ }
+
+ db_pprint_type(elem_addr, elem_type, depth);
+
+ if ((elem_addr + elem_size) < end) {
+ db_printf(", ");
+ }
+ }
+ db_printf("]\n");
+}
+
+static inline void
+db_pprint_enum(db_addr_t addr, struct ctf_type_v3 *type)
+{
+ struct ctf_enum *ep, *endp;
+ const char *valname;
+ u_int vlen = CTF_V3_INFO_VLEN(type->ctt_info);
+ db_expr_t val = db_get_value(addr, sizeof(int), 0);
+ size_t type_struct_size = ((type->ctt_size == CTF_V3_LSIZE_SENT) ?
+ sizeof(struct ctf_type_v3) :
+ sizeof(struct ctf_stype_v3));
+
+ if (db_pager_quit) {
+ return;
+ }
+
+ ep = (struct ctf_enum *)((db_addr_t)type + type_struct_size);
+ endp = ep + vlen;
+
+ for (; ep < endp; ep++) {
+ if (val == ep->cte_value) {
+ valname = db_ctf_stroff_to_str(ep->cte_name);
+ if (valname) {
+ db_printf("%s ", valname);
+ }
+
+ db_printf("(0x%lx)", val);
+ break;
+ }
+ }
+}
+
+static inline void
+db_pprint_ptr(db_addr_t addr, struct ctf_type_v3 *type, u_int depth)
+{
+ const char *qual = "";
+ const char *name;
+ struct ctf_type_v3 *ref_type;
+ u_int kind;
+ db_addr_t val;
+
+ ref_type = db_ctf_typeid_to_type(type->ctt_type);
+ kind = CTF_V3_INFO_KIND(ref_type->ctt_info);
+
+ switch (kind) {
+ case CTF_K_STRUCT:
+ qual = "struct ";
+ break;
+ case CTF_K_VOLATILE:
+ qual = "volatile ";
+ break;
+ case CTF_K_CONST:
+ qual = "const ";
+ break;
+ default:
+ break;
+ }
+
+ val = db_get_value(addr, sizeof(db_addr_t), false);
+
+ if (depth < max_depth) {
+ db_pprint_type(addr, ref_type, depth + 1);
+ } else {
+
+ name = db_ctf_stroff_to_str(ref_type->ctt_name);
+ if (name) {
+ db_printf("(%s%s *)", qual, name);
+ }
+
+ db_printf("0x%lx", val);
+ }
+}
+
+static void
+db_pprint_type(db_addr_t addr, struct ctf_type_v3 *type, u_int depth)
+{
+
+ if (db_pager_quit) {
+ return;
+ }
+
+ if (type == NULL) {
+ db_printf("unknown type");
+ return;
+ }
+
+ switch (CTF_V3_INFO_KIND(type->ctt_info)) {
+ case CTF_K_INTEGER:
+ db_pprint_int(addr, type);
+ break;
+ case CTF_K_UNION:
+ case CTF_K_STRUCT:
+ db_pprint_struct(addr, type, depth);
+ break;
+ case CTF_K_FUNCTION:
+ case CTF_K_FLOAT:
+ db_printf("0x%lx", addr);
+ break;
+ case CTF_K_POINTER:
+ db_pprint_ptr(addr, type, depth);
+ break;
+ case CTF_K_TYPEDEF:
+ case CTF_K_VOLATILE:
+ case CTF_K_RESTRICT:
+ case CTF_K_CONST: {
+ struct ctf_type_v3 *ref_type = db_ctf_typeid_to_type(
+ type->ctt_type);
+ db_pprint_type(addr, ref_type, depth);
+ break;
+ }
+ case CTF_K_ENUM:
+ db_pprint_enum(addr, type);
+ break;
+ case CTF_K_ARRAY:
+ db_pprint_arr(addr, type, depth);
+ break;
+ case CTF_K_UNKNOWN:
+ case CTF_K_FORWARD:
+ default:
+ break;
+ }
+}
+
+static int
+db_pprint_symbol(const Elf_Sym *sym)
+{
+ db_addr_t addr = sym->st_value;
+ struct ctf_type_v3 *type = NULL;
+ db_expr_t _val;
+
+ const char *sym_name = NULL;
+ const char *type_name = NULL;
+
+ if (db_pager_quit) {
+ return -1;
+ }
+
+ type = db_ctf_sym_to_type(sym);
+ if (!type) {
+ db_printf("Cant find CTF type info\n");
+ return -1;
+ }
+
+ db_symbol_values((c_db_sym_t)sym, &sym_name, &_val);
+ type_name = db_ctf_stroff_to_str(type->ctt_name);
+
+ if (type_name) {
+ db_printf("%s ", type_name);
+ }
+ if (sym_name) {
+ db_printf("%s = ", sym_name);
+ }
+
+ db_pprint_type(addr, type, 0);
+
+ return 0;
+}
+
+/*
+ * Pretty print an address.
+ * Syntax: pprint [/d depth] addr
+ */
+void
+db_pprint_cmd(db_expr_t addr, bool have_addr, db_expr_t count, char *modif)
+{
+ int t = 0;
+ Elf_Sym *sym;
+ db_expr_t off;
+
+ if (!db_ctf_loaded()) {
+ db_error("Kernel CTF data not present\n");
+ }
+
+ /* Parse print modifiers */
+ t = db_read_token();
+ if (t == tSLASH) {
+ t = db_read_token();
+ if (t != tIDENT) {
+ db_error("Invalid flag passed\n");
+ }
+ /* Fetch desired depth level */
+ if (!strcmp(db_tok_string, "d")) {
+ t = db_read_token();
+ if (t != tNUMBER) {
+ db_error("Invalid depth provided\n");
+ }
+ max_depth = db_tok_number;
+ } else {
+ db_error("Invalid flag passed\n");
+ }
+ /* Fetch next token */
+ t = db_read_token();
+ }
+
+ if (t != tNUMBER) {
+ db_error("No address supplied\n");
+ }
+
+ addr = db_tok_number;
+
+ sym = __DECONST(Elf_Sym *, db_search_symbol(addr, DB_STGY_ANY, &off));
+ if (sym == NULL) {
+ db_error("Symbol not found\n");
+ }
+
+ if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT) {
+ db_error("Symbol is not a variable\n");
+ }
+
+ if (db_pprint_symbol(sym)) {
+ db_error("");
+ }
+}
diff --git a/sys/ddb/ddb.h b/sys/ddb/ddb.h
--- a/sys/ddb/ddb.h
+++ b/sys/ddb/ddb.h
@@ -275,6 +275,7 @@
db_cmdfcn_t db_unscript_cmd;
db_cmdfcn_t db_watchpoint_cmd;
db_cmdfcn_t db_write_cmd;
+db_cmdfcn_t db_pprint_cmd;
/*
* Interface between DDB and the DDB output capture facility.
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Apr 20, 9:45 AM (18 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31831073
Default Alt Text
D37899.id114629.diff (16 KB)
Attached To
Mode
D37899: ddb: Add basic CTF support [2/2]
Attached
Detach File
Event Timeline
Log In to Comment