Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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);