Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Commit

Permalink
[Linux][GDB-JIT] Fix bugs in gdbjit that break lldb stepping (#8637)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
ayuckhulk authored and janvorli committed Dec 19, 2016
1 parent 6fce053 commit d23b78c
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 13 deletions.
44 changes: 32 additions & 12 deletions src/vm/gdbjit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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
{
Expand All @@ -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 */
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 */
Expand All @@ -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))
Expand All @@ -2408,7 +2428,7 @@ bool NotifyGdb::CollectCalledMethods(CalledMethod* pCalledMethods)
pList = pList->GetNext();
delete ptr;
}

SymbolCount = i;
return true;
}

Expand Down
2 changes: 1 addition & 1 deletion src/vm/gdbjit.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ class NotifyGdb
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
Expand Down

0 comments on commit d23b78c

Please sign in to comment.