Ticket #7761: return_values.patch

File return_values.patch, 17.5 KB (added by anevilyak, 11 years ago)

Proof of concept implementation

  • src/apps/debugger/Jamfile

    diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile
    index 44c56d0..c2aaa66 100644
    a b Application Debugger :  
    124124
    125125    # ids
    126126    FunctionID.cpp
     127    FunctionParameterID.cpp
    127128    LocalVariableID.cpp
    128129    ObjectID.cpp
    129     FunctionParameterID.cpp
     130    ReturnValueID.cpp
    130131
    131132    # jobs
    132133    GetCPUStateJob.cpp
  • src/apps/debugger/arch/Architecture.h

    diff --git a/src/apps/debugger/arch/Architecture.h b/src/apps/debugger/arch/Architecture.h
    index 38409d0..748e9dc 100644
    a b class StackTrace;  
    3030class Statement;
    3131class Team;
    3232class TeamMemory;
     33class ValueLocation;
    3334
    3435
    3536enum {
    public:  
    118119                                    int32& _maxBytesPerRegister,
    119120                                    uint8& _watchpointCapabilityFlags) = 0;
    120121
     122    virtual status_t            GetReturnAddressLocation(
     123                                    StackFrame* frame, target_size_t valueSize,
     124                                    ValueLocation*& _location) = 0;
     125
    121126
    122127protected:
    123128            TeamMemory*         fTeamMemory;
  • src/apps/debugger/arch/InstructionInfo.cpp

    diff --git a/src/apps/debugger/arch/InstructionInfo.cpp b/src/apps/debugger/arch/InstructionInfo.cpp
    index 03afae4..1a48c70 100644
    a b  
    99InstructionInfo::InstructionInfo()
    1010    :
    1111    fAddress(0),
     12    fTargetAddress(0),
    1213    fSize(0),
    1314    fType(INSTRUCTION_TYPE_OTHER),
    1415    fBreakpointAllowed(false),
    InstructionInfo::InstructionInfo()  
    1718}
    1819
    1920
    20 InstructionInfo::InstructionInfo(target_addr_t address, target_size_t size,
     21InstructionInfo::InstructionInfo(target_addr_t address,
     22    target_addr_t targetAddress, target_size_t size,
    2123    instruction_type type, bool breakpointAllowed,
    2224    const BString& disassembledLine)
    2325    :
    2426    fAddress(address),
     27    fTargetAddress(targetAddress),
    2528    fSize(size),
    2629    fType(type),
    2730    fBreakpointAllowed(breakpointAllowed),
    InstructionInfo::InstructionInfo(target_addr_t address, target_size_t size,  
    3134
    3235
    3336bool
    34 InstructionInfo::SetTo(target_addr_t address, target_size_t size,
    35     instruction_type type, bool breakpointAllowed,
     37InstructionInfo::SetTo(target_addr_t address, target_addr_t targetAddress,
     38    target_size_t size, instruction_type type, bool breakpointAllowed,
    3639    const BString& disassembledLine)
    3740{
    3841    fAddress = address;
     42    fTargetAddress = targetAddress;
    3943    fSize = size;
    4044    fType = type;
    4145    fBreakpointAllowed = breakpointAllowed;
  • src/apps/debugger/arch/InstructionInfo.h

    diff --git a/src/apps/debugger/arch/InstructionInfo.h b/src/apps/debugger/arch/InstructionInfo.h
    index 36c2fa2..f130080 100644
    a b class InstructionInfo {  
    2020public:
    2121                                InstructionInfo();
    2222                                InstructionInfo(target_addr_t address,
     23                                    target_addr_t targetAddress,
    2324                                    target_size_t size, instruction_type type,
    2425                                    bool breakpointAllowed,
    2526                                    const BString& disassembledLine);
    2627
    27             bool                SetTo(target_addr_t address, target_size_t size,
     28            bool                SetTo(target_addr_t address,
     29                                    target_addr_t targetAddress,
     30                                    target_size_t size,
    2831                                    instruction_type type,
    2932                                    bool breakpointAllowed,
    3033                                    const BString& disassembledLine);
    3134
    3235            target_addr_t       Address() const     { return fAddress; }
     36            target_addr_t       TargetAddress() const
     37                                    { return fTargetAddress; }
    3338            target_size_t       Size() const        { return fSize; }
    3439            instruction_type    Type() const        { return fType; }
    3540            bool                IsBreakpointAllowed() const
    public:  
    4045
    4146private:
    4247            target_addr_t       fAddress;
     48            target_addr_t       fTargetAddress;
    4349            target_size_t       fSize;
    4450            instruction_type    fType;
    4551            bool                fBreakpointAllowed;
  • src/apps/debugger/arch/x86/ArchitectureX86.cpp

    diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.cpp b/src/apps/debugger/arch/x86/ArchitectureX86.cpp
    index dd19a90..80aec92 100644
    a b  
    2323#include "StackFrame.h"
    2424#include "Statement.h"
    2525#include "TeamMemory.h"
     26#include "ValueLocation.h"
    2627#include "X86AssemblyLanguage.h"
    2728
    2829#include "disasm/DisassemblerX86.h"
    status_t  
    579580ArchitectureX86::GetInstructionInfo(target_addr_t address,
    580581    InstructionInfo& _info)
    581582{
    582     // read the code
     583    // read the code - maximum x86{-64} instruction size = 15 bytes
    583584    uint8 buffer[16];
    584         // TODO: What's the maximum instruction size?
    585585    ssize_t bytesRead = fTeamMemory->ReadMemory(address, buffer,
    586586        sizeof(buffer));
    587587    if (bytesRead < 0)
    ArchitectureX86::GetInstructionInfo(target_addr_t address,  
    596596    // disassemble the instruction
    597597    BString line;
    598598    target_addr_t instructionAddress;
     599    target_addr_t targetAddress = 0;
    599600    target_size_t instructionSize;
    600601    bool breakpointAllowed;
    601602    error = disassembler.GetNextInstruction(line, instructionAddress,
    ArchitectureX86::GetInstructionInfo(target_addr_t address,  
    607608    if (buffer[0] == 0xff && (buffer[1] & 0x34) == 0x10) {
    608609        // absolute call with r/m32
    609610        instructionType = INSTRUCTION_TYPE_SUBROUTINE_CALL;
     611        // TODO: retrieve target address (might be in a register)
    610612    } else if (buffer[0] == 0xe8 && instructionSize == 5) {
    611613        // relative call with rel32 -- don't categorize the call with 0 as
    612614        // subroutine call, since it is only used to get the address of the GOT
    613615        if (buffer[1] != 0 || buffer[2] != 0 || buffer[3] != 0
    614616            || buffer[4] != 0) {
    615617            instructionType = INSTRUCTION_TYPE_SUBROUTINE_CALL;
     618            int32 offset;
     619            memcpy(&offset, &buffer[1], 4);
     620            targetAddress = instructionAddress + instructionSize + offset;
    616621        }
    617622    }
    618623
    619     if (!_info.SetTo(instructionAddress, instructionSize, instructionType,
    620             breakpointAllowed, line)) {
     624    if (!_info.SetTo(instructionAddress, targetAddress, instructionSize,
     625            instructionType, breakpointAllowed, line)) {
    621626        return B_NO_MEMORY;
    622627    }
    623628
    ArchitectureX86::GetWatchpointDebugCapabilities(int32& _maxRegisterCount,  
    643648}
    644649
    645650
     651status_t
     652ArchitectureX86::GetReturnAddressLocation(StackFrame* frame,
     653    target_size_t valueSize, ValueLocation*& _location)
     654{
     655    ValueLocation* location = new(std::nothrow) ValueLocation(
     656        IsBigEndian());
     657    if (location == NULL)
     658        return B_NO_MEMORY;
     659    BReference<ValueLocation> locationReference(location,
     660        true);
     661
     662    if (valueSize <= 4) {
     663        ValuePieceLocation piece;
     664        piece.SetSize(valueSize);
     665        piece.SetToRegister(X86_REGISTER_EAX);
     666        if (!location->AddPiece(piece))
     667            return B_NO_MEMORY;
     668    } else if (valueSize <= 8) {
     669        ValuePieceLocation piece;
     670        piece.SetSize(4);
     671        piece.SetToRegister(X86_REGISTER_EAX);
     672        if (!location->AddPiece(piece))
     673            return B_NO_MEMORY;
     674        piece.SetToRegister(X86_REGISTER_EDX);
     675        piece.SetSize(valueSize - 4);
     676        if (!location->AddPiece(piece))
     677            return B_NO_MEMORY;
     678    } else {
     679        ValuePieceLocation piece;
     680        piece.SetToMemory(frame->GetCpuState()->StackPointer());
     681        piece.SetSize(valueSize);
     682        if (!location->AddPiece(piece))
     683            return B_NO_MEMORY;
     684    }
     685
     686    _location = locationReference.Detach();
     687    return B_OK;
     688}
     689
     690
    646691void
    647692ArchitectureX86::_AddRegister(int32 index, const char* name,
    648693    uint32 bitSize, uint32 valueType, register_type type, bool calleePreserved)
  • src/apps/debugger/arch/x86/ArchitectureX86.h

    diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.h b/src/apps/debugger/arch/x86/ArchitectureX86.h
    index 48e849c..1549f9b 100644
    a b public:  
    6666                                    int32& _maxBytesPerRegister,
    6767                                    uint8& _watchpointCapabilityFlags);
    6868
     69    virtual status_t            GetReturnAddressLocation(
     70                                    StackFrame* frame, target_size_t valueSize,
     71                                    ValueLocation*& _location);
     72
     73
    6974private:
    7075            struct ToDwarfRegisterMap;
    7176            struct FromDwarfRegisterMap;
  • src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp

    diff --git a/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp b/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp
    index 2152562..acf2f93 100644
    a b ArchitectureX8664::GetInstructionInfo(target_addr_t address,  
    487487    // disassemble the instruction
    488488    BString line;
    489489    target_addr_t instructionAddress;
     490    target_addr_t targetAddress = 0;
    490491    target_size_t instructionSize;
    491492    bool breakpointAllowed;
    492493    error = disassembler.GetNextInstruction(line, instructionAddress,
    ArchitectureX8664::GetInstructionInfo(target_addr_t address,  
    508509        }
    509510    }
    510511
    511     if (!_info.SetTo(instructionAddress, instructionSize, instructionType,
    512             breakpointAllowed, line)) {
     512    if (!_info.SetTo(instructionAddress, targetAddress, instructionSize,
     513            instructionType, breakpointAllowed, line)) {
    513514        return B_NO_MEMORY;
    514515    }
    515516
    ArchitectureX8664::GetWatchpointDebugCapabilities(int32& _maxRegisterCount,  
    534535}
    535536
    536537
     538status_t
     539ArchitectureX8664::GetReturnAddressLocation(StackFrame* frame,
     540    target_size_t valueSize, ValueLocation*& _location) {
     541    return B_NOT_SUPPORTED;
     542}
     543
     544
    537545void
    538546ArchitectureX8664::_AddRegister(int32 index, const char* name,
    539547    uint32 bitSize, uint32 valueType, register_type type, bool calleePreserved)
  • src/apps/debugger/arch/x86_64/ArchitectureX8664.h

    diff --git a/src/apps/debugger/arch/x86_64/ArchitectureX8664.h b/src/apps/debugger/arch/x86_64/ArchitectureX8664.h
    index ec81448..f61b8f3 100644
    a b public:  
    6767                                    int32& _maxBytesPerRegister,
    6868                                    uint8& _watchpointCapabilityFlags);
    6969
     70    virtual status_t            GetReturnAddressLocation(
     71                                    StackFrame* frame, target_size_t valueSize,
     72                                    ValueLocation*& _location);
     73
    7074private:
    7175            struct ToDwarfRegisterMap;
    7276            struct FromDwarfRegisterMap;
  • src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp

    diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp
    index c6aa3ca..d8942ff 100644
    a b  
    4141#include "FunctionID.h"
    4242#include "FunctionInstance.h"
    4343#include "GlobalTypeLookup.h"
     44#include "Image.h"
     45#include "ImageDebugInfo.h"
    4446#include "InstructionInfo.h"
    4547#include "LocatableFile.h"
    4648#include "Register.h"
     
    5658#include "TypeLookupConstraints.h"
    5759#include "UnsupportedLanguage.h"
    5860#include "Variable.h"
     61#include "ValueLocation.h"
    5962
    6063
    6164namespace {
    DwarfImageDebugInfo::CreateFrame(Image* image,  
    672675        // call to see if we need to potentially retrieve a return value
    673676        // as well
    674677        if (instructionPointer > functionInstance->Address() - fRelocationDelta) {
    675             _CreateReturnValue(functionInstance, function, frame,
     678            _CreateReturnValue(functionInstance, image, function, frame,
    676679                *stackFrameDebugInfo, instructionPointer);
    677680        }
    678681    }
    DwarfImageDebugInfo::_CreateLocalVariables(CompilationUnit* unit,  
    10851088
    10861089status_t
    10871090DwarfImageDebugInfo::_CreateReturnValue(FunctionInstance* functionInstance,
    1088     DwarfFunctionDebugInfo* function, StackFrame* frame,
     1091    Image* image, DwarfFunctionDebugInfo* function, StackFrame* frame,
    10891092    DwarfStackFrameDebugInfo& factory, target_addr_t instructionPointer)
    10901093{
    10911094    DisassembledCode* sourceCode = NULL;
    DwarfImageDebugInfo::_CreateReturnValue(FunctionInstance* functionInstance,  
    11111114        previousStatementAddress);
    11121115    if (statement == NULL)
    11131116        return B_BAD_VALUE;
     1117    previousStatementAddress = statement->CoveringAddressRange().Start() - 1;
     1118    statement = sourceCode->StatementAtAddress(
     1119        previousStatementAddress);
     1120    if (statement == NULL)
     1121        return B_BAD_VALUE;
    11141122
    11151123    TargetAddressRange range = statement->CoveringAddressRange();
    11161124    InstructionInfo info;
    11171125    if (fArchitecture->GetInstructionInfo(range.Start(), info) == B_OK
    11181126        && info.Type() == INSTRUCTION_TYPE_SUBROUTINE_CALL) {
    1119         // TODO: determine where the previous instruction actually jumps to,
    1120         // retrieve that function (could potentially be in another image),
    1121         // and use its return type to retrieve the return value (will need
    1122         // architecture support since function return value passing convention
    1123         // is arch-dependent).
     1127        target_addr_t targetAddress = info.TargetAddress();
     1128        if (targetAddress == 0)
     1129            return B_BAD_VALUE;
     1130
     1131        if (image->ContainsAddress(targetAddress)) {
     1132            FunctionInstance* targetFunction;
     1133            if (targetAddress >= fPLTSectionStart && targetAddress < fPLTSectionEnd) {
     1134                // TODO: resolve actual target address in the PIC case
     1135                // and adjust targetAddress accordingly
     1136            }
     1137            ImageDebugInfo* imageInfo = image->GetImageDebugInfo();
     1138            targetFunction = imageInfo->FunctionAtAddress(targetAddress);
     1139            if (targetFunction != NULL) {
     1140                DwarfFunctionDebugInfo* targetInfo =
     1141                    dynamic_cast<DwarfFunctionDebugInfo*>(
     1142                        targetFunction->GetFunctionDebugInfo());
     1143                if (targetInfo != NULL) {
     1144                    DIESubprogram* subProgram = targetInfo->SubprogramEntry();
     1145                    DIEType* returnType = subProgram->ReturnType();
     1146                    if (returnType == NULL) {
     1147                        // function doesn't return a value, we're done.
     1148                        return B_OK;
     1149                    }
     1150
     1151                    ValueLocation* location;
     1152                    result = fArchitecture->GetReturnAddressLocation(frame,
     1153                        returnType->ByteSize()->constant, location);
     1154                    if (result != B_OK)
     1155                        return result;
     1156                    BReference<ValueLocation> locationReference(location,
     1157                        true);
     1158                    Variable* variable = NULL;
     1159                    BReference<FunctionID> idReference(
     1160                        targetFunction->GetFunctionID(), true);
     1161                    result = factory.CreateReturnValue(idReference,
     1162                        returnType, location, variable);
     1163                    if (result != B_OK)
     1164                        return result;
     1165                    BReference<Variable> variableReference(variable, true);
     1166                    if (!frame->AddLocalVariable(variable))
     1167                        return B_NO_MEMORY;
     1168                }
     1169            }
     1170        }
    11241171    }
    11251172
    11261173    return B_OK;
  • src/apps/debugger/debug_info/DwarfImageDebugInfo.h

    diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h
    index c03370f..4c9b0c1 100644
    a b private:  
    104104                                    const EntryListWrapper& blockEntries);
    105105
    106106            status_t            _CreateReturnValue(FunctionInstance* instance,
     107                                    Image* image,
    107108                                    DwarfFunctionDebugInfo* info,
    108109                                    StackFrame* frame,
    109110                                    DwarfStackFrameDebugInfo& factory,
  • src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.cpp

    diff --git a/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.cpp
    index 99853ae..42cef63 100644
    a b  
    11/*
     2 * Copyright 2012, Rene Gollent, rene@gollent.com.
    23 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
    34 * Distributed under the terms of the MIT License.
    45 */
     
    2324#include "LocalVariableID.h"
    2425#include "Register.h"
    2526#include "RegisterMap.h"
     27#include "ReturnValueID.h"
    2628#include "StringUtils.h"
    2729#include "Tracing.h"
    2830#include "ValueLocation.h"
    private:  
    117119};
    118120
    119121
     122// #pragma mark - DwarfReturnValueID
     123
     124
     125struct DwarfStackFrameDebugInfo::DwarfReturnValueID
     126    : public ReturnValueID {
     127
     128    DwarfReturnValueID(FunctionID* functionID)
     129        :
     130        fFunctionID(functionID),
     131        fName("(returned)")
     132    {
     133        fFunctionID->AcquireReference();
     134    }
     135
     136    virtual ~DwarfReturnValueID()
     137    {
     138        fFunctionID->ReleaseReference();
     139    }
     140
     141    virtual bool operator==(const ObjectID& other) const
     142    {
     143        const DwarfReturnValueID* returnValueID
     144            = dynamic_cast<const DwarfReturnValueID*>(&other);
     145        return returnValueID != NULL
     146            && *fFunctionID == *returnValueID->fFunctionID
     147            && fName == returnValueID->fName;
     148    }
     149
     150protected:
     151    virtual uint32 ComputeHashValue() const
     152    {
     153        uint32 hash = fFunctionID->HashValue();
     154        return hash * 25 + StringUtils::HashValue(fName);
     155    }
     156
     157private:
     158    FunctionID*     fFunctionID;
     159    const BString   fName;
     160};
     161
     162
    120163// #pragma mark - DwarfStackFrameDebugInfo
    121164
    122165
    DwarfStackFrameDebugInfo::CreateLocalVariable(FunctionID* functionID,  
    235278
    236279
    237280status_t
     281DwarfStackFrameDebugInfo::CreateReturnValue(FunctionID* functionID,
     282    DIEType* returnType, ValueLocation* location, Variable*& _variable)
     283{
     284    if (returnType == NULL)
     285        return B_BAD_VALUE;
     286
     287    // create the type
     288    DwarfType* type;
     289    status_t error = fTypeFactory->CreateType(returnType, type);
     290    if (error != B_OK)
     291        return error;
     292    BReference<DwarfType> typeReference(type, true);
     293
     294    DwarfReturnValueID* id = new(std::nothrow) DwarfReturnValueID(
     295        functionID);
     296    if (id == NULL)
     297        return B_NO_MEMORY;
     298
     299    BString name;
     300    name.SetToFormat("%s returned", functionID->FunctionName().String());
     301
     302    Variable* variable = new(std::nothrow) Variable(id, name,
     303        type, location);
     304    if (variable == NULL)
     305        return B_NO_MEMORY;
     306
     307    _variable = variable;
     308
     309    return B_OK;
     310}
     311
     312
     313status_t
    238314DwarfStackFrameDebugInfo::_CreateVariable(ObjectID* id, const BString& name,
    239315    DIEType* typeEntry, LocationDescription* locationDescription,
    240316    Variable*& _variable)
  • src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h

    diff --git a/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h b/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h
    index e55d0d2..3e69130 100644
    a b  
    11/*
     2 * Copyright 2012, Rene Gollent, rene@gollent.com.
    23 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
    34 * Distributed under the terms of the MIT License.
    45 */
    public:  
    5657                                    DIEVariable* variableEntry,
    5758                                    Variable*& _variable);
    5859                                    // returns reference
     60            status_t            CreateReturnValue(FunctionID* functionID,
     61                                    DIEType* returnType,
     62                                    ValueLocation* location,
     63                                    Variable*& _variable);
     64                                    // returns reference
    5965
    6066private:
    6167            struct DwarfFunctionParameterID;
    6268            struct DwarfLocalVariableID;
     69            struct DwarfReturnValueID;
    6370
    6471private:
    6572            status_t            _CreateVariable(ObjectID* id,