Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 38001
b: refs/heads/master
c: ffc5089
h: refs/heads/master
i:
  37999: 32832e8
v: v3
  • Loading branch information
Franck Bui-Huu authored and Linus Torvalds committed Oct 3, 2006
1 parent 03dff4c commit ca0535a
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 45 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 339b0c0813a257893fa84be999b9b85a50846dd8
refs/heads/master: ffc5089196446c08d9a005cf0dd7cab18d119606
11 changes: 11 additions & 0 deletions trunk/include/linux/kallsyms.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
/* Lookup the address for a symbol. Returns 0 if not found. */
unsigned long kallsyms_lookup_name(const char *name);

extern int kallsyms_lookup_size_offset(unsigned long addr,
unsigned long *symbolsize,
unsigned long *offset);

/* Lookup an address. modname is set to NULL if it's in the kernel. */
const char *kallsyms_lookup(unsigned long addr,
unsigned long *symbolsize,
Expand All @@ -28,6 +32,13 @@ static inline unsigned long kallsyms_lookup_name(const char *name)
return 0;
}

static inline int kallsyms_lookup_size_offset(unsigned long addr,
unsigned long *symbolsize,
unsigned long *offset)
{
return 0;
}

static inline const char *kallsyms_lookup(unsigned long addr,
unsigned long *symbolsize,
unsigned long *offset,
Expand Down
123 changes: 80 additions & 43 deletions trunk/kernel/kallsyms.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ static inline int is_kernel(unsigned long addr)
return in_gate_area_no_task(addr);
}

static int is_ksym_addr(unsigned long addr)
{
if (all_var)
return is_kernel(addr);

return is_kernel_text(addr) || is_kernel_inittext(addr) ||
is_kernel_extratext(addr);
}

/* expand a compressed symbol data into the resulting uncompressed string,
given the offset to where the symbol is in the compressed stream */
static unsigned int kallsyms_expand_symbol(unsigned int off, char *result)
Expand Down Expand Up @@ -155,6 +164,73 @@ unsigned long kallsyms_lookup_name(const char *name)
return module_kallsyms_lookup_name(name);
}

static unsigned long get_symbol_pos(unsigned long addr,
unsigned long *symbolsize,
unsigned long *offset)
{
unsigned long symbol_start = 0, symbol_end = 0;
unsigned long i, low, high, mid;

/* This kernel should never had been booted. */
BUG_ON(!kallsyms_addresses);

/* do a binary search on the sorted kallsyms_addresses array */
low = 0;
high = kallsyms_num_syms;

while (high - low > 1) {
mid = (low + high) / 2;
if (kallsyms_addresses[mid] <= addr)
low = mid;
else
high = mid;
}

/*
* search for the first aliased symbol. Aliased
* symbols are symbols with the same address
*/
while (low && kallsyms_addresses[low-1] == kallsyms_addresses[low])
--low;

symbol_start = kallsyms_addresses[low];

/* Search for next non-aliased symbol */
for (i = low + 1; i < kallsyms_num_syms; i++) {
if (kallsyms_addresses[i] > symbol_start) {
symbol_end = kallsyms_addresses[i];
break;
}
}

/* if we found no next symbol, we use the end of the section */
if (!symbol_end) {
if (is_kernel_inittext(addr))
symbol_end = (unsigned long)_einittext;
else if (all_var)
symbol_end = (unsigned long)_end;
else
symbol_end = (unsigned long)_etext;
}

*symbolsize = symbol_end - symbol_start;
*offset = addr - symbol_start;

return low;
}

/*
* Lookup an address but don't bother to find any names.
*/
int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize,
unsigned long *offset)
{
if (is_ksym_addr(addr))
return !!get_symbol_pos(addr, symbolsize, offset);

return !!module_address_lookup(addr, symbolsize, offset, NULL);
}

/*
* Lookup an address
* - modname is set to NULL if it's in the kernel
Expand All @@ -167,57 +243,18 @@ const char *kallsyms_lookup(unsigned long addr,
unsigned long *offset,
char **modname, char *namebuf)
{
unsigned long i, low, high, mid;
const char *msym;

/* This kernel should never had been booted. */
BUG_ON(!kallsyms_addresses);

namebuf[KSYM_NAME_LEN] = 0;
namebuf[0] = 0;

if ((all_var && is_kernel(addr)) ||
(!all_var && (is_kernel_text(addr) || is_kernel_inittext(addr) ||
is_kernel_extratext(addr)))) {
unsigned long symbol_end = 0;

/* do a binary search on the sorted kallsyms_addresses array */
low = 0;
high = kallsyms_num_syms;

while (high-low > 1) {
mid = (low + high) / 2;
if (kallsyms_addresses[mid] <= addr) low = mid;
else high = mid;
}

/* search for the first aliased symbol. Aliased symbols are
symbols with the same address */
while (low && kallsyms_addresses[low - 1] == kallsyms_addresses[low])
--low;
if (is_ksym_addr(addr)) {
unsigned long pos;

pos = get_symbol_pos(addr, symbolsize, offset);
/* Grab name */
kallsyms_expand_symbol(get_symbol_offset(low), namebuf);

/* Search for next non-aliased symbol */
for (i = low + 1; i < kallsyms_num_syms; i++) {
if (kallsyms_addresses[i] > kallsyms_addresses[low]) {
symbol_end = kallsyms_addresses[i];
break;
}
}

/* if we found no next symbol, we use the end of the section */
if (!symbol_end) {
if (is_kernel_inittext(addr))
symbol_end = (unsigned long)_einittext;
else
symbol_end = all_var ? (unsigned long)_end : (unsigned long)_etext;
}

*symbolsize = symbol_end - kallsyms_addresses[low];
kallsyms_expand_symbol(get_symbol_offset(pos), namebuf);
*modname = NULL;
*offset = addr - kallsyms_addresses[low];
return namebuf;
}

Expand Down
3 changes: 2 additions & 1 deletion trunk/kernel/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -2040,7 +2040,8 @@ const char *module_address_lookup(unsigned long addr,
list_for_each_entry(mod, &modules, list) {
if (within(addr, mod->module_init, mod->init_size)
|| within(addr, mod->module_core, mod->core_size)) {
*modname = mod->name;
if (modname)
*modname = mod->name;
return get_ksymbol(mod, addr, size, offset);
}
}
Expand Down

0 comments on commit ca0535a

Please sign in to comment.