xref: /openbmc/linux/include/linux/kallsyms.h (revision 0eeaf1eb)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
21da177e4SLinus Torvalds /* Rewritten and vastly simplified by Rusty Russell for in-kernel
31da177e4SLinus Torvalds  * module loader:
41da177e4SLinus Torvalds  *   Copyright 2002 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
51da177e4SLinus Torvalds  */
61da177e4SLinus Torvalds #ifndef _LINUX_KALLSYMS_H
71da177e4SLinus Torvalds #define _LINUX_KALLSYMS_H
81da177e4SLinus Torvalds 
940e48eedSAdrian Bunk #include <linux/errno.h>
109294523eSStephen Boyd #include <linux/buildid.h>
112711b793SVegard Nossum #include <linux/kernel.h>
125a75983eSKamalesh Babulal #include <linux/stddef.h>
1304b8eb7aSSergey Senozhatsky #include <linux/mm.h>
1404b8eb7aSSergey Senozhatsky #include <linux/module.h>
1504b8eb7aSSergey Senozhatsky 
1604b8eb7aSSergey Senozhatsky #include <asm/sections.h>
171da177e4SLinus Torvalds 
18b8a94bfbSMiguel Ojeda #define KSYM_NAME_LEN 512
199294523eSStephen Boyd #define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s %s]") + \
209294523eSStephen Boyd 			(KSYM_NAME_LEN - 1) + \
219294523eSStephen Boyd 			2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + \
229294523eSStephen Boyd 			(BUILD_ID_SIZE_MAX * 2) + 1)
231da177e4SLinus Torvalds 
2416025184SKees Cook struct cred;
2575a66614SAnders Kaseorg struct module;
2675a66614SAnders Kaseorg 
is_kernel_text(unsigned long addr)2704b8eb7aSSergey Senozhatsky static inline int is_kernel_text(unsigned long addr)
2804b8eb7aSSergey Senozhatsky {
298f6e42e8SKefeng Wang 	if (__is_kernel_text(addr))
3004b8eb7aSSergey Senozhatsky 		return 1;
3104b8eb7aSSergey Senozhatsky 	return in_gate_area_no_mm(addr);
3204b8eb7aSSergey Senozhatsky }
3304b8eb7aSSergey Senozhatsky 
is_kernel(unsigned long addr)3404b8eb7aSSergey Senozhatsky static inline int is_kernel(unsigned long addr)
3504b8eb7aSSergey Senozhatsky {
368f6e42e8SKefeng Wang 	if (__is_kernel(addr))
3704b8eb7aSSergey Senozhatsky 		return 1;
3804b8eb7aSSergey Senozhatsky 	return in_gate_area_no_mm(addr);
3904b8eb7aSSergey Senozhatsky }
4004b8eb7aSSergey Senozhatsky 
is_ksym_addr(unsigned long addr)4104b8eb7aSSergey Senozhatsky static inline int is_ksym_addr(unsigned long addr)
4204b8eb7aSSergey Senozhatsky {
4304b8eb7aSSergey Senozhatsky 	if (IS_ENABLED(CONFIG_KALLSYMS_ALL))
4404b8eb7aSSergey Senozhatsky 		return is_kernel(addr);
4504b8eb7aSSergey Senozhatsky 
4604b8eb7aSSergey Senozhatsky 	return is_kernel_text(addr) || is_kernel_inittext(addr);
4704b8eb7aSSergey Senozhatsky }
4804b8eb7aSSergey Senozhatsky 
dereference_symbol_descriptor(void * ptr)4904b8eb7aSSergey Senozhatsky static inline void *dereference_symbol_descriptor(void *ptr)
5004b8eb7aSSergey Senozhatsky {
51a257caccSChristophe Leroy #ifdef CONFIG_HAVE_FUNCTION_DESCRIPTORS
5204b8eb7aSSergey Senozhatsky 	struct module *mod;
5304b8eb7aSSergey Senozhatsky 
5404b8eb7aSSergey Senozhatsky 	ptr = dereference_kernel_function_descriptor(ptr);
5504b8eb7aSSergey Senozhatsky 	if (is_ksym_addr((unsigned long)ptr))
5604b8eb7aSSergey Senozhatsky 		return ptr;
5704b8eb7aSSergey Senozhatsky 
5804b8eb7aSSergey Senozhatsky 	preempt_disable();
5904b8eb7aSSergey Senozhatsky 	mod = __module_address((unsigned long)ptr);
6004b8eb7aSSergey Senozhatsky 	preempt_enable();
6104b8eb7aSSergey Senozhatsky 
6204b8eb7aSSergey Senozhatsky 	if (mod)
6304b8eb7aSSergey Senozhatsky 		ptr = dereference_module_function_descriptor(mod, ptr);
6404b8eb7aSSergey Senozhatsky #endif
6504b8eb7aSSergey Senozhatsky 	return ptr;
6604b8eb7aSSergey Senozhatsky }
6704b8eb7aSSergey Senozhatsky 
68*0eeaf1ebSManinder Singh /* How and when do we show kallsyms values? */
69*0eeaf1ebSManinder Singh extern bool kallsyms_show_value(const struct cred *cred);
70*0eeaf1ebSManinder Singh 
71d721def7SJiri Olsa #ifdef CONFIG_KALLSYMS
7230f3bb09SZhen Lei unsigned long kallsyms_sym_address(int idx);
733703bd54SZhen Lei int kallsyms_on_each_symbol(int (*fn)(void *, const char *, unsigned long),
7475a66614SAnders Kaseorg 			    void *data);
754dc533e0SZhen Lei int kallsyms_on_each_match_symbol(int (*fn)(void *, unsigned long),
764dc533e0SZhen Lei 				  const char *name, void *data);
7775a66614SAnders Kaseorg 
783e355205SChristoph Hellwig /* Lookup the address for a symbol. Returns 0 if not found. */
793e355205SChristoph Hellwig unsigned long kallsyms_lookup_name(const char *name);
803e355205SChristoph Hellwig 
81ffc50891SFranck Bui-Huu extern int kallsyms_lookup_size_offset(unsigned long addr,
82ffc50891SFranck Bui-Huu 				  unsigned long *symbolsize,
83ffc50891SFranck Bui-Huu 				  unsigned long *offset);
84ffc50891SFranck Bui-Huu 
851da177e4SLinus Torvalds /* Lookup an address.  modname is set to NULL if it's in the kernel. */
861da177e4SLinus Torvalds const char *kallsyms_lookup(unsigned long addr,
871da177e4SLinus Torvalds 			    unsigned long *symbolsize,
881da177e4SLinus Torvalds 			    unsigned long *offset,
891da177e4SLinus Torvalds 			    char **modname, char *namebuf);
901da177e4SLinus Torvalds 
9142e38083SRobert Peterson /* Look up a kernel symbol and return it in a text buffer. */
9242e38083SRobert Peterson extern int sprint_symbol(char *buffer, unsigned long address);
939294523eSStephen Boyd extern int sprint_symbol_build_id(char *buffer, unsigned long address);
944796dd20SStephen Boyd extern int sprint_symbol_no_offset(char *buffer, unsigned long address);
950f77a8d3SNamhyung Kim extern int sprint_backtrace(char *buffer, unsigned long address);
969294523eSStephen Boyd extern int sprint_backtrace_build_id(char *buffer, unsigned long address);
9742e38083SRobert Peterson 
989d65cb4aSAlexey Dobriyan int lookup_symbol_name(unsigned long addr, char *symname);
999d65cb4aSAlexey Dobriyan 
1001da177e4SLinus Torvalds #else /* !CONFIG_KALLSYMS */
1011da177e4SLinus Torvalds 
kallsyms_lookup_name(const char * name)1021da177e4SLinus Torvalds static inline unsigned long kallsyms_lookup_name(const char *name)
1031da177e4SLinus Torvalds {
1041da177e4SLinus Torvalds 	return 0;
1051da177e4SLinus Torvalds }
1061da177e4SLinus Torvalds 
kallsyms_lookup_size_offset(unsigned long addr,unsigned long * symbolsize,unsigned long * offset)107ffc50891SFranck Bui-Huu static inline int kallsyms_lookup_size_offset(unsigned long addr,
108ffc50891SFranck Bui-Huu 					      unsigned long *symbolsize,
109ffc50891SFranck Bui-Huu 					      unsigned long *offset)
110ffc50891SFranck Bui-Huu {
111ffc50891SFranck Bui-Huu 	return 0;
112ffc50891SFranck Bui-Huu }
113ffc50891SFranck Bui-Huu 
kallsyms_lookup(unsigned long addr,unsigned long * symbolsize,unsigned long * offset,char ** modname,char * namebuf)1141da177e4SLinus Torvalds static inline const char *kallsyms_lookup(unsigned long addr,
1151da177e4SLinus Torvalds 					  unsigned long *symbolsize,
1161da177e4SLinus Torvalds 					  unsigned long *offset,
1171da177e4SLinus Torvalds 					  char **modname, char *namebuf)
1181da177e4SLinus Torvalds {
1191da177e4SLinus Torvalds 	return NULL;
1201da177e4SLinus Torvalds }
1211da177e4SLinus Torvalds 
sprint_symbol(char * buffer,unsigned long addr)12242e38083SRobert Peterson static inline int sprint_symbol(char *buffer, unsigned long addr)
12342e38083SRobert Peterson {
12442e38083SRobert Peterson 	*buffer = '\0';
12542e38083SRobert Peterson 	return 0;
12642e38083SRobert Peterson }
12742e38083SRobert Peterson 
sprint_symbol_build_id(char * buffer,unsigned long address)1289294523eSStephen Boyd static inline int sprint_symbol_build_id(char *buffer, unsigned long address)
1299294523eSStephen Boyd {
1309294523eSStephen Boyd 	*buffer = '\0';
1319294523eSStephen Boyd 	return 0;
1329294523eSStephen Boyd }
1339294523eSStephen Boyd 
sprint_symbol_no_offset(char * buffer,unsigned long addr)1344796dd20SStephen Boyd static inline int sprint_symbol_no_offset(char *buffer, unsigned long addr)
1354796dd20SStephen Boyd {
1364796dd20SStephen Boyd 	*buffer = '\0';
1374796dd20SStephen Boyd 	return 0;
1384796dd20SStephen Boyd }
1394796dd20SStephen Boyd 
sprint_backtrace(char * buffer,unsigned long addr)1400f77a8d3SNamhyung Kim static inline int sprint_backtrace(char *buffer, unsigned long addr)
1410f77a8d3SNamhyung Kim {
1420f77a8d3SNamhyung Kim 	*buffer = '\0';
1430f77a8d3SNamhyung Kim 	return 0;
1440f77a8d3SNamhyung Kim }
1450f77a8d3SNamhyung Kim 
sprint_backtrace_build_id(char * buffer,unsigned long addr)1469294523eSStephen Boyd static inline int sprint_backtrace_build_id(char *buffer, unsigned long addr)
1479294523eSStephen Boyd {
1489294523eSStephen Boyd 	*buffer = '\0';
1499294523eSStephen Boyd 	return 0;
1509294523eSStephen Boyd }
1519294523eSStephen Boyd 
lookup_symbol_name(unsigned long addr,char * symname)1529d65cb4aSAlexey Dobriyan static inline int lookup_symbol_name(unsigned long addr, char *symname)
1539d65cb4aSAlexey Dobriyan {
1549d65cb4aSAlexey Dobriyan 	return -ERANGE;
1559d65cb4aSAlexey Dobriyan }
1569d65cb4aSAlexey Dobriyan 
kallsyms_on_each_symbol(int (* fn)(void *,const char *,unsigned long),void * data)1573703bd54SZhen Lei static inline int kallsyms_on_each_symbol(int (*fn)(void *, const char *, unsigned long),
1583703bd54SZhen Lei 					  void *data)
159d721def7SJiri Olsa {
160d721def7SJiri Olsa 	return -EOPNOTSUPP;
161d721def7SJiri Olsa }
1624dc533e0SZhen Lei 
kallsyms_on_each_match_symbol(int (* fn)(void *,unsigned long),const char * name,void * data)1634dc533e0SZhen Lei static inline int kallsyms_on_each_match_symbol(int (*fn)(void *, unsigned long),
1644dc533e0SZhen Lei 						const char *name, void *data)
1654dc533e0SZhen Lei {
1664dc533e0SZhen Lei 	return -EOPNOTSUPP;
1674dc533e0SZhen Lei }
1681da177e4SLinus Torvalds #endif /*CONFIG_KALLSYMS*/
1691da177e4SLinus Torvalds 
print_ip_sym(const char * loglvl,unsigned long ip)1702062a4e8SDmitry Safonov static inline void print_ip_sym(const char *loglvl, unsigned long ip)
1712711b793SVegard Nossum {
1722062a4e8SDmitry Safonov 	printk("%s[<%px>] %pS\n", loglvl, (void *) ip, (void *) ip);
1732711b793SVegard Nossum }
1748d8fdf5cSHeiko Carstens 
1751da177e4SLinus Torvalds #endif /*_LINUX_KALLSYMS_H*/
176