Merge branch 'master' into sam460ex
This commit is contained in:
@@ -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_ */
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Rene Gollent, rene@gollent.com.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "ReturnValueID.h"
|
||||||
|
|
||||||
|
|
||||||
|
ReturnValueID::~ReturnValueID()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user