Debugger: Fix return value for PIC functions on x86-64.

- Add Architecture::ResolvePICFunctionAddress() and pull out the
previous code in DwarfImageDebugInfo into the x86-specific
implemementation.

- PIC handling works a bit differently on x86-64 than it does on x86
since x86-64 is likely to use RIP-relative addressing. Implement
ArchitectureX8664::ResolvePICFunctionAddress() accordingly.
This commit is contained in:
Rene Gollent 2013-07-28 17:30:49 -04:00
parent 0a1334de28
commit aef9e4fce2
6 changed files with 82 additions and 22 deletions

View File

@ -106,6 +106,10 @@ public:
virtual status_t GetInstructionInfo(target_addr_t address,
InstructionInfo& _info,
CpuState* state) = 0;
virtual status_t ResolvePICFunctionAddress(target_addr_t
instructionAddress,
CpuState* state,
target_addr_t& _targetAddress) = 0;
status_t CreateStackTrace(Team* team,
ImageDebugInfoProvider* imageInfoProvider,

View File

@ -597,6 +597,32 @@ ArchitectureX86::GetInstructionInfo(target_addr_t address,
}
status_t
ArchitectureX86::ResolvePICFunctionAddress(target_addr_t instructionAddress,
CpuState* state, target_addr_t& _targetAddress)
{
// if the function in question is position-independent, the call
// will actually have taken us to its corresponding PLT slot.
// in such a case, look at the disassembled jump to determine
// where to find the actual function address.
state->SetInstructionPointer(instructionAddress);
InstructionInfo info;
if (GetInstructionInfo(instructionAddress, info, state) != B_OK) {
return B_BAD_VALUE;
}
target_addr_t subroutineAddress = info.TargetAddress();
ssize_t bytesRead = fTeamMemory->ReadMemory(info.TargetAddress(),
&subroutineAddress, fAddressSize);
if (bytesRead != fAddressSize)
return B_BAD_VALUE;
_targetAddress = subroutineAddress;
return B_OK;
}
status_t
ArchitectureX86::GetWatchpointDebugCapabilities(int32& _maxRegisterCount,
int32& _maxBytesPerRegister, uint8& _watchpointCapabilityFlags)

View File

@ -1,6 +1,6 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2011-2012, Rene Gollent, rene@gollent.com.
* Copyright 2011-2013, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
#ifndef ARCHITECTURE_X86_H
@ -60,6 +60,10 @@ public:
Statement*& _statement);
virtual status_t GetInstructionInfo(target_addr_t address,
InstructionInfo& _info, CpuState* state);
virtual status_t ResolvePICFunctionAddress(
target_addr_t instructionAddress,
CpuState* state,
target_addr_t& _targetAddress);
virtual status_t GetWatchpointDebugCapabilities(
int32& _maxRegisterCount,

View File

@ -621,6 +621,40 @@ ArchitectureX8664::GetInstructionInfo(target_addr_t address,
}
status_t
ArchitectureX8664::ResolvePICFunctionAddress(target_addr_t instructionAddress,
CpuState* state, target_addr_t& _targetAddress)
{
// if the function in question is position-independent, the call
// will actually have taken us to its corresponding PLT slot.
// in such a case, look at the disassembled jump to determine
// where to find the actual function address.
InstructionInfo info;
if (GetInstructionInfo(instructionAddress, info, state) != B_OK)
return B_BAD_VALUE;
// x86-64 is likely to use a RIP-relative jump here
// as such, set our instruction pointer to the address
// after this instruction (where it would be during actual
// execution), and recalculate the target address of the jump
state->SetInstructionPointer(info.Address() + info.Size());
if (GetInstructionInfo(info.Address(), info, state) != B_OK)
return B_BAD_VALUE;
target_addr_t subroutineAddress;
ssize_t bytesRead = fTeamMemory->ReadMemory(info.TargetAddress(),
&subroutineAddress, fAddressSize);
if (bytesRead != fAddressSize)
return B_BAD_VALUE;
_targetAddress = subroutineAddress;
return B_OK;
return B_BAD_VALUE;
}
status_t
ArchitectureX8664::GetWatchpointDebugCapabilities(int32& _maxRegisterCount,
int32& _maxBytesPerRegister, uint8& _watchpointCapabilityFlags)

View File

@ -61,6 +61,10 @@ public:
Statement*& _statement);
virtual status_t GetInstructionInfo(target_addr_t address,
InstructionInfo& _info, CpuState* state);
virtual status_t ResolvePICFunctionAddress(target_addr_t
instructionAddress,
CpuState* state,
target_addr_t& _targetAddress);
virtual status_t GetWatchpointDebugCapabilities(
int32& _maxRegisterCount,

View File

@ -1112,27 +1112,15 @@ DwarfImageDebugInfo::_CreateReturnValues(ReturnValueInfoList* returnValueInfos,
}
status_t result = B_OK;
ImageDebugInfo* imageInfo = image->GetImageDebugInfo();
ImageDebugInfo* imageInfo = targetImage->GetImageDebugInfo();
FunctionInstance* targetFunction;
target_size_t addressSize = fDebuggerInterface->GetArchitecture()
->AddressSize();
if (subroutineAddress >= fPLTSectionStart
&& subroutineAddress < fPLTSectionEnd) {
// if the function in question is position-independent, the call
// will actually have taken us to its corresponding PLT slot.
// in such a case, look at the disassembled jump to determine
// where to find the actual function address.
InstructionInfo info;
if (fDebuggerInterface->GetArchitecture()->GetInstructionInfo(
subroutineAddress, info, subroutineState) != B_OK) {
return B_BAD_VALUE;
}
ssize_t bytesRead = fDebuggerInterface->ReadMemory(
info.TargetAddress(), &subroutineAddress, addressSize);
if (bytesRead != (ssize_t)addressSize)
return B_BAD_VALUE;
if (imageInfo->GetAddressSectionType(subroutineAddress)
== ADDRESS_SECTION_TYPE_PLT) {
result = fArchitecture->ResolvePICFunctionAddress(
subroutineAddress, subroutineState, subroutineAddress);
if (result != B_OK)
continue;
}
targetFunction = imageInfo->FunctionAtAddress(subroutineAddress);
@ -1166,7 +1154,7 @@ DwarfImageDebugInfo::_CreateReturnValues(ReturnValueInfoList* returnValueInfos,
// if we were unable to determine a size for the type,
// simply default to the architecture's register width.
if (byteSize == 0)
byteSize = addressSize;
byteSize = fArchitecture->AddressSize();
ValueLocation* location;
result = fArchitecture->GetReturnAddressLocation(frame,