diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2024-02-22 13:49:18 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2024-02-22 13:49:18 +0000 |
commit | 7770f74fd8836e5e6edc1c2bd3aa9cc0d67d54d4 (patch) | |
tree | d362c8808a0bd7de65e18a60b8f8dae062b53d4d | |
parent | 32d9373dbb03f16cff036e06f466595e5d4f3670 (diff) |
Improve db_ctf_pprint(), implement handlers for arrays and enums.
Use db_get_value() to access addr to ensure that alignment errors
don't cause exceptions. DDB on 32bit archs does normally not handle
64bit values so to print 64bit ints a bit of gymnastics is needed.
OK mpi@
-rw-r--r-- | sys/ddb/db_ctf.c | 155 |
1 files changed, 146 insertions, 9 deletions
diff --git a/sys/ddb/db_ctf.c b/sys/ddb/db_ctf.c index 1aed046b3e4..4a490e935fa 100644 --- a/sys/ddb/db_ctf.c +++ b/sys/ddb/db_ctf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: db_ctf.c,v 1.33 2022/08/14 14:57:38 millert Exp $ */ +/* $OpenBSD: db_ctf.c,v 1.34 2024/02/22 13:49:17 claudio Exp $ */ /* * Copyright (c) 2016-2017 Martin Pieuchot @@ -55,11 +55,14 @@ 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, size_t); +uint32_t db_ctf_type_len(const struct ctf_type *); +size_t db_ctf_type_size(const struct ctf_type *); const struct ctf_type *db_ctf_type_by_name(const char *, unsigned int); 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(const struct ctf_type *, vaddr_t); void db_ctf_pprint_struct(const struct ctf_type *, vaddr_t); +void db_ctf_pprint_enum(const struct ctf_type *, vaddr_t); void db_ctf_pprint_ptr(const struct ctf_type *, vaddr_t); /* @@ -242,6 +245,68 @@ db_ctf_type_len(const struct ctf_type *ctt) } /* + * Return the size of the type. + */ +size_t +db_ctf_type_size(const struct ctf_type *ctt) +{ + vaddr_t taddr = (vaddr_t)ctt; + const struct ctf_type *ref; + const struct ctf_array *arr; + size_t tlen = 0; + uint16_t kind; + uint32_t toff; + uint64_t size; + + kind = CTF_INFO_KIND(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); + } + + switch (kind) { + case CTF_K_UNKNOWN: + case CTF_K_FORWARD: + break; + case CTF_K_INTEGER: + case CTF_K_FLOAT: + tlen = size; + break; + case CTF_K_ARRAY: + arr = (struct ctf_array *)(taddr + toff); + ref = db_ctf_type_by_index(arr->cta_contents); + tlen = arr->cta_nelems * db_ctf_type_size(ref); + break; + case CTF_K_FUNCTION: + tlen = 0; + break; + case CTF_K_STRUCT: + case CTF_K_UNION: + case CTF_K_ENUM: + tlen = size; + break; + case CTF_K_POINTER: + tlen = sizeof(void *); + 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); + tlen = db_ctf_type_size(ref); + break; + default: + return 0; + } + + return tlen; +} + +/* * Return the CTF type associated to an ELF symbol. */ const struct ctf_type * @@ -347,8 +412,14 @@ db_ctf_pprint(const struct ctf_type *ctt, vaddr_t addr) { vaddr_t taddr = (vaddr_t)ctt; const struct ctf_type *ref; + const struct ctf_array *arr; uint16_t kind; - uint32_t eob, toff; + uint32_t eob, toff, i; + db_expr_t val; + size_t elm_size; + + if (ctt == NULL) + return; kind = CTF_INFO_KIND(ctt->ctt_info); if (ctt->ctt_size <= CTF_MAX_SIZE) @@ -357,20 +428,58 @@ db_ctf_pprint(const struct ctf_type *ctt, vaddr_t addr) toff = sizeof(struct ctf_type); switch (kind) { - case CTF_K_FLOAT: - case CTF_K_ENUM: case CTF_K_ARRAY: + arr = (struct ctf_array *)(taddr + toff); + ref = db_ctf_type_by_index(arr->cta_contents); + elm_size = db_ctf_type_size(ref); + db_printf("["); + for (i = 0; i < arr->cta_nelems; i++) { + db_ctf_pprint(ref, addr + i * elm_size); + if (i + 1 < arr->cta_nelems) + db_printf(","); + } + db_printf("]"); + break; + case CTF_K_ENUM: + db_ctf_pprint_enum(ctt, addr); + break; + case CTF_K_FLOAT: case CTF_K_FUNCTION: - db_printf("%lu", *((unsigned long *)addr)); + val = db_get_value(addr, sizeof(val), 0); + db_printf("%lx", (unsigned long)val); break; case CTF_K_INTEGER: eob = db_get_value((taddr + toff), sizeof(eob), 0); switch (CTF_INT_BITS(eob)) { - case 64: - db_printf("0x%llx", *((long long *)addr)); +#ifndef __LP64__ + case 64: { + uint64_t val64; +#if BYTE_ORDER == LITTLE_ENDIAN + val64 = db_get_value(addr + 4, CTF_INT_BITS(eob) / 8, + CTF_INT_ENCODING(eob) & CTF_INT_SIGNED); + val64 <<= 32; + val64 |= db_get_value(addr, CTF_INT_BITS(eob) / 8, 0); +#else + val64 = db_get_value(addr, CTF_INT_BITS(eob) / 8, + CTF_INT_ENCODING(eob) & CTF_INT_SIGNED); + val64 <<= 32; + val64 |= db_get_value(addr + 4, CTF_INT_BITS(eob) / 8, + 0); +#endif + if (CTF_INT_ENCODING(eob) & CTF_INT_SIGNED) + db_printf("%lld", val64); + else + db_printf("%llu", val64); break; + } +#endif default: - db_printf("0x%x", *((int *)addr)); + val = db_get_value(addr, CTF_INT_BITS(eob) / 8, + CTF_INT_ENCODING(eob) & CTF_INT_SIGNED); + if (CTF_INT_ENCODING(eob) & CTF_INT_SIGNED) + db_printf("%ld", val); + else + db_printf("%lu", val); break; } break; @@ -416,7 +525,6 @@ db_ctf_pprint_struct(const struct ctf_type *ctt, vaddr_t addr) db_printf("{"); if (size < CTF_LSTRUCT_THRESH) { - for (i = 0; i < vlen; i++) { struct ctf_member *ctm; @@ -452,6 +560,35 @@ db_ctf_pprint_struct(const struct ctf_type *ctt, vaddr_t addr) } void +db_ctf_pprint_enum(const struct ctf_type *ctt, vaddr_t addr) +{ + const char *name = NULL, *p = (const char *)ctt; + struct ctf_enum *cte; + uint32_t toff; + int32_t val; + uint16_t i, vlen; + + vlen = CTF_INFO_VLEN(ctt->ctt_info); + toff = sizeof(struct ctf_stype); + + val = (int32_t)db_get_value(addr, sizeof(val), 1); + for (i = 0; i < vlen; i++) { + cte = (struct ctf_enum *)(p + toff); + toff += sizeof(*cte); + + if (val == cte->cte_value) { + name = db_ctf_off2name(cte->cte_name); + break; + } + } + + if (name != NULL) + db_printf("%s", name); + else + db_printf("#%d", val); +} + +void db_ctf_pprint_ptr(const struct ctf_type *ctt, vaddr_t addr) { const char *name, *modif = ""; |