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
40 static const ctf_header_t *
db_ctf_fetch_cth(linker_ctf_t * lc)41 db_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 */
50 static uint32_t
sym_to_objtoff(linker_ctf_t * lc,const Elf_Sym * sym,const Elf_Sym * symtab,const Elf_Sym * symtab_end)51 sym_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 */
96 static u_int
db_ctf_type_size(struct ctf_type_v3 * t)97 db_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 */
152 struct ctf_type_v3 *
db_ctf_typename_to_type(linker_ctf_t * lc,const char * name)153 db_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 */
204 bool
db_ctf_lookup_typename(linker_ctf_t * lc,const char * typename)205 db_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 */
214 struct ctf_type_v3 *
db_ctf_typeid_to_type(db_ctf_sym_data_t sd,uint32_t typeid)215 db_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
249 const char *
db_ctf_stroff_to_str(db_ctf_sym_data_t sd,uint32_t off)250 db_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 */
270 struct ctf_type_v3 *
db_ctf_sym_to_type(db_ctf_sym_data_t sd)271 db_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 */
298 int
db_ctf_find_symbol(const char * name,db_ctf_sym_data_t sd)299 db_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 */
319 struct ctf_type_v3 *
db_ctf_find_typename(db_ctf_sym_data_t sd,const char * typename)320 db_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