From aef9e4fce29452a0770c4adc1ad67f64c5d2d034 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Sun, 28 Jul 2013 17:30:49 -0400 Subject: [PATCH] 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. --- src/apps/debugger/arch/Architecture.h | 4 +++ .../debugger/arch/x86/ArchitectureX86.cpp | 26 ++++++++++++++ src/apps/debugger/arch/x86/ArchitectureX86.h | 6 +++- .../arch/x86_64/ArchitectureX8664.cpp | 34 +++++++++++++++++++ .../debugger/arch/x86_64/ArchitectureX8664.h | 4 +++ .../debug_info/DwarfImageDebugInfo.cpp | 30 +++++----------- 6 files changed, 82 insertions(+), 22 deletions(-) diff --git a/src/apps/debugger/arch/Architecture.h b/src/apps/debugger/arch/Architecture.h index 76d553bac4..b792232a87 100644 --- a/src/apps/debugger/arch/Architecture.h +++ b/src/apps/debugger/arch/Architecture.h @@ -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, diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.cpp b/src/apps/debugger/arch/x86/ArchitectureX86.cpp index 7fa5002e70..0955446019 100644 --- a/src/apps/debugger/arch/x86/ArchitectureX86.cpp +++ b/src/apps/debugger/arch/x86/ArchitectureX86.cpp @@ -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) diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.h b/src/apps/debugger/arch/x86/ArchitectureX86.h index 1a6120cfa2..a672fb8a51 100644 --- a/src/apps/debugger/arch/x86/ArchitectureX86.h +++ b/src/apps/debugger/arch/x86/ArchitectureX86.h @@ -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, diff --git a/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp b/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp index 704d8c6a09..a234cfe1bf 100644 --- a/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp +++ b/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp @@ -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) diff --git a/src/apps/debugger/arch/x86_64/ArchitectureX8664.h b/src/apps/debugger/arch/x86_64/ArchitectureX8664.h index e448ba12e7..a5d2775d85 100644 --- a/src/apps/debugger/arch/x86_64/ArchitectureX8664.h +++ b/src/apps/debugger/arch/x86_64/ArchitectureX8664.h @@ -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, diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp index da83cf8d16..ba463b4824 100644 --- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp @@ -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,