registers_intel_x64.h
Go to the documentation of this file.
1 //
2 // Bareflank Unwind Library
3 //
4 // Copyright (C) 2015 Assured Information Security, Inc.
5 // Author: Rian Quinn <quinnr@ainfosec.com>
6 // Author: Brendan Kerrigan <kerriganb@ainfosec.com>
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2.1 of the License, or (at your option) any later version.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 
22 #ifndef REGISTERS_INTEL_X64_H
23 #define REGISTERS_INTEL_X64_H
24 
25 #include <log.h>
26 #include <abort.h>
27 #include <registers.h>
28 
29 #if (MAX_NUM_REGISTERS < 17)
30 #error MAX_NUM_REGISTERS was set too low
31 #endif
32 
33 // -----------------------------------------------------------------------------
34 // Load / Store Registers
35 // -----------------------------------------------------------------------------
36 
38 {
39  uint64_t rax;
40  uint64_t rdx;
41  uint64_t rcx;
42  uint64_t rbx;
43  uint64_t rdi;
44  uint64_t rsi;
45  uint64_t rbp;
46  uint64_t rsp;
47  uint64_t r08;
48  uint64_t r09;
49  uint64_t r10;
50  uint64_t r11;
51  uint64_t r12;
52  uint64_t r13;
53  uint64_t r14;
54  uint64_t r15;
55  uint64_t rip;
56 };
57 
65 extern "C"
67 
75 extern "C"
77 
78 // -----------------------------------------------------------------------------
79 // Register State
80 // -----------------------------------------------------------------------------
81 //
82 // Defines the register state for x86_64. The only unexpected thing here is
83 // the System V 64bit ABI defines the register order as rax, rdx, rcx, rbx, and
84 // not rax, rbx, rcx, rdx. This makes a really big difference because the
85 // reg(1) used by the personality function is stored in rdx as a result.
86 //
87 // See register.h for more information
88 //
89 
91 {
92 public:
94  m_registers(registers),
95  m_tmp_registers(registers)
96 
97  { }
98 
99  ~register_state_intel_x64() override = default;
100 
103 
105  register_state_intel_x64 &operator=(const register_state_intel_x64 &) = default;
106 
107  uint64_t get_ip() const override
108  { return m_registers.rip; }
109 
110  register_state &set_ip(uint64_t value) override
111  {
112  m_tmp_registers.rip = value;
113  return *this;
114  }
115 
116  uint64_t get(uint64_t index) const override
117  {
118  if (index >= max_num_registers())
119  ABORT("register index out of bounds");
120 
121  return reinterpret_cast<const uint64_t *>(&m_registers)[index];
122  }
123 
124  register_state &set(uint64_t index, uint64_t value) override
125  {
126  if (index >= max_num_registers())
127  ABORT("register index out of bounds");
128 
129  reinterpret_cast<uint64_t *>(&m_tmp_registers)[index] = value;
130 
131  return *this;
132  }
133 
134  void commit() override
135  { m_registers = m_tmp_registers; }
136 
137  void commit(uint64_t cfa) override
138  {
139  m_tmp_registers.rsp = cfa;
140  commit();
141  }
142 
143  void resume() override
144  { __load_registers_intel_x64(&m_registers); }
145 
146  uint64_t max_num_registers() const override
147  { return 17; }
148 
149  const char *name(uint64_t index) const override
150  {
151  if (index >= max_num_registers())
152  ABORT("register index out of bounds");
153 
154  switch (index)
155  {
156  case 0x00: return "rax";
157  case 0x01: return "rdx";
158  case 0x02: return "rcx";
159  case 0x03: return "rbx";
160  case 0x04: return "rdi";
161  case 0x05: return "rsi";
162  case 0x06: return "rbp";
163  case 0x07: return "rsp";
164  case 0x08: return "r08";
165  case 0x09: return "r09";
166  case 0x0A: return "r10";
167  case 0x0B: return "r11";
168  case 0x0C: return "r12";
169  case 0x0D: return "r13";
170  case 0x0E: return "r14";
171  case 0x0F: return "r15";
172  case 0x10: return "rip";
173  default: return "";
174  }
175  }
176 
177  void dump() const override
178  {
179  log("Register State:\n")
180  log(" rax: 0x%08lx\n", m_registers.rax);
181  log(" rdx: 0x%08lx\n", m_registers.rdx);
182  log(" rcx: 0x%08lx\n", m_registers.rcx);
183  log(" rbx: 0x%08lx\n", m_registers.rbx);
184  log(" rdi: 0x%08lx\n", m_registers.rdi);
185  log(" rsi: 0x%08lx\n", m_registers.rsi);
186  log(" rbp: 0x%08lx\n", m_registers.rbp);
187  log(" rsp: 0x%08lx\n", m_registers.rsp);
188  log(" r08: 0x%08lx\n", m_registers.r08);
189  log(" r09: 0x%08lx\n", m_registers.r09);
190  log(" r10: 0x%08lx\n", m_registers.r10);
191  log(" r11: 0x%08lx\n", m_registers.r11);
192  log(" r12: 0x%08lx\n", m_registers.r12);
193  log(" r13: 0x%08lx\n", m_registers.r13);
194  log(" r14: 0x%08lx\n", m_registers.r14);
195  log(" r15: 0x%08lx\n", m_registers.r15);
196  log(" rip: 0x%08lx\n", m_registers.rip);
197  log("\n")
198  }
199 
200 private:
201  registers_intel_x64_t m_registers;
202  registers_intel_x64_t m_tmp_registers;
203 };
204 
205 #endif
void dump() const override
void __store_registers_intel_x64(registers_intel_x64_t *state)
~register_state_intel_x64() override=default
register_state_intel_x64(const registers_intel_x64_t &registers)
#define ABORT(a)
Definition: abort.h:51
uint64_t max_num_registers() const override
void uint64_t uint64_t uint64_t *rdx noexcept
void __load_registers_intel_x64(registers_intel_x64_t *state)
auto index(const T virt, const F from)
void commit(uint64_t cfa) override
uint64_t get_ip() const override
register_state & set_ip(uint64_t value) override
#define log(...)
Definition: log.h:32
const char * name(uint64_t index) const override