linux/kernel/kallsyms.c
<<
>>
Prefs
   1/*
   2 * kallsyms.c: in-kernel printing of symbolic oopses and stack traces.
   3 *
   4 * Rewritten and vastly simplified by Rusty Russell for in-kernel
   5 * module loader:
   6 *   Copyright 2002 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
   7 *
   8 * ChangeLog:
   9 *
  10 * (25/Aug/2004) Paulo Marques <pmarques@grupopie.com>
  11 *      Changed the compression method from stem compression to "table lookup"
  12 *      compression (see scripts/kallsyms.c for a more complete description)
  13 */
  14#include <linux/kallsyms.h>
  15#include <linux/init.h>
  16#include <linux/seq_file.h>
  17#include <linux/fs.h>
  18#include <linux/kdb.h>
  19#include <linux/err.h>
  20#include <linux/proc_fs.h>
  21#include <linux/sched.h>        /* for cond_resched */
  22#include <linux/ctype.h>
  23#include <linux/slab.h>
  24#include <linux/filter.h>
  25#include <linux/ftrace.h>
  26#include <linux/compiler.h>
  27
  28/*
  29 * These will be re-linked against their real values
  30 * during the second link stage.
  31 */
  32extern const unsigned long kallsyms_addresses[] __weak;
  33extern const int kallsyms_offsets[] __weak;
  34extern const u8 kallsyms_names[] __weak;
  35
  36/*
  37 * Tell the compiler that the count isn't in the small data section if the arch
  38 * has one (eg: FRV).
  39 */
  40extern const unsigned long kallsyms_num_syms
  41__attribute__((weak, section(".rodata")));
  42
  43extern const unsigned long kallsyms_relative_base
  44__attribute__((weak, section(".rodata")));
  45
  46extern const u8 kallsyms_token_table[] __weak;
  47extern const u16 kallsyms_token_index[] __weak;
  48
  49extern const unsigned long kallsyms_markers[] __weak;
  50
  51/*
  52 * Expand a compressed symbol data into the resulting uncompressed string,
  53 * if uncompressed string is too long (>= maxlen), it will be truncated,
  54 * given the offset to where the symbol is in the compressed stream.
  55 */
  56static unsigned int kallsyms_expand_symbol(unsigned int off,
  57                                           char *result, size_t maxlen)
  58{
  59        int len, skipped_first = 0;
  60        const u8 *tptr, *data;
  61
  62        /* Get the compressed symbol length from the first symbol byte. */
  63        data = &kallsyms_names[off];
  64        len = *data;
  65        data++;
  66
  67        /*
  68         * Update the offset to return the offset for the next symbol on
  69         * the compressed stream.
  70         */
  71        off += len + 1;
  72
  73        /*
  74         * For every byte on the compressed symbol data, copy the table
  75         * entry for that byte.
  76         */
  77        while (len) {
  78                tptr = &kallsyms_token_table[kallsyms_token_index[*data]];
  79                data++;
  80                len--;
  81
  82                while (*tptr) {
  83                        if (skipped_first) {
  84                                if (maxlen <= 1)
  85                                        goto tail;
  86                                *result = *tptr;
  87                                result++;
  88                                maxlen--;
  89                        } else
  90                                skipped_first = 1;
  91                        tptr++;
  92                }
  93        }
  94
  95tail:
  96        if (maxlen)
  97                *result = '\0';
  98
  99        /* Return to offset to the next symbol. */
 100        return off;
 101}
 102
 103/*
 104 * Get symbol type information. This is encoded as a single char at the
 105 * beginning of the symbol name.
 106 */
 107static char kallsyms_get_symbol_type(unsigned int off)
 108{
 109        /*
 110         * Get just the first code, look it up in the token table,
 111         * and return the first char from this token.
 112         */
 113        return kallsyms_token_table[kallsyms_token_index[kallsyms_names[off + 1]]];
 114}
 115
 116
 117/*
 118 * Find the offset on the compressed stream given and index in the
 119 * kallsyms array.
 120 */
 121static unsigned int get_symbol_offset(unsigned long pos)
 122{
 123        const u8 *name;
 124        int i;
 125
 126        /*
 127         * Use the closest marker we have. We have markers every 256 positions,
 128         * so that should be close enough.
 129         */
 130        name = &kallsyms_names[kallsyms_markers[pos >> 8]];
 131
 132        /*
 133         * Sequentially scan all the symbols up to the point we're searching
 134         * for. Every symbol is stored in a [<len>][<len> bytes of data] format,
 135         * so we just need to add the len to the current pointer for every
 136         * symbol we wish to skip.
 137         */
 138        for (i = 0; i < (pos & 0xFF); i++)
 139                name = name + (*name) + 1;
 140
 141        return name - kallsyms_names;
 142}
 143
 144static unsigned long kallsyms_sym_address(int idx)
 145{
 146        if (!IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE))
 147                return kallsyms_addresses[idx];
 148
 149        /* values are unsigned offsets if --absolute-percpu is not in effect */
 150        if (!IS_ENABLED(CONFIG_KALLSYMS_ABSOLUTE_PERCPU))
 151                return kallsyms_relative_base + (u32)kallsyms_offsets[idx];
 152
 153        /* ...otherwise, positive offsets are absolute values */
 154        if (kallsyms_offsets[idx] >= 0)
 155                return kallsyms_offsets[idx];
 156
 157        /* ...and negative offsets are relative to kallsyms_relative_base - 1 */
 158        return kallsyms_relative_base - 1 - kallsyms_offsets[idx];
 159}
 160
 161/* Lookup the address for this symbol. Returns 0 if not found. */
 162unsigned long kallsyms_lookup_name(const char *name)
 163{
 164        char namebuf[KSYM_NAME_LEN];
 165        unsigned long i;
 166        unsigned int off;
 167
 168        for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
 169                off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
 170
 171                if (strcmp(namebuf, name) == 0)
 172                        return kallsyms_sym_address(i);
 173        }
 174        return module_kallsyms_lookup_name(name);
 175}
 176EXPORT_SYMBOL_GPL(kallsyms_lookup_name);
 177
 178int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
 179                                      unsigned long),
 180                            void *data)
 181{
 182        char namebuf[KSYM_NAME_LEN];
 183        unsigned long i;
 184        unsigned int off;
 185        int ret;
 186
 187        for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
 188                off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
 189                ret = fn(data, namebuf, NULL, kallsyms_sym_address(i));
 190                if (ret != 0)
 191                        return ret;
 192        }
 193        return module_kallsyms_on_each_symbol(fn, data);
 194}
 195EXPORT_SYMBOL_GPL(kallsyms_on_each_symbol);
 196
 197static unsigned long get_symbol_pos(unsigned long addr,
 198                                    unsigned long *symbolsize,
 199                                    unsigned long *offset)
 200{
 201        unsigned long symbol_start = 0, symbol_end = 0;
 202        unsigned long i, low, high, mid;
 203
 204        /* This kernel should never had been booted. */
 205        if (!IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE))
 206                BUG_ON(!kallsyms_addresses);
 207        else
 208                BUG_ON(!kallsyms_offsets);
 209
 210        /* Do a binary search on the sorted kallsyms_addresses array. */
 211        low = 0;
 212        high = kallsyms_num_syms;
 213
 214        while (high - low > 1) {
 215                mid = low + (high - low) / 2;
 216                if (kallsyms_sym_address(mid) <= addr)
 217                        low = mid;
 218                else
 219                        high = mid;
 220        }
 221
 222        /*
 223         * Search for the first aliased symbol. Aliased
 224         * symbols are symbols with the same address.
 225         */
 226        while (low && kallsyms_sym_address(low-1) == kallsyms_sym_address(low))
 227                --low;
 228
 229        symbol_start = kallsyms_sym_address(low);
 230
 231        /* Search for next non-aliased symbol. */
 232        for (i = low + 1; i < kallsyms_num_syms; i++) {
 233                if (kallsyms_sym_address(i) > symbol_start) {
 234                        symbol_end = kallsyms_sym_address(i);
 235                        break;
 236                }
 237        }
 238
 239        /* If we found no next symbol, we use the end of the section. */
 240        if (!symbol_end) {
 241                if (is_kernel_inittext(addr))
 242                        symbol_end = (unsigned long)_einittext;
 243                else if (IS_ENABLED(CONFIG_KALLSYMS_ALL))
 244                        symbol_end = (unsigned long)_end;
 245                else
 246                        symbol_end = (unsigned long)_etext;
 247        }
 248
 249        if (symbolsize)
 250                *symbolsize = symbol_end - symbol_start;
 251        if (offset)
 252                *offset = addr - symbol_start;
 253
 254        return low;
 255}
 256
 257/*
 258 * Lookup an address but don't bother to find any names.
 259 */
 260int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize,
 261                                unsigned long *offset)
 262{
 263        char namebuf[KSYM_NAME_LEN];
 264
 265        if (is_ksym_addr(addr))
 266                return !!get_symbol_pos(addr, symbolsize, offset);
 267        return !!module_address_lookup(addr, symbolsize, offset, NULL, namebuf) ||
 268               !!__bpf_address_lookup(addr, symbolsize, offset, namebuf);
 269}
 270
 271/*
 272 * Lookup an address
 273 * - modname is set to NULL if it's in the kernel.
 274 * - We guarantee that the returned name is valid until we reschedule even if.
 275 *   It resides in a module.
 276 * - We also guarantee that modname will be valid until rescheduled.
 277 */
 278const char *kallsyms_lookup(unsigned long addr,
 279                            unsigned long *symbolsize,
 280                            unsigned long *offset,
 281                            char **modname, char *namebuf)
 282{
 283        const char *ret;
 284
 285        namebuf[KSYM_NAME_LEN - 1] = 0;
 286        namebuf[0] = 0;
 287
 288        if (is_ksym_addr(addr)) {
 289                unsigned long pos;
 290
 291                pos = get_symbol_pos(addr, symbolsize, offset);
 292                /* Grab name */
 293                kallsyms_expand_symbol(get_symbol_offset(pos),
 294                                       namebuf, KSYM_NAME_LEN);
 295                if (modname)
 296                        *modname = NULL;
 297                return namebuf;
 298        }
 299
 300        /* See if it's in a module or a BPF JITed image. */
 301        ret = module_address_lookup(addr, symbolsize, offset,
 302                                    modname, namebuf);
 303        if (!ret)
 304                ret = bpf_address_lookup(addr, symbolsize,
 305                                         offset, modname, namebuf);
 306
 307        if (!ret)
 308                ret = ftrace_mod_address_lookup(addr, symbolsize,
 309                                                offset, modname, namebuf);
 310        return ret;
 311}
 312
 313int lookup_symbol_name(unsigned long addr, char *symname)
 314{
 315        symname[0] = '\0';
 316        symname[KSYM_NAME_LEN - 1] = '\0';
 317
 318        if (is_ksym_addr(addr)) {
 319                unsigned long pos;
 320
 321                pos = get_symbol_pos(addr, NULL, NULL);
 322                /* Grab name */
 323                kallsyms_expand_symbol(get_symbol_offset(pos),
 324                                       symname, KSYM_NAME_LEN);
 325                return 0;
 326        }
 327        /* See if it's in a module. */
 328        return lookup_module_symbol_name(addr, symname);
 329}
 330
 331int lookup_symbol_attrs(unsigned long addr, unsigned long *size,
 332                        unsigned long *offset, char *modname, char *name)
 333{
 334        name[0] = '\0';
 335        name[KSYM_NAME_LEN - 1] = '\0';
 336
 337        if (is_ksym_addr(addr)) {
 338                unsigned long pos;
 339
 340                pos = get_symbol_pos(addr, size, offset);
 341                /* Grab name */
 342                kallsyms_expand_symbol(get_symbol_offset(pos),
 343                                       name, KSYM_NAME_LEN);
 344                modname[0] = '\0';
 345                return 0;
 346        }
 347        /* See if it's in a module. */
 348        return lookup_module_symbol_attrs(addr, size, offset, modname, name);
 349}
 350
 351/* Look up a kernel symbol and return it in a text buffer. */
 352static int __sprint_symbol(char *buffer, unsigned long address,
 353                           int symbol_offset, int add_offset)
 354{
 355        char *modname;
 356        const char *name;
 357        unsigned long offset, size;
 358        int len;
 359
 360        address += symbol_offset;
 361        name = kallsyms_lookup(address, &size, &offset, &modname, buffer);
 362        if (!name)
 363                return sprintf(buffer, "0x%lx", address - symbol_offset);
 364
 365        if (name != buffer)
 366                strcpy(buffer, name);
 367        len = strlen(buffer);
 368        offset -= symbol_offset;
 369
 370        if (add_offset)
 371                len += sprintf(buffer + len, "+%#lx/%#lx", offset, size);
 372
 373        if (modname)
 374                len += sprintf(buffer + len, " [%s]", modname);
 375
 376        return len;
 377}
 378
 379/**
 380 * sprint_symbol - Look up a kernel symbol and return it in a text buffer
 381 * @buffer: buffer to be stored
 382 * @address: address to lookup
 383 *
 384 * This function looks up a kernel symbol with @address and stores its name,
 385 * offset, size and module name to @buffer if possible. If no symbol was found,
 386 * just saves its @address as is.
 387 *
 388 * This function returns the number of bytes stored in @buffer.
 389 */
 390int sprint_symbol(char *buffer, unsigned long address)
 391{
 392        return __sprint_symbol(buffer, address, 0, 1);
 393}
 394EXPORT_SYMBOL_GPL(sprint_symbol);
 395
 396/**
 397 * sprint_symbol_no_offset - Look up a kernel symbol and return it in a text buffer
 398 * @buffer: buffer to be stored
 399 * @address: address to lookup
 400 *
 401 * This function looks up a kernel symbol with @address and stores its name
 402 * and module name to @buffer if possible. If no symbol was found, just saves
 403 * its @address as is.
 404 *
 405 * This function returns the number of bytes stored in @buffer.
 406 */
 407int sprint_symbol_no_offset(char *buffer, unsigned long address)
 408{
 409        return __sprint_symbol(buffer, address, 0, 0);
 410}
 411EXPORT_SYMBOL_GPL(sprint_symbol_no_offset);
 412
 413/**
 414 * sprint_backtrace - Look up a backtrace symbol and return it in a text buffer
 415 * @buffer: buffer to be stored
 416 * @address: address to lookup
 417 *
 418 * This function is for stack backtrace and does the same thing as
 419 * sprint_symbol() but with modified/decreased @address. If there is a
 420 * tail-call to the function marked "noreturn", gcc optimized out code after
 421 * the call so that the stack-saved return address could point outside of the
 422 * caller. This function ensures that kallsyms will find the original caller
 423 * by decreasing @address.
 424 *
 425 * This function returns the number of bytes stored in @buffer.
 426 */
 427int sprint_backtrace(char *buffer, unsigned long address)
 428{
 429        return __sprint_symbol(buffer, address, -1, 1);
 430}
 431
 432/* To avoid using get_symbol_offset for every symbol, we carry prefix along. */
 433struct kallsym_iter {
 434        loff_t pos;
 435        loff_t pos_mod_end;
 436        loff_t pos_ftrace_mod_end;
 437        unsigned long value;
 438        unsigned int nameoff; /* If iterating in core kernel symbols. */
 439        char type;
 440        char name[KSYM_NAME_LEN];
 441        char module_name[MODULE_NAME_LEN];
 442        int exported;
 443        int show_value;
 444};
 445
 446static int get_ksymbol_mod(struct kallsym_iter *iter)
 447{
 448        int ret = module_get_kallsym(iter->pos - kallsyms_num_syms,
 449                                     &iter->value, &iter->type,
 450                                     iter->name, iter->module_name,
 451                                     &iter->exported);
 452        if (ret < 0) {
 453                iter->pos_mod_end = iter->pos;
 454                return 0;
 455        }
 456
 457        return 1;
 458}
 459
 460static int get_ksymbol_ftrace_mod(struct kallsym_iter *iter)
 461{
 462        int ret = ftrace_mod_get_kallsym(iter->pos - iter->pos_mod_end,
 463                                         &iter->value, &iter->type,
 464                                         iter->name, iter->module_name,
 465                                         &iter->exported);
 466        if (ret < 0) {
 467                iter->pos_ftrace_mod_end = iter->pos;
 468                return 0;
 469        }
 470
 471        return 1;
 472}
 473
 474static int get_ksymbol_bpf(struct kallsym_iter *iter)
 475{
 476        iter->module_name[0] = '\0';
 477        iter->exported = 0;
 478        return bpf_get_kallsym(iter->pos - iter->pos_ftrace_mod_end,
 479                               &iter->value, &iter->type,
 480                               iter->name) < 0 ? 0 : 1;
 481}
 482
 483/* Returns space to next name. */
 484static unsigned long get_ksymbol_core(struct kallsym_iter *iter)
 485{
 486        unsigned off = iter->nameoff;
 487
 488        iter->module_name[0] = '\0';
 489        iter->value = kallsyms_sym_address(iter->pos);
 490
 491        iter->type = kallsyms_get_symbol_type(off);
 492
 493        off = kallsyms_expand_symbol(off, iter->name, ARRAY_SIZE(iter->name));
 494
 495        return off - iter->nameoff;
 496}
 497
 498static void reset_iter(struct kallsym_iter *iter, loff_t new_pos)
 499{
 500        iter->name[0] = '\0';
 501        iter->nameoff = get_symbol_offset(new_pos);
 502        iter->pos = new_pos;
 503        if (new_pos == 0) {
 504                iter->pos_mod_end = 0;
 505                iter->pos_ftrace_mod_end = 0;
 506        }
 507}
 508
 509static int update_iter_mod(struct kallsym_iter *iter, loff_t pos)
 510{
 511        iter->pos = pos;
 512
 513        if (iter->pos_ftrace_mod_end > 0 &&
 514            iter->pos_ftrace_mod_end < iter->pos)
 515                return get_ksymbol_bpf(iter);
 516
 517        if (iter->pos_mod_end > 0 &&
 518            iter->pos_mod_end < iter->pos) {
 519                if (!get_ksymbol_ftrace_mod(iter))
 520                        return get_ksymbol_bpf(iter);
 521                return 1;
 522        }
 523
 524        if (!get_ksymbol_mod(iter)) {
 525                if (!get_ksymbol_ftrace_mod(iter))
 526                        return get_ksymbol_bpf(iter);
 527        }
 528
 529        return 1;
 530}
 531
 532/* Returns false if pos at or past end of file. */
 533static int update_iter(struct kallsym_iter *iter, loff_t pos)
 534{
 535        /* Module symbols can be accessed randomly. */
 536        if (pos >= kallsyms_num_syms)
 537                return update_iter_mod(iter, pos);
 538
 539        /* If we're not on the desired position, reset to new position. */
 540        if (pos != iter->pos)
 541                reset_iter(iter, pos);
 542
 543        iter->nameoff += get_ksymbol_core(iter);
 544        iter->pos++;
 545
 546        return 1;
 547}
 548
 549static void *s_next(struct seq_file *m, void *p, loff_t *pos)
 550{
 551        (*pos)++;
 552
 553        if (!update_iter(m->private, *pos))
 554                return NULL;
 555        return p;
 556}
 557
 558static void *s_start(struct seq_file *m, loff_t *pos)
 559{
 560        if (!update_iter(m->private, *pos))
 561                return NULL;
 562        return m->private;
 563}
 564
 565static void s_stop(struct seq_file *m, void *p)
 566{
 567}
 568
 569static int s_show(struct seq_file *m, void *p)
 570{
 571        void *value;
 572        struct kallsym_iter *iter = m->private;
 573
 574        /* Some debugging symbols have no name.  Ignore them. */
 575        if (!iter->name[0])
 576                return 0;
 577
 578        value = iter->show_value ? (void *)iter->value : NULL;
 579
 580        if (iter->module_name[0]) {
 581                char type;
 582
 583                /*
 584                 * Label it "global" if it is exported,
 585                 * "local" if not exported.
 586                 */
 587                type = iter->exported ? toupper(iter->type) :
 588                                        tolower(iter->type);
 589                seq_printf(m, "%px %c %s\t[%s]\n", value,
 590                           type, iter->name, iter->module_name);
 591        } else
 592                seq_printf(m, "%px %c %s\n", value,
 593                           iter->type, iter->name);
 594        return 0;
 595}
 596
 597static const struct seq_operations kallsyms_op = {
 598        .start = s_start,
 599        .next = s_next,
 600        .stop = s_stop,
 601        .show = s_show
 602};
 603
 604static inline int kallsyms_for_perf(void)
 605{
 606#ifdef CONFIG_PERF_EVENTS
 607        extern int sysctl_perf_event_paranoid;
 608        if (sysctl_perf_event_paranoid <= 1)
 609                return 1;
 610#endif
 611        return 0;
 612}
 613
 614/*
 615 * We show kallsyms information even to normal users if we've enabled
 616 * kernel profiling and are explicitly not paranoid (so kptr_restrict
 617 * is clear, and sysctl_perf_event_paranoid isn't set).
 618 *
 619 * Otherwise, require CAP_SYSLOG (assuming kptr_restrict isn't set to
 620 * block even that).
 621 */
 622int kallsyms_show_value(void)
 623{
 624        switch (kptr_restrict) {
 625        case 0:
 626                if (kallsyms_for_perf())
 627                        return 1;
 628        /* fallthrough */
 629        case 1:
 630                if (has_capability_noaudit(current, CAP_SYSLOG))
 631                        return 1;
 632        /* fallthrough */
 633        default:
 634                return 0;
 635        }
 636}
 637
 638static int kallsyms_open(struct inode *inode, struct file *file)
 639{
 640        /*
 641         * We keep iterator in m->private, since normal case is to
 642         * s_start from where we left off, so we avoid doing
 643         * using get_symbol_offset for every symbol.
 644         */
 645        struct kallsym_iter *iter;
 646        iter = __seq_open_private(file, &kallsyms_op, sizeof(*iter));
 647        if (!iter)
 648                return -ENOMEM;
 649        reset_iter(iter, 0);
 650
 651        iter->show_value = kallsyms_show_value();
 652        return 0;
 653}
 654
 655#ifdef  CONFIG_KGDB_KDB
 656const char *kdb_walk_kallsyms(loff_t *pos)
 657{
 658        static struct kallsym_iter kdb_walk_kallsyms_iter;
 659        if (*pos == 0) {
 660                memset(&kdb_walk_kallsyms_iter, 0,
 661                       sizeof(kdb_walk_kallsyms_iter));
 662                reset_iter(&kdb_walk_kallsyms_iter, 0);
 663        }
 664        while (1) {
 665                if (!update_iter(&kdb_walk_kallsyms_iter, *pos))
 666                        return NULL;
 667                ++*pos;
 668                /* Some debugging symbols have no name.  Ignore them. */
 669                if (kdb_walk_kallsyms_iter.name[0])
 670                        return kdb_walk_kallsyms_iter.name;
 671        }
 672}
 673#endif  /* CONFIG_KGDB_KDB */
 674
 675static const struct file_operations kallsyms_operations = {
 676        .open = kallsyms_open,
 677        .read = seq_read,
 678        .llseek = seq_lseek,
 679        .release = seq_release_private,
 680};
 681
 682static int __init kallsyms_init(void)
 683{
 684        proc_create("kallsyms", 0444, NULL, &kallsyms_operations);
 685        return 0;
 686}
 687device_initcall(kallsyms_init);
 688