Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix two issues detected by Valgrind #34462

Merged
merged 2 commits into from
Apr 3, 2020

Conversation

janvorli
Copy link
Member

@janvorli janvorli commented Apr 2, 2020

When I have used Valgrind to investigate a memory corruption issue recently,
I've noticed that it has also reported two cases when a conditional jump
was using an uninitialized variable as one of the inputs to the condition.

This change fixes these.

When I have used Valgrind to investigate a memory corruption issue recently,
I've noticed that it has also reported two cases when a conditional jump
was using an uninitialized variable as one of the inputs to the condition.

This change fixes these.
@janvorli janvorli added this to the 5.0 milestone Apr 2, 2020
@janvorli janvorli requested a review from jkotas April 2, 2020 15:19
@janvorli janvorli self-assigned this Apr 2, 2020
@tmds
Copy link
Member

tmds commented Apr 2, 2020

@janvorli I tried running valgrind against dotnet, but it failed and gave an error (I believe about a machine instruction it didn't know).
Does it work well for you?

@@ -1539,6 +1539,8 @@ Thread::Thread()
m_DeserializationTracker = NULL;

m_currentPrepareCodeConfig = nullptr;

memset(dangerousObjRefs, 0, sizeof(dangerousObjRefs));
Copy link
Member

Choose a reason for hiding this comment

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

Does this need to be under debug ifdef?

Copy link
Member Author

Choose a reason for hiding this comment

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

Right, it does. I have not noticed that it is a debug build only thing.

@janvorli
Copy link
Member Author

janvorli commented Apr 2, 2020

Does it work well for you?

It actually fails relatively early with .NET Core 5, but it worked fine with .NET Core 3.1.

@janvorli
Copy link
Member Author

janvorli commented Apr 2, 2020

@tmds this is the Valgrind failure with .NET Core 5 I was getting:

vex amd64->IR: unhandled instruction bytes: 0x48 0xCF 0x48 0x8D 0x64 0x24 0x30 0x5D
vex amd64->IR:   REX=1 REX.W=1 REX.R=0 REX.X=0 REX.B=0
vex amd64->IR:   VEX=0 VEX.L=0 VEX.nVVVV=0x0 ESC=NONE
vex amd64->IR:   PFX.66=0 PFX.F2=0 PFX.F3=0
==24510== valgrind: Unrecognised instruction at address 0x6c62d36.

This looks like a bug in Valgrind, as there is a valid IRET instruction with REX.W prefix.

@am11
Copy link
Member

am11 commented Apr 2, 2020

With:

valgrind -v --tool=memcheck --leak-check=full --show-reachable=yes \
    --num-callers=40 --log-file=dotnet-valgrind.log \
    dotnet5 new console

valgrind-3.13.0 on Ubuntu bionic found 176 Conditional jump or move depends on uninitialised value(s) cases and the last line of donet-valgrind.log shows:

==112569== ERROR SUMMARY: 1819 errors from 170 contexts (suppressed: 0 from 0)

dotnet5 --version => 5.0.100-preview.3.20177.2.

@tmds
Copy link
Member

tmds commented Apr 2, 2020

On Fedora 31 with .NET 3.1 I get:

$ dotnet --version
3.1.201
$ valgrind --version
valgrind-3.15.0
$ valgrind dotnet new console -o console
...
vex amd64->IR: unhandled instruction bytes: 0x48 0xE9 0x70 0xB3 0x41 0xA9 0x49 0xBA 0x88 0xCD
vex amd64->IR:   REX=1 REX.W=1 REX.R=0 REX.X=0 REX.B=0
vex amd64->IR:   VEX=0 VEX.L=0 VEX.nVVVV=0x0 ESC=NONE
vex amd64->IR:   PFX.66=0 PFX.F2=0 PFX.F3=0
==178762== valgrind: Unrecognised instruction at address 0x5d09698a.

@janvorli what version of valgrind are you using? And does it still work with .NET Core 3.1?

@janvorli
Copy link
Member Author

janvorli commented Apr 3, 2020

I was using the default valgrind package on Ubuntu 16.04, which is version 3.11.0. However, I have tested it just on an app reproducing the write behind allocated memory issue. So it is possible that more things would trouble it if it went through different code paths.
The instruction it has failed on in your case is just a pc relative jump with 32 bit offset (the first 6 bytes) with added REX.W prefix that has no effect. So I guess that's what has confused Valgrind.
I think I've actually seen this too in one of my test runs on .NET Core 5.0.

@janvorli janvorli closed this Apr 3, 2020
@janvorli janvorli reopened this Apr 3, 2020
@janvorli janvorli merged commit 83bbaba into dotnet:master Apr 3, 2020
@jkotas
Copy link
Member

jkotas commented Apr 3, 2020

Where are these superfluous REX.W prefixes coming from? Do we generate them, or is it something that clang generates?

@janvorli
Copy link
Member Author

janvorli commented Apr 3, 2020

One comes from RtlRestoreContext here:


I don't know where the other stems from.

@jkotas
Copy link
Member

jkotas commented Apr 3, 2020

Thanks. The prefix on iret is required - it is not superfluous, so we are good on that one.

@janvorli
Copy link
Member Author

janvorli commented Apr 4, 2020

@jkotas the other one - the JMP with extra REX.W prefix seems to be coming from the JIT or a code that runtime generates.

@jkotas
Copy link
Member

jkotas commented Apr 4, 2020

Is there a way to dump the disassembly before the offending JMP? Hopefully, we will be able to guess where it came from.

@janvorli
Copy link
Member Author

janvorli commented Apr 6, 2020

@jkotas there is a way to run valgrind in a mode where one can attach a debugger externally, so I'll give it a try.

@janvorli
Copy link
Member Author

janvorli commented Apr 6, 2020

@jkotas, I can see that the jump that it complains on is:
=> 0x000000003d5cb57a: 48 e9 00 30 41 c9 jmpq 0x69de580 <NDirectImportThunk>

So it comes from

static const int Type = 0x48;

It is used here:
void NDirectImportPrecode::Init(MethodDesc* pMD, LoaderAllocator *pLoaderAllocator)
{
WRAPPER_NO_CONTRACT;
StubPrecode::Init(pMD, pLoaderAllocator, NDirectImportPrecode::Type, GetEEFuncEntryPoint(NDirectImportThunk));
}

@ghost ghost locked as resolved and limited conversation to collaborators Dec 9, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants