Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/objtool/arch/loongarch/orc.c
26285 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
#include <linux/objtool_types.h>
3
#include <asm/orc_types.h>
4
5
#include <objtool/check.h>
6
#include <objtool/orc.h>
7
#include <objtool/warn.h>
8
#include <objtool/endianness.h>
9
10
int init_orc_entry(struct orc_entry *orc, struct cfi_state *cfi, struct instruction *insn)
11
{
12
struct cfi_reg *fp = &cfi->regs[CFI_FP];
13
struct cfi_reg *ra = &cfi->regs[CFI_RA];
14
15
memset(orc, 0, sizeof(*orc));
16
17
if (!cfi) {
18
/*
19
* This is usually either unreachable nops/traps (which don't
20
* trigger unreachable instruction warnings), or
21
* STACK_FRAME_NON_STANDARD functions.
22
*/
23
orc->type = ORC_TYPE_UNDEFINED;
24
return 0;
25
}
26
27
switch (cfi->type) {
28
case UNWIND_HINT_TYPE_UNDEFINED:
29
orc->type = ORC_TYPE_UNDEFINED;
30
return 0;
31
case UNWIND_HINT_TYPE_END_OF_STACK:
32
orc->type = ORC_TYPE_END_OF_STACK;
33
return 0;
34
case UNWIND_HINT_TYPE_CALL:
35
orc->type = ORC_TYPE_CALL;
36
break;
37
case UNWIND_HINT_TYPE_REGS:
38
orc->type = ORC_TYPE_REGS;
39
break;
40
case UNWIND_HINT_TYPE_REGS_PARTIAL:
41
orc->type = ORC_TYPE_REGS_PARTIAL;
42
break;
43
default:
44
ERROR_INSN(insn, "unknown unwind hint type %d", cfi->type);
45
return -1;
46
}
47
48
orc->signal = cfi->signal;
49
50
switch (cfi->cfa.base) {
51
case CFI_SP:
52
orc->sp_reg = ORC_REG_SP;
53
break;
54
case CFI_FP:
55
orc->sp_reg = ORC_REG_FP;
56
break;
57
default:
58
ERROR_INSN(insn, "unknown CFA base reg %d", cfi->cfa.base);
59
return -1;
60
}
61
62
switch (fp->base) {
63
case CFI_UNDEFINED:
64
orc->fp_reg = ORC_REG_UNDEFINED;
65
orc->fp_offset = 0;
66
break;
67
case CFI_CFA:
68
orc->fp_reg = ORC_REG_PREV_SP;
69
orc->fp_offset = fp->offset;
70
break;
71
case CFI_FP:
72
orc->fp_reg = ORC_REG_FP;
73
break;
74
default:
75
ERROR_INSN(insn, "unknown FP base reg %d", fp->base);
76
return -1;
77
}
78
79
switch (ra->base) {
80
case CFI_UNDEFINED:
81
orc->ra_reg = ORC_REG_UNDEFINED;
82
orc->ra_offset = 0;
83
break;
84
case CFI_CFA:
85
orc->ra_reg = ORC_REG_PREV_SP;
86
orc->ra_offset = ra->offset;
87
break;
88
case CFI_FP:
89
orc->ra_reg = ORC_REG_FP;
90
break;
91
default:
92
ERROR_INSN(insn, "unknown RA base reg %d", ra->base);
93
return -1;
94
}
95
96
orc->sp_offset = cfi->cfa.offset;
97
98
return 0;
99
}
100
101
int write_orc_entry(struct elf *elf, struct section *orc_sec,
102
struct section *ip_sec, unsigned int idx,
103
struct section *insn_sec, unsigned long insn_off,
104
struct orc_entry *o)
105
{
106
struct orc_entry *orc;
107
108
/* populate ORC data */
109
orc = (struct orc_entry *)orc_sec->data->d_buf + idx;
110
memcpy(orc, o, sizeof(*orc));
111
112
/* populate reloc for ip */
113
if (!elf_init_reloc_text_sym(elf, ip_sec, idx * sizeof(int), idx,
114
insn_sec, insn_off))
115
return -1;
116
117
return 0;
118
}
119
120
static const char *reg_name(unsigned int reg)
121
{
122
switch (reg) {
123
case ORC_REG_SP:
124
return "sp";
125
case ORC_REG_FP:
126
return "fp";
127
case ORC_REG_PREV_SP:
128
return "prevsp";
129
default:
130
return "?";
131
}
132
}
133
134
static const char *orc_type_name(unsigned int type)
135
{
136
switch (type) {
137
case UNWIND_HINT_TYPE_CALL:
138
return "call";
139
case UNWIND_HINT_TYPE_REGS:
140
return "regs";
141
case UNWIND_HINT_TYPE_REGS_PARTIAL:
142
return "regs (partial)";
143
default:
144
return "?";
145
}
146
}
147
148
static void print_reg(unsigned int reg, int offset)
149
{
150
if (reg == ORC_REG_UNDEFINED)
151
printf(" (und) ");
152
else
153
printf("%s + %3d", reg_name(reg), offset);
154
155
}
156
157
void orc_print_dump(struct elf *dummy_elf, struct orc_entry *orc, int i)
158
{
159
printf("type:%s", orc_type_name(orc[i].type));
160
161
printf(" sp:");
162
print_reg(orc[i].sp_reg, orc[i].sp_offset);
163
164
printf(" fp:");
165
print_reg(orc[i].fp_reg, orc[i].fp_offset);
166
167
printf(" ra:");
168
print_reg(orc[i].ra_reg, orc[i].ra_offset);
169
170
printf(" signal:%d\n", orc[i].signal);
171
}
172
173