0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <stddef.h>
0010 #include <errno.h> /* for EINVAL */
0011 #include <string.h> /* for strcmp */
0012 #include <linux/ptrace.h> /* for struct pt_regs */
0013 #include <linux/kernel.h> /* for offsetof */
0014 #include <dwarf-regs.h>
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 struct pt_regs_offset {
0038 const char *name;
0039 int offset;
0040 };
0041
0042 #define REG_OFFSET_END {.name = NULL, .offset = 0}
0043
0044 #ifdef __x86_64__
0045 # define REG_OFFSET_NAME_64(n, r) {.name = n, .offset = offsetof(struct pt_regs, r)}
0046 # define REG_OFFSET_NAME_32(n, r) {.name = n, .offset = -1}
0047 #else
0048 # define REG_OFFSET_NAME_64(n, r) {.name = n, .offset = -1}
0049 # define REG_OFFSET_NAME_32(n, r) {.name = n, .offset = offsetof(struct pt_regs, r)}
0050 #endif
0051
0052
0053 #ifndef __x86_64__
0054 static const struct pt_regs_offset x86_32_regoffset_table[] = {
0055 REG_OFFSET_NAME_32("%ax", eax),
0056 REG_OFFSET_NAME_32("%cx", ecx),
0057 REG_OFFSET_NAME_32("%dx", edx),
0058 REG_OFFSET_NAME_32("%bx", ebx),
0059 REG_OFFSET_NAME_32("$stack", esp),
0060 REG_OFFSET_NAME_32("%bp", ebp),
0061 REG_OFFSET_NAME_32("%si", esi),
0062 REG_OFFSET_NAME_32("%di", edi),
0063 REG_OFFSET_END,
0064 };
0065
0066 #define regoffset_table x86_32_regoffset_table
0067 #else
0068 static const struct pt_regs_offset x86_64_regoffset_table[] = {
0069 REG_OFFSET_NAME_64("%ax", rax),
0070 REG_OFFSET_NAME_64("%dx", rdx),
0071 REG_OFFSET_NAME_64("%cx", rcx),
0072 REG_OFFSET_NAME_64("%bx", rbx),
0073 REG_OFFSET_NAME_64("%si", rsi),
0074 REG_OFFSET_NAME_64("%di", rdi),
0075 REG_OFFSET_NAME_64("%bp", rbp),
0076 REG_OFFSET_NAME_64("%sp", rsp),
0077 REG_OFFSET_NAME_64("%r8", r8),
0078 REG_OFFSET_NAME_64("%r9", r9),
0079 REG_OFFSET_NAME_64("%r10", r10),
0080 REG_OFFSET_NAME_64("%r11", r11),
0081 REG_OFFSET_NAME_64("%r12", r12),
0082 REG_OFFSET_NAME_64("%r13", r13),
0083 REG_OFFSET_NAME_64("%r14", r14),
0084 REG_OFFSET_NAME_64("%r15", r15),
0085 REG_OFFSET_END,
0086 };
0087
0088 #define regoffset_table x86_64_regoffset_table
0089 #endif
0090
0091
0092 #define ARCH_MAX_REGS ((sizeof(regoffset_table) / sizeof(regoffset_table[0])) - 1)
0093
0094
0095 const char *get_arch_regstr(unsigned int n)
0096 {
0097 return (n < ARCH_MAX_REGS) ? regoffset_table[n].name : NULL;
0098 }
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108 int regs_query_register_offset(const char *name)
0109 {
0110 const struct pt_regs_offset *roff;
0111 for (roff = regoffset_table; roff->name != NULL; roff++)
0112 if (!strcmp(roff->name, name))
0113 return roff->offset;
0114 return -EINVAL;
0115 }