ia64_cxx_abi.cpp
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 #include <abort.h>
23 #include <dwarf4.h>
24 #include <eh_frame.h>
25 #include <registers.h>
26 #include <ia64_cxx_abi.h>
27 
28 // -----------------------------------------------------------------------------
29 // Context
30 // -----------------------------------------------------------------------------
31 
32 struct _Unwind_Context
33 {
34  fd_entry fde;
35  register_state *state;
36  _Unwind_Exception *exception_object;
37 
38  _Unwind_Context(register_state *s, _Unwind_Exception *eo) :
39  state(s),
40  exception_object(eo)
41  {
42  }
43 };
44 
45 // -----------------------------------------------------------------------------
46 // Helpers
47 // -----------------------------------------------------------------------------
48 
50 private_personality(_Unwind_Action action, _Unwind_Context *context)
51 {
52  if (auto pl = context->fde.cie().personality_function())
53  {
54  if (auto pr = *(reinterpret_cast<__personality_routine *>(pl)))
55  {
56  return pr(1, action,
57  context->exception_object->exception_class,
58  context->exception_object, context);
59  }
60  }
61 
62  return _URC_CONTINUE_UNWIND;
63 }
64 
65 // -----------------------------------------------------------------------------
66 // Implementation
67 // -----------------------------------------------------------------------------
68 
70 find_and_store_fde(_Unwind_Context *context)
71 {
72  if (!(context->fde = eh_frame::find_fde(context->state)))
73  return _URC_END_OF_STACK;
74 
75  return _URC_CONTINUE_UNWIND;
76 }
77 
79 private_phase1(_Unwind_Context *context)
80 {
81  auto result = _URC_CONTINUE_UNWIND;
82 
83  result = find_and_store_fde(context);
84  if (result != _URC_CONTINUE_UNWIND)
85  return result;
86 
87  dwarf4::unwind(context->fde, context->state);
88 
89  while (true)
90  {
91  result = find_and_store_fde(context);
92  if (result != _URC_CONTINUE_UNWIND)
93  return result;
94 
95  switch (private_personality(_UA_SEARCH_PHASE, context))
96  {
97  case _URC_HANDLER_FOUND:
98  context->exception_object->private_1 = context->fde.pc_begin();
99  return _URC_NO_REASON;
100 
102  break;
103 
104  default:
105  ABORT("phase 1 personality routine failed");
106  }
107 
108  dwarf4::unwind(context->fde, context->state);
109  }
110 }
111 
112 static _Unwind_Reason_Code
113 private_phase2(_Unwind_Context *context)
114 {
115  auto result = _URC_CONTINUE_UNWIND;
116 
117  result = find_and_store_fde(context);
118  if (result != _URC_CONTINUE_UNWIND)
119  return result;
120 
121  dwarf4::unwind(context->fde, context->state);
122 
123  while (true)
124  {
125  auto action = _UA_CLEANUP_PHASE;
126 
127  result = find_and_store_fde(context);
128  if (result != _URC_CONTINUE_UNWIND)
129  return result;
130 
131  if (context->exception_object->private_1 == context->fde.pc_begin())
132  action |= _UA_HANDLER_FRAME;
133 
134  switch (private_personality(action, context))
135  {
137  context->state->resume(); __builtin_unreachable();
138 
140  break;
141 
142  default:
143  ABORT("phase 2 personality routine failed");
144  }
145 
146  dwarf4::unwind(context->fde, context->state);
147  }
148 }
149 
150 extern "C" _Unwind_Reason_Code
152 {
153  auto ret = _URC_END_OF_STACK;
154 
155  auto registers = registers_intel_x64_t();
156  __store_registers_intel_x64(&registers);
157 
158  exception_object->private_1 = 0;
159  exception_object->private_2 = 0;
160 
161  auto state = register_state_intel_x64(registers);
162  auto context = _Unwind_Context(&state, exception_object);
163 
164  ret = private_phase1(&context);
165  if (ret != _URC_NO_REASON)
166  return ret;
167 
168  state = register_state_intel_x64(registers);
169  context = _Unwind_Context(&state, exception_object);
170 
171  ret = private_phase2(&context);
172  if (ret != _URC_NO_REASON)
173  return ret;
174 
176 }
177 
178 extern "C" void
180 {
181  auto registers = registers_intel_x64_t();
182  __store_registers_intel_x64(&registers);
183 
184  auto state = register_state_intel_x64(registers);
185  auto context = _Unwind_Context(&state, exception_object);
186 
187  private_phase2(&context);
188 }
189 
190 extern "C" void
192 {
193  if (exception_object->exception_cleanup != nullptr)
195  exception_object);
196 }
197 
198 extern "C" uintptr_t
199 _Unwind_GetGR(_Unwind_Context *context, int index)
200 {
201  return context->state->get(static_cast<uint64_t>(index));
202 }
203 
204 extern "C" void
205 _Unwind_SetGR(_Unwind_Context *context, int index, uintptr_t value)
206 {
207  context->state->set(static_cast<uint64_t>(index), value);
208  context->state->commit();
209 }
210 
211 extern "C" uintptr_t
212 _Unwind_GetIP(_Unwind_Context *context)
213 {
214  return context->state->get_ip();
215 }
216 
217 extern "C" void
218 _Unwind_SetIP(_Unwind_Context *context, uintptr_t value)
219 {
220  context->state->set_ip(value);
221  context->state->commit();
222 }
223 
224 extern "C" uintptr_t
225 _Unwind_GetLanguageSpecificData(_Unwind_Context *context)
226 {
227  return context->fde.lsda();
228 }
229 
230 extern "C" uintptr_t
231 _Unwind_GetRegionStart(_Unwind_Context *context)
232 {
233  return context->fde.pc_begin();
234 }
235 
236 extern "C" uintptr_t
237 _Unwind_GetIPInfo(_Unwind_Context *context, int *ip_before_insn)
238 {
239  if (ip_before_insn == nullptr)
240  ABORT("ip_before_insn == 0");
241 
242  *ip_before_insn = 0;
243  return _Unwind_GetIP(context);
244 }
static void unwind(const fd_entry &fde, register_state *state=nullptr)
Definition: dwarf4.cpp:1668
void __store_registers_intel_x64(registers_intel_x64_t *state)
uintptr_t _Unwind_GetIP(_Unwind_Context *context)
#define ABORT(a)
Definition: abort.h:51
_Unwind_Exception_Cleanup_Fn exception_cleanup
Definition: ia64_cxx_abi.h:162
uintptr_t _Unwind_GetRegionStart(_Unwind_Context *context)
uintptr_t _Unwind_GetGR(_Unwind_Context *context, int index)
auto index(const T virt, const F from)
static fd_entry find_fde(register_state *state)
Definition: eh_frame.cpp:408
void _Unwind_SetIP(_Unwind_Context *context, uintptr_t value)
void _Unwind_SetGR(_Unwind_Context *context, int index, uintptr_t value)
_Unwind_Reason_Code
Definition: ia64_cxx_abi.h:87
void _Unwind_DeleteException(_Unwind_Exception *exception_object)
void _Unwind_Resume(_Unwind_Exception *exception_object)
uintptr_t _Unwind_GetIPInfo(_Unwind_Context *context, int *ip_before_insn)
int _Unwind_Action
Definition: ia64_cxx_abi.h:260
Definition: eh_frame.h:510
_Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception *exception_object)
uintptr_t _Unwind_GetLanguageSpecificData(_Unwind_Context *context)