Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/perf/arch/loongarch/annotate/instructions.c
26292 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Perf annotate functions.
4
*
5
* Copyright (C) 2020-2023 Loongson Technology Corporation Limited
6
*/
7
8
static int loongarch_call__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms,
9
struct disasm_line *dl __maybe_unused)
10
{
11
char *c, *endptr, *tok, *name;
12
struct map *map = ms->map;
13
struct addr_map_symbol target = {
14
.ms = { .map = map, },
15
};
16
17
c = strchr(ops->raw, '#');
18
if (c++ == NULL)
19
return -1;
20
21
ops->target.addr = strtoull(c, &endptr, 16);
22
23
name = strchr(endptr, '<');
24
name++;
25
26
if (arch->objdump.skip_functions_char &&
27
strchr(name, arch->objdump.skip_functions_char))
28
return -1;
29
30
tok = strchr(name, '>');
31
if (tok == NULL)
32
return -1;
33
34
*tok = '\0';
35
ops->target.name = strdup(name);
36
*tok = '>';
37
38
if (ops->target.name == NULL)
39
return -1;
40
41
target.addr = map__objdump_2mem(map, ops->target.addr);
42
43
if (maps__find_ams(ms->maps, &target) == 0 &&
44
map__rip_2objdump(target.ms.map, map__map_ip(target.ms.map, target.addr)) == ops->target.addr)
45
ops->target.sym = target.ms.sym;
46
47
return 0;
48
}
49
50
static struct ins_ops loongarch_call_ops = {
51
.parse = loongarch_call__parse,
52
.scnprintf = call__scnprintf,
53
};
54
55
static int loongarch_jump__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms,
56
struct disasm_line *dl __maybe_unused)
57
{
58
struct map *map = ms->map;
59
struct symbol *sym = ms->sym;
60
struct addr_map_symbol target = {
61
.ms = { .map = map, },
62
};
63
const char *c = strchr(ops->raw, '#');
64
u64 start, end;
65
66
ops->jump.raw_comment = strchr(ops->raw, arch->objdump.comment_char);
67
ops->jump.raw_func_start = strchr(ops->raw, '<');
68
69
if (ops->jump.raw_func_start && c > ops->jump.raw_func_start)
70
c = NULL;
71
72
if (c++ != NULL)
73
ops->target.addr = strtoull(c, NULL, 16);
74
else
75
ops->target.addr = strtoull(ops->raw, NULL, 16);
76
77
target.addr = map__objdump_2mem(map, ops->target.addr);
78
start = map__unmap_ip(map, sym->start);
79
end = map__unmap_ip(map, sym->end);
80
81
ops->target.outside = target.addr < start || target.addr > end;
82
83
if (maps__find_ams(ms->maps, &target) == 0 &&
84
map__rip_2objdump(target.ms.map, map__map_ip(target.ms.map, target.addr)) == ops->target.addr)
85
ops->target.sym = target.ms.sym;
86
87
if (!ops->target.outside) {
88
ops->target.offset = target.addr - start;
89
ops->target.offset_avail = true;
90
} else {
91
ops->target.offset_avail = false;
92
}
93
94
return 0;
95
}
96
97
static struct ins_ops loongarch_jump_ops = {
98
.parse = loongarch_jump__parse,
99
.scnprintf = jump__scnprintf,
100
};
101
102
static
103
struct ins_ops *loongarch__associate_ins_ops(struct arch *arch, const char *name)
104
{
105
struct ins_ops *ops = NULL;
106
107
if (!strcmp(name, "bl"))
108
ops = &loongarch_call_ops;
109
else if (!strcmp(name, "jirl"))
110
ops = &ret_ops;
111
else if (!strcmp(name, "b") ||
112
!strncmp(name, "beq", 3) ||
113
!strncmp(name, "bne", 3) ||
114
!strncmp(name, "blt", 3) ||
115
!strncmp(name, "bge", 3) ||
116
!strncmp(name, "bltu", 4) ||
117
!strncmp(name, "bgeu", 4))
118
ops = &loongarch_jump_ops;
119
else
120
return NULL;
121
122
arch__associate_ins_ops(arch, name, ops);
123
124
return ops;
125
}
126
127
static
128
int loongarch__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
129
{
130
if (!arch->initialized) {
131
arch->associate_instruction_ops = loongarch__associate_ins_ops;
132
arch->initialized = true;
133
arch->objdump.comment_char = '#';
134
arch->e_machine = EM_LOONGARCH;
135
arch->e_flags = 0;
136
}
137
138
return 0;
139
}
140
141