Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/ddb/db_ctf.c
39476 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2023 Bojan Novković <[email protected]>
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 *
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
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
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 *
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
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 *
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 *
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 *
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
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 *
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
328