Skip to content
Snippets Groups Projects
annotate.c 31.7 KiB
Newer Older
/*
 * 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 "build-id.h"
#include "color.h"
#include "cache.h"
#include "symbol.h"
#include "debug.h"
#include "annotate.h"
#include <linux/bitops.h>
const char 	*disassembler_style;
static struct ins *ins__find(const char *name);
static int disasm_line__parse(char *line, char **namep, char **rawp);

static void ins__delete(struct ins_operands *ops)
{
	free(ops->source.raw);
	free(ops->source.name);
	free(ops->target.raw);
	free(ops->target.name);
}

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);
}

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);
}

static int call__parse(struct ins_operands *ops)
	ops->target.addr = strtoull(ops->raw, &endptr, 16);

	name = strchr(endptr, '<');
	if (name == NULL)
		goto indirect_call;

	name++;

	tok = strchr(name, '>');
	if (tok == NULL)
		return -1;

	*tok = '\0';
	return ops->target.name == NULL ? -1 : 0;
	tok = strchr(endptr, '(');
	if (tok != NULL) {
		ops->target.addr = 0;
		return 0;
	}

	tok = strchr(endptr, '*');
	if (tok == NULL)
		return -1;

	ops->target.addr = strtoull(tok + 1, NULL, 16);
static int call__scnprintf(struct ins *ins, char *bf, size_t size,
	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);
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;
}

static int jump__parse(struct ins_operands *ops)
	const char *s = strchr(ops->raw, '+');
	ops->target.addr = strtoull(ops->raw, NULL, 16);
		ops->target.offset = strtoull(s, NULL, 16);
	else
		ops->target.offset = UINT64_MAX;
static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
	return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset);
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;
}

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;
}

static int lock__parse(struct ins_operands *ops)
{
	char *name;

	ops->locked.ops = zalloc(sizeof(*ops->locked.ops));
	if (ops->locked.ops == NULL)
		return 0;

	if (disasm_line__parse(ops->raw, &name, &ops->locked.ops->raw) < 0)
		goto out_free_ops;

	ops->locked.ins = ins__find(name);
	if (ops->locked.ins == NULL)
		goto out_free_ops;
	if (!ops->locked.ins->ops)
		return 0;
	if (ops->locked.ins->ops->parse)
		ops->locked.ins->ops->parse(ops->locked.ops);

	return 0;

out_free_ops:
	free(ops->locked.ops);
	ops->locked.ops = NULL;
	return 0;
}

static int lock__scnprintf(struct ins *ins, char *bf, size_t size,
			   struct ins_operands *ops)
{
	int printed;

	if (ops->locked.ins == NULL)
		return ins__raw_scnprintf(ins, bf, size, ops);

Loading
Loading full blame...