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:
@@ -106,6 +106,10 @@ public:
|
|||||||
virtual status_t GetInstructionInfo(target_addr_t address,
|
virtual status_t GetInstructionInfo(target_addr_t address,
|
||||||
InstructionInfo& _info,
|
InstructionInfo& _info,
|
||||||
CpuState* state) = 0;
|
CpuState* state) = 0;
|
||||||
|
virtual status_t ResolvePICFunctionAddress(target_addr_t
|
||||||
|
instructionAddress,
|
||||||
|
CpuState* state,
|
||||||
|
target_addr_t& _targetAddress) = 0;
|
||||||
|
|
||||||
status_t CreateStackTrace(Team* team,
|
status_t CreateStackTrace(Team* team,
|
||||||
ImageDebugInfoProvider* imageInfoProvider,
|
ImageDebugInfoProvider* imageInfoProvider,
|
||||||
|
|||||||
@@ -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
|
status_t
|
||||||
ArchitectureX86::GetWatchpointDebugCapabilities(int32& _maxRegisterCount,
|
ArchitectureX86::GetWatchpointDebugCapabilities(int32& _maxRegisterCount,
|
||||||
int32& _maxBytesPerRegister, uint8& _watchpointCapabilityFlags)
|
int32& _maxBytesPerRegister, uint8& _watchpointCapabilityFlags)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
* Copyright 2011-2012, Rene Gollent, [email protected].
|
* Copyright 2011-2013, Rene Gollent, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef ARCHITECTURE_X86_H
|
#ifndef ARCHITECTURE_X86_H
|
||||||
@@ -60,6 +60,10 @@ public:
|
|||||||
Statement*& _statement);
|
Statement*& _statement);
|
||||||
virtual status_t GetInstructionInfo(target_addr_t address,
|
virtual status_t GetInstructionInfo(target_addr_t address,
|
||||||
InstructionInfo& _info, CpuState* state);
|
InstructionInfo& _info, CpuState* state);
|
||||||
|
virtual status_t ResolvePICFunctionAddress(
|
||||||
|
target_addr_t instructionAddress,
|
||||||
|
CpuState* state,
|
||||||
|
target_addr_t& _targetAddress);
|
||||||
|
|
||||||
virtual status_t GetWatchpointDebugCapabilities(
|
virtual status_t GetWatchpointDebugCapabilities(
|
||||||
int32& _maxRegisterCount,
|
int32& _maxRegisterCount,
|
||||||
|
|||||||
@@ -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
|
status_t
|
||||||
ArchitectureX8664::GetWatchpointDebugCapabilities(int32& _maxRegisterCount,
|
ArchitectureX8664::GetWatchpointDebugCapabilities(int32& _maxRegisterCount,
|
||||||
int32& _maxBytesPerRegister, uint8& _watchpointCapabilityFlags)
|
int32& _maxBytesPerRegister, uint8& _watchpointCapabilityFlags)
|
||||||
|
|||||||
@@ -61,6 +61,10 @@ public:
|
|||||||
Statement*& _statement);
|
Statement*& _statement);
|
||||||
virtual status_t GetInstructionInfo(target_addr_t address,
|
virtual status_t GetInstructionInfo(target_addr_t address,
|
||||||
InstructionInfo& _info, CpuState* state);
|
InstructionInfo& _info, CpuState* state);
|
||||||
|
virtual status_t ResolvePICFunctionAddress(target_addr_t
|
||||||
|
instructionAddress,
|
||||||
|
CpuState* state,
|
||||||
|
target_addr_t& _targetAddress);
|
||||||
|
|
||||||
virtual status_t GetWatchpointDebugCapabilities(
|
virtual status_t GetWatchpointDebugCapabilities(
|
||||||
int32& _maxRegisterCount,
|
int32& _maxRegisterCount,
|
||||||
|
|||||||
@@ -1112,27 +1112,15 @@ DwarfImageDebugInfo::_CreateReturnValues(ReturnValueInfoList* returnValueInfos,
|
|||||||
}
|
}
|
||||||
|
|
||||||
status_t result = B_OK;
|
status_t result = B_OK;
|
||||||
ImageDebugInfo* imageInfo = image->GetImageDebugInfo();
|
ImageDebugInfo* imageInfo = targetImage->GetImageDebugInfo();
|
||||||
|
|
||||||
FunctionInstance* targetFunction;
|
FunctionInstance* targetFunction;
|
||||||
target_size_t addressSize = fDebuggerInterface->GetArchitecture()
|
if (imageInfo->GetAddressSectionType(subroutineAddress)
|
||||||
->AddressSize();
|
== ADDRESS_SECTION_TYPE_PLT) {
|
||||||
if (subroutineAddress >= fPLTSectionStart
|
result = fArchitecture->ResolvePICFunctionAddress(
|
||||||
&& subroutineAddress < fPLTSectionEnd) {
|
subroutineAddress, subroutineState, subroutineAddress);
|
||||||
// if the function in question is position-independent, the call
|
if (result != B_OK)
|
||||||
// will actually have taken us to its corresponding PLT slot.
|
continue;
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
targetFunction = imageInfo->FunctionAtAddress(subroutineAddress);
|
targetFunction = imageInfo->FunctionAtAddress(subroutineAddress);
|
||||||
@@ -1166,7 +1154,7 @@ DwarfImageDebugInfo::_CreateReturnValues(ReturnValueInfoList* returnValueInfos,
|
|||||||
// if we were unable to determine a size for the type,
|
// if we were unable to determine a size for the type,
|
||||||
// simply default to the architecture's register width.
|
// simply default to the architecture's register width.
|
||||||
if (byteSize == 0)
|
if (byteSize == 0)
|
||||||
byteSize = addressSize;
|
byteSize = fArchitecture->AddressSize();
|
||||||
|
|
||||||
ValueLocation* location;
|
ValueLocation* location;
|
||||||
result = fArchitecture->GetReturnAddressLocation(frame,
|
result = fArchitecture->GetReturnAddressLocation(frame,
|
||||||
|
|||||||
Reference in New Issue
Block a user