Merge branch 'master' into sam460ex

This commit is contained in:
François Revol
2013-01-02 01:55:03 +01:00
31 changed files with 804 additions and 157 deletions
@@ -11,9 +11,9 @@ KernelAddon intel_extreme :
driver.cpp driver.cpp
device.cpp device.cpp
intel_extreme.cpp intel_extreme.cpp
power.cpp
kernel_cpp.cpp kernel_cpp.cpp
: libgraphicscommon.a : libgraphicscommon.a
; ;
@@ -10,16 +10,16 @@
#include "intel_extreme.h" #include "intel_extreme.h"
#include "AreaKeeper.h" #include "AreaKeeper.h"
#include "driver.h"
#include "utility.h"
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <driver_settings.h> #include <driver_settings.h>
#include <util/kernel_cpp.h> #include <util/kernel_cpp.h>
#include "utility.h"
#include "driver.h"
#include "power.h"
#define TRACE_INTELEXTREME #define TRACE_INTELEXTREME
@@ -296,38 +296,11 @@ intel_extreme_init(intel_info &info)
primary.offset = (addr_t)primary.base - info.aperture_base; primary.offset = (addr_t)primary.base - info.aperture_base;
} }
// Clock gating // Enable clock gating
// Fix some problems on certain chips (taken from X driver) intel_en_gating(info);
// TODO: clean this up
if (info.pci->device_id == 0x2a02 || info.pci->device_id == 0x2a12) {
TRACE("i965GM/i965GME quirk\n");
write32(info, 0x6204, (1L << 29));
} else if (info.device_type.InGroup(INTEL_TYPE_SNB)) {
TRACE("SandyBridge clock gating\n");
write32(info, 0x42020, (1L << 28) | (1L << 7) | (1L << 5));
} else if (info.device_type.InGroup(INTEL_TYPE_IVB)) {
TRACE("IvyBridge clock gating\n");
write32(info, 0x42020, (1L << 28));
} else if (info.device_type.InGroup(INTEL_TYPE_ILK)) {
TRACE("IronLake clock gating\n");
write32(info, 0x42020, (1L << 7) | (1L << 5));
} else if (info.device_type.InGroup(INTEL_TYPE_G4x)) {
TRACE("G4x clock gating\n");
write32(info, 0x6204, 0);
write32(info, 0x6208, (1L << 9) | (1L << 7) | (1L << 6));
write32(info, 0x6210, 0);
uint32 gateValue = (1L << 28) | (1L << 3) | (1L << 2); // Enable automatic gpu downclocking if we can to save power
if ((info.device_type.type & INTEL_TYPE_MOBILE) == INTEL_TYPE_MOBILE) { intel_en_downclock(info);
TRACE("G4x mobile clock gating\n");
gateValue |= 1L << 18;
}
write32(info, 0x6200, gateValue);
} else {
TRACE("i965 quirk\n");
write32(info, 0x6204, (1L << 29) | (1L << 23));
}
write32(info, 0x7408, 0x10);
// no errors, so keep areas and mappings // no errors, so keep areas and mappings
sharedCreator.Detach(); sharedCreator.Detach();
@@ -0,0 +1,175 @@
/*
* Copyright 2012-2013, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Alexander von Gluck IV, [email protected]
*/
#include "power.h"
#undef TRACE
#define TRACE_POWER
#ifdef TRACE_POWER
# define TRACE(x...) dprintf("intel_extreme:" x)
#else
# define TRACE(x...)
#endif
#define ERROR(x...) dprintf("intel_extreme: " x)
#define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
status_t
intel_en_gating(intel_info &info)
{
CALLED();
// Fix some problems on certain chips (taken from X driver)
// TODO: clean this up
if (info.pci->device_id == 0x2a02 || info.pci->device_id == 0x2a12) {
TRACE("i965GM/i965GME quirk\n");
write32(info, 0x6204, (1L << 29));
} else if (info.device_type.InGroup(INTEL_TYPE_SNB)) {
TRACE("SandyBridge clock gating\n");
write32(info, 0x42020, (1L << 28) | (1L << 7) | (1L << 5));
} else if (info.device_type.InGroup(INTEL_TYPE_IVB)) {
TRACE("IvyBridge clock gating\n");
write32(info, 0x42020, (1L << 28));
} else if (info.device_type.InGroup(INTEL_TYPE_ILK)) {
TRACE("IronLake clock gating\n");
write32(info, 0x42020, (1L << 7) | (1L << 5));
} else if (info.device_type.InGroup(INTEL_TYPE_G4x)) {
TRACE("G4x clock gating\n");
write32(info, 0x6204, 0);
write32(info, 0x6208, (1L << 9) | (1L << 7) | (1L << 6));
write32(info, 0x6210, 0);
uint32 gateValue = (1L << 28) | (1L << 3) | (1L << 2);
if ((info.device_type.type & INTEL_TYPE_MOBILE) == INTEL_TYPE_MOBILE) {
TRACE("G4x mobile clock gating\n");
gateValue |= 1L << 18;
}
write32(info, 0x6200, gateValue);
} else {
TRACE("i965 quirk\n");
write32(info, 0x6204, (1L << 29) | (1L << 23));
}
write32(info, 0x7408, 0x10);
return B_OK;
}
status_t
intel_en_downclock(intel_info &info)
{
CALLED();
if (!info.device_type.InGroup(INTEL_TYPE_SNB)
&& !info.device_type.InGroup(INTEL_TYPE_IVB)) {
TRACE("%s: Downclocking not supported on this chipset.\n", __func__);
return B_NOT_ALLOWED;
}
if((info.device_type.type & INTEL_TYPE_MOBILE) == 0) {
// I don't see a point enabling auto-downclocking on non-mobile devices.
TRACE("%s: Skip GPU downclocking on non-mobile device.\n", __func__);
return B_NOT_ALLOWED;
}
// TODO: Check for deep RC6
// IvyBridge, SandyBridge, and Haswell can do depth 1 atm
// Some chipsets can go deeper... but this is safe for now
// Haswell should *NOT* do over depth 1;
int depth = 1;
// Lets always print this for now incase it causes regressions for someone.
ERROR("%s: Enabling Intel GPU auto downclocking depth %d\n", __func__,
depth);
/* Magical sequence of register writes to enable
* downclocking from the fine folks at Xorg
*/
write32(info, INTEL6_RC_STATE, 0);
uint32 rpStateCapacity = read32(info, INTEL6_RP_STATE_CAP);
uint32 gtPerfStatus = read32(info, INTEL6_GT_PERF_STATUS);
uint8 maxDelay = rpStateCapacity & 0xff;
uint8 minDelay = (rpStateCapacity & 0xff0000) >> 16;
write32(info, INTEL6_RC_CONTROL, 0);
write32(info, INTEL6_RC1_WAKE_RATE_LIMIT, 1000 << 16);
write32(info, INTEL6_RC6_WAKE_RATE_LIMIT, 40 << 16 | 30);
write32(info, INTEL6_RC6pp_WAKE_RATE_LIMIT, 30);
write32(info, INTEL6_RC_EVALUATION_INTERVAL, 125000);
write32(info, INTEL6_RC_IDLE_HYSTERSIS, 25);
// TODO: Idle each ring
write32(info, INTEL6_RC_SLEEP, 0);
write32(info, INTEL6_RC1e_THRESHOLD, 1000);
write32(info, INTEL6_RC6_THRESHOLD, 50000);
write32(info, INTEL6_RC6p_THRESHOLD, 100000);
write32(info, INTEL6_RC6pp_THRESHOLD, 64000);
uint32 rc6Mask = INTEL6_RC_CTL_RC6_ENABLE;
if (depth > 1)
rc6Mask |= INTEL6_RC_CTL_RC6p_ENABLE;
if (depth > 2)
rc6Mask |= INTEL6_RC_CTL_RC6pp_ENABLE;
write32(info, INTEL6_RC_CONTROL, rc6Mask | INTEL6_RC_CTL_EI_MODE(1)
| INTEL6_RC_CTL_HW_ENABLE);
write32(info, INTEL6_RPNSWREQ, INTEL6_FREQUENCY(10) | INTEL6_OFFSET(0)
| INTEL6_AGGRESSIVE_TURBO);
write32(info, INTEL6_RC_VIDEO_FREQ, INTEL6_FREQUENCY(12));
write32(info, INTEL6_RP_DOWN_TIMEOUT, 1000000);
write32(info, INTEL6_RP_INTERRUPT_LIMITS, maxDelay << 24 | minDelay << 16);
write32(info, INTEL6_RP_UP_THRESHOLD, 59400);
write32(info, INTEL6_RP_DOWN_THRESHOLD, 245000);
write32(info, INTEL6_RP_UP_EI, 66000);
write32(info, INTEL6_RP_DOWN_EI, 350000);
write32(info, INTEL6_RP_IDLE_HYSTERSIS, 10);
write32(info, INTEL6_RP_CONTROL, INTEL6_RP_MEDIA_TURBO
| INTEL6_RP_MEDIA_HW_NORMAL_MODE | INTEL6_RP_MEDIA_IS_GFX
| INTEL6_RP_ENABLE | INTEL6_RP_UP_BUSY_AVG
| INTEL6_RP_DOWN_IDLE_CONT);
// TODO: | (HASWELL ? GEN7_RP_DOWN_IDLE_AVG : INTEL6_RP_DOWN_IDLE_CONT));
// TODO: wait for (read32(INTEL6_PCODE_MAILBOX) & INTEL6_PCODE_READY)
write32(info, INTEL6_PCODE_DATA, 0);
write32(info, INTEL6_PCODE_MAILBOX, INTEL6_PCODE_READY
| INTEL6_PCODE_WRITE_MIN_FREQ_TABLE);
// TODO: wait for (read32(INTEL6_PCODE_MAILBOX) & INTEL6_PCODE_READY)
// TODO: check for overclock support and set.
// Calculate limits and enforce them
uint8 gtPerfShift = (gtPerfStatus & 0xff00) >> 8;
if (gtPerfShift >= maxDelay)
gtPerfShift = maxDelay;
uint32 limits = maxDelay << 24;
if (gtPerfShift <= minDelay) {
gtPerfShift = minDelay;
limits |= minDelay << 16;
}
write32(info, INTEL6_RP_INTERRUPT_LIMITS, limits);
write32(info, INTEL6_RPNSWREQ, INTEL6_FREQUENCY(gtPerfShift)
| INTEL6_OFFSET(0) | INTEL6_AGGRESSIVE_TURBO);
// Requires MSI to be enabled.
write32(info, INTEL6_PMIER, INTEL6_PM_DEFERRED_EVENTS);
// TODO: Review need for spin lock irq rps here?
write32(info, INTEL6_PMIMR, 0);
// TODO: Review need for spin unlock irq rps here?
write32(info, INTEL6_PMINTRMSK, 0);
return B_OK;
}
@@ -0,0 +1,121 @@
/*
* Copyright 2012-2013, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Alexander von Gluck IV, [email protected]
*/
#ifndef _INTEL_POWER_H_
#define _INTEL_POWER_H_
#include <string.h>
#include "driver.h"
// Clocking configuration
#define INTEL6_GT_THREAD_STATUS_REG 0x13805c
#define INTEL6_GT_THREAD_STATUS_CORE_MASK 0x7
#define INTEL6_GT_THREAD_STATUS_CORE_MASK_HSW (0x7 | (0x07 << 16))
#define INTEL6_GT_PERF_STATUS 0x145948
#define INTEL6_RP_STATE_LIMITS 0x145994
#define INTEL6_RP_STATE_CAP 0x145998
#define INTEL6_RPNSWREQ 0xA008
#define INTEL6_TURBO_DISABLE (1<<31)
#define INTEL6_FREQUENCY(x) ((x)<<25)
#define INTEL6_OFFSET(x) ((x)<<19)
#define INTEL6_AGGRESSIVE_TURBO (0<<15)
#define INTEL6_RC_VIDEO_FREQ 0xA00C
#define INTEL6_RC_CONTROL 0xA090
#define INTEL6_RC_CTL_RC6pp_ENABLE (1<<16)
#define INTEL6_RC_CTL_RC6p_ENABLE (1<<17)
#define INTEL6_RC_CTL_RC6_ENABLE (1<<18)
#define INTEL6_RC_CTL_RC1e_ENABLE (1<<20)
#define INTEL6_RC_CTL_RC7_ENABLE (1<<22)
#define INTEL6_RC_CTL_EI_MODE(x) ((x)<<27)
#define INTEL6_RC_CTL_HW_ENABLE (1<<31)
#define INTEL6_RP_DOWN_TIMEOUT 0xA010
#define INTEL6_RP_INTERRUPT_LIMITS 0xA014
#define INTEL6_RPSTAT1 0xA01C
#define INTEL6_CAGF_SHIFT 8
#define INTEL6_CAGF_MASK (0x7f << INTEL6_CAGF_SHIFT)
#define INTEL6_RP_CONTROL 0xA024
#define INTEL6_RP_MEDIA_TURBO (1<<11)
#define INTEL6_RP_MEDIA_MODE_MASK (3<<9)
#define INTEL6_RP_MEDIA_HW_TURBO_MODE (3<<9)
#define INTEL6_RP_MEDIA_HW_NORMAL_MODE (2<<9)
#define INTEL6_RP_MEDIA_HW_MODE (1<<9)
#define INTEL6_RP_MEDIA_SW_MODE (0<<9)
#define INTEL6_RP_MEDIA_IS_GFX (1<<8)
#define INTEL6_RP_ENABLE (1<<7)
#define INTEL6_RP_UP_IDLE_MIN (0x1<<3)
#define INTEL6_RP_UP_BUSY_AVG (0x2<<3)
#define INTEL6_RP_UP_BUSY_CONT (0x4<<3)
#define GEN7_RP_DOWN_IDLE_AVG (0x2<<0)
#define INTEL6_RP_DOWN_IDLE_CONT (0x1<<0)
#define INTEL6_RP_UP_THRESHOLD 0xA02C
#define INTEL6_RP_DOWN_THRESHOLD 0xA030
#define INTEL6_RP_CUR_UP_EI 0xA050
#define INTEL6_CURICONT_MASK 0xffffff
#define INTEL6_RP_CUR_UP 0xA054
#define INTEL6_CURBSYTAVG_MASK 0xffffff
#define INTEL6_RP_PREV_UP 0xA058
#define INTEL6_RP_CUR_DOWN_EI 0xA05C
#define INTEL6_CURIAVG_MASK 0xffffff
#define INTEL6_RP_CUR_DOWN 0xA060
#define INTEL6_RP_PREV_DOWN 0xA064
#define INTEL6_RP_UP_EI 0xA068
#define INTEL6_RP_DOWN_EI 0xA06C
#define INTEL6_RP_IDLE_HYSTERSIS 0xA070
#define INTEL6_RC_STATE 0xA094
#define INTEL6_RC1_WAKE_RATE_LIMIT 0xA098
#define INTEL6_RC6_WAKE_RATE_LIMIT 0xA09C
#define INTEL6_RC6pp_WAKE_RATE_LIMIT 0xA0A0
#define INTEL6_RC_EVALUATION_INTERVAL 0xA0A8
#define INTEL6_RC_IDLE_HYSTERSIS 0xA0AC
#define INTEL6_RC_SLEEP 0xA0B0
#define INTEL6_RC1e_THRESHOLD 0xA0B4
#define INTEL6_RC6_THRESHOLD 0xA0B8
#define INTEL6_RC6p_THRESHOLD 0xA0BC
#define INTEL6_RC6pp_THRESHOLD 0xA0C0
#define INTEL6_PMINTRMSK 0xA168
#define INTEL6_PMISR 0x44020
#define INTEL6_PMIMR 0x44024 /* rps_lock */
#define INTEL6_PMIIR 0x44028
#define INTEL6_PMIER 0x4402C
#define INTEL6_PM_MBOX_EVENT (1<<25)
#define INTEL6_PM_THERMAL_EVENT (1<<24)
#define INTEL6_PM_RP_DOWN_TIMEOUT (1<<6)
#define INTEL6_PM_RP_UP_THRESHOLD (1<<5)
#define INTEL6_PM_RP_DOWN_THRESHOLD (1<<4)
#define INTEL6_PM_RP_UP_EI_EXPIRED (1<<2)
#define INTEL6_PM_RP_DOWN_EI_EXPIRED (1<<1)
#define INTEL6_PM_DEFERRED_EVENTS (INTEL6_PM_RP_UP_THRESHOLD \
| INTEL6_PM_RP_DOWN_THRESHOLD \
| INTEL6_PM_RP_DOWN_TIMEOUT)
#define INTEL6_GT_GFX_RC6_LOCKED 0x138104
#define INTEL6_GT_GFX_RC6 0x138108
#define INTEL6_GT_GFX_RC6p 0x13810C
#define INTEL6_GT_GFX_RC6pp 0x138110
#define INTEL6_PCODE_MAILBOX 0x138124
#define INTEL6_PCODE_READY (1<<31)
#define INTEL6_READ_OC_PARAMS 0xc
#define INTEL6_PCODE_WRITE_MIN_FREQ_TABLE 0x8
#define INTEL6_PCODE_READ_MIN_FREQ_TABLE 0x9
#define INTEL6_PCODE_DATA 0x138128
#define INTEL6_PCODE_FREQ_IA_RATIO_SHIFT 8
#define INTEL6_GT_CORE_STATUS 0x138060
#define INTEL6_CORE_CPD_STATE_MASK (7<<4)
#define INTEL6_RCn_MASK 7
#define INTEL6_RC0 0
#define INTEL6_RC3 2
#define INTEL6_RC6 3
#define INTEL6_RC7 4
status_t intel_en_gating(intel_info &info);
status_t intel_en_downclock(intel_info &info);
#endif /* _INTEL_POWER_H_ */
+2 -1
View File
@@ -124,9 +124,10 @@ Application Debugger :
# ids # ids
FunctionID.cpp FunctionID.cpp
FunctionParameterID.cpp
LocalVariableID.cpp LocalVariableID.cpp
ObjectID.cpp ObjectID.cpp
FunctionParameterID.cpp ReturnValueID.cpp
# jobs # jobs
GetCPUStateJob.cpp GetCPUStateJob.cpp
+4 -3
View File
@@ -94,8 +94,8 @@ Architecture::InitRegisterRules(CfaContext& context) const
status_t status_t
Architecture::CreateStackTrace(Team* team, Architecture::CreateStackTrace(Team* team,
ImageDebugInfoProvider* imageInfoProvider, CpuState* cpuState, ImageDebugInfoProvider* imageInfoProvider, CpuState* cpuState,
StackTrace*& _stackTrace, int32 maxStackDepth, bool useExistingTrace, StackTrace*& _stackTrace, target_addr_t returnFunctionAddress,
bool getFullFrameInfo) int32 maxStackDepth, bool useExistingTrace, bool getFullFrameInfo)
{ {
BReference<CpuState> cpuStateReference(cpuState); BReference<CpuState> cpuStateReference(cpuState);
@@ -163,7 +163,8 @@ Architecture::CreateStackTrace(Team* team,
if (function != NULL) { if (function != NULL) {
status_t error = functionDebugInfo->GetSpecificImageDebugInfo() status_t error = functionDebugInfo->GetSpecificImageDebugInfo()
->CreateFrame(image, function, cpuState, getFullFrameInfo, ->CreateFrame(image, function, cpuState, getFullFrameInfo,
frame, previousCpuState); nextFrame == NULL ? returnFunctionAddress : 0, frame,
previousCpuState);
if (error != B_OK && error != B_UNSUPPORTED) if (error != B_OK && error != B_UNSUPPORTED)
break; break;
} }
+8 -1
View File
@@ -30,6 +30,7 @@ class StackTrace;
class Statement; class Statement;
class Team; class Team;
class TeamMemory; class TeamMemory;
class ValueLocation;
enum { enum {
@@ -102,12 +103,14 @@ public:
target_addr_t address, target_addr_t address,
Statement*& _statement) = 0; Statement*& _statement) = 0;
virtual status_t GetInstructionInfo(target_addr_t address, virtual status_t GetInstructionInfo(target_addr_t address,
InstructionInfo& _info) = 0; InstructionInfo& _info,
CpuState* state) = 0;
status_t CreateStackTrace(Team* team, status_t CreateStackTrace(Team* team,
ImageDebugInfoProvider* imageInfoProvider, ImageDebugInfoProvider* imageInfoProvider,
CpuState* cpuState, CpuState* cpuState,
StackTrace*& _stackTrace, StackTrace*& _stackTrace,
target_addr_t returnFunctionAddress,
int32 maxStackDepth = -1, int32 maxStackDepth = -1,
bool useExistingTrace = false, bool useExistingTrace = false,
bool getFullFrameInfo = true); bool getFullFrameInfo = true);
@@ -118,6 +121,10 @@ public:
int32& _maxBytesPerRegister, int32& _maxBytesPerRegister,
uint8& _watchpointCapabilityFlags) = 0; uint8& _watchpointCapabilityFlags) = 0;
virtual status_t GetReturnAddressLocation(
StackFrame* frame, target_size_t valueSize,
ValueLocation*& _location) = 0;
protected: protected:
TeamMemory* fTeamMemory; TeamMemory* fTeamMemory;
+7 -3
View File
@@ -9,6 +9,7 @@
InstructionInfo::InstructionInfo() InstructionInfo::InstructionInfo()
: :
fAddress(0), fAddress(0),
fTargetAddress(0),
fSize(0), fSize(0),
fType(INSTRUCTION_TYPE_OTHER), fType(INSTRUCTION_TYPE_OTHER),
fBreakpointAllowed(false), fBreakpointAllowed(false),
@@ -17,11 +18,13 @@ InstructionInfo::InstructionInfo()
} }
InstructionInfo::InstructionInfo(target_addr_t address, target_size_t size, InstructionInfo::InstructionInfo(target_addr_t address,
target_addr_t targetAddress, target_size_t size,
instruction_type type, bool breakpointAllowed, instruction_type type, bool breakpointAllowed,
const BString& disassembledLine) const BString& disassembledLine)
: :
fAddress(address), fAddress(address),
fTargetAddress(targetAddress),
fSize(size), fSize(size),
fType(type), fType(type),
fBreakpointAllowed(breakpointAllowed), fBreakpointAllowed(breakpointAllowed),
@@ -31,11 +34,12 @@ InstructionInfo::InstructionInfo(target_addr_t address, target_size_t size,
bool bool
InstructionInfo::SetTo(target_addr_t address, target_size_t size, InstructionInfo::SetTo(target_addr_t address, target_addr_t targetAddress,
instruction_type type, bool breakpointAllowed, target_size_t size, instruction_type type, bool breakpointAllowed,
const BString& disassembledLine) const BString& disassembledLine)
{ {
fAddress = address; fAddress = address;
fTargetAddress = targetAddress;
fSize = size; fSize = size;
fType = type; fType = type;
fBreakpointAllowed = breakpointAllowed; fBreakpointAllowed = breakpointAllowed;
+8 -1
View File
@@ -12,6 +12,7 @@
enum instruction_type { enum instruction_type {
INSTRUCTION_TYPE_SUBROUTINE_CALL, INSTRUCTION_TYPE_SUBROUTINE_CALL,
INSTRUCTION_TYPE_JUMP,
INSTRUCTION_TYPE_OTHER INSTRUCTION_TYPE_OTHER
}; };
@@ -20,16 +21,21 @@ class InstructionInfo {
public: public:
InstructionInfo(); InstructionInfo();
InstructionInfo(target_addr_t address, InstructionInfo(target_addr_t address,
target_addr_t targetAddress,
target_size_t size, instruction_type type, target_size_t size, instruction_type type,
bool breakpointAllowed, bool breakpointAllowed,
const BString& disassembledLine); const BString& disassembledLine);
bool SetTo(target_addr_t address, target_size_t size, bool SetTo(target_addr_t address,
target_addr_t targetAddress,
target_size_t size,
instruction_type type, instruction_type type,
bool breakpointAllowed, bool breakpointAllowed,
const BString& disassembledLine); const BString& disassembledLine);
target_addr_t Address() const { return fAddress; } target_addr_t Address() const { return fAddress; }
target_addr_t TargetAddress() const
{ return fTargetAddress; }
target_size_t Size() const { return fSize; } target_size_t Size() const { return fSize; }
instruction_type Type() const { return fType; } instruction_type Type() const { return fType; }
bool IsBreakpointAllowed() const bool IsBreakpointAllowed() const
@@ -40,6 +46,7 @@ public:
private: private:
target_addr_t fAddress; target_addr_t fAddress;
target_addr_t fTargetAddress;
target_size_t fSize; target_size_t fSize;
instruction_type fType; instruction_type fType;
bool fBreakpointAllowed; bool fBreakpointAllowed;
+51 -33
View File
@@ -23,6 +23,7 @@
#include "StackFrame.h" #include "StackFrame.h"
#include "Statement.h" #include "Statement.h"
#include "TeamMemory.h" #include "TeamMemory.h"
#include "ValueLocation.h"
#include "X86AssemblyLanguage.h" #include "X86AssemblyLanguage.h"
#include "disasm/DisassemblerX86.h" #include "disasm/DisassemblerX86.h"
@@ -560,7 +561,7 @@ ArchitectureX86::GetStatement(FunctionDebugInfo* function,
// TODO: This is not architecture dependent anymore! // TODO: This is not architecture dependent anymore!
// get the instruction info // get the instruction info
InstructionInfo info; InstructionInfo info;
status_t error = GetInstructionInfo(address, info); status_t error = GetInstructionInfo(address, info, NULL);
if (error != B_OK) if (error != B_OK)
return error; return error;
@@ -577,11 +578,10 @@ ArchitectureX86::GetStatement(FunctionDebugInfo* function,
status_t status_t
ArchitectureX86::GetInstructionInfo(target_addr_t address, ArchitectureX86::GetInstructionInfo(target_addr_t address,
InstructionInfo& _info) InstructionInfo& _info, CpuState* state)
{ {
// read the code // read the code - maximum x86{-64} instruction size = 15 bytes
uint8 buffer[16]; uint8 buffer[16];
// TODO: What's the maximum instruction size?
ssize_t bytesRead = fTeamMemory->ReadMemory(address, buffer, ssize_t bytesRead = fTeamMemory->ReadMemory(address, buffer,
sizeof(buffer)); sizeof(buffer));
if (bytesRead < 0) if (bytesRead < 0)
@@ -593,35 +593,7 @@ ArchitectureX86::GetInstructionInfo(target_addr_t address,
if (error != B_OK) if (error != B_OK)
return error; return error;
// disassemble the instruction return disassembler.GetNextInstructionInfo(_info, state);
BString line;
target_addr_t instructionAddress;
target_size_t instructionSize;
bool breakpointAllowed;
error = disassembler.GetNextInstruction(line, instructionAddress,
instructionSize, breakpointAllowed);
if (error != B_OK)
return error;
instruction_type instructionType = INSTRUCTION_TYPE_OTHER;
if (buffer[0] == 0xff && (buffer[1] & 0x34) == 0x10) {
// absolute call with r/m32
instructionType = INSTRUCTION_TYPE_SUBROUTINE_CALL;
} else if (buffer[0] == 0xe8 && instructionSize == 5) {
// relative call with rel32 -- don't categorize the call with 0 as
// subroutine call, since it is only used to get the address of the GOT
if (buffer[1] != 0 || buffer[2] != 0 || buffer[3] != 0
|| buffer[4] != 0) {
instructionType = INSTRUCTION_TYPE_SUBROUTINE_CALL;
}
}
if (!_info.SetTo(instructionAddress, instructionSize, instructionType,
breakpointAllowed, line)) {
return B_NO_MEMORY;
}
return B_OK;
} }
@@ -643,6 +615,52 @@ ArchitectureX86::GetWatchpointDebugCapabilities(int32& _maxRegisterCount,
} }
status_t
ArchitectureX86::GetReturnAddressLocation(StackFrame* frame,
target_size_t valueSize, ValueLocation*& _location)
{
// for the calling conventions currently in use on Haiku,
// the x86 rules for how values are returned are as follows:
//
// - 32 bits or smaller values are returned directly in EAX.
// - 32-64 bit values are returned across EAX:EDX.
// - > 64 bit values are returned on the stack.
ValueLocation* location = new(std::nothrow) ValueLocation(
IsBigEndian());
if (location == NULL)
return B_NO_MEMORY;
BReference<ValueLocation> locationReference(location,
true);
if (valueSize <= 4) {
ValuePieceLocation piece;
piece.SetSize(valueSize);
piece.SetToRegister(X86_REGISTER_EAX);
if (!location->AddPiece(piece))
return B_NO_MEMORY;
} else if (valueSize <= 8) {
ValuePieceLocation piece;
piece.SetSize(4);
piece.SetToRegister(X86_REGISTER_EAX);
if (!location->AddPiece(piece))
return B_NO_MEMORY;
piece.SetToRegister(X86_REGISTER_EDX);
piece.SetSize(valueSize - 4);
if (!location->AddPiece(piece))
return B_NO_MEMORY;
} else {
ValuePieceLocation piece;
piece.SetToMemory(frame->GetCpuState()->StackPointer());
piece.SetSize(valueSize);
if (!location->AddPiece(piece))
return B_NO_MEMORY;
}
_location = locationReference.Detach();
return B_OK;
}
void void
ArchitectureX86::_AddRegister(int32 index, const char* name, ArchitectureX86::_AddRegister(int32 index, const char* name,
uint32 bitSize, uint32 valueType, register_type type, bool calleePreserved) uint32 bitSize, uint32 valueType, register_type type, bool calleePreserved)
+6 -1
View File
@@ -59,13 +59,18 @@ public:
target_addr_t address, target_addr_t address,
Statement*& _statement); Statement*& _statement);
virtual status_t GetInstructionInfo(target_addr_t address, virtual status_t GetInstructionInfo(target_addr_t address,
InstructionInfo& _info); InstructionInfo& _info, CpuState* state);
virtual status_t GetWatchpointDebugCapabilities( virtual status_t GetWatchpointDebugCapabilities(
int32& _maxRegisterCount, int32& _maxRegisterCount,
int32& _maxBytesPerRegister, int32& _maxBytesPerRegister,
uint8& _watchpointCapabilityFlags); uint8& _watchpointCapabilityFlags);
virtual status_t GetReturnAddressLocation(
StackFrame* frame, target_size_t valueSize,
ValueLocation*& _location);
private: private:
struct ToDwarfRegisterMap; struct ToDwarfRegisterMap;
struct FromDwarfRegisterMap; struct FromDwarfRegisterMap;
@@ -12,6 +12,36 @@
#include <OS.h> #include <OS.h>
#include "CpuStateX86.h"
#include "InstructionInfo.h"
static uint8 RegisterNumberFromUdisIndex(int32 udisIndex)
{
switch (udisIndex) {
case UD_R_RIP: return X86_REGISTER_EIP;
case UD_R_ESP: return X86_REGISTER_ESP;
case UD_R_EBP: return X86_REGISTER_EBP;
case UD_R_EAX: return X86_REGISTER_EAX;
case UD_R_EBX: return X86_REGISTER_EBX;
case UD_R_ECX: return X86_REGISTER_ECX;
case UD_R_EDX: return X86_REGISTER_EDX;
case UD_R_ESI: return X86_REGISTER_ESI;
case UD_R_EDI: return X86_REGISTER_EDI;
case UD_R_CS: return X86_REGISTER_CS;
case UD_R_DS: return X86_REGISTER_DS;
case UD_R_ES: return X86_REGISTER_ES;
case UD_R_FS: return X86_REGISTER_FS;
case UD_R_GS: return X86_REGISTER_GS;
case UD_R_SS: return X86_REGISTER_SS;
}
return X86_INT_REGISTER_END;
}
struct DisassemblerX86::UdisData : ud_t { struct DisassemblerX86::UdisData : ud_t {
}; };
@@ -108,3 +138,85 @@ DisassemblerX86::GetPreviousInstruction(target_addr_t nextAddress,
} }
} }
} }
status_t
DisassemblerX86::GetNextInstructionInfo(InstructionInfo& _info,
CpuState* state)
{
unsigned int size = ud_disassemble(fUdisData);
if (size < 1)
return B_ENTRY_NOT_FOUND;
uint32 address = (uint32)ud_insn_off(fUdisData);
instruction_type type = INSTRUCTION_TYPE_OTHER;
target_addr_t targetAddress = 0;
if (fUdisData->mnemonic == UD_Icall)
type = INSTRUCTION_TYPE_SUBROUTINE_CALL;
else if (fUdisData->mnemonic == UD_Ijmp)
type = INSTRUCTION_TYPE_JUMP;
if (state != NULL)
targetAddress = GetInstructionTargetAddress(state);
char buffer[256];
snprintf(buffer, sizeof(buffer), "0x%08" B_PRIx32 ": %16.16s %s", address,
ud_insn_hex(fUdisData), ud_insn_asm(fUdisData));
// TODO: Resolve symbols!
if (!_info.SetTo(address, targetAddress, size, type, true, buffer))
return B_NO_MEMORY;
return B_OK;
}
target_addr_t
DisassemblerX86::GetInstructionTargetAddress(CpuState* state) const
{
if (fUdisData->mnemonic != UD_Icall && fUdisData->mnemonic != UD_Ijmp)
return 0;
CpuStateX86* x86State = dynamic_cast<CpuStateX86*>(state);
if (x86State == NULL)
return 0;
target_addr_t targetAddress = 0;
switch (fUdisData->operand[0].type) {
case UD_OP_REG:
{
targetAddress = x86State->IntRegisterValue(
RegisterNumberFromUdisIndex(fUdisData->operand[0].base));
targetAddress += fUdisData->operand[0].offset;
}
break;
case UD_OP_MEM:
{
targetAddress = x86State->IntRegisterValue(
RegisterNumberFromUdisIndex(fUdisData->operand[0].base));
targetAddress += x86State->IntRegisterValue(
RegisterNumberFromUdisIndex(fUdisData->operand[0].index))
* fUdisData->operand[0].scale;
}
break;
case UD_OP_JIMM:
{
targetAddress = ud_insn_off(fUdisData)
+ fUdisData->operand[0].lval.sdword + ud_insn_len(fUdisData);
}
break;
case UD_OP_IMM:
case UD_OP_CONST:
{
targetAddress = fUdisData->operand[0].lval.udword;
}
break;
default:
break;
}
return targetAddress;
}
@@ -10,6 +10,10 @@
#include "Types.h" #include "Types.h"
class CpuState;
class InstructionInfo;
class DisassemblerX86 { class DisassemblerX86 {
public: public:
DisassemblerX86(); DisassemblerX86();
@@ -27,6 +31,14 @@ public:
target_addr_t& _address, target_addr_t& _address,
target_size_t& _size); target_size_t& _size);
virtual status_t GetNextInstructionInfo(
InstructionInfo& _info,
CpuState* state);
private:
target_addr_t GetInstructionTargetAddress(
CpuState* state) const;
private: private:
struct UdisData; struct UdisData;
@@ -3,9 +3,12 @@ SubDir HAIKU_TOP src apps debugger arch x86 disasm ;
CCFLAGS += -Werror ; CCFLAGS += -Werror ;
C++FLAGS += -Werror ; C++FLAGS += -Werror ;
UsePrivateHeaders shared ;
UseHeaders [ LibraryHeaders udis86 ] ; UseHeaders [ LibraryHeaders udis86 ] ;
UseHeaders [ LibraryHeaders [ FDirName udis86 libudis86 ] ] ; UseHeaders [ LibraryHeaders [ FDirName udis86 libudis86 ] ] ;
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ;
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ; SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ;
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) $(DOTDOT) types ] ; SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) $(DOTDOT) types ] ;
@@ -451,7 +451,7 @@ ArchitectureX8664::GetStatement(FunctionDebugInfo* function,
// TODO: This is not architecture dependent anymore! // TODO: This is not architecture dependent anymore!
// get the instruction info // get the instruction info
InstructionInfo info; InstructionInfo info;
status_t error = GetInstructionInfo(address, info); status_t error = GetInstructionInfo(address, info, NULL);
if (error != B_OK) if (error != B_OK)
return error; return error;
@@ -468,7 +468,7 @@ ArchitectureX8664::GetStatement(FunctionDebugInfo* function,
status_t status_t
ArchitectureX8664::GetInstructionInfo(target_addr_t address, ArchitectureX8664::GetInstructionInfo(target_addr_t address,
InstructionInfo& _info) InstructionInfo& _info, CpuState* state)
{ {
// read the code // read the code
uint8 buffer[16]; uint8 buffer[16];
@@ -487,6 +487,7 @@ ArchitectureX8664::GetInstructionInfo(target_addr_t address,
// disassemble the instruction // disassemble the instruction
BString line; BString line;
target_addr_t instructionAddress; target_addr_t instructionAddress;
target_addr_t targetAddress = 0;
target_size_t instructionSize; target_size_t instructionSize;
bool breakpointAllowed; bool breakpointAllowed;
error = disassembler.GetNextInstruction(line, instructionAddress, error = disassembler.GetNextInstruction(line, instructionAddress,
@@ -508,8 +509,8 @@ ArchitectureX8664::GetInstructionInfo(target_addr_t address,
} }
} }
if (!_info.SetTo(instructionAddress, instructionSize, instructionType, if (!_info.SetTo(instructionAddress, targetAddress, instructionSize,
breakpointAllowed, line)) { instructionType, breakpointAllowed, line)) {
return B_NO_MEMORY; return B_NO_MEMORY;
} }
@@ -534,6 +535,13 @@ ArchitectureX8664::GetWatchpointDebugCapabilities(int32& _maxRegisterCount,
} }
status_t
ArchitectureX8664::GetReturnAddressLocation(StackFrame* frame,
target_size_t valueSize, ValueLocation*& _location) {
return B_NOT_SUPPORTED;
}
void void
ArchitectureX8664::_AddRegister(int32 index, const char* name, ArchitectureX8664::_AddRegister(int32 index, const char* name,
uint32 bitSize, uint32 valueType, register_type type, bool calleePreserved) uint32 bitSize, uint32 valueType, register_type type, bool calleePreserved)
@@ -60,13 +60,17 @@ public:
target_addr_t address, target_addr_t address,
Statement*& _statement); Statement*& _statement);
virtual status_t GetInstructionInfo(target_addr_t address, virtual status_t GetInstructionInfo(target_addr_t address,
InstructionInfo& _info); InstructionInfo& _info, CpuState* state);
virtual status_t GetWatchpointDebugCapabilities( virtual status_t GetWatchpointDebugCapabilities(
int32& _maxRegisterCount, int32& _maxRegisterCount,
int32& _maxBytesPerRegister, int32& _maxBytesPerRegister,
uint8& _watchpointCapabilityFlags); uint8& _watchpointCapabilityFlags);
virtual status_t GetReturnAddressLocation(
StackFrame* frame, target_size_t valueSize,
ValueLocation*& _location);
private: private:
struct ToDwarfRegisterMap; struct ToDwarfRegisterMap;
struct FromDwarfRegisterMap; struct FromDwarfRegisterMap;
+28 -11
View File
@@ -253,8 +253,8 @@ ThreadHandler::HandleThreadAction(uint32 action)
if (stackTrace == NULL && cpuState != NULL) { if (stackTrace == NULL && cpuState != NULL) {
if (fDebuggerInterface->GetArchitecture()->CreateStackTrace( if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
fThread->GetTeam(), this, cpuState, stackTrace, 1, false, fThread->GetTeam(), this, cpuState, stackTrace, 0, 1,
false) == B_OK) { false, false) == B_OK) {
stackTraceReference.SetTo(stackTrace, true); stackTraceReference.SetTo(stackTrace, true);
} }
} }
@@ -469,7 +469,7 @@ ThreadHandler::_DoStepOver(CpuState* cpuState)
// just single-step, otherwise we set a breakpoint after the instruction. // just single-step, otherwise we set a breakpoint after the instruction.
InstructionInfo info; InstructionInfo info;
if (fDebuggerInterface->GetArchitecture()->GetInstructionInfo( if (fDebuggerInterface->GetArchitecture()->GetInstructionInfo(
cpuState->InstructionPointer(), info) != B_OK) { cpuState->InstructionPointer(), info, cpuState) != B_OK) {
TRACE_CONTROL(" failed to get instruction info\n"); TRACE_CONTROL(" failed to get instruction info\n");
return false; return false;
} }
@@ -484,6 +484,7 @@ ThreadHandler::_DoStepOver(CpuState* cpuState)
TRACE_CONTROL(" subroutine call -- installing breakpoint at address " TRACE_CONTROL(" subroutine call -- installing breakpoint at address "
"%#" B_PRIx64 "\n", info.Address() + info.Size()); "%#" B_PRIx64 "\n", info.Address() + info.Size());
fThread->SetExecutedSubroutine(info.TargetAddress());
if (_InstallTemporaryBreakpoint(info.Address() + info.Size()) != B_OK) if (_InstallTemporaryBreakpoint(info.Address() + info.Size()) != B_OK)
return false; return false;
@@ -565,9 +566,8 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState)
if (stackTrace == NULL && cpuState != NULL) { if (stackTrace == NULL && cpuState != NULL) {
if (fDebuggerInterface->GetArchitecture()->CreateStackTrace( if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
fThread->GetTeam(), this, cpuState, stackTrace, 1, fThread->GetTeam(), this, cpuState, stackTrace, 0, 1,
false, false) false, false) == B_OK) {
== B_OK) {
stackTraceReference.SetTo(stackTrace, true); stackTraceReference.SetTo(stackTrace, true);
} }
} }
@@ -576,7 +576,7 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState)
// If we're not in the same frame we started in, // If we're not in the same frame we started in,
// keep executing. // keep executing.
if (frame != NULL && fPreviousFrameAddress if (frame != NULL && fPreviousFrameAddress
!= stackTrace->FrameAt(0)->FrameAddress()) { != frame->FrameAddress()) {
status_t error = _InstallTemporaryBreakpoint( status_t error = _InstallTemporaryBreakpoint(
cpuState->InstructionPointer()); cpuState->InstructionPointer());
if (error != B_OK) if (error != B_OK)
@@ -608,6 +608,7 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState)
// That's the return address, so we're done in theory, // That's the return address, so we're done in theory,
// unless we're a recursive function. Check if we've actually // unless we're a recursive function. Check if we've actually
// exited the previous stack frame or not. // exited the previous stack frame or not.
fThread->SetExecutedSubroutine(cpuState->InstructionPointer());
target_addr_t framePointer = cpuState->StackFramePointer(); target_addr_t framePointer = cpuState->StackFramePointer();
bool hasExitedFrame = fDebuggerInterface->GetArchitecture() bool hasExitedFrame = fDebuggerInterface->GetArchitecture()
->StackGrowthDirection() == STACK_GROWTH_DIRECTION_POSITIVE ->StackGrowthDirection() == STACK_GROWTH_DIRECTION_POSITIVE
@@ -652,9 +653,8 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState)
if (stackTrace == NULL && cpuState != NULL) { if (stackTrace == NULL && cpuState != NULL) {
if (fDebuggerInterface->GetArchitecture()->CreateStackTrace( if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
fThread->GetTeam(), this, cpuState, stackTrace, 1, fThread->GetTeam(), this, cpuState, stackTrace, 0, 1,
false, false) false, false) == B_OK) {
== B_OK) {
stackTraceReference.SetTo(stackTrace, true); stackTraceReference.SetTo(stackTrace, true);
} }
} }
@@ -680,8 +680,25 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState)
case STEP_OVER: case STEP_OVER:
{ {
// If we have stepped out of the statement, we're done. // If we have stepped out of the statement, we're done.
if (!fStepStatement->ContainsAddress(cpuState->InstructionPointer())) if (!fStepStatement->ContainsAddress(cpuState->InstructionPointer())) {
StackTrace* stackTrace = fThread->GetStackTrace();
BReference<StackTrace> stackTraceReference(stackTrace);
if (stackTrace == NULL && cpuState != NULL) {
if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
fThread->GetTeam(), this, cpuState, stackTrace, 0,
1, false, false) == B_OK) {
stackTraceReference.SetTo(stackTrace, true);
}
}
if (stackTrace != NULL && stackTrace->FrameAt(0)
->FrameAddress() != fPreviousFrameAddress) {
fThread->SetExecutedSubroutine(
cpuState->InstructionPointer());
}
return false; return false;
}
return _DoStepOver(cpuState); return _DoStepOver(cpuState);
} }
@@ -68,8 +68,8 @@ DebuggerImageDebugInfo::GetAddressSectionType(target_addr_t address)
status_t status_t
DebuggerImageDebugInfo::CreateFrame(Image* image, DebuggerImageDebugInfo::CreateFrame(Image* image,
FunctionInstance* functionInstance, CpuState* cpuState, FunctionInstance* functionInstance, CpuState* cpuState,
bool getFullFrameInfo, StackFrame*& _previousFrame, bool getFullFrameInfo, target_addr_t returnFunctionAddress,
CpuState*& _previousCpuState) StackFrame*& _previousFrame, CpuState*& _previousCpuState)
{ {
return B_UNSUPPORTED; return B_UNSUPPORTED;
} }
@@ -36,6 +36,7 @@ public:
FunctionInstance* functionInstance, FunctionInstance* functionInstance,
CpuState* cpuState, CpuState* cpuState,
bool getFullFrameInfo, bool getFullFrameInfo,
target_addr_t returnFunctionAddress,
StackFrame*& _previousFrame, StackFrame*& _previousFrame,
CpuState*& _previousCpuState); CpuState*& _previousCpuState);
virtual status_t GetStatement(FunctionDebugInfo* function, virtual status_t GetStatement(FunctionDebugInfo* function,
@@ -41,6 +41,8 @@
#include "FunctionID.h" #include "FunctionID.h"
#include "FunctionInstance.h" #include "FunctionInstance.h"
#include "GlobalTypeLookup.h" #include "GlobalTypeLookup.h"
#include "Image.h"
#include "ImageDebugInfo.h"
#include "InstructionInfo.h" #include "InstructionInfo.h"
#include "LocatableFile.h" #include "LocatableFile.h"
#include "Register.h" #include "Register.h"
@@ -51,11 +53,13 @@
#include "StringUtils.h" #include "StringUtils.h"
#include "SymbolInfo.h" #include "SymbolInfo.h"
#include "TargetAddressRangeList.h" #include "TargetAddressRangeList.h"
#include "Team.h"
#include "TeamMemory.h" #include "TeamMemory.h"
#include "Tracing.h" #include "Tracing.h"
#include "TypeLookupConstraints.h" #include "TypeLookupConstraints.h"
#include "UnsupportedLanguage.h" #include "UnsupportedLanguage.h"
#include "Variable.h" #include "Variable.h"
#include "ValueLocation.h"
namespace { namespace {
@@ -518,7 +522,8 @@ DwarfImageDebugInfo::GetAddressSectionType(target_addr_t address)
status_t status_t
DwarfImageDebugInfo::CreateFrame(Image* image, DwarfImageDebugInfo::CreateFrame(Image* image,
FunctionInstance* functionInstance, CpuState* cpuState, FunctionInstance* functionInstance, CpuState* cpuState,
bool getFullFrameInfo, StackFrame*& _frame, CpuState*& _previousCpuState) bool getFullFrameInfo, target_addr_t returnFunctionAddress,
StackFrame*& _frame, CpuState*& _previousCpuState)
{ {
DwarfFunctionDebugInfo* function = dynamic_cast<DwarfFunctionDebugInfo*>( DwarfFunctionDebugInfo* function = dynamic_cast<DwarfFunctionDebugInfo*>(
functionInstance->GetFunctionDebugInfo()); functionInstance->GetFunctionDebugInfo());
@@ -668,13 +673,14 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
instructionPointer, functionInstance->Address() - fRelocationDelta, instructionPointer, functionInstance->Address() - fRelocationDelta,
subprogramEntry->Variables(), subprogramEntry->Blocks()); subprogramEntry->Variables(), subprogramEntry->Blocks());
// determine if the previously executed instruction was a function // TODO: re-enable once PIC and false positive issues
// call to see if we need to potentially retrieve a return value // are properly dealt with
// as well #if 0
if (instructionPointer > functionInstance->Address() - fRelocationDelta) { if (returnFunctionAddress != 0) {
_CreateReturnValue(functionInstance, function, frame, _CreateReturnValue(returnFunctionAddress, image, frame,
*stackFrameDebugInfo, instructionPointer); *stackFrameDebugInfo);
} }
#endif
} }
_frame = frameReference.Detach(); _frame = frameReference.Detach();
@@ -1084,43 +1090,73 @@ DwarfImageDebugInfo::_CreateLocalVariables(CompilationUnit* unit,
status_t status_t
DwarfImageDebugInfo::_CreateReturnValue(FunctionInstance* functionInstance, DwarfImageDebugInfo::_CreateReturnValue(target_addr_t returnFunctionAddress,
DwarfFunctionDebugInfo* function, StackFrame* frame, Image* image, StackFrame* frame, DwarfStackFrameDebugInfo& factory)
DwarfStackFrameDebugInfo& factory, target_addr_t instructionPointer)
{ {
DisassembledCode* sourceCode = NULL; if (!image->ContainsAddress(returnFunctionAddress)) {
target_size_t bufferSize = std::min(functionInstance->Size(), // our current image doesn't contain the target function,
(target_size_t)64 * 1024); // locate the one which does.
void* buffer = malloc(bufferSize); image = image->GetTeam()->ImageByAddress(returnFunctionAddress);
if (buffer == NULL) if (image == NULL)
return B_NO_MEMORY; return B_BAD_VALUE;
MemoryDeleter bufferDeleter(buffer); }
ssize_t bytesRead = function->GetSpecificImageDebugInfo()
->ReadCode(functionInstance->Address(), buffer, bufferSize);
if (bytesRead < 0)
return bytesRead;
status_t result = fArchitecture->DisassembleCode(function, buffer, status_t result = B_OK;
bytesRead, sourceCode); FunctionInstance* targetFunction;
if (result != B_OK) if (returnFunctionAddress >= fPLTSectionStart
return result; && returnFunctionAddress < fPLTSectionEnd) {
// TODO: handle resolving PLT entries
// to their target function
return B_UNSUPPORTED;
}
BReference<DisassembledCode> sourceCodeReference(sourceCode, true); ImageDebugInfo* imageInfo = image->GetImageDebugInfo();
target_addr_t previousStatementAddress = instructionPointer + fRelocationDelta - 1; targetFunction = imageInfo->FunctionAtAddress(returnFunctionAddress);
Statement* statement = sourceCode->StatementAtAddress( if (targetFunction != NULL) {
previousStatementAddress); DwarfFunctionDebugInfo* targetInfo =
if (statement == NULL) dynamic_cast<DwarfFunctionDebugInfo*>(
return B_BAD_VALUE; targetFunction->GetFunctionDebugInfo());
if (targetInfo != NULL) {
DIESubprogram* subProgram = targetInfo->SubprogramEntry();
DIEType* returnType = subProgram->ReturnType();
if (returnType == NULL) {
// check if we have a specification, and if so, if that has
// a return type
subProgram = dynamic_cast<DIESubprogram*>(subProgram->Specification());
if (subProgram != NULL)
returnType = subProgram->ReturnType();
TargetAddressRange range = statement->CoveringAddressRange(); // function doesn't return a value, we're done.
InstructionInfo info; if (returnType == NULL)
if (fArchitecture->GetInstructionInfo(range.Start(), info) == B_OK return B_OK;
&& info.Type() == INSTRUCTION_TYPE_SUBROUTINE_CALL) { }
// TODO: determine where the previous instruction actually jumps to,
// retrieve that function (could potentially be in another image), uint32 byteSize = 0;
// and use its return type to retrieve the return value (will need if (returnType->ByteSize() == NULL) {
// architecture support since function return value passing convention if (dynamic_cast<DIEAddressingType*>(returnType) != NULL)
// is arch-dependent). byteSize = fArchitecture->AddressSize();
} else
byteSize = returnType->ByteSize()->constant;
ValueLocation* location;
result = fArchitecture->GetReturnAddressLocation(frame,
byteSize, location);
if (result != B_OK)
return result;
BReference<ValueLocation> locationReference(location, true);
Variable* variable = NULL;
BReference<FunctionID> idReference(
targetFunction->GetFunctionID(), true);
result = factory.CreateReturnValue(idReference, returnType,
location, variable);
if (result != B_OK)
return result;
BReference<Variable> variableReference(variable, true);
if (!frame->AddLocalVariable(variable))
return B_NO_MEMORY;
}
} }
return B_OK; return B_OK;
@@ -64,6 +64,7 @@ public:
FunctionInstance* functionInstance, FunctionInstance* functionInstance,
CpuState* cpuState, CpuState* cpuState,
bool getFullFrameInfo, bool getFullFrameInfo,
target_addr_t returnFunctionAddress,
StackFrame*& _frame, StackFrame*& _frame,
CpuState*& _previousCpuState); CpuState*& _previousCpuState);
virtual status_t GetStatement(FunctionDebugInfo* function, virtual status_t GetStatement(FunctionDebugInfo* function,
@@ -103,11 +104,11 @@ private:
const EntryListWrapper& variableEntries, const EntryListWrapper& variableEntries,
const EntryListWrapper& blockEntries); const EntryListWrapper& blockEntries);
status_t _CreateReturnValue(FunctionInstance* instance, status_t _CreateReturnValue(
DwarfFunctionDebugInfo* info, target_addr_t returnFunctionAddress,
Image* image,
StackFrame* frame, StackFrame* frame,
DwarfStackFrameDebugInfo& factory, DwarfStackFrameDebugInfo& factory);
target_addr_t instructionPointer);
bool _EvaluateBaseTypeConstraints(DIEType* type, bool _EvaluateBaseTypeConstraints(DIEType* type,
const TypeLookupConstraints& constraints); const TypeLookupConstraints& constraints);
@@ -1,4 +1,5 @@
/* /*
* Copyright 2012, Rene Gollent, rene@gollent.com.
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -23,6 +24,7 @@
#include "LocalVariableID.h" #include "LocalVariableID.h"
#include "Register.h" #include "Register.h"
#include "RegisterMap.h" #include "RegisterMap.h"
#include "ReturnValueID.h"
#include "StringUtils.h" #include "StringUtils.h"
#include "Tracing.h" #include "Tracing.h"
#include "ValueLocation.h" #include "ValueLocation.h"
@@ -117,6 +119,47 @@ private:
}; };
// #pragma mark - DwarfReturnValueID
struct DwarfStackFrameDebugInfo::DwarfReturnValueID
: public ReturnValueID {
DwarfReturnValueID(FunctionID* functionID)
:
fFunctionID(functionID),
fName("(returned)")
{
fFunctionID->AcquireReference();
}
virtual ~DwarfReturnValueID()
{
fFunctionID->ReleaseReference();
}
virtual bool operator==(const ObjectID& other) const
{
const DwarfReturnValueID* returnValueID
= dynamic_cast<const DwarfReturnValueID*>(&other);
return returnValueID != NULL
&& *fFunctionID == *returnValueID->fFunctionID
&& fName == returnValueID->fName;
}
protected:
virtual uint32 ComputeHashValue() const
{
uint32 hash = fFunctionID->HashValue();
return hash * 25 + StringUtils::HashValue(fName);
}
private:
FunctionID* fFunctionID;
const BString fName;
};
// #pragma mark - DwarfStackFrameDebugInfo // #pragma mark - DwarfStackFrameDebugInfo
@@ -234,6 +277,39 @@ DwarfStackFrameDebugInfo::CreateLocalVariable(FunctionID* functionID,
} }
status_t
DwarfStackFrameDebugInfo::CreateReturnValue(FunctionID* functionID,
DIEType* returnType, ValueLocation* location, Variable*& _variable)
{
if (returnType == NULL)
return B_BAD_VALUE;
// create the type
DwarfType* type;
status_t error = fTypeFactory->CreateType(returnType, type);
if (error != B_OK)
return error;
BReference<DwarfType> typeReference(type, true);
DwarfReturnValueID* id = new(std::nothrow) DwarfReturnValueID(
functionID);
if (id == NULL)
return B_NO_MEMORY;
BString name;
name.SetToFormat("%s returned", functionID->FunctionName().String());
Variable* variable = new(std::nothrow) Variable(id, name,
type, location);
if (variable == NULL)
return B_NO_MEMORY;
_variable = variable;
return B_OK;
}
status_t status_t
DwarfStackFrameDebugInfo::_CreateVariable(ObjectID* id, const BString& name, DwarfStackFrameDebugInfo::_CreateVariable(ObjectID* id, const BString& name,
DIEType* typeEntry, LocationDescription* locationDescription, DIEType* typeEntry, LocationDescription* locationDescription,
@@ -1,4 +1,5 @@
/* /*
* Copyright 2012, Rene Gollent, rene@gollent.com.
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -56,10 +57,16 @@ public:
DIEVariable* variableEntry, DIEVariable* variableEntry,
Variable*& _variable); Variable*& _variable);
// returns reference // returns reference
status_t CreateReturnValue(FunctionID* functionID,
DIEType* returnType,
ValueLocation* location,
Variable*& _variable);
// returns reference
private: private:
struct DwarfFunctionParameterID; struct DwarfFunctionParameterID;
struct DwarfLocalVariableID; struct DwarfLocalVariableID;
struct DwarfReturnValueID;
private: private:
status_t _CreateVariable(ObjectID* id, status_t _CreateVariable(ObjectID* id,
@@ -56,6 +56,7 @@ public:
FunctionInstance* functionInstance, FunctionInstance* functionInstance,
CpuState* cpuState, CpuState* cpuState,
bool getFullFrameInfo, bool getFullFrameInfo,
target_addr_t returnFunctionAddress,
StackFrame*& _Frame, StackFrame*& _Frame,
CpuState*& _previousCpuState) = 0; CpuState*& _previousCpuState) = 0;
// returns reference to previous frame // returns reference to previous frame
+13
View File
@@ -0,0 +1,13 @@
/*
* Copyright 2012, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
#include "ReturnValueID.h"
ReturnValueID::~ReturnValueID()
{
}
+18
View File
@@ -0,0 +1,18 @@
/*
* Copyright 2012, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
#ifndef RETURN_VALUE_ID_H
#define RETURN_VALUE_ID_H
#include "ObjectID.h"
class ReturnValueID : public ObjectID {
public:
virtual ~ReturnValueID();
};
#endif // RETURN_VALUE_ID_H
+2 -1
View File
@@ -58,7 +58,8 @@ GetStackTraceJob::Do()
// get the stack trace // get the stack trace
StackTrace* stackTrace; StackTrace* stackTrace;
status_t error = fArchitecture->CreateStackTrace(fThread->GetTeam(), this, status_t error = fArchitecture->CreateStackTrace(fThread->GetTeam(), this,
fCpuState, stackTrace); fCpuState, stackTrace, fThread->ExecutedSubroutine()
? fThread->SubroutineAddress() : 0);
if (error != B_OK) if (error != B_OK)
return error; return error;
BReference<StackTrace> stackTraceReference(stackTrace, true); BReference<StackTrace> stackTraceReference(stackTrace, true);
+13
View File
@@ -17,6 +17,8 @@ Thread::Thread(Team* team, thread_id threadID)
fTeam(team), fTeam(team),
fID(threadID), fID(threadID),
fState(THREAD_STATE_UNKNOWN), fState(THREAD_STATE_UNKNOWN),
fExecutedSubroutine(false),
fSubroutineAddress(0),
fStoppedReason(THREAD_STOPPED_UNKNOWN), fStoppedReason(THREAD_STOPPED_UNKNOWN),
fCpuState(NULL), fCpuState(NULL),
fStackTrace(NULL) fStackTrace(NULL)
@@ -68,6 +70,8 @@ Thread::SetState(uint32 state, uint32 reason, const BString& info)
if (fState != THREAD_STATE_STOPPED) { if (fState != THREAD_STATE_STOPPED) {
SetCpuState(NULL); SetCpuState(NULL);
SetStackTrace(NULL); SetStackTrace(NULL);
fExecutedSubroutine = false;
fSubroutineAddress = 0;
} }
fTeam->NotifyThreadStateChanged(this); fTeam->NotifyThreadStateChanged(this);
@@ -108,3 +112,12 @@ Thread::SetStackTrace(StackTrace* trace)
fTeam->NotifyThreadStackTraceChanged(this); fTeam->NotifyThreadStackTraceChanged(this);
} }
void
Thread::SetExecutedSubroutine(target_addr_t address)
{
fExecutedSubroutine = true;
fSubroutineAddress = address;
}
+10
View File
@@ -11,6 +11,8 @@
#include <Referenceable.h> #include <Referenceable.h>
#include <util/DoublyLinkedList.h> #include <util/DoublyLinkedList.h>
#include "types/Types.h"
class CpuState; class CpuState;
class StackTrace; class StackTrace;
@@ -67,11 +69,19 @@ public:
StackTrace* GetStackTrace() const { return fStackTrace; } StackTrace* GetStackTrace() const { return fStackTrace; }
void SetStackTrace(StackTrace* trace); void SetStackTrace(StackTrace* trace);
bool ExecutedSubroutine() const
{ return fExecutedSubroutine; }
target_addr_t SubroutineAddress() const
{ return fSubroutineAddress; }
void SetExecutedSubroutine(target_addr_t address);
private: private:
Team* fTeam; Team* fTeam;
thread_id fID; thread_id fID;
BString fName; BString fName;
uint32 fState; uint32 fState;
bool fExecutedSubroutine;
target_addr_t fSubroutineAddress;
uint32 fStoppedReason; uint32 fStoppedReason;
BString fStoppedReasonInfo; BString fStoppedReasonInfo;
CpuState* fCpuState; CpuState* fCpuState;
+2
View File
@@ -302,6 +302,8 @@ TBarApp::InitSettings()
theDir.CreateFile(settingsFileName, fSettingsFile); theDir.CreateFile(settingsFileName, fSettingsFile);
} }
filePath = dirPath;
filePath.Append(clockSettingsFileName);
fClockSettingsFile = new BFile(filePath.Path(), O_RDWR); fClockSettingsFile = new BFile(filePath.Path(), O_RDWR);
if (fClockSettingsFile->InitCheck() != B_OK) { if (fClockSettingsFile->InitCheck() != B_OK) {
BDirectory theDir(dirPath.Path()); BDirectory theDir(dirPath.Path());
+15 -15
View File
@@ -21,9 +21,9 @@
#include "AntialiasingSettingsView.h" #include "AntialiasingSettingsView.h"
#include "APRView.h" #include "APRView.h"
#include "LookAndFeelSettingsView.h"
#include "defs.h" #include "defs.h"
#include "FontView.h" #include "FontView.h"
#include "LookAndFeelSettingsView.h"
#undef B_TRANSLATION_CONTEXT #undef B_TRANSLATION_CONTEXT
@@ -50,19 +50,19 @@ APRWindow::APRWindow(BRect frame)
BTabView* tabView = new BTabView("tabview", B_WIDTH_FROM_LABEL); BTabView* tabView = new BTabView("tabview", B_WIDTH_FROM_LABEL);
fLookAndFeelSettings = new LookAndFeelSettingsView(
B_TRANSLATE("Look and feel"));
fFontSettings = new FontView(B_TRANSLATE("Fonts")); fFontSettings = new FontView(B_TRANSLATE("Fonts"));
fColorsView = new APRView(B_TRANSLATE("Colors")); fColorsView = new APRView(B_TRANSLATE("Colors"));
fLookAndFeelSettings = new LookAndFeelSettingsView(
B_TRANSLATE("Look and feel"));
fAntialiasingSettings = new AntialiasingSettingsView( fAntialiasingSettings = new AntialiasingSettingsView(
B_TRANSLATE("Antialiasing")); B_TRANSLATE("Antialiasing"));
tabView->AddTab(fLookAndFeelSettings);
tabView->AddTab(fFontSettings); tabView->AddTab(fFontSettings);
tabView->AddTab(fColorsView); tabView->AddTab(fColorsView);
tabView->AddTab(fLookAndFeelSettings);
tabView->AddTab(fAntialiasingSettings); tabView->AddTab(fAntialiasingSettings);
_UpdateButtons(); _UpdateButtons();
@@ -91,8 +91,8 @@ APRWindow::MessageReceived(BMessage *message)
case kMsgSetDefaults: case kMsgSetDefaults:
fFontSettings->SetDefaults(); fFontSettings->SetDefaults();
fColorsView->SetDefaults(); fColorsView->SetDefaults();
fAntialiasingSettings->SetDefaults();
fLookAndFeelSettings->SetDefaults(); fLookAndFeelSettings->SetDefaults();
fAntialiasingSettings->SetDefaults();
_UpdateButtons(); _UpdateButtons();
break; break;
@@ -100,8 +100,8 @@ APRWindow::MessageReceived(BMessage *message)
case kMsgRevert: case kMsgRevert:
fColorsView->Revert(); fColorsView->Revert();
fAntialiasingSettings->Revert(); fAntialiasingSettings->Revert();
fFontSettings->Revert();
fLookAndFeelSettings->Revert(); fLookAndFeelSettings->Revert();
fFontSettings->Revert();
_UpdateButtons(); _UpdateButtons();
break; break;
@@ -128,10 +128,10 @@ APRWindow::_IsDefaultable() const
// printf("colors defaultable: %d\n", fColorsView->IsDefaultable()); // printf("colors defaultable: %d\n", fColorsView->IsDefaultable());
// printf("AA defaultable: %d\n", fAntialiasingSettings->IsDefaultable()); // printf("AA defaultable: %d\n", fAntialiasingSettings->IsDefaultable());
// printf("decor defaultable: %d\n", fLookAndFeelSettings->IsDefaultable()); // printf("decor defaultable: %d\n", fLookAndFeelSettings->IsDefaultable());
return fColorsView->IsDefaultable() return fFontSettings->IsDefaultable()
|| fFontSettings->IsDefaultable() || fColorsView->IsDefaultable()
|| fAntialiasingSettings->IsDefaultable() || fLookAndFeelSettings->IsDefaultable()
|| fLookAndFeelSettings->IsDefaultable(); || fAntialiasingSettings->IsDefaultable();
} }
@@ -142,8 +142,8 @@ APRWindow::_IsRevertable() const
// printf("colors revertable: %d\n", fColorsView->IsRevertable()); // printf("colors revertable: %d\n", fColorsView->IsRevertable());
// printf("AA revertable: %d\n", fAntialiasingSettings->IsRevertable()); // printf("AA revertable: %d\n", fAntialiasingSettings->IsRevertable());
// printf("decor revertable: %d\n", fLookAndFeelSettings->IsRevertable()); // printf("decor revertable: %d\n", fLookAndFeelSettings->IsRevertable());
return fColorsView->IsRevertable() return fFontSettings->IsRevertable()
|| fFontSettings->IsRevertable() || fColorsView->IsRevertable()
|| fAntialiasingSettings->IsRevertable() || fLookAndFeelSettings->IsRevertable()
|| fLookAndFeelSettings->IsRevertable(); || fAntialiasingSettings->IsRevertable();
} }