Commit eac08288 authored by Charles Jacobsen's avatar Charles Jacobsen Committed by Vikram Narayanan

stack-trace: Fix module loader to not 'erase' init symbols.

For normal module loads, __init code is freed, so it makes sense
we update the symbol table to remove those symbols. But for
LCDs, we want them to hang around.
parent d8f3540a
......@@ -808,4 +808,9 @@ int do_sys_delete_module(const char *name, unsigned int flags, int for_lcd);
int do_sys_init_module(void __user *umod, unsigned long len,
const char __user *uargs, int for_lcd);
const char *get_ksymbol(struct module *mod,
unsigned long addr,
unsigned long *size,
unsigned long *offset);
#endif /* _LINUX_MODULE_H */
......@@ -3432,6 +3432,11 @@ static noinline int do_init_module(struct module *mod, int for_lcd)
#ifdef CONFIG_KALLSYMS
/* Switch to core kallsyms now init is done: kallsyms may be walking! */
rcu_assign_pointer(mod->kallsyms, &mod->core_kallsyms);
if (!for_lcd) {
mod->num_symtab = mod->core_num_syms;
mod->symtab = mod->core_symtab;
mod->strtab = mod->core_strtab;
}
#endif
module_enable_ro(mod, true);
mod_tree_remove_init(mod);
......@@ -4054,6 +4059,7 @@ const char *get_ksymbol(struct module *mod,
*offset = addr - kallsyms->symtab[best].st_value;
return symname(kallsyms, best);
}
EXPORT_SYMBOL(get_ksymbol);
/* For kallsyms to ask for address resolution. NULL means not found. Careful
* not to lock to avoid deadlock on oopses, simply disable preemption. */
......
......@@ -47,64 +47,6 @@ fail1:
return ret;
}
static inline const char *adjust_addr(const char *addr, struct module *mod,
hva_t new_m_core_addr)
{
/* unsigned long offset; */
/*
* Compute offset into module's core
*/
return addr;
/* offset = ((unsigned long)addr) - ((unsigned long)mod->module_core); */
/* /\* */
/* * Add to new core location */
/* *\/ */
/* return (const char *)(hva_val(new_m_core_addr) + offset); */
}
static const char *get_ksymbol(struct module *mod,
hva_t addr,
unsigned long *size,
unsigned long *offset)
{
unsigned int i, best = 0;
unsigned long nextval;
/* At worse, next value is at end of module */
if (within_module_init(hva_val(addr), mod))
nextval = (unsigned long)mod->module_init+mod->init_text_size;
else
nextval = (unsigned long)mod->module_core+mod->core_text_size;
/* Scan for closest preceding symbol, and next symbol. (ELF
starts real symbols at 1). */
for (i = 1; i < mod->num_symtab; i++) {
if (mod->symtab[i].st_shndx == SHN_UNDEF)
continue;
/* We ignore unnamed symbols: they're uninformative
* and inserted at a whim. */
if (mod->symtab[i].st_value <= hva_val(addr)
&& mod->symtab[i].st_value > mod->symtab[best].st_value &&
*(mod->strtab + mod->symtab[i].st_name) != '\0')
best = i;
if (mod->symtab[i].st_value > hva_val(addr)
&& mod->symtab[i].st_value < nextval
&& *(mod->strtab + mod->symtab[i].st_name) != '\0')
nextval = mod->symtab[i].st_value;
}
if (!best)
return NULL;
if (size)
*size = nextval - mod->symtab[best].st_value;
if (offset)
*offset = hva_val(addr) - mod->symtab[best].st_value;
return mod->strtab + mod->symtab[best].st_name;
}
static inline int in_module(struct module *module, hva_t hva)
{
/*
......@@ -125,7 +67,13 @@ __lcd_sprint_symbol(char *buffer, hva_t hva, struct module *extra_module)
unsigned long len;
/*
* This code is motivated by kernel/kallsyms.c:__sprint_symbol
*
* According to doc in kernel/kallsyms.c:sprint_backtrace,
* we need to subtract 1 from the address to handle noreturn gcc
* optimizations.
*/
hva = __hva(hva_val(hva) - 1);
if (extra_module && in_module(extra_module, hva)) {
/*
* Symbol lands in our special LCD .ko image; look up
......@@ -134,7 +82,7 @@ __lcd_sprint_symbol(char *buffer, hva_t hva, struct module *extra_module)
* XXX: Danger: This is for debug only. The struct module
* is mapped inside an LCD which could mess with it.
*/
sym_name = get_ksymbol(extra_module, hva,
sym_name = get_ksymbol(extra_module, hva_val(hva),
&size, &offset);
if (!sym_name)
return 0;
......@@ -152,11 +100,7 @@ __lcd_sprint_symbol(char *buffer, hva_t hva, struct module *extra_module)
strcpy(buffer, sym_name);
}
/*
* According to doc in kernel/kallsyms.c:sprint_backtrace,
* we need to add 1 to the address to handle noreturn gcc
* optimizations.
*
* Since we always use this code for backtrace, always inc by 1
* Since we subtracted 1 from the address, add 1 to the offset
*/
offset += 1;
len = strlen(buffer);
......
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