From e71af5ae6c95d8936efeb5f46640136819e57025 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Mon, 31 Dec 2012 16:35:22 -0600 Subject: [PATCH 01/12] intel_extreme: Add RC6 downclocking support * Generation 6 (SandyBridge) and later support automatic downclocking of the GPU offering substantial battery use reductions. * As we're playing with fire here, only use on mobile devices SandyBridge or later. * This is testing stable on my SandyBridge laptop, however I need further confirmation of the functionality of this. * Move clock gating into a function in the power.cpp file --- .../drivers/graphics/intel_extreme/Jamfile | 2 +- .../graphics/intel_extreme/intel_extreme.cpp | 43 +---- .../drivers/graphics/intel_extreme/power.cpp | 175 ++++++++++++++++++ .../drivers/graphics/intel_extreme/power.h | 121 ++++++++++++ 4 files changed, 305 insertions(+), 36 deletions(-) create mode 100644 src/add-ons/kernel/drivers/graphics/intel_extreme/power.cpp create mode 100644 src/add-ons/kernel/drivers/graphics/intel_extreme/power.h diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/Jamfile b/src/add-ons/kernel/drivers/graphics/intel_extreme/Jamfile index 54e1a5e9f0..27611643cc 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/Jamfile +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/Jamfile @@ -11,9 +11,9 @@ KernelAddon intel_extreme : driver.cpp device.cpp intel_extreme.cpp + power.cpp kernel_cpp.cpp - : libgraphicscommon.a ; diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp index 462976a998..a6a8c81178 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp @@ -10,16 +10,16 @@ #include "intel_extreme.h" #include "AreaKeeper.h" -#include "driver.h" -#include "utility.h" - #include #include #include #include - #include #include +#include "utility.h" + +#include "driver.h" +#include "power.h" #define TRACE_INTELEXTREME @@ -296,38 +296,11 @@ intel_extreme_init(intel_info &info) primary.offset = (addr_t)primary.base - info.aperture_base; } - // Clock gating - // 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); + // Enable clock gating + intel_en_gating(info); - 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); + // Enable automatic gpu downclocking if we can to save power + intel_en_downclock(info); // no errors, so keep areas and mappings sharedCreator.Detach(); diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/power.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/power.cpp new file mode 100644 index 0000000000..9c4f6c7e8b --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/power.cpp @@ -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, kallisti5@unixzen.com + */ + + +#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; +} \ No newline at end of file diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/power.h b/src/add-ons/kernel/drivers/graphics/intel_extreme/power.h new file mode 100644 index 0000000000..c75acef70d --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/power.h @@ -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, kallisti5@unixzen.com + */ +#ifndef _INTEL_POWER_H_ +#define _INTEL_POWER_H_ + + +#include + +#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_ */ \ No newline at end of file From eed38dfa96a8fcfdd4d01c15ff6840272f924f73 Mon Sep 17 00:00:00 2001 From: Murai Takashi Date: Mon, 31 Dec 2012 20:41:09 +0900 Subject: [PATCH 02/12] Fix initializing fClockSettingFile. Signed-off-by: Rene Gollent --- src/apps/deskbar/BarApp.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/apps/deskbar/BarApp.cpp b/src/apps/deskbar/BarApp.cpp index af7372d696..9c12a2798a 100644 --- a/src/apps/deskbar/BarApp.cpp +++ b/src/apps/deskbar/BarApp.cpp @@ -302,6 +302,8 @@ TBarApp::InitSettings() theDir.CreateFile(settingsFileName, fSettingsFile); } + filePath = dirPath; + filePath.Append(clockSettingsFileName); fClockSettingsFile = new BFile(filePath.Path(), O_RDWR); if (fClockSettingsFile->InitCheck() != B_OK) { BDirectory theDir(dirPath.Path()); From 9ede3c06e8b42ae5428b6580a0416555af4dad05 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Fri, 28 Dec 2012 22:24:40 -0500 Subject: [PATCH 03/12] Add ReturnValueID base type. --- src/apps/debugger/Jamfile | 3 ++- src/apps/debugger/ids/ReturnValueID.cpp | 13 +++++++++++++ src/apps/debugger/ids/ReturnValueID.h | 18 ++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/apps/debugger/ids/ReturnValueID.cpp create mode 100644 src/apps/debugger/ids/ReturnValueID.h diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 44c56d0a89..c2aaa66bd9 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -124,9 +124,10 @@ Application Debugger : # ids FunctionID.cpp + FunctionParameterID.cpp LocalVariableID.cpp ObjectID.cpp - FunctionParameterID.cpp + ReturnValueID.cpp # jobs GetCPUStateJob.cpp diff --git a/src/apps/debugger/ids/ReturnValueID.cpp b/src/apps/debugger/ids/ReturnValueID.cpp new file mode 100644 index 0000000000..38e6c841b7 --- /dev/null +++ b/src/apps/debugger/ids/ReturnValueID.cpp @@ -0,0 +1,13 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ + + +#include "ReturnValueID.h" + + +ReturnValueID::~ReturnValueID() +{ +} + diff --git a/src/apps/debugger/ids/ReturnValueID.h b/src/apps/debugger/ids/ReturnValueID.h new file mode 100644 index 0000000000..021a9175c9 --- /dev/null +++ b/src/apps/debugger/ids/ReturnValueID.h @@ -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 From 84ea02a0f4e9cc454dc587d7920d18bf979c19b1 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Fri, 28 Dec 2012 22:26:22 -0500 Subject: [PATCH 04/12] Extend InstructionInfo for subroutines. - InstructionInfo now also stores the destination address of subroutine call instructions. - Adjust callers. --- src/apps/debugger/arch/InstructionInfo.cpp | 10 +++++++--- src/apps/debugger/arch/InstructionInfo.h | 8 +++++++- src/apps/debugger/arch/x86/ArchitectureX86.cpp | 9 +++++++-- src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp | 5 +++-- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/apps/debugger/arch/InstructionInfo.cpp b/src/apps/debugger/arch/InstructionInfo.cpp index 03afae474e..1a48c70848 100644 --- a/src/apps/debugger/arch/InstructionInfo.cpp +++ b/src/apps/debugger/arch/InstructionInfo.cpp @@ -9,6 +9,7 @@ InstructionInfo::InstructionInfo() : fAddress(0), + fTargetAddress(0), fSize(0), fType(INSTRUCTION_TYPE_OTHER), 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, const BString& disassembledLine) : fAddress(address), + fTargetAddress(targetAddress), fSize(size), fType(type), fBreakpointAllowed(breakpointAllowed), @@ -31,11 +34,12 @@ InstructionInfo::InstructionInfo(target_addr_t address, target_size_t size, bool -InstructionInfo::SetTo(target_addr_t address, target_size_t size, - instruction_type type, bool breakpointAllowed, +InstructionInfo::SetTo(target_addr_t address, target_addr_t targetAddress, + target_size_t size, instruction_type type, bool breakpointAllowed, const BString& disassembledLine) { fAddress = address; + fTargetAddress = targetAddress; fSize = size; fType = type; fBreakpointAllowed = breakpointAllowed; diff --git a/src/apps/debugger/arch/InstructionInfo.h b/src/apps/debugger/arch/InstructionInfo.h index 36c2fa2834..f130080fb6 100644 --- a/src/apps/debugger/arch/InstructionInfo.h +++ b/src/apps/debugger/arch/InstructionInfo.h @@ -20,16 +20,21 @@ class InstructionInfo { public: InstructionInfo(); InstructionInfo(target_addr_t address, + target_addr_t targetAddress, target_size_t size, instruction_type type, bool breakpointAllowed, 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, bool breakpointAllowed, const BString& disassembledLine); target_addr_t Address() const { return fAddress; } + target_addr_t TargetAddress() const + { return fTargetAddress; } target_size_t Size() const { return fSize; } instruction_type Type() const { return fType; } bool IsBreakpointAllowed() const @@ -40,6 +45,7 @@ public: private: target_addr_t fAddress; + target_addr_t fTargetAddress; target_size_t fSize; instruction_type fType; bool fBreakpointAllowed; diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.cpp b/src/apps/debugger/arch/x86/ArchitectureX86.cpp index dd19a9012d..5eccb064c8 100644 --- a/src/apps/debugger/arch/x86/ArchitectureX86.cpp +++ b/src/apps/debugger/arch/x86/ArchitectureX86.cpp @@ -596,6 +596,7 @@ ArchitectureX86::GetInstructionInfo(target_addr_t address, // disassemble the instruction BString line; target_addr_t instructionAddress; + target_addr_t targetAddress = 0; target_size_t instructionSize; bool breakpointAllowed; error = disassembler.GetNextInstruction(line, instructionAddress, @@ -607,17 +608,21 @@ ArchitectureX86::GetInstructionInfo(target_addr_t address, if (buffer[0] == 0xff && (buffer[1] & 0x34) == 0x10) { // absolute call with r/m32 instructionType = INSTRUCTION_TYPE_SUBROUTINE_CALL; + // TODO: retrieve target address (might be in a register) } 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; + int32 offset; + memcpy(&offset, &buffer[1], 4); + targetAddress = instructionAddress + instructionSize + offset; } } - if (!_info.SetTo(instructionAddress, instructionSize, instructionType, - breakpointAllowed, line)) { + if (!_info.SetTo(instructionAddress, targetAddress, instructionSize, + instructionType, breakpointAllowed, line)) { return B_NO_MEMORY; } diff --git a/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp b/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp index 21525627e7..f32b82055f 100644 --- a/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp +++ b/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp @@ -487,6 +487,7 @@ ArchitectureX8664::GetInstructionInfo(target_addr_t address, // disassemble the instruction BString line; target_addr_t instructionAddress; + target_addr_t targetAddress = 0; target_size_t instructionSize; bool breakpointAllowed; error = disassembler.GetNextInstruction(line, instructionAddress, @@ -508,8 +509,8 @@ ArchitectureX8664::GetInstructionInfo(target_addr_t address, } } - if (!_info.SetTo(instructionAddress, instructionSize, instructionType, - breakpointAllowed, line)) { + if (!_info.SetTo(instructionAddress, targetAddress, instructionSize, + instructionType, breakpointAllowed, line)) { return B_NO_MEMORY; } From dc693e9265707e9e0c470c2ec00106795424b6dc Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Fri, 28 Dec 2012 22:27:30 -0500 Subject: [PATCH 05/12] Extend Architecture to help retrieve return values. - Architecture now has a new function to retrieve the location where a return value can be found. Added implementation for x86 and stub for x86-64. --- src/apps/debugger/arch/Architecture.h | 5 ++ .../debugger/arch/x86/ArchitectureX86.cpp | 50 ++++++++++++++++++- src/apps/debugger/arch/x86/ArchitectureX86.h | 5 ++ .../arch/x86_64/ArchitectureX8664.cpp | 7 +++ .../debugger/arch/x86_64/ArchitectureX8664.h | 4 ++ 5 files changed, 69 insertions(+), 2 deletions(-) diff --git a/src/apps/debugger/arch/Architecture.h b/src/apps/debugger/arch/Architecture.h index 38409d0a3a..748e9dc63a 100644 --- a/src/apps/debugger/arch/Architecture.h +++ b/src/apps/debugger/arch/Architecture.h @@ -30,6 +30,7 @@ class StackTrace; class Statement; class Team; class TeamMemory; +class ValueLocation; enum { @@ -118,6 +119,10 @@ public: int32& _maxBytesPerRegister, uint8& _watchpointCapabilityFlags) = 0; + virtual status_t GetReturnAddressLocation( + StackFrame* frame, target_size_t valueSize, + ValueLocation*& _location) = 0; + protected: TeamMemory* fTeamMemory; diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.cpp b/src/apps/debugger/arch/x86/ArchitectureX86.cpp index 5eccb064c8..c7995d5193 100644 --- a/src/apps/debugger/arch/x86/ArchitectureX86.cpp +++ b/src/apps/debugger/arch/x86/ArchitectureX86.cpp @@ -23,6 +23,7 @@ #include "StackFrame.h" #include "Statement.h" #include "TeamMemory.h" +#include "ValueLocation.h" #include "X86AssemblyLanguage.h" #include "disasm/DisassemblerX86.h" @@ -579,9 +580,8 @@ status_t ArchitectureX86::GetInstructionInfo(target_addr_t address, InstructionInfo& _info) { - // read the code + // read the code - maximum x86{-64} instruction size = 15 bytes uint8 buffer[16]; - // TODO: What's the maximum instruction size? ssize_t bytesRead = fTeamMemory->ReadMemory(address, buffer, sizeof(buffer)); if (bytesRead < 0) @@ -648,6 +648,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 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 ArchitectureX86::_AddRegister(int32 index, const char* name, uint32 bitSize, uint32 valueType, register_type type, bool calleePreserved) diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.h b/src/apps/debugger/arch/x86/ArchitectureX86.h index 48e849c502..1549f9bd65 100644 --- a/src/apps/debugger/arch/x86/ArchitectureX86.h +++ b/src/apps/debugger/arch/x86/ArchitectureX86.h @@ -66,6 +66,11 @@ public: int32& _maxBytesPerRegister, uint8& _watchpointCapabilityFlags); + virtual status_t GetReturnAddressLocation( + StackFrame* frame, target_size_t valueSize, + ValueLocation*& _location); + + private: struct ToDwarfRegisterMap; struct FromDwarfRegisterMap; diff --git a/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp b/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp index f32b82055f..acf2f93d31 100644 --- a/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp +++ b/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp @@ -535,6 +535,13 @@ ArchitectureX8664::GetWatchpointDebugCapabilities(int32& _maxRegisterCount, } +status_t +ArchitectureX8664::GetReturnAddressLocation(StackFrame* frame, + target_size_t valueSize, ValueLocation*& _location) { + return B_NOT_SUPPORTED; +} + + void ArchitectureX8664::_AddRegister(int32 index, const char* name, uint32 bitSize, uint32 valueType, register_type type, bool calleePreserved) diff --git a/src/apps/debugger/arch/x86_64/ArchitectureX8664.h b/src/apps/debugger/arch/x86_64/ArchitectureX8664.h index ec814483f0..f61b8f38b1 100644 --- a/src/apps/debugger/arch/x86_64/ArchitectureX8664.h +++ b/src/apps/debugger/arch/x86_64/ArchitectureX8664.h @@ -67,6 +67,10 @@ public: int32& _maxBytesPerRegister, uint8& _watchpointCapabilityFlags); + virtual status_t GetReturnAddressLocation( + StackFrame* frame, target_size_t valueSize, + ValueLocation*& _location); + private: struct ToDwarfRegisterMap; struct FromDwarfRegisterMap; From c7ca91ffd364a32a50b3b563c6978b8a94417ded Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Fri, 28 Dec 2012 22:31:28 -0500 Subject: [PATCH 06/12] Add helper functions for creating return value variables. --- .../debug_info/DwarfStackFrameDebugInfo.cpp | 76 +++++++++++++++++++ .../debug_info/DwarfStackFrameDebugInfo.h | 7 ++ 2 files changed, 83 insertions(+) diff --git a/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.cpp index 99853ae8f3..42cef634e4 100644 --- a/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.cpp @@ -1,4 +1,5 @@ /* + * Copyright 2012, Rene Gollent, rene@gollent.com. * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ @@ -23,6 +24,7 @@ #include "LocalVariableID.h" #include "Register.h" #include "RegisterMap.h" +#include "ReturnValueID.h" #include "StringUtils.h" #include "Tracing.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(&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 @@ -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 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 DwarfStackFrameDebugInfo::_CreateVariable(ObjectID* id, const BString& name, DIEType* typeEntry, LocationDescription* locationDescription, diff --git a/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h b/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h index e55d0d2ed1..3e691308f3 100644 --- a/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h +++ b/src/apps/debugger/debug_info/DwarfStackFrameDebugInfo.h @@ -1,4 +1,5 @@ /* + * Copyright 2012, Rene Gollent, rene@gollent.com. * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ @@ -56,10 +57,16 @@ public: DIEVariable* variableEntry, Variable*& _variable); // returns reference + status_t CreateReturnValue(FunctionID* functionID, + DIEType* returnType, + ValueLocation* location, + Variable*& _variable); + // returns reference private: struct DwarfFunctionParameterID; struct DwarfLocalVariableID; + struct DwarfReturnValueID; private: status_t _CreateVariable(ObjectID* id, From f733c6031a76256d7b6652267b649892a9a849f7 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Fri, 28 Dec 2012 22:31:52 -0500 Subject: [PATCH 07/12] Initial implementation of _GetReturnValue(). - Look at the destination of the subroutine instruction and try to resolve it to a function. Currently only handles functions whose destination are within the same image. - If found, look up debug info for the target function. If available, determine if it returns a value. If so, construct an appropriate placeholder variable and add it to the frame's variable list. --- .../debug_info/DwarfImageDebugInfo.cpp | 61 ++++++++++++++++--- .../debugger/debug_info/DwarfImageDebugInfo.h | 1 + 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp index c6aa3ca4ac..d8942ffe0f 100644 --- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp @@ -41,6 +41,8 @@ #include "FunctionID.h" #include "FunctionInstance.h" #include "GlobalTypeLookup.h" +#include "Image.h" +#include "ImageDebugInfo.h" #include "InstructionInfo.h" #include "LocatableFile.h" #include "Register.h" @@ -56,6 +58,7 @@ #include "TypeLookupConstraints.h" #include "UnsupportedLanguage.h" #include "Variable.h" +#include "ValueLocation.h" namespace { @@ -672,7 +675,7 @@ DwarfImageDebugInfo::CreateFrame(Image* image, // call to see if we need to potentially retrieve a return value // as well if (instructionPointer > functionInstance->Address() - fRelocationDelta) { - _CreateReturnValue(functionInstance, function, frame, + _CreateReturnValue(functionInstance, image, function, frame, *stackFrameDebugInfo, instructionPointer); } } @@ -1085,7 +1088,7 @@ DwarfImageDebugInfo::_CreateLocalVariables(CompilationUnit* unit, status_t DwarfImageDebugInfo::_CreateReturnValue(FunctionInstance* functionInstance, - DwarfFunctionDebugInfo* function, StackFrame* frame, + Image* image, DwarfFunctionDebugInfo* function, StackFrame* frame, DwarfStackFrameDebugInfo& factory, target_addr_t instructionPointer) { DisassembledCode* sourceCode = NULL; @@ -1111,16 +1114,60 @@ DwarfImageDebugInfo::_CreateReturnValue(FunctionInstance* functionInstance, previousStatementAddress); if (statement == NULL) return B_BAD_VALUE; + previousStatementAddress = statement->CoveringAddressRange().Start() - 1; + statement = sourceCode->StatementAtAddress( + previousStatementAddress); + if (statement == NULL) + return B_BAD_VALUE; TargetAddressRange range = statement->CoveringAddressRange(); InstructionInfo info; if (fArchitecture->GetInstructionInfo(range.Start(), info) == 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), - // and use its return type to retrieve the return value (will need - // architecture support since function return value passing convention - // is arch-dependent). + target_addr_t targetAddress = info.TargetAddress(); + if (targetAddress == 0) + return B_BAD_VALUE; + + if (image->ContainsAddress(targetAddress)) { + FunctionInstance* targetFunction; + if (targetAddress >= fPLTSectionStart && targetAddress < fPLTSectionEnd) { + // TODO: resolve actual target address in the PIC case + // and adjust targetAddress accordingly + } + ImageDebugInfo* imageInfo = image->GetImageDebugInfo(); + targetFunction = imageInfo->FunctionAtAddress(targetAddress); + if (targetFunction != NULL) { + DwarfFunctionDebugInfo* targetInfo = + dynamic_cast( + targetFunction->GetFunctionDebugInfo()); + if (targetInfo != NULL) { + DIESubprogram* subProgram = targetInfo->SubprogramEntry(); + DIEType* returnType = subProgram->ReturnType(); + if (returnType == NULL) { + // function doesn't return a value, we're done. + return B_OK; + } + + ValueLocation* location; + result = fArchitecture->GetReturnAddressLocation(frame, + returnType->ByteSize()->constant, location); + if (result != B_OK) + return result; + BReference locationReference(location, + true); + Variable* variable = NULL; + BReference idReference( + targetFunction->GetFunctionID(), true); + result = factory.CreateReturnValue(idReference, + returnType, location, variable); + if (result != B_OK) + return result; + BReference variableReference(variable, true); + if (!frame->AddLocalVariable(variable)) + return B_NO_MEMORY; + } + } + } } return B_OK; diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h index c03370fdea..4c9b0c1db8 100644 --- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h @@ -104,6 +104,7 @@ private: const EntryListWrapper& blockEntries); status_t _CreateReturnValue(FunctionInstance* instance, + Image* image, DwarfFunctionDebugInfo* info, StackFrame* frame, DwarfStackFrameDebugInfo& factory, From cf2e209b2d15a1a39560260cfba7355303ef91ac Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Sat, 29 Dec 2012 22:43:34 -0500 Subject: [PATCH 08/12] More improvements to return value handling. - Thread now has a data member indicating if a subroutine was executed during the last set of steps. - ThreadHandler now sets the aforementioned state appropriate during Step Over/Step Out. - Architecture::CreateStackTrace() now takes a parameter indicating whether return value retrieval is desired (based on aforementioned thread value). Adjust callers accordingly. - DwarfImageDebugInfo: If return value retrieval is requested, loop backwards from the current IP to find the call instruction. --- src/apps/debugger/arch/Architecture.cpp | 7 +- src/apps/debugger/arch/Architecture.h | 1 + .../debugger/controllers/ThreadHandler.cpp | 36 ++++-- .../debug_info/DebuggerImageDebugInfo.cpp | 2 +- .../debug_info/DebuggerImageDebugInfo.h | 1 + .../debug_info/DwarfImageDebugInfo.cpp | 120 ++++++++++-------- .../debugger/debug_info/DwarfImageDebugInfo.h | 1 + .../debug_info/SpecificImageDebugInfo.h | 1 + src/apps/debugger/jobs/GetStackTraceJob.cpp | 2 +- src/apps/debugger/model/Thread.cpp | 10 ++ src/apps/debugger/model/Thread.h | 5 + 11 files changed, 119 insertions(+), 67 deletions(-) diff --git a/src/apps/debugger/arch/Architecture.cpp b/src/apps/debugger/arch/Architecture.cpp index 01b39992e5..4da06410f2 100644 --- a/src/apps/debugger/arch/Architecture.cpp +++ b/src/apps/debugger/arch/Architecture.cpp @@ -94,8 +94,8 @@ Architecture::InitRegisterRules(CfaContext& context) const status_t Architecture::CreateStackTrace(Team* team, ImageDebugInfoProvider* imageInfoProvider, CpuState* cpuState, - StackTrace*& _stackTrace, int32 maxStackDepth, bool useExistingTrace, - bool getFullFrameInfo) + StackTrace*& _stackTrace, bool getReturnValue, int32 maxStackDepth, + bool useExistingTrace, bool getFullFrameInfo) { BReference cpuStateReference(cpuState); @@ -163,7 +163,8 @@ Architecture::CreateStackTrace(Team* team, if (function != NULL) { status_t error = functionDebugInfo->GetSpecificImageDebugInfo() ->CreateFrame(image, function, cpuState, getFullFrameInfo, - frame, previousCpuState); + nextFrame == NULL ? getReturnValue : false, frame, + previousCpuState); if (error != B_OK && error != B_UNSUPPORTED) break; } diff --git a/src/apps/debugger/arch/Architecture.h b/src/apps/debugger/arch/Architecture.h index 748e9dc63a..3ab3f7daa4 100644 --- a/src/apps/debugger/arch/Architecture.h +++ b/src/apps/debugger/arch/Architecture.h @@ -109,6 +109,7 @@ public: ImageDebugInfoProvider* imageInfoProvider, CpuState* cpuState, StackTrace*& _stackTrace, + bool getReturnValue, int32 maxStackDepth = -1, bool useExistingTrace = false, bool getFullFrameInfo = true); diff --git a/src/apps/debugger/controllers/ThreadHandler.cpp b/src/apps/debugger/controllers/ThreadHandler.cpp index f9161060a2..7913da930f 100644 --- a/src/apps/debugger/controllers/ThreadHandler.cpp +++ b/src/apps/debugger/controllers/ThreadHandler.cpp @@ -253,8 +253,8 @@ ThreadHandler::HandleThreadAction(uint32 action) if (stackTrace == NULL && cpuState != NULL) { if (fDebuggerInterface->GetArchitecture()->CreateStackTrace( - fThread->GetTeam(), this, cpuState, stackTrace, 1, false, - false) == B_OK) { + fThread->GetTeam(), this, cpuState, stackTrace, false, 1, + false, false) == B_OK) { stackTraceReference.SetTo(stackTrace, true); } } @@ -484,6 +484,7 @@ ThreadHandler::_DoStepOver(CpuState* cpuState) TRACE_CONTROL(" subroutine call -- installing breakpoint at address " "%#" B_PRIx64 "\n", info.Address() + info.Size()); + fThread->SetExecutedSubroutine(); if (_InstallTemporaryBreakpoint(info.Address() + info.Size()) != B_OK) return false; @@ -565,9 +566,8 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState) if (stackTrace == NULL && cpuState != NULL) { if (fDebuggerInterface->GetArchitecture()->CreateStackTrace( - fThread->GetTeam(), this, cpuState, stackTrace, 1, - false, false) - == B_OK) { + fThread->GetTeam(), this, cpuState, stackTrace, false, + 1, false, false) == B_OK) { stackTraceReference.SetTo(stackTrace, true); } } @@ -576,7 +576,7 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState) // If we're not in the same frame we started in, // keep executing. if (frame != NULL && fPreviousFrameAddress - != stackTrace->FrameAt(0)->FrameAddress()) { + != frame->FrameAddress()) { status_t error = _InstallTemporaryBreakpoint( cpuState->InstructionPointer()); if (error != B_OK) @@ -608,6 +608,7 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState) // That's the return address, so we're done in theory, // unless we're a recursive function. Check if we've actually // exited the previous stack frame or not. + fThread->SetExecutedSubroutine(); target_addr_t framePointer = cpuState->StackFramePointer(); bool hasExitedFrame = fDebuggerInterface->GetArchitecture() ->StackGrowthDirection() == STACK_GROWTH_DIRECTION_POSITIVE @@ -652,9 +653,8 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState) if (stackTrace == NULL && cpuState != NULL) { if (fDebuggerInterface->GetArchitecture()->CreateStackTrace( - fThread->GetTeam(), this, cpuState, stackTrace, 1, - false, false) - == B_OK) { + fThread->GetTeam(), this, cpuState, stackTrace, false, + 1, false, false) == B_OK) { stackTraceReference.SetTo(stackTrace, true); } } @@ -680,8 +680,24 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState) case STEP_OVER: { // 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 stackTraceReference(stackTrace); + if (stackTrace == NULL && cpuState != NULL) { + if (fDebuggerInterface->GetArchitecture()->CreateStackTrace( + fThread->GetTeam(), this, cpuState, stackTrace, false, + 1, false, false) == B_OK) { + stackTraceReference.SetTo(stackTrace, true); + } + } + + if (stackTrace != NULL && stackTrace->FrameAt(0) + ->FrameAddress() != fPreviousFrameAddress) { + fThread->SetExecutedSubroutine(); + } + return false; + } return _DoStepOver(cpuState); } diff --git a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp index da467da3b0..1ff7ac88e0 100644 --- a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp @@ -68,7 +68,7 @@ DebuggerImageDebugInfo::GetAddressSectionType(target_addr_t address) status_t DebuggerImageDebugInfo::CreateFrame(Image* image, FunctionInstance* functionInstance, CpuState* cpuState, - bool getFullFrameInfo, StackFrame*& _previousFrame, + bool getFullFrameInfo, bool getReturnValue, StackFrame*& _previousFrame, CpuState*& _previousCpuState) { return B_UNSUPPORTED; diff --git a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h index 8c0c520160..981dbd8f46 100644 --- a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h +++ b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h @@ -36,6 +36,7 @@ public: FunctionInstance* functionInstance, CpuState* cpuState, bool getFullFrameInfo, + bool getReturnValue, StackFrame*& _previousFrame, CpuState*& _previousCpuState); virtual status_t GetStatement(FunctionDebugInfo* function, diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp index d8942ffe0f..c7448e05e8 100644 --- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp @@ -53,6 +53,7 @@ #include "StringUtils.h" #include "SymbolInfo.h" #include "TargetAddressRangeList.h" +#include "Team.h" #include "TeamMemory.h" #include "Tracing.h" #include "TypeLookupConstraints.h" @@ -521,7 +522,8 @@ DwarfImageDebugInfo::GetAddressSectionType(target_addr_t address) status_t DwarfImageDebugInfo::CreateFrame(Image* image, FunctionInstance* functionInstance, CpuState* cpuState, - bool getFullFrameInfo, StackFrame*& _frame, CpuState*& _previousCpuState) + bool getFullFrameInfo, bool getReturnValue, StackFrame*& _frame, + CpuState*& _previousCpuState) { DwarfFunctionDebugInfo* function = dynamic_cast( functionInstance->GetFunctionDebugInfo()); @@ -671,10 +673,7 @@ DwarfImageDebugInfo::CreateFrame(Image* image, instructionPointer, functionInstance->Address() - fRelocationDelta, subprogramEntry->Variables(), subprogramEntry->Blocks()); - // determine if the previously executed instruction was a function - // call to see if we need to potentially retrieve a return value - // as well - if (instructionPointer > functionInstance->Address() - fRelocationDelta) { + if (getReturnValue) { _CreateReturnValue(functionInstance, image, function, frame, *stackFrameDebugInfo, instructionPointer); } @@ -1091,6 +1090,8 @@ DwarfImageDebugInfo::_CreateReturnValue(FunctionInstance* functionInstance, Image* image, DwarfFunctionDebugInfo* function, StackFrame* frame, DwarfStackFrameDebugInfo& factory, target_addr_t instructionPointer) { + // the thread just executed a subroutine, look for the last call + // instruction. DisassembledCode* sourceCode = NULL; target_size_t bufferSize = std::min(functionInstance->Size(), (target_size_t)64 * 1024); @@ -1114,59 +1115,74 @@ DwarfImageDebugInfo::_CreateReturnValue(FunctionInstance* functionInstance, previousStatementAddress); if (statement == NULL) return B_BAD_VALUE; - previousStatementAddress = statement->CoveringAddressRange().Start() - 1; - statement = sourceCode->StatementAtAddress( - previousStatementAddress); - if (statement == NULL) + + InstructionInfo info; + do { + TargetAddressRange range = statement->CoveringAddressRange(); + result = fArchitecture->GetInstructionInfo(range.Start(), info); + if (result != B_OK) + return result; + + if (info.Type() == INSTRUCTION_TYPE_SUBROUTINE_CALL) + break; + + previousStatementAddress = statement->CoveringAddressRange().Start() - 1; + statement = sourceCode->StatementAtAddress( + previousStatementAddress); + } while (statement != NULL); + + // we weren't able to find a subroutine call by stepping back + // so we can't retrieve a return value + if (info.Type() != INSTRUCTION_TYPE_SUBROUTINE_CALL) + return B_OK; + + target_addr_t targetAddress = info.TargetAddress(); + if (targetAddress == 0) return B_BAD_VALUE; - TargetAddressRange range = statement->CoveringAddressRange(); - InstructionInfo info; - if (fArchitecture->GetInstructionInfo(range.Start(), info) == B_OK - && info.Type() == INSTRUCTION_TYPE_SUBROUTINE_CALL) { - target_addr_t targetAddress = info.TargetAddress(); - if (targetAddress == 0) + if (!image->ContainsAddress(targetAddress)) { + // our current image doesn't contain the target function, + // locate the one which does. + image = image->GetTeam()->ImageByAddress(targetAddress); + if (image == NULL) return B_BAD_VALUE; + } - if (image->ContainsAddress(targetAddress)) { - FunctionInstance* targetFunction; - if (targetAddress >= fPLTSectionStart && targetAddress < fPLTSectionEnd) { - // TODO: resolve actual target address in the PIC case - // and adjust targetAddress accordingly + FunctionInstance* targetFunction; + if (targetAddress >= fPLTSectionStart && targetAddress < fPLTSectionEnd) { + // TODO: resolve actual target address in the PIC case + // and adjust targetAddress accordingly + } + ImageDebugInfo* imageInfo = image->GetImageDebugInfo(); + targetFunction = imageInfo->FunctionAtAddress(targetAddress); + if (targetFunction != NULL) { + DwarfFunctionDebugInfo* targetInfo = + dynamic_cast( + targetFunction->GetFunctionDebugInfo()); + if (targetInfo != NULL) { + DIESubprogram* subProgram = targetInfo->SubprogramEntry(); + DIEType* returnType = subProgram->ReturnType(); + if (returnType == NULL) { + // function doesn't return a value, we're done. + return B_OK; } - ImageDebugInfo* imageInfo = image->GetImageDebugInfo(); - targetFunction = imageInfo->FunctionAtAddress(targetAddress); - if (targetFunction != NULL) { - DwarfFunctionDebugInfo* targetInfo = - dynamic_cast( - targetFunction->GetFunctionDebugInfo()); - if (targetInfo != NULL) { - DIESubprogram* subProgram = targetInfo->SubprogramEntry(); - DIEType* returnType = subProgram->ReturnType(); - if (returnType == NULL) { - // function doesn't return a value, we're done. - return B_OK; - } - ValueLocation* location; - result = fArchitecture->GetReturnAddressLocation(frame, - returnType->ByteSize()->constant, location); - if (result != B_OK) - return result; - BReference locationReference(location, - true); - Variable* variable = NULL; - BReference idReference( - targetFunction->GetFunctionID(), true); - result = factory.CreateReturnValue(idReference, - returnType, location, variable); - if (result != B_OK) - return result; - BReference variableReference(variable, true); - if (!frame->AddLocalVariable(variable)) - return B_NO_MEMORY; - } - } + ValueLocation* location; + result = fArchitecture->GetReturnAddressLocation(frame, + returnType->ByteSize()->constant, location); + if (result != B_OK) + return result; + BReference locationReference(location, true); + Variable* variable = NULL; + BReference idReference( + targetFunction->GetFunctionID(), true); + result = factory.CreateReturnValue(idReference, returnType, + location, variable); + if (result != B_OK) + return result; + BReference variableReference(variable, true); + if (!frame->AddLocalVariable(variable)) + return B_NO_MEMORY; } } diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h index 4c9b0c1db8..56cd1c13a6 100644 --- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h @@ -64,6 +64,7 @@ public: FunctionInstance* functionInstance, CpuState* cpuState, bool getFullFrameInfo, + bool getReturnValue, StackFrame*& _frame, CpuState*& _previousCpuState); virtual status_t GetStatement(FunctionDebugInfo* function, diff --git a/src/apps/debugger/debug_info/SpecificImageDebugInfo.h b/src/apps/debugger/debug_info/SpecificImageDebugInfo.h index 7287964ce5..4d424638f5 100644 --- a/src/apps/debugger/debug_info/SpecificImageDebugInfo.h +++ b/src/apps/debugger/debug_info/SpecificImageDebugInfo.h @@ -56,6 +56,7 @@ public: FunctionInstance* functionInstance, CpuState* cpuState, bool getFullFrameInfo, + bool getReturnValue, StackFrame*& _Frame, CpuState*& _previousCpuState) = 0; // returns reference to previous frame diff --git a/src/apps/debugger/jobs/GetStackTraceJob.cpp b/src/apps/debugger/jobs/GetStackTraceJob.cpp index 61a1c724d8..2f08190f99 100644 --- a/src/apps/debugger/jobs/GetStackTraceJob.cpp +++ b/src/apps/debugger/jobs/GetStackTraceJob.cpp @@ -58,7 +58,7 @@ GetStackTraceJob::Do() // get the stack trace StackTrace* stackTrace; status_t error = fArchitecture->CreateStackTrace(fThread->GetTeam(), this, - fCpuState, stackTrace); + fCpuState, stackTrace, fThread->ExecutedSubroutine()); if (error != B_OK) return error; BReference stackTraceReference(stackTrace, true); diff --git a/src/apps/debugger/model/Thread.cpp b/src/apps/debugger/model/Thread.cpp index c6692f89e5..f289bca440 100644 --- a/src/apps/debugger/model/Thread.cpp +++ b/src/apps/debugger/model/Thread.cpp @@ -17,6 +17,7 @@ Thread::Thread(Team* team, thread_id threadID) fTeam(team), fID(threadID), fState(THREAD_STATE_UNKNOWN), + fExecutedSubroutine(false), fStoppedReason(THREAD_STOPPED_UNKNOWN), fCpuState(NULL), fStackTrace(NULL) @@ -68,6 +69,7 @@ Thread::SetState(uint32 state, uint32 reason, const BString& info) if (fState != THREAD_STATE_STOPPED) { SetCpuState(NULL); SetStackTrace(NULL); + fExecutedSubroutine = false; } fTeam->NotifyThreadStateChanged(this); @@ -108,3 +110,11 @@ Thread::SetStackTrace(StackTrace* trace) fTeam->NotifyThreadStackTraceChanged(this); } + + +void +Thread::SetExecutedSubroutine() +{ + fExecutedSubroutine = true; +} + diff --git a/src/apps/debugger/model/Thread.h b/src/apps/debugger/model/Thread.h index e34064fffd..8ac086192d 100644 --- a/src/apps/debugger/model/Thread.h +++ b/src/apps/debugger/model/Thread.h @@ -67,11 +67,16 @@ public: StackTrace* GetStackTrace() const { return fStackTrace; } void SetStackTrace(StackTrace* trace); + bool ExecutedSubroutine() const + { return fExecutedSubroutine; } + void SetExecutedSubroutine(); + private: Team* fTeam; thread_id fID; BString fName; uint32 fState; + bool fExecutedSubroutine; uint32 fStoppedReason; BString fStoppedReasonInfo; CpuState* fCpuState; From bdbbc10b44c078b1738588d1a1b62ed1325dcd96 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Mon, 31 Dec 2012 22:52:34 -0500 Subject: [PATCH 09/12] Thread now also tracks the address of the last executed function. --- src/apps/debugger/model/Thread.cpp | 5 ++++- src/apps/debugger/model/Thread.h | 7 ++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/apps/debugger/model/Thread.cpp b/src/apps/debugger/model/Thread.cpp index f289bca440..63d21e036f 100644 --- a/src/apps/debugger/model/Thread.cpp +++ b/src/apps/debugger/model/Thread.cpp @@ -18,6 +18,7 @@ Thread::Thread(Team* team, thread_id threadID) fID(threadID), fState(THREAD_STATE_UNKNOWN), fExecutedSubroutine(false), + fSubroutineAddress(0), fStoppedReason(THREAD_STOPPED_UNKNOWN), fCpuState(NULL), fStackTrace(NULL) @@ -70,6 +71,7 @@ Thread::SetState(uint32 state, uint32 reason, const BString& info) SetCpuState(NULL); SetStackTrace(NULL); fExecutedSubroutine = false; + fSubroutineAddress = 0; } fTeam->NotifyThreadStateChanged(this); @@ -113,8 +115,9 @@ Thread::SetStackTrace(StackTrace* trace) void -Thread::SetExecutedSubroutine() +Thread::SetExecutedSubroutine(target_addr_t address) { fExecutedSubroutine = true; + fSubroutineAddress = address; } diff --git a/src/apps/debugger/model/Thread.h b/src/apps/debugger/model/Thread.h index 8ac086192d..1cba07ff0c 100644 --- a/src/apps/debugger/model/Thread.h +++ b/src/apps/debugger/model/Thread.h @@ -11,6 +11,8 @@ #include #include +#include "types/Types.h" + class CpuState; class StackTrace; @@ -69,7 +71,9 @@ public: bool ExecutedSubroutine() const { return fExecutedSubroutine; } - void SetExecutedSubroutine(); + target_addr_t SubroutineAddress() const + { return fSubroutineAddress; } + void SetExecutedSubroutine(target_addr_t address); private: Team* fTeam; @@ -77,6 +81,7 @@ private: BString fName; uint32 fState; bool fExecutedSubroutine; + target_addr_t fSubroutineAddress; uint32 fStoppedReason; BString fStoppedReasonInfo; CpuState* fCpuState; From 5745a40dd1813a745fc4b899862597c3f618ef6c Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Mon, 31 Dec 2012 22:54:39 -0500 Subject: [PATCH 10/12] Rework how return values are handled. - ArchitectureX86 now hands off the work for GetInstructionInfo() to DisassemblerX86, since the latter has all the information we need to properly classify and evaluate instructions. Correspondingly a CpuState is passed down to it in order to perform address calculations for the instruction if it's a jump or call instruction. The latter's targets are then stored on the thread for later retrieval when constructing a stack trace. Adjust X86_64 accordingly for the signature changes. This also fixes a bug where Step Over would sometimes result in a Step Into instead due to the previous implementation of GetInstructionInfo() occasionally failing to classify call instructions correctly. - Architecture::CreateStackTrace() now takes an argument specifying the address of the last executed function if applicable. This is used to decide who/where to decode a return value from. Adjust callers. - DwarfImageDebugInfo::_CreateReturnValue() uses the above information in order to know directly who the caller it needs to look up a return value for is, rather than trying to walk backwards to find them. Type resolution is now also a bit more sophisticated due to various cases where the subprogram entry didn't directly contain the return type but referred to another DIE that did. Retrieving return value now appears to work properly in all cases except when position independent code is involved. The latter however will require resolving the appropriate function address in the PLT, which will need some additional work. --- src/apps/debugger/arch/Architecture.cpp | 6 +- src/apps/debugger/arch/Architecture.h | 5 +- src/apps/debugger/arch/InstructionInfo.h | 1 + .../debugger/arch/x86/ArchitectureX86.cpp | 39 +----- src/apps/debugger/arch/x86/ArchitectureX86.h | 2 +- .../arch/x86/disasm/DisassemblerX86.cpp | 112 ++++++++++++++++++ .../arch/x86/disasm/DisassemblerX86.h | 12 ++ src/apps/debugger/arch/x86/disasm/Jamfile | 3 + .../arch/x86_64/ArchitectureX8664.cpp | 4 +- .../debugger/arch/x86_64/ArchitectureX8664.h | 2 +- .../debugger/controllers/ThreadHandler.cpp | 21 ++-- .../debug_info/DebuggerImageDebugInfo.cpp | 4 +- .../debug_info/DebuggerImageDebugInfo.h | 2 +- .../debug_info/DwarfImageDebugInfo.cpp | 101 ++++++---------- .../debugger/debug_info/DwarfImageDebugInfo.h | 9 +- .../debug_info/SpecificImageDebugInfo.h | 2 +- src/apps/debugger/jobs/GetStackTraceJob.cpp | 3 +- 17 files changed, 197 insertions(+), 131 deletions(-) diff --git a/src/apps/debugger/arch/Architecture.cpp b/src/apps/debugger/arch/Architecture.cpp index 4da06410f2..c1724f78ec 100644 --- a/src/apps/debugger/arch/Architecture.cpp +++ b/src/apps/debugger/arch/Architecture.cpp @@ -94,8 +94,8 @@ Architecture::InitRegisterRules(CfaContext& context) const status_t Architecture::CreateStackTrace(Team* team, ImageDebugInfoProvider* imageInfoProvider, CpuState* cpuState, - StackTrace*& _stackTrace, bool getReturnValue, int32 maxStackDepth, - bool useExistingTrace, bool getFullFrameInfo) + StackTrace*& _stackTrace, target_addr_t returnFunctionAddress, + int32 maxStackDepth, bool useExistingTrace, bool getFullFrameInfo) { BReference cpuStateReference(cpuState); @@ -163,7 +163,7 @@ Architecture::CreateStackTrace(Team* team, if (function != NULL) { status_t error = functionDebugInfo->GetSpecificImageDebugInfo() ->CreateFrame(image, function, cpuState, getFullFrameInfo, - nextFrame == NULL ? getReturnValue : false, frame, + nextFrame == NULL ? returnFunctionAddress : 0, frame, previousCpuState); if (error != B_OK && error != B_UNSUPPORTED) break; diff --git a/src/apps/debugger/arch/Architecture.h b/src/apps/debugger/arch/Architecture.h index 3ab3f7daa4..d9610ba77f 100644 --- a/src/apps/debugger/arch/Architecture.h +++ b/src/apps/debugger/arch/Architecture.h @@ -103,13 +103,14 @@ public: target_addr_t address, Statement*& _statement) = 0; virtual status_t GetInstructionInfo(target_addr_t address, - InstructionInfo& _info) = 0; + InstructionInfo& _info, + CpuState* state) = 0; status_t CreateStackTrace(Team* team, ImageDebugInfoProvider* imageInfoProvider, CpuState* cpuState, StackTrace*& _stackTrace, - bool getReturnValue, + target_addr_t returnFunctionAddress, int32 maxStackDepth = -1, bool useExistingTrace = false, bool getFullFrameInfo = true); diff --git a/src/apps/debugger/arch/InstructionInfo.h b/src/apps/debugger/arch/InstructionInfo.h index f130080fb6..25e9e365cd 100644 --- a/src/apps/debugger/arch/InstructionInfo.h +++ b/src/apps/debugger/arch/InstructionInfo.h @@ -12,6 +12,7 @@ enum instruction_type { INSTRUCTION_TYPE_SUBROUTINE_CALL, + INSTRUCTION_TYPE_JUMP, INSTRUCTION_TYPE_OTHER }; diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.cpp b/src/apps/debugger/arch/x86/ArchitectureX86.cpp index c7995d5193..39e5c7f71b 100644 --- a/src/apps/debugger/arch/x86/ArchitectureX86.cpp +++ b/src/apps/debugger/arch/x86/ArchitectureX86.cpp @@ -561,7 +561,7 @@ ArchitectureX86::GetStatement(FunctionDebugInfo* function, // TODO: This is not architecture dependent anymore! // get the instruction info InstructionInfo info; - status_t error = GetInstructionInfo(address, info); + status_t error = GetInstructionInfo(address, info, NULL); if (error != B_OK) return error; @@ -578,7 +578,7 @@ ArchitectureX86::GetStatement(FunctionDebugInfo* function, status_t ArchitectureX86::GetInstructionInfo(target_addr_t address, - InstructionInfo& _info) + InstructionInfo& _info, CpuState* state) { // read the code - maximum x86{-64} instruction size = 15 bytes uint8 buffer[16]; @@ -593,40 +593,7 @@ ArchitectureX86::GetInstructionInfo(target_addr_t address, if (error != B_OK) return error; - // disassemble the instruction - BString line; - target_addr_t instructionAddress; - target_addr_t targetAddress = 0; - 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; - // TODO: retrieve target address (might be in a register) - } 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; - int32 offset; - memcpy(&offset, &buffer[1], 4); - targetAddress = instructionAddress + instructionSize + offset; - } - } - - if (!_info.SetTo(instructionAddress, targetAddress, instructionSize, - instructionType, breakpointAllowed, line)) { - return B_NO_MEMORY; - } - - return B_OK; + return disassembler.GetNextInstructionInfo(_info, state); } diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.h b/src/apps/debugger/arch/x86/ArchitectureX86.h index 1549f9bd65..1a6120cfa2 100644 --- a/src/apps/debugger/arch/x86/ArchitectureX86.h +++ b/src/apps/debugger/arch/x86/ArchitectureX86.h @@ -59,7 +59,7 @@ public: target_addr_t address, Statement*& _statement); virtual status_t GetInstructionInfo(target_addr_t address, - InstructionInfo& _info); + InstructionInfo& _info, CpuState* state); virtual status_t GetWatchpointDebugCapabilities( int32& _maxRegisterCount, diff --git a/src/apps/debugger/arch/x86/disasm/DisassemblerX86.cpp b/src/apps/debugger/arch/x86/disasm/DisassemblerX86.cpp index f20838e31e..e686d7e7f8 100644 --- a/src/apps/debugger/arch/x86/disasm/DisassemblerX86.cpp +++ b/src/apps/debugger/arch/x86/disasm/DisassemblerX86.cpp @@ -12,6 +12,36 @@ #include +#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 { }; @@ -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(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; +} diff --git a/src/apps/debugger/arch/x86/disasm/DisassemblerX86.h b/src/apps/debugger/arch/x86/disasm/DisassemblerX86.h index b66a0adbcd..9d4952560d 100644 --- a/src/apps/debugger/arch/x86/disasm/DisassemblerX86.h +++ b/src/apps/debugger/arch/x86/disasm/DisassemblerX86.h @@ -10,6 +10,10 @@ #include "Types.h" +class CpuState; +class InstructionInfo; + + class DisassemblerX86 { public: DisassemblerX86(); @@ -27,6 +31,14 @@ public: target_addr_t& _address, target_size_t& _size); + virtual status_t GetNextInstructionInfo( + InstructionInfo& _info, + CpuState* state); + + +private: + target_addr_t GetInstructionTargetAddress( + CpuState* state) const; private: struct UdisData; diff --git a/src/apps/debugger/arch/x86/disasm/Jamfile b/src/apps/debugger/arch/x86/disasm/Jamfile index a916ab0144..0b40f9f7e0 100644 --- a/src/apps/debugger/arch/x86/disasm/Jamfile +++ b/src/apps/debugger/arch/x86/disasm/Jamfile @@ -3,9 +3,12 @@ SubDir HAIKU_TOP src apps debugger arch x86 disasm ; CCFLAGS += -Werror ; C++FLAGS += -Werror ; +UsePrivateHeaders shared ; + UseHeaders [ LibraryHeaders udis86 ] ; UseHeaders [ LibraryHeaders [ FDirName udis86 libudis86 ] ] ; +SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ; SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ; SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) $(DOTDOT) types ] ; diff --git a/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp b/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp index acf2f93d31..05ba2a4315 100644 --- a/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp +++ b/src/apps/debugger/arch/x86_64/ArchitectureX8664.cpp @@ -451,7 +451,7 @@ ArchitectureX8664::GetStatement(FunctionDebugInfo* function, // TODO: This is not architecture dependent anymore! // get the instruction info InstructionInfo info; - status_t error = GetInstructionInfo(address, info); + status_t error = GetInstructionInfo(address, info, NULL); if (error != B_OK) return error; @@ -468,7 +468,7 @@ ArchitectureX8664::GetStatement(FunctionDebugInfo* function, status_t ArchitectureX8664::GetInstructionInfo(target_addr_t address, - InstructionInfo& _info) + InstructionInfo& _info, CpuState* state) { // read the code uint8 buffer[16]; diff --git a/src/apps/debugger/arch/x86_64/ArchitectureX8664.h b/src/apps/debugger/arch/x86_64/ArchitectureX8664.h index f61b8f38b1..2ff90bedec 100644 --- a/src/apps/debugger/arch/x86_64/ArchitectureX8664.h +++ b/src/apps/debugger/arch/x86_64/ArchitectureX8664.h @@ -60,7 +60,7 @@ public: target_addr_t address, Statement*& _statement); virtual status_t GetInstructionInfo(target_addr_t address, - InstructionInfo& _info); + InstructionInfo& _info, CpuState* state); virtual status_t GetWatchpointDebugCapabilities( int32& _maxRegisterCount, diff --git a/src/apps/debugger/controllers/ThreadHandler.cpp b/src/apps/debugger/controllers/ThreadHandler.cpp index 7913da930f..6a2fe948fb 100644 --- a/src/apps/debugger/controllers/ThreadHandler.cpp +++ b/src/apps/debugger/controllers/ThreadHandler.cpp @@ -253,7 +253,7 @@ ThreadHandler::HandleThreadAction(uint32 action) if (stackTrace == NULL && cpuState != NULL) { if (fDebuggerInterface->GetArchitecture()->CreateStackTrace( - fThread->GetTeam(), this, cpuState, stackTrace, false, 1, + fThread->GetTeam(), this, cpuState, stackTrace, 0, 1, false, false) == B_OK) { stackTraceReference.SetTo(stackTrace, true); } @@ -469,7 +469,7 @@ ThreadHandler::_DoStepOver(CpuState* cpuState) // just single-step, otherwise we set a breakpoint after the instruction. InstructionInfo info; if (fDebuggerInterface->GetArchitecture()->GetInstructionInfo( - cpuState->InstructionPointer(), info) != B_OK) { + cpuState->InstructionPointer(), info, cpuState) != B_OK) { TRACE_CONTROL(" failed to get instruction info\n"); return false; } @@ -484,7 +484,7 @@ ThreadHandler::_DoStepOver(CpuState* cpuState) TRACE_CONTROL(" subroutine call -- installing breakpoint at address " "%#" B_PRIx64 "\n", info.Address() + info.Size()); - fThread->SetExecutedSubroutine(); + fThread->SetExecutedSubroutine(info.TargetAddress()); if (_InstallTemporaryBreakpoint(info.Address() + info.Size()) != B_OK) return false; @@ -566,8 +566,8 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState) if (stackTrace == NULL && cpuState != NULL) { if (fDebuggerInterface->GetArchitecture()->CreateStackTrace( - fThread->GetTeam(), this, cpuState, stackTrace, false, - 1, false, false) == B_OK) { + fThread->GetTeam(), this, cpuState, stackTrace, 0, 1, + false, false) == B_OK) { stackTraceReference.SetTo(stackTrace, true); } } @@ -608,7 +608,7 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState) // That's the return address, so we're done in theory, // unless we're a recursive function. Check if we've actually // exited the previous stack frame or not. - fThread->SetExecutedSubroutine(); + fThread->SetExecutedSubroutine(cpuState->InstructionPointer()); target_addr_t framePointer = cpuState->StackFramePointer(); bool hasExitedFrame = fDebuggerInterface->GetArchitecture() ->StackGrowthDirection() == STACK_GROWTH_DIRECTION_POSITIVE @@ -653,8 +653,8 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState) if (stackTrace == NULL && cpuState != NULL) { if (fDebuggerInterface->GetArchitecture()->CreateStackTrace( - fThread->GetTeam(), this, cpuState, stackTrace, false, - 1, false, false) == B_OK) { + fThread->GetTeam(), this, cpuState, stackTrace, 0, 1, + false, false) == B_OK) { stackTraceReference.SetTo(stackTrace, true); } } @@ -685,7 +685,7 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState) BReference stackTraceReference(stackTrace); if (stackTrace == NULL && cpuState != NULL) { if (fDebuggerInterface->GetArchitecture()->CreateStackTrace( - fThread->GetTeam(), this, cpuState, stackTrace, false, + fThread->GetTeam(), this, cpuState, stackTrace, 0, 1, false, false) == B_OK) { stackTraceReference.SetTo(stackTrace, true); } @@ -693,7 +693,8 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState) if (stackTrace != NULL && stackTrace->FrameAt(0) ->FrameAddress() != fPreviousFrameAddress) { - fThread->SetExecutedSubroutine(); + fThread->SetExecutedSubroutine( + cpuState->InstructionPointer()); } return false; diff --git a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp index 1ff7ac88e0..b40e08c998 100644 --- a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp @@ -68,8 +68,8 @@ DebuggerImageDebugInfo::GetAddressSectionType(target_addr_t address) status_t DebuggerImageDebugInfo::CreateFrame(Image* image, FunctionInstance* functionInstance, CpuState* cpuState, - bool getFullFrameInfo, bool getReturnValue, StackFrame*& _previousFrame, - CpuState*& _previousCpuState) + bool getFullFrameInfo, target_addr_t returnFunctionAddress, + StackFrame*& _previousFrame, CpuState*& _previousCpuState) { return B_UNSUPPORTED; } diff --git a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h index 981dbd8f46..bcafebc0f3 100644 --- a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h +++ b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h @@ -36,7 +36,7 @@ public: FunctionInstance* functionInstance, CpuState* cpuState, bool getFullFrameInfo, - bool getReturnValue, + target_addr_t returnFunctionAddress, StackFrame*& _previousFrame, CpuState*& _previousCpuState); virtual status_t GetStatement(FunctionDebugInfo* function, diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp index c7448e05e8..6d60b1b8e8 100644 --- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp @@ -522,8 +522,8 @@ DwarfImageDebugInfo::GetAddressSectionType(target_addr_t address) status_t DwarfImageDebugInfo::CreateFrame(Image* image, FunctionInstance* functionInstance, CpuState* cpuState, - bool getFullFrameInfo, bool getReturnValue, StackFrame*& _frame, - CpuState*& _previousCpuState) + bool getFullFrameInfo, target_addr_t returnFunctionAddress, + StackFrame*& _frame, CpuState*& _previousCpuState) { DwarfFunctionDebugInfo* function = dynamic_cast( functionInstance->GetFunctionDebugInfo()); @@ -673,9 +673,9 @@ DwarfImageDebugInfo::CreateFrame(Image* image, instructionPointer, functionInstance->Address() - fRelocationDelta, subprogramEntry->Variables(), subprogramEntry->Blocks()); - if (getReturnValue) { - _CreateReturnValue(functionInstance, image, function, frame, - *stackFrameDebugInfo, instructionPointer); + if (returnFunctionAddress != 0) { + _CreateReturnValue(returnFunctionAddress, image, frame, + *stackFrameDebugInfo); } } @@ -1086,75 +1086,28 @@ DwarfImageDebugInfo::_CreateLocalVariables(CompilationUnit* unit, status_t -DwarfImageDebugInfo::_CreateReturnValue(FunctionInstance* functionInstance, - Image* image, DwarfFunctionDebugInfo* function, StackFrame* frame, - DwarfStackFrameDebugInfo& factory, target_addr_t instructionPointer) +DwarfImageDebugInfo::_CreateReturnValue(target_addr_t returnFunctionAddress, + Image* image, StackFrame* frame, DwarfStackFrameDebugInfo& factory) { - // the thread just executed a subroutine, look for the last call - // instruction. - DisassembledCode* sourceCode = NULL; - target_size_t bufferSize = std::min(functionInstance->Size(), - (target_size_t)64 * 1024); - void* buffer = malloc(bufferSize); - if (buffer == NULL) - return B_NO_MEMORY; - 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, - bytesRead, sourceCode); - if (result != B_OK) - return result; - - BReference sourceCodeReference(sourceCode, true); - target_addr_t previousStatementAddress = instructionPointer + fRelocationDelta - 1; - Statement* statement = sourceCode->StatementAtAddress( - previousStatementAddress); - if (statement == NULL) - return B_BAD_VALUE; - - InstructionInfo info; - do { - TargetAddressRange range = statement->CoveringAddressRange(); - result = fArchitecture->GetInstructionInfo(range.Start(), info); - if (result != B_OK) - return result; - - if (info.Type() == INSTRUCTION_TYPE_SUBROUTINE_CALL) - break; - - previousStatementAddress = statement->CoveringAddressRange().Start() - 1; - statement = sourceCode->StatementAtAddress( - previousStatementAddress); - } while (statement != NULL); - - // we weren't able to find a subroutine call by stepping back - // so we can't retrieve a return value - if (info.Type() != INSTRUCTION_TYPE_SUBROUTINE_CALL) - return B_OK; - - target_addr_t targetAddress = info.TargetAddress(); - if (targetAddress == 0) - return B_BAD_VALUE; - - if (!image->ContainsAddress(targetAddress)) { + if (!image->ContainsAddress(returnFunctionAddress)) { // our current image doesn't contain the target function, // locate the one which does. - image = image->GetTeam()->ImageByAddress(targetAddress); + image = image->GetTeam()->ImageByAddress(returnFunctionAddress); if (image == NULL) return B_BAD_VALUE; } + status_t result = B_OK; FunctionInstance* targetFunction; - if (targetAddress >= fPLTSectionStart && targetAddress < fPLTSectionEnd) { - // TODO: resolve actual target address in the PIC case - // and adjust targetAddress accordingly + if (returnFunctionAddress >= fPLTSectionStart + && returnFunctionAddress < fPLTSectionEnd) { + // TODO: handle resolving PLT entries + // to their target function + return B_UNSUPPORTED; } + ImageDebugInfo* imageInfo = image->GetImageDebugInfo(); - targetFunction = imageInfo->FunctionAtAddress(targetAddress); + targetFunction = imageInfo->FunctionAtAddress(returnFunctionAddress); if (targetFunction != NULL) { DwarfFunctionDebugInfo* targetInfo = dynamic_cast( @@ -1163,15 +1116,30 @@ DwarfImageDebugInfo::_CreateReturnValue(FunctionInstance* functionInstance, 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(subProgram->Specification()); + if (subProgram != NULL) + returnType = subProgram->ReturnType(); + // function doesn't return a value, we're done. - return B_OK; + if (returnType == NULL) + return B_OK; } + uint32 byteSize = 0; + if (returnType->ByteSize() == NULL) { + if (dynamic_cast(returnType) != NULL) + byteSize = fArchitecture->AddressSize(); + } else + byteSize = returnType->ByteSize()->constant; + ValueLocation* location; result = fArchitecture->GetReturnAddressLocation(frame, - returnType->ByteSize()->constant, location); + byteSize, location); if (result != B_OK) return result; + BReference locationReference(location, true); Variable* variable = NULL; BReference idReference( @@ -1180,6 +1148,7 @@ DwarfImageDebugInfo::_CreateReturnValue(FunctionInstance* functionInstance, location, variable); if (result != B_OK) return result; + BReference variableReference(variable, true); if (!frame->AddLocalVariable(variable)) return B_NO_MEMORY; diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h index 56cd1c13a6..203920b11a 100644 --- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h @@ -64,7 +64,7 @@ public: FunctionInstance* functionInstance, CpuState* cpuState, bool getFullFrameInfo, - bool getReturnValue, + target_addr_t returnFunctionAddress, StackFrame*& _frame, CpuState*& _previousCpuState); virtual status_t GetStatement(FunctionDebugInfo* function, @@ -104,12 +104,11 @@ private: const EntryListWrapper& variableEntries, const EntryListWrapper& blockEntries); - status_t _CreateReturnValue(FunctionInstance* instance, + status_t _CreateReturnValue( + target_addr_t returnFunctionAddress, Image* image, - DwarfFunctionDebugInfo* info, StackFrame* frame, - DwarfStackFrameDebugInfo& factory, - target_addr_t instructionPointer); + DwarfStackFrameDebugInfo& factory); bool _EvaluateBaseTypeConstraints(DIEType* type, const TypeLookupConstraints& constraints); diff --git a/src/apps/debugger/debug_info/SpecificImageDebugInfo.h b/src/apps/debugger/debug_info/SpecificImageDebugInfo.h index 4d424638f5..ac655cdf16 100644 --- a/src/apps/debugger/debug_info/SpecificImageDebugInfo.h +++ b/src/apps/debugger/debug_info/SpecificImageDebugInfo.h @@ -56,7 +56,7 @@ public: FunctionInstance* functionInstance, CpuState* cpuState, bool getFullFrameInfo, - bool getReturnValue, + target_addr_t returnFunctionAddress, StackFrame*& _Frame, CpuState*& _previousCpuState) = 0; // returns reference to previous frame diff --git a/src/apps/debugger/jobs/GetStackTraceJob.cpp b/src/apps/debugger/jobs/GetStackTraceJob.cpp index 2f08190f99..23ce2fc102 100644 --- a/src/apps/debugger/jobs/GetStackTraceJob.cpp +++ b/src/apps/debugger/jobs/GetStackTraceJob.cpp @@ -58,7 +58,8 @@ GetStackTraceJob::Do() // get the stack trace StackTrace* stackTrace; status_t error = fArchitecture->CreateStackTrace(fThread->GetTeam(), this, - fCpuState, stackTrace, fThread->ExecutedSubroutine()); + fCpuState, stackTrace, fThread->ExecutedSubroutine() + ? fThread->SubroutineAddress() : 0); if (error != B_OK) return error; BReference stackTraceReference(stackTrace, true); From 612ab9791896498800cce95a52d2a50f61f6b78f Mon Sep 17 00:00:00 2001 From: Humdinger Date: Tue, 1 Jan 2013 17:44:25 +0100 Subject: [PATCH 11/12] Re-arranged tabs Pu the tabs back in the order it used to be. "Fonts" and "Colors" are probably changed more often than "Look and feel". Also re-arranged a few lines of code to reflect that order and sorted the includes. --- src/preferences/appearance/APRWindow.cpp | 30 ++++++++++++------------ 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/preferences/appearance/APRWindow.cpp b/src/preferences/appearance/APRWindow.cpp index 61203bcacb..87afe9487c 100644 --- a/src/preferences/appearance/APRWindow.cpp +++ b/src/preferences/appearance/APRWindow.cpp @@ -21,9 +21,9 @@ #include "AntialiasingSettingsView.h" #include "APRView.h" -#include "LookAndFeelSettingsView.h" #include "defs.h" #include "FontView.h" +#include "LookAndFeelSettingsView.h" #undef B_TRANSLATION_CONTEXT @@ -50,19 +50,19 @@ APRWindow::APRWindow(BRect frame) BTabView* tabView = new BTabView("tabview", B_WIDTH_FROM_LABEL); - fLookAndFeelSettings = new LookAndFeelSettingsView( - B_TRANSLATE("Look and feel")); - fFontSettings = new FontView(B_TRANSLATE("Fonts")); fColorsView = new APRView(B_TRANSLATE("Colors")); + fLookAndFeelSettings = new LookAndFeelSettingsView( + B_TRANSLATE("Look and feel")); + fAntialiasingSettings = new AntialiasingSettingsView( B_TRANSLATE("Antialiasing")); - tabView->AddTab(fLookAndFeelSettings); tabView->AddTab(fFontSettings); tabView->AddTab(fColorsView); + tabView->AddTab(fLookAndFeelSettings); tabView->AddTab(fAntialiasingSettings); _UpdateButtons(); @@ -91,8 +91,8 @@ APRWindow::MessageReceived(BMessage *message) case kMsgSetDefaults: fFontSettings->SetDefaults(); fColorsView->SetDefaults(); - fAntialiasingSettings->SetDefaults(); fLookAndFeelSettings->SetDefaults(); + fAntialiasingSettings->SetDefaults(); _UpdateButtons(); break; @@ -100,8 +100,8 @@ APRWindow::MessageReceived(BMessage *message) case kMsgRevert: fColorsView->Revert(); fAntialiasingSettings->Revert(); - fFontSettings->Revert(); fLookAndFeelSettings->Revert(); + fFontSettings->Revert(); _UpdateButtons(); break; @@ -128,10 +128,10 @@ APRWindow::_IsDefaultable() const // printf("colors defaultable: %d\n", fColorsView->IsDefaultable()); // printf("AA defaultable: %d\n", fAntialiasingSettings->IsDefaultable()); // printf("decor defaultable: %d\n", fLookAndFeelSettings->IsDefaultable()); - return fColorsView->IsDefaultable() - || fFontSettings->IsDefaultable() - || fAntialiasingSettings->IsDefaultable() - || fLookAndFeelSettings->IsDefaultable(); + return fFontSettings->IsDefaultable() + || fColorsView->IsDefaultable() + || fLookAndFeelSettings->IsDefaultable() + || fAntialiasingSettings->IsDefaultable(); } @@ -142,8 +142,8 @@ APRWindow::_IsRevertable() const // printf("colors revertable: %d\n", fColorsView->IsRevertable()); // printf("AA revertable: %d\n", fAntialiasingSettings->IsRevertable()); // printf("decor revertable: %d\n", fLookAndFeelSettings->IsRevertable()); - return fColorsView->IsRevertable() - || fFontSettings->IsRevertable() - || fAntialiasingSettings->IsRevertable() - || fLookAndFeelSettings->IsRevertable(); + return fFontSettings->IsRevertable() + || fColorsView->IsRevertable() + || fLookAndFeelSettings->IsRevertable() + || fAntialiasingSettings->IsRevertable(); } From ec269755757a4577b5d7b513805a4a36dd9ffa49 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Tue, 1 Jan 2013 16:12:50 -0500 Subject: [PATCH 12/12] Disable populating return values onto the variable list. - Still needs some work with respect to false positives in the most recent code, as well as the missing bits for PIC. --- src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp index 6d60b1b8e8..b96814da88 100644 --- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp @@ -673,10 +673,14 @@ DwarfImageDebugInfo::CreateFrame(Image* image, instructionPointer, functionInstance->Address() - fRelocationDelta, subprogramEntry->Variables(), subprogramEntry->Blocks()); + // TODO: re-enable once PIC and false positive issues + // are properly dealt with +#if 0 if (returnFunctionAddress != 0) { _CreateReturnValue(returnFunctionAddress, image, frame, *stackFrameDebugInfo); } +#endif } _frame = frameReference.Detach();