The Pedigree Project  0.1
Backtrace.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/Backtrace.h"
21 #include "pedigree/kernel/Log.h"
22 #include "pedigree/kernel/debugger/DwarfUnwinder.h"
23 #include "pedigree/kernel/linker/KernelElf.h"
24 #include "pedigree/kernel/processor/Processor.h"
25 #include "pedigree/kernel/processor/ProcessorInformation.h"
26 #include "pedigree/kernel/processor/StackFrame.h"
27 #include "pedigree/kernel/processor/VirtualAddressSpace.h"
28 
29 extern uintptr_t start;
30 
31 Backtrace::Backtrace() : m_nStackFrames(0)
32 {
33 }
34 
35 Backtrace::~Backtrace()
36 {
37 }
38 
39 void Backtrace::performBacktrace(InterruptState &state)
40 {
41 #ifdef DWARF
42  // Firstly, can we perform a DWARF backtrace?
43  if (KernelElf::instance().debugFrameTable() >
44  0 /*&& g_pKernel->debugFrameTableLength() > 0*/)
45  {
46  performDwarfBacktrace(state);
47  return;
48  }
49 #else
50  WARNING_NOLOCK("Backtracer built without DWARF enabled.");
51 #endif
52  // Can we perform a "normal", base-pointer-linked-list backtrace?
53  // Don't lock on the log - we may have hit a backtrace because the Log lock
54  // deadlocked
55  WARNING_NOLOCK("Dwarf backtracing not available.");
56 #if defined(X86_COMMON) || defined(HOSTED)
57  performBpBacktrace(state.getBasePointer(), state.getInstructionPointer());
58 #elif defined(ARM_COMMON)
59  performArmBacktrace(state.getBasePointer(), state.getInstructionPointer());
60 #else
61  ERROR_NOLOCK("Backtrace: No backtracing method available!");
62 #endif
63 }
64 
65 void Backtrace::performDwarfBacktrace(InterruptState &state)
66 {
67  ProcessorState initial(state);
68  ProcessorState next;
69 
70  size_t i = 0;
71  DwarfUnwinder du(
72  KernelElf::instance().debugFrameTable(),
73  KernelElf::instance().debugFrameTableLength());
74  uintptr_t frameBase;
75  while (i < MAX_STACK_FRAMES)
76  {
77  if (!du.unwind(initial, next, frameBase))
78  {
79  m_pReturnAddresses[i++] = initial.getInstructionPointer();
80  break;
81  }
82 
83  m_pStates[i] = next;
84  m_pBasePointers[i] = frameBase;
85  // This may look strange but it's correct - the i'th instruction pointer
86  // is the (i-1)'th return address.
87  m_pReturnAddresses[i] = initial.getInstructionPointer();
88  initial = next;
89  i++;
90  }
91 
92  m_nStackFrames = i;
93 }
94 
95 void Backtrace::performBpBacktrace(uintptr_t base, uintptr_t instruction)
96 {
97  if (base == 0)
99  if (instruction == 0)
100  instruction = Processor::getInstructionPointer();
101 
102  size_t i = 1;
103  m_pBasePointers[0] = base;
104  m_pReturnAddresses[0] = instruction;
105 
106  while (i < MAX_STACK_FRAMES)
107  {
108  // Sanity check: would we fault by reading this address?
109  if (Processor::information().getVirtualAddressSpace().isMapped(
110  reinterpret_cast<void *>(base)) &&
111  Processor::information().getVirtualAddressSpace().isMapped(
112  reinterpret_cast<void *>(base + sizeof(uintptr_t))))
113  {
114  uintptr_t nextAddress = *reinterpret_cast<uintptr_t *>(base);
115 
116  m_pReturnAddresses[i] =
117  *reinterpret_cast<uintptr_t *>(base + sizeof(uintptr_t));
118  m_pBasePointers[i] = nextAddress;
119 
120  base = nextAddress;
121 
122  m_pStates[i].setBasePointer(m_pBasePointers[i]);
123  m_pStates[i].setInstructionPointer(m_pReturnAddresses[i]);
124 
125  i++;
126 
127  if (nextAddress == 0)
128  break;
129  }
130  else
131  {
132  break;
133  }
134  }
135 
136  m_nStackFrames = i;
137 }
138 
139 #ifdef ARM_COMMON
140 void Backtrace::performArmBacktrace(uintptr_t base, uintptr_t instruction)
141 {
142  if (base == 0)
143  base = Processor::getBasePointer();
144  if (instruction == 0)
145  instruction = Processor::getInstructionPointer();
146 
147  size_t i = 1;
148  m_pBasePointers[0] = base;
149  m_pReturnAddresses[0] = instruction;
150 
151  VirtualAddressSpace &va = Processor::information().getVirtualAddressSpace();
152 
153  while (i < MAX_STACK_FRAMES)
154  {
155  uintptr_t *nextFramePointer =
156  reinterpret_cast<uintptr_t *>(base - (3 * sizeof(uintptr_t)));
157  uintptr_t *returnAddressPointer =
158  reinterpret_cast<uintptr_t *>(base - sizeof(uintptr_t));
159 
160  // Sanity check: would we fault by reading this address?
161  if (va.isMapped(nextFramePointer) &&
162  (i && va.isMapped(returnAddressPointer)))
163  {
164  // EABI frame pointer layout:
165  // FP[-1] = lr (return address)
166  // FP[-3] = previous frame (fp)
167 
168  uintptr_t nextFrame = *nextFramePointer;
169  m_pReturnAddresses[i] = *returnAddressPointer;
170  m_pBasePointers[i] = nextFrame;
171  base = nextFrame;
172 
173  m_pStates[i].setBasePointer(m_pBasePointers[i]);
174  m_pStates[i].setInstructionPointer(m_pReturnAddresses[i]);
175 
176  i++;
177 
178  if (nextFrame == 0)
179  {
180  break;
181  }
182  }
183  else
184  {
185  break;
186  }
187  }
188 
189  m_nStackFrames = i;
190 }
191 #endif
192 
193 void Backtrace::prettyPrint(
194  HugeStaticString &buf, size_t nFrames, size_t nFromFrame)
195 {
196  if (nFrames == 0 || nFrames > m_nStackFrames)
197  nFrames = m_nStackFrames;
198  // What symbol are we in?
199  // TODO grep the memory map for the right ELF to look at.
200 
201  for (size_t i = nFromFrame; i < nFrames + nFromFrame; i++)
202  {
203  uintptr_t symStart = 0;
204 
205  HugeStaticString row;
206 
207  const char *pSym = KernelElf::instance().globalLookupSymbol(
208  m_pReturnAddresses[i], &symStart);
209  if (pSym == 0)
210  {
211  row += "[";
212  row.append(m_pReturnAddresses[i], 16);
213  row += "]\n";
214  }
215  else
216  {
217  LargeStaticString sym(pSym);
218 
219  row += "[";
220  row.append(m_pReturnAddresses[i], 16);
221  row += "] ";
222  StackFrame sf(m_pStates[i], m_pBasePointers[i], sym);
223 
224  sf.prettyPrint(row);
225  }
226 
227  buf.append(row);
228  }
229 }
230 
232 {
233  return m_nStackFrames;
234 }
235 
236 uintptr_t Backtrace::getReturnAddress(size_t n)
237 {
238  // ASSERT(n < m_nStackFrames);
239  return m_pReturnAddresses[n];
240 }
241 
242 uintptr_t Backtrace::getBasePointer(size_t n)
243 {
244  // ASSERT(n < m_nStackFrames);
245  return m_pBasePointers[n];
246 }
bool unwind(const ProcessorState &inState, ProcessorState &outState, uintptr_t &frameBase)
uintptr_t m_pBasePointers[MAX_STACK_FRAMES]
Definition: Backtrace.h:92
virtual bool isMapped(void *virtualAddress)=0
static ProcessorInformation & information()
Definition: Processor.cc:45
static KernelElf & instance()
Definition: KernelElf.h:129
uintptr_t getBasePointer(size_t n)
Definition: Backtrace.cc:242
size_t m_nStackFrames
Definition: Backtrace.h:102
uintptr_t m_pReturnAddresses[MAX_STACK_FRAMES]
Definition: Backtrace.h:88
void performDwarfBacktrace(InterruptState &state)
Definition: Backtrace.cc:65
void performBacktrace(InterruptState &state)
Definition: Backtrace.cc:39
uintptr_t globalLookupSymbol(const char *pName)
Definition: KernelElf.cc:1031
void performBpBacktrace(uintptr_t base, uintptr_t instruction)
Definition: Backtrace.cc:95
static uintptr_t getInstructionPointer()
ProcessorState m_pStates[MAX_STACK_FRAMES]
Definition: Backtrace.h:97
uintptr_t getReturnAddress(size_t n)
Definition: Backtrace.cc:236
size_t numStackFrames()
Definition: Backtrace.cc:231
static uintptr_t getBasePointer()