1 // SPDX-License-Identifier: GPL-2.0-only << 2 /* 1 /* 3 * kallsyms.c: in-kernel printing of symbolic 2 * kallsyms.c: in-kernel printing of symbolic oopses and stack traces. 4 * 3 * 5 * Rewritten and vastly simplified by Rusty Ru 4 * Rewritten and vastly simplified by Rusty Russell for in-kernel 6 * module loader: 5 * module loader: 7 * Copyright 2002 Rusty Russell <rusty@rustc 6 * Copyright 2002 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation 8 * 7 * 9 * ChangeLog: 8 * ChangeLog: 10 * 9 * 11 * (25/Aug/2004) Paulo Marques <pmarques@grupo 10 * (25/Aug/2004) Paulo Marques <pmarques@grupopie.com> 12 * Changed the compression method from st 11 * Changed the compression method from stem compression to "table lookup" 13 * compression (see scripts/kallsyms.c fo 12 * compression (see scripts/kallsyms.c for a more complete description) 14 */ 13 */ 15 #include <linux/kallsyms.h> 14 #include <linux/kallsyms.h> >> 15 #include <linux/module.h> 16 #include <linux/init.h> 16 #include <linux/init.h> 17 #include <linux/seq_file.h> 17 #include <linux/seq_file.h> 18 #include <linux/fs.h> 18 #include <linux/fs.h> 19 #include <linux/kdb.h> 19 #include <linux/kdb.h> 20 #include <linux/err.h> 20 #include <linux/err.h> 21 #include <linux/proc_fs.h> 21 #include <linux/proc_fs.h> 22 #include <linux/sched.h> /* for cond_re 22 #include <linux/sched.h> /* for cond_resched */ >> 23 #include <linux/mm.h> 23 #include <linux/ctype.h> 24 #include <linux/ctype.h> 24 #include <linux/slab.h> 25 #include <linux/slab.h> 25 #include <linux/filter.h> 26 #include <linux/filter.h> 26 #include <linux/ftrace.h> << 27 #include <linux/kprobes.h> << 28 #include <linux/build_bug.h> << 29 #include <linux/compiler.h> 27 #include <linux/compiler.h> 30 #include <linux/module.h> << 31 #include <linux/kernel.h> << 32 #include <linux/bsearch.h> << 33 #include <linux/btf_ids.h> << 34 28 35 #include "kallsyms_internal.h" !! 29 #include <asm/sections.h> >> 30 >> 31 /* >> 32 * These will be re-linked against their real values >> 33 * during the second link stage. >> 34 */ >> 35 extern const unsigned long kallsyms_addresses[] __weak; >> 36 extern const int kallsyms_offsets[] __weak; >> 37 extern const u8 kallsyms_names[] __weak; >> 38 >> 39 /* >> 40 * Tell the compiler that the count isn't in the small data section if the arch >> 41 * has one (eg: FRV). >> 42 */ >> 43 extern const unsigned long kallsyms_num_syms >> 44 __attribute__((weak, section(".rodata"))); >> 45 >> 46 extern const unsigned long kallsyms_relative_base >> 47 __attribute__((weak, section(".rodata"))); >> 48 >> 49 extern const u8 kallsyms_token_table[] __weak; >> 50 extern const u16 kallsyms_token_index[] __weak; >> 51 >> 52 extern const unsigned long kallsyms_markers[] __weak; >> 53 >> 54 static inline int is_kernel_inittext(unsigned long addr) >> 55 { >> 56 if (addr >= (unsigned long)_sinittext >> 57 && addr <= (unsigned long)_einittext) >> 58 return 1; >> 59 return 0; >> 60 } >> 61 >> 62 static inline int is_kernel_text(unsigned long addr) >> 63 { >> 64 if ((addr >= (unsigned long)_stext && addr <= (unsigned long)_etext) || >> 65 arch_is_kernel_text(addr)) >> 66 return 1; >> 67 return in_gate_area_no_mm(addr); >> 68 } >> 69 >> 70 static inline int is_kernel(unsigned long addr) >> 71 { >> 72 if (addr >= (unsigned long)_stext && addr <= (unsigned long)_end) >> 73 return 1; >> 74 return in_gate_area_no_mm(addr); >> 75 } >> 76 >> 77 static int is_ksym_addr(unsigned long addr) >> 78 { >> 79 if (IS_ENABLED(CONFIG_KALLSYMS_ALL)) >> 80 return is_kernel(addr); >> 81 >> 82 return is_kernel_text(addr) || is_kernel_inittext(addr); >> 83 } 36 84 37 /* 85 /* 38 * Expand a compressed symbol data into the re 86 * Expand a compressed symbol data into the resulting uncompressed string, 39 * if uncompressed string is too long (>= maxl 87 * if uncompressed string is too long (>= maxlen), it will be truncated, 40 * given the offset to where the symbol is in 88 * given the offset to where the symbol is in the compressed stream. 41 */ 89 */ 42 static unsigned int kallsyms_expand_symbol(uns 90 static unsigned int kallsyms_expand_symbol(unsigned int off, 43 cha 91 char *result, size_t maxlen) 44 { 92 { 45 int len, skipped_first = 0; 93 int len, skipped_first = 0; 46 const char *tptr; !! 94 const u8 *tptr, *data; 47 const u8 *data; << 48 95 49 /* Get the compressed symbol length fr 96 /* Get the compressed symbol length from the first symbol byte. */ 50 data = &kallsyms_names[off]; 97 data = &kallsyms_names[off]; 51 len = *data; 98 len = *data; 52 data++; 99 data++; 53 off++; << 54 << 55 /* If MSB is 1, it is a "big" symbol, << 56 if ((len & 0x80) != 0) { << 57 len = (len & 0x7F) | (*data << << 58 data++; << 59 off++; << 60 } << 61 100 62 /* 101 /* 63 * Update the offset to return the off 102 * Update the offset to return the offset for the next symbol on 64 * the compressed stream. 103 * the compressed stream. 65 */ 104 */ 66 off += len; !! 105 off += len + 1; 67 106 68 /* 107 /* 69 * For every byte on the compressed sy 108 * For every byte on the compressed symbol data, copy the table 70 * entry for that byte. 109 * entry for that byte. 71 */ 110 */ 72 while (len) { 111 while (len) { 73 tptr = &kallsyms_token_table[k 112 tptr = &kallsyms_token_table[kallsyms_token_index[*data]]; 74 data++; 113 data++; 75 len--; 114 len--; 76 115 77 while (*tptr) { 116 while (*tptr) { 78 if (skipped_first) { 117 if (skipped_first) { 79 if (maxlen <= 118 if (maxlen <= 1) 80 goto t 119 goto tail; 81 *result = *tpt 120 *result = *tptr; 82 result++; 121 result++; 83 maxlen--; 122 maxlen--; 84 } else 123 } else 85 skipped_first 124 skipped_first = 1; 86 tptr++; 125 tptr++; 87 } 126 } 88 } 127 } 89 128 90 tail: 129 tail: 91 if (maxlen) 130 if (maxlen) 92 *result = '\0'; 131 *result = '\0'; 93 132 94 /* Return to offset to the next symbol 133 /* Return to offset to the next symbol. */ 95 return off; 134 return off; 96 } 135 } 97 136 98 /* 137 /* 99 * Get symbol type information. This is encode 138 * Get symbol type information. This is encoded as a single char at the 100 * beginning of the symbol name. 139 * beginning of the symbol name. 101 */ 140 */ 102 static char kallsyms_get_symbol_type(unsigned 141 static char kallsyms_get_symbol_type(unsigned int off) 103 { 142 { 104 /* 143 /* 105 * Get just the first code, look it up 144 * Get just the first code, look it up in the token table, 106 * and return the first char from this 145 * and return the first char from this token. 107 */ 146 */ 108 return kallsyms_token_table[kallsyms_t 147 return kallsyms_token_table[kallsyms_token_index[kallsyms_names[off + 1]]]; 109 } 148 } 110 149 111 150 112 /* 151 /* 113 * Find the offset on the compressed stream gi 152 * Find the offset on the compressed stream given and index in the 114 * kallsyms array. 153 * kallsyms array. 115 */ 154 */ 116 static unsigned int get_symbol_offset(unsigned 155 static unsigned int get_symbol_offset(unsigned long pos) 117 { 156 { 118 const u8 *name; 157 const u8 *name; 119 int i, len; !! 158 int i; 120 159 121 /* 160 /* 122 * Use the closest marker we have. We 161 * Use the closest marker we have. We have markers every 256 positions, 123 * so that should be close enough. 162 * so that should be close enough. 124 */ 163 */ 125 name = &kallsyms_names[kallsyms_marker 164 name = &kallsyms_names[kallsyms_markers[pos >> 8]]; 126 165 127 /* 166 /* 128 * Sequentially scan all the symbols u 167 * Sequentially scan all the symbols up to the point we're searching 129 * for. Every symbol is stored in a [< 168 * for. Every symbol is stored in a [<len>][<len> bytes of data] format, 130 * so we just need to add the len to t 169 * so we just need to add the len to the current pointer for every 131 * symbol we wish to skip. 170 * symbol we wish to skip. 132 */ 171 */ 133 for (i = 0; i < (pos & 0xFF); i++) { !! 172 for (i = 0; i < (pos & 0xFF); i++) 134 len = *name; !! 173 name = name + (*name) + 1; 135 << 136 /* << 137 * If MSB is 1, it is a "big" << 138 * the next byte (and skip it, << 139 */ << 140 if ((len & 0x80) != 0) << 141 len = ((len & 0x7F) | << 142 << 143 name = name + len + 1; << 144 } << 145 174 146 return name - kallsyms_names; 175 return name - kallsyms_names; 147 } 176 } 148 177 149 unsigned long kallsyms_sym_address(int idx) !! 178 static unsigned long kallsyms_sym_address(int idx) 150 { 179 { >> 180 if (!IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE)) >> 181 return kallsyms_addresses[idx]; >> 182 151 /* values are unsigned offsets if --ab 183 /* values are unsigned offsets if --absolute-percpu is not in effect */ 152 if (!IS_ENABLED(CONFIG_KALLSYMS_ABSOLU 184 if (!IS_ENABLED(CONFIG_KALLSYMS_ABSOLUTE_PERCPU)) 153 return kallsyms_relative_base 185 return kallsyms_relative_base + (u32)kallsyms_offsets[idx]; 154 186 155 /* ...otherwise, positive offsets are 187 /* ...otherwise, positive offsets are absolute values */ 156 if (kallsyms_offsets[idx] >= 0) 188 if (kallsyms_offsets[idx] >= 0) 157 return kallsyms_offsets[idx]; 189 return kallsyms_offsets[idx]; 158 190 159 /* ...and negative offsets are relativ 191 /* ...and negative offsets are relative to kallsyms_relative_base - 1 */ 160 return kallsyms_relative_base - 1 - ka 192 return kallsyms_relative_base - 1 - kallsyms_offsets[idx]; 161 } 193 } 162 194 163 static unsigned int get_symbol_seq(int index) << 164 { << 165 unsigned int i, seq = 0; << 166 << 167 for (i = 0; i < 3; i++) << 168 seq = (seq << 8) | kallsyms_se << 169 << 170 return seq; << 171 } << 172 << 173 static int kallsyms_lookup_names(const char *n << 174 unsigned int << 175 unsigned int << 176 { << 177 int ret; << 178 int low, mid, high; << 179 unsigned int seq, off; << 180 char namebuf[KSYM_NAME_LEN]; << 181 << 182 low = 0; << 183 high = kallsyms_num_syms - 1; << 184 << 185 while (low <= high) { << 186 mid = low + (high - low) / 2; << 187 seq = get_symbol_seq(mid); << 188 off = get_symbol_offset(seq); << 189 kallsyms_expand_symbol(off, na << 190 ret = strcmp(name, namebuf); << 191 if (ret > 0) << 192 low = mid + 1; << 193 else if (ret < 0) << 194 high = mid - 1; << 195 else << 196 break; << 197 } << 198 << 199 if (low > high) << 200 return -ESRCH; << 201 << 202 low = mid; << 203 while (low) { << 204 seq = get_symbol_seq(low - 1); << 205 off = get_symbol_offset(seq); << 206 kallsyms_expand_symbol(off, na << 207 if (strcmp(name, namebuf)) << 208 break; << 209 low--; << 210 } << 211 *start = low; << 212 << 213 if (end) { << 214 high = mid; << 215 while (high < kallsyms_num_sym << 216 seq = get_symbol_seq(h << 217 off = get_symbol_offse << 218 kallsyms_expand_symbol << 219 if (strcmp(name, nameb << 220 break; << 221 high++; << 222 } << 223 *end = high; << 224 } << 225 << 226 return 0; << 227 } << 228 << 229 /* Lookup the address for this symbol. Returns 195 /* Lookup the address for this symbol. Returns 0 if not found. */ 230 unsigned long kallsyms_lookup_name(const char 196 unsigned long kallsyms_lookup_name(const char *name) 231 { 197 { 232 int ret; !! 198 char namebuf[KSYM_NAME_LEN]; 233 unsigned int i; !! 199 unsigned long i; 234 !! 200 unsigned int off; 235 /* Skip the search for empty string. * << 236 if (!*name) << 237 return 0; << 238 201 239 ret = kallsyms_lookup_names(name, &i, !! 202 for (i = 0, off = 0; i < kallsyms_num_syms; i++) { 240 if (!ret) !! 203 off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf)); 241 return kallsyms_sym_address(ge << 242 204 >> 205 if (strcmp(namebuf, name) == 0) >> 206 return kallsyms_sym_address(i); >> 207 } 243 return module_kallsyms_lookup_name(nam 208 return module_kallsyms_lookup_name(name); 244 } 209 } >> 210 EXPORT_SYMBOL_GPL(kallsyms_lookup_name); 245 211 246 /* !! 212 int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *, 247 * Iterate over all symbols in vmlinux. For s !! 213 unsigned long), 248 * module_kallsyms_on_each_symbol instead. << 249 */ << 250 int kallsyms_on_each_symbol(int (*fn)(void *, << 251 void *data) 214 void *data) 252 { 215 { 253 char namebuf[KSYM_NAME_LEN]; 216 char namebuf[KSYM_NAME_LEN]; 254 unsigned long i; 217 unsigned long i; 255 unsigned int off; 218 unsigned int off; 256 int ret; 219 int ret; 257 220 258 for (i = 0, off = 0; i < kallsyms_num_ 221 for (i = 0, off = 0; i < kallsyms_num_syms; i++) { 259 off = kallsyms_expand_symbol(o 222 off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf)); 260 ret = fn(data, namebuf, kallsy !! 223 ret = fn(data, namebuf, NULL, kallsyms_sym_address(i)); 261 if (ret != 0) 224 if (ret != 0) 262 return ret; 225 return ret; 263 cond_resched(); << 264 } 226 } 265 return 0; !! 227 return module_kallsyms_on_each_symbol(fn, data); 266 } << 267 << 268 int kallsyms_on_each_match_symbol(int (*fn)(vo << 269 const char * << 270 { << 271 int ret; << 272 unsigned int i, start, end; << 273 << 274 ret = kallsyms_lookup_names(name, &sta << 275 if (ret) << 276 return 0; << 277 << 278 for (i = start; !ret && i <= end; i++) << 279 ret = fn(data, kallsyms_sym_ad << 280 cond_resched(); << 281 } << 282 << 283 return ret; << 284 } 228 } >> 229 EXPORT_SYMBOL_GPL(kallsyms_on_each_symbol); 285 230 286 static unsigned long get_symbol_pos(unsigned l 231 static unsigned long get_symbol_pos(unsigned long addr, 287 unsigned l 232 unsigned long *symbolsize, 288 unsigned l 233 unsigned long *offset) 289 { 234 { 290 unsigned long symbol_start = 0, symbol 235 unsigned long symbol_start = 0, symbol_end = 0; 291 unsigned long i, low, high, mid; 236 unsigned long i, low, high, mid; 292 237 293 /* Do a binary search on the sorted ka !! 238 /* This kernel should never had been booted. */ >> 239 if (!IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE)) >> 240 BUG_ON(!kallsyms_addresses); >> 241 else >> 242 BUG_ON(!kallsyms_offsets); >> 243 >> 244 /* Do a binary search on the sorted kallsyms_addresses array. */ 294 low = 0; 245 low = 0; 295 high = kallsyms_num_syms; 246 high = kallsyms_num_syms; 296 247 297 while (high - low > 1) { 248 while (high - low > 1) { 298 mid = low + (high - low) / 2; 249 mid = low + (high - low) / 2; 299 if (kallsyms_sym_address(mid) 250 if (kallsyms_sym_address(mid) <= addr) 300 low = mid; 251 low = mid; 301 else 252 else 302 high = mid; 253 high = mid; 303 } 254 } 304 255 305 /* 256 /* 306 * Search for the first aliased symbol 257 * Search for the first aliased symbol. Aliased 307 * symbols are symbols with the same a 258 * symbols are symbols with the same address. 308 */ 259 */ 309 while (low && kallsyms_sym_address(low 260 while (low && kallsyms_sym_address(low-1) == kallsyms_sym_address(low)) 310 --low; 261 --low; 311 262 312 symbol_start = kallsyms_sym_address(lo 263 symbol_start = kallsyms_sym_address(low); 313 264 314 /* Search for next non-aliased symbol. 265 /* Search for next non-aliased symbol. */ 315 for (i = low + 1; i < kallsyms_num_sym 266 for (i = low + 1; i < kallsyms_num_syms; i++) { 316 if (kallsyms_sym_address(i) > 267 if (kallsyms_sym_address(i) > symbol_start) { 317 symbol_end = kallsyms_ 268 symbol_end = kallsyms_sym_address(i); 318 break; 269 break; 319 } 270 } 320 } 271 } 321 272 322 /* If we found no next symbol, we use 273 /* If we found no next symbol, we use the end of the section. */ 323 if (!symbol_end) { 274 if (!symbol_end) { 324 if (is_kernel_inittext(addr)) 275 if (is_kernel_inittext(addr)) 325 symbol_end = (unsigned 276 symbol_end = (unsigned long)_einittext; 326 else if (IS_ENABLED(CONFIG_KAL 277 else if (IS_ENABLED(CONFIG_KALLSYMS_ALL)) 327 symbol_end = (unsigned 278 symbol_end = (unsigned long)_end; 328 else 279 else 329 symbol_end = (unsigned 280 symbol_end = (unsigned long)_etext; 330 } 281 } 331 282 332 if (symbolsize) 283 if (symbolsize) 333 *symbolsize = symbol_end - sym 284 *symbolsize = symbol_end - symbol_start; 334 if (offset) 285 if (offset) 335 *offset = addr - symbol_start; 286 *offset = addr - symbol_start; 336 287 337 return low; 288 return low; 338 } 289 } 339 290 340 /* 291 /* 341 * Lookup an address but don't bother to find 292 * Lookup an address but don't bother to find any names. 342 */ 293 */ 343 int kallsyms_lookup_size_offset(unsigned long 294 int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize, 344 unsigned long 295 unsigned long *offset) 345 { 296 { 346 char namebuf[KSYM_NAME_LEN]; 297 char namebuf[KSYM_NAME_LEN]; 347 298 348 if (is_ksym_addr(addr)) { !! 299 if (is_ksym_addr(addr)) 349 get_symbol_pos(addr, symbolsiz !! 300 return !!get_symbol_pos(addr, symbolsize, offset); 350 return 1; !! 301 return !!module_address_lookup(addr, symbolsize, offset, NULL, namebuf) || 351 } << 352 return !!module_address_lookup(addr, s << 353 !!__bpf_address_lookup(addr, sy 302 !!__bpf_address_lookup(addr, symbolsize, offset, namebuf); 354 } 303 } 355 304 356 static int kallsyms_lookup_buildid(unsigned lo !! 305 /* 357 unsigned long *symbols !! 306 * Lookup an address 358 unsigned long *offset, !! 307 * - modname is set to NULL if it's in the kernel. 359 const unsigned char ** !! 308 * - We guarantee that the returned name is valid until we reschedule even if. >> 309 * It resides in a module. >> 310 * - We also guarantee that modname will be valid until rescheduled. >> 311 */ >> 312 const char *kallsyms_lookup(unsigned long addr, >> 313 unsigned long *symbolsize, >> 314 unsigned long *offset, >> 315 char **modname, char *namebuf) 360 { 316 { 361 int ret; !! 317 const char *ret; 362 318 363 namebuf[KSYM_NAME_LEN - 1] = 0; 319 namebuf[KSYM_NAME_LEN - 1] = 0; 364 namebuf[0] = 0; 320 namebuf[0] = 0; 365 321 366 if (is_ksym_addr(addr)) { 322 if (is_ksym_addr(addr)) { 367 unsigned long pos; 323 unsigned long pos; 368 324 369 pos = get_symbol_pos(addr, sym 325 pos = get_symbol_pos(addr, symbolsize, offset); 370 /* Grab name */ 326 /* Grab name */ 371 kallsyms_expand_symbol(get_sym 327 kallsyms_expand_symbol(get_symbol_offset(pos), 372 namebuf 328 namebuf, KSYM_NAME_LEN); 373 if (modname) 329 if (modname) 374 *modname = NULL; 330 *modname = NULL; 375 if (modbuildid) !! 331 return namebuf; 376 *modbuildid = NULL; << 377 << 378 return strlen(namebuf); << 379 } 332 } 380 333 381 /* See if it's in a module or a BPF JI 334 /* See if it's in a module or a BPF JITed image. */ 382 ret = module_address_lookup(addr, symb 335 ret = module_address_lookup(addr, symbolsize, offset, 383 modname, m !! 336 modname, namebuf); 384 if (!ret) 337 if (!ret) 385 ret = bpf_address_lookup(addr, 338 ret = bpf_address_lookup(addr, symbolsize, 386 offse 339 offset, modname, namebuf); 387 << 388 if (!ret) << 389 ret = ftrace_mod_address_looku << 390 << 391 << 392 return ret; 340 return ret; 393 } 341 } 394 342 395 /* << 396 * Lookup an address << 397 * - modname is set to NULL if it's in the ker << 398 * - We guarantee that the returned name is va << 399 * It resides in a module. << 400 * - We also guarantee that modname will be va << 401 */ << 402 const char *kallsyms_lookup(unsigned long addr << 403 unsigned long *sym << 404 unsigned long *off << 405 char **modname, ch << 406 { << 407 int ret = kallsyms_lookup_buildid(addr << 408 NULL << 409 << 410 if (!ret) << 411 return NULL; << 412 << 413 return namebuf; << 414 } << 415 << 416 int lookup_symbol_name(unsigned long addr, cha 343 int lookup_symbol_name(unsigned long addr, char *symname) 417 { 344 { 418 symname[0] = '\0'; 345 symname[0] = '\0'; 419 symname[KSYM_NAME_LEN - 1] = '\0'; 346 symname[KSYM_NAME_LEN - 1] = '\0'; 420 347 421 if (is_ksym_addr(addr)) { 348 if (is_ksym_addr(addr)) { 422 unsigned long pos; 349 unsigned long pos; 423 350 424 pos = get_symbol_pos(addr, NUL 351 pos = get_symbol_pos(addr, NULL, NULL); 425 /* Grab name */ 352 /* Grab name */ 426 kallsyms_expand_symbol(get_sym 353 kallsyms_expand_symbol(get_symbol_offset(pos), 427 symname 354 symname, KSYM_NAME_LEN); 428 return 0; 355 return 0; 429 } 356 } 430 /* See if it's in a module. */ 357 /* See if it's in a module. */ 431 return lookup_module_symbol_name(addr, 358 return lookup_module_symbol_name(addr, symname); 432 } 359 } 433 360 >> 361 int lookup_symbol_attrs(unsigned long addr, unsigned long *size, >> 362 unsigned long *offset, char *modname, char *name) >> 363 { >> 364 name[0] = '\0'; >> 365 name[KSYM_NAME_LEN - 1] = '\0'; >> 366 >> 367 if (is_ksym_addr(addr)) { >> 368 unsigned long pos; >> 369 >> 370 pos = get_symbol_pos(addr, size, offset); >> 371 /* Grab name */ >> 372 kallsyms_expand_symbol(get_symbol_offset(pos), >> 373 name, KSYM_NAME_LEN); >> 374 modname[0] = '\0'; >> 375 return 0; >> 376 } >> 377 /* See if it's in a module. */ >> 378 return lookup_module_symbol_attrs(addr, size, offset, modname, name); >> 379 } >> 380 434 /* Look up a kernel symbol and return it in a 381 /* Look up a kernel symbol and return it in a text buffer. */ 435 static int __sprint_symbol(char *buffer, unsig 382 static int __sprint_symbol(char *buffer, unsigned long address, 436 int symbol_offset, !! 383 int symbol_offset, int add_offset) 437 { 384 { 438 char *modname; 385 char *modname; 439 const unsigned char *buildid; !! 386 const char *name; 440 unsigned long offset, size; 387 unsigned long offset, size; 441 int len; 388 int len; 442 389 443 address += symbol_offset; 390 address += symbol_offset; 444 len = kallsyms_lookup_buildid(address, !! 391 name = kallsyms_lookup(address, &size, &offset, &modname, buffer); 445 buffer) !! 392 if (!name) 446 if (!len) << 447 return sprintf(buffer, "0x%lx" 393 return sprintf(buffer, "0x%lx", address - symbol_offset); 448 394 >> 395 if (name != buffer) >> 396 strcpy(buffer, name); >> 397 len = strlen(buffer); 449 offset -= symbol_offset; 398 offset -= symbol_offset; 450 399 451 if (add_offset) 400 if (add_offset) 452 len += sprintf(buffer + len, " 401 len += sprintf(buffer + len, "+%#lx/%#lx", offset, size); 453 402 454 if (modname) { !! 403 if (modname) 455 len += sprintf(buffer + len, " !! 404 len += sprintf(buffer + len, " [%s]", modname); 456 #if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) << 457 if (add_buildid && buildid) { << 458 /* build ID should mat << 459 #if IS_ENABLED(CONFIG_MODULES) << 460 static_assert(sizeof(t << 461 #endif << 462 len += sprintf(buffer << 463 } << 464 #endif << 465 len += sprintf(buffer + len, " << 466 } << 467 405 468 return len; 406 return len; 469 } 407 } 470 408 471 /** 409 /** 472 * sprint_symbol - Look up a kernel symbol and 410 * sprint_symbol - Look up a kernel symbol and return it in a text buffer 473 * @buffer: buffer to be stored 411 * @buffer: buffer to be stored 474 * @address: address to lookup 412 * @address: address to lookup 475 * 413 * 476 * This function looks up a kernel symbol with 414 * This function looks up a kernel symbol with @address and stores its name, 477 * offset, size and module name to @buffer if 415 * offset, size and module name to @buffer if possible. If no symbol was found, 478 * just saves its @address as is. 416 * just saves its @address as is. 479 * 417 * 480 * This function returns the number of bytes s 418 * This function returns the number of bytes stored in @buffer. 481 */ 419 */ 482 int sprint_symbol(char *buffer, unsigned long 420 int sprint_symbol(char *buffer, unsigned long address) 483 { 421 { 484 return __sprint_symbol(buffer, address !! 422 return __sprint_symbol(buffer, address, 0, 1); 485 } 423 } 486 EXPORT_SYMBOL_GPL(sprint_symbol); 424 EXPORT_SYMBOL_GPL(sprint_symbol); 487 425 488 /** 426 /** 489 * sprint_symbol_build_id - Look up a kernel s << 490 * @buffer: buffer to be stored << 491 * @address: address to lookup << 492 * << 493 * This function looks up a kernel symbol with << 494 * offset, size, module name and module build << 495 * symbol was found, just saves its @address a << 496 * << 497 * This function returns the number of bytes s << 498 */ << 499 int sprint_symbol_build_id(char *buffer, unsig << 500 { << 501 return __sprint_symbol(buffer, address << 502 } << 503 EXPORT_SYMBOL_GPL(sprint_symbol_build_id); << 504 << 505 /** << 506 * sprint_symbol_no_offset - Look up a kernel 427 * sprint_symbol_no_offset - Look up a kernel symbol and return it in a text buffer 507 * @buffer: buffer to be stored 428 * @buffer: buffer to be stored 508 * @address: address to lookup 429 * @address: address to lookup 509 * 430 * 510 * This function looks up a kernel symbol with 431 * This function looks up a kernel symbol with @address and stores its name 511 * and module name to @buffer if possible. If 432 * and module name to @buffer if possible. If no symbol was found, just saves 512 * its @address as is. 433 * its @address as is. 513 * 434 * 514 * This function returns the number of bytes s 435 * This function returns the number of bytes stored in @buffer. 515 */ 436 */ 516 int sprint_symbol_no_offset(char *buffer, unsi 437 int sprint_symbol_no_offset(char *buffer, unsigned long address) 517 { 438 { 518 return __sprint_symbol(buffer, address !! 439 return __sprint_symbol(buffer, address, 0, 0); 519 } 440 } 520 EXPORT_SYMBOL_GPL(sprint_symbol_no_offset); 441 EXPORT_SYMBOL_GPL(sprint_symbol_no_offset); 521 442 522 /** 443 /** 523 * sprint_backtrace - Look up a backtrace symb 444 * sprint_backtrace - Look up a backtrace symbol and return it in a text buffer 524 * @buffer: buffer to be stored 445 * @buffer: buffer to be stored 525 * @address: address to lookup 446 * @address: address to lookup 526 * 447 * 527 * This function is for stack backtrace and do 448 * This function is for stack backtrace and does the same thing as 528 * sprint_symbol() but with modified/decreased 449 * sprint_symbol() but with modified/decreased @address. If there is a 529 * tail-call to the function marked "noreturn" 450 * tail-call to the function marked "noreturn", gcc optimized out code after 530 * the call so that the stack-saved return add 451 * the call so that the stack-saved return address could point outside of the 531 * caller. This function ensures that kallsyms 452 * caller. This function ensures that kallsyms will find the original caller 532 * by decreasing @address. 453 * by decreasing @address. 533 * 454 * 534 * This function returns the number of bytes s 455 * This function returns the number of bytes stored in @buffer. 535 */ 456 */ 536 int sprint_backtrace(char *buffer, unsigned lo 457 int sprint_backtrace(char *buffer, unsigned long address) 537 { 458 { 538 return __sprint_symbol(buffer, address !! 459 return __sprint_symbol(buffer, address, -1, 1); 539 } 460 } 540 461 541 /** !! 462 /* Look up a kernel symbol and print it to the kernel messages. */ 542 * sprint_backtrace_build_id - Look up a backt !! 463 void __print_symbol(const char *fmt, unsigned long address) 543 * @buffer: buffer to be stored << 544 * @address: address to lookup << 545 * << 546 * This function is for stack backtrace and do << 547 * sprint_symbol() but with modified/decreased << 548 * tail-call to the function marked "noreturn" << 549 * the call so that the stack-saved return add << 550 * caller. This function ensures that kallsyms << 551 * by decreasing @address. This function also << 552 * the @buffer if @address is within a kernel << 553 * << 554 * This function returns the number of bytes s << 555 */ << 556 int sprint_backtrace_build_id(char *buffer, un << 557 { 464 { 558 return __sprint_symbol(buffer, address !! 465 char buffer[KSYM_SYMBOL_LEN]; >> 466 >> 467 sprint_symbol(buffer, address); >> 468 >> 469 printk(fmt, buffer); 559 } 470 } >> 471 EXPORT_SYMBOL(__print_symbol); 560 472 561 /* To avoid using get_symbol_offset for every 473 /* To avoid using get_symbol_offset for every symbol, we carry prefix along. */ 562 struct kallsym_iter { 474 struct kallsym_iter { 563 loff_t pos; 475 loff_t pos; 564 loff_t pos_mod_end; 476 loff_t pos_mod_end; 565 loff_t pos_ftrace_mod_end; << 566 loff_t pos_bpf_end; << 567 unsigned long value; 477 unsigned long value; 568 unsigned int nameoff; /* If iterating 478 unsigned int nameoff; /* If iterating in core kernel symbols. */ 569 char type; 479 char type; 570 char name[KSYM_NAME_LEN]; 480 char name[KSYM_NAME_LEN]; 571 char module_name[MODULE_NAME_LEN]; 481 char module_name[MODULE_NAME_LEN]; 572 int exported; 482 int exported; 573 int show_value; << 574 }; 483 }; 575 484 576 static int get_ksymbol_mod(struct kallsym_iter 485 static int get_ksymbol_mod(struct kallsym_iter *iter) 577 { 486 { 578 int ret = module_get_kallsym(iter->pos 487 int ret = module_get_kallsym(iter->pos - kallsyms_num_syms, 579 &iter->va 488 &iter->value, &iter->type, 580 iter->nam 489 iter->name, iter->module_name, 581 &iter->ex 490 &iter->exported); 582 if (ret < 0) { 491 if (ret < 0) { 583 iter->pos_mod_end = iter->pos; 492 iter->pos_mod_end = iter->pos; 584 return 0; 493 return 0; 585 } 494 } 586 495 587 return 1; 496 return 1; 588 } 497 } 589 498 590 /* << 591 * ftrace_mod_get_kallsym() may also get symbo << 592 * purposes. In that case "__builtin__ftrace" << 593 * though "__builtin__ftrace" is not a module. << 594 */ << 595 static int get_ksymbol_ftrace_mod(struct kalls << 596 { << 597 int ret = ftrace_mod_get_kallsym(iter- << 598 &iter << 599 iter- << 600 &iter << 601 if (ret < 0) { << 602 iter->pos_ftrace_mod_end = ite << 603 return 0; << 604 } << 605 << 606 return 1; << 607 } << 608 << 609 static int get_ksymbol_bpf(struct kallsym_iter 499 static int get_ksymbol_bpf(struct kallsym_iter *iter) 610 { 500 { 611 int ret; !! 501 iter->module_name[0] = '\0'; 612 << 613 strscpy(iter->module_name, "bpf", MODU << 614 iter->exported = 0; << 615 ret = bpf_get_kallsym(iter->pos - iter << 616 &iter->value, &i << 617 iter->name); << 618 if (ret < 0) { << 619 iter->pos_bpf_end = iter->pos; << 620 return 0; << 621 } << 622 << 623 return 1; << 624 } << 625 << 626 /* << 627 * This uses "__builtin__kprobes" as a module << 628 * allocated for kprobes' purposes, even thoug << 629 * module. << 630 */ << 631 static int get_ksymbol_kprobe(struct kallsym_i << 632 { << 633 strscpy(iter->module_name, "__builtin_ << 634 iter->exported = 0; 502 iter->exported = 0; 635 return kprobe_get_kallsym(iter->pos - !! 503 return bpf_get_kallsym(iter->pos - iter->pos_mod_end, 636 &iter->value !! 504 &iter->value, &iter->type, 637 iter->name) !! 505 iter->name) < 0 ? 0 : 1; 638 } 506 } 639 507 640 /* Returns space to next name. */ 508 /* Returns space to next name. */ 641 static unsigned long get_ksymbol_core(struct k 509 static unsigned long get_ksymbol_core(struct kallsym_iter *iter) 642 { 510 { 643 unsigned off = iter->nameoff; 511 unsigned off = iter->nameoff; 644 512 645 iter->module_name[0] = '\0'; 513 iter->module_name[0] = '\0'; 646 iter->value = kallsyms_sym_address(ite 514 iter->value = kallsyms_sym_address(iter->pos); 647 515 648 iter->type = kallsyms_get_symbol_type( 516 iter->type = kallsyms_get_symbol_type(off); 649 517 650 off = kallsyms_expand_symbol(off, iter 518 off = kallsyms_expand_symbol(off, iter->name, ARRAY_SIZE(iter->name)); 651 519 652 return off - iter->nameoff; 520 return off - iter->nameoff; 653 } 521 } 654 522 655 static void reset_iter(struct kallsym_iter *it 523 static void reset_iter(struct kallsym_iter *iter, loff_t new_pos) 656 { 524 { 657 iter->name[0] = '\0'; 525 iter->name[0] = '\0'; 658 iter->nameoff = get_symbol_offset(new_ 526 iter->nameoff = get_symbol_offset(new_pos); 659 iter->pos = new_pos; 527 iter->pos = new_pos; 660 if (new_pos == 0) { !! 528 if (new_pos == 0) 661 iter->pos_mod_end = 0; 529 iter->pos_mod_end = 0; 662 iter->pos_ftrace_mod_end = 0; << 663 iter->pos_bpf_end = 0; << 664 } << 665 } 530 } 666 531 667 /* << 668 * The end position (last + 1) of each additio << 669 * in iter->pos_..._end as each section is add << 670 * determine which get_ksymbol_...() function << 671 */ << 672 static int update_iter_mod(struct kallsym_iter 532 static int update_iter_mod(struct kallsym_iter *iter, loff_t pos) 673 { 533 { 674 iter->pos = pos; 534 iter->pos = pos; 675 535 676 if ((!iter->pos_mod_end || iter->pos_m !! 536 if (iter->pos_mod_end > 0 && 677 get_ksymbol_mod(iter)) !! 537 iter->pos_mod_end < iter->pos) 678 return 1; !! 538 return get_ksymbol_bpf(iter); 679 << 680 if ((!iter->pos_ftrace_mod_end || iter << 681 get_ksymbol_ftrace_mod(iter)) << 682 return 1; << 683 539 684 if ((!iter->pos_bpf_end || iter->pos_b !! 540 if (!get_ksymbol_mod(iter)) 685 get_ksymbol_bpf(iter)) !! 541 return get_ksymbol_bpf(iter); 686 return 1; << 687 542 688 return get_ksymbol_kprobe(iter); !! 543 return 1; 689 } 544 } 690 545 691 /* Returns false if pos at or past end of file 546 /* Returns false if pos at or past end of file. */ 692 static int update_iter(struct kallsym_iter *it 547 static int update_iter(struct kallsym_iter *iter, loff_t pos) 693 { 548 { 694 /* Module symbols can be accessed rand 549 /* Module symbols can be accessed randomly. */ 695 if (pos >= kallsyms_num_syms) 550 if (pos >= kallsyms_num_syms) 696 return update_iter_mod(iter, p 551 return update_iter_mod(iter, pos); 697 552 698 /* If we're not on the desired positio 553 /* If we're not on the desired position, reset to new position. */ 699 if (pos != iter->pos) 554 if (pos != iter->pos) 700 reset_iter(iter, pos); 555 reset_iter(iter, pos); 701 556 702 iter->nameoff += get_ksymbol_core(iter 557 iter->nameoff += get_ksymbol_core(iter); 703 iter->pos++; 558 iter->pos++; 704 559 705 return 1; 560 return 1; 706 } 561 } 707 562 708 static void *s_next(struct seq_file *m, void * 563 static void *s_next(struct seq_file *m, void *p, loff_t *pos) 709 { 564 { 710 (*pos)++; 565 (*pos)++; 711 566 712 if (!update_iter(m->private, *pos)) 567 if (!update_iter(m->private, *pos)) 713 return NULL; 568 return NULL; 714 return p; 569 return p; 715 } 570 } 716 571 717 static void *s_start(struct seq_file *m, loff_ 572 static void *s_start(struct seq_file *m, loff_t *pos) 718 { 573 { 719 if (!update_iter(m->private, *pos)) 574 if (!update_iter(m->private, *pos)) 720 return NULL; 575 return NULL; 721 return m->private; 576 return m->private; 722 } 577 } 723 578 724 static void s_stop(struct seq_file *m, void *p 579 static void s_stop(struct seq_file *m, void *p) 725 { 580 { 726 } 581 } 727 582 728 static int s_show(struct seq_file *m, void *p) 583 static int s_show(struct seq_file *m, void *p) 729 { 584 { 730 void *value; << 731 struct kallsym_iter *iter = m->private 585 struct kallsym_iter *iter = m->private; 732 586 733 /* Some debugging symbols have no name 587 /* Some debugging symbols have no name. Ignore them. */ 734 if (!iter->name[0]) 588 if (!iter->name[0]) 735 return 0; 589 return 0; 736 590 737 value = iter->show_value ? (void *)ite << 738 << 739 if (iter->module_name[0]) { 591 if (iter->module_name[0]) { 740 char type; 592 char type; 741 593 742 /* 594 /* 743 * Label it "global" if it is 595 * Label it "global" if it is exported, 744 * "local" if not exported. 596 * "local" if not exported. 745 */ 597 */ 746 type = iter->exported ? touppe 598 type = iter->exported ? toupper(iter->type) : 747 tolowe 599 tolower(iter->type); 748 seq_printf(m, "%px %c %s\t[%s] !! 600 seq_printf(m, "%pK %c %s\t[%s]\n", (void *)iter->value, 749 type, iter->name, i 601 type, iter->name, iter->module_name); 750 } else 602 } else 751 seq_printf(m, "%px %c %s\n", v !! 603 seq_printf(m, "%pK %c %s\n", (void *)iter->value, 752 iter->type, iter->n 604 iter->type, iter->name); 753 return 0; 605 return 0; 754 } 606 } 755 607 756 static const struct seq_operations kallsyms_op 608 static const struct seq_operations kallsyms_op = { 757 .start = s_start, 609 .start = s_start, 758 .next = s_next, 610 .next = s_next, 759 .stop = s_stop, 611 .stop = s_stop, 760 .show = s_show 612 .show = s_show 761 }; 613 }; 762 614 763 #ifdef CONFIG_BPF_SYSCALL << 764 << 765 struct bpf_iter__ksym { << 766 __bpf_md_ptr(struct bpf_iter_meta *, m << 767 __bpf_md_ptr(struct kallsym_iter *, ks << 768 }; << 769 << 770 static int ksym_prog_seq_show(struct seq_file << 771 { << 772 struct bpf_iter__ksym ctx; << 773 struct bpf_iter_meta meta; << 774 struct bpf_prog *prog; << 775 << 776 meta.seq = m; << 777 prog = bpf_iter_get_info(&meta, in_sto << 778 if (!prog) << 779 return 0; << 780 << 781 ctx.meta = &meta; << 782 ctx.ksym = m ? m->private : NULL; << 783 return bpf_iter_run_prog(prog, &ctx); << 784 } << 785 << 786 static int bpf_iter_ksym_seq_show(struct seq_f << 787 { << 788 return ksym_prog_seq_show(m, false); << 789 } << 790 << 791 static void bpf_iter_ksym_seq_stop(struct seq_ << 792 { << 793 if (!p) << 794 (void) ksym_prog_seq_show(m, t << 795 else << 796 s_stop(m, p); << 797 } << 798 << 799 static const struct seq_operations bpf_iter_ks << 800 .start = s_start, << 801 .next = s_next, << 802 .stop = bpf_iter_ksym_seq_stop, << 803 .show = bpf_iter_ksym_seq_show, << 804 }; << 805 << 806 static int bpf_iter_ksym_init(void *priv_data, << 807 { << 808 struct kallsym_iter *iter = priv_data; << 809 << 810 reset_iter(iter, 0); << 811 << 812 /* cache here as in kallsyms_open() ca << 813 * credentials to tell BPF iterators i << 814 */ << 815 iter->show_value = kallsyms_show_value << 816 << 817 return 0; << 818 } << 819 << 820 DEFINE_BPF_ITER_FUNC(ksym, struct bpf_iter_met << 821 << 822 static const struct bpf_iter_seq_info ksym_ite << 823 .seq_ops = &bpf_iter_ks << 824 .init_seq_private = bpf_iter_ksy << 825 .fini_seq_private = NULL, << 826 .seq_priv_size = sizeof(struc << 827 }; << 828 << 829 static struct bpf_iter_reg ksym_iter_reg_info << 830 .target = "ksym", << 831 .feature = BPF_ITER_RES << 832 .ctx_arg_info_size = 1, << 833 .ctx_arg_info = { << 834 { offsetof(struct bpf_iter__ks << 835 PTR_TO_BTF_ID_OR_NULL }, << 836 }, << 837 .seq_info = &ksym_iter_s << 838 }; << 839 << 840 BTF_ID_LIST(btf_ksym_iter_id) << 841 BTF_ID(struct, kallsym_iter) << 842 << 843 static int __init bpf_ksym_iter_register(void) << 844 { << 845 ksym_iter_reg_info.ctx_arg_info[0].btf << 846 return bpf_iter_reg_target(&ksym_iter_ << 847 } << 848 << 849 late_initcall(bpf_ksym_iter_register); << 850 << 851 #endif /* CONFIG_BPF_SYSCALL */ << 852 << 853 static int kallsyms_open(struct inode *inode, 615 static int kallsyms_open(struct inode *inode, struct file *file) 854 { 616 { 855 /* 617 /* 856 * We keep iterator in m->private, sin 618 * We keep iterator in m->private, since normal case is to 857 * s_start from where we left off, so 619 * s_start from where we left off, so we avoid doing 858 * using get_symbol_offset for every s 620 * using get_symbol_offset for every symbol. 859 */ 621 */ 860 struct kallsym_iter *iter; 622 struct kallsym_iter *iter; 861 iter = __seq_open_private(file, &kalls 623 iter = __seq_open_private(file, &kallsyms_op, sizeof(*iter)); 862 if (!iter) 624 if (!iter) 863 return -ENOMEM; 625 return -ENOMEM; 864 reset_iter(iter, 0); 626 reset_iter(iter, 0); 865 627 866 /* << 867 * Instead of checking this on every s << 868 * the result here at open time. << 869 */ << 870 iter->show_value = kallsyms_show_value << 871 return 0; 628 return 0; 872 } 629 } 873 630 874 #ifdef CONFIG_KGDB_KDB 631 #ifdef CONFIG_KGDB_KDB 875 const char *kdb_walk_kallsyms(loff_t *pos) 632 const char *kdb_walk_kallsyms(loff_t *pos) 876 { 633 { 877 static struct kallsym_iter kdb_walk_ka 634 static struct kallsym_iter kdb_walk_kallsyms_iter; 878 if (*pos == 0) { 635 if (*pos == 0) { 879 memset(&kdb_walk_kallsyms_iter 636 memset(&kdb_walk_kallsyms_iter, 0, 880 sizeof(kdb_walk_kallsym 637 sizeof(kdb_walk_kallsyms_iter)); 881 reset_iter(&kdb_walk_kallsyms_ 638 reset_iter(&kdb_walk_kallsyms_iter, 0); 882 } 639 } 883 while (1) { 640 while (1) { 884 if (!update_iter(&kdb_walk_kal 641 if (!update_iter(&kdb_walk_kallsyms_iter, *pos)) 885 return NULL; 642 return NULL; 886 ++*pos; 643 ++*pos; 887 /* Some debugging symbols have 644 /* Some debugging symbols have no name. Ignore them. */ 888 if (kdb_walk_kallsyms_iter.nam 645 if (kdb_walk_kallsyms_iter.name[0]) 889 return kdb_walk_kallsy 646 return kdb_walk_kallsyms_iter.name; 890 } 647 } 891 } 648 } 892 #endif /* CONFIG_KGDB_KDB */ 649 #endif /* CONFIG_KGDB_KDB */ 893 650 894 static const struct proc_ops kallsyms_proc_ops !! 651 static const struct file_operations kallsyms_operations = { 895 .proc_open = kallsyms_open, !! 652 .open = kallsyms_open, 896 .proc_read = seq_read, !! 653 .read = seq_read, 897 .proc_lseek = seq_lseek, !! 654 .llseek = seq_lseek, 898 .proc_release = seq_release_private, !! 655 .release = seq_release_private, 899 }; 656 }; 900 657 901 static int __init kallsyms_init(void) 658 static int __init kallsyms_init(void) 902 { 659 { 903 proc_create("kallsyms", 0444, NULL, &k !! 660 proc_create("kallsyms", 0444, NULL, &kallsyms_operations); 904 return 0; 661 return 0; 905 } 662 } 906 device_initcall(kallsyms_init); 663 device_initcall(kallsyms_init); 907 664
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.