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