Removed unused opers and code
[platform/upstream/coreclr.git] / src / vm / gdbjit.cpp
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.cpp
6 //
7
8 //
9 // NotifyGdb implementation.
10 //
11 //*****************************************************************************
12
13 #include "common.h"
14 #include "formattype.h"
15 #include "gdbjit.h"
16 #include "gdbjithelpers.h"
17
18 __declspec(thread) bool tls_isSymReaderInProgress = false;
19
20 #ifdef _DEBUG
21 static void DumpElf(const char* methodName, const char *addr, size_t size)
22 {
23     char dump[1024] = { 0, };
24
25     strcat(dump, methodName);
26     strcat(dump, ".o");
27
28     FILE *f = fopen(dump,  "wb");
29     fwrite(addr, sizeof(char), size, f);
30     fclose(f);
31 }
32 #endif
33
34 TypeInfoBase*
35 GetTypeInfoFromTypeHandle(TypeHandle typeHandle,
36                           NotifyGdb::PTK_TypeInfoMap pTypeMap,
37                           FunctionMemberPtrArrayHolder &method)
38 {
39     TypeInfoBase *foundTypeInfo = nullptr;
40     TypeKey key = typeHandle.GetTypeKey();
41     PTR_MethodTable pMT = typeHandle.GetMethodTable();
42
43     if (pTypeMap->Lookup(&key, &foundTypeInfo))
44     {
45         return foundTypeInfo;
46     }
47
48     CorElementType corType = typeHandle.GetSignatureCorElementType();
49     switch (corType)
50     {
51         case ELEMENT_TYPE_I1:
52         case ELEMENT_TYPE_U1:
53         case ELEMENT_TYPE_CHAR:
54         case ELEMENT_TYPE_VOID:
55         case ELEMENT_TYPE_BOOLEAN:
56         case ELEMENT_TYPE_I2:
57         case ELEMENT_TYPE_U2:
58         case ELEMENT_TYPE_I4:
59         case ELEMENT_TYPE_U4:
60         case ELEMENT_TYPE_I8:
61         case ELEMENT_TYPE_U8:
62         case ELEMENT_TYPE_R4:
63         case ELEMENT_TYPE_R8:
64         case ELEMENT_TYPE_U:
65         case ELEMENT_TYPE_I:
66         {
67             NewHolder<PrimitiveTypeInfo> typeInfo = new PrimitiveTypeInfo(typeHandle);
68             pTypeMap->Add(typeInfo->GetTypeKey(), typeInfo);
69             typeInfo.SuppressRelease();
70             return typeInfo;
71         }
72         case ELEMENT_TYPE_VALUETYPE:
73         case ELEMENT_TYPE_CLASS:
74         {
75             ApproxFieldDescIterator fieldDescIterator(pMT,
76                 pMT->IsString() ? ApproxFieldDescIterator::INSTANCE_FIELDS : ApproxFieldDescIterator::ALL_FIELDS);
77             ULONG cFields = fieldDescIterator.Count();
78
79             NewHolder<ClassTypeInfo> typeInfo = new ClassTypeInfo(typeHandle, cFields, method);
80
81             NewHolder<RefTypeInfo> refTypeInfo = nullptr;
82             if (!typeHandle.IsValueType())
83             {
84                 refTypeInfo = new NamedRefTypeInfo(typeHandle, typeInfo);
85                 typeInfo.SuppressRelease();
86
87                 pTypeMap->Add(refTypeInfo->GetTypeKey(), refTypeInfo);
88                 refTypeInfo.SuppressRelease();
89             }
90             else
91             {
92                 pTypeMap->Add(typeInfo->GetTypeKey(), typeInfo);
93                 typeInfo.SuppressRelease();
94             }
95
96             //
97             // Now fill in the array
98             //
99             FieldDesc *pField;
100
101             for (ULONG i = 0; i < cFields; i++)
102             {
103                 pField = fieldDescIterator.Next();
104
105                 LPCUTF8 szName = pField->GetName();
106                 typeInfo->members[i].m_member_name = new char[strlen(szName) + 1];
107                 strcpy(typeInfo->members[i].m_member_name, szName);
108                 if (!pField->IsStatic())
109                 {
110                     typeInfo->members[i].m_member_offset = (ULONG)pField->GetOffset();
111                     if (!typeHandle.IsValueType())
112                         typeInfo->members[i].m_member_offset += Object::GetOffsetOfFirstField();
113                 }
114                 else
115                 {
116                     PTR_BYTE base = 0;
117                     MethodTable* pMT = pField->GetEnclosingMethodTable();
118                     base = pField->GetBase();
119
120                     // TODO: add support of generics with static fields
121                     if (pField->IsRVA() || !pMT->IsDynamicStatics())
122                     {
123                         PTR_VOID pAddress = pField->GetStaticAddressHandle((PTR_VOID)dac_cast<TADDR>(base));
124                         typeInfo->members[i].m_static_member_address = dac_cast<TADDR>(pAddress);
125                     }
126                 }
127
128                 typeInfo->members[i].m_member_type =
129                     GetTypeInfoFromTypeHandle(pField->GetExactFieldType(typeHandle), pTypeMap, method);
130
131                 // handle the System.String case:
132                 // coerce type of the second field into array type
133                 if (pMT->IsString() && i == 1)
134                 {
135                     TypeInfoBase* elemTypeInfo = typeInfo->members[1].m_member_type;
136                     typeInfo->m_array_type = new ArrayTypeInfo(typeHandle.MakeSZArray(), 1, elemTypeInfo);
137                     typeInfo->members[1].m_member_type = typeInfo->m_array_type;
138                 }
139             }
140             // Ignore inheritance from System.Object and System.ValueType classes.
141             if (!typeHandle.IsValueType() &&
142                 pMT->GetParentMethodTable() && pMT->GetParentMethodTable()->GetParentMethodTable())
143             {
144                 typeInfo->m_parent = GetTypeInfoFromTypeHandle(typeHandle.GetParent(), pTypeMap, method);
145             }
146
147             if (refTypeInfo)
148                 return refTypeInfo;
149             else
150                 return typeInfo;
151         }
152         case ELEMENT_TYPE_PTR:
153         case ELEMENT_TYPE_BYREF:
154         {
155             TypeInfoBase* valTypeInfo = GetTypeInfoFromTypeHandle(typeHandle.GetTypeParam(), pTypeMap, method);
156             NewHolder<RefTypeInfo> typeInfo = new RefTypeInfo(typeHandle, valTypeInfo);
157
158             typeInfo->m_type_offset = valTypeInfo->m_type_offset;
159
160             pTypeMap->Add(typeInfo->GetTypeKey(), typeInfo);
161             typeInfo.SuppressRelease();
162             return typeInfo;
163         }
164         case ELEMENT_TYPE_ARRAY:
165         case ELEMENT_TYPE_SZARRAY:
166         {
167             NewHolder<ClassTypeInfo> info = new ClassTypeInfo(typeHandle, pMT->GetRank() == 1 ? 2 : 3, method);
168             NewHolder<RefTypeInfo> refTypeInfo = new NamedRefTypeInfo(typeHandle, info);
169             info.SuppressRelease();
170
171             pTypeMap->Add(refTypeInfo->GetTypeKey(), refTypeInfo);
172             refTypeInfo.SuppressRelease();
173
174             TypeInfoBase* lengthTypeInfo = GetTypeInfoFromTypeHandle(
175                 TypeHandle(MscorlibBinder::GetElementType(ELEMENT_TYPE_I4)), pTypeMap, method);
176
177             TypeInfoBase* valTypeInfo = GetTypeInfoFromTypeHandle(typeHandle.GetTypeParam(), pTypeMap, method);
178             info->m_array_type = new ArrayTypeInfo(typeHandle, 1, valTypeInfo);
179
180             info->members[0].m_member_name = new char[16];
181             strcpy(info->members[0].m_member_name, "m_NumComponents");
182             info->members[0].m_member_offset = ArrayBase::GetOffsetOfNumComponents();
183             info->members[0].m_member_type = lengthTypeInfo;
184
185             info->members[1].m_member_name = new char[7];
186             strcpy(info->members[1].m_member_name, "m_Data");
187             info->members[1].m_member_offset = ArrayBase::GetDataPtrOffset(pMT);
188             info->members[1].m_member_type = info->m_array_type;
189
190             if (pMT->GetRank() != 1)
191             {
192                 TypeHandle dwordArray(MscorlibBinder::GetElementType(ELEMENT_TYPE_I4));
193                 info->m_array_bounds_type = new ArrayTypeInfo(dwordArray.MakeSZArray(), pMT->GetRank(), lengthTypeInfo);
194                 info->members[2].m_member_name = new char[9];
195                 strcpy(info->members[2].m_member_name, "m_Bounds");
196                 info->members[2].m_member_offset = ArrayBase::GetBoundsOffset(pMT);
197                 info->members[2].m_member_type = info->m_array_bounds_type;
198             }
199
200             return refTypeInfo;
201         }
202         default:
203             COMPlusThrowHR(COR_E_NOTSUPPORTED);
204     }
205 }
206
207 TypeInfoBase* GetArgTypeInfo(MethodDesc* methodDescPtr,
208                     NotifyGdb::PTK_TypeInfoMap pTypeMap,
209                     unsigned ilIndex,
210                     FunctionMemberPtrArrayHolder &method)
211 {
212     MetaSig sig(methodDescPtr);
213     TypeHandle th;
214     if (ilIndex == 0)
215     {
216         th = sig.GetRetTypeHandleNT();
217     }
218     else
219     {
220         while (--ilIndex)
221             sig.SkipArg();
222
223         sig.NextArg();
224         th = sig.GetLastTypeHandleNT();
225     }
226     return GetTypeInfoFromTypeHandle(th, pTypeMap, method);
227 }
228
229 TypeInfoBase* GetLocalTypeInfo(MethodDesc *methodDescPtr,
230                       NotifyGdb::PTK_TypeInfoMap pTypeMap,
231                       unsigned ilIndex,
232                       FunctionMemberPtrArrayHolder &funcs)
233 {
234     COR_ILMETHOD_DECODER method(methodDescPtr->GetILHeader());
235     if (method.GetLocalVarSigTok())
236     {
237         DWORD cbSigLen;
238         PCCOR_SIGNATURE pComSig;
239
240         if (FAILED(methodDescPtr->GetMDImport()->GetSigFromToken(method.GetLocalVarSigTok(), &cbSigLen, &pComSig)))
241         {
242             printf("\nInvalid record");
243             return nullptr;
244         }
245
246         _ASSERTE(*pComSig == IMAGE_CEE_CS_CALLCONV_LOCAL_SIG);
247
248         SigTypeContext typeContext(methodDescPtr, TypeHandle());
249         MetaSig sig(pComSig, cbSigLen, methodDescPtr->GetModule(), &typeContext, MetaSig::sigLocalVars);
250         if (ilIndex > 0)
251         {
252             while (ilIndex--)
253                 sig.SkipArg();
254         }
255         sig.NextArg();
256         TypeHandle th = sig.GetLastTypeHandleNT();
257         return GetTypeInfoFromTypeHandle(th, pTypeMap, funcs);
258     }
259     return nullptr;
260 }
261
262 HRESULT GetArgNameByILIndex(MethodDesc* methodDescPtr, unsigned index, NewArrayHolder<char> &paramName)
263 {
264     IMDInternalImport* mdImport = methodDescPtr->GetMDImport();
265     mdParamDef paramToken;
266     USHORT seq;
267     DWORD attr;
268     HRESULT status;
269
270     // Param indexing is 1-based.
271     ULONG32 mdIndex = index + 1;
272
273     MetaSig sig(methodDescPtr);
274     if (sig.HasThis())
275     {
276         mdIndex--;
277     }
278     status = mdImport->FindParamOfMethod(methodDescPtr->GetMemberDef(), mdIndex, &paramToken);
279     if (status == S_OK)
280     {
281         LPCSTR name;
282         status = mdImport->GetParamDefProps(paramToken, &seq, &attr, &name);
283         paramName = new char[strlen(name) + 1];
284         strcpy(paramName, name);
285     }
286     return status;
287 }
288
289 // Copy-pasted from src/debug/di/module.cpp
290 HRESULT FindNativeInfoInILVariable(DWORD dwIndex,
291                                    SIZE_T ip,
292                                    ICorDebugInfo::NativeVarInfo* nativeInfoList,
293                                    unsigned int nativeInfoCount,
294                                    ICorDebugInfo::NativeVarInfo** ppNativeInfo)
295 {
296     _ASSERTE(ppNativeInfo != NULL);
297     *ppNativeInfo = NULL;
298     int lastGoodOne = -1;
299     for (unsigned int i = 0; i < (unsigned)nativeInfoCount; i++)
300     {
301         if (nativeInfoList[i].varNumber == dwIndex)
302         {
303             if ((lastGoodOne == -1) || (nativeInfoList[lastGoodOne].startOffset < nativeInfoList[i].startOffset))
304             {
305                 lastGoodOne = i;
306             }
307
308             if ((nativeInfoList[i].startOffset <= ip) &&
309                 (nativeInfoList[i].endOffset > ip))
310             {
311                 *ppNativeInfo = &(nativeInfoList[i]);
312
313                 return S_OK;
314             }
315         }
316     }
317
318     if ((lastGoodOne > -1) && (nativeInfoList[lastGoodOne].endOffset == ip))
319     {
320         *ppNativeInfo = &(nativeInfoList[lastGoodOne]);
321         return S_OK;
322     }
323
324     return CORDBG_E_IL_VAR_NOT_AVAILABLE;
325 }
326
327 BYTE* DebugInfoStoreNew(void * pData, size_t cBytes)
328 {
329     return new BYTE[cBytes];
330 }
331
332 /* Get IL to native offsets map */
333 HRESULT
334 GetMethodNativeMap(MethodDesc* methodDesc,
335                    ULONG32* numMap,
336                    NewArrayHolder<DebuggerILToNativeMap> &map,
337                    ULONG32* pcVars,
338                    ICorDebugInfo::NativeVarInfo** ppVars)
339 {
340     // Use the DebugInfoStore to get IL->Native maps.
341     // It doesn't matter whether we're jitted, ngenned etc.
342
343     DebugInfoRequest request;
344     TADDR nativeCodeStartAddr = PCODEToPINSTR(methodDesc->GetNativeCode());
345     request.InitFromStartingAddr(methodDesc, nativeCodeStartAddr);
346
347     // Bounds info.
348     ULONG32 countMapCopy;
349     NewHolder<ICorDebugInfo::OffsetMapping> mapCopy(NULL);
350
351     BOOL success = DebugInfoManager::GetBoundariesAndVars(request,
352                                                           DebugInfoStoreNew,
353                                                           NULL, // allocator
354                                                           &countMapCopy,
355                                                           &mapCopy,
356                                                           pcVars,
357                                                           ppVars);
358
359     if (!success)
360     {
361         return E_FAIL;
362     }
363
364     // Need to convert map formats.
365     *numMap = countMapCopy;
366
367     map = new DebuggerILToNativeMap[countMapCopy];
368
369     ULONG32 i;
370     for (i = 0; i < *numMap; i++)
371     {
372         map[i].ilOffset = mapCopy[i].ilOffset;
373         map[i].nativeStartOffset = mapCopy[i].nativeOffset;
374         if (i > 0)
375         {
376             map[i - 1].nativeEndOffset = map[i].nativeStartOffset;
377         }
378         map[i].source = mapCopy[i].source;
379     }
380     if (*numMap >= 1)
381     {
382         map[i - 1].nativeEndOffset = 0;
383     }
384     return S_OK;
385 }
386
387 HRESULT FunctionMember::GetLocalsDebugInfo(NotifyGdb::PTK_TypeInfoMap pTypeMap,
388                            LocalsInfo& locals,
389                            int startNativeOffset,
390                            FunctionMemberPtrArrayHolder &method)
391 {
392
393     ICorDebugInfo::NativeVarInfo* nativeVar = NULL;
394     int thisOffs = 0;
395     if (!md->IsStatic())
396     {
397         thisOffs = 1;
398     }
399
400     int i;
401     for (i = 0; i < m_num_args - thisOffs; i++)
402     {
403         if (FindNativeInfoInILVariable(i + thisOffs, startNativeOffset, locals.vars, locals.countVars, &nativeVar) == S_OK)
404         {
405             vars[i + thisOffs].m_var_type = GetArgTypeInfo(md, pTypeMap, i + 1, method);
406             GetArgNameByILIndex(md, i + thisOffs, vars[i + thisOffs].m_var_name);
407             vars[i + thisOffs].m_il_index = i;
408             vars[i + thisOffs].m_native_offset = nativeVar->loc.vlStk.vlsOffset;
409             vars[i + thisOffs].m_var_abbrev = 6;
410         }
411     }
412     //Add info about 'this' as first argument
413     if (thisOffs == 1)
414     {
415         if (FindNativeInfoInILVariable(0, startNativeOffset, locals.vars, locals.countVars, &nativeVar) == S_OK)
416         {
417             TypeHandle th = TypeHandle(md->GetMethodTable());
418             if (th.IsValueType())
419                 th = th.MakePointer();
420             vars[0].m_var_type = GetTypeInfoFromTypeHandle(th, pTypeMap, method);
421             vars[0].m_var_name = new char[strlen("this") + 1];
422             strcpy(vars[0].m_var_name, "this");
423             vars[0].m_il_index = 0;
424             vars[0].m_native_offset = nativeVar->loc.vlStk.vlsOffset;
425             vars[0].m_var_abbrev = 13;
426          }
427          i++;
428     }
429     for (; i < m_num_vars; i++)
430     {
431         if (FindNativeInfoInILVariable(
432                 i, startNativeOffset, locals.vars, locals.countVars, &nativeVar) == S_OK)
433         {
434             int ilIndex = i - m_num_args;
435             vars[i].m_var_type = GetLocalTypeInfo(md, pTypeMap, ilIndex, method);
436             vars[i].m_var_name = new char[strlen(locals.localsName[ilIndex]) + 1];
437             strcpy(vars[i].m_var_name, locals.localsName[ilIndex]);
438             vars[i].m_il_index = ilIndex;
439             vars[i].m_native_offset = nativeVar->loc.vlStk.vlsOffset;
440             vars[i].m_var_abbrev = 5;
441             TADDR nativeStart;
442             TADDR nativeEnd;
443             int ilLen = locals.localsScope[ilIndex].ilEndOffset - locals.localsScope[ilIndex].ilStartOffset;
444             if (GetBlockInNativeCode(locals.localsScope[ilIndex].ilStartOffset, ilLen, &nativeStart, &nativeEnd))
445             {
446                 vars[i].m_low_pc = md->GetNativeCode() + nativeStart;
447                 vars[i].m_high_pc = nativeEnd - nativeStart;
448             }
449         }
450     }
451     return S_OK;
452 }
453
454 MethodDebugInfo::MethodDebugInfo(int numPoints, int numLocals)
455 {
456     points = (SequencePointInfo*) CoTaskMemAlloc(sizeof(SequencePointInfo) * numPoints);
457     if (points == nullptr)
458     {
459         COMPlusThrowOM();
460     }
461     memset(points, 0, sizeof(SequencePointInfo) * numPoints);
462     size = numPoints;
463
464     if (numLocals == 0)
465     {
466         locals = nullptr;
467         localsSize = 0;
468         return;
469     }
470
471     locals = (LocalVarInfo*) CoTaskMemAlloc(sizeof(LocalVarInfo) * numLocals);
472     if (locals == nullptr)
473     {
474         CoTaskMemFree(points);
475         COMPlusThrowOM();
476     }
477     memset(locals, 0, sizeof(LocalVarInfo) * numLocals);
478     localsSize = numLocals;
479 }
480
481 MethodDebugInfo::~MethodDebugInfo()
482 {
483     if (locals)
484     {
485         for (int i = 0; i < localsSize; i++)
486             CoTaskMemFree(locals[i].name);
487         CoTaskMemFree(locals);
488     }
489
490     for (int i = 0; i < size; i++)
491         CoTaskMemFree(points[i].fileName);
492     CoTaskMemFree(points);
493 }
494
495 /* Get mapping of IL offsets to source line numbers */
496 HRESULT
497 GetDebugInfoFromPDB(MethodDesc* methodDescPtr,
498                     NewArrayHolder<SymbolsInfo> &symInfo,
499                     unsigned int &symInfoLen,
500                     LocalsInfo &locals)
501 {
502     NewArrayHolder<DebuggerILToNativeMap> map;
503     ULONG32 numMap;
504
505     if (!getInfoForMethodDelegate)
506         return E_FAIL;
507
508     if (GetMethodNativeMap(methodDescPtr, &numMap, map, &locals.countVars, &locals.vars) != S_OK)
509         return E_FAIL;
510
511     const Module* mod = methodDescPtr->GetMethodTable()->GetModule();
512     SString modName = mod->GetFile()->GetPath();
513     if (modName.IsEmpty())
514         return E_FAIL;
515
516     StackScratchBuffer scratch;
517     const char* szModName = modName.GetUTF8(scratch);
518
519     MethodDebugInfo methodDebugInfo(numMap, locals.countVars);
520
521     if (getInfoForMethodDelegate(szModName, methodDescPtr->GetMemberDef(), methodDebugInfo) == FALSE)
522         return E_FAIL;
523
524     symInfoLen = numMap;
525     symInfo = new SymbolsInfo[numMap];
526
527     locals.size = methodDebugInfo.localsSize;
528     locals.localsName = new NewArrayHolder<char>[locals.size];
529     locals.localsScope = new LocalsInfo::Scope [locals.size];
530
531     for (ULONG32 i = 0; i < locals.size; i++)
532     {
533         size_t sizeRequired = WideCharToMultiByte(CP_UTF8, 0, methodDebugInfo.locals[i].name, -1, NULL, 0, NULL, NULL);
534         locals.localsName[i] = new char[sizeRequired];
535
536         int len = WideCharToMultiByte(
537             CP_UTF8, 0, methodDebugInfo.locals[i].name, -1, locals.localsName[i], sizeRequired, NULL, NULL);
538         locals.localsScope[i].ilStartOffset = methodDebugInfo.locals[i].startOffset;
539         locals.localsScope[i].ilEndOffset = methodDebugInfo.locals[i].endOffset;
540     }
541
542     for (ULONG32 j = 0; j < numMap; j++)
543     {
544         SymbolsInfo& s = symInfo[j];
545
546         if (j == 0) {
547             s.fileName[0] = 0;
548             s.lineNumber = 0;
549             s.fileIndex = 0;
550         } else {
551             s = symInfo[j - 1];
552         }
553         s.nativeOffset = map[j].nativeStartOffset;
554         s.ilOffset = map[j].ilOffset;
555         s.source = map[j].source;
556         s.lineNumber = 0;
557
558         for (ULONG32 i = 0; i < methodDebugInfo.size; i++)
559         {
560             const SequencePointInfo& sp = methodDebugInfo.points[i];
561
562             if (methodDebugInfo.points[i].ilOffset == map[j].ilOffset)
563             {
564                 s.fileIndex = 0;
565                 int len = WideCharToMultiByte(CP_UTF8, 0, sp.fileName, -1, s.fileName, sizeof(s.fileName), NULL, NULL);
566                 s.fileName[len] = 0;
567                 s.lineNumber = sp.lineNumber;
568                 break;
569             }
570         }
571     }
572
573     return S_OK;
574 }
575
576 /* LEB128 for 32-bit unsigned integer */
577 int Leb128Encode(uint32_t num, char* buf, int size)
578 {
579     int i = 0;
580
581     do
582     {
583         uint8_t byte = num & 0x7F;
584         if (i >= size)
585             break;
586         num >>= 7;
587         if (num != 0)
588             byte |= 0x80;
589         buf[i++] = byte;
590     }
591     while (num != 0);
592
593     return i;
594 }
595
596 /* LEB128 for 32-bit signed integer */
597 int Leb128Encode(int32_t num, char* buf, int size)
598 {
599     int i = 0;
600     bool hasMore = true, isNegative = num < 0;
601
602     while (hasMore && i < size)
603     {
604         uint8_t byte = num & 0x7F;
605         num >>= 7;
606
607         if ((num == 0 && (byte & 0x40) == 0) || (num  == -1 && (byte & 0x40) == 0x40))
608             hasMore = false;
609         else
610             byte |= 0x80;
611         buf[i++] = byte;
612     }
613
614     return i;
615 }
616
617 int GetFrameLocation(int nativeOffset, char* bufVarLoc)
618 {
619     char cnvBuf[16] = {0};
620     int len = Leb128Encode(static_cast<int32_t>(nativeOffset), cnvBuf, sizeof(cnvBuf));
621     bufVarLoc[0] = len + 1;
622     bufVarLoc[1] = DW_OP_fbreg;
623     for (int j = 0; j < len; j++)
624     {
625         bufVarLoc[j + 2] = cnvBuf[j];
626     }
627
628     return len + 2;  // We add '2' because first 2 bytes contain length of expression and DW_OP_fbreg operation.
629 }
630
631 // GDB JIT interface
632 typedef enum
633 {
634   JIT_NOACTION = 0,
635   JIT_REGISTER_FN,
636   JIT_UNREGISTER_FN
637 } jit_actions_t;
638
639 struct jit_code_entry
640 {
641   struct jit_code_entry *next_entry;
642   struct jit_code_entry *prev_entry;
643   const char *symfile_addr;
644   UINT64 symfile_size;
645 };
646
647 struct jit_descriptor
648 {
649   UINT32 version;
650   /* This type should be jit_actions_t, but we use uint32_t
651      to be explicit about the bitwidth.  */
652   UINT32 action_flag;
653   struct jit_code_entry *relevant_entry;
654   struct jit_code_entry *first_entry;
655 };
656 // GDB puts a breakpoint in this function.
657 // To prevent from inlining we add noinline attribute and inline assembler statement.
658 extern "C"
659 void __attribute__((noinline)) __jit_debug_register_code() { __asm__(""); };
660
661 /* Make sure to specify the version statically, because the
662    debugger may check the version before we can set it.  */
663 struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
664
665 // END of GDB JIT interface
666
667 /* Static data for .debug_str section */
668 const char* DebugStrings[] = {
669   "CoreCLR", "" /* module name */, "" /* module path */
670 };
671
672 const int DebugStringCount = sizeof(DebugStrings) / sizeof(DebugStrings[0]);
673
674 /* Static data for .debug_abbrev */
675 const unsigned char AbbrevTable[] = {
676     1, DW_TAG_compile_unit, DW_CHILDREN_yes,
677         DW_AT_producer, DW_FORM_strp, DW_AT_language, DW_FORM_data2, DW_AT_name, DW_FORM_strp, DW_AT_comp_dir, DW_FORM_strp,
678         DW_AT_stmt_list, DW_FORM_sec_offset, 0, 0,
679
680     2, DW_TAG_base_type, DW_CHILDREN_no,
681         DW_AT_name, DW_FORM_strp, DW_AT_encoding, DW_FORM_data1, DW_AT_byte_size, DW_FORM_data1, 0, 0,
682
683     3, DW_TAG_typedef, DW_CHILDREN_no, DW_AT_name, DW_FORM_strp,
684         DW_AT_type, DW_FORM_ref4, 0, 0,
685
686     4, DW_TAG_subprogram, DW_CHILDREN_yes,
687         DW_AT_name, DW_FORM_strp, DW_AT_linkage_name, DW_FORM_strp, DW_AT_decl_file, DW_FORM_data1, DW_AT_decl_line, DW_FORM_data1,
688         DW_AT_type, DW_FORM_ref4, DW_AT_external, DW_FORM_flag_present,
689         DW_AT_low_pc, DW_FORM_addr, DW_AT_high_pc, DW_FORM_size,
690         DW_AT_frame_base, DW_FORM_exprloc, 0, 0,
691
692     5, DW_TAG_variable, DW_CHILDREN_no,
693         DW_AT_name, DW_FORM_strp, DW_AT_decl_file, DW_FORM_data1, DW_AT_decl_line, DW_FORM_data1, DW_AT_type,
694         DW_FORM_ref4, DW_AT_location, DW_FORM_exprloc, 0, 0,
695
696     6, DW_TAG_formal_parameter, DW_CHILDREN_no,
697         DW_AT_name, DW_FORM_strp, DW_AT_decl_file, DW_FORM_data1, DW_AT_decl_line, DW_FORM_data1, DW_AT_type,
698         DW_FORM_ref4, DW_AT_location, DW_FORM_exprloc, 0, 0,
699
700     7, DW_TAG_class_type, DW_CHILDREN_yes,
701         DW_AT_name, DW_FORM_strp, DW_AT_byte_size, DW_FORM_data4, 0, 0,
702
703     8, DW_TAG_member, DW_CHILDREN_no,
704         DW_AT_name, DW_FORM_strp, DW_AT_type, DW_FORM_ref4, DW_AT_data_member_location, DW_FORM_data4, 0, 0,
705
706     9, DW_TAG_pointer_type, DW_CHILDREN_no,
707         DW_AT_type, DW_FORM_ref4, DW_AT_byte_size, DW_FORM_data1, 0, 0,
708
709     10, DW_TAG_array_type, DW_CHILDREN_yes,
710         DW_AT_type, DW_FORM_ref4, 0, 0,
711
712     11, DW_TAG_subrange_type, DW_CHILDREN_no,
713         DW_AT_upper_bound, DW_FORM_exprloc, 0, 0,
714
715     12, DW_TAG_subprogram, DW_CHILDREN_yes,
716         DW_AT_name, DW_FORM_strp, DW_AT_linkage_name, DW_FORM_strp, DW_AT_decl_file, DW_FORM_data1, DW_AT_decl_line, DW_FORM_data1,
717         DW_AT_type, DW_FORM_ref4, DW_AT_external, DW_FORM_flag_present,
718         DW_AT_low_pc, DW_FORM_addr, DW_AT_high_pc, DW_FORM_size,
719         DW_AT_frame_base, DW_FORM_exprloc, DW_AT_object_pointer, DW_FORM_ref4, 0, 0,
720
721     13, DW_TAG_formal_parameter, DW_CHILDREN_no,
722         DW_AT_name, DW_FORM_strp, DW_AT_decl_file, DW_FORM_data1, DW_AT_decl_line, DW_FORM_data1, DW_AT_type,
723         DW_FORM_ref4, DW_AT_location, DW_FORM_exprloc, DW_AT_artificial, DW_FORM_flag_present, 0, 0,
724
725     14, DW_TAG_member, DW_CHILDREN_no,
726         DW_AT_name, DW_FORM_strp, DW_AT_type, DW_FORM_ref4, DW_AT_external, DW_FORM_flag_present, 0, 0,
727
728     15, DW_TAG_variable, DW_CHILDREN_no, DW_AT_specification, DW_FORM_ref4, DW_AT_location, DW_FORM_exprloc,
729         0, 0,
730
731     16, DW_TAG_try_block, DW_CHILDREN_no,
732         DW_AT_low_pc, DW_FORM_addr, DW_AT_high_pc, DW_FORM_size,
733         0, 0,
734
735     17, DW_TAG_catch_block, DW_CHILDREN_no,
736         DW_AT_low_pc, DW_FORM_addr, DW_AT_high_pc, DW_FORM_size,
737         0, 0,
738
739     18, DW_TAG_inheritance, DW_CHILDREN_no, DW_AT_type, DW_FORM_ref4, DW_AT_data_member_location, DW_FORM_data1,
740         0, 0,
741
742     19, DW_TAG_subrange_type, DW_CHILDREN_no,
743         DW_AT_upper_bound, DW_FORM_udata, 0, 0,
744
745     20, DW_TAG_lexical_block, DW_CHILDREN_yes,
746         DW_AT_low_pc, DW_FORM_addr, DW_AT_high_pc, DW_FORM_size,
747         0, 0,
748
749     0
750 };
751
752 const int AbbrevTableSize = sizeof(AbbrevTable);
753
754 /* Static data for .debug_line, including header */
755 #define DWARF_LINE_BASE (-5)
756 #define DWARF_LINE_RANGE 14
757 #define DWARF_OPCODE_BASE 13
758
759 #ifdef FEATURE_GDBJIT_LANGID_CS
760 /* TODO: use corresponding constant when it will be added to llvm */
761 #define DW_LANG_MICROSOFT_CSHARP 0x9e57
762 #endif
763
764 DwarfLineNumHeader LineNumHeader = {
765     0, 2, 0, 1, 1, DWARF_LINE_BASE, DWARF_LINE_RANGE, DWARF_OPCODE_BASE, {0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1}
766 };
767
768 /* Static data for .debug_info */
769 struct __attribute__((packed)) DebugInfoCU
770 {
771     uint8_t m_cu_abbrev;
772     uint32_t m_prod_off;
773     uint16_t m_lang;
774     uint32_t m_cu_name;
775     uint32_t m_cu_dir;
776     uint32_t m_line_num;
777 } debugInfoCU = {
778 #ifdef FEATURE_GDBJIT_LANGID_CS
779     1, 0, DW_LANG_MICROSOFT_CSHARP, 0, 0
780 #else
781     1, 0, DW_LANG_C89, 0, 0
782 #endif
783 };
784
785 struct __attribute__((packed)) DebugInfoTryCatchSub
786 {
787     uint8_t m_sub_abbrev;
788     uintptr_t m_sub_low_pc, m_sub_high_pc;
789 };
790
791 struct __attribute__((packed)) DebugInfoSub
792 {
793     uint8_t m_sub_abbrev;
794     uint32_t m_sub_name;
795     uint32_t m_linkage_name;
796     uint8_t m_file, m_line;
797     uint32_t m_sub_type;
798     uintptr_t m_sub_low_pc, m_sub_high_pc;
799     uint8_t m_sub_loc[2];
800 };
801
802 struct __attribute__((packed)) DebugInfoSubMember
803 {
804     DebugInfoSub sub;
805     uint32_t m_obj_ptr;
806 };
807
808 struct __attribute__((packed)) DebugInfoLexicalBlock
809 {
810     uint8_t m_abbrev;
811     uintptr_t m_low_pc, m_high_pc;
812 };
813
814 // Holder for array of pointers to FunctionMember objects
815 class FunctionMemberPtrArrayHolder : public NewArrayHolder<NewHolder<FunctionMember>>
816 {
817 private:
818     int m_cElements;
819
820 public:
821     explicit FunctionMemberPtrArrayHolder(int cElements) :
822         NewArrayHolder<NewHolder<FunctionMember>>(new NewHolder<FunctionMember>[cElements]),
823         m_cElements(cElements)
824     {
825     }
826
827     int GetCount() const
828     {
829         return m_cElements;
830     }
831 };
832
833 struct __attribute__((packed)) DebugInfoType
834 {
835     uint8_t m_type_abbrev;
836     uint32_t m_type_name;
837     uint8_t m_encoding;
838     uint8_t m_byte_size;
839 };
840
841 struct __attribute__((packed)) DebugInfoVar
842 {
843     uint8_t m_var_abbrev;
844     uint32_t m_var_name;
845     uint8_t m_var_file, m_var_line;
846     uint32_t m_var_type;
847 };
848
849 struct __attribute__((packed)) DebugInfoTypeDef
850 {
851     uint8_t m_typedef_abbrev;
852     uint32_t m_typedef_name;
853     uint32_t m_typedef_type;
854 };
855
856 struct __attribute__((packed)) DebugInfoClassType
857 {
858     uint8_t m_type_abbrev;
859     uint32_t m_type_name;
860     uint32_t m_byte_size;
861 };
862
863 struct __attribute__((packed)) DebugInfoInheritance
864 {
865     uint8_t m_abbrev;
866     uint32_t m_type;
867     uint8_t m_data_member_location;
868 };
869
870 struct __attribute__((packed)) DebugInfoClassMember
871 {
872     uint8_t m_member_abbrev;
873     uint32_t m_member_name;
874     uint32_t m_member_type;
875 };
876
877 struct __attribute__((packed)) DebugInfoStaticMember
878 {
879     uint8_t m_member_abbrev;
880     uint32_t m_member_specification;
881 };
882
883
884 struct __attribute__((packed)) DebugInfoRefType
885 {
886     uint8_t m_type_abbrev;
887     uint32_t m_ref_type;
888     uint8_t m_byte_size;
889 };
890
891 struct __attribute__((packed)) DebugInfoArrayType
892 {
893     uint8_t m_abbrev;
894     uint32_t m_type;
895 };
896
897 void TypeInfoBase::DumpStrings(char* ptr, int& offset)
898 {
899     if (ptr != nullptr)
900     {
901         strcpy(ptr + offset, m_type_name);
902         m_type_name_offset = offset;
903     }
904     offset += strlen(m_type_name) + 1;
905 }
906
907 void TypeInfoBase::CalculateName()
908 {
909     // name the type
910     SString sName;
911
912     const TypeString::FormatFlags formatFlags = static_cast<TypeString::FormatFlags>(
913         TypeString::FormatNamespace |
914         TypeString::FormatAngleBrackets);
915
916     TypeString::AppendType(sName, typeHandle, formatFlags);
917
918     StackScratchBuffer buffer;
919     const UTF8 *utf8 = sName.GetUTF8(buffer);
920     if (typeHandle.IsValueType())
921     {
922         m_type_name = new char[strlen(utf8) + 1];
923         strcpy(m_type_name, utf8);
924     }
925     else
926     {
927         m_type_name = new char[strlen(utf8) + 1 + 2];
928         strcpy(m_type_name, "__");
929         strcpy(m_type_name + 2, utf8);
930     }
931
932     // Fix nested names
933     for (char *p = m_type_name; *p; ++p)
934     {
935         if (*p == '+')
936             *p = '.';
937     }
938 }
939
940 void TypeInfoBase::SetTypeHandle(TypeHandle handle)
941 {
942     typeHandle = handle;
943     typeKey = handle.GetTypeKey();
944 }
945
946 TypeHandle TypeInfoBase::GetTypeHandle()
947 {
948     return typeHandle;
949 }
950
951 TypeKey* TypeInfoBase::GetTypeKey()
952 {
953     return &typeKey;
954 }
955
956 void TypeDefInfo::DumpStrings(char *ptr, int &offset)
957 {
958     if (ptr != nullptr)
959     {
960         strcpy(ptr + offset, m_typedef_name);
961         m_typedef_name_offset = offset;
962     }
963     offset += strlen(m_typedef_name) + 1;
964 }
965
966 void TypeDefInfo::DumpDebugInfo(char *ptr, int &offset)
967 {
968     if (m_is_visited && m_base_ptr == ptr)
969     {
970         return;
971     }
972
973     m_base_ptr = ptr;
974     m_is_visited = true;
975
976     if (ptr != nullptr)
977     {
978         DebugInfoTypeDef buf;
979         buf.m_typedef_abbrev = 3;
980         buf.m_typedef_name = m_typedef_name_offset;
981         buf.m_typedef_type = offset + sizeof(DebugInfoTypeDef);
982         m_typedef_type_offset = offset;
983
984         memcpy(ptr + offset,
985                &buf,
986                sizeof(DebugInfoTypeDef));
987     }
988
989     offset += sizeof(DebugInfoTypeDef);
990 }
991
992 static const char *GetCSharpTypeName(TypeInfoBase *typeInfo)
993 {
994     switch(typeInfo->GetTypeHandle().GetSignatureCorElementType())
995     {
996         case ELEMENT_TYPE_I1: return "sbyte";
997         case ELEMENT_TYPE_U1:  return "byte";
998         case ELEMENT_TYPE_CHAR: return "char";
999         case ELEMENT_TYPE_VOID: return "void";
1000         case ELEMENT_TYPE_BOOLEAN: return "bool";
1001         case ELEMENT_TYPE_I2: return "short";
1002         case ELEMENT_TYPE_U2: return "ushort";
1003         case ELEMENT_TYPE_I4: return "int";
1004         case ELEMENT_TYPE_U4: return "uint";
1005         case ELEMENT_TYPE_I8: return "long";
1006         case ELEMENT_TYPE_U8: return "ulong";
1007         case ELEMENT_TYPE_R4: return "float";
1008         case ELEMENT_TYPE_R8: return "double";
1009         default: return typeInfo->m_type_name;
1010     }
1011 }
1012
1013 PrimitiveTypeInfo::PrimitiveTypeInfo(TypeHandle typeHandle)
1014     : TypeInfoBase(typeHandle),
1015       m_typedef_info(new TypeDefInfo(nullptr, 0))
1016 {
1017     CorElementType corType = typeHandle.GetSignatureCorElementType();
1018     m_type_encoding = CorElementTypeToDWEncoding[corType];
1019     m_type_size = CorTypeInfo::Size(corType);
1020
1021     if (corType == ELEMENT_TYPE_CHAR)
1022     {
1023         m_type_name = new char[9];
1024         strcpy(m_type_name, "char16_t");
1025     }
1026     else
1027     {
1028         CalculateName();
1029     }
1030 }
1031
1032 void PrimitiveTypeInfo::DumpStrings(char* ptr, int& offset)
1033 {
1034     TypeInfoBase::DumpStrings(ptr, offset);
1035     if (!m_typedef_info->m_typedef_name)
1036     {
1037         const char *typeName = GetCSharpTypeName(this);
1038         m_typedef_info->m_typedef_name = new char[strlen(typeName) + 1];
1039         strcpy(m_typedef_info->m_typedef_name, typeName);
1040     }
1041     m_typedef_info->DumpStrings(ptr, offset);
1042 }
1043
1044 void PrimitiveTypeInfo::DumpDebugInfo(char *ptr, int &offset)
1045 {
1046     if (m_is_visited && m_base_ptr == ptr)
1047     {
1048         return;
1049     }
1050
1051     m_base_ptr = ptr;
1052     m_is_visited = true;
1053
1054     m_typedef_info->DumpDebugInfo(ptr, offset);
1055
1056     if (ptr != nullptr)
1057     {
1058         DebugInfoType bufType;
1059         bufType.m_type_abbrev = 2;
1060         bufType.m_type_name = m_type_name_offset;
1061         bufType.m_encoding = m_type_encoding;
1062         bufType.m_byte_size = m_type_size;
1063
1064         memcpy(ptr + offset,
1065                &bufType,
1066                sizeof(DebugInfoType));
1067
1068         // Replace offset from real type to typedef
1069         m_type_offset = m_typedef_info->m_typedef_type_offset;
1070     }
1071
1072     offset += sizeof(DebugInfoType);
1073 }
1074
1075 ClassTypeInfo::ClassTypeInfo(TypeHandle typeHandle, int num_members, FunctionMemberPtrArrayHolder &method)
1076         : TypeInfoBase(typeHandle),
1077           m_num_members(num_members),
1078           members(new TypeMember[num_members]),
1079           m_parent(nullptr),
1080           m_method(method),
1081           m_array_type(nullptr)
1082 {
1083     CorElementType corType = typeHandle.GetSignatureCorElementType();
1084     PTR_MethodTable pMT = typeHandle.GetMethodTable();
1085
1086     switch (corType)
1087     {
1088         case ELEMENT_TYPE_VALUETYPE:
1089         case ELEMENT_TYPE_CLASS:
1090             m_type_size = pMT->IsValueType() ? typeHandle.GetSize() : typeHandle.AsMethodTable()->GetBaseSize();
1091             break;
1092         case ELEMENT_TYPE_ARRAY:
1093         case ELEMENT_TYPE_SZARRAY:
1094             m_type_size = pMT->GetClass()->GetSize();
1095             break;
1096         default:
1097             m_type_size = 0;
1098     }
1099
1100     CalculateName();
1101 }
1102
1103 void TypeMember::DumpStrings(char* ptr, int& offset)
1104 {
1105     if (ptr != nullptr)
1106     {
1107         strcpy(ptr + offset, m_member_name);
1108         m_member_name_offset = offset;
1109     }
1110     offset += strlen(m_member_name) + 1;
1111 }
1112
1113 void TypeMember::DumpDebugInfo(char* ptr, int& offset)
1114 {
1115     if (ptr != nullptr)
1116     {
1117         DebugInfoClassMember memberEntry;
1118
1119         if (m_static_member_address == 0)
1120             memberEntry.m_member_abbrev = 8;
1121         else
1122         {
1123             memberEntry.m_member_abbrev = 14;
1124             m_member_offset = offset;
1125         }
1126         memberEntry.m_member_name = m_member_name_offset;
1127         memberEntry.m_member_type = m_member_type->m_type_offset;
1128
1129         memcpy(ptr + offset, &memberEntry, sizeof(DebugInfoClassMember));
1130         if (m_static_member_address == 0)
1131             memcpy(ptr + offset + sizeof(DebugInfoClassMember), &m_member_offset, sizeof(m_member_offset));
1132     }
1133     offset += sizeof(DebugInfoClassMember);
1134     if (m_static_member_address == 0)
1135         offset += sizeof(m_member_offset);
1136 }
1137
1138 void TypeMember::DumpStaticDebugInfo(char* ptr, int& offset)
1139 {
1140     const int ptrSize = sizeof(TADDR);
1141     const int valueTypeBufSize = ptrSize + 6;
1142     const int refTypeBufSize = ptrSize + 2;
1143
1144     bool isValueType = m_member_type->GetTypeHandle().GetSignatureCorElementType() ==
1145                             ELEMENT_TYPE_VALUETYPE;
1146     int bufSize;
1147     if (isValueType)
1148     {
1149         bufSize = valueTypeBufSize;
1150     }
1151     else
1152     {
1153         bufSize = refTypeBufSize;
1154     }
1155
1156     if (ptr != nullptr)
1157     {
1158         DebugInfoStaticMember memberEntry;
1159
1160         memberEntry.m_member_abbrev = 15;
1161         memberEntry.m_member_specification = m_member_offset;
1162         memcpy(ptr + offset, &memberEntry, sizeof(DebugInfoStaticMember));
1163
1164         // for value type static fields compute address as:
1165         // addr = (*addr+sizeof(OBJECTREF))
1166         if (isValueType)
1167         {
1168             char buf[valueTypeBufSize] = {0};
1169             buf[0] = ptrSize + 5;
1170             buf[1] = DW_OP_addr;
1171
1172             for (int i = 0; i < ptrSize; i++)
1173             {
1174                 buf[i + 2] = m_static_member_address >> (i * 8);
1175             }
1176
1177             buf[ptrSize + 2] = DW_OP_deref;
1178             buf[ptrSize + 3] = DW_OP_const1u;
1179             buf[ptrSize + 4] = sizeof(OBJECTREF);
1180             buf[ptrSize + 5] = DW_OP_plus;
1181
1182             memcpy(ptr + offset + sizeof(DebugInfoStaticMember), &buf, bufSize);
1183         }
1184         else
1185         {
1186             char buf[refTypeBufSize] = {0};
1187             buf[0] = ptrSize + 1;
1188             buf[1] = DW_OP_addr;
1189
1190             for (int i = 0; i < ptrSize; i++)
1191             {
1192                 buf[i + 2] = m_static_member_address >> (i * 8);
1193             }
1194
1195             memcpy(ptr + offset + sizeof(DebugInfoStaticMember), &buf, bufSize);
1196         }
1197     }
1198     offset += sizeof(DebugInfoStaticMember);
1199     offset += bufSize;
1200 }
1201
1202 void FunctionMember::MangleName(char *buf, int &buf_offset, const char *name)
1203 {
1204     int name_length = strlen(name);
1205
1206     char tmp[20];
1207     int tmp_len = sprintf_s(tmp, _countof(tmp), "%i", name_length);
1208     if (tmp_len <= 0)
1209         return;
1210
1211     if (buf)
1212         strncpy(buf + buf_offset, tmp, tmp_len);
1213     buf_offset += tmp_len;
1214
1215     if (buf)
1216     {
1217         for (int i = 0; i < name_length; i++)
1218         {
1219             char c = name[i];
1220             bool valid = (c >= 'a' && c <= 'z') ||
1221                          (c >= 'A' && c <= 'Z') ||
1222                          (c >= '0' && c <= '9');
1223             *(buf + buf_offset + i) = valid ? c : '_';
1224         }
1225     }
1226     buf_offset += name_length;
1227 }
1228
1229 void FunctionMember::DumpMangledNamespaceAndMethod(char *buf, int &offset, const char *nspace, const char *mname)
1230 {
1231     static const char *begin_mangled = "_ZN";
1232     static const char *end_mangled = "Ev";
1233     static const int begin_mangled_len = strlen(begin_mangled);
1234     static const int end_mangled_len = strlen(end_mangled);
1235
1236     if (buf)
1237         strncpy(buf + offset, begin_mangled, begin_mangled_len);
1238     offset += begin_mangled_len;
1239
1240     MangleName(buf, offset, nspace);
1241     MangleName(buf, offset, mname);
1242
1243     if (buf)
1244         strncpy(buf + offset, end_mangled, end_mangled_len);
1245     offset += end_mangled_len;
1246
1247     if (buf)
1248         buf[offset] = '\0';
1249     ++offset;
1250 }
1251
1252 void FunctionMember::DumpLinkageName(char* ptr, int& offset)
1253 {
1254     SString namespaceOrClassName;
1255     SString methodName;
1256
1257     md->GetMethodInfoNoSig(namespaceOrClassName, methodName);
1258     SString utf8namespaceOrClassName;
1259     SString utf8methodName;
1260     namespaceOrClassName.ConvertToUTF8(utf8namespaceOrClassName);
1261     methodName.ConvertToUTF8(utf8methodName);
1262
1263     const char *nspace = utf8namespaceOrClassName.GetUTF8NoConvert();
1264     const char *mname = utf8methodName.GetUTF8NoConvert();
1265
1266     if (!nspace || !mname)
1267     {
1268         m_linkage_name_offset = 0;
1269         return;
1270     }
1271
1272     m_linkage_name_offset = offset;
1273     DumpMangledNamespaceAndMethod(ptr, offset, nspace, mname);
1274 }
1275
1276 void FunctionMember::DumpStrings(char* ptr, int& offset)
1277 {
1278     TypeMember::DumpStrings(ptr, offset);
1279
1280     for (int i = 0; i < m_num_vars; ++i)
1281     {
1282         vars[i].DumpStrings(ptr, offset);
1283     }
1284
1285     DumpLinkageName(ptr, offset);
1286 }
1287
1288 bool FunctionMember::GetBlockInNativeCode(int blockILOffset, int blockILLen, TADDR *startOffset, TADDR *endOffset)
1289 {
1290     PCODE pCode = md->GetNativeCode();
1291
1292     const int blockILEnd = blockILOffset + blockILLen;
1293
1294     *startOffset = 0;
1295     *endOffset = 0;
1296
1297     bool inBlock = false;
1298
1299     for (int i = 0; i < nlines; ++i)
1300     {
1301         TADDR nativeOffset = lines[i].nativeOffset + pCode;
1302
1303         // Limit block search to current function addresses
1304         if (nativeOffset < m_sub_low_pc)
1305             continue;
1306         if (nativeOffset >= m_sub_low_pc + m_sub_high_pc)
1307             break;
1308
1309         // Skip invalid IL offsets
1310         switch(lines[i].ilOffset)
1311         {
1312             case ICorDebugInfo::PROLOG:
1313             case ICorDebugInfo::EPILOG:
1314             case ICorDebugInfo::NO_MAPPING:
1315                 continue;
1316             default:
1317                 break;
1318         }
1319
1320         // Check if current IL is within block
1321         if (blockILOffset <= lines[i].ilOffset && lines[i].ilOffset < blockILEnd)
1322         {
1323             if (!inBlock)
1324             {
1325                 *startOffset = lines[i].nativeOffset;
1326                 inBlock = true;
1327             }
1328         }
1329         else
1330         {
1331             if (inBlock)
1332             {
1333                 *endOffset = lines[i].nativeOffset;
1334                 inBlock = false;
1335                 break;
1336             }
1337         }
1338     }
1339
1340     if (inBlock)
1341     {
1342         *endOffset = m_sub_low_pc + m_sub_high_pc - pCode;
1343     }
1344
1345     return *endOffset != *startOffset;
1346 }
1347
1348 void FunctionMember::DumpTryCatchBlock(char* ptr, int& offset, int ilOffset, int ilLen, int abbrev)
1349 {
1350     TADDR startOffset;
1351     TADDR endOffset;
1352
1353     if (!GetBlockInNativeCode(ilOffset, ilLen, &startOffset, &endOffset))
1354         return;
1355
1356     if (ptr != nullptr)
1357     {
1358         DebugInfoTryCatchSub subEntry;
1359
1360         subEntry.m_sub_abbrev = abbrev;
1361         subEntry.m_sub_low_pc = md->GetNativeCode() + startOffset;
1362         subEntry.m_sub_high_pc = endOffset - startOffset;
1363
1364         memcpy(ptr + offset, &subEntry, sizeof(DebugInfoTryCatchSub));
1365     }
1366     offset += sizeof(DebugInfoTryCatchSub);
1367 }
1368
1369 void FunctionMember::DumpTryCatchDebugInfo(char* ptr, int& offset)
1370 {
1371     if (!md)
1372         return;
1373
1374     COR_ILMETHOD *pHeader = md->GetILHeader();
1375     COR_ILMETHOD_DECODER header(pHeader);
1376
1377     unsigned ehCount = header.EHCount();
1378
1379     for (unsigned e = 0; e < ehCount; e++)
1380     {
1381         IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT ehBuff;
1382         const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* ehInfo;
1383
1384         ehInfo = header.EH->EHClause(e, &ehBuff);
1385
1386         DumpTryCatchBlock(ptr, offset, ehInfo->TryOffset, ehInfo->TryLength, 16);
1387         DumpTryCatchBlock(ptr, offset, ehInfo->HandlerOffset, ehInfo->HandlerLength, 17);
1388     }
1389 }
1390
1391 void FunctionMember::DumpVarsWithScopes(char *ptr, int &offset)
1392 {
1393     NewArrayHolder<DebugInfoLexicalBlock> scopeStack = new DebugInfoLexicalBlock[m_num_vars];
1394
1395     int scopeStackSize = 0;
1396     for (int i = 0; i < m_num_vars; ++i)
1397     {
1398         if (vars[i].m_high_pc == 0) // no scope info
1399         {
1400             vars[i].DumpDebugInfo(ptr, offset);
1401             continue;
1402         }
1403
1404         // Try to step out to enclosing scope, finilizing scopes on the way
1405         while (scopeStackSize > 0 &&
1406                vars[i].m_low_pc >= (scopeStack[scopeStackSize - 1].m_low_pc +
1407                                     scopeStack[scopeStackSize - 1].m_high_pc))
1408         {
1409             // Finalize scope
1410             if (ptr != nullptr)
1411             {
1412                 memset(ptr + offset, 0, 1);
1413             }
1414             offset += 1;
1415
1416             scopeStackSize--;
1417         }
1418         // Continue adding to prev scope?
1419         if (scopeStackSize > 0 &&
1420             scopeStack[scopeStackSize - 1].m_low_pc == vars[i].m_low_pc &&
1421             scopeStack[scopeStackSize - 1].m_high_pc == vars[i].m_high_pc)
1422         {
1423             vars[i].DumpDebugInfo(ptr, offset);
1424             continue;
1425         }
1426         // Start new scope
1427         scopeStackSize++;
1428         scopeStack[scopeStackSize - 1].m_abbrev = 20;
1429         scopeStack[scopeStackSize - 1].m_low_pc = vars[i].m_low_pc;
1430         scopeStack[scopeStackSize - 1].m_high_pc = vars[i].m_high_pc;
1431
1432         if (ptr != nullptr)
1433         {
1434             memcpy(ptr + offset, scopeStack + (scopeStackSize - 1), sizeof(DebugInfoLexicalBlock));
1435         }
1436         offset += sizeof(DebugInfoLexicalBlock);
1437
1438         vars[i].DumpDebugInfo(ptr, offset);
1439     }
1440     // Finalize any remaining scopes
1441     while (scopeStackSize > 0)
1442     {
1443         if (ptr != nullptr)
1444         {
1445             memset(ptr + offset, 0, 1);
1446         }
1447         offset += 1;
1448
1449         scopeStackSize--;
1450     }
1451 }
1452
1453 void FunctionMember::DumpDebugInfo(char* ptr, int& offset)
1454 {
1455     if (ptr != nullptr)
1456     {
1457         DebugInfoSub subEntry;
1458
1459         subEntry.m_sub_abbrev = 4;
1460         subEntry.m_sub_name = m_member_name_offset;
1461         subEntry.m_linkage_name = m_linkage_name_offset;
1462         subEntry.m_file = m_file;
1463         subEntry.m_line = m_line;
1464         subEntry.m_sub_type = m_member_type->m_type_offset;
1465         subEntry.m_sub_low_pc = m_sub_low_pc;
1466         subEntry.m_sub_high_pc = m_sub_high_pc;
1467         subEntry.m_sub_loc[0] = m_sub_loc[0];
1468         subEntry.m_sub_loc[1] = m_sub_loc[1];
1469
1470         if (!md->IsStatic())
1471         {
1472             DebugInfoSubMember subMemberEntry;
1473             subEntry.m_sub_abbrev = 12;
1474             subMemberEntry.sub = subEntry;
1475             subMemberEntry.m_obj_ptr = offset+sizeof(DebugInfoSubMember);
1476             memcpy(ptr + offset, &subMemberEntry, sizeof(DebugInfoSubMember));
1477         }
1478         else
1479         {
1480             memcpy(ptr + offset, &subEntry, sizeof(DebugInfoSub));
1481         }
1482         m_entry_offset = offset;
1483         dumped = true;
1484     }
1485
1486     if (!md->IsStatic())
1487     {
1488         offset += sizeof(DebugInfoSubMember);
1489     }
1490     else
1491     {
1492         offset += sizeof(DebugInfoSub);
1493     }
1494
1495     DumpVarsWithScopes(ptr, offset);
1496
1497     DumpTryCatchDebugInfo(ptr, offset);
1498
1499     // terminate children
1500     if (ptr != nullptr)
1501     {
1502         ptr[offset] = 0;
1503     }
1504     offset++;
1505 }
1506
1507 int FunctionMember::GetArgsAndLocalsLen()
1508 {
1509     int locSize = 0;
1510     char tmpBuf[16];
1511
1512     // Format for DWARF location expression: [expression length][operation][offset in SLEB128 encoding]
1513     for (int i = 0; i < m_num_vars; i++)
1514     {
1515         locSize += 2; // First byte contains expression length, second byte contains operation (DW_OP_fbreg).
1516         locSize += Leb128Encode(static_cast<int32_t>(vars[i].m_native_offset), tmpBuf, sizeof(tmpBuf));
1517     }
1518     return locSize;
1519 }
1520
1521 void ClassTypeInfo::DumpStrings(char* ptr, int& offset)
1522 {
1523     TypeInfoBase::DumpStrings(ptr, offset);
1524
1525     for (int i = 0; i < m_num_members; ++i)
1526     {
1527         members[i].DumpStrings(ptr, offset);
1528     }
1529
1530     if (m_parent != nullptr)
1531     {
1532         m_parent->DumpStrings(ptr, offset);
1533     }
1534 }
1535
1536 void RefTypeInfo::DumpStrings(char* ptr, int& offset)
1537 {
1538     TypeInfoBase::DumpStrings(ptr, offset);
1539     m_value_type->DumpStrings(ptr, offset);
1540 }
1541
1542 void RefTypeInfo::DumpDebugInfo(char* ptr, int& offset)
1543 {
1544     if (m_is_visited && m_base_ptr == ptr)
1545     {
1546         return;
1547     }
1548
1549     m_base_ptr = ptr;
1550     m_is_visited = true;
1551
1552     m_type_offset = offset;
1553     offset += sizeof(DebugInfoRefType);
1554     m_value_type->DumpDebugInfo(ptr, offset);
1555     if (ptr != nullptr)
1556     {
1557         DebugInfoRefType refType;
1558         refType.m_type_abbrev = 9;
1559         refType.m_ref_type = m_value_type->m_type_offset;
1560         refType.m_byte_size = m_type_size;
1561         memcpy(ptr + m_type_offset, &refType, sizeof(DebugInfoRefType));
1562     }
1563     else
1564     {
1565         m_type_offset = 0;
1566     }
1567 }
1568
1569 void NamedRefTypeInfo::DumpDebugInfo(char* ptr, int& offset)
1570 {
1571     if (m_is_visited && m_base_ptr == ptr)
1572     {
1573         return;
1574     }
1575
1576     m_base_ptr = ptr;
1577     m_is_visited = true;
1578
1579     m_type_offset = offset;
1580     offset += sizeof(DebugInfoRefType) + sizeof(DebugInfoTypeDef);
1581     m_value_type->DumpDebugInfo(ptr, offset);
1582     if (ptr != nullptr)
1583     {
1584         DebugInfoRefType refType;
1585         refType.m_type_abbrev = 9;
1586         refType.m_ref_type = m_value_type->m_type_offset;
1587         refType.m_byte_size = m_type_size;
1588         memcpy(ptr + m_type_offset, &refType, sizeof(DebugInfoRefType));
1589
1590         DebugInfoTypeDef bugTypeDef;
1591         bugTypeDef.m_typedef_abbrev = 3;
1592         bugTypeDef.m_typedef_name = m_value_type->m_type_name_offset + 2;
1593         bugTypeDef.m_typedef_type = m_type_offset;
1594         memcpy(ptr + m_type_offset + sizeof(DebugInfoRefType), &bugTypeDef, sizeof(DebugInfoTypeDef));
1595         m_type_offset += sizeof(DebugInfoRefType);
1596     }
1597     else
1598     {
1599         m_type_offset = 0;
1600     }
1601 }
1602
1603 void ClassTypeInfo::DumpDebugInfo(char* ptr, int& offset)
1604 {
1605     if (m_is_visited && m_base_ptr == ptr)
1606     {
1607         return;
1608     }
1609
1610     m_base_ptr = ptr;
1611     m_is_visited = true;
1612
1613     if (m_parent != nullptr)
1614     {
1615         m_parent->DumpDebugInfo(ptr, offset);
1616     }
1617
1618     // make sure that types of all members are dumped
1619     for (int i = 0; i < m_num_members; ++i)
1620     {
1621         if (members[i].m_member_type != this)
1622         {
1623             members[i].m_member_type->DumpDebugInfo(ptr, offset);
1624         }
1625     }
1626
1627     if (ptr != nullptr)
1628     {
1629         DebugInfoClassType bufType;
1630         bufType.m_type_abbrev = 7;
1631         bufType.m_type_name = m_type_name_offset;
1632         bufType.m_byte_size = m_type_size;
1633
1634         memcpy(ptr + offset, &bufType, sizeof(DebugInfoClassType));
1635         m_type_offset = offset;
1636     }
1637     offset += sizeof(DebugInfoClassType);
1638
1639     for (int i = 0; i < m_num_members; ++i)
1640     {
1641         members[i].DumpDebugInfo(ptr, offset);
1642     }
1643
1644     for (int i = 0; i < m_method.GetCount(); ++i)
1645     {
1646         if (m_method[i]->md->GetMethodTable() == GetTypeHandle().GetMethodTable())
1647         {
1648             // our method is part of this class, we should dump it now before terminating members
1649             m_method[i]->DumpDebugInfo(ptr, offset);
1650         }
1651     }
1652
1653     if (m_parent != nullptr)
1654     {
1655         if (ptr != nullptr)
1656         {
1657             DebugInfoInheritance buf;
1658             buf.m_abbrev = 18;
1659             if (RefTypeInfo *m_p = dynamic_cast<RefTypeInfo*>(m_parent))
1660                 buf.m_type = m_p->m_value_type->m_type_offset;
1661             else
1662                 buf.m_type = m_parent->m_type_offset;
1663             buf.m_data_member_location = 0;
1664             memcpy(ptr + offset, &buf, sizeof(DebugInfoInheritance));
1665         }
1666         offset += sizeof(DebugInfoInheritance);
1667     }
1668
1669     // members terminator
1670     if (ptr != nullptr)
1671     {
1672         ptr[offset] = 0;
1673     }
1674     offset++;
1675
1676     for (int i = 0; i < m_num_members; ++i)
1677     {
1678         if (members[i].m_static_member_address != 0)
1679             members[i].DumpStaticDebugInfo(ptr, offset);
1680     }
1681 }
1682
1683 void ArrayTypeInfo::DumpDebugInfo(char* ptr, int& offset)
1684 {
1685     if (m_is_visited && m_base_ptr == ptr)
1686     {
1687         return;
1688     }
1689
1690     m_base_ptr = ptr;
1691     m_is_visited = true;
1692
1693     m_elem_type->DumpDebugInfo(ptr, offset);
1694
1695     if (ptr != nullptr)
1696     {
1697         DebugInfoArrayType arrType;
1698
1699         arrType.m_abbrev = 10; // DW_TAG_array_type abbrev
1700         arrType.m_type = m_elem_type->m_type_offset;
1701
1702         memcpy(ptr + offset, &arrType, sizeof(DebugInfoArrayType));
1703         m_type_offset = offset;
1704     }
1705     offset += sizeof(DebugInfoArrayType);
1706
1707     char tmp[16] = { 0 };
1708     int len = Leb128Encode(static_cast<uint32_t>(m_count - 1), tmp + 1, sizeof(tmp) - 1);
1709     if (ptr != nullptr)
1710     {
1711         tmp[0] = 19; // DW_TAG_subrange_type abbrev with const upper bound
1712         memcpy(ptr + offset, tmp, len + 1);
1713     }
1714     offset += len + 1;
1715
1716     if (ptr != nullptr)
1717     {
1718         memset(ptr + offset, 0, 1);
1719     }
1720     offset += 1;
1721 }
1722
1723 void VarDebugInfo::DumpStrings(char *ptr, int& offset)
1724 {
1725     if (ptr != nullptr)
1726     {
1727         strcpy(ptr + offset, m_var_name);
1728         m_var_name_offset = offset;
1729     }
1730     offset += strlen(m_var_name) + 1;
1731 }
1732
1733 void VarDebugInfo::DumpDebugInfo(char* ptr, int& offset)
1734 {
1735     char bufVarLoc[16];
1736     int len = GetFrameLocation(m_native_offset, bufVarLoc);
1737     if (ptr != nullptr)
1738     {
1739         DebugInfoVar bufVar;
1740
1741         bufVar.m_var_abbrev = m_var_abbrev;
1742         bufVar.m_var_name = m_var_name_offset;
1743         bufVar.m_var_file = 1;
1744         bufVar.m_var_line = 1;
1745         bufVar.m_var_type = m_var_type->m_type_offset;
1746         memcpy(ptr + offset, &bufVar, sizeof(DebugInfoVar));
1747         memcpy(ptr + offset + sizeof(DebugInfoVar), bufVarLoc, len);
1748     }
1749     offset += sizeof(DebugInfoVar);
1750     offset += len;
1751 }
1752
1753 /* static data for symbol strings */
1754 struct Elf_Symbol {
1755     const char* m_name;
1756     int m_off;
1757     TADDR m_value;
1758     int m_section, m_size;
1759     NewArrayHolder<char> m_symbol_name;
1760     Elf_Symbol() : m_name(nullptr), m_off(0), m_value(0), m_section(0), m_size(0) {}
1761 };
1762
1763 template <class T>
1764 static int countFuncs(T &arr, int n)
1765 {
1766     int count = 0;
1767     for (int i = 0; i < n; i++) {
1768         if (arr[i].ilOffset == ICorDebugInfo::PROLOG)
1769         {
1770             count++;
1771         }
1772     }
1773     return count;
1774 }
1775
1776 template <class T>
1777 static int getNextPrologueIndex(int from, T &arr, int n)
1778 {
1779     for (int i = from; i < n; ++i) {
1780         if (arr[i].ilOffset == ICorDebugInfo::PROLOG)
1781         {
1782             return i;
1783         }
1784     }
1785     return -1;
1786 }
1787
1788 static inline bool isListedModule(const WCHAR *wszModuleFile)
1789 {
1790     static NewArrayHolder<WCHAR> wszModuleNames = nullptr;
1791     static DWORD cBytesNeeded = 0;
1792
1793     // Get names of interesting modules from environment
1794     if (wszModuleNames == nullptr && cBytesNeeded == 0)
1795     {
1796         DWORD cCharsNeeded = GetEnvironmentVariableW(W("CORECLR_GDBJIT"), NULL, 0);
1797
1798         if (cCharsNeeded == 0)
1799         {
1800             cBytesNeeded = 0xffffffff;
1801             return false;
1802         }
1803
1804         WCHAR *wszModuleNamesBuf = new WCHAR[cCharsNeeded+1];
1805
1806         cCharsNeeded = GetEnvironmentVariableW(W("CORECLR_GDBJIT"), wszModuleNamesBuf, cCharsNeeded);
1807
1808         if (cCharsNeeded == 0)
1809         {
1810             delete[] wszModuleNamesBuf;
1811             cBytesNeeded = 0xffffffff;
1812             return false;
1813         }
1814
1815         wszModuleNames = wszModuleNamesBuf;
1816         cBytesNeeded = cCharsNeeded + 1;
1817     }
1818     else if (wszModuleNames == nullptr)
1819     {
1820         return false;
1821     }
1822
1823     _ASSERTE(wszModuleNames != nullptr && cBytesNeeded > 0);
1824
1825     BOOL isUserDebug = FALSE;
1826
1827     NewArrayHolder<WCHAR> wszModuleName = new WCHAR[cBytesNeeded];
1828     LPWSTR pComma = wcsstr(wszModuleNames, W(","));
1829     LPWSTR tmp = wszModuleNames;
1830
1831     while (pComma != NULL)
1832     {
1833         wcsncpy(wszModuleName, tmp, pComma - tmp);
1834         wszModuleName[pComma - tmp] = W('\0');
1835
1836         if (wcscmp(wszModuleName, wszModuleFile) == 0)
1837         {
1838             isUserDebug = TRUE;
1839             break;
1840         }
1841         tmp = pComma + 1;
1842         pComma = wcsstr(tmp, W(","));
1843     }
1844     if (isUserDebug == FALSE)
1845     {
1846         wcsncpy(wszModuleName, tmp, wcslen(tmp));
1847         wszModuleName[wcslen(tmp)] = W('\0');
1848         if (wcscmp(wszModuleName, wszModuleFile) == 0)
1849         {
1850             isUserDebug = TRUE;
1851         }
1852     }
1853
1854     return isUserDebug;
1855 }
1856
1857 static NotifyGdb::AddrSet codeAddrs;
1858
1859 class Elf_SectionTracker
1860 {
1861     private:
1862         unsigned int m_Flag;
1863
1864     private:
1865         NewArrayHolder<char>  m_NamePtr;
1866         unsigned int          m_NameLen;
1867
1868     private:
1869         unsigned int m_Ind;
1870         unsigned int m_Off;
1871         unsigned int m_Len;
1872
1873     private:
1874         Elf_Shdr m_Hdr;
1875
1876     private:
1877         Elf_SectionTracker *m_Next;
1878
1879     public:
1880         Elf_SectionTracker(const char *name, unsigned ind, unsigned off, uint32_t type, uint64_t flags);
1881         ~Elf_SectionTracker();
1882
1883     public:
1884         bool NeedHeaderUpdate() const;
1885         void DisableHeaderUpdate();
1886
1887     public:
1888         unsigned int GetIndex() const   { return m_Ind; }
1889         unsigned int GetOffset() const  { return m_Off; }
1890         unsigned int GetSize() const    { return m_Len; }
1891
1892     public:
1893         const char *GetName() const     { return m_NamePtr; }
1894         unsigned int GetNameLen() const { return m_NameLen; }
1895
1896     public:
1897         Elf_SectionTracker *GetNext(void);
1898         void SetNext(Elf_SectionTracker *next);
1899
1900     public:
1901         void Forward(unsigned int len);
1902
1903     public:
1904         Elf_Shdr *Header(void);
1905         const Elf_Shdr *Header(void) const;
1906
1907 };
1908
1909 Elf_SectionTracker::Elf_SectionTracker(const char *name,
1910                                        unsigned ind, unsigned off,
1911                                        uint32_t type, uint64_t flags)
1912     : m_Flag(0),
1913       m_NamePtr(nullptr),
1914       m_NameLen(0),
1915       m_Ind(ind),
1916       m_Off(off),
1917       m_Len(0),
1918       m_Next(nullptr)
1919 {
1920     if (name)
1921     {
1922         unsigned int len = strlen(name);
1923         char *ptr = new char[len + 1];
1924
1925         strncpy(ptr, name, len + 1);
1926
1927         m_NamePtr = ptr;
1928         m_NameLen = len;
1929     }
1930
1931     m_Hdr.sh_type       = type;
1932     m_Hdr.sh_flags      = flags;
1933     m_Hdr.sh_name       = 0;
1934     m_Hdr.sh_addr       = 0;
1935     m_Hdr.sh_offset     = 0;
1936     m_Hdr.sh_size       = 0;
1937     m_Hdr.sh_link       = SHN_UNDEF;
1938     m_Hdr.sh_info       = 0;
1939     m_Hdr.sh_addralign  = 1;
1940     m_Hdr.sh_entsize    = 0;
1941 }
1942
1943 Elf_SectionTracker::~Elf_SectionTracker()
1944 {
1945 }
1946
1947 #define ESTF_NO_HEADER_UPDATE 0x00000001
1948
1949 bool Elf_SectionTracker::NeedHeaderUpdate() const
1950 {
1951     return !(m_Flag & ESTF_NO_HEADER_UPDATE);
1952 }
1953
1954 void Elf_SectionTracker::DisableHeaderUpdate()
1955 {
1956     m_Flag |= ESTF_NO_HEADER_UPDATE;
1957 }
1958
1959 void Elf_SectionTracker::Forward(unsigned int len)
1960 {
1961     m_Len += len;
1962 }
1963
1964 void Elf_SectionTracker::SetNext(Elf_SectionTracker *next)
1965 {
1966     m_Next = next;
1967 }
1968
1969 Elf_SectionTracker *Elf_SectionTracker::GetNext(void)
1970 {
1971     return m_Next;
1972 }
1973
1974 Elf_Shdr *Elf_SectionTracker::Header(void)
1975 {
1976     return &m_Hdr;
1977 }
1978
1979 const Elf_Shdr *Elf_SectionTracker::Header(void) const
1980 {
1981     return &m_Hdr;
1982 }
1983
1984 class Elf_Buffer
1985 {
1986     private:
1987         NewArrayHolder<char>  m_Ptr;
1988         unsigned int          m_Len;
1989         unsigned int          m_Pos;
1990
1991     public:
1992         Elf_Buffer(unsigned int len);
1993
1994     private:
1995         char *Ensure(unsigned int len);
1996         void Forward(unsigned int len);
1997
1998     public:
1999         unsigned int GetPos() const
2000         {
2001             return m_Pos;
2002         }
2003
2004         char *GetPtr(unsigned int off = 0)
2005         {
2006             return m_Ptr.GetValue() + off;
2007         }
2008
2009     public:
2010         char *Reserve(unsigned int len);
2011         template <typename T> T *ReserveT(unsigned int len = sizeof(T))
2012         {
2013             _ASSERTE(len >= sizeof(T));
2014             return reinterpret_cast<T *>(Reserve(len));
2015         }
2016
2017     public:
2018         void Append(const char *src, unsigned int len);
2019         template <typename T> void AppendT(T *src)
2020         {
2021             Append(reinterpret_cast<const char *>(src), sizeof(T));
2022         }
2023 };
2024
2025 Elf_Buffer::Elf_Buffer(unsigned int len)
2026     : m_Ptr(new char[len])
2027     , m_Len(len)
2028     , m_Pos(0)
2029 {
2030 }
2031
2032 char *Elf_Buffer::Ensure(unsigned int len)
2033 {
2034     bool bAdjusted = false;
2035
2036     while (m_Pos + len > m_Len)
2037     {
2038         m_Len *= 2;
2039         bAdjusted = true;
2040     }
2041
2042     if (bAdjusted)
2043     {
2044         char *ptr = new char [m_Len * 2];
2045         memcpy(ptr, m_Ptr.GetValue(), m_Pos);
2046         m_Ptr = ptr;
2047     }
2048
2049     return GetPtr(m_Pos);
2050 }
2051
2052 void Elf_Buffer::Forward(unsigned int len)
2053 {
2054     m_Pos += len;
2055 }
2056
2057 char *Elf_Buffer::Reserve(unsigned int len)
2058 {
2059     char *ptr = Ensure(len);
2060     Forward(len);
2061     return ptr;
2062 }
2063
2064 void Elf_Buffer::Append(const char *src, unsigned int len)
2065 {
2066     char *dst = Reserve(len);
2067     memcpy(dst, src, len);
2068 }
2069
2070 #define ELF_BUILDER_TEXT_SECTION_INDEX 1
2071
2072 class Elf_Builder
2073 {
2074     private:
2075         Elf_Buffer m_Buffer;
2076
2077     private:
2078         unsigned int          m_SectionCount;
2079         Elf_SectionTracker   *m_First;
2080         Elf_SectionTracker   *m_Last;
2081         Elf_SectionTracker   *m_Curr;
2082
2083     public:
2084         Elf_Builder();
2085         ~Elf_Builder();
2086
2087     public:
2088         unsigned int GetSectionCount(void) { return m_SectionCount; }
2089
2090     public:
2091         void Initialize(PCODE codePtr, TADDR codeLen);
2092
2093     public:
2094         Elf_SectionTracker *OpenSection(const char *name, uint32_t type, uint64_t flags);
2095         void CloseSection();
2096
2097     public:
2098         char *Reserve(unsigned int len);
2099         template <typename T> T *ReserveT(unsigned int len = sizeof(T))
2100         {
2101             _ASSERTE(len >= sizeof(T));
2102             return reinterpret_cast<T *>(Reserve(len));
2103         }
2104
2105     public:
2106         void Append(const char *src, unsigned int len);
2107         template <typename T> void AppendT(T *src)
2108         {
2109             Append(reinterpret_cast<const char *>(src), sizeof(T));
2110         }
2111
2112     public:
2113         void Finalize(void);
2114
2115     public:
2116         char *Export(size_t *len);
2117 };
2118
2119 Elf_Builder::Elf_Builder()
2120     : m_Buffer(128),
2121       m_SectionCount(0),
2122       m_First(nullptr),
2123       m_Last(nullptr),
2124       m_Curr(nullptr)
2125 {
2126 }
2127
2128 Elf_Builder::~Elf_Builder()
2129 {
2130     Elf_SectionTracker *curr = m_First;
2131
2132     while (curr)
2133     {
2134         Elf_SectionTracker *next = curr->GetNext();
2135         delete curr;
2136         curr = next;
2137     }
2138 }
2139
2140 void Elf_Builder::Initialize(PCODE codePtr, TADDR codeLen)
2141 {
2142     //
2143     // Reserve ELF Header
2144     //
2145     m_Buffer.Reserve(sizeof(Elf_Ehdr));
2146
2147     //
2148     // Create NULL section
2149     //
2150     Elf_SectionTracker *null = OpenSection("", SHT_NULL, 0);
2151     {
2152         null->DisableHeaderUpdate();
2153         null->Header()->sh_addralign = 0;
2154     }
2155     CloseSection();
2156
2157     //
2158     // Create '.text' section
2159     //
2160     Elf_SectionTracker *text = OpenSection(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
2161     {
2162         text->DisableHeaderUpdate();
2163         text->Header()->sh_addr = codePtr;
2164         text->Header()->sh_size = codeLen;
2165
2166         _ASSERTE(text->GetIndex() == ELF_BUILDER_TEXT_SECTION_INDEX);
2167     }
2168     CloseSection();
2169 }
2170
2171 char *Elf_Builder::Reserve(unsigned int len)
2172 {
2173     _ASSERTE(m_Curr != nullptr && "Section should be opened before");
2174     char *ptr = m_Buffer.Reserve(len);
2175     m_Curr->Forward(len);
2176     return ptr;
2177 }
2178
2179 void  Elf_Builder::Append(const char *src, unsigned int len)
2180 {
2181     _ASSERTE(m_Curr != nullptr && "Section should be opened before");
2182     char *dst = Reserve(len);
2183     memcpy(dst, src, len);
2184 }
2185
2186 Elf_SectionTracker *Elf_Builder::OpenSection(const char *name, uint32_t type, uint64_t flags)
2187 {
2188     _ASSERTE(m_Curr == nullptr && "Section should be closed before");
2189
2190     Elf_SectionTracker *next = new Elf_SectionTracker(name, m_SectionCount, m_Buffer.GetPos(), type, flags);
2191
2192     if (m_First == NULL)
2193     {
2194         m_First = next;
2195     }
2196
2197     if (m_Last != NULL)
2198     {
2199         m_Last->SetNext(next);
2200     }
2201
2202     m_SectionCount++;
2203
2204     m_Last = next;
2205     m_Curr = next;
2206
2207     return next;
2208 }
2209
2210 void Elf_Builder::CloseSection()
2211 {
2212     _ASSERTE(m_Curr != nullptr && "Section should be opened before");
2213     m_Curr = nullptr;
2214 }
2215
2216 char *Elf_Builder::Export(size_t *pLen)
2217 {
2218     unsigned int len = m_Buffer.GetPos();
2219     const char  *src = m_Buffer.GetPtr();
2220     char        *dst = new char[len];
2221
2222     memcpy(dst, src, len);
2223
2224     if (pLen)
2225     {
2226         *pLen = len;
2227     }
2228
2229     return dst;
2230 }
2231
2232 void Elf_Builder::Finalize()
2233 {
2234     //
2235     // Create '.shstrtab'
2236     //
2237     Elf_SectionTracker *shstrtab = OpenSection(".shstrtab", SHT_STRTAB, 0);
2238     {
2239         Elf_SectionTracker *curr = m_First;
2240
2241         while (curr)
2242         {
2243             unsigned int off = shstrtab->GetSize();
2244             unsigned int len = curr->GetNameLen();
2245
2246             char *dst = Reserve(len + 1);
2247             memcpy(dst, curr->GetName(), len);
2248             dst[len] = '\0';
2249
2250             curr->Header()->sh_name = off;
2251
2252             curr = curr->GetNext();
2253         }
2254     }
2255     CloseSection();
2256
2257     //
2258     // Create Section Header(s) Table
2259     //
2260     unsigned int shtOffset = m_Buffer.GetPos();
2261     {
2262         Elf_SectionTracker *curr = m_First;
2263
2264         while (curr)
2265         {
2266             if (curr->NeedHeaderUpdate())
2267             {
2268                 curr->Header()->sh_offset  = curr->GetOffset();
2269                 curr->Header()->sh_size    = curr->GetSize();
2270             }
2271             m_Buffer.AppendT(curr->Header());
2272             curr = curr->GetNext();
2273         }
2274     }
2275
2276     //
2277     // Update ELF Header
2278     //
2279     Elf_Ehdr *elfHeader = new (m_Buffer.GetPtr()) Elf_Ehdr;
2280
2281 #ifdef _TARGET_ARM_
2282     elfHeader->e_flags = EF_ARM_EABI_VER5;
2283 #ifdef ARM_SOFTFP
2284     elfHeader->e_flags |= EF_ARM_SOFT_FLOAT;
2285 #else
2286     elfHeader->e_flags |= EF_ARM_VFP_FLOAT;
2287 #endif
2288 #endif
2289     elfHeader->e_shoff = shtOffset;
2290     elfHeader->e_shentsize = sizeof(Elf_Shdr);
2291     elfHeader->e_shnum = m_SectionCount;
2292     elfHeader->e_shstrndx = shstrtab->GetIndex();
2293 }
2294
2295 #ifdef FEATURE_GDBJIT_FRAME
2296 struct __attribute__((packed)) Length
2297 {
2298     UINT32 value;
2299
2300     Length &operator=(UINT32 n)
2301     {
2302         value = n;
2303         return *this;
2304     }
2305
2306     Length()
2307     {
2308         value = 0;
2309     }
2310 };
2311
2312 struct __attribute__((packed)) CIE
2313 {
2314     Length  length;
2315     UINT32  id;
2316     UINT8   version;
2317     UINT8   augmentation;
2318     UINT8   code_alignment_factor;
2319     INT8    data_alignment_factor;
2320     UINT8   return_address_register;
2321     UINT8   instructions[0];
2322 };
2323
2324 struct __attribute__((packed)) FDE
2325 {
2326     Length  length;
2327     UINT32  cie;
2328     PCODE   initial_location;
2329     TADDR   address_range;
2330     UINT8   instructions[0];
2331 };
2332
2333 static void BuildDebugFrame(Elf_Builder &elfBuilder, PCODE pCode, TADDR codeSize)
2334 {
2335 #if defined(_TARGET_ARM_)
2336     const unsigned int code_alignment_factor = 2;
2337     const int data_alignment_factor = -4;
2338
2339     UINT8 cieCode[] = {
2340         // DW_CFA_def_cfa 13[sp], 0
2341         0x0c, 0x0d, 0x00,
2342     };
2343
2344     UINT8 fdeCode[] = {
2345         // DW_CFA_advance_loc 1
2346        0x02, 0x01,
2347        // DW_CFA_def_cfa_offset 8
2348        0x0e, 0x08,
2349        // DW_CFA_offset 11(r11), -8(= -4 * 2)
2350        (0x02 << 6) | 0x0b, 0x02,
2351        // DW_CFA_offset 14(lr),  -4(= -4 * 1)
2352        (0x02 << 6) | 0x0e, 0x01,
2353        // DW_CFA_def_cfa_register 11(r11)
2354        0x0d, 0x0b,
2355     };
2356 #elif defined(_TARGET_X86_)
2357     const unsigned int code_alignment_factor = 1;
2358     const int data_alignment_factor = -4;
2359
2360     UINT8 cieCode[] = {
2361         // DW_CFA_def_cfa 4(esp), 4
2362         0x0c, 0x04, 0x04,
2363         // DW_CFA_offset 8(eip), -4(= -4 * 1)
2364        (0x02 << 6) | 0x08, 0x01,
2365     };
2366
2367     UINT8 fdeCode[] = {
2368         // DW_CFA_advance_loc 1
2369        0x02, 0x01,
2370        // DW_CFA_def_cfa_offset 8
2371        0x0e, 0x08,
2372        // DW_CFA_offset 5(ebp), -8(= -4 * 2)
2373        (0x02 << 6) | 0x05, 0x02,
2374        // DW_CFA_def_cfa_register 5(ebp)
2375        0x0d, 0x05,
2376     };
2377 #elif defined(_TARGET_AMD64_)
2378     const unsigned int code_alignment_factor = 1;
2379     const int data_alignment_factor = -8;
2380
2381     UINT8 cieCode[] = {
2382       // DW_CFA_def_cfa 7(rsp), 8
2383       0x0c, 0x07, 0x08,
2384       // DW_CFA_offset 16, -16 (= -8 * 2)
2385       (0x02 << 6) | 0x10, 0x01,
2386     };
2387
2388     UINT8 fdeCode[] = {
2389       // DW_CFA_advance_loc(1)
2390       0x02, 0x01,
2391       // DW_CFA_def_cfa_offset(16)
2392       0x0e, 0x10,
2393       // DW_CFA_offset 6, -16 (= -8 * 2)
2394       (0x02 << 6) | 0x06, 0x02,
2395       // DW_CFA_def_cfa_register(6)
2396       0x0d, 0x06,
2397     };
2398 #else
2399 #error "Unsupported architecture"
2400 #endif
2401
2402     elfBuilder.OpenSection(".debug_frame", SHT_PROGBITS, 0);
2403
2404     //
2405     // Common Information Entry
2406     //
2407     int cieLen = ALIGN_UP(sizeof(CIE) + sizeof(cieCode), ADDRESS_SIZE) + sizeof(Length);
2408
2409     CIE *pCIE = elfBuilder.ReserveT<CIE>(cieLen);
2410
2411     memset(pCIE, 0, cieLen);
2412
2413     pCIE->length  = cieLen - sizeof(Length);
2414     pCIE->id      = 0xffffffff;
2415     pCIE->version = 3;
2416     pCIE->augmentation = 0;
2417     Leb128Encode(code_alignment_factor, reinterpret_cast<char *>(&pCIE->code_alignment_factor), 1);
2418     Leb128Encode(data_alignment_factor, reinterpret_cast<char *>(&pCIE->data_alignment_factor), 1);
2419
2420     pCIE->return_address_register = 0;
2421
2422     memcpy(&pCIE->instructions, cieCode, sizeof(cieCode));
2423
2424     //
2425     // Frame Description Entry
2426     //
2427     int fdeLen = ALIGN_UP((sizeof(FDE) + sizeof(fdeCode)), ADDRESS_SIZE) + sizeof(Length);
2428
2429     FDE *pFDE = elfBuilder.ReserveT<FDE>(fdeLen);
2430
2431     memset(pFDE, 0, fdeLen);
2432
2433     pFDE->length = fdeLen - sizeof(Length);
2434     pFDE->cie = 0;
2435     pFDE->initial_location = pCode;
2436     pFDE->address_range = codeSize;
2437     memcpy(&pFDE->instructions, fdeCode, sizeof(fdeCode));
2438
2439     elfBuilder.CloseSection();
2440 }
2441 #endif // FEATURE_GDBJIT_FRAME
2442
2443 /* Create ELF/DWARF debug info for jitted method */
2444 void NotifyGdb::MethodPrepared(MethodDesc* methodDescPtr)
2445 {
2446     EX_TRY
2447     {
2448         if (!tls_isSymReaderInProgress)
2449         {
2450             tls_isSymReaderInProgress = true;
2451             NotifyGdb::OnMethodPrepared(methodDescPtr);
2452             tls_isSymReaderInProgress = false;
2453         }
2454     }
2455     EX_CATCH
2456     {
2457     }
2458     EX_END_CATCH(SwallowAllExceptions);
2459 }
2460
2461 void NotifyGdb::OnMethodPrepared(MethodDesc* methodDescPtr)
2462 {
2463     PCODE pCode = methodDescPtr->GetNativeCode();
2464     if (pCode == NULL)
2465         return;
2466
2467     /* Get method name & size of jitted code */
2468     EECodeInfo codeInfo(pCode);
2469     if (!codeInfo.IsValid())
2470     {
2471         return;
2472     }
2473
2474     TADDR codeSize = codeInfo.GetCodeManager()->GetFunctionSize(codeInfo.GetGCInfoToken());
2475
2476     pCode = PCODEToPINSTR(pCode);
2477
2478     /* Get module name */
2479     const Module* mod = methodDescPtr->GetMethodTable()->GetModule();
2480     SString modName = mod->GetFile()->GetPath();
2481     StackScratchBuffer scratch;
2482     const char* szModName = modName.GetUTF8(scratch);
2483     const char* szModuleFile = SplitFilename(szModName);
2484
2485     int length = MultiByteToWideChar(CP_UTF8, 0, szModuleFile, -1, NULL, 0);
2486     if (length == 0)
2487         return;
2488     NewArrayHolder<WCHAR> wszModuleFile = new WCHAR[length+1];
2489     length = MultiByteToWideChar(CP_UTF8, 0, szModuleFile, -1, wszModuleFile, length);
2490
2491     if (length == 0)
2492         return;
2493
2494     bool bNotify = false;
2495
2496     Elf_Builder elfBuilder;
2497
2498     elfBuilder.Initialize(pCode, codeSize);
2499
2500 #ifdef FEATURE_GDBJIT_FRAME
2501     if (g_pConfig->ShouldEmitDebugFrame())
2502     {
2503         bool bEmitted = EmitFrameInfo(elfBuilder, pCode, codeSize);
2504         bNotify = bNotify || bEmitted;
2505     }
2506 #endif
2507
2508     if (isListedModule(wszModuleFile))
2509     {
2510         bool bEmitted = EmitDebugInfo(elfBuilder, methodDescPtr, pCode, codeSize);
2511         bNotify = bNotify || bEmitted;
2512     }
2513 #ifdef FEATURE_GDBJIT_SYMTAB
2514     else
2515     {
2516         bool bEmitted = EmitSymtab(elfBuilder, methodDescPtr, pCode, codeSize);
2517         bNotify = bNotify || bEmitted;
2518     }
2519 #endif
2520
2521     if (!bNotify)
2522     {
2523         return;
2524     }
2525
2526     elfBuilder.Finalize();
2527
2528     char   *symfile_addr = NULL;
2529     size_t  symfile_size = 0;
2530
2531     symfile_addr = elfBuilder.Export(&symfile_size);
2532
2533 #ifdef _DEBUG
2534     LPCUTF8 methodName = methodDescPtr->GetName();
2535
2536     if (g_pConfig->ShouldDumpElfOnMethod(methodName))
2537     {
2538         DumpElf(methodName, symfile_addr, symfile_size);
2539     }
2540 #endif
2541
2542     /* Create GDB JIT structures */
2543     NewHolder<jit_code_entry> jit_symbols = new jit_code_entry;
2544
2545     /* Fill the new entry */
2546     jit_symbols->next_entry = jit_symbols->prev_entry = 0;
2547     jit_symbols->symfile_addr = symfile_addr;
2548     jit_symbols->symfile_size = symfile_size;
2549
2550     /* Link into list */
2551     jit_code_entry *head = __jit_debug_descriptor.first_entry;
2552     __jit_debug_descriptor.first_entry = jit_symbols;
2553     if (head != 0)
2554     {
2555         jit_symbols->next_entry = head;
2556         head->prev_entry = jit_symbols;
2557     }
2558
2559     jit_symbols.SuppressRelease();
2560
2561     /* Notify the debugger */
2562     __jit_debug_descriptor.relevant_entry = jit_symbols;
2563     __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
2564     __jit_debug_register_code();
2565 }
2566
2567 #ifdef FEATURE_GDBJIT_FRAME
2568 bool NotifyGdb::EmitFrameInfo(Elf_Builder &elfBuilder, PCODE pCode, TADDR codeSize)
2569 {
2570     BuildDebugFrame(elfBuilder, pCode, codeSize);
2571     return true;
2572 }
2573 #endif // FEATURE_GDBJIT_FRAME
2574
2575 #ifdef FEATURE_GDBJIT_SYMTAB
2576 bool NotifyGdb::EmitSymtab(Elf_Builder &elfBuilder, MethodDesc* methodDescPtr, PCODE pCode, TADDR codeSize)
2577 {
2578     NewArrayHolder<DebuggerILToNativeMap> map = nullptr;
2579     NewArrayHolder<Elf_Symbol> symbols = nullptr;
2580     NewArrayHolder<NewArrayHolder<char>> symbolNames = nullptr;
2581
2582     ULONG32 numMap;
2583     int symbolCount;
2584
2585     LPCUTF8 methodName = methodDescPtr->GetName();
2586
2587     if (GetMethodNativeMap(methodDescPtr, &numMap, map, NULL, NULL) == S_OK)
2588     {
2589         int methodCount = countFuncs(map, numMap);
2590         symbolCount = methodCount + 1;
2591         symbols = new Elf_Symbol[symbolCount];
2592
2593         if (methodCount > 1)
2594             symbolNames = new NewArrayHolder<char>[methodCount - 1];
2595
2596         int startIndex = getNextPrologueIndex(0, map, numMap);
2597
2598         int methodNameSize = strlen(methodName) + 10;
2599
2600         for (int i = 1; i < symbolCount; ++i)
2601         {
2602             int endIndex = getNextPrologueIndex(startIndex + 1, map, numMap);
2603
2604             PCODE methodStart = map[startIndex].nativeStartOffset;
2605             TADDR methodSize = endIndex == -1 ? codeSize - methodStart : map[endIndex].nativeStartOffset - methodStart;
2606
2607             if (i == 1)
2608             {
2609                 symbols[i].m_name = methodName;
2610             }
2611             else
2612             {
2613                 int symbolNameIndex = i - 2;
2614                 symbolNames[symbolNameIndex] = new char[methodNameSize];
2615                 sprintf_s(symbolNames[symbolNameIndex], methodNameSize, "%s_%d", methodName, symbolNameIndex + 1);
2616                 symbols[i].m_name = symbolNames[symbolNameIndex];
2617             }
2618
2619             symbols[i].m_value = pCode + methodStart;
2620             symbols[i].m_size = methodSize;
2621
2622             startIndex = endIndex;
2623         }
2624     }
2625     else
2626     {
2627         symbolCount = 2;
2628         symbols = new Elf_Symbol[symbolCount];
2629
2630         symbols[1].m_name = methodName;
2631         symbols[1].m_value = pCode;
2632         symbols[1].m_size = codeSize;
2633     }
2634
2635     symbols[0].m_name = "";
2636
2637     MemBuf sectSymTab, sectStrTab;
2638
2639     if (!BuildStringTableSection(sectStrTab, symbols, symbolCount))
2640     {
2641         return false;
2642     }
2643
2644     if (!BuildSymbolTableSection(sectSymTab, pCode, codeSize, symbolCount - 1, symbols, symbolCount, 0))
2645     {
2646         return false;
2647     }
2648
2649     Elf_SectionTracker *strtab = elfBuilder.OpenSection(".strtab", SHT_STRTAB, 0);
2650     elfBuilder.Append(sectStrTab.MemPtr, sectStrTab.MemSize);
2651     elfBuilder.CloseSection();
2652
2653     Elf_SectionTracker *symtab = elfBuilder.OpenSection(".symtab", SHT_SYMTAB, 0);
2654     elfBuilder.Append(sectSymTab.MemPtr, sectSymTab.MemSize);
2655     symtab->Header()->sh_link = strtab->GetIndex();
2656     symtab->Header()->sh_entsize = sizeof(Elf_Sym);
2657     elfBuilder.CloseSection();
2658
2659     return true;
2660 }
2661 #endif // FEATURE_GDBJIT_SYMTAB
2662
2663 bool NotifyGdb::EmitDebugInfo(Elf_Builder &elfBuilder, MethodDesc* methodDescPtr, PCODE pCode, TADDR codeSize)
2664 {
2665     unsigned int thunkIndexBase = elfBuilder.GetSectionCount();
2666
2667     LPCUTF8 methodName = methodDescPtr->GetName();
2668
2669     int symbolCount = 0;
2670     NewArrayHolder<Elf_Symbol> symbolNames;
2671
2672     unsigned int symInfoLen = 0;
2673     NewArrayHolder<SymbolsInfo> symInfo = nullptr;
2674     LocalsInfo locals;
2675
2676     NewHolder<TK_TypeInfoMap> pTypeMap = new TK_TypeInfoMap();
2677
2678     /* Get debug info for method from portable PDB */
2679     HRESULT hr = GetDebugInfoFromPDB(methodDescPtr, symInfo, symInfoLen, locals);
2680     if (FAILED(hr) || symInfoLen == 0)
2681     {
2682         return false;
2683     }
2684
2685     int method_count = countFuncs(symInfo, symInfoLen);
2686     FunctionMemberPtrArrayHolder method(method_count);
2687
2688     CodeHeader* pCH = (CodeHeader*)pCode - 1;
2689     CalledMethod* pCalledMethods = reinterpret_cast<CalledMethod*>(pCH->GetCalledMethods());
2690     /* Collect addresses of thunks called by method */
2691     if (!CollectCalledMethods(pCalledMethods, (TADDR)methodDescPtr->GetNativeCode(), method, symbolNames, symbolCount))
2692     {
2693         return false;
2694     }
2695     pCH->SetCalledMethods(NULL);
2696
2697     MetaSig sig(methodDescPtr);
2698     int nArgsCount = sig.NumFixedArgs();
2699     if (sig.HasThis())
2700         nArgsCount++;
2701
2702     unsigned int firstLineIndex = 0;
2703     for (;firstLineIndex < symInfoLen; firstLineIndex++) {
2704         if (symInfo[firstLineIndex].lineNumber != 0 && symInfo[firstLineIndex].lineNumber != HiddenLine) break;
2705     }
2706
2707     if (firstLineIndex >= symInfoLen)
2708     {
2709         return false;
2710     }
2711
2712     int start_index = getNextPrologueIndex(0, symInfo, symInfoLen);
2713
2714     for (int method_index = 0; method_index < method.GetCount(); ++method_index)
2715     {
2716         method[method_index] = new FunctionMember(methodDescPtr, locals.size, nArgsCount);
2717
2718         int end_index = getNextPrologueIndex(start_index + 1, symInfo, symInfoLen);
2719
2720         PCODE method_start = symInfo[start_index].nativeOffset;
2721         TADDR method_size = end_index == -1 ? codeSize - method_start : symInfo[end_index].nativeOffset - method_start;
2722
2723         // method return type
2724         method[method_index]->m_member_type = GetArgTypeInfo(methodDescPtr, pTypeMap, 0, method);
2725         method[method_index]->m_sub_low_pc = pCode + method_start;
2726         method[method_index]->m_sub_high_pc = method_size;
2727         method[method_index]->lines = symInfo;
2728         method[method_index]->nlines = symInfoLen;
2729         method[method_index]->GetLocalsDebugInfo(pTypeMap, locals, symInfo[firstLineIndex].nativeOffset, method);
2730         size_t methodNameSize = strlen(methodName) + 10;
2731         method[method_index]->m_member_name = new char[methodNameSize];
2732         if (method_index == 0)
2733             sprintf_s(method[method_index]->m_member_name, methodNameSize, "%s", methodName);
2734         else
2735             sprintf_s(method[method_index]->m_member_name, methodNameSize, "%s_%i", methodName, method_index);
2736
2737         // method's class
2738         GetTypeInfoFromTypeHandle(TypeHandle(method[method_index]->md->GetMethodTable()), pTypeMap, method);
2739
2740         start_index = end_index;
2741     }
2742
2743     MemBuf sectSymTab, sectStrTab, dbgInfo, dbgAbbrev, dbgPubname, dbgPubType, dbgLine,
2744         dbgStr;
2745
2746     /* Build .debug_abbrev section */
2747     if (!BuildDebugAbbrev(dbgAbbrev))
2748     {
2749         return false;
2750     }
2751
2752     const char *cuPath = "";
2753
2754     /* Build .debug_line section */
2755     if (!BuildLineTable(dbgLine, pCode, codeSize, symInfo, symInfoLen, cuPath))
2756     {
2757         return false;
2758     }
2759
2760     // Split full path to compile unit into file name and directory path
2761     const char *fileName = SplitFilename(cuPath);
2762     int dirLen = fileName - cuPath;
2763     NewArrayHolder<char> dirPath;
2764     if (dirLen != 0)
2765     {
2766         dirPath = new char[dirLen];
2767         memcpy(dirPath, DebugStrings[1], dirLen - 1);
2768         dirPath[dirLen - 1] = '\0';
2769     }
2770     DebugStrings[1] = fileName;
2771     DebugStrings[2] = dirPath ? (const char *)dirPath : "";
2772
2773     /* Build .debug_str section */
2774     if (!BuildDebugStrings(dbgStr, pTypeMap, method))
2775     {
2776         return false;
2777     }
2778
2779     /* Build .debug_info section */
2780     if (!BuildDebugInfo(dbgInfo, pTypeMap, method))
2781     {
2782         return false;
2783     }
2784
2785     DebugStrings[1] = "";
2786     DebugStrings[2] = "";
2787
2788     for (int i = 0; i < method.GetCount(); ++i)
2789     {
2790         method[i]->lines = nullptr;
2791         method[i]->nlines = 0;
2792     }
2793
2794     /* Build .debug_pubname section */
2795     if (!BuildDebugPub(dbgPubname, methodName, dbgInfo.MemSize, 0x28))
2796     {
2797         return false;
2798     }
2799
2800     /* Build debug_pubtype section */
2801     if (!BuildDebugPub(dbgPubType, "int", dbgInfo.MemSize, 0x1a))
2802     {
2803         return false;
2804     }
2805
2806     /* Build .strtab section */
2807     symbolNames[0].m_name = "";
2808     for (int i = 0; i < method.GetCount(); ++i)
2809     {
2810         symbolNames[1 + i].m_name = method[i]->m_member_name;
2811         symbolNames[1 + i].m_value = method[i]->m_sub_low_pc;
2812         symbolNames[1 + i].m_section = 1;
2813         symbolNames[1 + i].m_size = method[i]->m_sub_high_pc;
2814     }
2815     if (!BuildStringTableSection(sectStrTab, symbolNames, symbolCount))
2816     {
2817         return false;
2818     }
2819     /* Build .symtab section */
2820     if (!BuildSymbolTableSection(sectSymTab, pCode, codeSize, method.GetCount(), symbolNames, symbolCount, thunkIndexBase))
2821     {
2822         return false;
2823     }
2824
2825     for (int i = 1 + method.GetCount(); i < symbolCount; i++)
2826     {
2827         char name[256];
2828
2829         sprintf_s(name, _countof(name), ".thunk_%i", i);
2830
2831         Elf_SectionTracker *thunk = elfBuilder.OpenSection(name, SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
2832         thunk->DisableHeaderUpdate();
2833         elfBuilder.CloseSection();
2834     }
2835
2836     elfBuilder.OpenSection(".debug_str", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS);
2837     elfBuilder.Append(dbgStr.MemPtr, dbgStr.MemSize);
2838     elfBuilder.CloseSection();
2839
2840     elfBuilder.OpenSection(".debug_abbrev", SHT_PROGBITS, 0);
2841     elfBuilder.Append(dbgAbbrev.MemPtr, dbgAbbrev.MemSize);
2842     elfBuilder.CloseSection();
2843
2844     elfBuilder.OpenSection(".debug_info", SHT_PROGBITS, 0);
2845     elfBuilder.Append(dbgInfo.MemPtr, dbgInfo.MemSize);
2846     elfBuilder.CloseSection();
2847
2848     elfBuilder.OpenSection(".debug_pubnames", SHT_PROGBITS, 0);
2849     elfBuilder.Append(dbgPubname.MemPtr, dbgPubname.MemSize);
2850     elfBuilder.CloseSection();
2851
2852     elfBuilder.OpenSection(".debug_pubtypes", SHT_PROGBITS, 0);
2853     elfBuilder.Append(dbgPubType.MemPtr, dbgPubType.MemSize);
2854     elfBuilder.CloseSection();
2855
2856     elfBuilder.OpenSection(".debug_line", SHT_PROGBITS, 0);
2857     elfBuilder.Append(dbgLine.MemPtr, dbgLine.MemSize);
2858     elfBuilder.CloseSection();
2859
2860     Elf_SectionTracker *strtab = elfBuilder.OpenSection(".strtab", SHT_STRTAB, 0);
2861     elfBuilder.Append(sectStrTab.MemPtr, sectStrTab.MemSize);
2862     elfBuilder.CloseSection();
2863
2864     Elf_SectionTracker *symtab = elfBuilder.OpenSection(".symtab", SHT_SYMTAB, 0);
2865     elfBuilder.Append(sectSymTab.MemPtr, sectSymTab.MemSize);
2866     symtab->Header()->sh_link = strtab->GetIndex();
2867     symtab->Header()->sh_entsize = sizeof(Elf_Sym);
2868     elfBuilder.CloseSection();
2869
2870     return true;
2871 }
2872
2873 void NotifyGdb::MethodPitched(MethodDesc* methodDescPtr)
2874 {
2875     PCODE pCode = methodDescPtr->GetNativeCode();
2876
2877     if (pCode == NULL)
2878         return;
2879
2880     /* Find relevant entry */
2881     for (jit_code_entry* jit_symbols = __jit_debug_descriptor.first_entry; jit_symbols != 0; jit_symbols = jit_symbols->next_entry)
2882     {
2883         const char* ptr = jit_symbols->symfile_addr;
2884         uint64_t size = jit_symbols->symfile_size;
2885
2886         const Elf_Ehdr* pEhdr = reinterpret_cast<const Elf_Ehdr*>(ptr);
2887         const Elf_Shdr* pShdr = reinterpret_cast<const Elf_Shdr*>(ptr + pEhdr->e_shoff);
2888         pShdr += ELF_BUILDER_TEXT_SECTION_INDEX; // bump to .text section
2889         if (pShdr->sh_addr == pCode)
2890         {
2891             /* Notify the debugger */
2892             __jit_debug_descriptor.relevant_entry = jit_symbols;
2893             __jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN;
2894             __jit_debug_register_code();
2895
2896             /* Free memory */
2897             delete[] ptr;
2898
2899             /* Unlink from list */
2900             if (jit_symbols->prev_entry == 0)
2901                 __jit_debug_descriptor.first_entry = jit_symbols->next_entry;
2902             else
2903                 jit_symbols->prev_entry->next_entry = jit_symbols->next_entry;
2904             delete jit_symbols;
2905             break;
2906         }
2907     }
2908 }
2909
2910 /* Build the DWARF .debug_line section */
2911 bool NotifyGdb::BuildLineTable(MemBuf& buf, PCODE startAddr, TADDR codeSize, SymbolsInfo* lines, unsigned nlines,
2912                                const char * &cuPath)
2913 {
2914     MemBuf fileTable, lineProg;
2915
2916     /* Build file table */
2917     if (!BuildFileTable(fileTable, lines, nlines, cuPath))
2918         return false;
2919     /* Build line info program */
2920     if (!BuildLineProg(lineProg, startAddr, codeSize, lines, nlines))
2921     {
2922         return false;
2923     }
2924
2925     buf.MemSize = sizeof(DwarfLineNumHeader) + fileTable.MemSize + lineProg.MemSize;
2926     buf.MemPtr = new char[buf.MemSize];
2927
2928     /* Fill the line info header */
2929     DwarfLineNumHeader* header = reinterpret_cast<DwarfLineNumHeader*>(buf.MemPtr.GetValue());
2930     memcpy(buf.MemPtr, &LineNumHeader, sizeof(DwarfLineNumHeader));
2931     header->m_length = buf.MemSize - sizeof(header->m_length);
2932
2933     // Set m_hdr_field to the number of bytes following the m_hdr_field field to the beginning of the first byte of
2934     // the line number program itself.
2935     header->m_hdr_length = sizeof(DwarfLineNumHeader)
2936                            - sizeof(header->m_length)
2937                            - sizeof(header->m_version)
2938                            - sizeof(header->m_hdr_length)
2939                            + fileTable.MemSize;
2940
2941     /* copy file table */
2942     memcpy(buf.MemPtr + sizeof(DwarfLineNumHeader), fileTable.MemPtr, fileTable.MemSize);
2943     /* copy line program */
2944     memcpy(buf.MemPtr + sizeof(DwarfLineNumHeader) + fileTable.MemSize, lineProg.MemPtr, lineProg.MemSize);
2945
2946     return true;
2947 }
2948
2949 // A class for building Directory Table and File Table (in .debug_line section) from a list of files
2950 class NotifyGdb::FileTableBuilder
2951 {
2952     int m_capacity;
2953
2954     NewArrayHolder< NewArrayHolder<char> > m_dirs;
2955     int m_dirs_count;
2956
2957     struct FileEntry
2958     {
2959         const char* path;
2960         const char* name;
2961         int dir;
2962     };
2963     NewArrayHolder<FileEntry> m_files;
2964     int m_files_count;
2965
2966     int FindDir(const char *name) const
2967     {
2968         for (int i = 0; i < m_dirs_count; ++i)
2969         {
2970             if (strcmp(m_dirs[i], name) == 0)
2971                 return i;
2972         }
2973         return -1;
2974     }
2975
2976     int FindFile(const char *path) const
2977     {
2978         for (int i = 0; i < m_files_count; ++i)
2979         {
2980             if (strcmp(m_files[i].path, path) == 0)
2981                 return i;
2982         }
2983         return -1;
2984     }
2985
2986 public:
2987
2988     FileTableBuilder(int capacity) :
2989         m_capacity(capacity),
2990         m_dirs(new NewArrayHolder<char>[capacity]),
2991         m_dirs_count(0),
2992         m_files(new FileEntry[capacity]),
2993         m_files_count(0)
2994     {
2995     }
2996
2997     int Add(const char *path)
2998     {
2999         // Already exists?
3000         int i = FindFile(path);
3001         if (i != -1)
3002             return i;
3003
3004         if (m_files_count >= m_capacity)
3005             return -1;
3006
3007         // Add new file entry
3008         m_files[m_files_count].path = path;
3009         const char *filename = SplitFilename(path);
3010         m_files[m_files_count].name = filename;
3011         int dirLen = filename - path;
3012         if (dirLen == 0)
3013         {
3014             m_files[m_files_count].dir = 0;
3015             return m_files_count++;
3016         }
3017
3018         // Construct directory path
3019         NewArrayHolder<char> dirName = new char[dirLen + 1];
3020         int delimiterDelta = dirLen == 1 ? 0 : 1; // Avoid empty dir entry when file is at Unix root /
3021         memcpy(dirName, path, dirLen - delimiterDelta);
3022         dirName[dirLen - delimiterDelta] = '\0';
3023
3024         // Try to find existing directory entry
3025         i = FindDir(dirName);
3026         if (i != -1)
3027         {
3028             m_files[m_files_count].dir = i + 1;
3029             return m_files_count++;
3030         }
3031
3032         // Create new directory entry
3033         if (m_dirs_count >= m_capacity)
3034             return -1;
3035
3036         m_dirs[m_dirs_count++] = dirName.Extract();
3037
3038         m_files[m_files_count].dir = m_dirs_count;
3039         return m_files_count++;
3040     }
3041
3042     void Build(MemBuf& buf)
3043     {
3044         unsigned totalSize = 0;
3045
3046         // Compute buffer size
3047         for (unsigned i = 0; i < m_dirs_count; ++i)
3048             totalSize += strlen(m_dirs[i]) + 1;
3049         totalSize += 1;
3050
3051         char cnv_buf[16];
3052         for (unsigned i = 0; i < m_files_count; ++i)
3053         {
3054             int len = Leb128Encode(static_cast<uint32_t>(m_files[i].dir), cnv_buf, sizeof(cnv_buf));
3055             totalSize += strlen(m_files[i].name) + 1 + len + 2;
3056         }
3057         totalSize += 1;
3058
3059         // Fill the buffer
3060         buf.MemSize = totalSize;
3061         buf.MemPtr = new char[buf.MemSize];
3062
3063         char *ptr = buf.MemPtr;
3064
3065         for (unsigned i = 0; i < m_dirs_count; ++i)
3066         {
3067             strcpy(ptr, m_dirs[i]);
3068             ptr += strlen(m_dirs[i]) + 1;
3069         }
3070         // final zero byte for directory table
3071         *ptr++ = 0;
3072
3073         for (unsigned i = 0; i < m_files_count; ++i)
3074         {
3075             strcpy(ptr, m_files[i].name);
3076             ptr += strlen(m_files[i].name) + 1;
3077
3078             // Index in directory table
3079             int len = Leb128Encode(static_cast<uint32_t>(m_files[i].dir), cnv_buf, sizeof(cnv_buf));
3080             memcpy(ptr, cnv_buf, len);
3081             ptr += len;
3082
3083             // Two LEB128 entries which we don't care
3084             *ptr++ = 0;
3085             *ptr++ = 0;
3086         }
3087         // final zero byte
3088         *ptr = 0;
3089     }
3090 };
3091
3092 /* Buid the source files table for DWARF source line info */
3093 bool NotifyGdb::BuildFileTable(MemBuf& buf, SymbolsInfo* lines, unsigned nlines, const char * &cuPath)
3094 {
3095     FileTableBuilder fileTable(nlines);
3096
3097     cuPath = "";
3098     for (unsigned i = 0; i < nlines; ++i)
3099     {
3100         const char* fileName = lines[i].fileName;
3101
3102         if (fileName[0] == '\0')
3103             continue;
3104
3105         if (*cuPath == '\0') // Use first non-empty filename as compile unit
3106             cuPath = fileName;
3107
3108         lines[i].fileIndex = fileTable.Add(fileName);
3109     }
3110
3111     fileTable.Build(buf);
3112
3113     return true;
3114 }
3115
3116 /* Command to set absolute address */
3117 void NotifyGdb::IssueSetAddress(char*& ptr, PCODE addr)
3118 {
3119     *ptr++ = 0;
3120     *ptr++ = ADDRESS_SIZE + 1;
3121     *ptr++ = DW_LNE_set_address;
3122     *reinterpret_cast<PCODE*>(ptr) = addr;
3123     ptr += ADDRESS_SIZE;
3124 }
3125
3126 /* End of line program */
3127 void NotifyGdb::IssueEndOfSequence(char*& ptr)
3128 {
3129     *ptr++ = 0;
3130     *ptr++ = 1;
3131     *ptr++ = DW_LNE_end_sequence;
3132 }
3133
3134 /* Command w/o parameters */
3135 void NotifyGdb::IssueSimpleCommand(char*& ptr, uint8_t command)
3136 {
3137     *ptr++ = command;
3138 }
3139
3140 /* Command with one LEB128 parameter */
3141 void NotifyGdb::IssueParamCommand(char*& ptr, uint8_t command, char* param, int param_size)
3142 {
3143     *ptr++ = command;
3144     while (param_size-- > 0)
3145     {
3146         *ptr++ = *param++;
3147     }
3148 }
3149
3150 static void fixLineMapping(SymbolsInfo* lines, unsigned nlines)
3151 {
3152     // Fix EPILOGUE line mapping
3153     int prevLine = 0;
3154     for (int i = 0; i < nlines; ++i)
3155     {
3156         if (lines[i].lineNumber == HiddenLine)
3157             continue;
3158         if (lines[i].ilOffset == ICorDebugInfo::PROLOG) // will be fixed in next step
3159         {
3160             prevLine = 0;
3161         }
3162         else
3163         {
3164             if (lines[i].lineNumber == 0)
3165             {
3166                 lines[i].lineNumber = prevLine;
3167             }
3168             else
3169             {
3170                 prevLine = lines[i].lineNumber;
3171             }
3172         }
3173     }
3174     // Fix PROLOGUE line mapping
3175     prevLine = lines[nlines - 1].lineNumber;
3176     for (int i = nlines - 1; i >= 0; --i)
3177     {
3178         if (lines[i].lineNumber == HiddenLine)
3179             continue;
3180         if (lines[i].lineNumber == 0)
3181             lines[i].lineNumber = prevLine;
3182         else
3183             prevLine = lines[i].lineNumber;
3184     }
3185     // Skip HiddenLines
3186     for (int i = 0; i < nlines; ++i)
3187     {
3188         if (lines[i].lineNumber == HiddenLine)
3189         {
3190             lines[i].lineNumber = 0;
3191             if (i + 1 < nlines && lines[i + 1].ilOffset == ICorDebugInfo::NO_MAPPING)
3192                 lines[i + 1].lineNumber = 0;
3193         }
3194     }
3195 }
3196
3197 /* Build program for DWARF source line section */
3198 bool NotifyGdb::BuildLineProg(MemBuf& buf, PCODE startAddr, TADDR codeSize, SymbolsInfo* lines, unsigned nlines)
3199 {
3200     static char cnv_buf[16];
3201
3202     /* reserve memory assuming worst case: set address, advance line command, set proglogue/epilogue and copy for each line */
3203     buf.MemSize =
3204                 + 6                              /* set file command */
3205                 + nlines * 6                     /* advance line commands */
3206                 + nlines * (3 + ADDRESS_SIZE)    /* set address commands */
3207                 + nlines * 1                     /* set prologue end or epilogue begin commands */
3208                 + nlines * 1                     /* copy commands */
3209                 + 6                              /* advance PC command */
3210                 + 3;                             /* end of sequence command */
3211     buf.MemPtr = new char[buf.MemSize];
3212     char* ptr = buf.MemPtr;
3213
3214     if (buf.MemPtr == nullptr)
3215         return false;
3216
3217     fixLineMapping(lines, nlines);
3218
3219     int prevLine = 1, prevFile = 0;
3220
3221     for (int i = 0; i < nlines; ++i)
3222     {
3223         /* different source file */
3224         if (lines[i].fileIndex != prevFile)
3225         {
3226             int len = Leb128Encode(static_cast<uint32_t>(lines[i].fileIndex+1), cnv_buf, sizeof(cnv_buf));
3227             IssueParamCommand(ptr, DW_LNS_set_file, cnv_buf, len);
3228             prevFile = lines[i].fileIndex;
3229         }
3230
3231         // GCC don't use the is_prologue_end flag to mark the first instruction after the prologue.
3232         // Instead of it it is issueing a line table entry for the first instruction of the prologue
3233         // and one for the first instruction after the prologue.
3234         // We do not want to confuse the debugger so we have to avoid adding a line in such case.
3235         if (i > 0 && lines[i - 1].nativeOffset == lines[i].nativeOffset)
3236             continue;
3237
3238         IssueSetAddress(ptr, startAddr + lines[i].nativeOffset);
3239
3240         if (lines[i].lineNumber != prevLine) {
3241             int len = Leb128Encode(static_cast<int32_t>(lines[i].lineNumber - prevLine), cnv_buf, sizeof(cnv_buf));
3242             IssueParamCommand(ptr, DW_LNS_advance_line, cnv_buf, len);
3243             prevLine = lines[i].lineNumber;
3244         }
3245
3246         if (lines[i].ilOffset == ICorDebugInfo::EPILOG)
3247             IssueSimpleCommand(ptr, DW_LNS_set_epilogue_begin);
3248         else if (i > 0 && lines[i - 1].ilOffset == ICorDebugInfo::PROLOG)
3249             IssueSimpleCommand(ptr, DW_LNS_set_prologue_end);
3250
3251         IssueParamCommand(ptr, DW_LNS_copy, NULL, 0);
3252     }
3253
3254     int lastAddr = nlines > 0 ? lines[nlines - 1].nativeOffset : 0;
3255
3256     // Advance PC to the end of function
3257     if (lastAddr < codeSize) {
3258         int len = Leb128Encode(static_cast<uint32_t>(codeSize - lastAddr), cnv_buf, sizeof(cnv_buf));
3259         IssueParamCommand(ptr, DW_LNS_advance_pc, cnv_buf, len);
3260     }
3261
3262     IssueEndOfSequence(ptr);
3263
3264     buf.MemSize = ptr - buf.MemPtr;
3265     return true;
3266 }
3267
3268 /* Build the DWARF .debug_str section */
3269 bool NotifyGdb::BuildDebugStrings(MemBuf& buf, PTK_TypeInfoMap pTypeMap, FunctionMemberPtrArrayHolder &method)
3270 {
3271     int totalLength = 0;
3272
3273     /* calculate total section size */
3274     for (int i = 0; i < DebugStringCount; ++i)
3275     {
3276         totalLength += strlen(DebugStrings[i]) + 1;
3277     }
3278
3279     for (int i = 0; i < method.GetCount(); ++i)
3280     {
3281         method[i]->DumpStrings(nullptr, totalLength);
3282     }
3283
3284     {
3285         auto iter = pTypeMap->Begin();
3286         while (iter != pTypeMap->End())
3287         {
3288             TypeInfoBase *typeInfo = iter->Value();
3289             typeInfo->DumpStrings(nullptr, totalLength);
3290             iter++;
3291         }
3292     }
3293
3294     buf.MemSize = totalLength;
3295     buf.MemPtr = new char[totalLength];
3296
3297     /* copy strings */
3298     char* bufPtr = buf.MemPtr;
3299     int offset = 0;
3300     for (int i = 0; i < DebugStringCount; ++i)
3301     {
3302         strcpy(bufPtr + offset, DebugStrings[i]);
3303         offset += strlen(DebugStrings[i]) + 1;
3304     }
3305
3306     for (int i = 0; i < method.GetCount(); ++i)
3307     {
3308         method[i]->DumpStrings(bufPtr, offset);
3309     }
3310
3311     {
3312         auto iter = pTypeMap->Begin();
3313         while (iter != pTypeMap->End())
3314         {
3315             TypeInfoBase *typeInfo = iter->Value();
3316             typeInfo->DumpStrings(bufPtr, offset);
3317             iter++;
3318         }
3319     }
3320
3321     return true;
3322 }
3323
3324 /* Build the DWARF .debug_abbrev section */
3325 bool NotifyGdb::BuildDebugAbbrev(MemBuf& buf)
3326 {
3327     buf.MemPtr = new char[AbbrevTableSize];
3328     buf.MemSize = AbbrevTableSize;
3329
3330     memcpy(buf.MemPtr, AbbrevTable, AbbrevTableSize);
3331     return true;
3332 }
3333
3334 /* Build tge DWARF .debug_info section */
3335 bool NotifyGdb::BuildDebugInfo(MemBuf& buf, PTK_TypeInfoMap pTypeMap, FunctionMemberPtrArrayHolder &method)
3336 {
3337     int totalTypeVarSubSize = 0;
3338     {
3339         auto iter = pTypeMap->Begin();
3340         while (iter != pTypeMap->End())
3341         {
3342             TypeInfoBase *typeInfo = iter->Value();
3343             typeInfo->DumpDebugInfo(nullptr, totalTypeVarSubSize);
3344             iter++;
3345         }
3346     }
3347
3348     for (int i = 0; i < method.GetCount(); ++i)
3349     {
3350         method[i]->DumpDebugInfo(nullptr, totalTypeVarSubSize);
3351     }
3352
3353     //int locSize = GetArgsAndLocalsLen(argsDebug, argsDebugSize, localsDebug, localsDebugSize);
3354     buf.MemSize = sizeof(DwarfCompUnit) + sizeof(DebugInfoCU) + totalTypeVarSubSize + 2;
3355     buf.MemPtr = new char[buf.MemSize];
3356
3357     int offset = 0;
3358     /* Compile uint header */
3359     DwarfCompUnit* cu = reinterpret_cast<DwarfCompUnit*>(buf.MemPtr.GetValue());
3360     cu->m_length = buf.MemSize - sizeof(uint32_t);
3361     cu->m_version = 4;
3362     cu->m_abbrev_offset = 0;
3363     cu->m_addr_size = ADDRESS_SIZE;
3364     offset += sizeof(DwarfCompUnit);
3365     DebugInfoCU* diCU =
3366        reinterpret_cast<DebugInfoCU*>(buf.MemPtr + offset);
3367     memcpy(buf.MemPtr + offset, &debugInfoCU, sizeof(DebugInfoCU));
3368     offset += sizeof(DebugInfoCU);
3369     diCU->m_prod_off = 0;
3370     diCU->m_cu_name = strlen(DebugStrings[0]) + 1;
3371     diCU->m_cu_dir = diCU->m_cu_name + strlen(DebugStrings[1]) + 1;
3372     {
3373         auto iter = pTypeMap->Begin();
3374         while (iter != pTypeMap->End())
3375         {
3376             TypeInfoBase *typeInfo = iter->Value();
3377             typeInfo->DumpDebugInfo(buf.MemPtr, offset);
3378             iter++;
3379         }
3380     }
3381     for (int i = 0; i < method.GetCount(); ++i)
3382     {
3383         if (!method[i]->IsDumped())
3384         {
3385             method[i]->DumpDebugInfo(buf.MemPtr, offset);
3386         }
3387         else
3388         {
3389             method[i]->DumpDebugInfo(buf.MemPtr, method[i]->m_entry_offset);
3390         }
3391     }
3392     memset(buf.MemPtr + offset, 0, buf.MemSize - offset);
3393     return true;
3394 }
3395
3396 /* Build the DWARF lookup section */
3397 bool NotifyGdb::BuildDebugPub(MemBuf& buf, const char* name, uint32_t size, uint32_t die_offset)
3398 {
3399     uint32_t length = sizeof(DwarfPubHeader) + sizeof(uint32_t) + strlen(name) + 1 + sizeof(uint32_t);
3400
3401     buf.MemSize = length;
3402     buf.MemPtr = new char[buf.MemSize];
3403
3404     DwarfPubHeader* header = reinterpret_cast<DwarfPubHeader*>(buf.MemPtr.GetValue());
3405     header->m_length = length - sizeof(uint32_t);
3406     header->m_version = 2;
3407     header->m_debug_info_off = 0;
3408     header->m_debug_info_len = size;
3409     *reinterpret_cast<uint32_t*>(buf.MemPtr + sizeof(DwarfPubHeader)) = die_offset;
3410     strcpy(buf.MemPtr + sizeof(DwarfPubHeader) + sizeof(uint32_t), name);
3411     *reinterpret_cast<uint32_t*>(buf.MemPtr + length - sizeof(uint32_t)) = 0;
3412
3413     return true;
3414 }
3415
3416 /* Store addresses and names of the called methods into symbol table */
3417 bool NotifyGdb::CollectCalledMethods(CalledMethod* pCalledMethods,
3418                                      TADDR nativeCode,
3419                                      FunctionMemberPtrArrayHolder &method,
3420                                      NewArrayHolder<Elf_Symbol> &symbolNames,
3421                                      int &symbolCount)
3422 {
3423     AddrSet tmpCodeAddrs;
3424
3425     if (!codeAddrs.Contains(nativeCode))
3426         codeAddrs.Add(nativeCode);
3427
3428     CalledMethod* pList = pCalledMethods;
3429
3430      /* count called methods */
3431     while (pList != NULL)
3432     {
3433         TADDR callAddr = (TADDR)pList->GetCallAddr();
3434         if (!tmpCodeAddrs.Contains(callAddr) && !codeAddrs.Contains(callAddr)) {
3435             tmpCodeAddrs.Add(callAddr);
3436         }
3437         pList = pList->GetNext();
3438     }
3439
3440     symbolCount = 1 + method.GetCount() + tmpCodeAddrs.GetCount();
3441     symbolNames = new Elf_Symbol[symbolCount];
3442
3443     pList = pCalledMethods;
3444     int i = 1 + method.GetCount();
3445     while (i < symbolCount && pList != NULL)
3446     {
3447         TADDR callAddr = (TADDR)pList->GetCallAddr();
3448         if (!codeAddrs.Contains(callAddr))
3449         {
3450             MethodDesc* pMD = pList->GetMethodDesc();
3451             LPCUTF8 methodName = pMD->GetName();
3452             int symbolNameLength = strlen(methodName) + sizeof("__thunk_");
3453             symbolNames[i].m_symbol_name = new char[symbolNameLength];
3454             symbolNames[i].m_name = symbolNames[i].m_symbol_name;
3455             sprintf_s((char*)symbolNames[i].m_name, symbolNameLength, "__thunk_%s", methodName);
3456             symbolNames[i].m_value = callAddr;
3457             ++i;
3458             codeAddrs.Add(callAddr);
3459         }
3460         pList = pList->GetNext();
3461     }
3462     symbolCount = i;
3463     return true;
3464 }
3465
3466 /* Build ELF .strtab section */
3467 bool NotifyGdb::BuildStringTableSection(MemBuf& buf, NewArrayHolder<Elf_Symbol> &symbolNames, int symbolCount)
3468 {
3469     int len = 0;
3470     for (int i = 0; i < symbolCount; ++i)
3471         len += strlen(symbolNames[i].m_name) + 1;
3472     len++; // end table with zero-length string
3473
3474     buf.MemSize = len;
3475     buf.MemPtr = new char[buf.MemSize];
3476
3477     char* ptr = buf.MemPtr;
3478     for (int i = 0; i < symbolCount; ++i)
3479     {
3480         symbolNames[i].m_off = ptr - buf.MemPtr;
3481         strcpy(ptr, symbolNames[i].m_name);
3482         ptr += strlen(symbolNames[i].m_name) + 1;
3483     }
3484     buf.MemPtr[buf.MemSize-1] = 0;
3485
3486     return true;
3487 }
3488
3489 /* Build ELF .symtab section */
3490 bool NotifyGdb::BuildSymbolTableSection(MemBuf& buf, PCODE addr, TADDR codeSize, int methodCount,
3491                                         NewArrayHolder<Elf_Symbol> &symbolNames, int symbolCount,
3492                                         unsigned int thunkIndexBase)
3493 {
3494     buf.MemSize = symbolCount * sizeof(Elf_Sym);
3495     buf.MemPtr = new char[buf.MemSize];
3496
3497     Elf_Sym *sym = reinterpret_cast<Elf_Sym*>(buf.MemPtr.GetValue());
3498
3499     sym[0].st_name = 0;
3500     sym[0].st_info = 0;
3501     sym[0].st_other = 0;
3502     sym[0].st_value = 0;
3503     sym[0].st_size = 0;
3504     sym[0].st_shndx = SHN_UNDEF;
3505
3506     for (int i = 1; i < 1 + methodCount; ++i)
3507     {
3508         sym[i].st_name = symbolNames[i].m_off;
3509         sym[i].setBindingAndType(STB_GLOBAL, STT_FUNC);
3510         sym[i].st_other = 0;
3511         sym[i].st_value = PINSTRToPCODE(symbolNames[i].m_value - addr);
3512         sym[i].st_shndx = ELF_BUILDER_TEXT_SECTION_INDEX;
3513         sym[i].st_size = symbolNames[i].m_size;
3514     }
3515
3516     for (int i = 1 + methodCount; i < symbolCount; ++i)
3517     {
3518         sym[i].st_name = symbolNames[i].m_off;
3519         sym[i].setBindingAndType(STB_GLOBAL, STT_FUNC);
3520         sym[i].st_other = 0;
3521         sym[i].st_shndx = thunkIndexBase + (i - (1 + methodCount)); // .thunks section index
3522         sym[i].st_size = 8;
3523 #ifdef _TARGET_ARM_
3524         sym[i].st_value = 1; // for THUMB code
3525 #else
3526         sym[i].st_value = 0;
3527 #endif
3528     }
3529     return true;
3530 }
3531
3532 /* Split file name part from the full path */
3533 const char * NotifyGdb::SplitFilename(const char* path)
3534 {
3535     // Search for the last directory delimiter (Windows or Unix)
3536     const char *pSlash = nullptr;
3537     for (const char *p = path; *p != '\0'; p++)
3538     {
3539         if (*p == '/' || *p == '\\')
3540             pSlash = p;
3541     }
3542
3543     return pSlash ? pSlash + 1 : path;
3544 }
3545
3546 /* ELF 32bit header */
3547 Elf32_Ehdr::Elf32_Ehdr()
3548 {
3549     e_ident[EI_MAG0] = ElfMagic[0];
3550     e_ident[EI_MAG1] = ElfMagic[1];
3551     e_ident[EI_MAG2] = ElfMagic[2];
3552     e_ident[EI_MAG3] = ElfMagic[3];
3553     e_ident[EI_CLASS] = ELFCLASS32;
3554     e_ident[EI_DATA] = ELFDATA2LSB;
3555     e_ident[EI_VERSION] = EV_CURRENT;
3556     e_ident[EI_OSABI] = ELFOSABI_NONE;
3557     e_ident[EI_ABIVERSION] = 0;
3558     for (int i = EI_PAD; i < EI_NIDENT; ++i)
3559         e_ident[i] = 0;
3560
3561     e_type = ET_REL;
3562 #if defined(_TARGET_X86_)
3563     e_machine = EM_386;
3564 #elif defined(_TARGET_ARM_)
3565     e_machine = EM_ARM;
3566 #endif
3567     e_flags = 0;
3568     e_version = 1;
3569     e_entry = 0;
3570     e_phoff = 0;
3571     e_ehsize = sizeof(Elf32_Ehdr);
3572     e_phentsize = 0;
3573     e_phnum = 0;
3574 }
3575
3576 /* ELF 64bit header */
3577 Elf64_Ehdr::Elf64_Ehdr()
3578 {
3579     e_ident[EI_MAG0] = ElfMagic[0];
3580     e_ident[EI_MAG1] = ElfMagic[1];
3581     e_ident[EI_MAG2] = ElfMagic[2];
3582     e_ident[EI_MAG3] = ElfMagic[3];
3583     e_ident[EI_CLASS] = ELFCLASS64;
3584     e_ident[EI_DATA] = ELFDATA2LSB;
3585     e_ident[EI_VERSION] = EV_CURRENT;
3586     e_ident[EI_OSABI] = ELFOSABI_NONE;
3587     e_ident[EI_ABIVERSION] = 0;
3588     for (int i = EI_PAD; i < EI_NIDENT; ++i)
3589         e_ident[i] = 0;
3590
3591     e_type = ET_REL;
3592 #if defined(_TARGET_AMD64_)
3593     e_machine = EM_X86_64;
3594 #elif defined(_TARGET_ARM64_)
3595     e_machine = EM_AARCH64;
3596 #endif
3597     e_flags = 0;
3598     e_version = 1;
3599     e_entry = 0;
3600     e_phoff = 0;
3601     e_ehsize = sizeof(Elf64_Ehdr);
3602     e_phentsize = 0;
3603     e_phnum = 0;
3604 }