The Pedigree Project  0.1
DwarfCfiAutomaton.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "pedigree/kernel/debugger/DwarfCfiAutomaton.h"
21 #include "pedigree/kernel/Log.h"
22 #include "pedigree/kernel/debugger/DwarfUnwinder.h"
23 
25  : m_InitialState(), m_CurrentState(), m_nCodeAlignmentFactor(),
26  m_nDataAlignmentFactor(), m_nStartingPc()
27 {
28 }
29 
31 {
32 }
33 
35  const DwarfState &startingState, uintptr_t nCodeLocation, size_t nCodeLen,
36  int32_t nCodeAlignmentFactor, int32_t nDataAlignmentFactor,
37  uintptr_t nStartingPc)
38 {
39  // NOTICE("CfiAutomaton starting up at PC=" << Hex << nStartingPc);
40  m_nCodeAlignmentFactor = nCodeAlignmentFactor;
41  m_nDataAlignmentFactor = nDataAlignmentFactor;
42  m_nStartingPc = nStartingPc;
43 
44  // Set up our states, initially.
45  m_InitialState = startingState;
46  m_CurrentState = startingState;
47 
48  // Execute the preamble instructions.
49  execute(nCodeLocation, nCodeLen, static_cast<uintptr_t>(~0));
50 
51  // Save the state.
53 }
54 
56  uintptr_t nCodeLocation, size_t nCodeLen, uintptr_t nBreakAt)
57 {
58  uintptr_t nCurrentCodeLocation = nCodeLocation;
59  uintptr_t nProgramCounter = m_nStartingPc;
60  while ((nCurrentCodeLocation < nCodeLocation + nCodeLen) &&
61  (nProgramCounter <= nBreakAt))
62  {
63  executeInstruction(nCurrentCodeLocation, nProgramCounter);
64  }
65  // If we reached the end of the instruction stream, this state just
66  // continues.
67  return &m_CurrentState;
68 }
69 
70 void DwarfCfiAutomaton::executeInstruction(uintptr_t &nLocation, uintptr_t &nPc)
71 {
72  uint8_t *pLocation = reinterpret_cast<uint8_t *>(nLocation);
73  nLocation++; // nLocation will always increase by at least one.
74 
75  if ((pLocation[0] & 0xc0) == DW_CFA_advance_loc)
76  {
77  uint8_t nDelta = pLocation[0] & 0x3f;
78  nPc += nDelta * m_nCodeAlignmentFactor;
79  // NOTICE("DW_CFA_advance_loc (" << Hex << nDelta << ")");
80  }
81  else if ((pLocation[0] & 0xc0) == DW_CFA_offset)
82  {
83  uint8_t nRegister = pLocation[0] & 0x3f;
84  uint32_t nLocationOffset = 0;
85  pLocation = reinterpret_cast<uint8_t *>(nLocation);
86  int32_t nOffset = static_cast<int32_t>(
87  DwarfUnwinder::decodeUleb128(pLocation, nLocationOffset));
88  nLocation += nLocationOffset;
89  m_CurrentState.m_RegisterStates[nRegister] = DwarfState::Offset;
90  m_CurrentState.m_R[nRegister] = nOffset * m_nDataAlignmentFactor;
91  // NOTICE("DW_CFA_offset (r" << Dec << nRegister << ", " << Hex <<
92  // nOffset * m_nDataAlignmentFactor << ")");
93  }
94  else if ((pLocation[0] & 0xc0) == DW_CFA_restore)
95  {
96  // WARNING("DW_CFA_restore not implemented!");
97  }
98  else
99  switch (pLocation[0])
100  {
101  case DW_CFA_nop:
102  {
103  // NOTICE("DW_CFA_nop");
104  break;
105  }
106  case DW_CFA_set_loc:
107  {
108  processor_register_t *pAddress =
109  reinterpret_cast<processor_register_t *>(nLocation);
110  nPc = *pAddress;
111  nLocation += sizeof(processor_register_t);
112  // NOTICE("DW_CFA_set_loc (" << Hex << nPc << ")");
113  break;
114  }
115  case DW_CFA_advance_loc1:
116  {
117  uint8_t nDelta = *reinterpret_cast<uint8_t *>(nLocation);
118  nLocation += 1;
119  nPc += nDelta * m_nCodeAlignmentFactor;
120  // NOTICE("DW_CFA_advance_loc1 (" << Hex << nDelta <<
121  // ")");
122  break;
123  }
124  case DW_CFA_advance_loc2:
125  {
126  uint16_t nDelta = *reinterpret_cast<uint16_t *>(nLocation);
127  nLocation += 2;
128  nPc += nDelta * m_nCodeAlignmentFactor;
129  // NOTICE("DW_CFA_advance_loc2 (" << Hex << nDelta <<
130  // ")");
131  break;
132  }
133  case DW_CFA_advance_loc4:
134  {
135  uint32_t nDelta = *reinterpret_cast<uint32_t *>(nLocation);
136  nLocation += 4;
137  nPc += nDelta * m_nCodeAlignmentFactor;
138  // NOTICE("DW_CFA_advance_loc4 (" << Hex << nDelta <<
139  // ")");
140  break;
141  }
142  // case DW_CFA_offset_extended:
143  // {
144  // }
145  // case DW_CFA_restore_extended:
146  // {
147  // }
148  // case DW_CFA_undefined:
149  // {
150  // }
151  // case DW_CFA_same_value:
152  // {
153  // }
154  // case DW_CFA_register:
155  // {
156  // }
157  // case DW_CFA_remember_state:
158  // {
159  // }
160  // case DW_CFA_restore_state:
161  // {
162  // }
163  case DW_CFA_def_cfa:
164  {
165  uint32_t nOffset = 0;
166  pLocation = reinterpret_cast<uint8_t *>(nLocation);
167  m_CurrentState.m_CfaState = DwarfState::ValOffset;
169  DwarfUnwinder::decodeUleb128(pLocation, nOffset);
170  m_CurrentState.m_CfaOffset = static_cast<ssize_t>(
171  DwarfUnwinder::decodeUleb128(pLocation, nOffset));
172  nLocation += nOffset;
173  // NOTICE("DW_CFA_def_cfa (" << Hex <<
174  // m_CurrentState.m_CfaRegister << ", " <<
175  // m_CurrentState.m_CfaOffset << ")");
176  break;
177  }
178  case DW_CFA_def_cfa_register:
179  {
180  uint32_t nOffset = 0;
181  pLocation = reinterpret_cast<uint8_t *>(nLocation);
183  DwarfUnwinder::decodeUleb128(pLocation, nOffset);
184  nLocation += nOffset;
185  // NOTICE("DW_CFA_def_cfa_reg (" << Hex <<
186  // m_CurrentState.m_CfaRegister << ")");
187  break;
188  }
189  case DW_CFA_def_cfa_offset:
190  {
191  uint32_t nOffset = 0;
192  pLocation = reinterpret_cast<uint8_t *>(nLocation);
193  m_CurrentState.m_CfaOffset = static_cast<ssize_t>(
194  DwarfUnwinder::decodeUleb128(pLocation, nOffset));
195  nLocation += nOffset;
196  // NOTICE("DW_CFA_def_cfa_offset (" << Hex <<
197  // m_CurrentState.m_CfaOffset << ")");
198  break;
199  }
200  // case DW_CFA_def_cfa_expression:
201  // {
202  // }
203  // case DW_CFA_expression:
204  // {
205  // }
206  case DW_CFA_offset_extended_sf:
207  {
208  uint32_t nLocationOffset = 0;
209  pLocation = reinterpret_cast<uint8_t *>(nLocation);
210  uint32_t nRegister =
211  DwarfUnwinder::decodeUleb128(pLocation, nLocationOffset);
212  nLocation += nLocationOffset;
213 
214  nLocationOffset = 0;
215  pLocation = reinterpret_cast<uint8_t *>(nLocation);
216  int32_t nOffset =
217  DwarfUnwinder::decodeSleb128(pLocation, nLocationOffset);
218 
219  nLocation += nLocationOffset;
220 
221  m_CurrentState.m_RegisterStates[nRegister] = DwarfState::Offset;
222  m_CurrentState.m_R[nRegister] =
223  nOffset * m_nDataAlignmentFactor;
224  // NOTICE("DW_CFA_offset_extended_sf (r" << Dec <<
225  // nRegister << ", " << Hex << nOffset *
226  // m_nDataAlignmentFactor << ")");
227  break;
228  }
229  // case DW_CFA_def_cfa_sf:
230  // {
231  // }
232  // case DW_CFA_def_cfa_offset_sf:
233  // {
234  // }
235  // case DW_CFA_val_offset:
236  // {
237  // }
238  // case DW_CFA_val_offset_sf:
239  // {
240  // }
241  // case DW_CFA_val_expression:
242  // {
243  // }
244  // case DW_CFA_lo_user:
245  // {
246  // }
247  // case DW_CFA_hi_user:
248  // {
249  // }
250  case DW_CFA_GNU_args_size:
251  {
252  uint32_t nLocationOffset = 0;
253  pLocation = reinterpret_cast<uint8_t *>(nLocation);
254  DwarfUnwinder::decodeUleb128(pLocation, nLocationOffset);
255  nLocation += nLocationOffset;
256  break;
257  }
258  default:
259  ERROR(
260  "Unrecognised DWARF CFA instruction: " << Hex
261  << pLocation[0]);
262  nPc++;
263  }
264 }
uint32_t m_CfaRegister
Definition: DwarfState.h:316
RegisterState m_RegisterStates[DWARF_MAX_REGISTERS]
Definition: DwarfState.h:301
static int32_t decodeSleb128(uint8_t *pBase, uint32_t &nOffset)
void initialise(const DwarfState &startingState, uintptr_t nCodeLocation, size_t nCodeLen, int32_t nCodeAlignmentFactor, int32_t nDataAlignmentFactor, uintptr_t nStartingPc)
RegisterState m_CfaState
Definition: DwarfState.h:312
Definition: Log.h:136
static uint32_t decodeUleb128(uint8_t *pBase, uint32_t &nOffset)
processor_register_t m_R[DWARF_MAX_REGISTERS]
Definition: DwarfState.h:306
DwarfState * execute(uintptr_t nCodeLocation, size_t nCodeLen, uintptr_t nBreakAt)
#define ERROR(text)
Definition: Log.h:82
void executeInstruction(uintptr_t &nLocation, uintptr_t &nPc)