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