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