Ticket #8877: debugger_x86-64.patch

File debugger_x86-64.patch, 32.5 KB (added by anevilyak, 12 years ago)
  • src/apps/debugger/Jamfile

    diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile
    index fca0a83..fd0d6fb 100644
    a b UsePrivateSystemHeaders ;  
    99
    1010SEARCH_SOURCE += [ FDirName $(SUBDIR) arch ] ;
    1111SEARCH_SOURCE += [ FDirName $(SUBDIR) arch x86 ] ;
     12SEARCH_SOURCE += [ FDirName $(SUBDIR) arch x86_64 ] ;
    1213SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_info ] ;
    1314SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface ] ;
    1415SEARCH_SOURCE += [ FDirName $(SUBDIR) elf ] ;
    Application Debugger :  
    7475    ArchitectureX86.cpp
    7576    CpuStateX86.cpp
    7677
     78    # arch/x86_64
     79    ArchitectureX86_64.cpp
     80    CpuStateX86_64.cpp
     81
    7782    # debug_info
    7883    BasicFunctionDebugInfo.cpp
    7984    DebuggerImageDebugInfo.cpp
  • new file src/apps/debugger/arch/x86_64/ArchitectureX86_64.cpp

    diff --git a/src/apps/debugger/arch/x86_64/ArchitectureX86_64.cpp b/src/apps/debugger/arch/x86_64/ArchitectureX86_64.cpp
    new file mode 100644
    index 0000000..60f5ac4
    - +  
     1/*
     2 * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
     3 * Copyright 2011-2012, Rene Gollent, rene@gollent.com.
     4 * Distributed under the terms of the MIT License.
     5 */
     6
     7
     8#include "ArchitectureX86_64.h"
     9
     10#include <new>
     11
     12#include <String.h>
     13
     14#include <AutoDeleter.h>
     15
     16#include "CfaContext.h"
     17#include "CpuStateX86_64.h"
     18#include "DisassembledCode.h"
     19#include "FunctionDebugInfo.h"
     20#include "InstructionInfo.h"
     21#include "NoOpStackFrameDebugInfo.h"
     22#include "RegisterMap.h"
     23#include "StackFrame.h"
     24#include "Statement.h"
     25#include "TeamMemory.h"
     26#include "X86AssemblyLanguage.h"
     27
     28#include "disasm/DisassemblerX86.h"
     29
     30
     31// source: http://www.x86-64.org/documentation/abi.pdf
     32static const int32 kFromDwarfRegisters[] = {
     33    X86_64_REGISTER_RAX,
     34    X86_64_REGISTER_RDX,
     35    X86_64_REGISTER_RCX,
     36    X86_64_REGISTER_RBX,
     37    X86_64_REGISTER_RSI,
     38    X86_64_REGISTER_RDI,
     39    X86_64_REGISTER_RBP,
     40    X86_64_REGISTER_RSP,
     41    X86_64_REGISTER_R8,
     42    X86_64_REGISTER_R9,
     43    X86_64_REGISTER_R10,
     44    X86_64_REGISTER_R11,
     45    X86_64_REGISTER_R12,
     46    X86_64_REGISTER_R13,
     47    X86_64_REGISTER_R14,
     48    X86_64_REGISTER_R15,
     49    -1, // RA
     50    -1, -1, -1, -1, -1, -1, -1, -1, // xmm0-xmm7
     51    -1, -1, -1, -1, -1, -1, -1, -1, // xmm8-xmm15
     52    -1, -1, -1, -1, -1, -1, -1, -1, // st0-st7
     53    -1, -1, -1, -1, -1, -1, -1, -1, // mm0-mm7
     54    -1, // rflags
     55    -1, // es
     56    X86_64_REGISTER_CS,
     57    -1, // ss
     58    -1, // ds
     59    X86_64_REGISTER_FS,
     60    X86_64_REGISTER_GS,
     61
     62};
     63static const int32 kFromDwarfRegisterCount = sizeof(kFromDwarfRegisters) / 4;
     64
     65
     66// #pragma mark - ToDwarfRegisterMap
     67
     68
     69struct ArchitectureX86_64::ToDwarfRegisterMap : RegisterMap {
     70    ToDwarfRegisterMap()
     71    {
     72        // init the index array from the reverse map
     73        memset(fIndices, -1, sizeof(fIndices));
     74        for (int32 i = 0; i < kFromDwarfRegisterCount; i++) {
     75            if (kFromDwarfRegisters[i] >= 0)
     76                fIndices[kFromDwarfRegisters[i]] = i;
     77        }
     78    }
     79
     80    virtual int32 CountRegisters() const
     81    {
     82        return X86_64_REGISTER_COUNT;
     83    }
     84
     85    virtual int32 MapRegisterIndex(int32 index) const
     86    {
     87        return index >= 0 && index < X86_64_REGISTER_COUNT ? fIndices[index] : -1;
     88    }
     89
     90private:
     91    int32   fIndices[X86_64_REGISTER_COUNT];
     92};
     93
     94
     95// #pragma mark - FromDwarfRegisterMap
     96
     97
     98struct ArchitectureX86_64::FromDwarfRegisterMap : RegisterMap {
     99    virtual int32 CountRegisters() const
     100    {
     101        return kFromDwarfRegisterCount;
     102    }
     103
     104    virtual int32 MapRegisterIndex(int32 index) const
     105    {
     106        return index >= 0 && index < kFromDwarfRegisterCount
     107            ? kFromDwarfRegisters[index] : -1;
     108    }
     109};
     110
     111
     112// #pragma mark - ArchitectureX86_64
     113
     114
     115ArchitectureX86_64::ArchitectureX86_64(TeamMemory* teamMemory)
     116    :
     117    Architecture(teamMemory, 4, false),
     118    fAssemblyLanguage(NULL),
     119    fToDwarfRegisterMap(NULL),
     120    fFromDwarfRegisterMap(NULL)
     121{
     122}
     123
     124
     125ArchitectureX86_64::~ArchitectureX86_64()
     126{
     127    if (fToDwarfRegisterMap != NULL)
     128        fToDwarfRegisterMap->ReleaseReference();
     129    if (fFromDwarfRegisterMap != NULL)
     130        fFromDwarfRegisterMap->ReleaseReference();
     131    if (fAssemblyLanguage != NULL)
     132        fAssemblyLanguage->ReleaseReference();
     133}
     134
     135
     136status_t
     137ArchitectureX86_64::Init()
     138{
     139    fAssemblyLanguage = new(std::nothrow) X86AssemblyLanguage;
     140    if (fAssemblyLanguage == NULL)
     141        return B_NO_MEMORY;
     142
     143    try {
     144        _AddIntegerRegister(X86_64_REGISTER_RIP, "rip", B_UINT64_TYPE,
     145            REGISTER_TYPE_INSTRUCTION_POINTER, false);
     146        _AddIntegerRegister(X86_64_REGISTER_RSP, "rsp", B_UINT64_TYPE,
     147            REGISTER_TYPE_STACK_POINTER, true);
     148        _AddIntegerRegister(X86_64_REGISTER_RBP, "rbp", B_UINT64_TYPE,
     149            REGISTER_TYPE_GENERAL_PURPOSE, true);
     150
     151        _AddIntegerRegister(X86_64_REGISTER_RAX, "rax", B_UINT64_TYPE,
     152            REGISTER_TYPE_GENERAL_PURPOSE, false);
     153        _AddIntegerRegister(X86_64_REGISTER_RBX, "rbx", B_UINT64_TYPE,
     154            REGISTER_TYPE_GENERAL_PURPOSE, true);
     155        _AddIntegerRegister(X86_64_REGISTER_RCX, "rcx", B_UINT64_TYPE,
     156            REGISTER_TYPE_GENERAL_PURPOSE, false);
     157        _AddIntegerRegister(X86_64_REGISTER_RDX, "rdx", B_UINT64_TYPE,
     158            REGISTER_TYPE_GENERAL_PURPOSE, false);
     159
     160        _AddIntegerRegister(X86_64_REGISTER_RSI, "rsi", B_UINT64_TYPE,
     161            REGISTER_TYPE_GENERAL_PURPOSE, true);
     162        _AddIntegerRegister(X86_64_REGISTER_RDI, "rdi", B_UINT64_TYPE,
     163            REGISTER_TYPE_GENERAL_PURPOSE, true);
     164
     165        _AddIntegerRegister(X86_64_REGISTER_R8, "r8", B_UINT64_TYPE,
     166            REGISTER_TYPE_GENERAL_PURPOSE, true);
     167        _AddIntegerRegister(X86_64_REGISTER_R9, "r9", B_UINT64_TYPE,
     168            REGISTER_TYPE_GENERAL_PURPOSE, true);
     169        _AddIntegerRegister(X86_64_REGISTER_R10, "r10", B_UINT64_TYPE,
     170            REGISTER_TYPE_GENERAL_PURPOSE, true);
     171        _AddIntegerRegister(X86_64_REGISTER_R11, "r11", B_UINT64_TYPE,
     172            REGISTER_TYPE_GENERAL_PURPOSE, true);
     173        _AddIntegerRegister(X86_64_REGISTER_R12, "r12", B_UINT64_TYPE,
     174            REGISTER_TYPE_GENERAL_PURPOSE, true);
     175        _AddIntegerRegister(X86_64_REGISTER_R13, "r13", B_UINT64_TYPE,
     176            REGISTER_TYPE_GENERAL_PURPOSE, true);
     177        _AddIntegerRegister(X86_64_REGISTER_R14, "r14", B_UINT64_TYPE,
     178            REGISTER_TYPE_GENERAL_PURPOSE, true);
     179        _AddIntegerRegister(X86_64_REGISTER_R15, "r15", B_UINT64_TYPE,
     180            REGISTER_TYPE_GENERAL_PURPOSE, true);
     181
     182        _AddIntegerRegister(X86_64_REGISTER_CS, "cs", B_UINT16_TYPE,
     183            REGISTER_TYPE_SPECIAL_PURPOSE, true);
     184        _AddIntegerRegister(X86_64_REGISTER_FS, "fs", B_UINT16_TYPE,
     185            REGISTER_TYPE_SPECIAL_PURPOSE, true);
     186        _AddIntegerRegister(X86_64_REGISTER_GS, "gs", B_UINT16_TYPE,
     187            REGISTER_TYPE_SPECIAL_PURPOSE, true);
     188
     189    } catch (std::bad_alloc) {
     190        return B_NO_MEMORY;
     191    }
     192
     193    fToDwarfRegisterMap = new(std::nothrow) ToDwarfRegisterMap;
     194    fFromDwarfRegisterMap = new(std::nothrow) FromDwarfRegisterMap;
     195
     196    if (fToDwarfRegisterMap == NULL || fFromDwarfRegisterMap == NULL)
     197        return B_NO_MEMORY;
     198
     199    return B_OK;
     200}
     201
     202
     203int32
     204ArchitectureX86_64::StackGrowthDirection() const
     205{
     206    return STACK_GROWTH_DIRECTION_NEGATIVE;
     207}
     208
     209
     210int32
     211ArchitectureX86_64::CountRegisters() const
     212{
     213    return fRegisters.Count();
     214}
     215
     216
     217const Register*
     218ArchitectureX86_64::Registers() const
     219{
     220    return fRegisters.Elements();
     221}
     222
     223
     224status_t
     225ArchitectureX86_64::InitRegisterRules(CfaContext& context) const
     226{
     227    status_t error = Architecture::InitRegisterRules(context);
     228    if (error != B_OK)
     229        return error;
     230
     231    // set up rule for RIP register
     232    context.RegisterRule(fToDwarfRegisterMap->MapRegisterIndex(
     233        X86_64_REGISTER_RIP))->SetToLocationOffset(-4);
     234
     235    return B_OK;
     236}
     237
     238status_t
     239ArchitectureX86_64::GetDwarfRegisterMaps(RegisterMap** _toDwarf,
     240    RegisterMap** _fromDwarf) const
     241{
     242    if (_toDwarf != NULL) {
     243        *_toDwarf = fToDwarfRegisterMap;
     244        fToDwarfRegisterMap->AcquireReference();
     245    }
     246
     247    if (_fromDwarf != NULL) {
     248        *_fromDwarf = fFromDwarfRegisterMap;
     249        fFromDwarfRegisterMap->AcquireReference();
     250    }
     251
     252    return B_OK;
     253}
     254
     255
     256status_t
     257ArchitectureX86_64::CreateCpuState(CpuState*& _state)
     258{
     259    CpuStateX86_64* state = new(std::nothrow) CpuStateX86_64;
     260    if (state == NULL)
     261        return B_NO_MEMORY;
     262
     263    _state = state;
     264    return B_OK;
     265}
     266
     267
     268status_t
     269ArchitectureX86_64::CreateCpuState(const void* cpuStateData, size_t size,
     270    CpuState*& _state)
     271{
     272    if (size != sizeof(x86_debug_cpu_state))
     273        return B_BAD_VALUE;
     274
     275    CpuStateX86_64* state = new(std::nothrow) CpuStateX86_64(
     276        *(const x86_64_debug_cpu_state*)cpuStateData);
     277    if (state == NULL)
     278        return B_NO_MEMORY;
     279
     280    _state = state;
     281    return B_OK;
     282}
     283
     284
     285status_t
     286ArchitectureX86_64::CreateStackFrame(Image* image, FunctionDebugInfo* function,
     287    CpuState* _cpuState, bool isTopFrame, StackFrame*& _frame,
     288    CpuState*& _previousCpuState)
     289{
     290    CpuStateX86_64* cpuState = dynamic_cast<CpuStateX86_64*>(_cpuState);
     291
     292    uint64 framePointer = cpuState->IntRegisterValue(X86_64_REGISTER_RBP);
     293    uint64 eip = cpuState->IntRegisterValue(X86_64_REGISTER_RIP);
     294
     295    bool readStandardFrame = true;
     296    uint64 previousFramePointer = 0;
     297    uint64 returnAddress = 0;
     298
     299    // check for syscall frames
     300    stack_frame_type frameType;
     301    bool hasPrologue = false;
     302    if (isTopFrame && cpuState->InterruptVector() == 99) {
     303        // The thread is performing a syscall. So this frame is not really the
     304        // top-most frame and we need to adjust the eip.
     305        frameType = STACK_FRAME_TYPE_SYSCALL;
     306        eip -= 2;
     307            // int 99, sysenter, and syscall all are 2 byte instructions
     308
     309        // The syscall stubs are frameless, the return address is on top of the
     310        // stack.
     311        uint64 rsp = cpuState->IntRegisterValue(X86_64_REGISTER_RSP);
     312        uint64 address;
     313        if (fTeamMemory->ReadMemory(rsp, &address, 8) == 8) {
     314            returnAddress = address;
     315            previousFramePointer = framePointer;
     316            framePointer = 0;
     317            readStandardFrame = false;
     318        }
     319    } else {
     320        hasPrologue = _HasFunctionPrologue(function);
     321        if (hasPrologue)
     322            frameType = STACK_FRAME_TYPE_STANDARD;
     323        else
     324            frameType = STACK_FRAME_TYPE_FRAMELESS;
     325        // TODO: Handling for frameless functions. It's not trivial to find the
     326        // return address on the stack, though.
     327
     328        // If the function is not frameless and we're at the top frame we need
     329        // to check whether the prologue has not been executed (completely) or
     330        // we're already after the epilogue.
     331        if (hasPrologue && isTopFrame) {
     332            uint32 stack = 0;
     333            if (eip < function->Address() + 3) {
     334                // The prologue has not been executed yet, i.e. there's no
     335                // stack frame yet. Get the return address from the stack.
     336                stack = cpuState->IntRegisterValue(X86_64_REGISTER_RSP);
     337                if (eip > function->Address()) {
     338                    // The "push %ebp" has already been executed.
     339                    stack += 8;
     340                }
     341            } else {
     342                // Not in the function prologue, but maybe after the epilogue.
     343                // The epilogue is a single "pop %ebp", so we check whether the
     344                // current instruction is already a "ret".
     345                uint8 code[1];
     346                if (fTeamMemory->ReadMemory(eip, &code, 1) == 1
     347                    && code[0] == 0xc3) {
     348                    stack = cpuState->IntRegisterValue(X86_64_REGISTER_RSP);
     349                }
     350            }
     351
     352            if (stack != 0) {
     353                uint64 address;
     354                if (fTeamMemory->ReadMemory(stack, &address, 8) == 8) {
     355                    returnAddress = address;
     356                    previousFramePointer = framePointer;
     357                    framePointer = 0;
     358                    readStandardFrame = false;
     359                    frameType = STACK_FRAME_TYPE_FRAMELESS;
     360                }
     361            }
     362        }
     363    }
     364
     365    // create the stack frame
     366    StackFrameDebugInfo* stackFrameDebugInfo
     367        = new(std::nothrow) NoOpStackFrameDebugInfo;
     368    if (stackFrameDebugInfo == NULL)
     369        return B_NO_MEMORY;
     370    BReference<StackFrameDebugInfo> stackFrameDebugInfoReference(
     371        stackFrameDebugInfo, true);
     372
     373    StackFrame* frame = new(std::nothrow) StackFrame(frameType, cpuState,
     374        framePointer, eip, stackFrameDebugInfo);
     375    if (frame == NULL)
     376        return B_NO_MEMORY;
     377    BReference<StackFrame> frameReference(frame, true);
     378
     379    status_t error = frame->Init();
     380    if (error != B_OK)
     381        return error;
     382
     383    // read the previous frame and return address, if this is a standard frame
     384    if (readStandardFrame) {
     385        uint64 frameData[2];
     386        if (framePointer != 0
     387            && fTeamMemory->ReadMemory(framePointer, frameData,
     388                    sizeof(frameData))
     389                == sizeof(frameData)) {
     390            previousFramePointer = frameData[0];
     391            returnAddress = frameData[1];
     392        }
     393    }
     394
     395    // create the CPU state, if we have any info
     396    CpuStateX86_64* previousCpuState = NULL;
     397    if (returnAddress != 0) {
     398        // prepare the previous CPU state
     399        previousCpuState = new(std::nothrow) CpuStateX86_64;
     400        if (previousCpuState == NULL)
     401            return B_NO_MEMORY;
     402
     403        previousCpuState->SetIntRegister(X86_64_REGISTER_RBP,
     404            previousFramePointer);
     405        previousCpuState->SetIntRegister(X86_64_REGISTER_RIP, returnAddress);
     406        frame->SetPreviousCpuState(previousCpuState);
     407    }
     408
     409    frame->SetReturnAddress(returnAddress);
     410
     411    _frame = frameReference.Detach();
     412    _previousCpuState = previousCpuState;
     413    return B_OK;
     414}
     415
     416
     417void
     418ArchitectureX86_64::UpdateStackFrameCpuState(const StackFrame* frame,
     419    Image* previousImage, FunctionDebugInfo* previousFunction,
     420    CpuState* previousCpuState)
     421{
     422    // This is not a top frame, so we want to offset eip to the previous
     423    // (calling) instruction.
     424    CpuStateX86_64* cpuState = dynamic_cast<CpuStateX86_64*>(previousCpuState);
     425
     426    // get rip
     427    uint64 rip = cpuState->IntRegisterValue(X86_64_REGISTER_RIP);
     428    if (previousFunction == NULL || rip <= previousFunction->Address())
     429        return;
     430    target_addr_t functionAddress = previousFunction->Address();
     431
     432    // allocate a buffer for the function code to disassemble
     433    size_t bufferSize = rip - functionAddress;
     434    void* buffer = malloc(bufferSize);
     435    if (buffer == NULL)
     436        return;
     437    MemoryDeleter bufferDeleter(buffer);
     438
     439    // read the code
     440    ssize_t bytesRead = fTeamMemory->ReadMemory(functionAddress, buffer,
     441        bufferSize);
     442    if (bytesRead != (ssize_t)bufferSize)
     443        return;
     444
     445    // disassemble to get the previous instruction
     446    DisassemblerX86 disassembler;
     447    target_addr_t instructionAddress;
     448    target_size_t instructionSize;
     449    if (disassembler.Init(functionAddress, buffer, bufferSize) == B_OK
     450        && disassembler.GetPreviousInstruction(rip, instructionAddress,
     451            instructionSize) == B_OK) {
     452        rip -= instructionSize;
     453        cpuState->SetIntRegister(X86_64_REGISTER_RIP, rip);
     454    }
     455}
     456
     457
     458status_t
     459ArchitectureX86_64::ReadValueFromMemory(target_addr_t address, uint32 valueType,
     460    BVariant& _value) const
     461{
     462    uint8 buffer[64];
     463    size_t size = BVariant::SizeOfType(valueType);
     464    if (size == 0 || size > sizeof(buffer))
     465        return B_BAD_VALUE;
     466
     467    ssize_t bytesRead = fTeamMemory->ReadMemory(address, buffer, size);
     468    if (bytesRead < 0)
     469        return bytesRead;
     470    if ((size_t)bytesRead != size)
     471        return B_ERROR;
     472
     473    // TODO: We need to swap endianess, if the host is big endian!
     474
     475    switch (valueType) {
     476        case B_INT8_TYPE:
     477            _value.SetTo(*(int8*)buffer);
     478            return B_OK;
     479        case B_UINT8_TYPE:
     480            _value.SetTo(*(uint8*)buffer);
     481            return B_OK;
     482        case B_INT16_TYPE:
     483            _value.SetTo(*(int16*)buffer);
     484            return B_OK;
     485        case B_UINT16_TYPE:
     486            _value.SetTo(*(uint16*)buffer);
     487            return B_OK;
     488        case B_INT32_TYPE:
     489            _value.SetTo(*(int32*)buffer);
     490            return B_OK;
     491        case B_UINT32_TYPE:
     492            _value.SetTo(*(uint32*)buffer);
     493            return B_OK;
     494        case B_INT64_TYPE:
     495            _value.SetTo(*(int64*)buffer);
     496            return B_OK;
     497        case B_UINT64_TYPE:
     498            _value.SetTo(*(uint64*)buffer);
     499            return B_OK;
     500        case B_FLOAT_TYPE:
     501            _value.SetTo(*(float*)buffer);
     502                // TODO: float on the host might work differently!
     503            return B_OK;
     504        case B_DOUBLE_TYPE:
     505            _value.SetTo(*(double*)buffer);
     506                // TODO: double on the host might work differently!
     507            return B_OK;
     508        default:
     509            return B_BAD_VALUE;
     510    }
     511}
     512
     513
     514status_t
     515ArchitectureX86_64::ReadValueFromMemory(target_addr_t addressSpace,
     516    target_addr_t address, uint32 valueType, BVariant& _value) const
     517{
     518    // n/a on this architecture
     519    return B_BAD_VALUE;
     520}
     521
     522
     523status_t
     524ArchitectureX86_64::DisassembleCode(FunctionDebugInfo* function,
     525    const void* buffer, size_t bufferSize, DisassembledCode*& _sourceCode)
     526{
     527    DisassembledCode* source = new(std::nothrow) DisassembledCode(
     528        fAssemblyLanguage);
     529    if (source == NULL)
     530        return B_NO_MEMORY;
     531    BReference<DisassembledCode> sourceReference(source, true);
     532
     533    // init disassembler
     534    DisassemblerX86 disassembler;
     535    status_t error = disassembler.Init(function->Address(), buffer, bufferSize);
     536    if (error != B_OK)
     537        return error;
     538
     539    // add a function name line
     540    BString functionName(function->PrettyName());
     541    if (!source->AddCommentLine((functionName << ':').String()))
     542        return B_NO_MEMORY;
     543
     544    // disassemble the instructions
     545    BString line;
     546    target_addr_t instructionAddress;
     547    target_size_t instructionSize;
     548    bool breakpointAllowed;
     549    while (disassembler.GetNextInstruction(line, instructionAddress,
     550                instructionSize, breakpointAllowed) == B_OK) {
     551// TODO: Respect breakpointAllowed!
     552        if (!source->AddInstructionLine(line, instructionAddress,
     553                instructionSize)) {
     554            return B_NO_MEMORY;
     555        }
     556    }
     557
     558    _sourceCode = sourceReference.Detach();
     559    return B_OK;
     560}
     561
     562
     563status_t
     564ArchitectureX86_64::GetStatement(FunctionDebugInfo* function,
     565    target_addr_t address, Statement*& _statement)
     566{
     567// TODO: This is not architecture dependent anymore!
     568    // get the instruction info
     569    InstructionInfo info;
     570    status_t error = GetInstructionInfo(address, info);
     571    if (error != B_OK)
     572        return error;
     573
     574    // create a statement
     575    ContiguousStatement* statement = new(std::nothrow) ContiguousStatement(
     576        SourceLocation(-1), TargetAddressRange(info.Address(), info.Size()));
     577    if (statement == NULL)
     578        return B_NO_MEMORY;
     579
     580    _statement = statement;
     581    return B_OK;
     582}
     583
     584
     585status_t
     586ArchitectureX86_64::GetInstructionInfo(target_addr_t address,
     587    InstructionInfo& _info)
     588{
     589    // read the code
     590    uint8 buffer[16];
     591        // TODO: What's the maximum instruction size?
     592    ssize_t bytesRead = fTeamMemory->ReadMemory(address, buffer,
     593        sizeof(buffer));
     594    if (bytesRead < 0)
     595        return bytesRead;
     596
     597    // init disassembler
     598    DisassemblerX86 disassembler;
     599    status_t error = disassembler.Init(address, buffer, bytesRead);
     600    if (error != B_OK)
     601        return error;
     602
     603    // disassemble the instruction
     604    BString line;
     605    target_addr_t instructionAddress;
     606    target_size_t instructionSize;
     607    bool breakpointAllowed;
     608    error = disassembler.GetNextInstruction(line, instructionAddress,
     609        instructionSize, breakpointAllowed);
     610    if (error != B_OK)
     611        return error;
     612
     613    // TODO: any changes needed for x86-64?
     614    instruction_type instructionType = INSTRUCTION_TYPE_OTHER;
     615    if (buffer[0] == 0xff && (buffer[1] & 0x34) == 0x10) {
     616        // absolute call with r/m32
     617        instructionType = INSTRUCTION_TYPE_SUBROUTINE_CALL;
     618    } else if (buffer[0] == 0xe8 && instructionSize == 5) {
     619        // relative call with rel32 -- don't categorize the call with 0 as
     620        // subroutine call, since it is only used to get the address of the GOT
     621        if (buffer[1] != 0 || buffer[2] != 0 || buffer[3] != 0
     622            || buffer[4] != 0) {
     623            instructionType = INSTRUCTION_TYPE_SUBROUTINE_CALL;
     624        }
     625    }
     626
     627    if (!_info.SetTo(instructionAddress, instructionSize, instructionType,
     628            breakpointAllowed, line)) {
     629        return B_NO_MEMORY;
     630    }
     631
     632    return B_OK;
     633}
     634
     635
     636void
     637ArchitectureX86_64::_AddRegister(int32 index, const char* name,
     638    uint32 bitSize, uint32 valueType, register_type type, bool calleePreserved)
     639{
     640    if (!fRegisters.Add(Register(index, name, bitSize, valueType, type,
     641            calleePreserved))) {
     642        throw std::bad_alloc();
     643    }
     644}
     645
     646
     647void
     648ArchitectureX86_64::_AddIntegerRegister(int32 index, const char* name,
     649    uint32 valueType, register_type type, bool calleePreserved)
     650{
     651    _AddRegister(index, name, 8 * BVariant::SizeOfType(valueType), valueType,
     652        type, calleePreserved);
     653}
     654
     655
     656bool
     657ArchitectureX86_64::_HasFunctionPrologue(FunctionDebugInfo* function) const
     658{
     659    // TODO: rework for x86-64
     660    if (function == NULL)
     661        return false;
     662
     663    // check whether the function has the typical prologue
     664    if (function->Size() < 3)
     665        return false;
     666
     667    uint8 buffer[3];
     668    if (fTeamMemory->ReadMemory(function->Address(), buffer, 3) != 3)
     669        return false;
     670
     671    return buffer[0] == 0x55 && buffer[1] == 0x89 && buffer[2] == 0xe5;
     672}
  • new file src/apps/debugger/arch/x86_64/ArchitectureX86_64.h

    diff --git a/src/apps/debugger/arch/x86_64/ArchitectureX86_64.h b/src/apps/debugger/arch/x86_64/ArchitectureX86_64.h
    new file mode 100644
    index 0000000..478e71a
    - +  
     1/*
     2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
     3 * Copyright 2011-2012, Rene Gollent, rene@gollent.com.
     4 * Distributed under the terms of the MIT License.
     5 */
     6#ifndef ARCHITECTURE_X86_64_H
     7#define ARCHITECTURE_X86_64_H
     8
     9
     10#include <Array.h>
     11
     12#include "Architecture.h"
     13#include "Register.h"
     14
     15
     16class SourceLanguage;
     17
     18
     19class ArchitectureX86_64 : public Architecture {
     20public:
     21                                ArchitectureX86_64(TeamMemory* teamMemory);
     22    virtual                     ~ArchitectureX86_64();
     23
     24    virtual status_t            Init();
     25
     26    virtual int32               StackGrowthDirection() const;
     27
     28    virtual int32               CountRegisters() const;
     29    virtual const Register*     Registers() const;
     30    virtual status_t            InitRegisterRules(CfaContext& context) const;
     31
     32    virtual status_t            GetDwarfRegisterMaps(RegisterMap** _toDwarf,
     33                                    RegisterMap** _fromDwarf) const;
     34
     35    virtual status_t            CreateCpuState(CpuState*& _state);
     36    virtual status_t            CreateCpuState(const void* cpuStateData,
     37                                    size_t size, CpuState*& _state);
     38    virtual status_t            CreateStackFrame(Image* image,
     39                                    FunctionDebugInfo* function,
     40                                    CpuState* cpuState, bool isTopFrame,
     41                                    StackFrame*& _previousFrame,
     42                                    CpuState*& _previousCpuState);
     43    virtual void                UpdateStackFrameCpuState(
     44                                    const StackFrame* frame,
     45                                    Image* previousImage,
     46                                    FunctionDebugInfo* previousFunction,
     47                                    CpuState* previousCpuState);
     48
     49    virtual status_t            ReadValueFromMemory(target_addr_t address,
     50                                    uint32 valueType, BVariant& _value) const;
     51    virtual status_t            ReadValueFromMemory(target_addr_t addressSpace,
     52                                    target_addr_t address, uint32 valueType,
     53                                    BVariant& _value) const;
     54
     55    virtual status_t            DisassembleCode(FunctionDebugInfo* function,
     56                                    const void* buffer, size_t bufferSize,
     57                                    DisassembledCode*& _sourceCode);
     58    virtual status_t            GetStatement(FunctionDebugInfo* function,
     59                                    target_addr_t address,
     60                                    Statement*& _statement);
     61    virtual status_t            GetInstructionInfo(target_addr_t address,
     62                                    InstructionInfo& _info);
     63
     64private:
     65            struct ToDwarfRegisterMap;
     66            struct FromDwarfRegisterMap;
     67
     68private:
     69            void                _AddRegister(int32 index, const char* name,
     70                                    uint32 bitSize, uint32 valueType,
     71                                    register_type type, bool calleePreserved);
     72            void                _AddIntegerRegister(int32 index,
     73                                    const char* name, uint32 valueType,
     74                                    register_type type, bool calleePreserved);
     75
     76            bool                _HasFunctionPrologue(
     77                                    FunctionDebugInfo* function) const;
     78
     79private:
     80            Array<Register>     fRegisters;
     81            SourceLanguage*     fAssemblyLanguage;
     82            ToDwarfRegisterMap* fToDwarfRegisterMap;
     83            FromDwarfRegisterMap* fFromDwarfRegisterMap;
     84};
     85
     86
     87#endif  // ARCHITECTURE_X86_H
  • new file src/apps/debugger/arch/x86_64/CpuStateX86_64.cpp

    diff --git a/src/apps/debugger/arch/x86_64/CpuStateX86_64.cpp b/src/apps/debugger/arch/x86_64/CpuStateX86_64.cpp
    new file mode 100644
    index 0000000..406c4da
    - +  
     1/*
     2 * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
     3 * Copyright 2011-2012, Rene Gollent, rene@gollent.com.
     4 * Distributed under the terms of the MIT License.
     5 */
     6
     7#include "CpuStateX86_64.h"
     8
     9#include "Register.h"
     10
     11
     12CpuStateX86_64::CpuStateX86_64()
     13    :
     14    fSetRegisters(),
     15    fInterruptVector(0)
     16{
     17}
     18
     19
     20CpuStateX86_64::CpuStateX86_64(const x86_64_debug_cpu_state& state)
     21    :
     22    fSetRegisters(),
     23    fInterruptVector(0)
     24{
     25    SetIntRegister(X86_64_REGISTER_RIP, state.rip);
     26    SetIntRegister(X86_64_REGISTER_RSP, state.rsp);
     27    SetIntRegister(X86_64_REGISTER_RBP, state.rbp);
     28    SetIntRegister(X86_64_REGISTER_RAX, state.rax);
     29    SetIntRegister(X86_64_REGISTER_RBX, state.rbx);
     30    SetIntRegister(X86_64_REGISTER_RCX, state.rcx);
     31    SetIntRegister(X86_64_REGISTER_RDX, state.rdx);
     32    SetIntRegister(X86_64_REGISTER_RSI, state.rsi);
     33    SetIntRegister(X86_64_REGISTER_RDI, state.rdi);
     34    SetIntRegister(X86_64_REGISTER_R8, state.r8);
     35    SetIntRegister(X86_64_REGISTER_R9, state.r9);
     36    SetIntRegister(X86_64_REGISTER_R10, state.r10);
     37    SetIntRegister(X86_64_REGISTER_R11, state.r11);
     38    SetIntRegister(X86_64_REGISTER_R12, state.r12);
     39    SetIntRegister(X86_64_REGISTER_R13, state.r13);
     40    SetIntRegister(X86_64_REGISTER_R14, state.r14);
     41    SetIntRegister(X86_64_REGISTER_R15, state.r15);
     42    SetIntRegister(X86_64_REGISTER_CS, state.cs);
     43    SetIntRegister(X86_64_REGISTER_FS, state.fs);
     44    SetIntRegister(X86_64_REGISTER_GS, state.gs);
     45
     46    // TODO: fix
     47//  fInterruptVector = state.vector;
     48}
     49
     50
     51CpuStateX86_64::~CpuStateX86_64()
     52{
     53}
     54
     55
     56target_addr_t
     57CpuStateX86_64::InstructionPointer() const
     58{
     59    return IsRegisterSet(X86_64_REGISTER_RIP)
     60        ? IntRegisterValue(X86_64_REGISTER_RIP) : 0;
     61}
     62
     63
     64target_addr_t
     65CpuStateX86_64::StackFramePointer() const
     66{
     67    return IsRegisterSet(X86_64_REGISTER_RBP)
     68        ? IntRegisterValue(X86_64_REGISTER_RBP) : 0;
     69}
     70
     71
     72target_addr_t
     73CpuStateX86_64::StackPointer() const
     74{
     75    return IsRegisterSet(X86_64_REGISTER_RSP)
     76        ? IntRegisterValue(X86_64_REGISTER_RSP) : 0;
     77}
     78
     79
     80bool
     81CpuStateX86_64::GetRegisterValue(const Register* reg, BVariant& _value) const
     82{
     83    int32 index = reg->Index();
     84    if (!IsRegisterSet(index))
     85        return false;
     86
     87    if (index >= X86_64_INT_REGISTER_END)
     88        return false;
     89
     90    if (reg->BitSize() == 16)
     91        _value.SetTo((uint16)fIntRegisters[index]);
     92    else
     93        _value.SetTo(fIntRegisters[index]);
     94
     95    return true;
     96}
     97
     98
     99bool
     100CpuStateX86_64::SetRegisterValue(const Register* reg, const BVariant& value)
     101{
     102    int32 index = reg->Index();
     103    if (index >= X86_64_INT_REGISTER_END)
     104        return false;
     105
     106    fIntRegisters[index] = value.ToUInt64();
     107    fSetRegisters[index] = 1;
     108    return true;
     109}
     110
     111
     112bool
     113CpuStateX86_64::IsRegisterSet(int32 index) const
     114{
     115    return index >= 0 && index < X86_64_REGISTER_COUNT && fSetRegisters[index];
     116}
     117
     118
     119uint32
     120CpuStateX86_64::IntRegisterValue(int32 index) const
     121{
     122    if (!IsRegisterSet(index) || index >= X86_64_INT_REGISTER_END)
     123        return 0;
     124
     125    return fIntRegisters[index];
     126}
     127
     128
     129void
     130CpuStateX86_64::SetIntRegister(int32 index, uint64 value)
     131{
     132    if (index < 0 || index >= X86_64_INT_REGISTER_END)
     133        return;
     134
     135    fIntRegisters[index] = value;
     136    fSetRegisters[index] = 1;
     137}
     138
     139
     140void
     141CpuStateX86_64::UnsetRegister(int32 index)
     142{
     143    if (index < 0 || index >= X86_64_REGISTER_COUNT)
     144        return;
     145
     146    fSetRegisters[index] = 0;
     147}
  • new file src/apps/debugger/arch/x86_64/CpuStateX86_64.h

    diff --git a/src/apps/debugger/arch/x86_64/CpuStateX86_64.h b/src/apps/debugger/arch/x86_64/CpuStateX86_64.h
    new file mode 100644
    index 0000000..5408d2c
    - +  
     1/*
     2 * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
     3 * Copyright 2011-2012, Rene Gollent, rene@gollent.com.
     4 * Distributed under the terms of the MIT License.
     5 */
     6#ifndef CPU_STATE_X86_64_H
     7#define CPU_STATE_X86_64_H
     8
     9#include <bitset>
     10
     11#include <debugger.h>
     12
     13#include "CpuState.h"
     14
     15
     16enum {
     17    X86_64_REGISTER_RIP = 0,
     18    X86_64_REGISTER_RSP,
     19    X86_64_REGISTER_RBP,
     20
     21    X86_64_REGISTER_RAX,
     22    X86_64_REGISTER_RBX,
     23    X86_64_REGISTER_RCX,
     24    X86_64_REGISTER_RDX,
     25
     26    X86_64_REGISTER_RSI,
     27    X86_64_REGISTER_RDI,
     28
     29    X86_64_REGISTER_R8,
     30    X86_64_REGISTER_R9,
     31    X86_64_REGISTER_R10,
     32    X86_64_REGISTER_R11,
     33    X86_64_REGISTER_R12,
     34    X86_64_REGISTER_R13,
     35    X86_64_REGISTER_R14,
     36    X86_64_REGISTER_R15,
     37
     38    X86_64_REGISTER_CS,
     39    X86_64_REGISTER_FS,
     40    X86_64_REGISTER_GS,
     41
     42    X86_64_INT_REGISTER_END,
     43    X86_64_REGISTER_COUNT
     44};
     45
     46
     47class CpuStateX86_64 : public CpuState {
     48public:
     49                                CpuStateX86_64();
     50                                CpuStateX86_64(
     51                                    const x86_64_debug_cpu_state& state);
     52    virtual                     ~CpuStateX86_64();
     53
     54    virtual target_addr_t       InstructionPointer() const;
     55    virtual target_addr_t       StackFramePointer() const;
     56    virtual target_addr_t       StackPointer() const;
     57    virtual bool                GetRegisterValue(const Register* reg,
     58                                    BVariant& _value) const;
     59    virtual bool                SetRegisterValue(const Register* reg,
     60                                    const BVariant& value);
     61
     62            uint32              InterruptVector() const
     63                                    { return fInterruptVector; }
     64
     65            bool                IsRegisterSet(int32 index) const;
     66            uint32              IntRegisterValue(int32 index) const;
     67            void                SetIntRegister(int32 index, uint64 value);
     68            void                UnsetRegister(int32 index);
     69
     70private:
     71    typedef std::bitset<X86_64_REGISTER_COUNT> RegisterBitSet;
     72
     73private:
     74            uint32              fIntRegisters[X86_64_REGISTER_COUNT];
     75            RegisterBitSet      fSetRegisters;
     76            uint32              fInterruptVector;
     77};
     78
     79
     80#endif  // CPU_STATE_X86_64_H
  • src/apps/debugger/debugger_interface/DebuggerInterface.cpp

    diff --git a/src/apps/debugger/debugger_interface/DebuggerInterface.cpp b/src/apps/debugger/debugger_interface/DebuggerInterface.cpp
    index 2504389..86189a7 100644
    a b  
    2121
    2222#include "debug_utils.h"
    2323
     24#ifdef ARCH_x86
    2425#include "ArchitectureX86.h"
     26#elif defined(ARCH_x86_64)
     27#include "ArchitectureX86_64.h"
     28#endif
    2529#include "CpuState.h"
    2630#include "DebugEvent.h"
    2731#include "ImageInfo.h"
    status_t  
    252256DebuggerInterface::Init()
    253257{
    254258    // create the architecture
    255     // TODO: this probably needs to be rethought a bit,
    256     // since especially when we eventually support remote debugging,
    257     // the architecture will depend on the target machine, not the host
    258259#ifdef ARCH_x86
    259260    fArchitecture = new(std::nothrow) ArchitectureX86(this);
     261#elif defined(ARCH_x86_64)
     262    fArchitecture = new(std::nothrow) ArchitectureX86_64(this);
    260263#else
    261264    return B_UNSUPPORTED;
    262265#endif
  • src/apps/debugger/elf/ElfFile.cpp

    diff --git a/src/apps/debugger/elf/ElfFile.cpp b/src/apps/debugger/elf/ElfFile.cpp
    index abf1147..932e650 100644
    a b  
    1919
    2020#include "Tracing.h"
    2121
     22#ifdef B_HAIKU_64_BIT
     23#include "elf64.h"
     24#else
     25#include "elf32.h"
     26#endif
    2227
    2328// #pragma mark - ElfSection
    2429
    ElfFile::Init(const char* fileName)  
    147152    fFileSize = st.st_size;
    148153
    149154    // read the elf header
    150     fElfHeader = (Elf32_Ehdr*)malloc(sizeof(Elf32_Ehdr));
     155    fElfHeader = (elf_ehdr*)malloc(sizeof(elf_ehdr));
    151156    if (fElfHeader == NULL)
    152157        return B_NO_MEMORY;
    153158
    154     ssize_t bytesRead = pread(fFD, fElfHeader, sizeof(Elf32_Ehdr), 0);
    155     if (bytesRead != (ssize_t)sizeof(Elf32_Ehdr))
     159    ssize_t bytesRead = pread(fFD, fElfHeader, sizeof(elf_ehdr), 0);
     160    if (bytesRead != (ssize_t)sizeof(elf_ehdr))
    156161        return bytesRead < 0 ? errno : B_ERROR;
    157162
    158163    // check the ELF header
    159     if (!_CheckRange(0, sizeof(Elf32_Ehdr)) || !_CheckElfHeader()) {
     164    if (!_CheckRange(0, sizeof(elf_ehdr)) || !_CheckElfHeader()) {
    160165        WARNING("\"%s\": Not an ELF file\n", fileName);
    161166        return B_BAD_DATA;
    162167    }
    ElfFile::Init(const char* fileName)  
    183188        return bytesRead < 0 ? errno : B_ERROR;
    184189
    185190    // check and get the section header string section
    186     Elf32_Shdr* stringSectionHeader = (Elf32_Shdr*)(sectionHeaderTable
     191    elf_shdr* stringSectionHeader = (elf_shdr*)(sectionHeaderTable
    187192        + fElfHeader->e_shstrndx * sectionHeaderSize);
    188193    if (!_CheckRange(stringSectionHeader->sh_offset,
    189194            stringSectionHeader->sh_size)) {
    ElfFile::Init(const char* fileName)  
    207212
    208213    // read the other sections
    209214    for (int i = 0; i < sectionCount; i++) {
    210         Elf32_Shdr* sectionHeader = (Elf32_Shdr*)(sectionHeaderTable
     215        elf_shdr* sectionHeader = (elf_shdr*)(sectionHeaderTable
    211216            + i * sectionHeaderSize);
    212217        // skip invalid sections and the section header string section
    213218        const char* name = sectionStrings + sectionHeader->sh_name;
    ElfFile::Init(const char* fileName)  
    249254
    250255    // read the program headers and create ElfSegment objects
    251256    for (int i = 0; i < segmentCount; i++) {
    252         Elf32_Phdr* programHeader = (Elf32_Phdr*)(programHeaderTable
     257        elf_phdr* programHeader = (elf_phdr*)(programHeaderTable
    253258            + i * programHeaderSize);
    254259        // skip program headers we aren't interested in or that are invalid
    255260        if (programHeader->p_type != PT_LOAD || programHeader->p_filesz == 0
    bool  
    341346ElfFile::_CheckElfHeader() const
    342347{
    343348    return memcmp(fElfHeader->e_ident, ELF_MAGIC, 4) == 0
    344         && fElfHeader->e_ident[4] == ELFCLASS32
     349        && fElfHeader->e_ident[4] == ELF_CLASS
    345350        && fElfHeader->e_shoff > 0
    346351        && fElfHeader->e_shnum > 0
    347         && fElfHeader->e_shentsize >= sizeof(struct Elf32_Shdr)
     352        && fElfHeader->e_shentsize >= sizeof(elf_shdr)
    348353        && fElfHeader->e_shstrndx != SHN_UNDEF
    349354        && fElfHeader->e_shstrndx < fElfHeader->e_shnum
    350355        && fElfHeader->e_phoff > 0
    351356        && fElfHeader->e_phnum > 0
    352         && fElfHeader->e_phentsize >= sizeof(struct Elf32_Phdr);
     357        && fElfHeader->e_phentsize >= sizeof(elf_phdr);
    353358}
  • src/apps/debugger/elf/ElfFile.h

    diff --git a/src/apps/debugger/elf/ElfFile.h b/src/apps/debugger/elf/ElfFile.h
    index c4e7665..64b702e 100644
    a b  
    99
    1010#include <SupportDefs.h>
    1111
    12 #include <elf32.h>
     12#include <elf_common.h>
    1313#include <util/DoublyLinkedList.h>
    1414
    1515#include "Types.h"
    private:  
    9696private:
    9797            off_t               fFileSize;
    9898            int                 fFD;
    99             Elf32_Ehdr*         fElfHeader;
     99            elf_ehdr*           fElfHeader;
    100100            SectionList         fSections;
    101101            SegmentList         fSegments;
    102102};