Commit a5508ddc authored by Rusty Russell's avatar Rusty Russell Committed by Linus Torvalds

[PATCH] kallsyms for new modules

Since I believe kallsyms is important, this reimplements it sanely,
using the current module infrastructure, and not using an external
kallsyms script.

FYI, the previous interface was:

int kallsyms_symbol_to_address(
	const char       *name,			/* Name to lookup */
	unsigned long    *token,		/* Which module to start with */
	const char      **mod_name,		/* Set to module name or "kernel" */
	unsigned long    *mod_start,		/* Set to start address of module */
	unsigned long    *mod_end,		/* Set to end address of module */
	const char      **sec_name,		/* Set to section name */
	unsigned long    *sec_start,		/* Set to start address of section */
	unsigned long    *sec_end,		/* Set to end address of section */
	const char      **sym_name,		/* Set to full symbol name */
	unsigned long    *sym_start,		/* Set to start address of symbol */
	unsigned long    *sym_end		/* Set to end address of symbol */
	);

The new one is:
/* Lookup an address.  modname is set to NULL if it's in the kernel. */
const char *kallsyms_lookup(unsigned long addr,
			    unsigned long *symbolsize,
			    unsigned long *offset,
			    char **modname);
parent 60c30d29
...@@ -157,7 +157,7 @@ OBJCOPY = $(CROSS_COMPILE)objcopy ...@@ -157,7 +157,7 @@ OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump OBJDUMP = $(CROSS_COMPILE)objdump
AWK = awk AWK = awk
GENKSYMS = /sbin/genksyms GENKSYMS = /sbin/genksyms
KALLSYMS = /sbin/kallsyms KALLSYMS = scripts/kallsyms
PERL = perl PERL = perl
MODFLAGS = -DMODULE MODFLAGS = -DMODULE
CFLAGS_MODULE = $(MODFLAGS) CFLAGS_MODULE = $(MODFLAGS)
...@@ -335,7 +335,7 @@ ifdef CONFIG_KALLSYMS ...@@ -335,7 +335,7 @@ ifdef CONFIG_KALLSYMS
kallsyms.o := .tmp_kallsyms2.o kallsyms.o := .tmp_kallsyms2.o
quiet_cmd_kallsyms = KSYM $@ quiet_cmd_kallsyms = KSYM $@
cmd_kallsyms = $(KALLSYMS) $< > $@ cmd_kallsyms = sh $(KALLSYMS) $< $@
.tmp_kallsyms1.o: .tmp_vmlinux1 .tmp_kallsyms1.o: .tmp_vmlinux1
$(call cmd,kallsyms) $(call cmd,kallsyms)
......
...@@ -1604,14 +1604,13 @@ config DEBUG_HIGHMEM ...@@ -1604,14 +1604,13 @@ config DEBUG_HIGHMEM
This options enables addition error checking for high memory systems. This options enables addition error checking for high memory systems.
Disable for production systems. Disable for production systems.
# Reimplemented RSN. config KALLSYMS
#config KALLSYMS bool "Load all symbols for debugging/kksymoops"
# bool "Load all symbols for debugging/kksymoops" depends on DEBUG_KERNEL
# depends on DEBUG_KERNEL help
# help Say Y here to let the kernel print out symbolic crash information and
# Say Y here to let the kernel print out symbolic crash information and symbolic stack backtraces. This increases the size of the kernel
# symbolic stack backtraces. This increases the size of the kernel somewhat, as all symbols have to be loaded into the kernel image.
# somewhat, as all symbols have to be loaded into the kernel image.
config X86_EXTRA_IRQS config X86_EXTRA_IRQS
bool bool
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/mc146818rtc.h> #include <linux/mc146818rtc.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kallsyms.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/highmem.h> #include <linux/highmem.h>
#include <linux/kallsyms.h>
#ifdef CONFIG_EISA #ifdef CONFIG_EISA
#include <linux/ioport.h> #include <linux/ioport.h>
......
...@@ -813,13 +813,13 @@ config DEBUG_KERNEL ...@@ -813,13 +813,13 @@ config DEBUG_KERNEL
Say Y here if you are developing drivers or trying to debug and Say Y here if you are developing drivers or trying to debug and
identify kernel problems. identify kernel problems.
# config KALLSYMS config KALLSYMS
# bool "Load all symbols for debugging/kksymoops" bool "Load all symbols for debugging/kksymoops"
# depends on DEBUG_KERNEL depends on DEBUG_KERNEL
# help help
# Say Y here to let the kernel print out symbolic crash information and Say Y here to let the kernel print out symbolic crash information and
# symbolic stack backtraces. This increases the size of the kernel symbolic stack backtraces. This increases the size of the kernel
# somewhat, as all symbols have to be loaded into the kernel image. somewhat, as all symbols have to be loaded into the kernel image.
config IA64_PRINT_HAZARDS config IA64_PRINT_HAZARDS
bool "Print possible IA-64 dependency violations to console" bool "Print possible IA-64 dependency violations to console"
......
...@@ -1807,9 +1807,9 @@ config DEBUG_HIGHMEM ...@@ -1807,9 +1807,9 @@ config DEBUG_HIGHMEM
bool "Highmem debugging" bool "Highmem debugging"
depends on DEBUG_KERNEL && HIGHMEM depends on DEBUG_KERNEL && HIGHMEM
# config KALLSYMS config KALLSYMS
# bool "Load all symbols for debugging/kksymoops" bool "Load all symbols for debugging/kksymoops"
# depends on DEBUG_KERNEL depends on DEBUG_KERNEL
config KGDB config KGDB
bool "Include kgdb kernel debugger" bool "Include kgdb kernel debugger"
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <linux/prctl.h> #include <linux/prctl.h>
#include <linux/init_task.h> #include <linux/init_task.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kallsyms.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
......
...@@ -739,13 +739,13 @@ config INIT_DEBUG ...@@ -739,13 +739,13 @@ config INIT_DEBUG
help help
Fill __init and __initdata at the end of boot. This is only for debugging. Fill __init and __initdata at the end of boot. This is only for debugging.
# config KALLSYMS config KALLSYMS
# bool "Load all symbols for debugging/kksymoops" bool "Load all symbols for debugging/kksymoops"
# depends on DEBUG_KERNEL depends on DEBUG_KERNEL
# help help
# Say Y here to let the kernel print out symbolic crash information and Say Y here to let the kernel print out symbolic crash information and
# symbolic stack backtraces. This increases the size of the kernel symbolic stack backtraces. This increases the size of the kernel
# somewhat, as all symbols have to be loaded into the kernel image. somewhat, as all symbols have to be loaded into the kernel image.
endmenu endmenu
......
...@@ -258,20 +258,18 @@ static int proc_pid_cmdline(struct task_struct *task, char * buffer) ...@@ -258,20 +258,18 @@ static int proc_pid_cmdline(struct task_struct *task, char * buffer)
*/ */
static int proc_pid_wchan(struct task_struct *task, char *buffer) static int proc_pid_wchan(struct task_struct *task, char *buffer)
{ {
const char *sym_name, *ignore; char *modname;
unsigned long wchan, dummy; const char *sym_name;
unsigned long wchan, size, offset;
wchan = get_wchan(task); wchan = get_wchan(task);
if (!kallsyms_address_to_symbol(wchan, &ignore, &dummy, &dummy, sym_name = kallsyms_lookup(wchan, &size, &offset, &modname);
&ignore, &dummy, &dummy, &sym_name, if (sym_name)
&dummy, &dummy)) { return sprintf(buffer, "%s", sym_name);
return sprintf(buffer, "%lu", wchan); return sprintf(buffer, "%lu", wchan);
}
return sprintf(buffer, "%s", sym_name);
} }
#endif #endif /* CONFIG_KALLSYMS */
/************************************************************************/ /************************************************************************/
/* Here the fs part begins */ /* Here the fs part begins */
......
/* kallsyms headers /* Rewritten and vastly simplified by Rusty Russell for in-kernel
Copyright 2000 Keith Owens <kaos@ocs.com.au> * module loader:
* Copyright 2002 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
This file is part of the Linux modutils. It is exported to kernel
space so debuggers can access the kallsyms data.
The kallsyms data contains all the non-stack symbols from a kernel
or a module. The kernel symbols are held between __start___kallsyms
and __stop___kallsyms. The symbols for a module are accessed via
the struct module chain which is based at module_list.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#ifndef _LINUX_KALLSYMS_H
#define _LINUX_KALLSYMS_H
#ident "$Id: linux-2.4.9-kallsyms.patch,v 1.8 2002/02/11 18:34:53 arjanv Exp $" #include <linux/config.h>
#ifndef MODUTILS_KALLSYMS_H
#define MODUTILS_KALLSYMS_H 1
/* Have to (re)define these ElfW entries here because external kallsyms
* code does not have access to modutils/include/obj.h. This code is
* included from user spaces tools (modutils) and kernel, they need
* different includes.
*/
#ifndef ELFCLASS32
#ifdef __KERNEL__
#include <linux/elf.h>
#else /* __KERNEL__ */
#include <elf.h>
#endif /* __KERNEL__ */
#endif /* ELFCLASS32 */
#ifndef ELFCLASSM
#define ELFCLASSM ELF_CLASS
#endif
#ifndef ElfW
# if ELFCLASSM == ELFCLASS32
# define ElfW(x) Elf32_ ## x
# define ELFW(x) ELF32_ ## x
# else
# define ElfW(x) Elf64_ ## x
# define ELFW(x) ELF64_ ## x
# endif
#endif
/* Format of data in the kallsyms section.
* Most of the fields are small numbers but the total size and all
* offsets can be large so use the 32/64 bit types for these fields.
*
* Do not use sizeof() on these structures, modutils may be using extra
* fields. Instead use the size fields in the header to access the
* other bits of data.
*/
struct kallsyms_header {
int size; /* Size of this header */
ElfW(Word) total_size; /* Total size of kallsyms data */
int sections; /* Number of section entries */
ElfW(Off) section_off; /* Offset to first section entry */
int section_size; /* Size of one section entry */
int symbols; /* Number of symbol entries */
ElfW(Off) symbol_off; /* Offset to first symbol entry */
int symbol_size; /* Size of one symbol entry */
ElfW(Off) string_off; /* Offset to first string */
ElfW(Addr) start; /* Start address of first section */
ElfW(Addr) end; /* End address of last section */
};
struct kallsyms_section {
ElfW(Addr) start; /* Start address of section */
ElfW(Word) size; /* Size of this section */
ElfW(Off) name_off; /* Offset to section name */
ElfW(Word) flags; /* Flags from section */
};
struct kallsyms_symbol {
ElfW(Off) section_off; /* Offset to section that owns this symbol */
ElfW(Addr) symbol_addr; /* Address of symbol */
ElfW(Off) name_off; /* Offset to symbol name */
};
#define KALLSYMS_SEC_NAME "__kallsyms"
#define KALLSYMS_IDX 2 /* obj_kallsyms creates kallsyms as section 2 */
#define kallsyms_next_sec(h,s) \
((s) = (struct kallsyms_section *)((char *)(s) + (h)->section_size))
#define kallsyms_next_sym(h,s) \
((s) = (struct kallsyms_symbol *)((char *)(s) + (h)->symbol_size))
#ifdef CONFIG_KALLSYMS #ifdef CONFIG_KALLSYMS
/* Lookup an address. modname is set to NULL if it's in the kernel. */
const char *kallsyms_lookup(unsigned long addr,
unsigned long *symbolsize,
unsigned long *offset,
char **modname);
int kallsyms_symbol_to_address( /* Replace "%s" in format with address, if found */
const char *name, /* Name to lookup */ extern void __print_symbol(const char *fmt, unsigned long address);
unsigned long *token, /* Which module to start with */
const char **mod_name, /* Set to module name or "kernel" */
unsigned long *mod_start, /* Set to start address of module */
unsigned long *mod_end, /* Set to end address of module */
const char **sec_name, /* Set to section name */
unsigned long *sec_start, /* Set to start address of section */
unsigned long *sec_end, /* Set to end address of section */
const char **sym_name, /* Set to full symbol name */
unsigned long *sym_start, /* Set to start address of symbol */
unsigned long *sym_end /* Set to end address of symbol */
);
int kallsyms_address_to_symbol( #else /* !CONFIG_KALLSYMS */
unsigned long address, /* Address to lookup */
const char **mod_name, /* Set to module name */
unsigned long *mod_start, /* Set to start address of module */
unsigned long *mod_end, /* Set to end address of module */
const char **sec_name, /* Set to section name */
unsigned long *sec_start, /* Set to start address of section */
unsigned long *sec_end, /* Set to end address of section */
const char **sym_name, /* Set to full symbol name */
unsigned long *sym_start, /* Set to start address of symbol */
unsigned long *sym_end /* Set to end address of symbol */
);
int kallsyms_sections(void *token, static inline const char *kallsyms_lookup(unsigned long addr,
int (*callback)(void *, /* token */ unsigned long *symbolsize,
const char *, /* module name */ unsigned long *offset,
const char *, /* section name */ char **modname)
ElfW(Addr), /* Section start */ {
ElfW(Addr), /* Section end */ return NULL;
ElfW(Word) /* Section flags */ }
)
);
#else /* Stupid that this does nothing, but I didn't create this mess. */
#define __print_symbol(fmt, addr)
#endif /*CONFIG_KALLSYMS*/
static inline int kallsyms_address_to_symbol( /* This macro allows us to keep printk typechecking */
unsigned long address, /* Address to lookup */ static void __check_printsym_format(const char *fmt, ...)
const char **mod_name, /* Set to module name */ __attribute__((format(printf,1,2)));
unsigned long *mod_start, /* Set to start address of module */ static inline void __check_printsym_format(const char *fmt, ...)
unsigned long *mod_end, /* Set to end address of module */
const char **sec_name, /* Set to section name */
unsigned long *sec_start, /* Set to start address of section */
unsigned long *sec_end, /* Set to end address of section */
const char **sym_name, /* Set to full symbol name */
unsigned long *sym_start, /* Set to start address of symbol */
unsigned long *sym_end /* Set to end address of symbol */
)
{ {
return -ESRCH;
} }
#endif #define print_symbol(fmt, addr) \
do { \
__check_printsym_format(fmt, ""); \
__print_symbol(fmt, addr); \
} while(0)
#endif /* kallsyms.h */ #endif /*_LINUX_KALLSYMS_H*/
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/cache.h> #include <linux/cache.h>
#include <linux/kmod.h> #include <linux/kmod.h>
#include <linux/elf.h>
#include <asm/module.h> #include <asm/module.h>
#include <asm/uaccess.h> /* For struct exception_table_entry */ #include <asm/uaccess.h> /* For struct exception_table_entry */
...@@ -29,7 +31,6 @@ ...@@ -29,7 +31,6 @@
#define MODULE_GENERIC_TABLE(gtype,name) #define MODULE_GENERIC_TABLE(gtype,name)
#define MODULE_DEVICE_TABLE(type,name) #define MODULE_DEVICE_TABLE(type,name)
#define MODULE_PARM_DESC(var,desc) #define MODULE_PARM_DESC(var,desc)
#define print_symbol(format, addr)
#define print_modules() #define print_modules()
#define MODULE_NAME_LEN (64 - sizeof(unsigned long)) #define MODULE_NAME_LEN (64 - sizeof(unsigned long))
...@@ -137,6 +138,13 @@ struct module ...@@ -137,6 +138,13 @@ struct module
void (*exit)(void); void (*exit)(void);
#endif #endif
#ifdef CONFIG_KALLSYMS
/* We keep the symbol and string tables for kallsyms. */
Elf_Sym *symtab;
unsigned long num_syms;
char *strtab;
#endif
/* The command line arguments (may be mangled). People like /* The command line arguments (may be mangled). People like
keeping pointers to this stuff */ keeping pointers to this stuff */
char args[0]; char args[0];
...@@ -211,6 +219,12 @@ do { \ ...@@ -211,6 +219,12 @@ do { \
} \ } \
} while(0) } while(0)
/* For kallsyms to ask for address resolution. NULL means not found. */
const char *module_address_lookup(unsigned long addr,
unsigned long *symbolsize,
unsigned long *offset,
char **modname);
#else /* !CONFIG_MODULES... */ #else /* !CONFIG_MODULES... */
#define EXPORT_SYMBOL(sym) #define EXPORT_SYMBOL(sym)
#define EXPORT_SYMBOL_GPL(sym) #define EXPORT_SYMBOL_GPL(sym)
...@@ -227,6 +241,15 @@ do { \ ...@@ -227,6 +241,15 @@ do { \
#define module_name(mod) "kernel" #define module_name(mod) "kernel"
#define __unsafe(mod) #define __unsafe(mod)
/* For kallsyms to ask for address resolution. NULL means not found. */
static inline const char *module_address_lookup(unsigned long addr,
unsigned long *symbolsize,
unsigned long *offset,
char **modname)
{
return NULL;
}
#endif /* CONFIG_MODULES */ #endif /* CONFIG_MODULES */
/* For archs to search exception tables */ /* For archs to search exception tables */
......
This diff is collapsed.
...@@ -898,6 +898,11 @@ static struct module *load_module(void *umod, ...@@ -898,6 +898,11 @@ static struct module *load_module(void *umod,
DEBUGP("Exception table found in section %u\n", i); DEBUGP("Exception table found in section %u\n", i);
exindex = i; exindex = i;
} }
#ifdef CONFIG_KALLSYMS
/* symbol and string tables for decoding later. */
if (sechdrs[i].sh_type == SHT_SYMTAB || i == hdr->e_shstrndx)
sechdrs[i].sh_flags |= SHF_ALLOC;
#endif
#ifndef CONFIG_MODULE_UNLOAD #ifndef CONFIG_MODULE_UNLOAD
/* Don't load .exit sections */ /* Don't load .exit sections */
if (strstr(secstrings+sechdrs[i].sh_name, ".exit")) if (strstr(secstrings+sechdrs[i].sh_name, ".exit"))
...@@ -1026,6 +1031,11 @@ static struct module *load_module(void *umod, ...@@ -1026,6 +1031,11 @@ static struct module *load_module(void *umod,
goto cleanup; goto cleanup;
} }
#ifdef CONFIG_KALLSYMS
mod->symtab = (void *)sechdrs[symindex].sh_offset;
mod->num_syms = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
mod->strtab = (void *)sechdrs[strindex].sh_offset;
#endif
err = module_finalize(hdr, sechdrs, mod); err = module_finalize(hdr, sechdrs, mod);
if (err < 0) if (err < 0)
goto cleanup; goto cleanup;
...@@ -1141,9 +1151,82 @@ sys_init_module(void *umod, ...@@ -1141,9 +1151,82 @@ sys_init_module(void *umod,
return 0; return 0;
} }
/* Called by the /proc file system to return a current list of #ifdef CONFIG_KALLSYMS
modules. Al Viro came up with this interface as an "improvement". static inline int inside_init(struct module *mod, unsigned long addr)
God save us from any more such interface improvements. */ {
if (mod->module_init
&& (unsigned long)mod->module_init <= addr
&& (unsigned long)mod->module_init + mod->init_size > addr)
return 1;
return 0;
}
static inline int inside_core(struct module *mod, unsigned long addr)
{
if ((unsigned long)mod->module_core <= addr
&& (unsigned long)mod->module_core + mod->core_size > addr)
return 1;
return 0;
}
static const char *get_ksymbol(struct module *mod,
unsigned long addr,
unsigned long *size,
unsigned long *offset)
{
unsigned int i, next = 0, best = 0;
/* Scan for closest preceeding symbol, and next symbol. (ELF
starts real symbols at 1). */
for (i = 1; i < mod->num_syms; i++) {
if (mod->symtab[i].st_shndx == SHN_UNDEF)
continue;
if (mod->symtab[i].st_value <= addr
&& mod->symtab[i].st_value > mod->symtab[best].st_value)
best = i;
if (mod->symtab[i].st_value > addr
&& mod->symtab[i].st_value < mod->symtab[next].st_value)
next = i;
}
if (!best)
return NULL;
if (!next) {
/* Last symbol? It ends at the end of the module then. */
if (inside_core(mod, addr))
*size = mod->module_core+mod->core_size - (void*)addr;
else
*size = mod->module_init+mod->init_size - (void*)addr;
} else
*size = mod->symtab[next].st_value - addr;
*offset = addr - mod->symtab[best].st_value;
return mod->strtab + mod->symtab[best].st_name;
}
/* For kallsyms to ask for address resolution. NULL means not found.
We don't lock, as this is used for oops resolution and races are a
lesser concern. */
const char *module_address_lookup(unsigned long addr,
unsigned long *size,
unsigned long *offset,
char **modname)
{
struct module *mod;
list_for_each_entry(mod, &modules, list) {
if (inside_core(mod, addr) || inside_init(mod, addr)) {
*modname = mod->name;
return get_ksymbol(mod, addr, size, offset);
}
}
return NULL;
}
#endif /* CONFIG_KALLSYMS */
/* Called by the /proc file system to return a list of modules. */
static void *m_start(struct seq_file *m, loff_t *pos) static void *m_start(struct seq_file *m, loff_t *pos)
{ {
struct list_head *i; struct list_head *i;
......
...@@ -105,6 +105,7 @@ ...@@ -105,6 +105,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kmod.h> #include <linux/kmod.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kallsyms.h>
#if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO) #if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO)
#include <linux/wireless.h> /* Note : will define WIRELESS_EXT */ #include <linux/wireless.h> /* Note : will define WIRELESS_EXT */
#include <net/iw_handler.h> #include <net/iw_handler.h>
......
#! /bin/sh
# Written by Rusty Russell <rusty@rustcorp.com.au> 2002.
if [ $# -ne 2 ]; then
echo Usage: kallsyms vmlinux objfile >&2
echo Adds a .kallsyms section containing symbol info.
exit 1
fi
set -e
# Clean up on exit.
trap "rm -f kallsyms.map kallsyms.c $2" 0
# Takes nm output from $1, produces a .c file on standard output.
encode_symbols()
{
# First take addresses.
echo "unsigned long kallsyms_addresses[] = {"
sed 's/^[ ]*\([A-Fa-f0-9]*\).*/0x\1UL,/' < $1
echo "};"
# Now output size.
echo "unsigned long kallsyms_num_syms = `wc -l < $1`;"
# Now output names.
echo "char kallsyms_names[] = ";
sed 's/^[ ]*[A-Fa-f0-9]*[ ]*.[ ]\(.*\)/"\1\\0"/' < $1
echo ";"
}
# FIXME: Use System.map as input, and regenerate each time in Makefile.
$NM $1 | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > kallsyms.map
encode_symbols kallsyms.map > kallsyms.c
$CC $CFLAGS -c -o $2 kallsyms.c
trap "rm -f kallsyms.map kallsyms.c" 0
exit 0
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment