Line data Source code
1 : /* $OpenBSD: db_ctf.c,v 1.27 2018/08/31 11:57:04 bluhm Exp $ */
2 :
3 : /*
4 : * Copyright (c) 2016-2017 Martin Pieuchot
5 : * Copyright (c) 2016 Jasper Lievisse Adriaanse <jasper@openbsd.org>
6 : *
7 : * Permission to use, copy, modify, and distribute this software for any
8 : * purpose with or without fee is hereby granted, provided that the above
9 : * copyright notice and this permission notice appear in all copies.
10 : *
11 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 : */
19 :
20 : #include <sys/param.h>
21 : #include <sys/stdint.h>
22 : #include <sys/systm.h>
23 : #include <sys/exec.h>
24 :
25 : #include <machine/db_machdep.h>
26 :
27 : #include <ddb/db_extern.h>
28 : #include <ddb/db_command.h>
29 : #include <ddb/db_elf.h>
30 : #include <ddb/db_lex.h>
31 : #include <ddb/db_output.h>
32 : #include <ddb/db_sym.h>
33 : #include <ddb/db_access.h>
34 :
35 : #include <sys/exec_elf.h>
36 : #include <sys/ctf.h>
37 : #include <sys/malloc.h>
38 : #include <lib/libz/zlib.h>
39 :
40 : extern db_symtab_t db_symtab;
41 :
42 : struct ddb_ctf {
43 : struct ctf_header *cth;
44 : const char *rawctf; /* raw .SUNW_ctf section */
45 : size_t rawctflen; /* raw .SUNW_ctf section size */
46 : const char *data; /* decompressed CTF data */
47 : size_t dlen; /* decompressed CTF data size */
48 : char *strtab; /* ELF string table */
49 : uint32_t ctf_found;
50 : };
51 :
52 : struct ddb_ctf db_ctf;
53 :
54 : static const char *db_ctf_off2name(uint32_t);
55 : static Elf_Sym *db_ctf_idx2sym(size_t *, uint8_t);
56 : static char *db_ctf_decompress(const char *, size_t, off_t);
57 :
58 : const struct ctf_type *db_ctf_type_by_name(const char *, unsigned int);
59 : const struct ctf_type *db_ctf_type_by_symbol(Elf_Sym *);
60 : const struct ctf_type *db_ctf_type_by_index(uint16_t);
61 : void db_ctf_pprint(const struct ctf_type *, vaddr_t);
62 : void db_ctf_pprint_struct(const struct ctf_type *, vaddr_t);
63 : void db_ctf_pprint_ptr(const struct ctf_type *, vaddr_t);
64 :
65 : /*
66 : * Entrypoint to verify CTF presence, initialize the header, decompress
67 : * the data, etc.
68 : */
69 : void
70 0 : db_ctf_init(void)
71 : {
72 : db_symtab_t *stab = &db_symtab;
73 0 : size_t rawctflen;
74 :
75 : /* Assume nothing was correct found until proven otherwise. */
76 0 : db_ctf.ctf_found = 0;
77 :
78 0 : if (stab->private == NULL)
79 0 : return;
80 :
81 0 : db_ctf.strtab = db_elf_find_strtab(stab);
82 0 : if (db_ctf.strtab == NULL)
83 0 : return;
84 :
85 0 : db_ctf.rawctf = db_elf_find_section(stab, &rawctflen, ELF_CTF);
86 0 : if (db_ctf.rawctf == NULL)
87 0 : return;
88 :
89 0 : db_ctf.rawctflen = rawctflen;
90 0 : db_ctf.cth = (struct ctf_header *)db_ctf.rawctf;
91 0 : db_ctf.dlen = db_ctf.cth->cth_stroff + db_ctf.cth->cth_strlen;
92 :
93 0 : if ((db_ctf.cth->cth_flags & CTF_F_COMPRESS) == 0) {
94 0 : db_printf("unsupported non-compressed CTF section\n");
95 0 : return;
96 : }
97 :
98 : /* Now decompress the section, take into account to skip the header */
99 0 : db_ctf.data = db_ctf_decompress(db_ctf.rawctf + sizeof(*db_ctf.cth),
100 0 : db_ctf.rawctflen - sizeof(*db_ctf.cth), db_ctf.dlen);
101 0 : if (db_ctf.data == NULL)
102 0 : return;
103 :
104 : /* We made it this far, everything seems fine. */
105 0 : db_ctf.ctf_found = 1;
106 0 : }
107 :
108 : /*
109 : * Convert an index to a symbol name while ensuring the type is matched.
110 : * It must be noted this only works if the CTF table has the same order
111 : * as the symbol table.
112 : */
113 : Elf_Sym *
114 0 : db_ctf_idx2sym(size_t *idx, uint8_t type)
115 : {
116 : Elf_Sym *symp, *symtab_start, *symtab_end;
117 0 : size_t i = *idx + 1;
118 :
119 0 : symtab_start = STAB_TO_SYMSTART(&db_symtab);
120 0 : symtab_end = STAB_TO_SYMEND(&db_symtab);
121 :
122 0 : for (symp = &symtab_start[i]; symp < symtab_end; i++, symp++) {
123 0 : if (ELF_ST_TYPE(symp->st_info) != type)
124 : continue;
125 :
126 0 : *idx = i;
127 0 : return symp;
128 : }
129 :
130 0 : return NULL;
131 0 : }
132 :
133 : /*
134 : * For a given function name, return the number of arguments.
135 : */
136 : int
137 0 : db_ctf_func_numargs(Elf_Sym *st)
138 : {
139 : Elf_Sym *symp;
140 : uint16_t *fstart, *fend;
141 : uint16_t *fsp, kind, vlen;
142 0 : size_t i, idx = 0;
143 :
144 0 : if (!db_ctf.ctf_found || st == NULL)
145 0 : return -1;
146 :
147 0 : fstart = (uint16_t *)(db_ctf.data + db_ctf.cth->cth_funcoff);
148 0 : fend = (uint16_t *)(db_ctf.data + db_ctf.cth->cth_typeoff);
149 :
150 : fsp = fstart;
151 0 : while (fsp < fend) {
152 0 : symp = db_ctf_idx2sym(&idx, STT_FUNC);
153 0 : if (symp == NULL)
154 : break;
155 :
156 0 : kind = CTF_INFO_KIND(*fsp);
157 0 : vlen = CTF_INFO_VLEN(*fsp);
158 0 : fsp++;
159 :
160 0 : if (kind == CTF_K_UNKNOWN && vlen == 0)
161 0 : continue;
162 :
163 : /* Skip return type */
164 0 : fsp++;
165 :
166 : /* Skip argument types */
167 0 : for (i = 0; i < vlen; i++)
168 0 : fsp++;
169 :
170 0 : if (symp == st)
171 0 : return vlen;
172 : }
173 :
174 0 : return -1;
175 0 : }
176 :
177 : /*
178 : * Return the length of the type record in the CTF section.
179 : */
180 : uint32_t
181 0 : db_ctf_type_len(const struct ctf_type *ctt)
182 : {
183 : uint16_t kind, vlen, i;
184 : uint32_t tlen;
185 : uint64_t size;
186 :
187 0 : kind = CTF_INFO_KIND(ctt->ctt_info);
188 0 : vlen = CTF_INFO_VLEN(ctt->ctt_info);
189 :
190 0 : if (ctt->ctt_size <= CTF_MAX_SIZE) {
191 0 : size = ctt->ctt_size;
192 : tlen = sizeof(struct ctf_stype);
193 0 : } else {
194 0 : size = CTF_TYPE_LSIZE(ctt);
195 : tlen = sizeof(struct ctf_type);
196 : }
197 :
198 0 : switch (kind) {
199 : case CTF_K_UNKNOWN:
200 : case CTF_K_FORWARD:
201 : break;
202 : case CTF_K_INTEGER:
203 0 : tlen += sizeof(uint32_t);
204 0 : break;
205 : case CTF_K_FLOAT:
206 0 : tlen += sizeof(uint32_t);
207 0 : break;
208 : case CTF_K_ARRAY:
209 0 : tlen += sizeof(struct ctf_array);
210 0 : break;
211 : case CTF_K_FUNCTION:
212 0 : tlen += (vlen + (vlen & 1)) * sizeof(uint16_t);
213 0 : break;
214 : case CTF_K_STRUCT:
215 : case CTF_K_UNION:
216 0 : if (size < CTF_LSTRUCT_THRESH) {
217 0 : for (i = 0; i < vlen; i++) {
218 0 : tlen += sizeof(struct ctf_member);
219 : }
220 : } else {
221 0 : for (i = 0; i < vlen; i++) {
222 0 : tlen += sizeof(struct ctf_lmember);
223 : }
224 : }
225 : break;
226 : case CTF_K_ENUM:
227 0 : for (i = 0; i < vlen; i++) {
228 0 : tlen += sizeof(struct ctf_enum);
229 : }
230 : break;
231 : case CTF_K_POINTER:
232 : case CTF_K_TYPEDEF:
233 : case CTF_K_VOLATILE:
234 : case CTF_K_CONST:
235 : case CTF_K_RESTRICT:
236 : break;
237 : default:
238 0 : return 0;
239 : }
240 :
241 0 : return tlen;
242 0 : }
243 :
244 : /*
245 : * Return the CTF type associated to an ELF symbol.
246 : */
247 : const struct ctf_type *
248 0 : db_ctf_type_by_symbol(Elf_Sym *st)
249 : {
250 : Elf_Sym *symp;
251 0 : uint32_t objtoff = db_ctf.cth->cth_objtoff;
252 : uint16_t *dsp;
253 0 : size_t idx = 0;
254 :
255 0 : if (!db_ctf.ctf_found || st == NULL)
256 0 : return NULL;
257 :
258 0 : while (objtoff < db_ctf.cth->cth_funcoff) {
259 0 : dsp = (uint16_t *)(db_ctf.data + objtoff);
260 :
261 0 : symp = db_ctf_idx2sym(&idx, STT_OBJECT);
262 0 : if (symp == NULL)
263 : break;
264 0 : if (symp == st)
265 0 : return db_ctf_type_by_index(*dsp);
266 :
267 0 : objtoff += sizeof(*dsp);
268 : }
269 :
270 0 : return NULL;
271 0 : }
272 :
273 : const struct ctf_type *
274 0 : db_ctf_type_by_name(const char *name, unsigned int kind)
275 : {
276 : struct ctf_header *cth;
277 : const struct ctf_type *ctt;
278 : const char *tname;
279 : uint32_t off, toff;
280 :
281 0 : if (!db_ctf.ctf_found)
282 0 : return (NULL);
283 :
284 0 : cth = db_ctf.cth;
285 :
286 0 : for (off = cth->cth_typeoff; off < cth->cth_stroff; off += toff) {
287 0 : ctt = (struct ctf_type *)(db_ctf.data + off);
288 0 : toff = db_ctf_type_len(ctt);
289 0 : if (toff == 0) {
290 0 : db_printf("incorrect type at offset %u", off);
291 0 : break;
292 : }
293 :
294 0 : if (CTF_INFO_KIND(ctt->ctt_info) != kind)
295 : continue;
296 :
297 0 : tname = db_ctf_off2name(ctt->ctt_name);
298 0 : if (tname == NULL)
299 : continue;
300 :
301 0 : if (strcmp(name, tname) == 0)
302 0 : return (ctt);
303 : }
304 :
305 0 : return (NULL);
306 0 : }
307 :
308 : /*
309 : * Return the CTF type corresponding to a given index in the type section.
310 : */
311 : const struct ctf_type *
312 0 : db_ctf_type_by_index(uint16_t index)
313 : {
314 0 : uint32_t offset = db_ctf.cth->cth_typeoff;
315 : uint16_t idx = 1;
316 :
317 0 : if (!db_ctf.ctf_found)
318 0 : return NULL;
319 :
320 0 : while (offset < db_ctf.cth->cth_stroff) {
321 : const struct ctf_type *ctt;
322 : uint32_t toff;
323 :
324 0 : ctt = (struct ctf_type *)(db_ctf.data + offset);
325 0 : if (idx == index)
326 0 : return ctt;
327 :
328 0 : toff = db_ctf_type_len(ctt);
329 0 : if (toff == 0) {
330 0 : db_printf("incorrect type at offset %u", offset);
331 0 : break;
332 : }
333 0 : offset += toff;
334 0 : idx++;
335 0 : }
336 :
337 0 : return NULL;
338 0 : }
339 :
340 : /*
341 : * Pretty print `addr'.
342 : */
343 : void
344 0 : db_ctf_pprint(const struct ctf_type *ctt, vaddr_t addr)
345 : {
346 0 : db_addr_t taddr = (db_addr_t)ctt;
347 : const struct ctf_type *ref;
348 : uint16_t kind;
349 : uint32_t eob, toff;
350 :
351 0 : kind = CTF_INFO_KIND(ctt->ctt_info);
352 0 : if (ctt->ctt_size <= CTF_MAX_SIZE)
353 0 : toff = sizeof(struct ctf_stype);
354 : else
355 : toff = sizeof(struct ctf_type);
356 :
357 0 : switch (kind) {
358 : case CTF_K_FLOAT:
359 : case CTF_K_ENUM:
360 : case CTF_K_ARRAY:
361 : case CTF_K_FUNCTION:
362 0 : db_printf("%lu", *((unsigned long *)addr));
363 0 : break;
364 : case CTF_K_INTEGER:
365 0 : eob = db_get_value((taddr + toff), sizeof(eob), 0);
366 0 : switch (CTF_INT_BITS(eob)) {
367 : case 64:
368 0 : db_printf("0x%llx", *((long long *)addr));
369 0 : break;
370 : default:
371 0 : db_printf("0x%x", *((int *)addr));
372 0 : break;
373 : }
374 : break;
375 : case CTF_K_STRUCT:
376 : case CTF_K_UNION:
377 0 : db_ctf_pprint_struct(ctt, addr);
378 0 : break;
379 : case CTF_K_POINTER:
380 0 : db_ctf_pprint_ptr(ctt, addr);
381 0 : break;
382 : case CTF_K_TYPEDEF:
383 : case CTF_K_VOLATILE:
384 : case CTF_K_CONST:
385 : case CTF_K_RESTRICT:
386 0 : ref = db_ctf_type_by_index(ctt->ctt_type);
387 0 : db_ctf_pprint(ref, addr);
388 0 : break;
389 : case CTF_K_UNKNOWN:
390 : case CTF_K_FORWARD:
391 : default:
392 : break;
393 : }
394 0 : }
395 :
396 : void
397 0 : db_ctf_pprint_struct(const struct ctf_type *ctt, vaddr_t addr)
398 : {
399 0 : const char *name, *p = (const char *)ctt;
400 : const struct ctf_type *ref;
401 : uint32_t toff;
402 : uint64_t size;
403 : uint16_t i, vlen;
404 :
405 0 : vlen = CTF_INFO_VLEN(ctt->ctt_info);
406 :
407 0 : if (ctt->ctt_size <= CTF_MAX_SIZE) {
408 0 : size = ctt->ctt_size;
409 : toff = sizeof(struct ctf_stype);
410 0 : } else {
411 0 : size = CTF_TYPE_LSIZE(ctt);
412 : toff = sizeof(struct ctf_type);
413 : }
414 :
415 0 : db_printf("{");
416 0 : if (size < CTF_LSTRUCT_THRESH) {
417 :
418 0 : for (i = 0; i < vlen; i++) {
419 : struct ctf_member *ctm;
420 :
421 0 : ctm = (struct ctf_member *)(p + toff);
422 0 : toff += sizeof(struct ctf_member);
423 :
424 0 : name = db_ctf_off2name(ctm->ctm_name);
425 0 : if (name != NULL)
426 0 : db_printf("%s = ", name);
427 0 : ref = db_ctf_type_by_index(ctm->ctm_type);
428 0 : db_ctf_pprint(ref, addr + ctm->ctm_offset / 8);
429 0 : if (i < vlen - 1)
430 0 : db_printf(", ");
431 : }
432 : } else {
433 0 : for (i = 0; i < vlen; i++) {
434 : struct ctf_lmember *ctlm;
435 :
436 0 : ctlm = (struct ctf_lmember *)(p + toff);
437 0 : toff += sizeof(struct ctf_lmember);
438 :
439 0 : name = db_ctf_off2name(ctlm->ctlm_name);
440 0 : if (name != NULL)
441 0 : db_printf("%s = ", name);
442 0 : ref = db_ctf_type_by_index(ctlm->ctlm_type);
443 0 : db_ctf_pprint(ref, addr +
444 0 : CTF_LMEM_OFFSET(ctlm) / 8);
445 0 : if (i < vlen - 1)
446 0 : db_printf(", ");
447 : }
448 : }
449 0 : db_printf("}");
450 0 : }
451 :
452 : void
453 0 : db_ctf_pprint_ptr(const struct ctf_type *ctt, vaddr_t addr)
454 : {
455 : const char *name, *modif = "";
456 : const struct ctf_type *ref;
457 : uint16_t kind;
458 : unsigned long ptr;
459 :
460 0 : ref = db_ctf_type_by_index(ctt->ctt_type);
461 0 : kind = CTF_INFO_KIND(ref->ctt_info);
462 :
463 0 : switch (kind) {
464 : case CTF_K_VOLATILE:
465 : modif = "volatile ";
466 0 : ref = db_ctf_type_by_index(ref->ctt_type);
467 0 : break;
468 : case CTF_K_CONST:
469 : modif = "const ";
470 0 : ref = db_ctf_type_by_index(ref->ctt_type);
471 0 : break;
472 : case CTF_K_STRUCT:
473 : modif = "struct ";
474 0 : break;
475 : case CTF_K_UNION:
476 : modif = "union ";
477 0 : break;
478 : default:
479 : break;
480 : }
481 :
482 0 : name = db_ctf_off2name(ref->ctt_name);
483 0 : if (name != NULL)
484 0 : db_printf("(%s%s *)", modif, name);
485 :
486 0 : ptr = (unsigned long)db_get_value(addr, sizeof(ptr), 0);
487 :
488 0 : db_printf("0x%lx", ptr);
489 0 : }
490 :
491 : static const char *
492 0 : db_ctf_off2name(uint32_t offset)
493 : {
494 : const char *name;
495 :
496 0 : if (CTF_NAME_STID(offset) != CTF_STRTAB_0)
497 0 : return "external";
498 :
499 0 : if (CTF_NAME_OFFSET(offset) >= db_ctf.cth->cth_strlen)
500 0 : return "exceeds strlab";
501 :
502 0 : if (db_ctf.cth->cth_stroff + CTF_NAME_OFFSET(offset) >= db_ctf.dlen)
503 0 : return "invalid";
504 :
505 0 : name = db_ctf.data + db_ctf.cth->cth_stroff + CTF_NAME_OFFSET(offset);
506 0 : if (*name == '\0')
507 0 : return NULL;
508 :
509 0 : return name;
510 0 : }
511 :
512 : static char *
513 0 : db_ctf_decompress(const char *buf, size_t size, off_t len)
514 : {
515 0 : z_stream stream;
516 : char *data;
517 : int error;
518 :
519 0 : data = malloc(len, M_TEMP, M_WAITOK|M_ZERO|M_CANFAIL);
520 0 : if (data == NULL)
521 0 : return NULL;
522 :
523 0 : memset(&stream, 0, sizeof(stream));
524 0 : stream.next_in = (void *)buf;
525 0 : stream.avail_in = size;
526 0 : stream.next_out = data;
527 0 : stream.avail_out = len;
528 :
529 0 : if ((error = inflateInit(&stream)) != Z_OK) {
530 0 : db_printf("zlib inflateInit failed: %s", zError(error));
531 0 : goto exit;
532 : }
533 :
534 0 : if ((error = inflate(&stream, Z_FINISH)) != Z_STREAM_END) {
535 0 : db_printf("zlib inflate failed: %s", zError(error));
536 0 : inflateEnd(&stream);
537 0 : goto exit;
538 : }
539 :
540 0 : if ((error = inflateEnd(&stream)) != Z_OK) {
541 0 : db_printf("zlib inflateEnd failed: %s", zError(error));
542 0 : goto exit;
543 : }
544 :
545 0 : if (stream.total_out != len) {
546 0 : db_printf("decompression failed: %llu != %llu",
547 : stream.total_out, len);
548 0 : goto exit;
549 : }
550 :
551 0 : return data;
552 :
553 : exit:
554 0 : free(data, M_DEVBUF, len);
555 0 : return NULL;
556 0 : }
557 :
558 : /*
559 : * pprint <symbol name>
560 : */
561 : void
562 0 : db_ctf_pprint_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
563 : {
564 : Elf_Sym *st;
565 : const struct ctf_type *ctt;
566 : int t;
567 :
568 0 : if (!db_ctf.ctf_found) {
569 0 : db_printf("No CTF data found\n");
570 0 : db_flush_lex();
571 0 : return;
572 : }
573 :
574 : /*
575 : * Read the struct name from the debugger input.
576 : */
577 0 : t = db_read_token();
578 0 : if (t != tIDENT) {
579 0 : db_printf("Bad symbol name\n");
580 0 : db_flush_lex();
581 0 : return;
582 : }
583 :
584 0 : if ((st = db_symbol_by_name(db_tok_string, &addr)) == NULL) {
585 0 : db_printf("Symbol not found %s\n", db_tok_string);
586 0 : db_flush_lex();
587 0 : return;
588 : }
589 :
590 0 : if ((ctt = db_ctf_type_by_symbol(st)) == NULL) {
591 0 : modif[0] = '\0';
592 0 : db_print_cmd(addr, 0, 0, modif);
593 0 : db_flush_lex();
594 0 : return;
595 : }
596 :
597 0 : db_printf("%s:\t", db_tok_string);
598 0 : db_ctf_pprint(ctt, addr);
599 0 : db_printf("\n");
600 0 : }
601 :
602 : /*
603 : * show struct <struct name> [addr]: displays the data starting at addr
604 : * (`dot' if unspecified) as a struct of the given type.
605 : */
606 : void
607 0 : db_ctf_show_struct(db_expr_t addr, int have_addr, db_expr_t count,
608 : char *modifiers)
609 : {
610 : const struct ctf_type *ctt;
611 : const char *name;
612 : uint64_t sz;
613 : int t;
614 :
615 : /*
616 : * Read the struct name from the debugger input.
617 : */
618 0 : t = db_read_token();
619 0 : if (t != tIDENT) {
620 0 : db_printf("Bad struct name\n");
621 0 : db_flush_lex();
622 0 : return;
623 : }
624 : name = db_tok_string;
625 :
626 0 : ctt = db_ctf_type_by_name(name, CTF_K_STRUCT);
627 0 : if (ctt == NULL) {
628 0 : db_printf("unknown struct %s\n", name);
629 0 : db_flush_lex();
630 0 : return;
631 : }
632 :
633 : /*
634 : * Read the address, if any, from the debugger input.
635 : * In that case, update `dot' value.
636 : */
637 0 : if (db_expression(&addr)) {
638 0 : db_dot = (db_addr_t)addr;
639 0 : db_last_addr = db_dot;
640 0 : } else
641 0 : addr = (db_expr_t)db_dot;
642 :
643 0 : db_skip_to_eol();
644 :
645 : /*
646 : * Display the structure contents.
647 : */
648 0 : sz = (ctt->ctt_size <= CTF_MAX_SIZE) ?
649 0 : ctt->ctt_size : CTF_TYPE_LSIZE(ctt);
650 0 : db_printf("struct %s at %p (%llu bytes) ", name, (void *)addr, sz);
651 0 : db_ctf_pprint_struct(ctt, addr);
652 0 : }
|