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 * 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