1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5// ==++==
6//
7
8//
9// ==--==
10#ifndef __disasm_h__
11#define __disasm_h__
12
13#include "sos_stacktrace.h"
14
15struct InfoHdr;
16class GCDump;
17
18
19struct DumpStackFlag
20{
21 BOOL fEEonly;
22 BOOL fSuppressSrcInfo;
23 DWORD_PTR top;
24 DWORD_PTR end;
25};
26
27struct GCEncodingInfo
28{
29 LPVOID pvMainFiber;
30 LPVOID pvGCTableFiber;
31
32 BYTE *table;
33 unsigned int methodSize;
34
35 char buf[1000];
36 int cch;
37
38 SIZE_T ofs;
39
40 // When decoding a cold region, set this to the size of the hot region to keep offset
41 // calculations working.
42 SIZE_T hotSizeToAdd;
43 bool fDoneDecoding;
44};
45
46// Returns:
47// NULL if the EHInfo passed in does not refer to a Typed clause
48// "..." if pEHInfo->isCatchAllHandler is TRUE
49// "TypeName" if pEHInfo is a DACEHInfo* that references type "TypeName".
50// Note:
51// The return is a pointer to a global buffer, therefore this value must
52// be consumed as soon as possible after a call to this function.
53LPCWSTR EHTypedClauseTypeName(const DACEHInfo* pEHInfo);
54
55struct SOSEHInfo
56{
57 DACEHInfo *m_pInfos;
58 UINT EHCount;
59 CLRDATA_ADDRESS methodStart;
60
61 SOSEHInfo() { ZeroMemory(this, sizeof(SOSEHInfo)); }
62 ~SOSEHInfo() { if (m_pInfos) { delete [] m_pInfos; } }
63
64 void FormatForDisassembly(CLRDATA_ADDRESS offSet);
65};
66
67BOOL IsClonedFinally(DACEHInfo *pEHInfo);
68
69void DumpStackWorker (DumpStackFlag &DSFlag);
70
71void UnassemblyUnmanaged (DWORD_PTR IP, BOOL bSuppressLines);
72
73HRESULT CheckEEDll ();
74
75BOOL GetCalleeSite (DWORD_PTR IP, DWORD_PTR &IPCallee);
76
77void DisasmAndClean (DWORD_PTR &IP, __out_ecount_opt(length) char *line, ULONG length);
78
79INT_PTR GetValueFromExpr(___in __in_z char *ptr, INT_PTR &value);
80
81void NextTerm (__deref_inout_z char *& ptr);
82
83BOOL IsByRef (__deref_inout_z char *& ptr);
84
85BOOL IsTermSep (char ch);
86
87const char * HelperFuncName (size_t IP);
88
89enum eTargetType { ettUnk = 0, ettNative = 1, ettJitHelp = 2, ettStub = 3, ettMD = 4 };
90
91// GetFinalTarget is based on HandleCall, but avoids printing anything to the output.
92// This is currently only called on x64
93eTargetType GetFinalTarget(DWORD_PTR callee, DWORD_PTR* finalMDorIP);
94
95#ifdef _MSC_VER
96// SOS is essentially single-threaded. ignore "construction of local static object is not thread-safe"
97#pragma warning(push)
98#pragma warning(disable:4640)
99#endif // _MSC_VER
100
101//-----------------------------------------------------------------------------------------
102//
103// Implementations for the supported target platforms
104//
105//-----------------------------------------------------------------------------------------
106
107#ifndef THUMB_CODE
108#define THUMB_CODE 1
109#endif
110#define STACKWALK_CONTROLPC_ADJUST_OFFSET 2
111
112#ifdef SOS_TARGET_X86
113
114/// X86 Machine specific code
115class X86Machine : public IMachine
116{
117public:
118 typedef X86_CONTEXT TGT_CTXT;
119
120 static IMachine* GetInstance()
121 { static X86Machine s_X86MachineInstance; return &s_X86MachineInstance; }
122
123 ULONG GetPlatform() const { return IMAGE_FILE_MACHINE_I386; }
124 ULONG GetContextSize() const { return sizeof(X86_CONTEXT); }
125 virtual void Unassembly(
126 TADDR IPBegin,
127 TADDR IPEnd,
128 TADDR IPAskedFor,
129 TADDR GCStressCodeCopy,
130 GCEncodingInfo * pGCEncodingInfo,
131 SOSEHInfo *pEHInfo,
132 BOOL bSuppressLines,
133 BOOL bDisplayOffsets) const;
134 virtual void IsReturnAddress(
135 TADDR retAddr,
136 TADDR* whereCalled) const;
137 virtual BOOL GetExceptionContext (
138 TADDR stack,
139 TADDR PC,
140 TADDR *cxrAddr,
141 CROSS_PLATFORM_CONTEXT * cxr,
142 TADDR * exrAddr,
143 PEXCEPTION_RECORD exr) const;
144
145 // retrieve stack pointer, frame pointer, and instruction pointer from the target context
146 virtual TADDR GetSP(const CROSS_PLATFORM_CONTEXT & ctx) const { return ctx.X86Context.Esp; }
147 virtual TADDR GetBP(const CROSS_PLATFORM_CONTEXT & ctx) const { return ctx.X86Context.Ebp; }
148 virtual TADDR GetIP(const CROSS_PLATFORM_CONTEXT & ctx) const { return ctx.X86Context.Eip; }
149
150 virtual void FillSimpleContext(StackTrace_SimpleContext * dest, LPVOID srcCtx) const;
151 virtual void FillTargetContext(LPVOID destCtx, LPVOID srcCtx, int idx = 0) const;
152
153 virtual LPCSTR GetDumpStackHeading() const { return s_DumpStackHeading; }
154 virtual LPCSTR GetDumpStackObjectsHeading() const { return s_DSOHeading; }
155 virtual LPCSTR GetSPName() const { return s_SPName; }
156 virtual void GetGCRegisters(LPCSTR** regNames, unsigned int* cntRegs) const
157 { _ASSERTE(cntRegs != NULL); *regNames = s_GCRegs; *cntRegs = _countof(s_GCRegs); }
158
159 virtual void DumpGCInfo(GCInfoToken gcInfoToken, unsigned methodSize, printfFtn gcPrintf, bool encBytes, bool bPrintHeader) const;
160
161private:
162 X86Machine() {}
163 ~X86Machine() {}
164 X86Machine(const X86Machine& machine); // undefined
165 X86Machine & operator=(const X86Machine&); // undefined
166
167private:
168 static LPCSTR s_DumpStackHeading;
169 static LPCSTR s_DSOHeading;
170 static LPCSTR s_GCRegs[7];
171 static LPCSTR s_SPName;
172}; // class X86Machine
173
174#endif // SOS_TARGET_X86
175
176
177#ifdef SOS_TARGET_ARM
178
179/// ARM Machine specific code
180class ARMMachine : public IMachine
181{
182public:
183 typedef ARM_CONTEXT TGT_CTXT;
184
185 static IMachine* GetInstance()
186 { return &s_ARMMachineInstance; }
187
188 ULONG GetPlatform() const { return IMAGE_FILE_MACHINE_ARMNT; }
189 ULONG GetContextSize() const { return sizeof(ARM_CONTEXT); }
190 virtual void Unassembly(
191 TADDR IPBegin,
192 TADDR IPEnd,
193 TADDR IPAskedFor,
194 TADDR GCStressCodeCopy,
195 GCEncodingInfo *pGCEncodingInfo,
196 SOSEHInfo *pEHInfo,
197 BOOL bSuppressLines,
198 BOOL bDisplayOffsets) const;
199 virtual void IsReturnAddress(
200 TADDR retAddr,
201 TADDR* whereCalled) const;
202 virtual BOOL GetExceptionContext (
203 TADDR stack,
204 TADDR PC,
205 TADDR *cxrAddr,
206 CROSS_PLATFORM_CONTEXT * cxr,
207 TADDR *exrAddr,
208 PEXCEPTION_RECORD exr) const;
209
210 // retrieve stack pointer, frame pointer, and instruction pointer from the target context
211 virtual TADDR GetSP(const CROSS_PLATFORM_CONTEXT & ctx) const { return ctx.ArmContext.Sp; }
212 // @ARMTODO: frame pointer
213 virtual TADDR GetBP(const CROSS_PLATFORM_CONTEXT & ctx) const { return 0; }
214 virtual TADDR GetIP(const CROSS_PLATFORM_CONTEXT & ctx) const { return ctx.ArmContext.Pc; }
215
216 virtual void FillSimpleContext(StackTrace_SimpleContext * dest, LPVOID srcCtx) const;
217 virtual void FillTargetContext(LPVOID destCtx, LPVOID srcCtx, int idx = 0) const;
218
219 virtual LPCSTR GetDumpStackHeading() const { return s_DumpStackHeading; }
220 virtual LPCSTR GetDumpStackObjectsHeading() const { return s_DSOHeading; }
221 virtual LPCSTR GetSPName() const { return s_SPName; }
222 virtual void GetGCRegisters(LPCSTR** regNames, unsigned int* cntRegs) const
223 { _ASSERTE(cntRegs != NULL); *regNames = s_GCRegs; *cntRegs = _countof(s_GCRegs); }
224
225 virtual void DumpGCInfo(GCInfoToken gcInfoToken, unsigned methodSize, printfFtn gcPrintf, bool encBytes, bool bPrintHeader) const;
226
227private:
228 ARMMachine() {}
229 ~ARMMachine() {}
230 ARMMachine(const ARMMachine& machine); // undefined
231 ARMMachine & operator=(const ARMMachine&); // undefined
232
233private:
234 static LPCSTR s_DumpStackHeading;
235 static LPCSTR s_DSOHeading;
236 static LPCSTR s_GCRegs[14];
237 static LPCSTR s_SPName;
238 static ARMMachine s_ARMMachineInstance;
239}; // class ARMMachine
240
241#endif // SOS_TARGET_ARM
242
243#ifdef SOS_TARGET_AMD64
244
245/// AMD64 Machine specific code
246class AMD64Machine : public IMachine
247{
248public:
249 typedef AMD64_CONTEXT TGT_CTXT;
250
251 static IMachine* GetInstance()
252 { static AMD64Machine s_AMD64MachineInstance; return &s_AMD64MachineInstance; }
253
254 ULONG GetPlatform() const { return IMAGE_FILE_MACHINE_AMD64; }
255 ULONG GetContextSize() const { return sizeof(AMD64_CONTEXT); }
256
257 virtual void Unassembly(
258 TADDR IPBegin,
259 TADDR IPEnd,
260 TADDR IPAskedFor,
261 TADDR GCStressCodeCopy,
262 GCEncodingInfo *pGCEncodingInfo,
263 SOSEHInfo *pEHInfo,
264 BOOL bSuppressLines,
265 BOOL bDisplayOffsets) const;
266
267 virtual void IsReturnAddress(
268 TADDR retAddr,
269 TADDR* whereCalled) const;
270
271 virtual BOOL GetExceptionContext (
272 TADDR stack,
273 TADDR PC,
274 TADDR *cxrAddr,
275 CROSS_PLATFORM_CONTEXT * cxr,
276 TADDR *exrAddr,
277 PEXCEPTION_RECORD exr) const;
278
279 // retrieve stack pointer, frame pointer, and instruction pointer from the target context
280 virtual TADDR GetSP(const CROSS_PLATFORM_CONTEXT & ctx) const { return ctx.Amd64Context.Rsp; }
281 virtual TADDR GetBP(const CROSS_PLATFORM_CONTEXT & ctx) const { return ctx.Amd64Context.Rbp; }
282 virtual TADDR GetIP(const CROSS_PLATFORM_CONTEXT & ctx) const { return ctx.Amd64Context.Rip; }
283
284 virtual void FillSimpleContext(StackTrace_SimpleContext * dest, LPVOID srcCtx) const;
285 virtual void FillTargetContext(LPVOID destCtx, LPVOID srcCtx, int idx = 0) const;
286
287 virtual LPCSTR GetDumpStackHeading() const { return s_DumpStackHeading; }
288 virtual LPCSTR GetDumpStackObjectsHeading() const { return s_DSOHeading; }
289 virtual LPCSTR GetSPName() const { return s_SPName; }
290 virtual void GetGCRegisters(LPCSTR** regNames, unsigned int* cntRegs) const
291 { _ASSERTE(cntRegs != NULL); *regNames = s_GCRegs; *cntRegs = _countof(s_GCRegs); }
292
293 virtual void DumpGCInfo(GCInfoToken gcInfoToken, unsigned methodSize, printfFtn gcPrintf, bool encBytes, bool bPrintHeader) const;
294
295private:
296 AMD64Machine() {}
297 ~AMD64Machine() {}
298 AMD64Machine(const AMD64Machine& machine); // undefined
299 AMD64Machine & operator=(const AMD64Machine&); // undefined
300
301private:
302 static LPCSTR s_DumpStackHeading;
303 static LPCSTR s_DSOHeading;
304 static LPCSTR s_GCRegs[15];
305 static LPCSTR s_SPName;
306}; // class AMD64Machine
307
308#endif // SOS_TARGET_AMD64
309
310#ifdef SOS_TARGET_ARM64
311
312/// ARM64 Machine specific code
313class ARM64Machine : public IMachine
314{
315public:
316 typedef ARM64_CONTEXT TGT_CTXT;
317
318 static IMachine* GetInstance()
319 { static ARM64Machine s_ARM64MachineInstance; return &s_ARM64MachineInstance; }
320
321 ULONG GetPlatform() const { return IMAGE_FILE_MACHINE_ARM64; }
322 ULONG GetContextSize() const { return sizeof(ARM64_CONTEXT); }
323 virtual void Unassembly(
324 TADDR IPBegin,
325 TADDR IPEnd,
326 TADDR IPAskedFor,
327 TADDR GCStressCodeCopy,
328 GCEncodingInfo *pGCEncodingInfo,
329 SOSEHInfo *pEHInfo,
330 BOOL bSuppressLines,
331 BOOL bDisplayOffsets) const;
332 virtual void IsReturnAddress(
333 TADDR retAddr,
334 TADDR* whereCalled) const;
335 virtual BOOL GetExceptionContext (
336 TADDR stack,
337 TADDR PC,
338 TADDR *cxrAddr,
339 CROSS_PLATFORM_CONTEXT * cxr,
340 TADDR *exrAddr,
341 PEXCEPTION_RECORD exr) const;
342
343 // retrieve stack pointer, frame pointer, and instruction pointer from the target context
344 virtual TADDR GetSP(const CROSS_PLATFORM_CONTEXT & ctx) const { return ctx.Arm64Context.Sp; }
345 virtual TADDR GetBP(const CROSS_PLATFORM_CONTEXT & ctx) const { return ctx.Arm64Context.Fp; }
346 virtual TADDR GetIP(const CROSS_PLATFORM_CONTEXT & ctx) const { return ctx.Arm64Context.Pc; }
347
348 virtual void FillSimpleContext(StackTrace_SimpleContext * dest, LPVOID srcCtx) const;
349 virtual void FillTargetContext(LPVOID destCtx, LPVOID srcCtx, int idx = 0) const;
350
351 virtual LPCSTR GetDumpStackHeading() const { return s_DumpStackHeading; }
352 virtual LPCSTR GetDumpStackObjectsHeading() const { return s_DSOHeading; }
353 virtual LPCSTR GetSPName() const { return s_SPName; }
354 virtual void GetGCRegisters(LPCSTR** regNames, unsigned int* cntRegs) const
355 { _ASSERTE(cntRegs != NULL); *regNames = s_GCRegs; *cntRegs = _countof(s_GCRegs);}
356
357 virtual void DumpGCInfo(GCInfoToken gcInfoToken, unsigned methodSize, printfFtn gcPrintf, bool encBytes, bool bPrintHeader) const;
358
359private:
360 ARM64Machine() {}
361 ~ARM64Machine() {}
362 ARM64Machine(const ARM64Machine& machine); // undefined
363 ARM64Machine & operator=(const ARM64Machine&); // undefined
364
365 static LPCSTR s_DumpStackHeading;
366 static LPCSTR s_DSOHeading;
367 static LPCSTR s_GCRegs[28];
368 static LPCSTR s_SPName;
369
370}; // class ARM64Machine
371
372#endif // SOS_TARGET_ARM64
373#ifdef _MSC_VER
374#pragma warning(pop)
375#endif // _MSC_VER
376
377
378//
379// Inline methods
380//
381
382
383#ifdef SOS_TARGET_X86
384inline void X86Machine::FillSimpleContext(StackTrace_SimpleContext * dest, LPVOID srcCtx) const
385{
386 TGT_CTXT& src = *(TGT_CTXT*) srcCtx;
387 dest->StackOffset = src.Esp;
388 dest->FrameOffset = src.Ebp;
389 dest->InstructionOffset = src.Eip;
390}
391
392inline void X86Machine::FillTargetContext(LPVOID destCtx, LPVOID srcCtx, int idx /*= 0*/) const
393{
394 TGT_CTXT* dest = (TGT_CTXT*)destCtx + idx;
395 *dest = *(TGT_CTXT*)srcCtx;
396}
397#endif // SOS_TARGET_X86
398
399
400#ifdef SOS_TARGET_ARM
401inline void ARMMachine::FillSimpleContext(StackTrace_SimpleContext * dest, LPVOID srcCtx) const
402{
403 TGT_CTXT& src = *(TGT_CTXT*) srcCtx;
404 dest->StackOffset = src.Sp;
405 // @ARMTODO: frame pointer - keep in sync with ARMMachine::GetBP
406 dest->FrameOffset = 0;
407 dest->InstructionOffset = src.Pc;
408}
409
410inline void ARMMachine::FillTargetContext(LPVOID destCtx, LPVOID srcCtx, int idx /*= 0*/) const
411{
412 TGT_CTXT* dest = (TGT_CTXT*)destCtx + idx;
413 *dest = *(TGT_CTXT*)srcCtx;
414}
415#endif // SOS_TARGET_ARM
416
417
418#ifdef SOS_TARGET_AMD64
419inline void AMD64Machine::FillSimpleContext(StackTrace_SimpleContext * dest, LPVOID srcCtx) const
420{
421 TGT_CTXT& src = *(TGT_CTXT*) srcCtx;
422 dest->StackOffset = src.Rsp;
423 dest->FrameOffset = src.Rbp;
424 dest->InstructionOffset = src.Rip;
425}
426
427inline void AMD64Machine::FillTargetContext(LPVOID destCtx, LPVOID srcCtx, int idx /*= 0*/) const
428{
429 TGT_CTXT* dest = (TGT_CTXT*)destCtx + idx;
430 *dest = *(TGT_CTXT*)srcCtx;
431}
432#endif // SOS_TARGET_AMD64
433
434#ifdef SOS_TARGET_ARM64
435inline void ARM64Machine::FillSimpleContext(StackTrace_SimpleContext * dest, LPVOID srcCtx) const
436{
437 TGT_CTXT& src = *(TGT_CTXT*) srcCtx;
438 dest->StackOffset = src.Sp;
439 dest->FrameOffset = src.Fp;
440 dest->InstructionOffset = src.Pc;
441}
442
443inline void ARM64Machine::FillTargetContext(LPVOID destCtx, LPVOID srcCtx, int idx /*= 0*/) const
444{
445 TGT_CTXT* dest = (TGT_CTXT*)destCtx + idx;
446 *dest = *(TGT_CTXT*)srcCtx;
447}
448#endif // SOS_TARGET_ARM64
449
450#endif // __disasm_h__
451