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 //*****************************************************************************
9 // Header file for GDB JIT interface implemenation.
11 //*****************************************************************************
19 #include "typestring.h"
21 #include "dbginterface.h"
22 #include "../inc/llvm/ELF.h"
23 #include "../inc/llvm/Dwarf.h"
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
38 #error "Target is not supported"
42 static constexpr const int CorElementTypeToDWEncoding[] =
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,
81 struct __attribute__((packed)) DwarfCompUnit
85 uint32_t m_abbrev_offset;
89 struct __attribute__((packed)) DwarfPubHeader
93 uint32_t m_debug_info_off;
94 uint32_t m_debug_info_len;
97 #define DW_LNS_MAX DW_LNS_set_isa
99 struct __attribute__((packed)) DwarfLineNumHeader
103 uint32_t m_hdr_length;
104 uint8_t m_min_instr_len;
105 uint8_t m_def_is_stmt;
107 uint8_t m_line_range;
108 uint8_t m_opcode_base;
109 uint8_t m_std_num_arg[DW_LNS_MAX];
112 const ULONG32 HiddenLine = 0x00feefee;
116 int lineNumber, ilOffset, nativeOffset, fileIndex;
117 char fileName[2*MAX_PATH_FNAME];
118 ICorDebugInfo::SourceTypes source;
130 // writes all string literals this type needs to ptr
131 virtual void DumpStrings(char* ptr, int& offset) = 0;
133 virtual void DumpDebugInfo(char* ptr, int& offset) = 0;
135 virtual ~DwarfDumpable() {}
149 NewArrayHolder< NewArrayHolder<char> > localsName;
150 NewArrayHolder<Scope> localsScope;
152 NewArrayHolder<ICorDebugInfo::NativeVarInfo> vars;
157 class TypeInfoBase : public DwarfDumpable
160 TypeInfoBase(TypeHandle typeHandle)
161 : m_type_name(nullptr),
162 m_type_name_offset(0),
165 typeHandle(typeHandle),
166 typeKey(typeHandle.GetTypeKey())
170 virtual void DumpStrings(char* ptr, int& offset) override;
171 void CalculateName();
172 void SetTypeHandle(TypeHandle handle);
173 TypeHandle GetTypeHandle();
174 TypeKey* GetTypeKey();
176 NewArrayHolder<char> m_type_name;
177 int m_type_name_offset;
181 TypeHandle typeHandle;
185 class TypeDefInfo : public DwarfDumpable
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;
193 NewArrayHolder<char> m_typedef_name;
195 int m_typedef_type_offset;
196 int m_typedef_name_offset;
199 class PrimitiveTypeInfo: public TypeInfoBase
202 PrimitiveTypeInfo(TypeHandle typeHandle);
204 void DumpDebugInfo(char* ptr, int& offset) override;
205 void DumpStrings(char* ptr, int& offset) override;
208 NewHolder<TypeDefInfo> m_typedef_info;
211 class RefTypeInfo: public TypeInfoBase
214 RefTypeInfo(TypeHandle typeHandle, TypeInfoBase *value_type)
215 : TypeInfoBase(typeHandle),
216 m_value_type(value_type)
218 m_type_size = sizeof(TADDR);
221 void DumpStrings(char* ptr, int& offset) override;
222 void DumpDebugInfo(char* ptr, int& offset) override;
223 TypeInfoBase *m_value_type;
226 class NamedRefTypeInfo: public RefTypeInfo
229 NamedRefTypeInfo(TypeHandle typeHandle, TypeInfoBase *value_type)
230 : RefTypeInfo(typeHandle, value_type), m_value_type_storage(value_type)
234 void DumpDebugInfo(char* ptr, int& offset) override;
236 NewHolder<TypeInfoBase> m_value_type_storage;
239 class FunctionMemberPtrArrayHolder;
242 class ClassTypeInfo: public TypeInfoBase
245 ClassTypeInfo(TypeHandle typeHandle, int num_members, FunctionMemberPtrArrayHolder &method);
247 void DumpStrings(char* ptr, int& offset) override;
248 void DumpDebugInfo(char* ptr, int& offset) override;
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;
258 class TypeMember: public DwarfDumpable
262 : m_member_name(nullptr),
263 m_member_name_offset(0),
265 m_static_member_address(0),
266 m_member_type(nullptr)
270 void DumpStrings(char* ptr, int& offset) override;
271 void DumpDebugInfo(char* ptr, int& offset) override;
272 void DumpStaticDebugInfo(char* ptr, int& offset);
274 NewArrayHolder<char> m_member_name;
275 int m_member_name_offset;
277 TADDR m_static_member_address;
278 TypeInfoBase *m_member_type;
281 class ArrayTypeInfo: public TypeInfoBase
284 ArrayTypeInfo(TypeHandle typeHandle, int count, TypeInfoBase* elemType)
285 : TypeInfoBase(typeHandle),
287 m_elem_type(elemType)
291 void DumpDebugInfo(char* ptr, int& offset) override;
294 TypeInfoBase *m_elem_type;
297 class VarDebugInfo: public DwarfDumpable
300 VarDebugInfo(int abbrev)
301 : m_var_name(nullptr),
302 m_var_abbrev(abbrev),
303 m_var_name_offset(0),
313 : m_var_name(nullptr),
315 m_var_name_offset(0),
324 void DumpStrings(char* ptr, int& offset) override;
325 void DumpDebugInfo(char* ptr, int& offset) override;
327 NewArrayHolder<char> m_var_name;
329 int m_var_name_offset;
332 TypeInfoBase *m_var_type;
339 class DebugStringsCU;
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
352 static inline void OnDestructPerEntryCleanupAction(typename PARENT_TRAITS::element_t e)
356 static const bool s_DestructPerEntryCleanupAction = true;
359 template <typename VALUE>
360 class TypeKeyHashTraits : public DefaultSHashTraits< KeyValuePair<TypeKey*,VALUE> >
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;
369 static key_t GetKey(element_t e)
371 LIMITED_METHOD_CONTRACT;
374 static BOOL Equals(key_t k1, key_t k2)
376 LIMITED_METHOD_CONTRACT;
377 return k1->Equals(k2);
379 static count_t Hash(key_t k)
381 LIMITED_METHOD_CONTRACT;
382 return k->ComputeHash();
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); }
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> >
401 NewArrayHolder<char> MemPtr;
403 MemBuf() : MemPtr(0), MemSize(0)
405 void Resize(unsigned newSize)
413 char *tmp = new char [newSize];
414 memmove(tmp, MemPtr.GetValue(), newSize < MemSize ? newSize : MemSize);
420 static void OnMethodPrepared(MethodDesc* methodDescPtr);
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);
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);
453 class FunctionMember: public TypeMember
456 FunctionMember(MethodDesc *md, int num_locals, int num_args)
464 m_num_args(num_args),
465 m_num_locals(num_locals),
466 m_num_vars(num_args + num_locals),
468 vars(new VarDebugInfo[m_num_vars]),
471 m_linkage_name_offset(0),
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;
484 #error Unsupported platform!
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,
493 int startNativeOffset,
494 FunctionMemberPtrArrayHolder &method);
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];
505 uint8_t m_num_locals;
508 NewArrayHolder<VarDebugInfo> vars;
511 int m_linkage_name_offset;
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);
522 #endif // #ifndef __GDBJIT_H__