cregit-Linux how code gets into the kernel

Release 4.10 tools/perf/util/symbol.c

Directory: tools/perf/util
#include <dirent.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <fcntl.h>
#include <unistd.h>
#include <inttypes.h>
#include "annotate.h"
#include "build-id.h"
#include "util.h"
#include "debug.h"
#include "machine.h"
#include "symbol.h"
#include "strlist.h"
#include "intlist.h"
#include "header.h"

#include <elf.h>
#include <limits.h>
#include <symbol/kallsyms.h>
#include <sys/utsname.h>

static int dso__load_kernel_sym(struct dso *dso, struct map *map);
static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map);
static bool symbol__is_idle(const char *name);


int vmlinux_path__nr_entries;

char **vmlinux_path;


struct symbol_conf symbol_conf = {
	.use_modules		= true,
	.try_vmlinux_path	= true,
	.annotate_src		= true,
	.demangle		= true,
	.demangle_kernel	= false,
	.cumulate_callchain	= true,
	.show_hist_headers	= true,
	.symfs			= "",
	.event_group		= true,
};


static enum dso_binary_type binary_type_symtab[] = {
	DSO_BINARY_TYPE__KALLSYMS,
	DSO_BINARY_TYPE__GUEST_KALLSYMS,
	DSO_BINARY_TYPE__JAVA_JIT,
	DSO_BINARY_TYPE__DEBUGLINK,
	DSO_BINARY_TYPE__BUILD_ID_CACHE,
	DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
	DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
	DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
	DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
	DSO_BINARY_TYPE__GUEST_KMODULE,
	DSO_BINARY_TYPE__GUEST_KMODULE_COMP,
	DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
	DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP,
	DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
	DSO_BINARY_TYPE__NOT_FOUND,
};


#define DSO_BINARY_TYPE__SYMTAB_CNT ARRAY_SIZE(binary_type_symtab)


bool symbol_type__is_a(char symbol_type, enum map_type map_type) { symbol_type = toupper(symbol_type); switch (map_type) { case MAP__FUNCTION: return symbol_type == 'T' || symbol_type == 'W'; case MAP__VARIABLE: return symbol_type == 'D'; default: return false; } }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo4285.71%266.67%
anton blanchardanton blanchard714.29%133.33%
Total49100.00%3100.00%


static int prefix_underscores_count(const char *str) { const char *tail = str; while (*tail == '_') tail++; return tail - str; }

Contributors

PersonTokensPropCommitsCommitProp
anton blanchardanton blanchard33100.00%1100.00%
Total33100.00%1100.00%


int __weak arch__choose_best_symbol(struct symbol *syma, struct symbol *symb __maybe_unused) { /* Avoid "SyS" kernel syscall aliases */ if (strlen(syma->name) >= 3 && !strncmp(syma->name, "SyS", 3)) return SYMBOL_B; if (strlen(syma->name) >= 10 && !strncmp(syma->name, "compat_SyS", 10)) return SYMBOL_B; return SYMBOL_A; }

Contributors

PersonTokensPropCommitsCommitProp
naveen n. raonaveen n. rao7298.63%150.00%
anton blanchardanton blanchard11.37%150.00%
Total73100.00%2100.00%


static int choose_best_symbol(struct symbol *syma, struct symbol *symb) { s64 a; s64 b; size_t na, nb; /* Prefer a symbol with non zero length */ a = syma->end - syma->start; b = symb->end - symb->start; if ((b == 0) && (a > 0)) return SYMBOL_A; else if ((a == 0) && (b > 0)) return SYMBOL_B; /* Prefer a non weak symbol over a weak one */ a = syma->binding == STB_WEAK; b = symb->binding == STB_WEAK; if (b && !a) return SYMBOL_A; if (a && !b) return SYMBOL_B; /* Prefer a global symbol over a non global one */ a = syma->binding == STB_GLOBAL; b = symb->binding == STB_GLOBAL; if (a && !b) return SYMBOL_A; if (b && !a) return SYMBOL_B; /* Prefer a symbol with less underscores */ a = prefix_underscores_count(syma->name); b = prefix_underscores_count(symb->name); if (b > a) return SYMBOL_A; else if (a > b) return SYMBOL_B; /* Choose the symbol with the longest name */ na = strlen(syma->name); nb = strlen(symb->name); if (na > nb) return SYMBOL_A; else if (na < nb) return SYMBOL_B; return arch__choose_best_symbol(syma, symb); }

Contributors

PersonTokensPropCommitsCommitProp
anton blanchardanton blanchard20986.72%133.33%
adrian hunteradrian hunter3012.45%133.33%
naveen n. raonaveen n. rao20.83%133.33%
Total241100.00%3100.00%


void symbols__fixup_duplicate(struct rb_root *symbols) { struct rb_node *nd; struct symbol *curr, *next; if (symbol_conf.allow_aliases) return; nd = rb_first(symbols); while (nd) { curr = rb_entry(nd, struct symbol, rb_node); again: nd = rb_next(&curr->rb_node); next = rb_entry(nd, struct symbol, rb_node); if (!nd) break; if (curr->start != next->start) continue; if (choose_best_symbol(curr, next) == SYMBOL_A) { rb_erase(&next->rb_node, symbols); symbol__delete(next); goto again; } else { nd = rb_next(&curr->rb_node); rb_erase(&curr->rb_node, symbols); symbol__delete(curr); } } }

Contributors

PersonTokensPropCommitsCommitProp
anton blanchardanton blanchard13486.45%125.00%
arnaldo carvalho de meloarnaldo carvalho de melo117.10%250.00%
chenggang qinchenggang qin106.45%125.00%
Total155100.00%4100.00%


void symbols__fixup_end(struct rb_root *symbols) { struct rb_node *nd, *prevnd = rb_first(symbols); struct symbol *curr, *prev; if (prevnd == NULL) return; curr = rb_entry(prevnd, struct symbol, rb_node); for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) { prev = curr; curr = rb_entry(nd, struct symbol, rb_node); if (prev->end == prev->start && prev->end != curr->start) prev->end = curr->start; } /* Last entry */ if (curr->end == curr->start) curr->end = roundup(curr->start, 4096); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo136100.00%5100.00%
Total136100.00%5100.00%


void __map_groups__fixup_end(struct map_groups *mg, enum map_type type) { struct maps *maps = &mg->maps[type]; struct map *next, *curr; pthread_rwlock_wrlock(&maps->lock); curr = maps__first(maps); if (curr == NULL) goto out_unlock; for (next = map__next(curr); next; next = map__next(curr)) { curr->end = next->start; curr = next; } /* * We still haven't the actual symbols, so guess the * last map final address. */ curr->end = ~0ULL; out_unlock: pthread_rwlock_unlock(&maps->lock); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo10899.08%1090.91%
ian munsieian munsie10.92%19.09%
Total109100.00%11100.00%


struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name) { size_t namelen = strlen(name) + 1; struct symbol *sym = calloc(1, (symbol_conf.priv_size + sizeof(*sym) + namelen)); if (sym == NULL) return NULL; if (symbol_conf.priv_size) { if (symbol_conf.init_annotation) { struct annotation *notes = (void *)sym; pthread_mutex_init(&notes->lock, NULL); } sym = ((void *)sym) + symbol_conf.priv_size; } sym->start = start; sym->end = len ? start + len : start; sym->binding = binding; sym->namelen = namelen - 1; pr_debug4("%s: %s %#" PRIx64 "-%#" PRIx64 "\n", __func__, name, start, sym->end); memcpy(sym->name, name, namelen); return sym; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo16993.89%1280.00%
ingo molnaringo molnar52.78%16.67%
mike galbraithmike galbraith42.22%16.67%
paul mackerraspaul mackerras21.11%16.67%
Total180100.00%15100.00%


void symbol__delete(struct symbol *sym) { free(((void *)sym) - symbol_conf.priv_size); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo25100.00%4100.00%
Total25100.00%4100.00%


void symbols__delete(struct rb_root *symbols) { struct symbol *pos; struct rb_node *next = rb_first(symbols); while (next) { pos = rb_entry(next, struct symbol, rb_node); next = rb_next(&pos->rb_node); rb_erase(&pos->rb_node, symbols); symbol__delete(pos); } }

Contributors

PersonTokensPropCommitsCommitProp
jiri olsajiri olsa4870.59%125.00%
arnaldo carvalho de meloarnaldo carvalho de melo2029.41%375.00%
Total68100.00%4100.00%


void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel) { struct rb_node **p = &symbols->rb_node; struct rb_node *parent = NULL; const u64 ip = sym->start; struct symbol *s; if (kernel) { const char *name = sym->name; /* * ppc64 uses function descriptors and appends a '.' to the * start of every instruction address. Remove it. */ if (name[0] == '.') name++; sym->idle = symbol__is_idle(name); } while (*p != NULL) { parent = *p; s = rb_entry(parent, struct symbol, rb_node); if (ip < s->start) p = &(*p)->rb_left; else p = &(*p)->rb_right; } rb_link_node(&sym->rb_node, parent, p); rb_insert_color(&sym->rb_node, symbols); }

Contributors

PersonTokensPropCommitsCommitProp
jiri olsajiri olsa8552.15%321.43%
arnaldo carvalho de meloarnaldo carvalho de melo7143.56%964.29%
masami hiramatsumasami hiramatsu53.07%17.14%
yanmin zhangyanmin zhang21.23%17.14%
Total163100.00%14100.00%


void symbols__insert(struct rb_root *symbols, struct symbol *sym) { __symbols__insert(symbols, sym, false); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo24100.00%1100.00%
Total24100.00%1100.00%


static struct symbol *symbols__find(struct rb_root *symbols, u64 ip) { struct rb_node *n; if (symbols == NULL) return NULL; n = symbols->rb_node; while (n) { struct symbol *s = rb_entry(n, struct symbol, rb_node); if (ip < s->start) n = n->rb_left; else if (ip > s->end || (ip == s->end && ip != s->start)) n = n->rb_right; else return s; } return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
jiri olsajiri olsa5551.40%222.22%
arnaldo carvalho de meloarnaldo carvalho de melo3734.58%666.67%
chris phlipotchris phlipot1514.02%111.11%
Total107100.00%9100.00%


static struct symbol *symbols__first(struct rb_root *symbols) { struct rb_node *n = rb_first(symbols); if (n) return rb_entry(n, struct symbol, rb_node); return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
adrian hunteradrian hunter41100.00%1100.00%
Total41100.00%1100.00%


static struct symbol *symbols__last(struct rb_root *symbols) { struct rb_node *n = rb_last(symbols); if (n) return rb_entry(n, struct symbol, rb_node); return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
adrian hunteradrian hunter41100.00%1100.00%
Total41100.00%1100.00%


static struct symbol *symbols__next(struct symbol *sym) { struct rb_node *n = rb_next(&sym->rb_node); if (n) return rb_entry(n, struct symbol, rb_node); return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
adrian hunteradrian hunter44100.00%1100.00%
Total44100.00%1100.00%


static void symbols__insert_by_name(struct rb_root *symbols, struct symbol *sym) { struct rb_node **p = &symbols->rb_node; struct rb_node *parent = NULL; struct symbol_name_rb_node *symn, *s; symn = container_of(sym, struct symbol_name_rb_node, sym); while (*p != NULL) { parent = *p; s = rb_entry(parent, struct symbol_name_rb_node, rb_node); if (strcmp(sym->name, s->sym.name) < 0) p = &(*p)->rb_left; else p = &(*p)->rb_right; } rb_link_node(&symn->rb_node, parent, p); rb_insert_color(&symn->rb_node, symbols); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo10776.43%375.00%
jiri olsajiri olsa3323.57%125.00%
Total140100.00%4100.00%


static void symbols__sort_by_name(struct rb_root *symbols, struct rb_root *source) { struct rb_node *nd; for (nd = rb_first(source); nd; nd = rb_next(nd)) { struct symbol *pos = rb_entry(nd, struct symbol, rb_node); symbols__insert_by_name(symbols, pos); } }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo5384.13%480.00%
jiri olsajiri olsa1015.87%120.00%
Total63100.00%5100.00%


static struct symbol *symbols__find_by_name(struct rb_root *symbols, const char *name) { struct rb_node *n; struct symbol_name_rb_node *s = NULL; if (symbols == NULL) return NULL; n = symbols->rb_node; while (n) { int cmp; s = rb_entry(n, struct symbol_name_rb_node, rb_node); cmp = arch__compare_symbol_names(name, s->sym.name); if (cmp < 0) n = n->rb_left; else if (cmp > 0) n = n->rb_right; else break; } if (n == NULL) return NULL; /* return first symbol that has same name (if any) */ for (n = rb_prev(n); n; n = rb_prev(n)) { struct symbol_name_rb_node *tmp; tmp = rb_entry(n, struct symbol_name_rb_node, rb_node); if (arch__compare_symbol_names(tmp->sym.name, s->sym.name)) break; s = tmp; } return &s->sym; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo10356.91%240.00%
namhyung kimnamhyung kim7440.88%120.00%
martin liskamartin liska21.10%120.00%
naveen n. raonaveen n. rao21.10%120.00%
Total181100.00%5100.00%


void dso__reset_find_symbol_cache(struct dso *dso) { enum map_type type; for (type = MAP__FUNCTION; type <= MAP__VARIABLE; ++type) { dso->last_find_result[type].addr = 0; dso->last_find_result[type].symbol = NULL; } }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo51100.00%1100.00%
Total51100.00%1100.00%


void dso__insert_symbol(struct dso *dso, enum map_type type, struct symbol *sym) { __symbols__insert(&dso->symbols[type], sym, dso->kernel); /* update the symbol cache if necessary */ if (dso->last_find_result[type].addr >= sym->start && (dso->last_find_result[type].addr < sym->end || sym->start == sym->end)) { dso->last_find_result[type].symbol = sym; } }

Contributors

PersonTokensPropCommitsCommitProp
chris phlipotchris phlipot8394.32%150.00%
arnaldo carvalho de meloarnaldo carvalho de melo55.68%150.00%
Total88100.00%2100.00%


struct symbol *dso__find_symbol(struct dso *dso, enum map_type type, u64 addr) { if (dso->last_find_result[type].addr != addr) { dso->last_find_result[type].addr = addr; dso->last_find_result[type].symbol = symbols__find(&dso->symbols[type], addr); } return dso->last_find_result[type].symbol; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo77100.00%4100.00%
Total77100.00%4100.00%


struct symbol *dso__first_symbol(struct dso *dso, enum map_type type) { return symbols__first(&dso->symbols[type]); }

Contributors

PersonTokensPropCommitsCommitProp
adrian hunteradrian hunter28100.00%2100.00%
Total28100.00%2100.00%


struct symbol *dso__last_symbol(struct dso *dso, enum map_type type) { return symbols__last(&dso->symbols[type]); }

Contributors

PersonTokensPropCommitsCommitProp
adrian hunteradrian hunter28100.00%2100.00%
Total28100.00%2100.00%


struct symbol *dso__next_symbol(struct symbol *sym) { return symbols__next(sym); }

Contributors

PersonTokensPropCommitsCommitProp
adrian hunteradrian hunter18100.00%1100.00%
Total18100.00%1100.00%


struct symbol *symbol__next_by_name(struct symbol *sym) { struct symbol_name_rb_node *s = container_of(sym, struct symbol_name_rb_node, sym); struct rb_node *n = rb_next(&s->rb_node); return n ? &rb_entry(n, struct symbol_name_rb_node, rb_node)->sym : NULL; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo58100.00%1100.00%
Total58100.00%1100.00%

/* * Teturns first symbol that matched with @name. */
struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, const char *name) { return symbols__find_by_name(&dso->symbol_names[type], name); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo35100.00%2100.00%
Total35100.00%2100.00%


void dso__sort_by_name(struct dso *dso, enum map_type type) { dso__set_sorted_by_name(dso, type); return symbols__sort_by_name(&dso->symbol_names[type], &dso->symbols[type]); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo41100.00%2100.00%
Total41100.00%2100.00%


int modules__parse(const char *filename, void *arg, int (*process_module)(void *arg, const char *name, u64 start)) { char *line = NULL; size_t n; FILE *file; int err = 0; file = fopen(filename, "r"); if (file == NULL) return -1; while (1) { char name[PATH_MAX]; u64 start; char *sep; ssize_t line_len; line_len = getline(&line, &n, file); if (line_len < 0) { if (feof(file)) break; err = -1; goto out; } if (!line) { err = -1; goto out; } line[--line_len] = '\0'; /* \n */ sep = strrchr(line, 'x'); if (sep == NULL) continue; hex2u64(sep + 1, &start); sep = strchr(line, ' '); if (sep == NULL) continue; *sep = '\0'; scnprintf(name, sizeof(name), "[%s]", line); err = process_module(arg, name, start); if (err) break; } out: free(line); fclose(file); return err; }

Contributors

PersonTokensPropCommitsCommitProp
adrian hunteradrian hunter245100.00%1100.00%
Total245100.00%1100.00%

struct process_kallsyms_args { struct map *map; struct dso *dso;