xref: /openbsd-src/sys/ddb/db_ctf.c (revision 3374c67d44f9b75b98444cbf63020f777792342e)
1 /*	$OpenBSD: db_ctf.c,v 1.33 2022/08/14 14:57:38 millert 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, size_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 db_ctf_init(void)
71 {
72 	db_symtab_t *stab = &db_symtab;
73 	size_t rawctflen;
74 
75 	/* Assume nothing was correct found until proven otherwise. */
76 	db_ctf.ctf_found = 0;
77 
78 	if (stab->private == NULL)
79 		return;
80 
81 	db_ctf.strtab = db_elf_find_strtab(stab);
82 	if (db_ctf.strtab == NULL)
83 		return;
84 
85 	db_ctf.rawctf = db_elf_find_section(stab, &rawctflen, ELF_CTF);
86 	if (db_ctf.rawctf == NULL)
87 		return;
88 
89 	db_ctf.rawctflen = rawctflen;
90 	db_ctf.cth = (struct ctf_header *)db_ctf.rawctf;
91 	db_ctf.dlen = db_ctf.cth->cth_stroff + db_ctf.cth->cth_strlen;
92 
93 	if ((db_ctf.cth->cth_flags & CTF_F_COMPRESS) == 0) {
94 		db_printf("unsupported non-compressed CTF section\n");
95 		return;
96 	}
97 
98 	/* Now decompress the section, take into account to skip the header */
99 	db_ctf.data = db_ctf_decompress(db_ctf.rawctf + sizeof(*db_ctf.cth),
100 	    db_ctf.rawctflen - sizeof(*db_ctf.cth), db_ctf.dlen);
101 	if (db_ctf.data == NULL)
102 		return;
103 
104 	/* We made it this far, everything seems fine. */
105 	db_ctf.ctf_found = 1;
106 }
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 db_ctf_idx2sym(size_t *idx, uint8_t type)
115 {
116 	Elf_Sym *symp, *symtab_start, *symtab_end;
117 	size_t i = *idx + 1;
118 
119 	symtab_start = STAB_TO_SYMSTART(&db_symtab);
120 	symtab_end = STAB_TO_SYMEND(&db_symtab);
121 
122 	for (symp = &symtab_start[i]; symp < symtab_end; i++, symp++) {
123 		if (ELF_ST_TYPE(symp->st_info) != type)
124 			continue;
125 
126 		*idx = i;
127 		return symp;
128 	}
129 
130 	return NULL;
131 }
132 
133 /*
134  * For a given function name, return the number of arguments.
135  */
136 int
137 db_ctf_func_numargs(Elf_Sym *st)
138 {
139 	Elf_Sym			*symp;
140 	uint16_t		*fstart, *fend;
141 	uint16_t		*fsp, kind, vlen;
142 	size_t			 i, idx = 0;
143 
144 	if (!db_ctf.ctf_found || st == NULL)
145 		return -1;
146 
147 	fstart = (uint16_t *)(db_ctf.data + db_ctf.cth->cth_funcoff);
148 	fend = (uint16_t *)(db_ctf.data + db_ctf.cth->cth_typeoff);
149 
150 	fsp = fstart;
151 	while (fsp < fend) {
152 		symp = db_ctf_idx2sym(&idx, STT_FUNC);
153 		if (symp == NULL)
154 			break;
155 
156 		kind = CTF_INFO_KIND(*fsp);
157 		vlen = CTF_INFO_VLEN(*fsp);
158 		fsp++;
159 
160 		if (kind == CTF_K_UNKNOWN && vlen == 0)
161 			continue;
162 
163 		/* Skip return type */
164 		fsp++;
165 
166 		/* Skip argument types */
167 		for (i = 0; i < vlen; i++)
168 			fsp++;
169 
170 		if (symp == st)
171 			return vlen;
172 	}
173 
174 	return 0;
175 }
176 
177 /*
178  * Return the length of the type record in the CTF section.
179  */
180 uint32_t
181 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 	kind = CTF_INFO_KIND(ctt->ctt_info);
188 	vlen = CTF_INFO_VLEN(ctt->ctt_info);
189 
190 	if (ctt->ctt_size <= CTF_MAX_SIZE) {
191 		size = ctt->ctt_size;
192 		tlen = sizeof(struct ctf_stype);
193 	} else {
194 		size = CTF_TYPE_LSIZE(ctt);
195 		tlen = sizeof(struct ctf_type);
196 	}
197 
198 	switch (kind) {
199 	case CTF_K_UNKNOWN:
200 	case CTF_K_FORWARD:
201 		break;
202 	case CTF_K_INTEGER:
203 		tlen += sizeof(uint32_t);
204 		break;
205 	case CTF_K_FLOAT:
206 		tlen += sizeof(uint32_t);
207 		break;
208 	case CTF_K_ARRAY:
209 		tlen += sizeof(struct ctf_array);
210 		break;
211 	case CTF_K_FUNCTION:
212 		tlen += (vlen + (vlen & 1)) * sizeof(uint16_t);
213 		break;
214 	case CTF_K_STRUCT:
215 	case CTF_K_UNION:
216 		if (size < CTF_LSTRUCT_THRESH) {
217 			for (i = 0; i < vlen; i++) {
218 				tlen += sizeof(struct ctf_member);
219 			}
220 		} else {
221 			for (i = 0; i < vlen; i++) {
222 				tlen += sizeof(struct ctf_lmember);
223 			}
224 		}
225 		break;
226 	case CTF_K_ENUM:
227 		for (i = 0; i < vlen; i++) {
228 			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 		return 0;
239 	}
240 
241 	return tlen;
242 }
243 
244 /*
245  * Return the CTF type associated to an ELF symbol.
246  */
247 const struct ctf_type *
248 db_ctf_type_by_symbol(Elf_Sym *st)
249 {
250 	Elf_Sym			*symp;
251 	uint32_t		 objtoff;
252 	uint16_t		*dsp;
253 	size_t			 idx = 0;
254 
255 	if (!db_ctf.ctf_found || st == NULL)
256 		return NULL;
257 
258 	objtoff = db_ctf.cth->cth_objtoff;
259 
260 	while (objtoff < db_ctf.cth->cth_funcoff) {
261 		dsp = (uint16_t *)(db_ctf.data + objtoff);
262 
263 		symp = db_ctf_idx2sym(&idx, STT_OBJECT);
264 		if (symp == NULL)
265 			break;
266 		if (symp == st)
267 			return db_ctf_type_by_index(*dsp);
268 
269 		objtoff += sizeof(*dsp);
270 	}
271 
272 	return NULL;
273 }
274 
275 const struct ctf_type *
276 db_ctf_type_by_name(const char *name, unsigned int kind)
277 {
278 	struct ctf_header	*cth;
279 	const struct ctf_type   *ctt;
280 	const char		*tname;
281 	uint32_t		 off, toff;
282 
283 	if (!db_ctf.ctf_found)
284 		return (NULL);
285 
286 	cth = db_ctf.cth;
287 
288 	for (off = cth->cth_typeoff; off < cth->cth_stroff; off += toff) {
289 		ctt = (struct ctf_type *)(db_ctf.data + off);
290 		toff = db_ctf_type_len(ctt);
291 		if (toff == 0) {
292 			db_printf("incorrect type at offset %u", off);
293 			break;
294 		}
295 
296 		if (CTF_INFO_KIND(ctt->ctt_info) != kind)
297 			continue;
298 
299 		tname = db_ctf_off2name(ctt->ctt_name);
300 		if (tname == NULL)
301 			continue;
302 
303 		if (strcmp(name, tname) == 0)
304 			return (ctt);
305 	}
306 
307 	return (NULL);
308 }
309 
310 /*
311  * Return the CTF type corresponding to a given index in the type section.
312  */
313 const struct ctf_type *
314 db_ctf_type_by_index(uint16_t index)
315 {
316 	uint32_t		 offset = db_ctf.cth->cth_typeoff;
317 	uint16_t		 idx = 1;
318 
319 	if (!db_ctf.ctf_found)
320 		return NULL;
321 
322 	while (offset < db_ctf.cth->cth_stroff) {
323 		const struct ctf_type   *ctt;
324 		uint32_t		 toff;
325 
326 		ctt = (struct ctf_type *)(db_ctf.data + offset);
327 		if (idx == index)
328 			return ctt;
329 
330 		toff = db_ctf_type_len(ctt);
331 		if (toff == 0) {
332 			db_printf("incorrect type at offset %u", offset);
333 			break;
334 		}
335 		offset += toff;
336 		idx++;
337 	}
338 
339 	return NULL;
340 }
341 
342 /*
343  * Pretty print `addr'.
344  */
345 void
346 db_ctf_pprint(const struct ctf_type *ctt, vaddr_t addr)
347 {
348 	vaddr_t			 taddr = (vaddr_t)ctt;
349 	const struct ctf_type	*ref;
350 	uint16_t		 kind;
351 	uint32_t		 eob, toff;
352 
353 	kind = CTF_INFO_KIND(ctt->ctt_info);
354 	if (ctt->ctt_size <= CTF_MAX_SIZE)
355 		toff = sizeof(struct ctf_stype);
356 	else
357 		toff = sizeof(struct ctf_type);
358 
359 	switch (kind) {
360 	case CTF_K_FLOAT:
361 	case CTF_K_ENUM:
362 	case CTF_K_ARRAY:
363 	case CTF_K_FUNCTION:
364 		db_printf("%lu", *((unsigned long *)addr));
365 		break;
366 	case CTF_K_INTEGER:
367 		eob = db_get_value((taddr + toff), sizeof(eob), 0);
368 		switch (CTF_INT_BITS(eob)) {
369 		case 64:
370 			db_printf("0x%llx", *((long long *)addr));
371 			break;
372 		default:
373 			db_printf("0x%x", *((int *)addr));
374 			break;
375 		}
376 		break;
377 	case CTF_K_STRUCT:
378 	case CTF_K_UNION:
379 		db_ctf_pprint_struct(ctt, addr);
380 		break;
381 	case CTF_K_POINTER:
382 		db_ctf_pprint_ptr(ctt, addr);
383 		break;
384 	case CTF_K_TYPEDEF:
385 	case CTF_K_VOLATILE:
386 	case CTF_K_CONST:
387 	case CTF_K_RESTRICT:
388 		ref = db_ctf_type_by_index(ctt->ctt_type);
389 		db_ctf_pprint(ref, addr);
390 		break;
391 	case CTF_K_UNKNOWN:
392 	case CTF_K_FORWARD:
393 	default:
394 		break;
395 	}
396 }
397 
398 void
399 db_ctf_pprint_struct(const struct ctf_type *ctt, vaddr_t addr)
400 {
401 	const char		*name, *p = (const char *)ctt;
402 	const struct ctf_type	*ref;
403 	uint32_t		 toff;
404 	uint64_t		 size;
405 	uint16_t		 i, vlen;
406 
407 	vlen = CTF_INFO_VLEN(ctt->ctt_info);
408 
409 	if (ctt->ctt_size <= CTF_MAX_SIZE) {
410 		size = ctt->ctt_size;
411 		toff = sizeof(struct ctf_stype);
412 	} else {
413 		size = CTF_TYPE_LSIZE(ctt);
414 		toff = sizeof(struct ctf_type);
415 	}
416 
417 	db_printf("{");
418 	if (size < CTF_LSTRUCT_THRESH) {
419 
420 		for (i = 0; i < vlen; i++) {
421 			struct ctf_member	*ctm;
422 
423 			ctm = (struct ctf_member *)(p + toff);
424 			toff += sizeof(struct ctf_member);
425 
426 			name = db_ctf_off2name(ctm->ctm_name);
427 			if (name != NULL)
428 				db_printf("%s = ", name);
429 			ref = db_ctf_type_by_index(ctm->ctm_type);
430 			db_ctf_pprint(ref, addr + ctm->ctm_offset / 8);
431 			if (i < vlen - 1)
432 				db_printf(", ");
433 		}
434 	} else {
435 		for (i = 0; i < vlen; i++) {
436 			struct ctf_lmember	*ctlm;
437 
438 			ctlm = (struct ctf_lmember *)(p + toff);
439 			toff += sizeof(struct ctf_lmember);
440 
441 			name = db_ctf_off2name(ctlm->ctlm_name);
442 			if (name != NULL)
443 				db_printf("%s = ", name);
444 			ref = db_ctf_type_by_index(ctlm->ctlm_type);
445 			db_ctf_pprint(ref, addr +
446 			    CTF_LMEM_OFFSET(ctlm) / 8);
447 			if (i < vlen - 1)
448 				db_printf(", ");
449 		}
450 	}
451 	db_printf("}");
452 }
453 
454 void
455 db_ctf_pprint_ptr(const struct ctf_type *ctt, vaddr_t addr)
456 {
457 	const char		*name, *modif = "";
458 	const struct ctf_type	*ref;
459 	uint16_t		 kind;
460 	unsigned long		 ptr;
461 
462 	ref = db_ctf_type_by_index(ctt->ctt_type);
463 	kind = CTF_INFO_KIND(ref->ctt_info);
464 
465 	switch (kind) {
466 	case CTF_K_VOLATILE:
467 		modif = "volatile ";
468 		ref = db_ctf_type_by_index(ref->ctt_type);
469 		break;
470 	case CTF_K_CONST:
471 		modif = "const ";
472 		ref = db_ctf_type_by_index(ref->ctt_type);
473 		break;
474 	case CTF_K_STRUCT:
475 		modif = "struct ";
476 		break;
477 	case CTF_K_UNION:
478 		modif = "union ";
479 		break;
480 	default:
481 		break;
482 	}
483 
484 	name = db_ctf_off2name(ref->ctt_name);
485 	if (name != NULL)
486 		db_printf("(%s%s *)", modif, name);
487 
488 	ptr = (unsigned long)db_get_value(addr, sizeof(ptr), 0);
489 
490 	db_printf("0x%lx", ptr);
491 }
492 
493 static const char *
494 db_ctf_off2name(uint32_t offset)
495 {
496 	const char		*name;
497 
498 	if (!db_ctf.ctf_found)
499 		return NULL;
500 
501 	if (CTF_NAME_STID(offset) != CTF_STRTAB_0)
502 		return "external";
503 
504 	if (CTF_NAME_OFFSET(offset) >= db_ctf.cth->cth_strlen)
505 		return "exceeds strlab";
506 
507 	if (db_ctf.cth->cth_stroff + CTF_NAME_OFFSET(offset) >= db_ctf.dlen)
508 		return "invalid";
509 
510 	name = db_ctf.data + db_ctf.cth->cth_stroff + CTF_NAME_OFFSET(offset);
511 	if (*name == '\0')
512 		return NULL;
513 
514 	return name;
515 }
516 
517 static char *
518 db_ctf_decompress(const char *buf, size_t size, size_t len)
519 {
520 	z_stream		 stream;
521 	char			*data;
522 	int			 error;
523 
524 	data = malloc(len, M_TEMP, M_WAITOK|M_ZERO|M_CANFAIL);
525 	if (data == NULL)
526 		return NULL;
527 
528 	memset(&stream, 0, sizeof(stream));
529 	stream.next_in = (void *)buf;
530 	stream.avail_in = size;
531 	stream.next_out = data;
532 	stream.avail_out = len;
533 
534 	if ((error = inflateInit(&stream)) != Z_OK) {
535 		db_printf("zlib inflateInit failed: %s", zError(error));
536 		goto exit;
537 	}
538 
539 	if ((error = inflate(&stream, Z_FINISH)) != Z_STREAM_END) {
540 		db_printf("zlib inflate failed: %s", zError(error));
541 		inflateEnd(&stream);
542 		goto exit;
543 	}
544 
545 	if ((error = inflateEnd(&stream)) != Z_OK) {
546 		db_printf("zlib inflateEnd failed: %s", zError(error));
547 		goto exit;
548 	}
549 
550 	if (stream.total_out != len) {
551 		db_printf("decompression failed: %lu != %zu",
552 		    stream.total_out, len);
553 		goto exit;
554 	}
555 
556 	return data;
557 
558 exit:
559 	free(data, M_DEVBUF, len);
560 	return NULL;
561 }
562 
563 /*
564  * pprint <symbol name>
565  */
566 void
567 db_ctf_pprint_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
568 {
569 	Elf_Sym *st;
570 	const struct ctf_type *ctt;
571 	int t;
572 
573 	if (!db_ctf.ctf_found) {
574 		db_printf("No CTF data found\n");
575 		db_flush_lex();
576 		return;
577 	}
578 
579 	/*
580 	 * Read the struct name from the debugger input.
581 	 */
582 	t = db_read_token();
583 	if (t != tIDENT) {
584 		db_printf("Bad symbol name\n");
585 		db_flush_lex();
586 		return;
587 	}
588 
589 	if ((st = db_symbol_by_name(db_tok_string, &addr)) == NULL) {
590 		db_printf("Symbol not found %s\n", db_tok_string);
591 		db_flush_lex();
592 		return;
593 	}
594 
595 	if ((ctt = db_ctf_type_by_symbol(st)) == NULL) {
596 		modif[0] = '\0';
597 		db_print_cmd(addr, 0, 0, modif);
598 		db_flush_lex();
599 		return;
600 	}
601 
602 	db_printf("%s:\t", db_tok_string);
603 	db_ctf_pprint(ctt, addr);
604 	db_printf("\n");
605 }
606 
607 /*
608  * show struct <struct name> [addr]: displays the data starting at addr
609  * (`dot' if unspecified) as a struct of the given type.
610  */
611 void
612 db_ctf_show_struct(db_expr_t addr, int have_addr, db_expr_t count,
613     char *modifiers)
614 {
615 	const struct ctf_type *ctt;
616 	const char *name;
617 	uint64_t sz;
618 	int t;
619 
620 	/*
621 	 * Read the struct name from the debugger input.
622 	 */
623 	t = db_read_token();
624 	if (t != tIDENT) {
625 		db_printf("Bad struct name\n");
626 		db_flush_lex();
627 		return;
628 	}
629 	name = db_tok_string;
630 
631 	ctt = db_ctf_type_by_name(name, CTF_K_STRUCT);
632 	if (ctt == NULL) {
633 		db_printf("unknown struct %s\n", name);
634 		db_flush_lex();
635 		return;
636 	}
637 
638 	/*
639 	 * Read the address, if any, from the debugger input.
640 	 * In that case, update `dot' value.
641 	 */
642 	if (db_expression(&addr)) {
643 		db_dot = (vaddr_t)addr;
644 		db_last_addr = db_dot;
645 	} else
646 		addr = (db_expr_t)db_dot;
647 
648 	db_skip_to_eol();
649 
650 	/*
651 	 * Display the structure contents.
652 	 */
653 	sz = (ctt->ctt_size <= CTF_MAX_SIZE) ?
654 	    ctt->ctt_size : CTF_TYPE_LSIZE(ctt);
655 	db_printf("struct %s at %p (%llu bytes) ", name, (void *)addr, sz);
656 	db_ctf_pprint_struct(ctt, addr);
657 }
658