-
Notifications
You must be signed in to change notification settings - Fork 2.7k
[Linux][GDB-JIT] Fix bugs in gdbjit that break lldb stepping #8637
Changes from all commits
679bbdc
c6d8104
0f11960
8dc2527
6dfdce6
bde801d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1432,13 +1432,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(); | ||
|
@@ -1886,18 +1884,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 | ||
{ | ||
|
@@ -1909,11 +1906,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 */ | ||
|
@@ -1950,6 +1959,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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A nit - we don't build with GCC, we use Clang There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If LLDB sees two lines with the same native address, it thinks that the code was compiled by GCC and sets is_prologue_end flag. We want to avoid such random prologue end in the middle of a function. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I've misread the comment a bit. |
||
// 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) { | ||
|
@@ -2139,10 +2155,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 */ | ||
|
@@ -2159,7 +2178,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)) | ||
|
@@ -2178,7 +2198,7 @@ bool NotifyGdb::CollectCalledMethods(CalledMethod* pCalledMethods) | |
pList = pList->GetNext(); | ||
delete ptr; | ||
} | ||
|
||
SymbolCount = i; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand the reason for this change. The loop will always exit when There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks! It seems that I forgot to add check for |
||
return true; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In which case is a line with ilOffset == ICorDebugInfo::NO_MAPPING right after a hidden line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I saw this in generated code for
try {...}, catch {...} finally {...}
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What would happen from the debugging experience point of view if we did not have this
if
here?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When stepping past
catch{...}
block LLDB will stop at the end oftry{...}
and and only than go to the start offinally{...}
. Bhis change allows lldb to skip that unnecessary stop at the end oftry {...}
.