1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2023 Bojan Novkovi�� <bnovkov@freebsd.org>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
29#include <sys/types.h>
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/ctype.h>
33#include <sys/linker.h>
34#include <sys/malloc.h>
35#include <sys/mutex.h>
36
37#include <ddb/ddb.h>
38#include <ddb/db_ctf.h>
39
40static const ctf_header_t *
41db_ctf_fetch_cth(linker_ctf_t *lc)
42{
43	return (const ctf_header_t *)lc->ctftab;
44}
45
46/*
47 * Tries to look up the ELF symbol -> CTF type identifier mapping by scanning
48 * the CTF object section.
49 */
50static uint32_t
51sym_to_objtoff(linker_ctf_t *lc, const Elf_Sym *sym, const Elf_Sym *symtab,
52    const Elf_Sym *symtab_end)
53{
54	const ctf_header_t *hp = db_ctf_fetch_cth(lc);
55	uint32_t objtoff = hp->cth_objtoff;
56	const size_t idwidth = 4;
57
58	/* Ignore non-object symbols */
59	if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT) {
60		return (DB_CTF_INVALID_OFF);
61	}
62	/* Sanity check */
63	if (!(sym >= symtab && sym <= symtab_end)) {
64		return (DB_CTF_INVALID_OFF);
65	}
66
67	for (const Elf_Sym *symp = symtab; symp < symtab_end; symp++) {
68		/* Make sure we do not go beyond the objtoff section */
69		if (objtoff >= hp->cth_funcoff) {
70			objtoff = DB_CTF_INVALID_OFF;
71			break;
72		}
73		if (symp->st_name == 0 || symp->st_shndx == SHN_UNDEF) {
74			continue;
75		}
76		if (symp->st_shndx == SHN_ABS && symp->st_value == 0) {
77			continue;
78		}
79
80		/* Skip non-object symbols */
81		if (ELF_ST_TYPE(symp->st_info) != STT_OBJECT) {
82			continue;
83		}
84		if (symp == sym) {
85			break;
86		}
87		objtoff += idwidth;
88	}
89
90	return (objtoff);
91}
92
93/*
94 * Returns the size of CTF type 't'.
95 */
96static u_int
97db_ctf_type_size(struct ctf_type_v3 *t)
98{
99	u_int vlen, kind, ssize;
100	u_int type_struct_size, kind_size;
101
102	vlen = CTF_V3_INFO_VLEN(t->ctt_info);
103	kind = CTF_V3_INFO_KIND(t->ctt_info);
104	ssize = ((t->ctt_size == CTF_V3_LSIZE_SENT) ? CTF_TYPE_LSIZE(t) :
105						      t->ctt_size);
106	type_struct_size = ((t->ctt_size == CTF_V3_LSIZE_SENT) ?
107		sizeof(struct ctf_type_v3) :
108		sizeof(struct ctf_stype_v3));
109
110	switch (kind) {
111	case CTF_K_INTEGER:
112	case CTF_K_FLOAT:
113		kind_size = sizeof(uint32_t);
114		break;
115	case CTF_K_ARRAY:
116		kind_size = sizeof(struct ctf_array_v3);
117		break;
118	case CTF_K_UNION:
119	case CTF_K_STRUCT:
120		kind_size = vlen *
121		    ((ssize < CTF_V3_LSTRUCT_THRESH) ?
122			    sizeof(struct ctf_member_v3) :
123			    sizeof(struct ctf_lmember_v3));
124		break;
125	case CTF_K_ENUM:
126		kind_size = vlen * sizeof(struct ctf_enum);
127		break;
128	case CTF_K_FUNCTION:
129		kind_size = vlen * sizeof(uint32_t);
130		break;
131	case CTF_K_UNKNOWN:
132	case CTF_K_FORWARD:
133	case CTF_K_POINTER:
134	case CTF_K_TYPEDEF:
135	case CTF_K_VOLATILE:
136	case CTF_K_CONST:
137	case CTF_K_RESTRICT:
138		kind_size = 0;
139		break;
140	default:
141		db_printf("Error: invalid CTF type kind encountered\n");
142		return (-1);
143	}
144
145	return (type_struct_size + kind_size);
146}
147
148/*
149 * Looks up type name 'name' in the CTF string table and returns the
150 * corresponding CTF type struct, if any.
151 */
152struct ctf_type_v3 *
153db_ctf_typename_to_type(linker_ctf_t *lc, const char *name)
154{
155	const ctf_header_t *hp = db_ctf_fetch_cth(lc);
156	char *start, *cur, *end;
157	uint32_t stroff = hp->cth_stroff;
158	uint32_t typeoff = hp->cth_typeoff;
159	uint32_t name_stroff;
160	const uint8_t *ctfstart = (const uint8_t *)hp + sizeof(ctf_header_t);
161
162	u_int skiplen;
163
164	/* Scan ctf strtab for typename. */
165	start = cur = __DECONST(char *, hp) + sizeof(ctf_header_t) +
166	    hp->cth_stroff;
167	end = cur + hp->cth_strlen;
168	while (cur < end) {
169		if (strcmp(cur, name) == 0)
170			break;
171		cur += strlen(cur) + 1;
172	}
173	if (cur >= end)
174		return (NULL);
175	name_stroff = (uint32_t)(cur - start);
176
177	/* Scan for type containing the found stroff. */
178	while (typeoff < stroff) {
179		struct ctf_type_v3 *t =
180		    (struct ctf_type_v3 *)(__DECONST(uint8_t *, ctfstart) +
181			typeoff);
182		/* We found the type struct */
183		if (t->ctt_name == name_stroff) {
184			break;
185		}
186		if ((skiplen = db_ctf_type_size(t)) == -1) {
187			return (NULL);
188		}
189		typeoff += skiplen;
190	}
191	if (typeoff < stroff) {
192		return (struct ctf_type_v3 *)(__DECONST(uint8_t *, ctfstart) +
193		    typeoff);
194	} else { /* A type struct was not found */
195		return (NULL);
196	}
197}
198
199/*
200 * Wrapper used by the kernel linker CTF routines.
201 * Currently used to implement lookup of CTF types accross all loaded kernel
202 * modules.
203 */
204bool
205db_ctf_lookup_typename(linker_ctf_t *lc, const char *typename)
206{
207	return (db_ctf_typename_to_type(lc, typename) != NULL);
208}
209
210/*
211 * Returns the type corresponding to the 'typeid' parameter from the CTF type
212 * section.
213 */
214struct ctf_type_v3 *
215db_ctf_typeid_to_type(db_ctf_sym_data_t sd, uint32_t typeid)
216{
217	const ctf_header_t *hp = db_ctf_fetch_cth(&sd->lc);
218	const uint8_t *ctfstart = (const uint8_t *)hp + sizeof(ctf_header_t);
219	uint32_t typeoff = hp->cth_typeoff;
220	uint32_t stroff = hp->cth_stroff;
221	/* CTF typeids start at 0x1 */
222	size_t cur_typeid = 1;
223	u_int skiplen;
224
225	/* Find corresponding type */
226	while (typeoff < stroff) {
227		struct ctf_type_v3 *t =
228		    (struct ctf_type_v3 *)(__DECONST(uint8_t *, ctfstart) +
229			typeoff);
230
231		/* We found the type struct */
232		if (cur_typeid == typeid) {
233			break;
234		}
235		cur_typeid++;
236		if ((skiplen = db_ctf_type_size(t)) == -1) {
237			return (NULL);
238		}
239		typeoff += skiplen;
240	}
241	if (typeoff < stroff) {
242		return (struct ctf_type_v3 *)(__DECONST(uint8_t *, ctfstart) +
243		    typeoff);
244	} else { /* A type struct was not found */
245		return (NULL);
246	}
247}
248
249const char *
250db_ctf_stroff_to_str(db_ctf_sym_data_t sd, uint32_t off)
251{
252	const ctf_header_t *hp = db_ctf_fetch_cth(&sd->lc);
253	uint32_t stroff = hp->cth_stroff + off;
254	const char *ret;
255
256	if (stroff >= (hp->cth_stroff + hp->cth_strlen)) {
257		return ("invalid");
258	}
259	ret = ((const char *)hp + sizeof(ctf_header_t)) + stroff;
260	if (*ret == '\0') {
261		return (NULL);
262	}
263
264	return (ret);
265}
266
267/*
268 * Tries to find the type of the symbol specified in 'sd->sym'.
269 */
270struct ctf_type_v3 *
271db_ctf_sym_to_type(db_ctf_sym_data_t sd)
272{
273	uint32_t objtoff, typeid;
274	const Elf_Sym *symtab, *symtab_end;
275
276	if (sd->sym == NULL) {
277		return (NULL);
278	}
279	symtab = sd->lc.symtab;
280	symtab_end = symtab + sd->lc.nsym;
281
282	objtoff = sym_to_objtoff(&sd->lc, sd->sym, symtab, symtab_end);
283	/* Sanity check - should not happen */
284	if (objtoff == DB_CTF_INVALID_OFF) {
285		db_printf("Could not find CTF object offset.\n");
286		return (NULL);
287	}
288
289	typeid = *(
290	    const uint32_t *)(sd->lc.ctftab + sizeof(ctf_header_t) + objtoff);
291
292	return (db_ctf_typeid_to_type(sd, typeid));
293}
294
295/*
296 * Scans the kernel file and all loaded module for symbol 'name'.
297 */
298int
299db_ctf_find_symbol(const char *name, db_ctf_sym_data_t sd)
300{
301	int error;
302	c_linker_sym_t lsym = NULL;
303
304	error = linker_ctf_lookup_sym_ddb(name, &lsym, &sd->lc);
305	if (error != 0) {
306		db_printf(
307		    "failed to look up symbol and CTF info for %s: error %d\n",
308		    name, error);
309		return (error);
310	}
311	sd->sym = __DECONST(Elf_Sym *, lsym);
312
313	return (0);
314}
315
316/*
317 * Scans the kernel file and all loaded module for type specified by 'typename'.
318 */
319struct ctf_type_v3 *
320db_ctf_find_typename(db_ctf_sym_data_t sd, const char *typename)
321{
322	if (linker_ctf_lookup_typename_ddb(&sd->lc, typename) != 0) {
323		return (NULL);
324	}
325	return (db_ctf_typename_to_type(&sd->lc, typename));
326}
327