cregit-Linux how code gets into the kernel

Release 4.10 tools/perf/util/annotate.c

Directory: tools/perf/util
/*
 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
 *
 * Parts came from builtin-annotate.c, see those files for further
 * copyright notes.
 *
 * Released under the GPL v2. (and only v2, not any later version)
 */

#include "util.h"
#include "ui/ui.h"
#include "sort.h"
#include "build-id.h"
#include "color.h"
#include "cache.h"
#include "symbol.h"
#include "debug.h"
#include "annotate.h"
#include "evsel.h"
#include "block-range.h"
#include "arch/common.h"
#include <regex.h>
#include <pthread.h>
#include <linux/bitops.h>
#include <sys/utsname.h>


const char 	*disassembler_style;

const char	*objdump_path;

static regex_t	 file_lineno;

static struct ins_ops *ins__find(struct arch *arch, const char *name);
static void ins__sort(struct arch *arch);
static int disasm_line__parse(char *line, const char **namep, char **rawp);


struct arch {
	
const char	*name;
	
struct ins	*instructions;
	
size_t		nr_instructions;
	
size_t		nr_instructions_allocated;
	
struct ins_ops  *(*associate_instruction_ops)(struct arch *arch, const char *name);
	
bool		sorted_instructions;
	
bool		initialized;
	
void		*priv;
	
int		(*init)(struct arch *arch);
	struct		{
		
char comment_char;
		
char skip_functions_char;
	} 
objdump;
};


static struct ins_ops call_ops;

static struct ins_ops dec_ops;

static struct ins_ops jump_ops;

static struct ins_ops mov_ops;

static struct ins_ops nop_ops;

static struct ins_ops lock_ops;

static struct ins_ops ret_ops;


static int arch__grow_instructions(struct arch *arch) { struct ins *new_instructions; size_t new_nr_allocated; if (arch->nr_instructions_allocated == 0 && arch->instructions) goto grow_from_non_allocated_table; new_nr_allocated = arch->nr_instructions_allocated + 128; new_instructions = realloc(arch->instructions, new_nr_allocated * sizeof(struct ins)); if (new_instructions == NULL) return -1; out_update_instructions: arch->instructions = new_instructions; arch->nr_instructions_allocated = new_nr_allocated; return 0; grow_from_non_allocated_table: new_nr_allocated = arch->nr_instructions + 128; new_instructions = calloc(new_nr_allocated, sizeof(struct ins)); if (new_instructions == NULL) return -1; memcpy(new_instructions, arch->instructions, arch->nr_instructions); goto out_update_instructions; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo135100.00%1100.00%
Total135100.00%1100.00%


static int arch__associate_ins_ops(struct arch* arch, const char *name, struct ins_ops *ops) { struct ins *ins; if (arch->nr_instructions == arch->nr_instructions_allocated && arch__grow_instructions(arch)) return -1; ins = &arch->instructions[arch->nr_instructions]; ins->name = strdup(name); if (!ins->name) return -1; ins->ops = ops; arch->nr_instructions++; ins__sort(arch); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo96100.00%1100.00%
Total96100.00%1100.00%

#include "arch/arm/annotate/instructions.c" #include "arch/arm64/annotate/instructions.c" #include "arch/x86/annotate/instructions.c" #include "arch/powerpc/annotate/instructions.c" static struct arch architectures[] = { { .name = "arm", .init = arm__annotate_init, }, { .name = "arm64", .init = arm64__annotate_init, }, { .name = "x86", .instructions = x86__instructions, .nr_instructions = ARRAY_SIZE(x86__instructions), .objdump = { .comment_char = '#', }, }, { .name = "powerpc", .init = powerpc__annotate_init, }, };
static void ins__delete(struct ins_operands *ops) { if (ops == NULL) return; zfree(&ops->source.raw); zfree(&ops->source.name); zfree(&ops->target.raw); zfree(&ops->target.name); }

Contributors

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


static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops) { return scnprintf(bf, size, "%-6.6s %s", ins->name, ops->raw); }

Contributors

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


int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops) { if (ins->ops->scnprintf) return ins->ops->scnprintf(ins, bf, size, ops); return ins__raw_scnprintf(ins, bf, size, ops); }

Contributors

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


static int call__parse(struct arch *arch, struct ins_operands *ops, struct map *map) { char *endptr, *tok, *name; ops->target.addr = strtoull(ops->raw, &endptr, 16); name = strchr(endptr, '<'); if (name == NULL) goto indirect_call; name++; if (arch->objdump.skip_functions_char && strchr(name, arch->objdump.skip_functions_char)) return -1; tok = strchr(name, '>'); if (tok == NULL) return -1; *tok = '\0'; ops->target.name = strdup(name); *tok = '>'; return ops->target.name == NULL ? -1 : 0; indirect_call: tok = strchr(endptr, '*'); if (tok == NULL) { struct symbol *sym = map__find_symbol(map, map->map_ip(map, ops->target.addr)); if (sym != NULL) ops->target.name = strdup(sym->name); else ops->target.addr = 0; return 0; } ops->target.addr = strtoull(tok + 1, NULL, 16); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo22694.17%981.82%
russell kingrussell king125.00%19.09%
ravi bangoriaravi bangoria20.83%19.09%
Total240100.00%11100.00%


static int call__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops) { if (ops->target.name) return scnprintf(bf, size, "%-6.6s %s", ins->name, ops->target.name); if (ops->target.addr == 0) return ins__raw_scnprintf(ins, bf, size, ops); return scnprintf(bf, size, "%-6.6s *%" PRIx64, ins->name, ops->target.addr); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo94100.00%3100.00%
Total94100.00%3100.00%

static struct ins_ops call_ops = { .parse = call__parse, .scnprintf = call__scnprintf, };
bool ins__is_call(const struct ins *ins) { return ins->ops == &call_ops; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo19100.00%1100.00%
Total19100.00%1100.00%


static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map *map __maybe_unused) { const char *s = strchr(ops->raw, '+'); const char *c = strchr(ops->raw, ','); if (c++ != NULL) ops->target.addr = strtoull(c, NULL, 16); else ops->target.addr = strtoull(ops->raw, NULL, 16); if (s++ != NULL) { ops->target.offset = strtoull(s, NULL, 16); ops->target.offset_avail = true; } else { ops->target.offset_avail = false; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo8461.31%666.67%
ravi bangoriaravi bangoria5137.23%222.22%
adrian hunteradrian hunter21.46%111.11%
Total137100.00%9100.00%


static int jump__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops) { if (!ops->target.addr || ops->target.offset < 0) return ins__raw_scnprintf(ins, bf, size, ops); return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo4460.27%360.00%
ravi bangoriaravi bangoria2939.73%240.00%
Total73100.00%5100.00%

static struct ins_ops jump_ops = { .parse = jump__parse, .scnprintf = jump__scnprintf, };
bool ins__is_jump(const struct ins *ins) { return ins->ops == &jump_ops; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo19100.00%1100.00%
Total19100.00%1100.00%


static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep) { char *endptr, *name, *t; if (strstr(raw, "(%rip)") == NULL) return 0; *addrp = strtoull(comment, &endptr, 16); name = strchr(endptr, '<'); if (name == NULL) return -1; name++; t = strchr(name, '>'); if (t == NULL) return 0; *t = '\0'; *namep = strdup(name); *t = '>'; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo121100.00%1100.00%
Total121100.00%1100.00%


static int lock__parse(struct arch *arch, struct ins_operands *ops, struct map *map) { ops->locked.ops = zalloc(sizeof(*ops->locked.ops)); if (ops->locked.ops == NULL) return 0; if (disasm_line__parse(ops->raw, &ops->locked.ins.name, &ops->locked.ops->raw) < 0) goto out_free_ops; ops->locked.ins.ops = ins__find(arch, ops->locked.ins.name); if (ops->locked.ins.ops == NULL) goto out_free_ops; if (ops->locked.ins.ops->parse && ops->locked.ins.ops->parse(arch, ops->locked.ops, map) < 0) goto out_free_ops; return 0; out_free_ops: zfree(&ops->locked.ops); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo16794.35%777.78%
rabin vincentrabin vincent105.65%222.22%
Total177100.00%9100.00%


static int lock__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops) { int printed; if (ops->locked.ins.ops == NULL) return ins__raw_scnprintf(ins, bf, size, ops); printed = scnprintf(bf, size, "%-6.6s ", ins->name); return printed + ins__scnprintf(&ops->locked.ins, bf + printed, size - printed, ops->locked.ops); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo92100.00%3100.00%
Total92100.00%3100.00%


static void lock__delete(struct ins_operands *ops) { struct ins *ins = &ops->locked.ins; if (ins->ops && ins->ops->free) ins->ops->free(ops->locked.ops); else ins__delete(ops->locked.ops); zfree(&ops->locked.ops); zfree(&ops->target.raw); zfree(&ops->target.name); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo4450.00%375.00%
rabin vincentrabin vincent4450.00%125.00%
Total88100.00%4100.00%

static struct ins_ops lock_ops = { .free = lock__delete, .parse = lock__parse, .scnprintf = lock__scnprintf, };
static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map *map __maybe_unused) { char *s = strchr(ops->raw, ','), *target, *comment, prev; if (s == NULL) return -1; *s = '\0'; ops->source.raw = strdup(ops->raw); *s = ','; if (ops->source.raw == NULL) return -1; target = ++s; comment = strchr(s, arch->objdump.comment_char); if (comment != NULL) s = comment - 1; else s = strchr(s, '\0') - 1; while (s > target && isspace(s[0])) --s; s++; prev = *s; *s = '\0'; ops->target.raw = strdup(target); *s = prev; if (ops->target.raw == NULL) goto out_free_source; if (comment == NULL) return 0; while (comment[0] != '\0' && isspace(comment[0])) ++comment; comment__symbol(ops->source.raw, comment, &ops->source.addr, &ops->source.name); comment__symbol(ops->target.raw, comment, &ops->target.addr, &ops->target.name); return 0; out_free_source: zfree(&ops->source.raw); return -1; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo25086.51%571.43%
alex conversealex converse3311.42%114.29%
russell kingrussell king62.08%114.29%
Total289100.00%7100.00%


static int mov__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops) { return scnprintf(bf, size, "%-6.6s %s,%s", ins->name, ops->source.name ?: ops->source.raw, ops->target.name ?: ops->target.raw); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo63100.00%2100.00%
Total63100.00%2100.00%

static struct ins_ops mov_ops = { .parse = mov__parse, .scnprintf = mov__scnprintf, };
static int dec__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map *map __maybe_unused) { char *target, *comment, *s, prev; target = s = ops->raw; while (s[0] != '\0' && !isspace(s[0])) ++s; prev = *s; *s = '\0'; ops->target.raw = strdup(target); *s = prev; if (ops->target.raw == NULL) return -1; comment = strchr(s, arch->objdump.comment_char); if (comment == NULL) return 0; while (comment[0] != '\0' && isspace(comment[0])) ++comment; comment__symbol(ops->target.raw, comment, &ops->target.addr, &ops->target.name); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo16997.13%480.00%
kim phillipskim phillips52.87%120.00%
Total174100.00%5100.00%


static int dec__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops) { return scnprintf(bf, size, "%-6.6s %s", ins->name, ops->target.name ?: ops->target.raw); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo50100.00%1100.00%
Total50100.00%1100.00%

static struct ins_ops dec_ops = { .parse = dec__parse, .scnprintf = dec__scnprintf, };
static int nop__scnprintf(struct ins *ins __maybe_unused, char *bf, size_t size, struct ins_operands *ops __maybe_unused) { return scnprintf(bf, size, "%-6.6s", "nop"); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo3594.59%150.00%
irina tirdeairina tirdea25.41%150.00%
Total37100.00%2100.00%

static struct ins_ops nop_ops = { .scnprintf = nop__scnprintf, }; static struct ins_ops ret_ops = { .scnprintf = ins__raw_scnprintf, };
bool ins__is_ret(const struct ins *ins) { return ins->ops == &ret_ops; }

Contributors

PersonTokensPropCommitsCommitProp
naveen n. raonaveen n. rao19100.00%1100.00%
Total19100.00%1100.00%


static int ins__key_cmp(const void *name, const void *insp) { const struct ins *ins = insp; return strcmp(name, ins->name); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo34100.00%2100.00%
Total34100.00%2100.00%


static int ins__cmp(const void *a, const void *b) { const struct ins *ia = a; const struct ins *ib = b; return strcmp(ia->name, ib->name); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo44100.00%2100.00%
Total44100.00%2100.00%


static void ins__sort(struct arch *arch) { const int nmemb = arch->nr_instructions; qsort(arch->instructions, nmemb, sizeof(struct ins), ins__cmp); }

Contributors

PersonTokensPropCommitsCommitProp
chris ryderchris ryder2261.11%150.00%
arnaldo carvalho de meloarnaldo carvalho de melo1438.89%150.00%
Total36100.00%2100.00%


static struct ins_ops *__ins__find(struct arch *arch, const char *name) { struct ins *ins; const int nmemb = arch->nr_instructions; if (!arch->sorted_instructions) { ins__sort(arch); arch->sorted_instructions = true; } ins = bsearch(name, arch->instructions, nmemb, sizeof(struct ins), ins__key_cmp); return ins ? ins->ops : NULL; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo6883.95%480.00%
chris ryderchris ryder1316.05%120.00%
Total81100.00%5100.00%


static struct ins_ops *ins__find(struct arch *arch, const char *name) { struct ins_ops *ops = __ins__find(arch, name); if (!ops && arch->associate_instruction_ops) ops = arch->associate_instruction_ops(arch, name); return ops; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo53100.00%1100.00%
Total53100.00%1100.00%


static int arch__key_cmp(const void *name,