diff options
author | Konstantin Baladurin <k.baladurin@partner.samsung.com> | 2017-09-13 15:17:55 +0300 |
---|---|---|
committer | Jan Vorlicek <janvorli@microsoft.com> | 2017-09-13 14:17:55 +0200 |
commit | d6a8414adeb217fba21f124b45c3d5fa100bb932 (patch) | |
tree | 88c98c7e137047b029057e6620e9b23eb6bd9c5e | |
parent | 80dd47bb5564f1cfc843c8d753096a0a3acfbe2d (diff) | |
download | coreclr-d6a8414adeb217fba21f124b45c3d5fa100bb932.tar.gz coreclr-d6a8414adeb217fba21f124b45c3d5fa100bb932.tar.bz2 coreclr-d6a8414adeb217fba21f124b45c3d5fa100bb932.zip |
Introduce FEATURE_GDBJIT_SYMTAB (#13567)
* Introduce FEATURE_GDBJIT_SYMTAB
This commit adds new feature FEATURE_GDBJIT_SYMTAB. When it's set
ELF file with symtab section will be generated for all JITed methods.
It helps lldb and gdb correctly unwind frames of JITed methods as they
can use assembly language inspection to determine location of saved
registers on stack.
* gdbjit symtab feature: use different symbols for each function in JITed code
-rw-r--r-- | clrdefinitions.cmake | 3 | ||||
-rw-r--r-- | src/vm/gdbjit.cpp | 119 | ||||
-rw-r--r-- | src/vm/gdbjit.h | 5 |
3 files changed, 115 insertions, 12 deletions
diff --git a/clrdefinitions.cmake b/clrdefinitions.cmake index 6cec17b13e..18c93c377e 100644 --- a/clrdefinitions.cmake +++ b/clrdefinitions.cmake @@ -125,6 +125,9 @@ endif(FEATURE_GDBJIT_FRAME) if(FEATURE_GDBJIT_LANGID_CS) add_definitions(-DFEATURE_GDBJIT_LANGID_CS) endif(FEATURE_GDBJIT_LANGID_CS) +if(FEATURE_GDBJIT_SYMTAB) + add_definitions(-DFEATURE_GDBJIT_SYMTAB) +endif(FEATURE_GDBJIT_SYMTAB) if(CLR_CMAKE_PLATFORM_LINUX) add_definitions(-DFEATURE_PERFTRACING) endif(CLR_CMAKE_PLATFORM_LINUX) diff --git a/src/vm/gdbjit.cpp b/src/vm/gdbjit.cpp index 1ffab8a3ce..9557b0bf3e 100644 --- a/src/vm/gdbjit.cpp +++ b/src/vm/gdbjit.cpp @@ -1759,11 +1759,12 @@ struct Elf_Symbol { Elf_Symbol() : m_name(nullptr), m_off(0), m_value(0), m_section(0), m_size(0) {} }; -static int countFuncs(const SymbolsInfo *lines, int nlines) +template <class T> +static int countFuncs(T &arr, int n) { int count = 0; - for (int i = 0; i < nlines; i++) { - if (lines[i].ilOffset == ICorDebugInfo::PROLOG) + for (int i = 0; i < n; i++) { + if (arr[i].ilOffset == ICorDebugInfo::PROLOG) { count++; } @@ -1771,10 +1772,11 @@ static int countFuncs(const SymbolsInfo *lines, int nlines) return count; } -static int getNextPrologueIndex(int from, const SymbolsInfo *lines, int nlines) +template <class T> +static int getNextPrologueIndex(int from, T &arr, int n) { - for (int i = from; i < nlines; ++i) { - if (lines[i].ilOffset == ICorDebugInfo::PROLOG) + for (int i = from; i < n; ++i) { + if (arr[i].ilOffset == ICorDebugInfo::PROLOG) { return i; } @@ -2509,6 +2511,13 @@ void NotifyGdb::OnMethodPrepared(MethodDesc* methodDescPtr) bool bEmitted = EmitDebugInfo(elfBuilder, methodDescPtr, pCode, codeSize, szModuleFile); bNotify = bNotify || bEmitted; } +#ifdef FEATURE_GDBJIT_SYMTAB + else + { + bool bEmitted = EmitSymtab(elfBuilder, methodDescPtr, pCode, codeSize); + bNotify = bNotify || bEmitted; + } +#endif if (!bNotify) { @@ -2564,6 +2573,94 @@ bool NotifyGdb::EmitFrameInfo(Elf_Builder &elfBuilder, PCODE pCode, TADDR codeSi } #endif // FEATURE_GDBJIT_FRAME +#ifdef FEATURE_GDBJIT_SYMTAB +bool NotifyGdb::EmitSymtab(Elf_Builder &elfBuilder, MethodDesc* methodDescPtr, PCODE pCode, TADDR codeSize) +{ + NewArrayHolder<DebuggerILToNativeMap> map = nullptr; + NewArrayHolder<Elf_Symbol> symbols = nullptr; + NewArrayHolder<NewArrayHolder<char>> symbolNames = nullptr; + + ULONG32 numMap; + int symbolCount; + + LPCUTF8 methodName = methodDescPtr->GetName(); + + if (GetMethodNativeMap(methodDescPtr, &numMap, map, NULL, NULL) == S_OK) + { + int methodCount = countFuncs(map, numMap); + symbolCount = methodCount + 1; + symbols = new Elf_Symbol[symbolCount]; + + if (methodCount > 1) + symbolNames = new NewArrayHolder<char>[methodCount - 1]; + + int startIndex = getNextPrologueIndex(0, map, numMap); + + int methodNameSize = strlen(methodName) + 10; + + for (int i = 1; i < symbolCount; ++i) + { + int endIndex = getNextPrologueIndex(startIndex + 1, map, numMap); + + PCODE methodStart = map[startIndex].nativeStartOffset; + TADDR methodSize = endIndex == -1 ? codeSize - methodStart : map[endIndex].nativeStartOffset - methodStart; + + if (i == 1) + { + symbols[i].m_name = methodName; + } + else + { + int symbolNameIndex = i - 2; + symbolNames[symbolNameIndex] = new char[methodNameSize]; + sprintf_s(symbolNames[symbolNameIndex], methodNameSize, "%s_%d", methodName, symbolNameIndex + 1); + symbols[i].m_name = symbolNames[symbolNameIndex]; + } + + symbols[i].m_value = pCode + methodStart; + symbols[i].m_size = methodSize; + + startIndex = endIndex; + } + } + else + { + symbolCount = 2; + symbols = new Elf_Symbol[symbolCount]; + + symbols[1].m_name = methodName; + symbols[1].m_value = pCode; + symbols[1].m_size = codeSize; + } + + symbols[0].m_name = ""; + + MemBuf sectSymTab, sectStrTab; + + if (!BuildStringTableSection(sectStrTab, symbols, symbolCount)) + { + return false; + } + + if (!BuildSymbolTableSection(sectSymTab, pCode, codeSize, symbolCount - 1, symbols, symbolCount, 0)) + { + return false; + } + + Elf_SectionTracker *strtab = elfBuilder.OpenSection(".strtab", SHT_STRTAB, 0); + elfBuilder.Append(sectStrTab.MemPtr, sectStrTab.MemSize); + elfBuilder.CloseSection(); + + Elf_SectionTracker *symtab = elfBuilder.OpenSection(".symtab", SHT_SYMTAB, 0); + elfBuilder.Append(sectSymTab.MemPtr, sectSymTab.MemSize); + symtab->Header()->sh_link = strtab->GetIndex(); + symtab->Header()->sh_entsize = sizeof(Elf_Sym); + elfBuilder.CloseSection(); + + return true; +} +#endif // FEATURE_GDBJIT_SYMTAB + bool NotifyGdb::EmitDebugInfo(Elf_Builder &elfBuilder, MethodDesc* methodDescPtr, PCODE pCode, TADDR codeSize, const char *szModuleFile) { unsigned int thunkIndexBase = elfBuilder.GetSectionCount(); @@ -2705,7 +2802,7 @@ bool NotifyGdb::EmitDebugInfo(Elf_Builder &elfBuilder, MethodDesc* methodDescPtr return false; } /* Build .symtab section */ - if (!BuildSymbolTableSection(sectSymTab, pCode, codeSize, method, symbolNames, symbolCount, thunkIndexBase)) + if (!BuildSymbolTableSection(sectSymTab, pCode, codeSize, method.GetCount(), symbolNames, symbolCount, thunkIndexBase)) { return false; } @@ -3265,7 +3362,7 @@ bool NotifyGdb::BuildStringTableSection(MemBuf& buf, NewArrayHolder<Elf_Symbol> } /* Build ELF .symtab section */ -bool NotifyGdb::BuildSymbolTableSection(MemBuf& buf, PCODE addr, TADDR codeSize, FunctionMemberPtrArrayHolder &method, +bool NotifyGdb::BuildSymbolTableSection(MemBuf& buf, PCODE addr, TADDR codeSize, int methodCount, NewArrayHolder<Elf_Symbol> &symbolNames, int symbolCount, unsigned int thunkIndexBase) { @@ -3281,7 +3378,7 @@ bool NotifyGdb::BuildSymbolTableSection(MemBuf& buf, PCODE addr, TADDR codeSize, sym[0].st_size = 0; sym[0].st_shndx = SHN_UNDEF; - for (int i = 1; i < 1 + method.GetCount(); ++i) + for (int i = 1; i < 1 + methodCount; ++i) { sym[i].st_name = symbolNames[i].m_off; sym[i].setBindingAndType(STB_GLOBAL, STT_FUNC); @@ -3291,12 +3388,12 @@ bool NotifyGdb::BuildSymbolTableSection(MemBuf& buf, PCODE addr, TADDR codeSize, sym[i].st_size = symbolNames[i].m_size; } - for (int i = 1 + method.GetCount(); i < symbolCount; ++i) + for (int i = 1 + methodCount; i < symbolCount; ++i) { sym[i].st_name = symbolNames[i].m_off; sym[i].setBindingAndType(STB_GLOBAL, STT_FUNC); sym[i].st_other = 0; - sym[i].st_shndx = thunkIndexBase + (i - (1 + method.GetCount())); // .thunks section index + sym[i].st_shndx = thunkIndexBase + (i - (1 + methodCount)); // .thunks section index sym[i].st_size = 8; #ifdef _TARGET_ARM_ sym[i].st_value = 1; // for THUMB code diff --git a/src/vm/gdbjit.h b/src/vm/gdbjit.h index ff5b4dfa7b..f7267ad2a1 100644 --- a/src/vm/gdbjit.h +++ b/src/vm/gdbjit.h @@ -419,9 +419,12 @@ private: #ifdef FEATURE_GDBJIT_FRAME static bool EmitFrameInfo(Elf_Builder &, PCODE pCode, TADDR codeSzie); #endif // FEATURE_GDBJIT_FRAME +#ifdef FEATURE_GDBJIT_SYMTAB + static bool EmitSymtab(Elf_Builder &, MethodDesc* methodDescPtr, PCODE pCode, TADDR codeSize); +#endif // FEATURE_GDBJIT_SYMTAB static bool EmitDebugInfo(Elf_Builder &, MethodDesc* methodDescPtr, PCODE pCode, TADDR codeSize, const char *szModuleFile); - static bool BuildSymbolTableSection(MemBuf& buf, PCODE addr, TADDR codeSize, FunctionMemberPtrArrayHolder &method, + static bool BuildSymbolTableSection(MemBuf& buf, PCODE addr, TADDR codeSize, int methodCount, NewArrayHolder<Elf_Symbol> &symbolNames, int symbolCount, unsigned int thunkIndexBase); static bool BuildStringTableSection(MemBuf& strTab, NewArrayHolder<Elf_Symbol> &symbolNames, int symbolCount); |