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