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