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

[Linux][GDB-JIT] Fix bugs in gdbjit that break lldb stepping#8637

Merged
janvorli merged 6 commits intodotnet:masterfrom
ayuckhulk:gdbjit-fix-stepping-flaws
Dec 19, 2016
Merged

[Linux][GDB-JIT] Fix bugs in gdbjit that break lldb stepping#8637
janvorli merged 6 commits intodotnet:masterfrom
ayuckhulk:gdbjit-fix-stepping-flaws

Conversation

@ayuckhulk
Copy link

This PR fixes a number of bugs in GDBJIT that sometimes break LLDB stepping:

  • Overlapping symbols in .text and .thunk sections
    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.
  • Symbols containing garbage in .thunk sections
    When __thunk* symbols of previously compiled methods cause generation of __thunk* symbols for currently compiled method without filling symbol info.
  • Incorrect prologue_end detection by LLDB
    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.
  • LLDB does not skip HiddenLines

@mikem8361, @janvorli PTAL

cc @Dmitri-Botcharnikov @chunseoklee @seanshpark @lucenticus

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.
Fix a bug when __thunk* symbols of previously compiled methods cause
generation of __thunk* symbols for currently compiled method without
filling symbol info.
Allow LLDB to to skip HiddenLines when stepping.
delete ptr;
}

SymbolCount = i;
Copy link
Member

Choose a reason for hiding this comment

The 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 i is equal to the SymbolCount, so this assignment doesn't make sense. It seems the previous version of the code would have the same effect.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! It seems that I forgot to add check for pList != NULL.

prevFile = lines[i].fileIndex;
}

// GCC don't use the is_prologue_end flag to mark the first instruction after the prologue.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A nit - we don't build with GCC, we use Clang

Copy link
Author

Choose a reason for hiding this comment

The 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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I've misread the comment a bit.

if (lines[i].lineNumber == 0 || lines[i].lineNumber == HiddenLine)
if (lines[i].lineNumber == 0)
{
if (prevLine != 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This if is not necessary. If you leave it out, if the prevLine was 0, it would assign zero to the lines[i].lineNumber and since it was already zero, it would not change.

if (lines[i].lineNumber == HiddenLine)
{
lines[i].lineNumber = 0;
if (i + 1 < nlines && lines[i + 1].ilOffset == ICorDebugInfo::NO_MAPPING)
Copy link
Member

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?

Copy link
Author

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 {...}.

Copy link
Member

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?

Copy link
Author

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 of try{...} and and only than go to the start of finally{...}. Bhis change allows lldb to skip that unnecessary stop at the end of try {...}.

Copy link
Member

@janvorli janvorli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you!

@ayuckhulk
Copy link
Author

@janvorli Thank you for the review!

@janvorli
Copy link
Member

@dotnet-bot test Linux ARM Emulator Cross Debug Build

@janvorli
Copy link
Member

@dotnet-bot test Windows_NT x86 Checked Build and Test

@ayuckhulk
Copy link
Author

@janvorli Is this PR ready to be merged?

@janvorli janvorli merged commit d23b78c into dotnet:master Dec 19, 2016
@ayuckhulk
Copy link
Author

Thank you!

@karelz karelz modified the milestone: 2.0.0 Aug 28, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants