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/Log.h"
21#include "pedigree/kernel/debugger/DwarfCfiAutomaton.h"
22#include "pedigree/kernel/debugger/DwarfUnwinder.h"
23
25 : m_InitialState(),
26 m_CurrentState(),
27 m_nCodeAlignmentFactor(),
28 m_nDataAlignmentFactor(),
29 m_nStartingPc() {}
30
32
33void DwarfCfiAutomaton::initialise(const DwarfState& startingState, uintptr_t nCodeLocation,
34 size_t nCodeLen, int32_t nCodeAlignmentFactor,
35 int32_t nDataAlignmentFactor, uintptr_t nStartingPc) {
36 // NOTICE("CfiAutomaton starting up at PC=" << Hex << nStartingPc);
37 m_nCodeAlignmentFactor = nCodeAlignmentFactor;
38 m_nDataAlignmentFactor = nDataAlignmentFactor;
39 m_nStartingPc = nStartingPc;
40
41 // Set up our states, initially.
42 m_InitialState = startingState;
43 m_CurrentState = startingState;
44
45 // Execute the preamble instructions.
46 execute(nCodeLocation, nCodeLen, static_cast<uintptr_t>(~0));
47
48 // Save the state.
50}
51
52DwarfState* DwarfCfiAutomaton::execute(uintptr_t nCodeLocation, size_t nCodeLen,
53 uintptr_t nBreakAt) {
54 uintptr_t nCurrentCodeLocation = nCodeLocation;
55 uintptr_t nProgramCounter = m_nStartingPc;
56 while ((nCurrentCodeLocation < nCodeLocation + nCodeLen) && (nProgramCounter <= nBreakAt)) {
57 executeInstruction(nCurrentCodeLocation, nProgramCounter);
58 }
59 // If we reached the end of the instruction stream, this state just
60 // continues.
61 return &m_CurrentState;
62}
63
64void DwarfCfiAutomaton::executeInstruction(uintptr_t& nLocation, uintptr_t& nPc) {
65 uint8_t* pLocation = reinterpret_cast<uint8_t*>(nLocation);
66 nLocation++; // nLocation will always increase by at least one.
67
68 if ((pLocation[0] & 0xc0) == DW_CFA_advance_loc) {
69 uint8_t nDelta = pLocation[0] & 0x3f;
70 nPc += nDelta * m_nCodeAlignmentFactor;
71 // NOTICE("DW_CFA_advance_loc (" << Hex << nDelta << ")");
72 } else if ((pLocation[0] & 0xc0) == DW_CFA_offset) {
73 uint8_t nRegister = pLocation[0] & 0x3f;
74 uint32_t nLocationOffset = 0;
75 pLocation = reinterpret_cast<uint8_t*>(nLocation);
76 int32_t nOffset =
77 static_cast<int32_t>(DwarfUnwinder::decodeUleb128(pLocation, nLocationOffset));
78 nLocation += nLocationOffset;
79 m_CurrentState.m_RegisterStates[nRegister] = DwarfState::Offset;
80 m_CurrentState.m_R[nRegister] = nOffset * m_nDataAlignmentFactor;
81 // NOTICE("DW_CFA_offset (r" << Dec << nRegister << ", " << Hex <<
82 // nOffset * m_nDataAlignmentFactor << ")");
83 } else if ((pLocation[0] & 0xc0) == DW_CFA_restore) {
84 // WARNING("DW_CFA_restore not implemented!");
85 } else
86 switch (pLocation[0]) {
87 case DW_CFA_nop: {
88 // NOTICE("DW_CFA_nop");
89 break;
90 }
91 case DW_CFA_set_loc: {
92 processor_register_t* pAddress = reinterpret_cast<processor_register_t*>(nLocation);
93 nPc = *pAddress;
94 nLocation += sizeof(processor_register_t);
95 // NOTICE("DW_CFA_set_loc (" << Hex << nPc << ")");
96 break;
97 }
98 case DW_CFA_advance_loc1: {
99 uint8_t nDelta = *reinterpret_cast<uint8_t*>(nLocation);
100 nLocation += 1;
101 nPc += nDelta * m_nCodeAlignmentFactor;
102 // NOTICE("DW_CFA_advance_loc1 (" << Hex << nDelta <<
103 // ")");
104 break;
105 }
106 case DW_CFA_advance_loc2: {
107 uint16_t nDelta = *reinterpret_cast<uint16_t*>(nLocation);
108 nLocation += 2;
109 nPc += nDelta * m_nCodeAlignmentFactor;
110 // NOTICE("DW_CFA_advance_loc2 (" << Hex << nDelta <<
111 // ")");
112 break;
113 }
114 case DW_CFA_advance_loc4: {
115 uint32_t nDelta = *reinterpret_cast<uint32_t*>(nLocation);
116 nLocation += 4;
117 nPc += nDelta * m_nCodeAlignmentFactor;
118 // NOTICE("DW_CFA_advance_loc4 (" << Hex << nDelta <<
119 // ")");
120 break;
121 }
122 // case DW_CFA_offset_extended:
123 // {
124 // }
125 // case DW_CFA_restore_extended:
126 // {
127 // }
128 // case DW_CFA_undefined:
129 // {
130 // }
131 // case DW_CFA_same_value:
132 // {
133 // }
134 // case DW_CFA_register:
135 // {
136 // }
137 // case DW_CFA_remember_state:
138 // {
139 // }
140 // case DW_CFA_restore_state:
141 // {
142 // }
143 case DW_CFA_def_cfa: {
144 uint32_t nOffset = 0;
145 pLocation = reinterpret_cast<uint8_t*>(nLocation);
146 m_CurrentState.m_CfaState = DwarfState::ValOffset;
148 m_CurrentState.m_CfaOffset =
149 static_cast<ssize_t>(DwarfUnwinder::decodeUleb128(pLocation, nOffset));
150 nLocation += nOffset;
151 // NOTICE("DW_CFA_def_cfa (" << Hex <<
152 // m_CurrentState.m_CfaRegister << ", " <<
153 // m_CurrentState.m_CfaOffset << ")");
154 break;
155 }
156 case DW_CFA_def_cfa_register: {
157 uint32_t nOffset = 0;
158 pLocation = reinterpret_cast<uint8_t*>(nLocation);
160 nLocation += nOffset;
161 // NOTICE("DW_CFA_def_cfa_reg (" << Hex <<
162 // m_CurrentState.m_CfaRegister << ")");
163 break;
164 }
165 case DW_CFA_def_cfa_offset: {
166 uint32_t nOffset = 0;
167 pLocation = reinterpret_cast<uint8_t*>(nLocation);
168 m_CurrentState.m_CfaOffset =
169 static_cast<ssize_t>(DwarfUnwinder::decodeUleb128(pLocation, nOffset));
170 nLocation += nOffset;
171 // NOTICE("DW_CFA_def_cfa_offset (" << Hex <<
172 // m_CurrentState.m_CfaOffset << ")");
173 break;
174 }
175 // case DW_CFA_def_cfa_expression:
176 // {
177 // }
178 // case DW_CFA_expression:
179 // {
180 // }
181 case DW_CFA_offset_extended_sf: {
182 uint32_t nLocationOffset = 0;
183 pLocation = reinterpret_cast<uint8_t*>(nLocation);
184 uint32_t nRegister = DwarfUnwinder::decodeUleb128(pLocation, nLocationOffset);
185 nLocation += nLocationOffset;
186
187 nLocationOffset = 0;
188 pLocation = reinterpret_cast<uint8_t*>(nLocation);
189 int32_t nOffset = DwarfUnwinder::decodeSleb128(pLocation, nLocationOffset);
190
191 nLocation += nLocationOffset;
192
193 m_CurrentState.m_RegisterStates[nRegister] = DwarfState::Offset;
194 m_CurrentState.m_R[nRegister] = nOffset * m_nDataAlignmentFactor;
195 // NOTICE("DW_CFA_offset_extended_sf (r" << Dec <<
196 // nRegister << ", " << Hex << nOffset *
197 // m_nDataAlignmentFactor << ")");
198 break;
199 }
200 // case DW_CFA_def_cfa_sf:
201 // {
202 // }
203 // case DW_CFA_def_cfa_offset_sf:
204 // {
205 // }
206 // case DW_CFA_val_offset:
207 // {
208 // }
209 // case DW_CFA_val_offset_sf:
210 // {
211 // }
212 // case DW_CFA_val_expression:
213 // {
214 // }
215 // case DW_CFA_lo_user:
216 // {
217 // }
218 // case DW_CFA_hi_user:
219 // {
220 // }
221 case DW_CFA_GNU_args_size: {
222 uint32_t nLocationOffset = 0;
223 pLocation = reinterpret_cast<uint8_t*>(nLocation);
224 DwarfUnwinder::decodeUleb128(pLocation, nLocationOffset);
225 nLocation += nLocationOffset;
226 break;
227 }
228 default:
229 ERROR("Unrecognised DWARF CFA instruction: " << Hex << pLocation[0]);
230 nPc++;
231 }
232}
void executeInstruction(uintptr_t &nLocation, uintptr_t &nPc)
void initialise(const DwarfState &startingState, uintptr_t nCodeLocation, size_t nCodeLen, int32_t nCodeAlignmentFactor, int32_t nDataAlignmentFactor, uintptr_t nStartingPc)
DwarfState * execute(uintptr_t nCodeLocation, size_t nCodeLen, uintptr_t nBreakAt)
processor_register_t m_R[DWARF_MAX_REGISTERS]
Definition DwarfState.h:202
RegisterState m_RegisterStates[DWARF_MAX_REGISTERS]
Definition DwarfState.h:197
RegisterState m_CfaState
Definition DwarfState.h:208
uint32_t m_CfaRegister
Definition DwarfState.h:212
static uint32_t decodeUleb128(uint8_t *pBase, uint32_t &nOffset)
static int32_t decodeSleb128(uint8_t *pBase, uint32_t &nOffset)
@ Hex
Definition Log.h:124