1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * dwarf-regs.c : Mapping of DWARF debug register numbers into register names.
4 * Extracted from probe-finder.c
5 *
6 * Written by Masami Hiramatsu <mhiramat@redhat.com>
7 */
8
9 #include <errno.h> /* for EINVAL */
10 #include <string.h> /* for strcmp */
11 #include <linux/kernel.h> /* for ARRAY_SIZE */
12 #include <dwarf-regs.h>
13 #include "../../../arch/x86/include/uapi/asm/perf_regs.h"
14
15 struct dwarf_regs_idx {
16 const char *name;
17 int dwarf_regnum;
18 };
19
20 static const struct dwarf_regs_idx i386_regidx_table[] = {
21 { "eax", 0 }, { "ax", 0 }, { "al", 0 },
22 { "ecx", 1 }, { "cx", 1 }, { "cl", 1 },
23 { "edx", 2 }, { "dx", 2 }, { "dl", 2 },
24 { "ebx", 3 }, { "bx", 3 }, { "bl", 3 },
25 { "esp", 4 }, { "sp", 4 }, { "$stack", 4},
26 { "ebp", 5 }, { "bp", 5 },
27 { "esi", 6 }, { "si", 6 },
28 { "edi", 7 }, { "di", 7 },
29 // 8 - Return Address RA
30 { "eflags", 9}, { "flags", 9},
31 // 10 - reserved
32 { "st0", 11},
33 { "st1", 12},
34 { "st2", 13},
35 { "st3", 14},
36 { "st4", 15},
37 { "st5", 16},
38 { "st6", 17},
39 { "st7", 18},
40 // 19-20 - reserved
41 { "xmm0", 21},
42 { "xmm1", 22},
43 { "xmm2", 23},
44 { "xmm3", 24},
45 { "xmm4", 25},
46 { "xmm5", 26},
47 { "xmm6", 27},
48 { "xmm7", 28},
49 { "mm0", 29},
50 { "mm1", 30},
51 { "mm2", 31},
52 { "mm3", 32},
53 { "mm4", 33},
54 { "mm5", 34},
55 { "mm6", 35},
56 { "mm7", 36},
57 // 37-38 - unknown
58 { "mxcsr", 39}, // 128-bit Media Control and Status
59 { "es", 40},
60 { "cs", 41},
61 { "ss", 42},
62 { "ds", 43},
63 { "fs", 44},
64 { "gs", 45},
65 // 46-47 - reserved
66 { "tr", 48}, // Task Register
67 { "ldtr", 49}, // LDT Register
68 // 50-92 - reserved
69 { "fs.base", 92},
70 { "gs.base", 93},
71 // End of regular dwarf registers.
72 { "eip", DWARF_REG_PC }, { "ip", DWARF_REG_PC },
73 };
74
75 static const struct dwarf_regs_idx x86_64_regidx_table[] = {
76 { "rax", 0 }, { "eax", 0 }, { "ax", 0 }, { "al", 0 },
77 { "rdx", 1 }, { "edx", 1 }, { "dx", 1 }, { "dl", 1 },
78 { "rcx", 2 }, { "ecx", 2 }, { "cx", 2 }, { "cl", 2 },
79 { "rbx", 3 }, { "edx", 3 }, { "bx", 3 }, { "bl", 3 },
80 { "rsi", 4 }, { "esi", 4 }, { "si", 4 }, { "sil", 4 },
81 { "rdi", 5 }, { "edi", 5 }, { "di", 5 }, { "dil", 5 },
82 { "rbp", 6 }, { "ebp", 6 }, { "bp", 6 }, { "bpl", 6 },
83 { "rsp", 7 }, { "esp", 7 }, { "sp", 7 }, { "spl", 7 },
84 { "r8", 8 }, { "r8d", 8 }, { "r8w", 8 }, { "r8b", 8 },
85 { "r9", 9 }, { "r9d", 9 }, { "r9w", 9 }, { "r9b", 9 },
86 { "r10", 10 }, { "r10d", 10 }, { "r10w", 10 }, { "r10b", 10 },
87 { "r11", 11 }, { "r11d", 11 }, { "r11w", 11 }, { "r11b", 11 },
88 { "r12", 12 }, { "r12d", 12 }, { "r12w", 12 }, { "r12b", 12 },
89 { "r13", 13 }, { "r13d", 13 }, { "r13w", 13 }, { "r13b", 13 },
90 { "r14", 14 }, { "r14d", 14 }, { "r14w", 14 }, { "r14b", 14 },
91 { "r15", 15 }, { "r15d", 15 }, { "r15w", 15 }, { "r15b", 15 },
92 // 16 - Return Address RA
93 { "xmm0", 17},
94 { "xmm1", 18},
95 { "xmm2", 19},
96 { "xmm3", 20},
97 { "xmm4", 21},
98 { "xmm5", 22},
99 { "xmm6", 23},
100 { "xmm7", 24},
101 { "xmm8", 25},
102 { "xmm9", 26},
103 { "xmm10", 27},
104 { "xmm11", 28},
105 { "xmm12", 29},
106 { "xmm13", 30},
107 { "xmm14", 31},
108 { "xmm15", 32},
109 { "st0", 33},
110 { "st1", 34},
111 { "st2", 35},
112 { "st3", 36},
113 { "st4", 37},
114 { "st5", 38},
115 { "st6", 39},
116 { "st7", 40},
117 { "mm0", 41},
118 { "mm1", 42},
119 { "mm2", 43},
120 { "mm3", 44},
121 { "mm4", 45},
122 { "mm5", 46},
123 { "mm6", 47},
124 { "mm7", 48},
125 { "rflags", 49}, { "eflags", 49}, { "flags", 49},
126 { "es", 50},
127 { "cs", 51},
128 { "ss", 52},
129 { "ds", 53},
130 { "fs", 54},
131 { "gs", 55},
132 // 56-47 - reserved
133 { "fs.base", 58},
134 { "gs.base", 59},
135 // 60-61 - reserved
136 { "tr", 62}, // Task Register
137 { "ldtr", 63}, // LDT Register
138 { "mxcsr", 64}, // 128-bit Media Control and Status
139 { "fcw", 65}, // x87 Control Word
140 { "fsw", 66}, // x87 Status Word
141 // End of regular dwarf registers.
142 { "rip", DWARF_REG_PC }, { "eip", DWARF_REG_PC }, { "ip", DWARF_REG_PC },
143 };
144
get_regnum(const struct dwarf_regs_idx * entries,size_t num_entries,const char * name)145 static int get_regnum(const struct dwarf_regs_idx *entries, size_t num_entries, const char *name)
146 {
147 if (*name != '%')
148 return -EINVAL;
149
150 name++;
151 for (size_t i = 0; i < num_entries; i++) {
152 if (!strcmp(entries[i].name, name))
153 return entries[i].dwarf_regnum;
154 }
155 return -ENOENT;
156 }
157
__get_dwarf_regnum_i386(const char * name)158 int __get_dwarf_regnum_i386(const char *name)
159 {
160 return get_regnum(i386_regidx_table, ARRAY_SIZE(i386_regidx_table), name);
161 }
162
__get_dwarf_regnum_x86_64(const char * name)163 int __get_dwarf_regnum_x86_64(const char *name)
164 {
165 return get_regnum(x86_64_regidx_table, ARRAY_SIZE(x86_64_regidx_table), name);
166 }
167
__get_dwarf_regnum_for_perf_regnum_i386(int perf_regnum)168 int __get_dwarf_regnum_for_perf_regnum_i386(int perf_regnum)
169 {
170 static const int dwarf_i386_regnums[] = {
171 [PERF_REG_X86_AX] = 0,
172 [PERF_REG_X86_BX] = 3,
173 [PERF_REG_X86_CX] = 1,
174 [PERF_REG_X86_DX] = 2,
175 [PERF_REG_X86_SI] = 6,
176 [PERF_REG_X86_DI] = 7,
177 [PERF_REG_X86_BP] = 5,
178 [PERF_REG_X86_SP] = 4,
179 [PERF_REG_X86_IP] = 8,
180 [PERF_REG_X86_FLAGS] = 9,
181 [PERF_REG_X86_CS] = 41,
182 [PERF_REG_X86_SS] = 42,
183 [PERF_REG_X86_DS] = 43,
184 [PERF_REG_X86_ES] = 40,
185 [PERF_REG_X86_FS] = 44,
186 [PERF_REG_X86_GS] = 45,
187 [PERF_REG_X86_XMM0] = 21,
188 [PERF_REG_X86_XMM1] = 22,
189 [PERF_REG_X86_XMM2] = 23,
190 [PERF_REG_X86_XMM3] = 24,
191 [PERF_REG_X86_XMM4] = 25,
192 [PERF_REG_X86_XMM5] = 26,
193 [PERF_REG_X86_XMM6] = 27,
194 [PERF_REG_X86_XMM7] = 28,
195 };
196
197 if (perf_regnum == 0)
198 return 0;
199
200 if (perf_regnum < 0 || perf_regnum > (int)ARRAY_SIZE(dwarf_i386_regnums) ||
201 dwarf_i386_regnums[perf_regnum] == 0)
202 return -ENOENT;
203
204 return dwarf_i386_regnums[perf_regnum];
205 }
206
__get_dwarf_regnum_for_perf_regnum_x86_64(int perf_regnum)207 int __get_dwarf_regnum_for_perf_regnum_x86_64(int perf_regnum)
208 {
209 static const int dwarf_x86_64_regnums[] = {
210 [PERF_REG_X86_AX] = 0,
211 [PERF_REG_X86_BX] = 3,
212 [PERF_REG_X86_CX] = 2,
213 [PERF_REG_X86_DX] = 1,
214 [PERF_REG_X86_SI] = 4,
215 [PERF_REG_X86_DI] = 5,
216 [PERF_REG_X86_BP] = 6,
217 [PERF_REG_X86_SP] = 7,
218 [PERF_REG_X86_IP] = 16,
219 [PERF_REG_X86_FLAGS] = 49,
220 [PERF_REG_X86_CS] = 51,
221 [PERF_REG_X86_SS] = 52,
222 [PERF_REG_X86_DS] = 53,
223 [PERF_REG_X86_ES] = 50,
224 [PERF_REG_X86_FS] = 54,
225 [PERF_REG_X86_GS] = 55,
226 [PERF_REG_X86_R8] = 8,
227 [PERF_REG_X86_R9] = 9,
228 [PERF_REG_X86_R10] = 10,
229 [PERF_REG_X86_R11] = 11,
230 [PERF_REG_X86_R12] = 12,
231 [PERF_REG_X86_R13] = 13,
232 [PERF_REG_X86_R14] = 14,
233 [PERF_REG_X86_R15] = 15,
234 [PERF_REG_X86_XMM0] = 17,
235 [PERF_REG_X86_XMM1] = 18,
236 [PERF_REG_X86_XMM2] = 19,
237 [PERF_REG_X86_XMM3] = 20,
238 [PERF_REG_X86_XMM4] = 21,
239 [PERF_REG_X86_XMM5] = 22,
240 [PERF_REG_X86_XMM6] = 23,
241 [PERF_REG_X86_XMM7] = 24,
242 [PERF_REG_X86_XMM8] = 25,
243 [PERF_REG_X86_XMM9] = 26,
244 [PERF_REG_X86_XMM10] = 27,
245 [PERF_REG_X86_XMM11] = 28,
246 [PERF_REG_X86_XMM12] = 29,
247 [PERF_REG_X86_XMM13] = 30,
248 [PERF_REG_X86_XMM14] = 31,
249 [PERF_REG_X86_XMM15] = 32,
250 };
251
252 if (perf_regnum == 0)
253 return 0;
254
255 if (perf_regnum < 0 || perf_regnum > (int)ARRAY_SIZE(dwarf_x86_64_regnums) ||
256 dwarf_x86_64_regnums[perf_regnum] == 0)
257 return -ENOENT;
258
259 return dwarf_x86_64_regnums[perf_regnum];
260 }
261