Merge branch 'tracing-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[safe/jmp/linux-2.6] / kernel / kallsyms.c
index f1ea6f6..7b8b0f2 100644 (file)
 
 /* These will be re-linked against their real values during the second link stage */
 extern const unsigned long kallsyms_addresses[] __attribute__((weak));
-extern const unsigned long kallsyms_num_syms __attribute__((weak));
 extern const u8 kallsyms_names[] __attribute__((weak));
 
+/* tell the compiler that the count isn't in the small data section if the arch
+ * has one (eg: FRV)
+ */
+extern const unsigned long kallsyms_num_syms
+__attribute__((weak, section(".rodata")));
+
 extern const u8 kallsyms_token_table[] __attribute__((weak));
 extern const u16 kallsyms_token_index[] __attribute__((weak));
 
@@ -48,14 +53,6 @@ static inline int is_kernel_inittext(unsigned long addr)
        return 0;
 }
 
-static inline int is_kernel_extratext(unsigned long addr)
-{
-       if (addr >= (unsigned long)_sextratext
-           && addr <= (unsigned long)_eextratext)
-               return 1;
-       return 0;
-}
-
 static inline int is_kernel_text(unsigned long addr)
 {
        if (addr >= (unsigned long)_stext && addr <= (unsigned long)_etext)
@@ -75,8 +72,7 @@ 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);
+       return is_kernel_text(addr) || is_kernel_inittext(addr);
 }
 
 /* expand a compressed symbol data into the resulting uncompressed string,
@@ -152,7 +148,7 @@ static unsigned int get_symbol_offset(unsigned long pos)
 /* Lookup the address for this symbol. Returns 0 if not found. */
 unsigned long kallsyms_lookup_name(const char *name)
 {
-       char namebuf[KSYM_NAME_LEN+1];
+       char namebuf[KSYM_NAME_LEN];
        unsigned long i;
        unsigned int off;
 
@@ -180,7 +176,7 @@ static unsigned long get_symbol_pos(unsigned long addr,
        high = kallsyms_num_syms;
 
        while (high - low > 1) {
-               mid = (low + high) / 2;
+               mid = low + (high - low) / 2;
                if (kallsyms_addresses[mid] <= addr)
                        low = mid;
                else
@@ -214,8 +210,10 @@ static unsigned long get_symbol_pos(unsigned long addr,
                        symbol_end = (unsigned long)_etext;
        }
 
-       *symbolsize = symbol_end - symbol_start;
-       *offset = addr - symbol_start;
+       if (symbolsize)
+               *symbolsize = symbol_end - symbol_start;
+       if (offset)
+               *offset = addr - symbol_start;
 
        return low;
 }
@@ -226,10 +224,11 @@ static unsigned long get_symbol_pos(unsigned long addr,
 int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize,
                                unsigned long *offset)
 {
+       char namebuf[KSYM_NAME_LEN];
        if (is_ksym_addr(addr))
                return !!get_symbol_pos(addr, symbolsize, offset);
 
-       return !!module_address_lookup(addr, symbolsize, offset, NULL);
+       return !!module_address_lookup(addr, symbolsize, offset, NULL, namebuf);
 }
 
 /*
@@ -244,9 +243,7 @@ const char *kallsyms_lookup(unsigned long addr,
                            unsigned long *offset,
                            char **modname, char *namebuf)
 {
-       const char *msym;
-
-       namebuf[KSYM_NAME_LEN] = 0;
+       namebuf[KSYM_NAME_LEN - 1] = 0;
        namebuf[0] = 0;
 
        if (is_ksym_addr(addr)) {
@@ -255,16 +252,50 @@ const char *kallsyms_lookup(unsigned long addr,
                pos = get_symbol_pos(addr, symbolsize, offset);
                /* Grab name */
                kallsyms_expand_symbol(get_symbol_offset(pos), namebuf);
-               *modname = NULL;
+               if (modname)
+                       *modname = NULL;
                return namebuf;
        }
 
        /* see if it's in a module */
-       msym = module_address_lookup(addr, symbolsize, offset, modname);
-       if (msym)
-               return strncpy(namebuf, msym, KSYM_NAME_LEN);
+       return module_address_lookup(addr, symbolsize, offset, modname,
+                                    namebuf);
+}
 
-       return NULL;
+int lookup_symbol_name(unsigned long addr, char *symname)
+{
+       symname[0] = '\0';
+       symname[KSYM_NAME_LEN - 1] = '\0';
+
+       if (is_ksym_addr(addr)) {
+               unsigned long pos;
+
+               pos = get_symbol_pos(addr, NULL, NULL);
+               /* Grab name */
+               kallsyms_expand_symbol(get_symbol_offset(pos), symname);
+               return 0;
+       }
+       /* see if it's in a module */
+       return lookup_module_symbol_name(addr, symname);
+}
+
+int lookup_symbol_attrs(unsigned long addr, unsigned long *size,
+                       unsigned long *offset, char *modname, char *name)
+{
+       name[0] = '\0';
+       name[KSYM_NAME_LEN - 1] = '\0';
+
+       if (is_ksym_addr(addr)) {
+               unsigned long pos;
+
+               pos = get_symbol_pos(addr, size, offset);
+               /* Grab name */
+               kallsyms_expand_symbol(get_symbol_offset(pos), name);
+               modname[0] = '\0';
+               return 0;
+       }
+       /* see if it's in a module */
+       return lookup_module_symbol_attrs(addr, size, offset, modname, name);
 }
 
 /* Look up a kernel symbol and return it in a text buffer. */
@@ -273,18 +304,24 @@ int sprint_symbol(char *buffer, unsigned long address)
        char *modname;
        const char *name;
        unsigned long offset, size;
-       char namebuf[KSYM_NAME_LEN+1];
+       int len;
 
-       name = kallsyms_lookup(address, &size, &offset, &modname, namebuf);
+       name = kallsyms_lookup(address, &size, &offset, &modname, buffer);
        if (!name)
                return sprintf(buffer, "0x%lx", address);
-       else {
-               if (modname)
-                       return sprintf(buffer, "%s+%#lx/%#lx [%s]", name, offset,
-                               size, modname);
-               else
-                       return sprintf(buffer, "%s+%#lx/%#lx", name, offset, size);
-       }
+
+       if (name != buffer)
+               strcpy(buffer, name);
+       len = strlen(buffer);
+       buffer += len;
+
+       if (modname)
+               len += sprintf(buffer, "+%#lx/%#lx [%s]",
+                                               offset, size, modname);
+       else
+               len += sprintf(buffer, "+%#lx/%#lx", offset, size);
+
+       return len;
 }
 
 /* Look up a kernel symbol and print it to the kernel messages. */
@@ -304,8 +341,8 @@ struct kallsym_iter
        unsigned long value;
        unsigned int nameoff; /* If iterating in core kernel symbols */
        char type;
-       char name[KSYM_NAME_LEN+1];
-       char module_name[MODULE_NAME_LEN + 1];
+       char name[KSYM_NAME_LEN];
+       char module_name[MODULE_NAME_LEN];
        int exported;
 };
 
@@ -432,27 +469,16 @@ static int kallsyms_open(struct inode *inode, struct file *file)
        return ret;
 }
 
-static int kallsyms_release(struct inode *inode, struct file *file)
-{
-       struct seq_file *m = (struct seq_file *)file->private_data;
-       kfree(m->private);
-       return seq_release(inode, file);
-}
-
 static const struct file_operations kallsyms_operations = {
        .open = kallsyms_open,
        .read = seq_read,
        .llseek = seq_lseek,
-       .release = kallsyms_release,
+       .release = seq_release_private,
 };
 
 static int __init kallsyms_init(void)
 {
-       struct proc_dir_entry *entry;
-
-       entry = create_proc_entry("kallsyms", 0444, NULL);
-       if (entry)
-               entry->proc_fops = &kallsyms_operations;
+       proc_create("kallsyms", 0444, NULL, &kallsyms_operations);
        return 0;
 }
 __initcall(kallsyms_init);