diff options
author | Igor Kulaychuk <igor.kulaychuk@gmail.com> | 2016-12-19 14:03:59 +0300 |
---|---|---|
committer | Jan Vorlicek <janvorli@microsoft.com> | 2016-12-19 12:03:59 +0100 |
commit | d23b78ce50d04e97cc23f997fab8c0ce5faa8726 (patch) | |
tree | 595aa07ab83ff85d0a3332425afd88967ee6404f /src | |
parent | 6fce053a60454b76e09a0677ea0568de1d165b43 (diff) | |
download | coreclr-d23b78ce50d04e97cc23f997fab8c0ce5faa8726.tar.gz coreclr-d23b78ce50d04e97cc23f997fab8c0ce5faa8726.tar.bz2 coreclr-d23b78ce50d04e97cc23f997fab8c0ce5faa8726.zip |
[Linux][GDB-JIT] Fix bugs in gdbjit that break lldb stepping (#8637)
* Fix .text and .thunk symbols overlapping
When current method calls itself, a __thunk* symbol might be generated with the same address
as the method symbol in .text section. Avoid generating such __thunk* symbol.
* Do not create DWARF line table entries with the same address
* For each HiddenLine assign a zero line number in DWARF
Allow LLDB to to skip HiddenLines when stepping.
* Fix __thunk symbols containing garbage
Fix a bug when __thunk* symbols of previously compiled methods cause
generation of __thunk* symbols for currently compiled method without
filling symbol info.
* Fix missing check for the end of list of compiled methods
* Remove unnecessary check for zero prevLine in gdbjit
Diffstat (limited to 'src')
-rw-r--r-- | src/vm/gdbjit.cpp | 44 | ||||
-rw-r--r-- | src/vm/gdbjit.h | 2 |
2 files changed, 33 insertions, 13 deletions
diff --git a/src/vm/gdbjit.cpp b/src/vm/gdbjit.cpp index 96f8f8f93d..8e728839d6 100644 --- a/src/vm/gdbjit.cpp +++ b/src/vm/gdbjit.cpp @@ -1648,13 +1648,11 @@ void NotifyGdb::MethodCompiled(MethodDesc* MethodDescPtr) CodeHeader* pCH = (CodeHeader*)pCode - 1; CalledMethod* pCalledMethods = reinterpret_cast<CalledMethod*>(pCH->GetCalledMethods()); /* Collect addresses of thunks called by method */ - if (!CollectCalledMethods(pCalledMethods)) + if (!CollectCalledMethods(pCalledMethods, (TADDR)MethodDescPtr->GetNativeCode())) { return; } pCH->SetCalledMethods(NULL); - if (!codeAddrs.Contains((TADDR)pCode)) - codeAddrs.Add((TADDR)pCode); MetaSig sig(MethodDescPtr); int nArgsCount = sig.NumFixedArgs(); @@ -2102,18 +2100,17 @@ static void fixLineMapping(SymbolsInfo* lines, unsigned nlines) int prevLine = 0; for (int i = 0; i < nlines; ++i) { + if (lines[i].lineNumber == HiddenLine) + continue; if (lines[i].ilOffset == ICorDebugInfo::PROLOG) // will be fixed in next step { prevLine = 0; } else { - if (lines[i].lineNumber == 0 || lines[i].lineNumber == HiddenLine) + if (lines[i].lineNumber == 0) { - if (prevLine != 0) - { - lines[i].lineNumber = prevLine; - } + lines[i].lineNumber = prevLine; } else { @@ -2125,11 +2122,23 @@ static void fixLineMapping(SymbolsInfo* lines, unsigned nlines) prevLine = lines[nlines - 1].lineNumber; for (int i = nlines - 1; i >= 0; --i) { - if (lines[i].lineNumber == 0 || lines[i].lineNumber == HiddenLine) + if (lines[i].lineNumber == HiddenLine) + continue; + if (lines[i].lineNumber == 0) lines[i].lineNumber = prevLine; else prevLine = lines[i].lineNumber; } + // Skip HiddenLines + for (int i = 0; i < nlines; ++i) + { + if (lines[i].lineNumber == HiddenLine) + { + lines[i].lineNumber = 0; + if (i + 1 < nlines && lines[i + 1].ilOffset == ICorDebugInfo::NO_MAPPING) + lines[i + 1].lineNumber = 0; + } + } } /* Build program for DWARF source line section */ @@ -2166,6 +2175,13 @@ bool NotifyGdb::BuildLineProg(MemBuf& buf, PCODE startAddr, TADDR codeSize, Symb prevFile = lines[i].fileIndex; } + // GCC don't use the is_prologue_end flag to mark the first instruction after the prologue. + // Instead of it it is issueing a line table entry for the first instruction of the prologue + // and one for the first instruction after the prologue. + // We do not want to confuse the debugger so we have to avoid adding a line in such case. + if (i > 0 && lines[i - 1].nativeOffset == lines[i].nativeOffset) + continue; + IssueSetAddress(ptr, startAddr + lines[i].nativeOffset); if (lines[i].lineNumber != prevLine) { @@ -2369,10 +2385,13 @@ bool NotifyGdb::BuildDebugPub(MemBuf& buf, const char* name, uint32_t size, uint } /* Store addresses and names of the called methods into symbol table */ -bool NotifyGdb::CollectCalledMethods(CalledMethod* pCalledMethods) +bool NotifyGdb::CollectCalledMethods(CalledMethod* pCalledMethods, TADDR nativeCode) { AddrSet tmpCodeAddrs; + if (!codeAddrs.Contains(nativeCode)) + codeAddrs.Add(nativeCode); + CalledMethod* pList = pCalledMethods; /* count called methods */ @@ -2389,7 +2408,8 @@ bool NotifyGdb::CollectCalledMethods(CalledMethod* pCalledMethods) SymbolNames = new (nothrow) Elf_Symbol[SymbolCount]; pList = pCalledMethods; - for (int i = 1 + method.GetCount(); i < SymbolCount;) + int i = 1 + method.GetCount(); + while (i < SymbolCount && pList != NULL) { TADDR callAddr = (TADDR)pList->GetCallAddr(); if (!codeAddrs.Contains(callAddr)) @@ -2408,7 +2428,7 @@ bool NotifyGdb::CollectCalledMethods(CalledMethod* pCalledMethods) pList = pList->GetNext(); delete ptr; } - + SymbolCount = i; return true; } diff --git a/src/vm/gdbjit.h b/src/vm/gdbjit.h index 7d440b7e93..3160eccf57 100644 --- a/src/vm/gdbjit.h +++ b/src/vm/gdbjit.h @@ -401,7 +401,7 @@ private: static void IssueSimpleCommand(char*& ptr, uint8_t command); static void IssueParamCommand(char*& ptr, uint8_t command, char* param, int param_len); static void SplitPathname(const char* path, const char*& pathName, const char*& fileName); - static bool CollectCalledMethods(CalledMethod* pCM); + static bool CollectCalledMethods(CalledMethod* pCM, TADDR nativeCode); #ifdef _DEBUG static void DumpElf(const char* methodName, const MemBuf& buf); #endif |