Closed GoogleCodeExporter closed 9 years ago
As soon as I have access to Visual Studio Express 2013 I will be able to look
at this.
Or I can try help you to look at this.
So first thing is to identify which function patching fails. You can figure it
out by stepping in debugger.
Once problematic function is identified we'll need to understand why exactly it
failed. And in order to do that VS's disasm window can be used, which can be
pointed at address we're trying to patch.
Original comment by alkondratenko
on 29 Sep 2013 at 2:42
I've tried to gather as much information for you as possible this morning,
please find below my findings.
Cause of the crash is gperftools failing to patch the main executables
'expand_base' function found within expand.c
void * __cdecl _expand_base (void * pBlock, size_t newsize)
What is interesting to note is that during a separate DLLs patching process,
this function is successfully patched to the gperftools function - so during
the main executables patching process, it encounters this function which has
already been patched.
The disasm of the function during the call to patch the main executable is:
void * __cdecl _expand_base (void * pBlock, size_t newsize)
{
743C05F9 jmp `anonymous
namespace'::LibcInfoWithPatchFunctions<1>::Perftools__expand (5B0683B0h)
It is worthwhile mentioning at this point that the jmp command in this case is
a E9 opcode jump.
So at this point, everything seems like it should be working except the
patching function is being provided a different address to patch (it's actually
a pointer to a mid-point of another function call that just so happens to have
a return statement).
This suggested that the problem has occurred before the patching process, so I
found a fancy function called PreamblePatcher::ResolveTargetImpl that from my
understanding follows the jmp calls until it gets to the necessary function
that will be performing the actual operation, which is the point where
gperftools will patch.
The issue with PreamblePatcher::ResolveTargetImpl is it successfully finds the
_expand_base function (which has already been patched, as per above) but it
resolves the target address incorrectly.
The target code which I think is the root of the issue is the following inside
PreamblePatcher::ResolveTargetImpl (line 95):
if (target[0] == ASM_JMP32REL) {
// target[1-4] holds the place the jmp goes to, but it's
// relative to the next instruction.
int relative_offset; // Windows guarantees int is 4 bytes
SIDESTEP_ASSERT(sizeof(relative_offset) == 4);
memcpy(reinterpret_cast<void*>(&relative_offset),
reinterpret_cast<void*>(target + 1), 4);
new_target = target + 5 + relative_offset;
}
This will successfully detect the E9 jmp but looking at the memory for the
address I was left confused:
0x743C05F9 e9 b2 7d ca e6 cc cc 85 ff 75 17 e8 13 14 f7 ff c7 00 16 00 00 00 e8
So following that relative jmp instruction to the appropriate point in memory I
was left with a address that wasn't a valid pointer, I've obviously done
something incorrectly I think as the disasm correctly resolves the instruction
(as you saw above), but none the less the PreamblePatcher::ResolveTargetImpl
also incorrectly resolved this address (it returns 0x5C2283B0, where as the
correct pointer to return should have been 0x5B0683B0 as per the disasm).
Hopefully this information is enough for you to go off, I've had to stop
debugging for the time being as a urgent task has come up. I'll try to get back
to debugging more when I can.
Original comment by shaun.bu...@immersaview.com
on 30 Sep 2013 at 1:45
What if _expand_base is actually broken in msvc2013 ?
Can you try some small program that uses it without gperftools ?
Original comment by alkondratenko
on 13 Oct 2013 at 2:38
With recent visual studio 2013 express I'm not seeing this problem.
Original comment by alkondratenko
on 5 Jan 2014 at 9:07
Original issue reported on code.google.com by
shaun.bu...@immersaview.com
on 27 Sep 2013 at 6:36