Merge pull request #14619 from briansull/emitter-cleanup
[platform/upstream/coreclr.git] / src / vm / gdbjit.h
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 // File: gdbjit.h
6 //
7
8 //
9 // Header file for GDB JIT interface implemenation.
10 //
11 //*****************************************************************************
12
13
14 #ifndef __GDBJIT_H__
15 #define __GDBJIT_H__
16
17 #include <stdint.h>
18 #include "typekey.h"
19 #include "typestring.h"
20 #include "method.hpp"
21 #include "dbginterface.h"
22 #include "../inc/llvm/ELF.h"
23 #include "../inc/llvm/Dwarf.h"
24
25 #if defined(_TARGET_X86_) || defined(_TARGET_ARM_)
26     typedef Elf32_Ehdr  Elf_Ehdr;
27     typedef Elf32_Shdr  Elf_Shdr;
28     typedef Elf32_Sym   Elf_Sym;
29     const uint16_t DW_FORM_size = DW_FORM_data4;
30 #define ADDRESS_SIZE 4
31 #elif defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)
32     typedef Elf64_Ehdr  Elf_Ehdr;
33     typedef Elf64_Shdr  Elf_Shdr;
34     typedef Elf64_Sym   Elf_Sym;
35     const uint16_t DW_FORM_size = DW_FORM_data8;
36 #define ADDRESS_SIZE 8
37 #else
38 #error "Target is not supported"
39 #endif
40
41
42 static constexpr const int CorElementTypeToDWEncoding[] =
43 {
44 /* ELEMENT_TYPE_END */          0,
45 /* ELEMENT_TYPE_VOID */         DW_ATE_address,
46 /* ELEMENT_TYPE_BOOLEAN */      DW_ATE_boolean,
47 /* ELEMENT_TYPE_CHAR */         DW_ATE_UTF,
48 /* ELEMENT_TYPE_I1 */           DW_ATE_signed,
49 /* ELEMENT_TYPE_U1 */           DW_ATE_unsigned,
50 /* ELEMENT_TYPE_I2 */           DW_ATE_signed,
51 /* ELEMENT_TYPE_U2 */           DW_ATE_unsigned,
52 /* ELEMENT_TYPE_I4 */           DW_ATE_signed,
53 /* ELEMENT_TYPE_U4 */           DW_ATE_unsigned,
54 /* ELEMENT_TYPE_I8 */           DW_ATE_signed,
55 /* ELEMENT_TYPE_U8 */           DW_ATE_unsigned,
56 /* ELEMENT_TYPE_R4 */           DW_ATE_float,
57 /* ELEMENT_TYPE_R8 */           DW_ATE_float,
58 /* ELEMENT_TYPE_STRING */       DW_ATE_address,
59 /* ELEMENT_TYPE_PTR */          DW_ATE_address,
60 /* ELEMENT_TYPE_BYREF */        DW_ATE_address,
61 /* ELEMENT_TYPE_VALUETYPE */    DW_ATE_address,
62 /* ELEMENT_TYPE_CLASS */        DW_ATE_address,
63 /* ELEMENT_TYPE_VAR */          DW_ATE_address,
64 /* ELEMENT_TYPE_ARRAY */        DW_ATE_address,
65 /* ELEMENT_TYPE_GENERICINST */  DW_ATE_address,
66 /* ELEMENT_TYPE_TYPEDBYREF */   DW_ATE_address,
67 /* SKIP 17 */                   DW_ATE_address,
68 /* ELEMENT_TYPE_I */            DW_ATE_signed,
69 /* ELEMENT_TYPE_U */            DW_ATE_unsigned,
70 /* SKIP 1a */                   DW_ATE_address,
71 /* ELEMENT_TYPE_FNPTR */        DW_ATE_address,
72 /* ELEMENT_TYPE_OBJECT */       DW_ATE_address,
73 /* ELEMENT_TYPE_SZARRAY */      DW_ATE_address,
74 /* ELEMENT_TYPE_MVAR */         DW_ATE_address,
75 /* ELEMENT_TYPE_CMOD_REQD */    DW_ATE_address,
76 /* ELEMENT_TYPE_CMOD_OPT */     DW_ATE_address,
77 /* ELEMENT_TYPE_INTERNAL */     DW_ATE_address,
78 /* ELEMENT_TYPE_MAX */          DW_ATE_address,
79 };
80
81 struct __attribute__((packed)) DwarfCompUnit
82 {
83     uint32_t m_length;
84     uint16_t m_version;
85     uint32_t m_abbrev_offset;
86     uint8_t m_addr_size;
87 };
88
89 struct __attribute__((packed)) DwarfPubHeader
90 {
91     uint32_t m_length;
92     uint16_t m_version;
93     uint32_t m_debug_info_off;
94     uint32_t m_debug_info_len;
95 };
96
97 #define DW_LNS_MAX DW_LNS_set_isa
98
99 struct __attribute__((packed)) DwarfLineNumHeader
100 {
101     uint32_t m_length;
102     uint16_t m_version;
103     uint32_t m_hdr_length;
104     uint8_t m_min_instr_len;
105     uint8_t m_def_is_stmt;
106     int8_t m_line_base;
107     uint8_t m_line_range;
108     uint8_t m_opcode_base;
109     uint8_t m_std_num_arg[DW_LNS_MAX];
110 };
111
112 const ULONG32 HiddenLine = 0x00feefee;
113
114 struct SymbolsInfo
115 {
116     int lineNumber, ilOffset, nativeOffset, fileIndex;
117     char fileName[2*MAX_PATH_FNAME];
118     ICorDebugInfo::SourceTypes source;
119 };
120
121 class DwarfDumpable
122 {
123 public:
124     DwarfDumpable() :
125         m_base_ptr(nullptr),
126         m_is_visited(false)
127     {
128     }
129
130     // writes all string literals this type needs to ptr
131     virtual void DumpStrings(char* ptr, int& offset) = 0;
132
133     virtual void DumpDebugInfo(char* ptr, int& offset) = 0;
134
135     virtual ~DwarfDumpable() {}
136
137     char *m_base_ptr;
138     bool m_is_visited;
139 };
140
141 class LocalsInfo
142 {
143 public:
144     struct Scope {
145         int ilStartOffset;
146         int ilEndOffset;
147     };
148     int size;
149     NewArrayHolder< NewArrayHolder<char> > localsName;
150     NewArrayHolder<Scope> localsScope;
151     ULONG32 countVars;
152     NewArrayHolder<ICorDebugInfo::NativeVarInfo> vars;
153 };
154
155 class TypeMember;
156
157 class TypeInfoBase : public DwarfDumpable
158 {
159 public:
160     TypeInfoBase(TypeHandle typeHandle)
161         : m_type_name(nullptr),
162           m_type_name_offset(0),
163           m_type_size(0),
164           m_type_offset(0),
165           typeHandle(typeHandle),
166           typeKey(typeHandle.GetTypeKey())
167     {
168     }
169
170     virtual void DumpStrings(char* ptr, int& offset) override;
171     void CalculateName();
172     void SetTypeHandle(TypeHandle handle);
173     TypeHandle GetTypeHandle();
174     TypeKey* GetTypeKey();
175
176     NewArrayHolder<char> m_type_name;
177     int m_type_name_offset;
178     ULONG m_type_size;
179     int m_type_offset;
180 private:
181     TypeHandle typeHandle;
182     TypeKey typeKey;
183 };
184
185 class TypeDefInfo : public DwarfDumpable
186 {
187 public:
188     TypeDefInfo(char *typedef_name,int typedef_type):
189     m_typedef_name(typedef_name), m_typedef_type(typedef_type), m_typedef_type_offset(0) {}
190     void DumpStrings(char* ptr, int& offset) override;
191     void DumpDebugInfo(char* ptr, int& offset) override;
192
193     NewArrayHolder<char> m_typedef_name;
194     int m_typedef_type;
195     int m_typedef_type_offset;
196     int m_typedef_name_offset;
197 };
198
199 class PrimitiveTypeInfo: public TypeInfoBase
200 {
201 public:
202     PrimitiveTypeInfo(TypeHandle typeHandle);
203
204     void DumpDebugInfo(char* ptr, int& offset) override;
205     void DumpStrings(char* ptr, int& offset) override;
206
207     int m_type_encoding;
208     NewHolder<TypeDefInfo> m_typedef_info;
209 };
210
211 class RefTypeInfo: public TypeInfoBase
212 {
213 public:
214     RefTypeInfo(TypeHandle typeHandle, TypeInfoBase *value_type)
215         : TypeInfoBase(typeHandle),
216           m_value_type(value_type)
217     {
218         m_type_size = sizeof(TADDR);
219         CalculateName();
220     }
221     void DumpStrings(char* ptr, int& offset) override;
222     void DumpDebugInfo(char* ptr, int& offset) override;
223     TypeInfoBase *m_value_type;
224 };
225
226 class NamedRefTypeInfo: public RefTypeInfo
227 {
228 public:
229     NamedRefTypeInfo(TypeHandle typeHandle, TypeInfoBase *value_type)
230         : RefTypeInfo(typeHandle, value_type), m_value_type_storage(value_type)
231     {
232     }
233
234     void DumpDebugInfo(char* ptr, int& offset) override;
235
236     NewHolder<TypeInfoBase> m_value_type_storage;
237 };
238
239 class FunctionMemberPtrArrayHolder;
240 class ArrayTypeInfo;
241
242 class ClassTypeInfo: public TypeInfoBase
243 {
244 public:
245     ClassTypeInfo(TypeHandle typeHandle, int num_members, FunctionMemberPtrArrayHolder &method);
246
247     void DumpStrings(char* ptr, int& offset) override;
248     void DumpDebugInfo(char* ptr, int& offset) override;
249
250     int m_num_members;
251     NewArrayHolder<TypeMember> members;
252     TypeInfoBase* m_parent;
253     FunctionMemberPtrArrayHolder &m_method;
254     NewHolder<ArrayTypeInfo> m_array_type;
255     NewHolder<ArrayTypeInfo> m_array_bounds_type;
256 };
257
258 class TypeMember: public DwarfDumpable
259 {
260 public:
261     TypeMember()
262         : m_member_name(nullptr),
263           m_member_name_offset(0),
264           m_member_offset(0),
265           m_static_member_address(0),
266           m_member_type(nullptr)
267     {
268     }
269
270     void DumpStrings(char* ptr, int& offset) override;
271     void DumpDebugInfo(char* ptr, int& offset) override;
272     void DumpStaticDebugInfo(char* ptr, int& offset);
273
274     NewArrayHolder<char> m_member_name;
275     int m_member_name_offset;
276     int m_member_offset;
277     TADDR m_static_member_address;
278     TypeInfoBase *m_member_type;
279 };
280
281 class ArrayTypeInfo: public TypeInfoBase
282 {
283 public:
284     ArrayTypeInfo(TypeHandle typeHandle, int count, TypeInfoBase* elemType)
285         : TypeInfoBase(typeHandle),
286           m_count(count),
287           m_elem_type(elemType)
288     {
289     }
290
291     void DumpDebugInfo(char* ptr, int& offset) override;
292
293     int m_count;
294     TypeInfoBase *m_elem_type;
295 };
296
297 class VarDebugInfo: public DwarfDumpable
298 {
299 public:
300     VarDebugInfo(int abbrev)
301         : m_var_name(nullptr),
302           m_var_abbrev(abbrev),
303           m_var_name_offset(0),
304           m_il_index(0),
305           m_native_offset(0),
306           m_var_type(nullptr),
307           m_low_pc(0),
308           m_high_pc(0)
309     {
310     }
311
312     VarDebugInfo()
313         : m_var_name(nullptr),
314           m_var_abbrev(6),
315           m_var_name_offset(0),
316           m_il_index(0),
317           m_native_offset(0),
318           m_var_type(nullptr),
319           m_low_pc(0),
320           m_high_pc(0)
321     {
322     }
323
324     void DumpStrings(char* ptr, int& offset) override;
325     void DumpDebugInfo(char* ptr, int& offset) override;
326
327     NewArrayHolder<char> m_var_name;
328     int m_var_abbrev;
329     int m_var_name_offset;
330     int m_il_index;
331     int m_native_offset;
332     TypeInfoBase *m_var_type;
333     uintptr_t m_low_pc;
334     uintptr_t m_high_pc;
335 };
336
337 struct Elf_Symbol;
338 class Elf_Builder;
339 class DebugStringsCU;
340
341 class NotifyGdb
342 {
343 public:
344     class FileTableBuilder;
345     static void Initialize();
346     static void MethodPrepared(MethodDesc* methodDescPtr);
347     static void MethodPitched(MethodDesc* methodDescPtr);
348     template <typename PARENT_TRAITS>
349     class DeleteValuesOnDestructSHashTraits : public PARENT_TRAITS
350     {
351     public:
352         static inline void OnDestructPerEntryCleanupAction(typename PARENT_TRAITS::element_t e)
353         {
354             delete e.Value();
355         }
356         static const bool s_DestructPerEntryCleanupAction = true;
357     };
358
359     template <typename VALUE>
360     class TypeKeyHashTraits : public DefaultSHashTraits< KeyValuePair<TypeKey*,VALUE> >
361     {
362     public:
363         // explicitly declare local typedefs for these traits types, otherwise
364         // the compiler may get confused
365         typedef typename DefaultSHashTraits< KeyValuePair<TypeKey*,VALUE> >::element_t element_t;
366         typedef typename DefaultSHashTraits< KeyValuePair<TypeKey*,VALUE> >::count_t count_t;
367         typedef TypeKey* key_t;
368
369         static key_t GetKey(element_t e)
370         {
371             LIMITED_METHOD_CONTRACT;
372             return e.Key();
373         }
374         static BOOL Equals(key_t k1, key_t k2)
375         {
376             LIMITED_METHOD_CONTRACT;
377             return k1->Equals(k2);
378         }
379         static count_t Hash(key_t k)
380         {
381             LIMITED_METHOD_CONTRACT;
382             return k->ComputeHash();
383         }
384
385         static const element_t Null() { LIMITED_METHOD_CONTRACT; return element_t(key_t(),VALUE()); }
386         static const element_t Deleted() { LIMITED_METHOD_CONTRACT; return element_t(key_t(-1), VALUE()); }
387         static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e.Key() == key_t(); }
388         static bool IsDeleted(const element_t &e) { return e.Key() == key_t(-1); }
389     };
390
391     typedef MapSHash<TypeKey*, TypeInfoBase*, DeleteValuesOnDestructSHashTraits<TypeKeyHashTraits<TypeInfoBase*>>> TK_TypeInfoMap;
392     typedef TK_TypeInfoMap* PTK_TypeInfoMap;
393     typedef SetSHash< TADDR,
394                       NoRemoveSHashTraits <
395                       NonDacAwareSHashTraits< SetSHashTraits <TADDR> >
396                     > > AddrSet;
397 private:
398
399     struct MemBuf
400     {
401         NewArrayHolder<char> MemPtr;
402         unsigned MemSize;
403         MemBuf() : MemPtr(0), MemSize(0)
404         {}
405         void Resize(unsigned newSize)
406         {
407             if (newSize == 0)
408             {
409                 MemPtr = nullptr;
410                 MemSize = 0;
411                 return;
412             }
413             char *tmp = new char [newSize];
414             memmove(tmp, MemPtr.GetValue(), newSize < MemSize ? newSize : MemSize);
415             MemPtr = tmp;
416             MemSize = newSize;
417         }
418     };
419
420     static void OnMethodPrepared(MethodDesc* methodDescPtr);
421
422 #ifdef FEATURE_GDBJIT_FRAME
423     static bool EmitFrameInfo(Elf_Builder &, PCODE pCode, TADDR codeSzie);
424 #endif // FEATURE_GDBJIT_FRAME
425 #ifdef FEATURE_GDBJIT_SYMTAB
426     static bool EmitSymtab(Elf_Builder &, MethodDesc* methodDescPtr, PCODE pCode, TADDR codeSize);
427 #endif // FEATURE_GDBJIT_SYMTAB
428     static bool EmitDebugInfo(Elf_Builder &, MethodDesc* methodDescPtr, PCODE pCode, TADDR codeSize);
429
430     static bool BuildSymbolTableSection(MemBuf& buf, PCODE addr, TADDR codeSize, int methodCount,
431                                         NewArrayHolder<Elf_Symbol> &symbolNames, int symbolCount,
432                                         unsigned int thunkIndexBase);
433     static bool BuildStringTableSection(MemBuf& strTab, NewArrayHolder<Elf_Symbol> &symbolNames, int symbolCount);
434     static bool BuildDebugStrings(MemBuf& buf, PTK_TypeInfoMap pTypeMap, FunctionMemberPtrArrayHolder &method,
435                                   DebugStringsCU &debugStringsCU);
436     static bool BuildDebugAbbrev(MemBuf& buf);
437     static bool BuildDebugInfo(MemBuf& buf, PTK_TypeInfoMap pTypeMap, FunctionMemberPtrArrayHolder &method,
438                                DebugStringsCU &debugStringsCU);
439     static bool BuildDebugPub(MemBuf& buf, const char* name, uint32_t size, uint32_t dieOffset);
440     static bool BuildLineTable(MemBuf& buf, PCODE startAddr, TADDR codeSize, SymbolsInfo* lines, unsigned nlines,
441                                const char * &cuPath);
442     static bool BuildFileTable(MemBuf& buf, SymbolsInfo* lines, unsigned nlines, const char * &cuPath);
443     static bool BuildLineProg(MemBuf& buf, PCODE startAddr, TADDR codeSize, SymbolsInfo* lines, unsigned nlines);
444     static void IssueSetAddress(char*& ptr, PCODE addr);
445     static void IssueEndOfSequence(char*& ptr);
446     static void IssueSimpleCommand(char*& ptr, uint8_t command);
447     static void IssueParamCommand(char*& ptr, uint8_t command, char* param, int param_len);
448     static const char* SplitFilename(const char* path);
449     static bool CollectCalledMethods(CalledMethod* pCM, TADDR nativeCode, FunctionMemberPtrArrayHolder &method,
450                                      NewArrayHolder<Elf_Symbol> &symbolNames, int &symbolCount);
451 };
452
453 class FunctionMember: public TypeMember
454 {
455 public:
456     FunctionMember(MethodDesc *md, int num_locals, int num_args)
457         : TypeMember(),
458           md(md),
459           m_file(1),
460           m_line(1),
461           m_sub_low_pc(0),
462           m_sub_high_pc(0),
463           m_sub_loc(),
464           m_num_args(num_args),
465           m_num_locals(num_locals),
466           m_num_vars(num_args + num_locals),
467           m_entry_offset(0),
468           vars(new VarDebugInfo[m_num_vars]),
469           lines(NULL),
470           nlines(0),
471           m_linkage_name_offset(0),
472           dumped(false)
473     {
474         m_sub_loc[0] = 1;
475 #if defined(_TARGET_AMD64_)
476         m_sub_loc[1] = DW_OP_reg6;
477 #elif defined(_TARGET_X86_)
478         m_sub_loc[1] = DW_OP_reg5;
479 #elif defined(_TARGET_ARM64_)
480         m_sub_loc[1] = DW_OP_reg29;
481 #elif defined(_TARGET_ARM_)
482         m_sub_loc[1] = DW_OP_reg11;
483 #else
484 #error Unsupported platform!
485 #endif
486     }
487
488     void DumpStrings(char* ptr, int& offset) override;
489     void DumpDebugInfo(char* ptr, int& offset) override;
490     void DumpTryCatchDebugInfo(char* ptr, int& offset);
491     HRESULT GetLocalsDebugInfo(NotifyGdb::PTK_TypeInfoMap pTypeMap,
492                            LocalsInfo& locals,
493                            int startNativeOffset,
494                            FunctionMemberPtrArrayHolder &method);
495     BOOL IsDumped()
496     {
497         return dumped;
498     }
499
500     MethodDesc *md;
501     uint8_t m_file, m_line;
502     uintptr_t m_sub_low_pc, m_sub_high_pc;
503     uint8_t m_sub_loc[2];
504     uint8_t m_num_args;
505     uint8_t m_num_locals;
506     uint16_t m_num_vars;
507     int m_entry_offset;
508     NewArrayHolder<VarDebugInfo> vars;
509     SymbolsInfo* lines;
510     unsigned nlines;
511     int m_linkage_name_offset;
512 private:
513     int GetArgsAndLocalsLen();
514     void MangleName(char *buf, int &buf_offset, const char *name);
515     void DumpMangledNamespaceAndMethod(char *buf, int &offset, const char *nspace, const char *mname);
516     void DumpLinkageName(char* ptr, int& offset);
517     bool GetBlockInNativeCode(int blockILOffset, int blockILLen, TADDR *startOffset, TADDR *endOffset);
518     void DumpTryCatchBlock(char* ptr, int& offset, int ilOffset, int ilLen, int abbrev);
519     void DumpVarsWithScopes(char* ptr, int& offset);
520     BOOL dumped;
521 };
522 #endif // #ifndef __GDBJIT_H__