Merge branch 'master' into sam460ex
This commit is contained in:
@@ -973,12 +973,12 @@ if [ IsOptionalHaikuImagePackageAdded friss ] {
|
|||||||
} else {
|
} else {
|
||||||
if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||||
InstallOptionalHaikuImagePackage
|
InstallOptionalHaikuImagePackage
|
||||||
friss-29-r1a4-x86-gcc4-2012-09-09.zip
|
friss-33-r1a4-x86-gcc4-2012-11-06.zip
|
||||||
: $(baseURL)/friss-29-r1a4-x86-gcc4-2012-09-09.zip ;
|
: $(baseURL)/friss-33-r1a4-x86-gcc4-2012-11-06.zip ;
|
||||||
} else {
|
} else {
|
||||||
InstallOptionalHaikuImagePackage
|
InstallOptionalHaikuImagePackage
|
||||||
friss-29-r1a4-x86-gcc2-2012-08-28.zip
|
friss-33-r1a4-x86-gcc2-2012-11-06.zip
|
||||||
: $(baseURL)/friss-29-r1a4-x86-gcc2-2012-08-28.zip ;
|
: $(baseURL)/friss-33-r1a4-x86-gcc2-2012-11-06.zip ;
|
||||||
}
|
}
|
||||||
# AddSymlinkToHaikuImage home config settings deskbar Desktop\ applets
|
# AddSymlinkToHaikuImage home config settings deskbar Desktop\ applets
|
||||||
# : /boot/apps/FRiSS/FRiSS ;
|
# : /boot/apps/FRiSS/FRiSS ;
|
||||||
@@ -1160,12 +1160,14 @@ if [ IsOptionalHaikuImagePackageAdded KeymapSwitcher ] {
|
|||||||
} else {
|
} else {
|
||||||
if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||||
InstallOptionalHaikuImagePackage
|
InstallOptionalHaikuImagePackage
|
||||||
KeymapSwitcher-1.2.7-r1a4-x86-gcc4-2012-09-09.zip
|
KeymapSwitcher-1.2.7-r1a4-x86-gcc4-2012-11-01.zip
|
||||||
: $(baseURL)/KeymapSwitcher-1.2.7-r1a4-x86-gcc4-2012-09-09.zip ;
|
: $(baseURL)/KeymapSwitcher-1.2.7-r1a4-x86-gcc4-2012-11-01.zip
|
||||||
|
: : : false ;
|
||||||
} else {
|
} else {
|
||||||
InstallOptionalHaikuImagePackage
|
InstallOptionalHaikuImagePackage
|
||||||
KeymapSwitcher-1.2.7-r1a4-x86-gcc2-2012-08-31.zip
|
KeymapSwitcher-1.2.7-r1a4-x86-gcc2-2012-11-01.zip
|
||||||
: $(baseURL)/KeymapSwitcher-1.2.7-r1a4-x86-gcc2-2012-08-31.zip ;
|
: $(baseURL)/KeymapSwitcher-1.2.7-r1a4-x86-gcc2-2012-11-01.zip
|
||||||
|
: : : false ;
|
||||||
}
|
}
|
||||||
AddSymlinkToHaikuImage home config settings deskbar Preferences
|
AddSymlinkToHaikuImage home config settings deskbar Preferences
|
||||||
: /boot/common/bin/KeymapSwitcher ;
|
: /boot/common/bin/KeymapSwitcher ;
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ switch $(HAIKU_BUILD_PROFILE) {
|
|||||||
WebPositive WonderBrush ;
|
WebPositive WonderBrush ;
|
||||||
AddOptionalHaikuImagePackages CVS Development Git Mercurial
|
AddOptionalHaikuImagePackages CVS Development Git Mercurial
|
||||||
Python Subversion OpenSSH OpenSSL ;
|
Python Subversion OpenSSH OpenSSL ;
|
||||||
AddOptionalHaikuImagePackages Nano P7zip Welcome BeBook XZ-Utils ;
|
AddOptionalHaikuImagePackages KeymapSwitcher Nano P7zip Welcome
|
||||||
|
BeBook XZ-Utils ;
|
||||||
AddOptionalHaikuImagePackages wpa_supplicant ;
|
AddOptionalHaikuImagePackages wpa_supplicant ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -89,12 +89,15 @@ mkdir -p $installDir $objDir $binutilsObjDir $gccObjDir $tmpIncludeDir \
|
|||||||
$tmpLibDir || exit 1
|
$tmpLibDir || exit 1
|
||||||
mkdir -p $installDir/lib/gcc-lib/i586-pc-haiku/$haikuRequiredLegacyGCCVersion
|
mkdir -p $installDir/lib/gcc-lib/i586-pc-haiku/$haikuRequiredLegacyGCCVersion
|
||||||
|
|
||||||
|
# force the POSIX locale, as the build (makeinfo) might choke otherwise
|
||||||
|
export LC_ALL=POSIX
|
||||||
|
|
||||||
# build binutils
|
# build binutils
|
||||||
cd $binutilsObjDir
|
cd $binutilsObjDir
|
||||||
CFLAGS="-O2" CXXFLAGS="-O2" $buildToolsDir/binutils/configure \
|
CFLAGS="-O2" CXXFLAGS="-O2" $buildToolsDir/binutils/configure \
|
||||||
--prefix=$installDir --target=i586-pc-haiku --disable-nls \
|
--prefix=$installDir --target=i586-pc-haiku --disable-nls \
|
||||||
--enable-shared=yes --disable-werror || exit 1
|
--enable-shared=yes --disable-werror || exit 1
|
||||||
make $additionalMakeArgs || exit 1
|
make -j1 $additionalMakeArgs || exit 1
|
||||||
make $additionalMakeArgs install || exit 1
|
make $additionalMakeArgs install || exit 1
|
||||||
|
|
||||||
PATH=$PATH:$installDir/bin
|
PATH=$PATH:$installDir/bin
|
||||||
@@ -154,7 +157,7 @@ eval "sed $sedExpr Makefile.bak > Makefile" || exit 1
|
|||||||
rm Makefile.bak
|
rm Makefile.bak
|
||||||
|
|
||||||
# make gcc
|
# make gcc
|
||||||
make cross || {
|
make -j1 cross || {
|
||||||
echo "ERROR: Building gcc failed." >&2
|
echo "ERROR: Building gcc failed." >&2
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,6 +110,8 @@ mkdir -p $installDir $objDir $binutilsObjDir $gccObjDir $tmpIncludeDir \
|
|||||||
$tmpLibDir || exit 1
|
$tmpLibDir || exit 1
|
||||||
mkdir -p $installDir/lib/gcc/$haikuMachine/$gccVersion
|
mkdir -p $installDir/lib/gcc/$haikuMachine/$gccVersion
|
||||||
|
|
||||||
|
# force the POSIX locale, as the build (makeinfo) might choke otherwise
|
||||||
|
export LC_ALL=POSIX
|
||||||
|
|
||||||
# build binutils
|
# build binutils
|
||||||
cd $binutilsObjDir
|
cd $binutilsObjDir
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
- Need the ability to save crash reports.
|
||||||
|
- CLI needs to be more fully implemented.
|
||||||
|
- General expression evaluation parser. Once implemented, should supplant the primitive one currently used for C/C++ typecasting support, as well as being exposed for user expression input.
|
||||||
|
- Conditional breakpoint/watchpoints. Contingent on above general expression parser.
|
||||||
|
- Remote debug interface support.
|
||||||
|
- Kernel debug support.
|
||||||
|
- Architecture needs to be able to report back the hardware debugging capabilities/limitations of the target platform.
|
||||||
|
- WatchpointManager needs to be able to use the aforementioned information from Architecture in order to more intelligently
|
||||||
|
manage/restrict watchpoint usage (especially once expression watchpoints come into play).
|
||||||
|
- More complete DWARF3/4 support.
|
||||||
|
- x86-64 support.
|
||||||
|
- Support for retrieving/displaying function return values (arch-specific).
|
||||||
|
- Syntax highlighting in source view.
|
||||||
|
- Detection of mouse hovering over a variable in SourceView and showing value in tooltip (probably requires expression parsing support).
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
* Does not support < ARMv5
|
||||||
|
* Requires support for high vectors
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
* Figure out how to get page flags (modified/accessed) and implement it ;)
|
||||||
|
|
||||||
|
* Fix serial port mapping. Currently kernel uses the haiku_loader identity
|
||||||
|
mapping for it, but this lives in user virtual address space...
|
||||||
|
(Need to not use identity mapping in haiku_loader but just
|
||||||
|
map_physical_memory() there too so it can be handed over without issues).
|
||||||
|
|
||||||
|
* Seperate ARM architecture/System-On-Chip IP code. Needed very early on
|
||||||
|
(Interrupt Controller, Timer IP block). Should use FDT for this too.
|
||||||
|
|
||||||
|
* Use FDT to remove all the seperate board definitions in the build. Use a
|
||||||
|
"minimal ARM architecture version" as the compile flag for ARM support.
|
||||||
|
This to be able to optimize a kernel build for a specific SoC (or family).
|
||||||
|
|
||||||
|
* Research stack unwinding to implement backtrace support for KDL & friends.
|
||||||
|
|
||||||
|
* Add KDL hangman to the boot floppy image for more enjoyment during porting....
|
||||||
|
|
||||||
|
* Userland...........
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
/* raw exception frames */
|
/* raw exception frames */
|
||||||
struct iframe {
|
struct iframe {
|
||||||
|
uint32 spsr;
|
||||||
uint32 r0;
|
uint32 r0;
|
||||||
uint32 r1;
|
uint32 r1;
|
||||||
uint32 r2;
|
uint32 r2;
|
||||||
@@ -25,10 +26,11 @@ struct iframe {
|
|||||||
uint32 r10;
|
uint32 r10;
|
||||||
uint32 r11;
|
uint32 r11;
|
||||||
uint32 r12;
|
uint32 r12;
|
||||||
uint32 r13;
|
uint32 usr_sp;
|
||||||
uint32 lr;
|
uint32 usr_lr;
|
||||||
|
uint32 svc_sp;
|
||||||
|
uint32 svc_lr;
|
||||||
uint32 pc;
|
uint32 pc;
|
||||||
uint32 cpsr;
|
|
||||||
} _PACKED;
|
} _PACKED;
|
||||||
|
|
||||||
typedef struct arch_cpu_info {
|
typedef struct arch_cpu_info {
|
||||||
@@ -40,6 +42,20 @@ extern int arch_mmu_type;
|
|||||||
extern int arch_platform;
|
extern int arch_platform;
|
||||||
extern int arch_machine;
|
extern int arch_machine;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern addr_t arm_get_far(void);
|
||||||
|
extern int32 arm_get_fsr(void);
|
||||||
|
|
||||||
|
extern int mmu_read_c1(void);
|
||||||
|
extern int mmu_write_c1(int val);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // !_ASSEMBLER
|
#endif // !_ASSEMBLER
|
||||||
|
|
||||||
#endif /* _KERNEL_ARCH_ARM_CPU_H */
|
#endif /* _KERNEL_ARCH_ARM_CPU_H */
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ InitializeNTFSEditor::PartitionNameChanged(const char* name)
|
|||||||
void
|
void
|
||||||
InitializeNTFSEditor::_CreateViewControls()
|
InitializeNTFSEditor::_CreateViewControls()
|
||||||
{
|
{
|
||||||
fNameTC = new BTextControl("Name:", "Haiku", NULL);
|
fNameTC = new BTextControl("Name:", "New NTFS Volume", NULL);
|
||||||
fNameTC->SetModificationMessage(new BMessage(MSG_NAME_CHANGED));
|
fNameTC->SetModificationMessage(new BMessage(MSG_NAME_CHANGED));
|
||||||
// TODO find out what is the max length for this specific FS partition name
|
// TODO find out what is the max length for this specific FS partition name
|
||||||
fNameTC->TextView()->SetMaxBytes(31);
|
fNameTC->TextView()->SetMaxBytes(31);
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
using std::nothrow;
|
using std::nothrow;
|
||||||
|
|
||||||
#define kPartitionTypeNTFS "NTFS File System"
|
#define kPartitionTypeNTFS "NT File System"
|
||||||
|
|
||||||
static const uint32 kDiskSystemFlags =
|
static const uint32 kDiskSystemFlags =
|
||||||
0
|
0
|
||||||
|
|||||||
@@ -47,14 +47,26 @@ HAIKU_CHECK_DISABLE_INTERRUPTS(device_t dev)
|
|||||||
if (status == 0 || status == 0xffffffff ||
|
if (status == 0 || status == 0xffffffff ||
|
||||||
(sc->msk_pflags & MSK_FLAG_SUSPEND) != 0 ||
|
(sc->msk_pflags & MSK_FLAG_SUSPEND) != 0 ||
|
||||||
(status & sc->msk_intrmask) == 0) {
|
(status & sc->msk_intrmask) == 0) {
|
||||||
|
|
||||||
|
/* Clear possibly spurious TWSI IRQ, see FreeBSD r234666. */
|
||||||
|
if ((status & Y2_IS_TWSI_RDY) != 0)
|
||||||
|
CSR_WRITE_4(sc, B2_I2C_IRQ, 1);
|
||||||
|
|
||||||
CSR_WRITE_4(sc, B0_Y2_SP_ICR, 2);
|
CSR_WRITE_4(sc, B0_Y2_SP_ICR, 2);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sc->haiku_interrupt_status = status;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NO_HAIKU_REENABLE_INTERRUPTS();
|
void
|
||||||
|
HAIKU_REENABLE_INTERRUPTS(device_t dev)
|
||||||
|
{
|
||||||
|
struct msk_softc *sc = device_get_softc(dev);
|
||||||
|
CSR_WRITE_4(sc, B0_Y2_SP_ICR, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
HAIKU_DRIVER_REQUIREMENTS(FBSD_TASKQUEUES | FBSD_FAST_TASKQUEUE | FBSD_SWI_TASKQUEUE);
|
HAIKU_DRIVER_REQUIREMENTS(FBSD_TASKQUEUES | FBSD_FAST_TASKQUEUE | FBSD_SWI_TASKQUEUE);
|
||||||
|
|||||||
@@ -3610,6 +3610,7 @@ msk_intr(void *xsc)
|
|||||||
sc = xsc;
|
sc = xsc;
|
||||||
MSK_LOCK(sc);
|
MSK_LOCK(sc);
|
||||||
|
|
||||||
|
#ifndef __HAIKU__
|
||||||
/* Reading B0_Y2_SP_ISRC2 masks further interrupts. */
|
/* Reading B0_Y2_SP_ISRC2 masks further interrupts. */
|
||||||
status = CSR_READ_4(sc, B0_Y2_SP_ISRC2);
|
status = CSR_READ_4(sc, B0_Y2_SP_ISRC2);
|
||||||
if (status == 0 || status == 0xffffffff ||
|
if (status == 0 || status == 0xffffffff ||
|
||||||
@@ -3619,6 +3620,9 @@ msk_intr(void *xsc)
|
|||||||
MSK_UNLOCK(sc);
|
MSK_UNLOCK(sc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
status = sc->haiku_interrupt_status;
|
||||||
|
#endif
|
||||||
|
|
||||||
sc_if0 = sc->msk_if[MSK_PORT_A];
|
sc_if0 = sc->msk_if[MSK_PORT_A];
|
||||||
sc_if1 = sc->msk_if[MSK_PORT_B];
|
sc_if1 = sc->msk_if[MSK_PORT_B];
|
||||||
@@ -3655,8 +3659,10 @@ msk_intr(void *xsc)
|
|||||||
if ((status & Y2_IS_STAT_BMU) != 0 && domore == 0)
|
if ((status & Y2_IS_STAT_BMU) != 0 && domore == 0)
|
||||||
CSR_WRITE_4(sc, STAT_CTRL, SC_STAT_CLR_IRQ);
|
CSR_WRITE_4(sc, STAT_CTRL, SC_STAT_CLR_IRQ);
|
||||||
|
|
||||||
|
#ifndef __HAIKU__
|
||||||
/* Reenable interrupts. */
|
/* Reenable interrupts. */
|
||||||
CSR_WRITE_4(sc, B0_Y2_SP_ICR, 2);
|
CSR_WRITE_4(sc, B0_Y2_SP_ICR, 2);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (ifp0 != NULL && (ifp0->if_drv_flags & IFF_DRV_RUNNING) != 0 &&
|
if (ifp0 != NULL && (ifp0->if_drv_flags & IFF_DRV_RUNNING) != 0 &&
|
||||||
!IFQ_DRV_IS_EMPTY(&ifp0->if_snd))
|
!IFQ_DRV_IS_EMPTY(&ifp0->if_snd))
|
||||||
|
|||||||
@@ -2520,6 +2520,9 @@ struct msk_softc {
|
|||||||
int msk_process_limit;
|
int msk_process_limit;
|
||||||
int msk_stat_cons;
|
int msk_stat_cons;
|
||||||
struct mtx msk_mtx;
|
struct mtx msk_mtx;
|
||||||
|
#ifdef __HAIKU__
|
||||||
|
uint32_t haiku_interrupt_status;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MSK_LOCK(_sc) mtx_lock(&(_sc)->msk_mtx)
|
#define MSK_LOCK(_sc) mtx_lock(&(_sc)->msk_mtx)
|
||||||
|
|||||||
@@ -368,12 +368,6 @@ AX88772Device::_SetupAX88772()
|
|||||||
|
|
||||||
snooze(150000);
|
snooze(150000);
|
||||||
|
|
||||||
result = WriteRXControlRegister(0);
|
|
||||||
if (result != B_OK) {
|
|
||||||
TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", 0, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,12 +443,6 @@ AX88772Device::_SetupAX88772A()
|
|||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
result = WriteRXControlRegister(0);
|
|
||||||
if (result != B_OK) {
|
|
||||||
TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", 0, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
fIPG[0] = 0x15;
|
fIPG[0] = 0x15;
|
||||||
fIPG[1] = 0x16;
|
fIPG[1] = 0x16;
|
||||||
fIPG[2] = 0x1A;
|
fIPG[2] = 0x1A;
|
||||||
@@ -481,12 +469,6 @@ AX88772Device::_SetupAX88772B()
|
|||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
result = WriteRXControlRegister(0);
|
|
||||||
if (result != B_OK) {
|
|
||||||
TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", 0, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
fIPG[0] = 0x15;
|
fIPG[0] = 0x15;
|
||||||
fIPG[1] = 0x16;
|
fIPG[1] = 0x16;
|
||||||
fIPG[2] = 0x1A;
|
fIPG[2] = 0x1A;
|
||||||
@@ -513,6 +495,9 @@ AX88772Device::StartDevice()
|
|||||||
"%d bytes of %d written.\n", actualLength, sizeof(fIPG));
|
"%d bytes of %d written.\n", actualLength, sizeof(fIPG));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16 rxcontrol = 0;
|
||||||
|
|
||||||
// AX88772B uses different maximum frame burst configuration.
|
// AX88772B uses different maximum frame burst configuration.
|
||||||
if (fDeviceInfo.fType == DeviceInfo::AX88772B) {
|
if (fDeviceInfo.fType == DeviceInfo::AX88772B) {
|
||||||
result = gUSBModule->send_request(fDevice,
|
result = gUSBModule->send_request(fDevice,
|
||||||
@@ -526,9 +511,11 @@ AX88772Device::StartDevice()
|
|||||||
TRACE_ALWAYS("Error of writing frame burst:%#010x\n", result);
|
TRACE_ALWAYS("Error of writing frame burst:%#010x\n", result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rxcontrol = RXCTL_USB_MFB;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 rxcontrol = RXCTL_START | RXCTL_BROADCAST;
|
rxcontrol |= RXCTL_START | RXCTL_BROADCAST;
|
||||||
result = WriteRXControlRegister(rxcontrol);
|
result = WriteRXControlRegister(rxcontrol);
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n",
|
TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n",
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ static file_system_module_info sNTFSFileSystem = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
"ntfs", // short_name
|
"ntfs", // short_name
|
||||||
"NTFS File System", // pretty_name
|
"NT File System", // pretty_name
|
||||||
B_DISK_SYSTEM_SUPPORTS_INITIALIZING
|
B_DISK_SYSTEM_SUPPORTS_INITIALIZING
|
||||||
| B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME
|
| B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME
|
||||||
| B_DISK_SYSTEM_SUPPORTS_WRITING, // DDM flags
|
| B_DISK_SYSTEM_SUPPORTS_WRITING, // DDM flags
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ static const struct partition_type kPartitionTypes[] = {
|
|||||||
{ 0x85, /*"Linux extendend partition"*/INTEL_EXTENDED_PARTITION_NAME,
|
{ 0x85, /*"Linux extendend partition"*/INTEL_EXTENDED_PARTITION_NAME,
|
||||||
false },
|
false },
|
||||||
{ 0x86, "NTFS volume set", false },
|
{ 0x86, "NTFS volume set", false },
|
||||||
{ 0x87, "NTFS volume set", false },
|
{ 0x87, "NTFS volume set", true },
|
||||||
{ 0x88, "Linux plaintext", false },
|
{ 0x88, "Linux plaintext", false },
|
||||||
{ 0x8e, "Linux LVM", false },
|
{ 0x8e, "Linux LVM", false },
|
||||||
{ 0x93, "Amoeba", false },
|
{ 0x93, "Amoeba", false },
|
||||||
|
|||||||
@@ -9,11 +9,14 @@ UsePrivateSystemHeaders ;
|
|||||||
|
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) arch ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) arch ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) arch x86 ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) arch x86 ] ;
|
||||||
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) controllers ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_info ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_info ] ;
|
||||||
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_managers ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) elf ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) elf ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) files ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) files ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) ids ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) ids ] ;
|
||||||
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) jobs ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) model ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) model ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) settings ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) settings ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) settings generic ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) settings generic ] ;
|
||||||
@@ -55,14 +58,7 @@ SourceHdrs
|
|||||||
;
|
;
|
||||||
|
|
||||||
Application Debugger :
|
Application Debugger :
|
||||||
BreakpointManager.cpp
|
|
||||||
Debugger.cpp
|
Debugger.cpp
|
||||||
Jobs.cpp
|
|
||||||
TeamMemoryBlockManager.cpp
|
|
||||||
TeamDebugger.cpp
|
|
||||||
ThreadHandler.cpp
|
|
||||||
WatchpointManager.cpp
|
|
||||||
Worker.cpp
|
|
||||||
|
|
||||||
# arch
|
# arch
|
||||||
Architecture.cpp
|
Architecture.cpp
|
||||||
@@ -75,6 +71,15 @@ Application Debugger :
|
|||||||
ArchitectureX86.cpp
|
ArchitectureX86.cpp
|
||||||
CpuStateX86.cpp
|
CpuStateX86.cpp
|
||||||
|
|
||||||
|
# controllers
|
||||||
|
TeamDebugger.cpp
|
||||||
|
ThreadHandler.cpp
|
||||||
|
|
||||||
|
# debug_managers
|
||||||
|
BreakpointManager.cpp
|
||||||
|
TeamMemoryBlockManager.cpp
|
||||||
|
WatchpointManager.cpp
|
||||||
|
|
||||||
# debug_info
|
# debug_info
|
||||||
BasicFunctionDebugInfo.cpp
|
BasicFunctionDebugInfo.cpp
|
||||||
DebuggerImageDebugInfo.cpp
|
DebuggerImageDebugInfo.cpp
|
||||||
@@ -117,6 +122,15 @@ Application Debugger :
|
|||||||
ObjectID.cpp
|
ObjectID.cpp
|
||||||
FunctionParameterID.cpp
|
FunctionParameterID.cpp
|
||||||
|
|
||||||
|
# jobs
|
||||||
|
GetCPUStateJob.cpp
|
||||||
|
GetStackTraceJob.cpp
|
||||||
|
GetThreadStateJob.cpp
|
||||||
|
LoadImageDebugInfoJob.cpp
|
||||||
|
LoadSourceCodeJob.cpp
|
||||||
|
ResolveValueNodeJob.cpp
|
||||||
|
RetrieveMemoryBlockJob.cpp
|
||||||
|
|
||||||
# model
|
# model
|
||||||
Breakpoint.cpp
|
Breakpoint.cpp
|
||||||
DisassembledCode.cpp
|
DisassembledCode.cpp
|
||||||
@@ -150,7 +164,6 @@ Application Debugger :
|
|||||||
TeamSettings.cpp
|
TeamSettings.cpp
|
||||||
TeamUiSettings.cpp
|
TeamUiSettings.cpp
|
||||||
TeamUiSettingsFactory.cpp
|
TeamUiSettingsFactory.cpp
|
||||||
WatchpointSetting.cpp
|
|
||||||
|
|
||||||
# settings/generic
|
# settings/generic
|
||||||
Setting.cpp
|
Setting.cpp
|
||||||
@@ -211,6 +224,7 @@ Application Debugger :
|
|||||||
TeamWindow.cpp
|
TeamWindow.cpp
|
||||||
ThreadListView.cpp
|
ThreadListView.cpp
|
||||||
VariablesView.cpp
|
VariablesView.cpp
|
||||||
|
WatchPromptWindow.cpp
|
||||||
|
|
||||||
# user_interface/gui/util
|
# user_interface/gui/util
|
||||||
ActionMenuItem.cpp
|
ActionMenuItem.cpp
|
||||||
@@ -236,6 +250,7 @@ Application Debugger :
|
|||||||
BitBuffer.cpp
|
BitBuffer.cpp
|
||||||
IntegerFormatter.cpp
|
IntegerFormatter.cpp
|
||||||
StringUtils.cpp
|
StringUtils.cpp
|
||||||
|
Worker.cpp
|
||||||
|
|
||||||
# value
|
# value
|
||||||
TypeHandler.cpp
|
TypeHandler.cpp
|
||||||
|
|||||||
@@ -1,698 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012, Rene Gollent, rene@gollent.com.
|
|
||||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "Jobs.h"
|
|
||||||
|
|
||||||
#include <AutoLocker.h>
|
|
||||||
#include <memory_private.h>
|
|
||||||
|
|
||||||
#include "Architecture.h"
|
|
||||||
#include "BitBuffer.h"
|
|
||||||
#include "CpuState.h"
|
|
||||||
#include "DebuggerInterface.h"
|
|
||||||
#include "DisassembledCode.h"
|
|
||||||
#include "FileSourceCode.h"
|
|
||||||
#include "Function.h"
|
|
||||||
#include "Image.h"
|
|
||||||
#include "ImageDebugInfo.h"
|
|
||||||
#include "Register.h"
|
|
||||||
#include "SourceCode.h"
|
|
||||||
#include "SpecificImageDebugInfo.h"
|
|
||||||
#include "StackFrameDebugInfo.h"
|
|
||||||
#include "StackFrameValueInfos.h"
|
|
||||||
#include "StackFrameValues.h"
|
|
||||||
#include "StackTrace.h"
|
|
||||||
#include "Team.h"
|
|
||||||
#include "TeamDebugInfo.h"
|
|
||||||
#include "TeamMemory.h"
|
|
||||||
#include "TeamMemoryBlock.h"
|
|
||||||
#include "TeamTypeInformation.h"
|
|
||||||
#include "Thread.h"
|
|
||||||
#include "Tracing.h"
|
|
||||||
#include "Type.h"
|
|
||||||
#include "TypeComponentPath.h"
|
|
||||||
#include "Value.h"
|
|
||||||
#include "ValueLoader.h"
|
|
||||||
#include "ValueLocation.h"
|
|
||||||
#include "ValueNode.h"
|
|
||||||
#include "ValueNodeContainer.h"
|
|
||||||
#include "Variable.h"
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - GetThreadStateJob
|
|
||||||
|
|
||||||
|
|
||||||
GetThreadStateJob::GetThreadStateJob(DebuggerInterface* debuggerInterface,
|
|
||||||
Thread* thread)
|
|
||||||
:
|
|
||||||
fKey(thread, JOB_TYPE_GET_THREAD_STATE),
|
|
||||||
fDebuggerInterface(debuggerInterface),
|
|
||||||
fThread(thread)
|
|
||||||
{
|
|
||||||
fThread->AcquireReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
GetThreadStateJob::~GetThreadStateJob()
|
|
||||||
{
|
|
||||||
fThread->ReleaseReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const JobKey&
|
|
||||||
GetThreadStateJob::Key() const
|
|
||||||
{
|
|
||||||
return fKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
GetThreadStateJob::Do()
|
|
||||||
{
|
|
||||||
CpuState* state = NULL;
|
|
||||||
status_t error = fDebuggerInterface->GetCpuState(fThread->ID(), state);
|
|
||||||
BReference<CpuState> reference(state, true);
|
|
||||||
|
|
||||||
AutoLocker<Team> locker(fThread->GetTeam());
|
|
||||||
|
|
||||||
if (fThread->State() != THREAD_STATE_UNKNOWN)
|
|
||||||
return B_OK;
|
|
||||||
|
|
||||||
if (error == B_OK) {
|
|
||||||
fThread->SetState(THREAD_STATE_STOPPED);
|
|
||||||
fThread->SetCpuState(state);
|
|
||||||
} else if (error == B_BAD_THREAD_STATE) {
|
|
||||||
fThread->SetState(THREAD_STATE_RUNNING);
|
|
||||||
} else
|
|
||||||
return error;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - GetCpuStateJob
|
|
||||||
|
|
||||||
|
|
||||||
GetCpuStateJob::GetCpuStateJob(DebuggerInterface* debuggerInterface,
|
|
||||||
Thread* thread)
|
|
||||||
:
|
|
||||||
fKey(thread, JOB_TYPE_GET_CPU_STATE),
|
|
||||||
fDebuggerInterface(debuggerInterface),
|
|
||||||
fThread(thread)
|
|
||||||
{
|
|
||||||
fThread->AcquireReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
GetCpuStateJob::~GetCpuStateJob()
|
|
||||||
{
|
|
||||||
fThread->ReleaseReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const JobKey&
|
|
||||||
GetCpuStateJob::Key() const
|
|
||||||
{
|
|
||||||
return fKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
GetCpuStateJob::Do()
|
|
||||||
{
|
|
||||||
CpuState* state;
|
|
||||||
status_t error = fDebuggerInterface->GetCpuState(fThread->ID(), state);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
BReference<CpuState> reference(state, true);
|
|
||||||
|
|
||||||
AutoLocker<Team> locker(fThread->GetTeam());
|
|
||||||
|
|
||||||
if (fThread->State() == THREAD_STATE_STOPPED)
|
|
||||||
fThread->SetCpuState(state);
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - GetStackTraceJob
|
|
||||||
|
|
||||||
|
|
||||||
GetStackTraceJob::GetStackTraceJob(DebuggerInterface* debuggerInterface,
|
|
||||||
Architecture* architecture, Thread* thread)
|
|
||||||
:
|
|
||||||
fKey(thread, JOB_TYPE_GET_STACK_TRACE),
|
|
||||||
fDebuggerInterface(debuggerInterface),
|
|
||||||
fArchitecture(architecture),
|
|
||||||
fThread(thread)
|
|
||||||
{
|
|
||||||
fThread->AcquireReference();
|
|
||||||
|
|
||||||
fCpuState = fThread->GetCpuState();
|
|
||||||
if (fCpuState != NULL)
|
|
||||||
fCpuState->AcquireReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
GetStackTraceJob::~GetStackTraceJob()
|
|
||||||
{
|
|
||||||
if (fCpuState != NULL)
|
|
||||||
fCpuState->ReleaseReference();
|
|
||||||
|
|
||||||
fThread->ReleaseReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const JobKey&
|
|
||||||
GetStackTraceJob::Key() const
|
|
||||||
{
|
|
||||||
return fKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
GetStackTraceJob::Do()
|
|
||||||
{
|
|
||||||
if (fCpuState == NULL)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
// get the stack trace
|
|
||||||
StackTrace* stackTrace;
|
|
||||||
status_t error = fArchitecture->CreateStackTrace(fThread->GetTeam(), this,
|
|
||||||
fCpuState, stackTrace);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
BReference<StackTrace> stackTraceReference(stackTrace, true);
|
|
||||||
|
|
||||||
// set the stack trace, unless something has changed
|
|
||||||
AutoLocker<Team> locker(fThread->GetTeam());
|
|
||||||
|
|
||||||
if (fThread->GetCpuState() == fCpuState)
|
|
||||||
fThread->SetStackTrace(stackTrace);
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
GetStackTraceJob::GetImageDebugInfo(Image* image, ImageDebugInfo*& _info)
|
|
||||||
{
|
|
||||||
AutoLocker<Team> teamLocker(fThread->GetTeam());
|
|
||||||
|
|
||||||
while (image->GetImageDebugInfo() == NULL) {
|
|
||||||
// schedule a job, if not loaded
|
|
||||||
ImageDebugInfo* info;
|
|
||||||
status_t error = LoadImageDebugInfoJob::ScheduleIfNecessary(GetWorker(),
|
|
||||||
image, &info);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
if (info != NULL) {
|
|
||||||
_info = info;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
teamLocker.Unlock();
|
|
||||||
|
|
||||||
// wait for the job to finish
|
|
||||||
switch (WaitFor(SimpleJobKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO))) {
|
|
||||||
case JOB_DEPENDENCY_SUCCEEDED:
|
|
||||||
case JOB_DEPENDENCY_NOT_FOUND:
|
|
||||||
// "Not found" can happen due to a race condition between
|
|
||||||
// unlocking the worker and starting to wait.
|
|
||||||
break;
|
|
||||||
case JOB_DEPENDENCY_FAILED:
|
|
||||||
case JOB_DEPENDENCY_ABORTED:
|
|
||||||
default:
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
teamLocker.Lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
_info = image->GetImageDebugInfo();
|
|
||||||
_info->AcquireReference();
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - LoadImageDebugInfoJob
|
|
||||||
|
|
||||||
|
|
||||||
LoadImageDebugInfoJob::LoadImageDebugInfoJob(Image* image)
|
|
||||||
:
|
|
||||||
fKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO),
|
|
||||||
fImage(image)
|
|
||||||
{
|
|
||||||
fImage->AcquireReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LoadImageDebugInfoJob::~LoadImageDebugInfoJob()
|
|
||||||
{
|
|
||||||
fImage->ReleaseReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const JobKey&
|
|
||||||
LoadImageDebugInfoJob::Key() const
|
|
||||||
{
|
|
||||||
return fKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
LoadImageDebugInfoJob::Do()
|
|
||||||
{
|
|
||||||
// get an image info for the image
|
|
||||||
AutoLocker<Team> locker(fImage->GetTeam());
|
|
||||||
ImageInfo imageInfo(fImage->Info());
|
|
||||||
locker.Unlock();
|
|
||||||
|
|
||||||
// create the debug info
|
|
||||||
ImageDebugInfo* debugInfo;
|
|
||||||
status_t error = fImage->GetTeam()->DebugInfo()->LoadImageDebugInfo(
|
|
||||||
imageInfo, fImage->ImageFile(), debugInfo);
|
|
||||||
|
|
||||||
// set the result
|
|
||||||
locker.Lock();
|
|
||||||
if (error == B_OK) {
|
|
||||||
error = fImage->SetImageDebugInfo(debugInfo, IMAGE_DEBUG_INFO_LOADED);
|
|
||||||
debugInfo->ReleaseReference();
|
|
||||||
} else
|
|
||||||
fImage->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_UNAVAILABLE);
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*static*/ status_t
|
|
||||||
LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image,
|
|
||||||
ImageDebugInfo** _imageDebugInfo)
|
|
||||||
{
|
|
||||||
AutoLocker<Team> teamLocker(image->GetTeam());
|
|
||||||
|
|
||||||
// If already loaded, we're done.
|
|
||||||
if (image->GetImageDebugInfo() != NULL) {
|
|
||||||
if (_imageDebugInfo != NULL) {
|
|
||||||
*_imageDebugInfo = image->GetImageDebugInfo();
|
|
||||||
(*_imageDebugInfo)->AcquireReference();
|
|
||||||
}
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If already loading, the caller has to wait, if desired.
|
|
||||||
if (image->ImageDebugInfoState() == IMAGE_DEBUG_INFO_LOADING) {
|
|
||||||
if (_imageDebugInfo != NULL)
|
|
||||||
*_imageDebugInfo = NULL;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If an earlier load attempt failed, bail out.
|
|
||||||
if (image->ImageDebugInfoState() != IMAGE_DEBUG_INFO_NOT_LOADED)
|
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
// schedule a job
|
|
||||||
LoadImageDebugInfoJob* job = new(std::nothrow) LoadImageDebugInfoJob(image);
|
|
||||||
if (job == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
status_t error = worker->ScheduleJob(job);
|
|
||||||
if (error != B_OK) {
|
|
||||||
image->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_UNAVAILABLE);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
image->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_LOADING);
|
|
||||||
|
|
||||||
if (_imageDebugInfo != NULL)
|
|
||||||
*_imageDebugInfo = NULL;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - LoadSourceCodeJob
|
|
||||||
|
|
||||||
|
|
||||||
LoadSourceCodeJob::LoadSourceCodeJob(
|
|
||||||
DebuggerInterface* debuggerInterface, Architecture* architecture,
|
|
||||||
Team* team, FunctionInstance* functionInstance, bool loadForFunction)
|
|
||||||
:
|
|
||||||
fKey(functionInstance, JOB_TYPE_LOAD_SOURCE_CODE),
|
|
||||||
fDebuggerInterface(debuggerInterface),
|
|
||||||
fArchitecture(architecture),
|
|
||||||
fTeam(team),
|
|
||||||
fFunctionInstance(functionInstance),
|
|
||||||
fLoadForFunction(loadForFunction)
|
|
||||||
{
|
|
||||||
fFunctionInstance->AcquireReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LoadSourceCodeJob::~LoadSourceCodeJob()
|
|
||||||
{
|
|
||||||
fFunctionInstance->ReleaseReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const JobKey&
|
|
||||||
LoadSourceCodeJob::Key() const
|
|
||||||
{
|
|
||||||
return fKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
LoadSourceCodeJob::Do()
|
|
||||||
{
|
|
||||||
// if requested, try loading the source code for the function
|
|
||||||
Function* function = fFunctionInstance->GetFunction();
|
|
||||||
if (fLoadForFunction) {
|
|
||||||
FileSourceCode* sourceCode;
|
|
||||||
status_t error = fTeam->DebugInfo()->LoadSourceCode(
|
|
||||||
function->SourceFile(), sourceCode);
|
|
||||||
|
|
||||||
AutoLocker<Team> locker(fTeam);
|
|
||||||
|
|
||||||
if (error == B_OK) {
|
|
||||||
function->SetSourceCode(sourceCode, FUNCTION_SOURCE_LOADED);
|
|
||||||
sourceCode->ReleaseReference();
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
function->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only try to load the function instance code, if it's not overridden yet.
|
|
||||||
AutoLocker<Team> locker(fTeam);
|
|
||||||
if (fFunctionInstance->SourceCodeState() != FUNCTION_SOURCE_LOADING)
|
|
||||||
return B_OK;
|
|
||||||
locker.Unlock();
|
|
||||||
|
|
||||||
// disassemble the function
|
|
||||||
DisassembledCode* sourceCode = NULL;
|
|
||||||
status_t error = fTeam->DebugInfo()->DisassembleFunction(fFunctionInstance,
|
|
||||||
sourceCode);
|
|
||||||
|
|
||||||
// set the result
|
|
||||||
locker.Lock();
|
|
||||||
if (error == B_OK) {
|
|
||||||
if (fFunctionInstance->SourceCodeState() == FUNCTION_SOURCE_LOADING) {
|
|
||||||
fFunctionInstance->SetSourceCode(sourceCode,
|
|
||||||
FUNCTION_SOURCE_LOADED);
|
|
||||||
sourceCode->ReleaseReference();
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
fFunctionInstance->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE);
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - ResolveValueNodeValueJob
|
|
||||||
|
|
||||||
|
|
||||||
ResolveValueNodeValueJob::ResolveValueNodeValueJob(
|
|
||||||
DebuggerInterface* debuggerInterface, Architecture* architecture,
|
|
||||||
CpuState* cpuState, TeamTypeInformation* typeInformation,
|
|
||||||
ValueNodeContainer* container, ValueNode* valueNode)
|
|
||||||
:
|
|
||||||
fKey(valueNode, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE),
|
|
||||||
fDebuggerInterface(debuggerInterface),
|
|
||||||
fArchitecture(architecture),
|
|
||||||
fCpuState(cpuState),
|
|
||||||
fTypeInformation(typeInformation),
|
|
||||||
fContainer(container),
|
|
||||||
fValueNode(valueNode)
|
|
||||||
{
|
|
||||||
if (fCpuState != NULL)
|
|
||||||
fCpuState->AcquireReference();
|
|
||||||
fContainer->AcquireReference();
|
|
||||||
fValueNode->AcquireReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ResolveValueNodeValueJob::~ResolveValueNodeValueJob()
|
|
||||||
{
|
|
||||||
if (fCpuState != NULL)
|
|
||||||
fCpuState->ReleaseReference();
|
|
||||||
fContainer->ReleaseReference();
|
|
||||||
fValueNode->ReleaseReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const JobKey&
|
|
||||||
ResolveValueNodeValueJob::Key() const
|
|
||||||
{
|
|
||||||
return fKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ResolveValueNodeValueJob::Do()
|
|
||||||
{
|
|
||||||
// check whether the node still belongs to the container
|
|
||||||
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
|
|
||||||
if (fValueNode->Container() != fContainer)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
// if already resolved, we're done
|
|
||||||
status_t nodeResolutionState
|
|
||||||
= fValueNode->LocationAndValueResolutionState();
|
|
||||||
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
|
|
||||||
return nodeResolutionState;
|
|
||||||
|
|
||||||
containerLocker.Unlock();
|
|
||||||
|
|
||||||
// resolve
|
|
||||||
status_t error = _ResolveNodeValue();
|
|
||||||
if (error != B_OK) {
|
|
||||||
nodeResolutionState = fValueNode->LocationAndValueResolutionState();
|
|
||||||
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
|
|
||||||
return nodeResolutionState;
|
|
||||||
|
|
||||||
containerLocker.Lock();
|
|
||||||
fValueNode->SetLocationAndValue(NULL, NULL, error);
|
|
||||||
containerLocker.Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ResolveValueNodeValueJob::_ResolveNodeValue()
|
|
||||||
{
|
|
||||||
// get the node child and parent node
|
|
||||||
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
|
|
||||||
ValueNodeChild* nodeChild = fValueNode->NodeChild();
|
|
||||||
BReference<ValueNodeChild> nodeChildReference(nodeChild);
|
|
||||||
|
|
||||||
ValueNode* parentNode = nodeChild->Parent();
|
|
||||||
BReference<ValueNode> parentNodeReference(parentNode);
|
|
||||||
|
|
||||||
// Check whether the node child location has been resolved already
|
|
||||||
// (successfully).
|
|
||||||
status_t nodeChildResolutionState = nodeChild->LocationResolutionState();
|
|
||||||
bool nodeChildDone = nodeChildResolutionState != VALUE_NODE_UNRESOLVED;
|
|
||||||
if (nodeChildDone && nodeChildResolutionState != B_OK)
|
|
||||||
return nodeChildResolutionState;
|
|
||||||
|
|
||||||
// If the child node location has not been resolved yet, check whether the
|
|
||||||
// parent node location and value have been resolved already (successfully).
|
|
||||||
bool parentDone = true;
|
|
||||||
if (!nodeChildDone && parentNode != NULL) {
|
|
||||||
status_t parentResolutionState
|
|
||||||
= parentNode->LocationAndValueResolutionState();
|
|
||||||
parentDone = parentResolutionState != VALUE_NODE_UNRESOLVED;
|
|
||||||
if (parentDone && parentResolutionState != B_OK)
|
|
||||||
return parentResolutionState;
|
|
||||||
}
|
|
||||||
|
|
||||||
containerLocker.Unlock();
|
|
||||||
|
|
||||||
// resolve the parent node location and value, if necessary
|
|
||||||
if (!parentDone) {
|
|
||||||
status_t error = _ResolveParentNodeValue(parentNode);
|
|
||||||
if (error != B_OK) {
|
|
||||||
TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
|
|
||||||
"node: %p (\"%s\"): _ResolveParentNodeValue(%p) failed\n",
|
|
||||||
fValueNode, fValueNode->Name().String(), parentNode);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (State() == JOB_STATE_WAITING)
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// resolve the node child location, if necessary
|
|
||||||
if (!nodeChildDone) {
|
|
||||||
status_t error = _ResolveNodeChildLocation(nodeChild);
|
|
||||||
if (error != B_OK) {
|
|
||||||
TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
|
|
||||||
"node: %p (\"%s\"): _ResolveNodeChildLocation(%p) failed\n",
|
|
||||||
fValueNode, fValueNode->Name().String(), nodeChild);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// resolve the node location and value
|
|
||||||
ValueLoader valueLoader(fArchitecture, fDebuggerInterface,
|
|
||||||
fTypeInformation, fCpuState);
|
|
||||||
ValueLocation* location;
|
|
||||||
Value* value;
|
|
||||||
status_t error = fValueNode->ResolvedLocationAndValue(&valueLoader,
|
|
||||||
location, value);
|
|
||||||
if (error != B_OK) {
|
|
||||||
TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
|
|
||||||
"node: %p (\"%s\"): fValueNode->ResolvedLocationAndValue() "
|
|
||||||
"failed\n", fValueNode, fValueNode->Name().String());
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
BReference<ValueLocation> locationReference(location, true);
|
|
||||||
BReference<Value> valueReference(value, true);
|
|
||||||
|
|
||||||
// set location and value on the node
|
|
||||||
containerLocker.Lock();
|
|
||||||
status_t nodeResolutionState
|
|
||||||
= fValueNode->LocationAndValueResolutionState();
|
|
||||||
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
|
|
||||||
return nodeResolutionState;
|
|
||||||
fValueNode->SetLocationAndValue(location, value, B_OK);
|
|
||||||
containerLocker.Unlock();
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ResolveValueNodeValueJob::_ResolveNodeChildLocation(ValueNodeChild* nodeChild)
|
|
||||||
{
|
|
||||||
// resolve the location
|
|
||||||
ValueLoader valueLoader(fArchitecture, fDebuggerInterface,
|
|
||||||
fTypeInformation, fCpuState);
|
|
||||||
ValueLocation* location = NULL;
|
|
||||||
status_t error = nodeChild->ResolveLocation(&valueLoader, location);
|
|
||||||
BReference<ValueLocation> locationReference(location, true);
|
|
||||||
|
|
||||||
// set the location on the node child
|
|
||||||
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
|
|
||||||
status_t nodeChildResolutionState = nodeChild->LocationResolutionState();
|
|
||||||
if (nodeChildResolutionState == VALUE_NODE_UNRESOLVED)
|
|
||||||
nodeChild->SetLocation(location, error);
|
|
||||||
else
|
|
||||||
error = nodeChildResolutionState;
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ResolveValueNodeValueJob::_ResolveParentNodeValue(ValueNode* parentNode)
|
|
||||||
{
|
|
||||||
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
|
|
||||||
|
|
||||||
if (parentNode->Container() != fContainer)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
// if the parent node already has a value, we're done
|
|
||||||
status_t nodeResolutionState
|
|
||||||
= parentNode->LocationAndValueResolutionState();
|
|
||||||
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
|
|
||||||
return nodeResolutionState;
|
|
||||||
|
|
||||||
// check whether a job is already in progress
|
|
||||||
AutoLocker<Worker> workerLocker(GetWorker());
|
|
||||||
SimpleJobKey jobKey(parentNode, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE);
|
|
||||||
if (GetWorker()->GetJob(jobKey) == NULL) {
|
|
||||||
workerLocker.Unlock();
|
|
||||||
|
|
||||||
// schedule the job
|
|
||||||
status_t error = GetWorker()->ScheduleJob(
|
|
||||||
new(std::nothrow) ResolveValueNodeValueJob(fDebuggerInterface,
|
|
||||||
fArchitecture, fCpuState, fTypeInformation, fContainer,
|
|
||||||
parentNode));
|
|
||||||
if (error != B_OK) {
|
|
||||||
// scheduling failed -- set the value to invalid
|
|
||||||
parentNode->SetLocationAndValue(NULL, NULL, error);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait for the job to finish
|
|
||||||
workerLocker.Unlock();
|
|
||||||
containerLocker.Unlock();
|
|
||||||
|
|
||||||
switch (WaitFor(jobKey)) {
|
|
||||||
case JOB_DEPENDENCY_SUCCEEDED:
|
|
||||||
case JOB_DEPENDENCY_NOT_FOUND:
|
|
||||||
// "Not found" can happen due to a race condition between
|
|
||||||
// unlocking the worker and starting to wait.
|
|
||||||
break;
|
|
||||||
case JOB_DEPENDENCY_ACTIVE:
|
|
||||||
return B_OK;
|
|
||||||
case JOB_DEPENDENCY_FAILED:
|
|
||||||
case JOB_DEPENDENCY_ABORTED:
|
|
||||||
default:
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
containerLocker.Lock();
|
|
||||||
|
|
||||||
// now there should be a value for the node
|
|
||||||
nodeResolutionState = parentNode->LocationAndValueResolutionState();
|
|
||||||
return nodeResolutionState != VALUE_NODE_UNRESOLVED
|
|
||||||
? nodeResolutionState : B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RetrieveMemoryBlockJob::RetrieveMemoryBlockJob(Team* team,
|
|
||||||
TeamMemory* teamMemory, TeamMemoryBlock* memoryBlock)
|
|
||||||
:
|
|
||||||
fKey(memoryBlock, JOB_TYPE_GET_MEMORY_BLOCK),
|
|
||||||
fTeam(team),
|
|
||||||
fTeamMemory(teamMemory),
|
|
||||||
fMemoryBlock(memoryBlock)
|
|
||||||
{
|
|
||||||
fTeamMemory->AcquireReference();
|
|
||||||
fMemoryBlock->AcquireReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RetrieveMemoryBlockJob::~RetrieveMemoryBlockJob()
|
|
||||||
{
|
|
||||||
fTeamMemory->ReleaseReference();
|
|
||||||
fMemoryBlock->ReleaseReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const JobKey&
|
|
||||||
RetrieveMemoryBlockJob::Key() const
|
|
||||||
{
|
|
||||||
return fKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
RetrieveMemoryBlockJob::Do()
|
|
||||||
{
|
|
||||||
ssize_t result = fTeamMemory->ReadMemory(fMemoryBlock->BaseAddress(),
|
|
||||||
fMemoryBlock->Data(), fMemoryBlock->Size());
|
|
||||||
if (result < 0)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
uint32 protection = 0;
|
|
||||||
uint32 locking = 0;
|
|
||||||
status_t error = get_memory_properties(fTeam->ID(),
|
|
||||||
(const void *)fMemoryBlock->BaseAddress(), &protection, &locking);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
fMemoryBlock->SetWritable((protection & B_WRITE_AREA) != 0);
|
|
||||||
fMemoryBlock->MarkValid();
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
@@ -29,6 +29,7 @@ enum {
|
|||||||
MSG_IMAGE_FILE_CHANGED = 'ifch',
|
MSG_IMAGE_FILE_CHANGED = 'ifch',
|
||||||
MSG_FUNCTION_SOURCE_CODE_CHANGED = 'fnsc',
|
MSG_FUNCTION_SOURCE_CODE_CHANGED = 'fnsc',
|
||||||
MSG_USER_BREAKPOINT_CHANGED = 'ubrc',
|
MSG_USER_BREAKPOINT_CHANGED = 'ubrc',
|
||||||
|
MSG_WATCHPOINT_CHANGED = 'wapc',
|
||||||
MSG_DEBUGGER_EVENT = 'dbge',
|
MSG_DEBUGGER_EVENT = 'dbge',
|
||||||
MSG_LOAD_SETTINGS = 'ldst',
|
MSG_LOAD_SETTINGS = 'ldst',
|
||||||
|
|
||||||
@@ -53,7 +54,8 @@ enum {
|
|||||||
MSG_INSPECTOR_WINDOW_CLOSED = 'irwc',
|
MSG_INSPECTOR_WINDOW_CLOSED = 'irwc',
|
||||||
MSG_INSPECT_ADDRESS = 'isad',
|
MSG_INSPECT_ADDRESS = 'isad',
|
||||||
MSG_SHOW_TYPECAST_NODE_PROMPT = 'stnp',
|
MSG_SHOW_TYPECAST_NODE_PROMPT = 'stnp',
|
||||||
MSG_TYPECAST_NODE = 'tyno'
|
MSG_TYPECAST_NODE = 'tyno',
|
||||||
|
MSG_SHOW_WATCH_VARIABLE_PROMPT = 'swvp'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-16
@@ -46,7 +46,7 @@
|
|||||||
#include "ValueNodeContainer.h"
|
#include "ValueNodeContainer.h"
|
||||||
#include "Variable.h"
|
#include "Variable.h"
|
||||||
#include "WatchpointManager.h"
|
#include "WatchpointManager.h"
|
||||||
#include "WatchpointSetting.h"
|
|
||||||
|
|
||||||
// #pragma mark - ImageHandler
|
// #pragma mark - ImageHandler
|
||||||
|
|
||||||
@@ -1583,21 +1583,6 @@ TeamDebugger::_LoadSettings()
|
|||||||
breakpointSetting->IsEnabled());
|
breakpointSetting->IsEnabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the saved watchpoints;
|
|
||||||
for (int32 i = 0; const WatchpointSetting* watchpointSetting
|
|
||||||
= fTeamSettings.WatchpointAt(i); i++) {
|
|
||||||
Watchpoint* watchpoint = new(std::nothrow) Watchpoint(
|
|
||||||
watchpointSetting->Address(), watchpointSetting->Type(),
|
|
||||||
watchpointSetting->Length());
|
|
||||||
if (watchpoint == NULL)
|
|
||||||
return;
|
|
||||||
BReference<Watchpoint> watchpointReference(watchpoint, true);
|
|
||||||
|
|
||||||
// install it
|
|
||||||
fWatchpointManager->InstallWatchpoint(watchpoint,
|
|
||||||
watchpointSetting->IsEnabled());
|
|
||||||
}
|
|
||||||
|
|
||||||
const TeamUiSettings* uiSettings = fTeamSettings.UiSettingFor(
|
const TeamUiSettings* uiSettings = fTeamSettings.UiSettingFor(
|
||||||
fUserInterface->ID());
|
fUserInterface->ID());
|
||||||
if (uiSettings != NULL)
|
if (uiSettings != NULL)
|
||||||
+11
-1
@@ -74,6 +74,12 @@ WatchpointManager::InstallWatchpoint(Watchpoint* watchpoint,
|
|||||||
watchpoint->SetInstalled(false);
|
watchpoint->SetInstalled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (error == B_OK) {
|
||||||
|
if (fTeam->WatchpointAtAddress(watchpoint->Address()) == NULL)
|
||||||
|
fTeam->AddWatchpoint(watchpoint);
|
||||||
|
fTeam->NotifyWatchpointChanged(watchpoint);
|
||||||
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,12 +90,16 @@ WatchpointManager::UninstallWatchpoint(Watchpoint* watchpoint)
|
|||||||
AutoLocker<BLocker> installLocker(fLock);
|
AutoLocker<BLocker> installLocker(fLock);
|
||||||
AutoLocker<Team> teamLocker(fTeam);
|
AutoLocker<Team> teamLocker(fTeam);
|
||||||
|
|
||||||
|
fTeam->RemoveWatchpoint(watchpoint);
|
||||||
|
|
||||||
if (!watchpoint->IsInstalled())
|
if (!watchpoint->IsInstalled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
status_t error = fDebuggerInterface->UninstallWatchpoint(
|
status_t error = fDebuggerInterface->UninstallWatchpoint(
|
||||||
watchpoint->Address());
|
watchpoint->Address());
|
||||||
|
|
||||||
if (error == B_OK)
|
if (error == B_OK) {
|
||||||
watchpoint->SetInstalled(false);
|
watchpoint->SetInstalled(false);
|
||||||
|
fTeam->NotifyWatchpointChanged(watchpoint);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Rene Gollent, rene@gollent.com.
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Jobs.h"
|
||||||
|
|
||||||
|
#include <AutoLocker.h>
|
||||||
|
|
||||||
|
#include "CpuState.h"
|
||||||
|
#include "DebuggerInterface.h"
|
||||||
|
#include "Team.h"
|
||||||
|
#include "Thread.h"
|
||||||
|
|
||||||
|
|
||||||
|
GetCpuStateJob::GetCpuStateJob(DebuggerInterface* debuggerInterface,
|
||||||
|
Thread* thread)
|
||||||
|
:
|
||||||
|
fKey(thread, JOB_TYPE_GET_CPU_STATE),
|
||||||
|
fDebuggerInterface(debuggerInterface),
|
||||||
|
fThread(thread)
|
||||||
|
{
|
||||||
|
fThread->AcquireReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GetCpuStateJob::~GetCpuStateJob()
|
||||||
|
{
|
||||||
|
fThread->ReleaseReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const JobKey&
|
||||||
|
GetCpuStateJob::Key() const
|
||||||
|
{
|
||||||
|
return fKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
GetCpuStateJob::Do()
|
||||||
|
{
|
||||||
|
CpuState* state;
|
||||||
|
status_t error = fDebuggerInterface->GetCpuState(fThread->ID(), state);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
BReference<CpuState> reference(state, true);
|
||||||
|
|
||||||
|
AutoLocker<Team> locker(fThread->GetTeam());
|
||||||
|
|
||||||
|
if (fThread->State() == THREAD_STATE_STOPPED)
|
||||||
|
fThread->SetCpuState(state);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Rene Gollent, rene@gollent.com.
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Jobs.h"
|
||||||
|
|
||||||
|
#include <AutoLocker.h>
|
||||||
|
|
||||||
|
#include "Architecture.h"
|
||||||
|
#include "CpuState.h"
|
||||||
|
#include "DebuggerInterface.h"
|
||||||
|
#include "ImageDebugInfo.h"
|
||||||
|
#include "StackTrace.h"
|
||||||
|
#include "Thread.h"
|
||||||
|
#include "Team.h"
|
||||||
|
|
||||||
|
|
||||||
|
GetStackTraceJob::GetStackTraceJob(DebuggerInterface* debuggerInterface,
|
||||||
|
Architecture* architecture, Thread* thread)
|
||||||
|
:
|
||||||
|
fKey(thread, JOB_TYPE_GET_STACK_TRACE),
|
||||||
|
fDebuggerInterface(debuggerInterface),
|
||||||
|
fArchitecture(architecture),
|
||||||
|
fThread(thread)
|
||||||
|
{
|
||||||
|
fThread->AcquireReference();
|
||||||
|
|
||||||
|
fCpuState = fThread->GetCpuState();
|
||||||
|
if (fCpuState != NULL)
|
||||||
|
fCpuState->AcquireReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GetStackTraceJob::~GetStackTraceJob()
|
||||||
|
{
|
||||||
|
if (fCpuState != NULL)
|
||||||
|
fCpuState->ReleaseReference();
|
||||||
|
|
||||||
|
fThread->ReleaseReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const JobKey&
|
||||||
|
GetStackTraceJob::Key() const
|
||||||
|
{
|
||||||
|
return fKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
GetStackTraceJob::Do()
|
||||||
|
{
|
||||||
|
if (fCpuState == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// get the stack trace
|
||||||
|
StackTrace* stackTrace;
|
||||||
|
status_t error = fArchitecture->CreateStackTrace(fThread->GetTeam(), this,
|
||||||
|
fCpuState, stackTrace);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
BReference<StackTrace> stackTraceReference(stackTrace, true);
|
||||||
|
|
||||||
|
// set the stack trace, unless something has changed
|
||||||
|
AutoLocker<Team> locker(fThread->GetTeam());
|
||||||
|
|
||||||
|
if (fThread->GetCpuState() == fCpuState)
|
||||||
|
fThread->SetStackTrace(stackTrace);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
GetStackTraceJob::GetImageDebugInfo(Image* image, ImageDebugInfo*& _info)
|
||||||
|
{
|
||||||
|
AutoLocker<Team> teamLocker(fThread->GetTeam());
|
||||||
|
|
||||||
|
while (image->GetImageDebugInfo() == NULL) {
|
||||||
|
// schedule a job, if not loaded
|
||||||
|
ImageDebugInfo* info;
|
||||||
|
status_t error = LoadImageDebugInfoJob::ScheduleIfNecessary(GetWorker(),
|
||||||
|
image, &info);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
if (info != NULL) {
|
||||||
|
_info = info;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
teamLocker.Unlock();
|
||||||
|
|
||||||
|
// wait for the job to finish
|
||||||
|
switch (WaitFor(SimpleJobKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO))) {
|
||||||
|
case JOB_DEPENDENCY_SUCCEEDED:
|
||||||
|
case JOB_DEPENDENCY_NOT_FOUND:
|
||||||
|
// "Not found" can happen due to a race condition between
|
||||||
|
// unlocking the worker and starting to wait.
|
||||||
|
break;
|
||||||
|
case JOB_DEPENDENCY_FAILED:
|
||||||
|
case JOB_DEPENDENCY_ABORTED:
|
||||||
|
default:
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
teamLocker.Lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
_info = image->GetImageDebugInfo();
|
||||||
|
_info->AcquireReference();
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Rene Gollent, rene@gollent.com.
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Jobs.h"
|
||||||
|
|
||||||
|
#include <AutoLocker.h>
|
||||||
|
|
||||||
|
#include "CpuState.h"
|
||||||
|
#include "DebuggerInterface.h"
|
||||||
|
#include "Team.h"
|
||||||
|
#include "Thread.h"
|
||||||
|
|
||||||
|
|
||||||
|
GetThreadStateJob::GetThreadStateJob(DebuggerInterface* debuggerInterface,
|
||||||
|
Thread* thread)
|
||||||
|
:
|
||||||
|
fKey(thread, JOB_TYPE_GET_THREAD_STATE),
|
||||||
|
fDebuggerInterface(debuggerInterface),
|
||||||
|
fThread(thread)
|
||||||
|
{
|
||||||
|
fThread->AcquireReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GetThreadStateJob::~GetThreadStateJob()
|
||||||
|
{
|
||||||
|
fThread->ReleaseReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const JobKey&
|
||||||
|
GetThreadStateJob::Key() const
|
||||||
|
{
|
||||||
|
return fKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
GetThreadStateJob::Do()
|
||||||
|
{
|
||||||
|
CpuState* state = NULL;
|
||||||
|
status_t error = fDebuggerInterface->GetCpuState(fThread->ID(), state);
|
||||||
|
BReference<CpuState> reference(state, true);
|
||||||
|
|
||||||
|
AutoLocker<Team> locker(fThread->GetTeam());
|
||||||
|
|
||||||
|
if (fThread->State() != THREAD_STATE_UNKNOWN)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
if (error == B_OK) {
|
||||||
|
fThread->SetState(THREAD_STATE_STOPPED);
|
||||||
|
fThread->SetCpuState(state);
|
||||||
|
} else if (error == B_BAD_THREAD_STATE) {
|
||||||
|
fThread->SetState(THREAD_STATE_RUNNING);
|
||||||
|
} else
|
||||||
|
return error;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Rene Gollent, rene@gollent.com.
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Jobs.h"
|
||||||
|
|
||||||
|
#include <AutoLocker.h>
|
||||||
|
|
||||||
|
#include "Image.h"
|
||||||
|
#include "ImageDebugInfo.h"
|
||||||
|
#include "TeamDebugInfo.h"
|
||||||
|
#include "Team.h"
|
||||||
|
|
||||||
|
|
||||||
|
LoadImageDebugInfoJob::LoadImageDebugInfoJob(Image* image)
|
||||||
|
:
|
||||||
|
fKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO),
|
||||||
|
fImage(image)
|
||||||
|
{
|
||||||
|
fImage->AcquireReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LoadImageDebugInfoJob::~LoadImageDebugInfoJob()
|
||||||
|
{
|
||||||
|
fImage->ReleaseReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const JobKey&
|
||||||
|
LoadImageDebugInfoJob::Key() const
|
||||||
|
{
|
||||||
|
return fKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
LoadImageDebugInfoJob::Do()
|
||||||
|
{
|
||||||
|
// get an image info for the image
|
||||||
|
AutoLocker<Team> locker(fImage->GetTeam());
|
||||||
|
ImageInfo imageInfo(fImage->Info());
|
||||||
|
locker.Unlock();
|
||||||
|
|
||||||
|
// create the debug info
|
||||||
|
ImageDebugInfo* debugInfo;
|
||||||
|
status_t error = fImage->GetTeam()->DebugInfo()->LoadImageDebugInfo(
|
||||||
|
imageInfo, fImage->ImageFile(), debugInfo);
|
||||||
|
|
||||||
|
// set the result
|
||||||
|
locker.Lock();
|
||||||
|
if (error == B_OK) {
|
||||||
|
error = fImage->SetImageDebugInfo(debugInfo, IMAGE_DEBUG_INFO_LOADED);
|
||||||
|
debugInfo->ReleaseReference();
|
||||||
|
} else
|
||||||
|
fImage->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_UNAVAILABLE);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ status_t
|
||||||
|
LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image,
|
||||||
|
ImageDebugInfo** _imageDebugInfo)
|
||||||
|
{
|
||||||
|
AutoLocker<Team> teamLocker(image->GetTeam());
|
||||||
|
|
||||||
|
// If already loaded, we're done.
|
||||||
|
if (image->GetImageDebugInfo() != NULL) {
|
||||||
|
if (_imageDebugInfo != NULL) {
|
||||||
|
*_imageDebugInfo = image->GetImageDebugInfo();
|
||||||
|
(*_imageDebugInfo)->AcquireReference();
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If already loading, the caller has to wait, if desired.
|
||||||
|
if (image->ImageDebugInfoState() == IMAGE_DEBUG_INFO_LOADING) {
|
||||||
|
if (_imageDebugInfo != NULL)
|
||||||
|
*_imageDebugInfo = NULL;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If an earlier load attempt failed, bail out.
|
||||||
|
if (image->ImageDebugInfoState() != IMAGE_DEBUG_INFO_NOT_LOADED)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
// schedule a job
|
||||||
|
LoadImageDebugInfoJob* job = new(std::nothrow) LoadImageDebugInfoJob(image);
|
||||||
|
if (job == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
status_t error = worker->ScheduleJob(job);
|
||||||
|
if (error != B_OK) {
|
||||||
|
image->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_UNAVAILABLE);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
image->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_LOADING);
|
||||||
|
|
||||||
|
if (_imageDebugInfo != NULL)
|
||||||
|
*_imageDebugInfo = NULL;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Rene Gollent, rene@gollent.com.
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Jobs.h"
|
||||||
|
|
||||||
|
#include <AutoLocker.h>
|
||||||
|
|
||||||
|
#include "Architecture.h"
|
||||||
|
#include "DebuggerInterface.h"
|
||||||
|
#include "DisassembledCode.h"
|
||||||
|
#include "Function.h"
|
||||||
|
#include "FunctionInstance.h"
|
||||||
|
#include "FileSourceCode.h"
|
||||||
|
#include "Team.h"
|
||||||
|
#include "TeamDebugInfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
LoadSourceCodeJob::LoadSourceCodeJob(
|
||||||
|
DebuggerInterface* debuggerInterface, Architecture* architecture,
|
||||||
|
Team* team, FunctionInstance* functionInstance, bool loadForFunction)
|
||||||
|
:
|
||||||
|
fKey(functionInstance, JOB_TYPE_LOAD_SOURCE_CODE),
|
||||||
|
fDebuggerInterface(debuggerInterface),
|
||||||
|
fArchitecture(architecture),
|
||||||
|
fTeam(team),
|
||||||
|
fFunctionInstance(functionInstance),
|
||||||
|
fLoadForFunction(loadForFunction)
|
||||||
|
{
|
||||||
|
fFunctionInstance->AcquireReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LoadSourceCodeJob::~LoadSourceCodeJob()
|
||||||
|
{
|
||||||
|
fFunctionInstance->ReleaseReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const JobKey&
|
||||||
|
LoadSourceCodeJob::Key() const
|
||||||
|
{
|
||||||
|
return fKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
LoadSourceCodeJob::Do()
|
||||||
|
{
|
||||||
|
// if requested, try loading the source code for the function
|
||||||
|
Function* function = fFunctionInstance->GetFunction();
|
||||||
|
if (fLoadForFunction) {
|
||||||
|
FileSourceCode* sourceCode;
|
||||||
|
status_t error = fTeam->DebugInfo()->LoadSourceCode(
|
||||||
|
function->SourceFile(), sourceCode);
|
||||||
|
|
||||||
|
AutoLocker<Team> locker(fTeam);
|
||||||
|
|
||||||
|
if (error == B_OK) {
|
||||||
|
function->SetSourceCode(sourceCode, FUNCTION_SOURCE_LOADED);
|
||||||
|
sourceCode->ReleaseReference();
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
function->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only try to load the function instance code, if it's not overridden yet.
|
||||||
|
AutoLocker<Team> locker(fTeam);
|
||||||
|
if (fFunctionInstance->SourceCodeState() != FUNCTION_SOURCE_LOADING)
|
||||||
|
return B_OK;
|
||||||
|
locker.Unlock();
|
||||||
|
|
||||||
|
// disassemble the function
|
||||||
|
DisassembledCode* sourceCode = NULL;
|
||||||
|
status_t error = fTeam->DebugInfo()->DisassembleFunction(fFunctionInstance,
|
||||||
|
sourceCode);
|
||||||
|
|
||||||
|
// set the result
|
||||||
|
locker.Lock();
|
||||||
|
if (error == B_OK) {
|
||||||
|
if (fFunctionInstance->SourceCodeState() == FUNCTION_SOURCE_LOADING) {
|
||||||
|
fFunctionInstance->SetSourceCode(sourceCode,
|
||||||
|
FUNCTION_SOURCE_LOADED);
|
||||||
|
sourceCode->ReleaseReference();
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
fFunctionInstance->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
@@ -0,0 +1,254 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Rene Gollent, rene@gollent.com.
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Jobs.h"
|
||||||
|
|
||||||
|
#include <AutoLocker.h>
|
||||||
|
|
||||||
|
#include "Architecture.h"
|
||||||
|
#include "CpuState.h"
|
||||||
|
#include "DebuggerInterface.h"
|
||||||
|
#include "TeamTypeInformation.h"
|
||||||
|
#include "Tracing.h"
|
||||||
|
#include "Value.h"
|
||||||
|
#include "ValueLoader.h"
|
||||||
|
#include "ValueLocation.h"
|
||||||
|
#include "ValueNode.h"
|
||||||
|
#include "ValueNodeContainer.h"
|
||||||
|
|
||||||
|
|
||||||
|
ResolveValueNodeValueJob::ResolveValueNodeValueJob(
|
||||||
|
DebuggerInterface* debuggerInterface, Architecture* architecture,
|
||||||
|
CpuState* cpuState, TeamTypeInformation* typeInformation,
|
||||||
|
ValueNodeContainer* container, ValueNode* valueNode)
|
||||||
|
:
|
||||||
|
fKey(valueNode, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE),
|
||||||
|
fDebuggerInterface(debuggerInterface),
|
||||||
|
fArchitecture(architecture),
|
||||||
|
fCpuState(cpuState),
|
||||||
|
fTypeInformation(typeInformation),
|
||||||
|
fContainer(container),
|
||||||
|
fValueNode(valueNode)
|
||||||
|
{
|
||||||
|
if (fCpuState != NULL)
|
||||||
|
fCpuState->AcquireReference();
|
||||||
|
fContainer->AcquireReference();
|
||||||
|
fValueNode->AcquireReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ResolveValueNodeValueJob::~ResolveValueNodeValueJob()
|
||||||
|
{
|
||||||
|
if (fCpuState != NULL)
|
||||||
|
fCpuState->ReleaseReference();
|
||||||
|
fContainer->ReleaseReference();
|
||||||
|
fValueNode->ReleaseReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const JobKey&
|
||||||
|
ResolveValueNodeValueJob::Key() const
|
||||||
|
{
|
||||||
|
return fKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ResolveValueNodeValueJob::Do()
|
||||||
|
{
|
||||||
|
// check whether the node still belongs to the container
|
||||||
|
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
|
||||||
|
if (fValueNode->Container() != fContainer)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// if already resolved, we're done
|
||||||
|
status_t nodeResolutionState
|
||||||
|
= fValueNode->LocationAndValueResolutionState();
|
||||||
|
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
|
||||||
|
return nodeResolutionState;
|
||||||
|
|
||||||
|
containerLocker.Unlock();
|
||||||
|
|
||||||
|
// resolve
|
||||||
|
status_t error = _ResolveNodeValue();
|
||||||
|
if (error != B_OK) {
|
||||||
|
nodeResolutionState = fValueNode->LocationAndValueResolutionState();
|
||||||
|
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
|
||||||
|
return nodeResolutionState;
|
||||||
|
|
||||||
|
containerLocker.Lock();
|
||||||
|
fValueNode->SetLocationAndValue(NULL, NULL, error);
|
||||||
|
containerLocker.Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ResolveValueNodeValueJob::_ResolveNodeValue()
|
||||||
|
{
|
||||||
|
// get the node child and parent node
|
||||||
|
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
|
||||||
|
ValueNodeChild* nodeChild = fValueNode->NodeChild();
|
||||||
|
BReference<ValueNodeChild> nodeChildReference(nodeChild);
|
||||||
|
|
||||||
|
ValueNode* parentNode = nodeChild->Parent();
|
||||||
|
BReference<ValueNode> parentNodeReference(parentNode);
|
||||||
|
|
||||||
|
// Check whether the node child location has been resolved already
|
||||||
|
// (successfully).
|
||||||
|
status_t nodeChildResolutionState = nodeChild->LocationResolutionState();
|
||||||
|
bool nodeChildDone = nodeChildResolutionState != VALUE_NODE_UNRESOLVED;
|
||||||
|
if (nodeChildDone && nodeChildResolutionState != B_OK)
|
||||||
|
return nodeChildResolutionState;
|
||||||
|
|
||||||
|
// If the child node location has not been resolved yet, check whether the
|
||||||
|
// parent node location and value have been resolved already (successfully).
|
||||||
|
bool parentDone = true;
|
||||||
|
if (!nodeChildDone && parentNode != NULL) {
|
||||||
|
status_t parentResolutionState
|
||||||
|
= parentNode->LocationAndValueResolutionState();
|
||||||
|
parentDone = parentResolutionState != VALUE_NODE_UNRESOLVED;
|
||||||
|
if (parentDone && parentResolutionState != B_OK)
|
||||||
|
return parentResolutionState;
|
||||||
|
}
|
||||||
|
|
||||||
|
containerLocker.Unlock();
|
||||||
|
|
||||||
|
// resolve the parent node location and value, if necessary
|
||||||
|
if (!parentDone) {
|
||||||
|
status_t error = _ResolveParentNodeValue(parentNode);
|
||||||
|
if (error != B_OK) {
|
||||||
|
TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
|
||||||
|
"node: %p (\"%s\"): _ResolveParentNodeValue(%p) failed\n",
|
||||||
|
fValueNode, fValueNode->Name().String(), parentNode);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (State() == JOB_STATE_WAITING)
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolve the node child location, if necessary
|
||||||
|
if (!nodeChildDone) {
|
||||||
|
status_t error = _ResolveNodeChildLocation(nodeChild);
|
||||||
|
if (error != B_OK) {
|
||||||
|
TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
|
||||||
|
"node: %p (\"%s\"): _ResolveNodeChildLocation(%p) failed\n",
|
||||||
|
fValueNode, fValueNode->Name().String(), nodeChild);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolve the node location and value
|
||||||
|
ValueLoader valueLoader(fArchitecture, fDebuggerInterface,
|
||||||
|
fTypeInformation, fCpuState);
|
||||||
|
ValueLocation* location;
|
||||||
|
Value* value;
|
||||||
|
status_t error = fValueNode->ResolvedLocationAndValue(&valueLoader,
|
||||||
|
location, value);
|
||||||
|
if (error != B_OK) {
|
||||||
|
TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
|
||||||
|
"node: %p (\"%s\"): fValueNode->ResolvedLocationAndValue() "
|
||||||
|
"failed\n", fValueNode, fValueNode->Name().String());
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
BReference<ValueLocation> locationReference(location, true);
|
||||||
|
BReference<Value> valueReference(value, true);
|
||||||
|
|
||||||
|
// set location and value on the node
|
||||||
|
containerLocker.Lock();
|
||||||
|
status_t nodeResolutionState
|
||||||
|
= fValueNode->LocationAndValueResolutionState();
|
||||||
|
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
|
||||||
|
return nodeResolutionState;
|
||||||
|
fValueNode->SetLocationAndValue(location, value, B_OK);
|
||||||
|
containerLocker.Unlock();
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ResolveValueNodeValueJob::_ResolveNodeChildLocation(ValueNodeChild* nodeChild)
|
||||||
|
{
|
||||||
|
// resolve the location
|
||||||
|
ValueLoader valueLoader(fArchitecture, fDebuggerInterface,
|
||||||
|
fTypeInformation, fCpuState);
|
||||||
|
ValueLocation* location = NULL;
|
||||||
|
status_t error = nodeChild->ResolveLocation(&valueLoader, location);
|
||||||
|
BReference<ValueLocation> locationReference(location, true);
|
||||||
|
|
||||||
|
// set the location on the node child
|
||||||
|
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
|
||||||
|
status_t nodeChildResolutionState = nodeChild->LocationResolutionState();
|
||||||
|
if (nodeChildResolutionState == VALUE_NODE_UNRESOLVED)
|
||||||
|
nodeChild->SetLocation(location, error);
|
||||||
|
else
|
||||||
|
error = nodeChildResolutionState;
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ResolveValueNodeValueJob::_ResolveParentNodeValue(ValueNode* parentNode)
|
||||||
|
{
|
||||||
|
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
|
||||||
|
|
||||||
|
if (parentNode->Container() != fContainer)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// if the parent node already has a value, we're done
|
||||||
|
status_t nodeResolutionState
|
||||||
|
= parentNode->LocationAndValueResolutionState();
|
||||||
|
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
|
||||||
|
return nodeResolutionState;
|
||||||
|
|
||||||
|
// check whether a job is already in progress
|
||||||
|
AutoLocker<Worker> workerLocker(GetWorker());
|
||||||
|
SimpleJobKey jobKey(parentNode, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE);
|
||||||
|
if (GetWorker()->GetJob(jobKey) == NULL) {
|
||||||
|
workerLocker.Unlock();
|
||||||
|
|
||||||
|
// schedule the job
|
||||||
|
status_t error = GetWorker()->ScheduleJob(
|
||||||
|
new(std::nothrow) ResolveValueNodeValueJob(fDebuggerInterface,
|
||||||
|
fArchitecture, fCpuState, fTypeInformation, fContainer,
|
||||||
|
parentNode));
|
||||||
|
if (error != B_OK) {
|
||||||
|
// scheduling failed -- set the value to invalid
|
||||||
|
parentNode->SetLocationAndValue(NULL, NULL, error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for the job to finish
|
||||||
|
workerLocker.Unlock();
|
||||||
|
containerLocker.Unlock();
|
||||||
|
|
||||||
|
switch (WaitFor(jobKey)) {
|
||||||
|
case JOB_DEPENDENCY_SUCCEEDED:
|
||||||
|
case JOB_DEPENDENCY_NOT_FOUND:
|
||||||
|
// "Not found" can happen due to a race condition between
|
||||||
|
// unlocking the worker and starting to wait.
|
||||||
|
break;
|
||||||
|
case JOB_DEPENDENCY_ACTIVE:
|
||||||
|
return B_OK;
|
||||||
|
case JOB_DEPENDENCY_FAILED:
|
||||||
|
case JOB_DEPENDENCY_ABORTED:
|
||||||
|
default:
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
containerLocker.Lock();
|
||||||
|
|
||||||
|
// now there should be a value for the node
|
||||||
|
nodeResolutionState = parentNode->LocationAndValueResolutionState();
|
||||||
|
return nodeResolutionState != VALUE_NODE_UNRESOLVED
|
||||||
|
? nodeResolutionState : B_ERROR;
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Rene Gollent, rene@gollent.com.
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Jobs.h"
|
||||||
|
|
||||||
|
#include <AutoLocker.h>
|
||||||
|
#include <memory_private.h>
|
||||||
|
|
||||||
|
#include "Team.h"
|
||||||
|
#include "TeamMemory.h"
|
||||||
|
#include "TeamMemoryBlock.h"
|
||||||
|
|
||||||
|
|
||||||
|
RetrieveMemoryBlockJob::RetrieveMemoryBlockJob(Team* team,
|
||||||
|
TeamMemory* teamMemory, TeamMemoryBlock* memoryBlock)
|
||||||
|
:
|
||||||
|
fKey(memoryBlock, JOB_TYPE_GET_MEMORY_BLOCK),
|
||||||
|
fTeam(team),
|
||||||
|
fTeamMemory(teamMemory),
|
||||||
|
fMemoryBlock(memoryBlock)
|
||||||
|
{
|
||||||
|
fTeamMemory->AcquireReference();
|
||||||
|
fMemoryBlock->AcquireReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RetrieveMemoryBlockJob::~RetrieveMemoryBlockJob()
|
||||||
|
{
|
||||||
|
fTeamMemory->ReleaseReference();
|
||||||
|
fMemoryBlock->ReleaseReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const JobKey&
|
||||||
|
RetrieveMemoryBlockJob::Key() const
|
||||||
|
{
|
||||||
|
return fKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
RetrieveMemoryBlockJob::Do()
|
||||||
|
{
|
||||||
|
ssize_t result = fTeamMemory->ReadMemory(fMemoryBlock->BaseAddress(),
|
||||||
|
fMemoryBlock->Data(), fMemoryBlock->Size());
|
||||||
|
if (result < 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
uint32 protection = 0;
|
||||||
|
uint32 locking = 0;
|
||||||
|
status_t error = get_memory_properties(fTeam->ID(),
|
||||||
|
(const void *)fMemoryBlock->BaseAddress(), &protection, &locking);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
fMemoryBlock->SetWritable((protection & B_WRITE_AREA) != 0);
|
||||||
|
fMemoryBlock->MarkValid();
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
@@ -92,6 +92,9 @@ Team::~Team()
|
|||||||
for (int32 i = 0; Breakpoint* breakpoint = fBreakpoints.ItemAt(i); i++)
|
for (int32 i = 0; Breakpoint* breakpoint = fBreakpoints.ItemAt(i); i++)
|
||||||
breakpoint->ReleaseReference();
|
breakpoint->ReleaseReference();
|
||||||
|
|
||||||
|
for (int32 i = 0; Watchpoint* watchpoint = fWatchpoints.ItemAt(i); i++)
|
||||||
|
watchpoint->ReleaseReference();
|
||||||
|
|
||||||
while (Image* image = fImages.RemoveHead())
|
while (Image* image = fImages.RemoveHead())
|
||||||
image->ReleaseReference();
|
image->ReleaseReference();
|
||||||
|
|
||||||
|
|||||||
@@ -145,6 +145,8 @@ public:
|
|||||||
TargetAddressRange range,
|
TargetAddressRange range,
|
||||||
BObjectList<Watchpoint>& watchpoints)
|
BObjectList<Watchpoint>& watchpoints)
|
||||||
const;
|
const;
|
||||||
|
const WatchpointList& Watchpoints() const
|
||||||
|
{ return fWatchpoints; }
|
||||||
|
|
||||||
status_t GetStatementAtAddress(target_addr_t address,
|
status_t GetStatementAtAddress(target_addr_t address,
|
||||||
FunctionInstance*& _function,
|
FunctionInstance*& _function,
|
||||||
@@ -187,7 +189,6 @@ private:
|
|||||||
|
|
||||||
typedef BObjectList<Breakpoint> BreakpointList;
|
typedef BObjectList<Breakpoint> BreakpointList;
|
||||||
typedef DoublyLinkedList<Listener> ListenerList;
|
typedef DoublyLinkedList<Listener> ListenerList;
|
||||||
typedef BObjectList<Watchpoint> WatchpointList;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _NotifyThreadAdded(Thread* thread);
|
void _NotifyThreadAdded(Thread* thread);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#define WATCHPOINT_H
|
#define WATCHPOINT_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <ObjectList.h>
|
||||||
#include <Referenceable.h>
|
#include <Referenceable.h>
|
||||||
|
|
||||||
#include "types/Types.h"
|
#include "types/Types.h"
|
||||||
@@ -49,4 +50,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef BObjectList<Watchpoint> WatchpointList;
|
||||||
|
|
||||||
|
|
||||||
#endif // WATCHPOINT_H
|
#endif // WATCHPOINT_H
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
#include "TeamUiSettings.h"
|
#include "TeamUiSettings.h"
|
||||||
#include "TeamUiSettingsFactory.h"
|
#include "TeamUiSettingsFactory.h"
|
||||||
#include "UserBreakpoint.h"
|
#include "UserBreakpoint.h"
|
||||||
#include "WatchpointSetting.h"
|
|
||||||
|
|
||||||
|
|
||||||
TeamSettings::TeamSettings()
|
TeamSettings::TeamSettings()
|
||||||
@@ -71,23 +70,6 @@ TeamSettings::SetTo(Team* team)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add watchpoints
|
|
||||||
for (int32 i = 0; Watchpoint* watchpoint = team->WatchpointAt(i); i++) {
|
|
||||||
WatchpointSetting* watchpointSetting
|
|
||||||
= new(std::nothrow) WatchpointSetting;
|
|
||||||
if (watchpointSetting == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
status_t error = watchpointSetting->SetTo(*watchpoint,
|
|
||||||
watchpoint->IsEnabled());
|
|
||||||
if (error == B_OK && !fWatchpoints.AddItem(watchpointSetting))
|
|
||||||
error = B_NO_MEMORY;
|
|
||||||
if (error != B_OK) {
|
|
||||||
delete watchpointSetting;
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,20 +166,6 @@ TeamSettings::BreakpointAt(int32 index) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32
|
|
||||||
TeamSettings::CountWatchpoints() const
|
|
||||||
{
|
|
||||||
return fWatchpoints.CountItems();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const WatchpointSetting*
|
|
||||||
TeamSettings::WatchpointAt(int32 index) const
|
|
||||||
{
|
|
||||||
return fWatchpoints.ItemAt(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
TeamSettings::CountUiSettings() const
|
TeamSettings::CountUiSettings() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ class BMessage;
|
|||||||
class Team;
|
class Team;
|
||||||
class BreakpointSetting;
|
class BreakpointSetting;
|
||||||
class TeamUiSettings;
|
class TeamUiSettings;
|
||||||
class WatchpointSetting;
|
|
||||||
|
|
||||||
|
|
||||||
class TeamSettings {
|
class TeamSettings {
|
||||||
@@ -34,9 +33,6 @@ public:
|
|||||||
int32 CountBreakpoints() const;
|
int32 CountBreakpoints() const;
|
||||||
const BreakpointSetting* BreakpointAt(int32 index) const;
|
const BreakpointSetting* BreakpointAt(int32 index) const;
|
||||||
|
|
||||||
int32 CountWatchpoints() const;
|
|
||||||
const WatchpointSetting* WatchpointAt(int32 index) const;
|
|
||||||
|
|
||||||
int32 CountUiSettings() const;
|
int32 CountUiSettings() const;
|
||||||
const TeamUiSettings* UiSettingAt(int32 index) const;
|
const TeamUiSettings* UiSettingAt(int32 index) const;
|
||||||
const TeamUiSettings* UiSettingFor(const char* id) const;
|
const TeamUiSettings* UiSettingFor(const char* id) const;
|
||||||
@@ -48,14 +44,12 @@ public:
|
|||||||
private:
|
private:
|
||||||
typedef BObjectList<BreakpointSetting> BreakpointList;
|
typedef BObjectList<BreakpointSetting> BreakpointList;
|
||||||
typedef BObjectList<TeamUiSettings> UiSettingsList;
|
typedef BObjectList<TeamUiSettings> UiSettingsList;
|
||||||
typedef BObjectList<WatchpointSetting> WatchpointList;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _Unset();
|
void _Unset();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BreakpointList fBreakpoints;
|
BreakpointList fBreakpoints;
|
||||||
WatchpointList fWatchpoints;
|
|
||||||
UiSettingsList fUiSettings;
|
UiSettingsList fUiSettings;
|
||||||
BString fTeamName;
|
BString fTeamName;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,100 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
|
||||||
* Copyright 2012, Rene Gollent, rene@gollent.com.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "WatchpointSetting.h"
|
|
||||||
|
|
||||||
#include <Message.h>
|
|
||||||
|
|
||||||
#include "Watchpoint.h"
|
|
||||||
|
|
||||||
|
|
||||||
WatchpointSetting::WatchpointSetting()
|
|
||||||
:
|
|
||||||
fAddress(0),
|
|
||||||
fType(0),
|
|
||||||
fLength(0),
|
|
||||||
fEnabled(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
WatchpointSetting::WatchpointSetting(const WatchpointSetting& other)
|
|
||||||
:
|
|
||||||
fAddress(other.fAddress),
|
|
||||||
fType(other.fType),
|
|
||||||
fLength(other.fLength),
|
|
||||||
fEnabled(other.fEnabled)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
WatchpointSetting::~WatchpointSetting()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
WatchpointSetting::SetTo(const Watchpoint& watchpoint, bool enabled)
|
|
||||||
{
|
|
||||||
fAddress = watchpoint.Address();
|
|
||||||
fType = watchpoint.Type();
|
|
||||||
fLength = watchpoint.Length();
|
|
||||||
fEnabled = enabled;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
WatchpointSetting::SetTo(const BMessage& archive)
|
|
||||||
{
|
|
||||||
if (archive.FindUInt64("address", &fAddress) != B_OK)
|
|
||||||
fAddress = 0;
|
|
||||||
|
|
||||||
if (archive.FindUInt32("type", &fType) != B_OK)
|
|
||||||
fType = 0;
|
|
||||||
|
|
||||||
if (archive.FindInt32("length", &fLength) != B_OK)
|
|
||||||
fLength = 0;
|
|
||||||
|
|
||||||
if (archive.FindBool("enabled", &fEnabled) != B_OK)
|
|
||||||
fEnabled = false;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
WatchpointSetting::WriteTo(BMessage& archive) const
|
|
||||||
{
|
|
||||||
archive.MakeEmpty();
|
|
||||||
|
|
||||||
status_t error;
|
|
||||||
if ((error = archive.AddUInt64("address", fAddress)) != B_OK
|
|
||||||
|| (error = archive.AddUInt32("type", fType)) != B_OK
|
|
||||||
|| (error = archive.AddInt32("length", fLength)) != B_OK
|
|
||||||
|| (error = archive.AddBool("enabled", fEnabled)) != B_OK) {
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
WatchpointSetting&
|
|
||||||
WatchpointSetting::operator=(const WatchpointSetting& other)
|
|
||||||
{
|
|
||||||
if (this == &other)
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
fAddress = other.fAddress;
|
|
||||||
fType = other.fType;
|
|
||||||
fLength = other.fLength;
|
|
||||||
fEnabled = other.fEnabled;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
|
||||||
* Copyright 2012, Rene Gollent, rene@gollent.com.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
#ifndef WATCHPOINT_SETTING_H
|
|
||||||
#define WATCHPOINT_SETTING_H
|
|
||||||
|
|
||||||
|
|
||||||
#include <String.h>
|
|
||||||
|
|
||||||
#include "types/Types.h"
|
|
||||||
|
|
||||||
class BMessage;
|
|
||||||
class Watchpoint;
|
|
||||||
|
|
||||||
|
|
||||||
class WatchpointSetting {
|
|
||||||
public:
|
|
||||||
WatchpointSetting();
|
|
||||||
WatchpointSetting(
|
|
||||||
const WatchpointSetting& other);
|
|
||||||
~WatchpointSetting();
|
|
||||||
|
|
||||||
status_t SetTo(const Watchpoint& watchpoint,
|
|
||||||
bool enabled);
|
|
||||||
status_t SetTo(const BMessage& archive);
|
|
||||||
status_t WriteTo(BMessage& archive) const;
|
|
||||||
|
|
||||||
target_addr_t Address() const { return fAddress; }
|
|
||||||
uint32 Type() const { return fType; }
|
|
||||||
int32 Length() const { return fLength; }
|
|
||||||
|
|
||||||
bool IsEnabled() const { return fEnabled; }
|
|
||||||
|
|
||||||
WatchpointSetting& operator=(const WatchpointSetting& other);
|
|
||||||
|
|
||||||
private:
|
|
||||||
target_addr_t fAddress;
|
|
||||||
uint32 fType;
|
|
||||||
int32 fLength;
|
|
||||||
bool fEnabled;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif // BREAKPOINT_SETTING_H
|
|
||||||
@@ -18,9 +18,10 @@
|
|||||||
#include "GuiSettingsUtils.h"
|
#include "GuiSettingsUtils.h"
|
||||||
#include "LocatableFile.h"
|
#include "LocatableFile.h"
|
||||||
#include "table/TableColumns.h"
|
#include "table/TableColumns.h"
|
||||||
|
#include "TargetAddressTableColumn.h"
|
||||||
#include "Team.h"
|
#include "Team.h"
|
||||||
#include "UserBreakpoint.h"
|
#include "UserBreakpoint.h"
|
||||||
#include "TargetAddressTableColumn.h"
|
#include "Watchpoint.h"
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - BreakpointsTableModel
|
// #pragma mark - BreakpointsTableModel
|
||||||
@@ -32,16 +33,18 @@ public:
|
|||||||
:
|
:
|
||||||
fTeam(team)
|
fTeam(team)
|
||||||
{
|
{
|
||||||
Update(NULL);
|
UpdateBreakpoint(NULL);
|
||||||
|
UpdateWatchpoint(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
~BreakpointsTableModel()
|
~BreakpointsTableModel()
|
||||||
{
|
{
|
||||||
fTeam = NULL;
|
fTeam = NULL;
|
||||||
Update(NULL);
|
UpdateBreakpoint(NULL);
|
||||||
|
UpdateWatchpoint(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Update(UserBreakpoint* changedBreakpoint)
|
bool UpdateBreakpoint(UserBreakpoint* changedBreakpoint)
|
||||||
{
|
{
|
||||||
if (fTeam == NULL) {
|
if (fTeam == NULL) {
|
||||||
for (int32 i = 0;
|
for (int32 i = 0;
|
||||||
@@ -93,6 +96,59 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UpdateWatchpoint(Watchpoint* changedWatchpoint)
|
||||||
|
{
|
||||||
|
if (fTeam == NULL) {
|
||||||
|
for (int32 i = 0;
|
||||||
|
Watchpoint* watchpoint = fWatchpoints.ItemAt(i);
|
||||||
|
i++) {
|
||||||
|
watchpoint->ReleaseReference();
|
||||||
|
}
|
||||||
|
fWatchpoints.MakeEmpty();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoLocker<Team> locker(fTeam);
|
||||||
|
|
||||||
|
int32 breakpointCount = fBreakpoints.CountItems();
|
||||||
|
int32 index = 0;
|
||||||
|
int32 teamIndex = 0;
|
||||||
|
Watchpoint* newWatchpoint = fTeam->WatchpointAt(teamIndex);
|
||||||
|
// remove no longer existing breakpoints
|
||||||
|
while (Watchpoint* oldWatchpoint = fWatchpoints.ItemAt(index)) {
|
||||||
|
if (oldWatchpoint == newWatchpoint) {
|
||||||
|
if (oldWatchpoint == changedWatchpoint)
|
||||||
|
NotifyRowsChanged(index + breakpointCount, 1);
|
||||||
|
index++;
|
||||||
|
teamIndex++;
|
||||||
|
newWatchpoint = fTeam->WatchpointAt(teamIndex);
|
||||||
|
} else {
|
||||||
|
// TODO: Not particularly efficient!
|
||||||
|
fWatchpoints.RemoveItemAt(index);
|
||||||
|
oldWatchpoint->ReleaseReference();
|
||||||
|
NotifyRowsRemoved(index + breakpointCount, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add new breakpoints
|
||||||
|
int32 countBefore = fWatchpoints.CountItems();
|
||||||
|
while (newWatchpoint != NULL) {
|
||||||
|
if (!fWatchpoints.AddItem(newWatchpoint))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
newWatchpoint->AcquireReference();
|
||||||
|
teamIndex++;
|
||||||
|
newWatchpoint = fTeam->WatchpointAt(teamIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 count = fWatchpoints.CountItems();
|
||||||
|
if (count > countBefore)
|
||||||
|
NotifyRowsAdded(countBefore + breakpointCount, count - countBefore);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
virtual int32 CountColumns() const
|
virtual int32 CountColumns() const
|
||||||
{
|
{
|
||||||
return 5;
|
return 5;
|
||||||
@@ -100,10 +156,33 @@ public:
|
|||||||
|
|
||||||
virtual int32 CountRows() const
|
virtual int32 CountRows() const
|
||||||
{
|
{
|
||||||
return fBreakpoints.CountItems();
|
return fBreakpoints.CountItems() + fWatchpoints.CountItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool GetValueAt(int32 rowIndex, int32 columnIndex, BVariant& value)
|
virtual bool GetValueAt(int32 rowIndex, int32 columnIndex, BVariant& value)
|
||||||
|
{
|
||||||
|
int32 breakpointCount = fBreakpoints.CountItems();
|
||||||
|
if (rowIndex < breakpointCount)
|
||||||
|
return _GetBreakpointValueAt(rowIndex, columnIndex, value);
|
||||||
|
|
||||||
|
return _GetWatchpointValueAt(rowIndex - breakpointCount, columnIndex,
|
||||||
|
value);
|
||||||
|
}
|
||||||
|
|
||||||
|
UserBreakpoint* BreakpointAt(int32 index) const
|
||||||
|
{
|
||||||
|
return fBreakpoints.ItemAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
Watchpoint* WatchpointAt(int32 index) const
|
||||||
|
{
|
||||||
|
return fWatchpoints.ItemAt(index - fBreakpoints.CountItems());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
bool _GetBreakpointValueAt(int32 rowIndex, int32 columnIndex,
|
||||||
|
BVariant &value)
|
||||||
{
|
{
|
||||||
UserBreakpoint* breakpoint = fBreakpoints.ItemAt(rowIndex);
|
UserBreakpoint* breakpoint = fBreakpoints.ItemAt(rowIndex);
|
||||||
if (breakpoint == NULL)
|
if (breakpoint == NULL)
|
||||||
@@ -145,14 +224,36 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UserBreakpoint* BreakpointAt(int32 index) const
|
bool _GetWatchpointValueAt(int32 rowIndex, int32 columnIndex,
|
||||||
|
BVariant& value)
|
||||||
{
|
{
|
||||||
return fBreakpoints.ItemAt(index);
|
Watchpoint* watchpoint = fWatchpoints.ItemAt(rowIndex);
|
||||||
|
if (watchpoint == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (columnIndex) {
|
||||||
|
case 0:
|
||||||
|
value.SetTo((int32)watchpoint->IsEnabled());
|
||||||
|
return true;
|
||||||
|
case 1:
|
||||||
|
value.SetTo("Watchpoint");
|
||||||
|
return true;
|
||||||
|
case 2:
|
||||||
|
return false;
|
||||||
|
case 3:
|
||||||
|
return false;
|
||||||
|
case 4:
|
||||||
|
value.SetTo(watchpoint->Address());
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Team* fTeam;
|
Team* fTeam;
|
||||||
BObjectList<UserBreakpoint> fBreakpoints;
|
BObjectList<UserBreakpoint> fBreakpoints;
|
||||||
|
BObjectList<Watchpoint> fWatchpoints;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -202,7 +303,8 @@ BreakpointListView::UnsetListener()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BreakpointListView::SetBreakpoint(UserBreakpoint* breakpoint)
|
BreakpointListView::SetBreakpoint(UserBreakpoint* breakpoint,
|
||||||
|
Watchpoint* watchpoint)
|
||||||
{
|
{
|
||||||
if (breakpoint == fBreakpoint)
|
if (breakpoint == fBreakpoint)
|
||||||
return;
|
return;
|
||||||
@@ -232,7 +334,14 @@ BreakpointListView::SetBreakpoint(UserBreakpoint* breakpoint)
|
|||||||
void
|
void
|
||||||
BreakpointListView::UserBreakpointChanged(UserBreakpoint* breakpoint)
|
BreakpointListView::UserBreakpointChanged(UserBreakpoint* breakpoint)
|
||||||
{
|
{
|
||||||
fBreakpointsTableModel->Update(breakpoint);
|
fBreakpointsTableModel->UpdateBreakpoint(breakpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BreakpointListView::WatchpointChanged(Watchpoint* watchpoint)
|
||||||
|
{
|
||||||
|
fBreakpointsTableModel->UpdateWatchpoint(watchpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -271,8 +380,13 @@ BreakpointListView::TableSelectionChanged(Table* table)
|
|||||||
TableSelectionModel* selectionModel = table->SelectionModel();
|
TableSelectionModel* selectionModel = table->SelectionModel();
|
||||||
UserBreakpoint* breakpoint = fBreakpointsTableModel->BreakpointAt(
|
UserBreakpoint* breakpoint = fBreakpointsTableModel->BreakpointAt(
|
||||||
selectionModel->RowAt(0));
|
selectionModel->RowAt(0));
|
||||||
|
if (breakpoint != NULL)
|
||||||
fListener->BreakpointSelectionChanged(breakpoint);
|
fListener->BreakpointSelectionChanged(breakpoint);
|
||||||
|
else {
|
||||||
|
Watchpoint* watchpoint = fBreakpointsTableModel->WatchpointAt(
|
||||||
|
selectionModel->RowAt(0));
|
||||||
|
fListener->WatchpointSelectionChanged(watchpoint);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
class Team;
|
class Team;
|
||||||
class UserBreakpoint;
|
class UserBreakpoint;
|
||||||
|
class Watchpoint;
|
||||||
|
|
||||||
|
|
||||||
class BreakpointListView : public BGroupView, private TableListener {
|
class BreakpointListView : public BGroupView, private TableListener {
|
||||||
@@ -29,9 +30,13 @@ public:
|
|||||||
|
|
||||||
void UnsetListener();
|
void UnsetListener();
|
||||||
|
|
||||||
void SetBreakpoint(UserBreakpoint* breakpoint);
|
void SetBreakpoint(UserBreakpoint* breakpoint,
|
||||||
|
Watchpoint* watchpoint);
|
||||||
|
|
||||||
void UserBreakpointChanged(
|
void UserBreakpointChanged(
|
||||||
UserBreakpoint* breakpoint);
|
UserBreakpoint* breakpoint);
|
||||||
|
void WatchpointChanged(
|
||||||
|
Watchpoint* breakpoint);
|
||||||
|
|
||||||
void LoadSettings(const BMessage& settings);
|
void LoadSettings(const BMessage& settings);
|
||||||
status_t SaveSettings(BMessage& settings);
|
status_t SaveSettings(BMessage& settings);
|
||||||
@@ -48,6 +53,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
Team* fTeam;
|
Team* fTeam;
|
||||||
UserBreakpoint* fBreakpoint;
|
UserBreakpoint* fBreakpoint;
|
||||||
|
Watchpoint* fWatchpoint;
|
||||||
Table* fBreakpointsTable;
|
Table* fBreakpointsTable;
|
||||||
BreakpointsTableModel* fBreakpointsTableModel;
|
BreakpointsTableModel* fBreakpointsTableModel;
|
||||||
Listener* fListener;
|
Listener* fListener;
|
||||||
@@ -60,6 +66,9 @@ public:
|
|||||||
|
|
||||||
virtual void BreakpointSelectionChanged(
|
virtual void BreakpointSelectionChanged(
|
||||||
UserBreakpoint* breakpoint) = 0;
|
UserBreakpoint* breakpoint) = 0;
|
||||||
|
|
||||||
|
virtual void WatchpointSelectionChanged(
|
||||||
|
Watchpoint* watchpoint) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -68,20 +68,26 @@ BreakpointsView::UnsetListener()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BreakpointsView::SetBreakpoint(UserBreakpoint* breakpoint)
|
BreakpointsView::SetBreakpoint(UserBreakpoint* breakpoint, Watchpoint* watchpoint)
|
||||||
{
|
{
|
||||||
if (breakpoint == fBreakpoint)
|
if (breakpoint == fBreakpoint && watchpoint == fWatchpoint)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (fWatchpoint != NULL)
|
||||||
|
fWatchpoint->ReleaseReference();
|
||||||
|
|
||||||
if (fBreakpoint != NULL)
|
if (fBreakpoint != NULL)
|
||||||
fBreakpoint->ReleaseReference();
|
fBreakpoint->ReleaseReference();
|
||||||
|
|
||||||
|
fWatchpoint = watchpoint;
|
||||||
fBreakpoint = breakpoint;
|
fBreakpoint = breakpoint;
|
||||||
|
|
||||||
if (fBreakpoint != NULL)
|
if (fBreakpoint != NULL)
|
||||||
fBreakpoint->AcquireReference();
|
fBreakpoint->AcquireReference();
|
||||||
|
else if (fWatchpoint != NULL)
|
||||||
|
fWatchpoint->AcquireReference();
|
||||||
|
|
||||||
fListView->SetBreakpoint(breakpoint);
|
fListView->SetBreakpoint(breakpoint, watchpoint);
|
||||||
|
|
||||||
_UpdateButtons();
|
_UpdateButtons();
|
||||||
}
|
}
|
||||||
@@ -96,21 +102,49 @@ BreakpointsView::UserBreakpointChanged(UserBreakpoint* breakpoint)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BreakpointsView::WatchpointChanged(Watchpoint* watchpoint)
|
||||||
|
{
|
||||||
|
fListView->WatchpointChanged(watchpoint);
|
||||||
|
|
||||||
|
_UpdateButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BreakpointsView::MessageReceived(BMessage* message)
|
BreakpointsView::MessageReceived(BMessage* message)
|
||||||
{
|
{
|
||||||
switch (message->what) {
|
switch (message->what) {
|
||||||
case MSG_ENABLE_BREAKPOINT:
|
case MSG_ENABLE_BREAKPOINT:
|
||||||
if (fListener != NULL && fBreakpoint != NULL)
|
if (fListener != NULL) {
|
||||||
fListener->SetBreakpointEnabledRequested(fBreakpoint, true);
|
if (fBreakpoint != NULL) {
|
||||||
|
fListener->SetBreakpointEnabledRequested(fBreakpoint,
|
||||||
|
true);
|
||||||
|
} else if (fWatchpoint != NULL) {
|
||||||
|
fListener->SetWatchpointEnabledRequested(fWatchpoint,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case MSG_DISABLE_BREAKPOINT:
|
case MSG_DISABLE_BREAKPOINT:
|
||||||
if (fListener != NULL && fBreakpoint != NULL)
|
if (fListener != NULL) {
|
||||||
fListener->SetBreakpointEnabledRequested(fBreakpoint, false);
|
if (fBreakpoint != NULL) {
|
||||||
|
fListener->SetBreakpointEnabledRequested(fBreakpoint,
|
||||||
|
false);
|
||||||
|
} else if (fWatchpoint != NULL) {
|
||||||
|
fListener->SetWatchpointEnabledRequested(fWatchpoint,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case MSG_CLEAR_BREAKPOINT:
|
case MSG_CLEAR_BREAKPOINT:
|
||||||
if (fListener != NULL && fBreakpoint != NULL)
|
if (fListener != NULL) {
|
||||||
fListener->ClearBreakpointRequested(fBreakpoint);
|
if (fBreakpoint != NULL) {
|
||||||
|
fListener->ClearBreakpointRequested(fBreakpoint);
|
||||||
|
} else if (fWatchpoint != NULL) {
|
||||||
|
fListener->ClearWatchpointRequested(fWatchpoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BGroupView::MessageReceived(message);
|
BGroupView::MessageReceived(message);
|
||||||
@@ -159,6 +193,14 @@ BreakpointsView::BreakpointSelectionChanged(UserBreakpoint* breakpoint)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BreakpointsView::WatchpointSelectionChanged(Watchpoint* watchpoint)
|
||||||
|
{
|
||||||
|
if (fListener != NULL)
|
||||||
|
fListener->WatchpointSelectionChanged(watchpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BreakpointsView::_Init()
|
BreakpointsView::_Init()
|
||||||
{
|
{
|
||||||
@@ -182,8 +224,19 @@ BreakpointsView::_UpdateButtons()
|
|||||||
{
|
{
|
||||||
AutoLocker<Team> teamLocker(fTeam);
|
AutoLocker<Team> teamLocker(fTeam);
|
||||||
|
|
||||||
|
bool enabled = false;
|
||||||
|
bool valid = false;
|
||||||
|
|
||||||
if (fBreakpoint != NULL && fBreakpoint->IsValid()) {
|
if (fBreakpoint != NULL && fBreakpoint->IsValid()) {
|
||||||
if (fBreakpoint->IsEnabled()) {
|
valid = true;
|
||||||
|
enabled = fBreakpoint->IsEnabled();
|
||||||
|
} else if (fWatchpoint != NULL) {
|
||||||
|
valid = true;
|
||||||
|
enabled = fWatchpoint->IsEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valid) {
|
||||||
|
if (enabled) {
|
||||||
fToggleBreakpointButton->SetLabel("Disable");
|
fToggleBreakpointButton->SetLabel("Disable");
|
||||||
fToggleBreakpointButton->SetMessage(
|
fToggleBreakpointButton->SetMessage(
|
||||||
new BMessage(MSG_DISABLE_BREAKPOINT));
|
new BMessage(MSG_DISABLE_BREAKPOINT));
|
||||||
|
|||||||
@@ -28,9 +28,13 @@ public:
|
|||||||
|
|
||||||
void UnsetListener();
|
void UnsetListener();
|
||||||
|
|
||||||
void SetBreakpoint(UserBreakpoint* breakpoint);
|
void SetBreakpoint(UserBreakpoint* breakpoint,
|
||||||
|
Watchpoint* watchpoint);
|
||||||
|
|
||||||
void UserBreakpointChanged(
|
void UserBreakpointChanged(
|
||||||
UserBreakpoint* breakpoint);
|
UserBreakpoint* breakpoint);
|
||||||
|
void WatchpointChanged(
|
||||||
|
Watchpoint* watchpoint);
|
||||||
|
|
||||||
virtual void MessageReceived(BMessage* message);
|
virtual void MessageReceived(BMessage* message);
|
||||||
virtual void AttachedToWindow();
|
virtual void AttachedToWindow();
|
||||||
@@ -42,6 +46,8 @@ private:
|
|||||||
// BreakpointListView::Listener
|
// BreakpointListView::Listener
|
||||||
virtual void BreakpointSelectionChanged(
|
virtual void BreakpointSelectionChanged(
|
||||||
UserBreakpoint* breakpoint);
|
UserBreakpoint* breakpoint);
|
||||||
|
virtual void WatchpointSelectionChanged(
|
||||||
|
Watchpoint* watchpoint);
|
||||||
|
|
||||||
void _Init();
|
void _Init();
|
||||||
|
|
||||||
@@ -50,6 +56,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
Team* fTeam;
|
Team* fTeam;
|
||||||
UserBreakpoint* fBreakpoint;
|
UserBreakpoint* fBreakpoint;
|
||||||
|
Watchpoint* fWatchpoint;
|
||||||
BreakpointListView* fListView;
|
BreakpointListView* fListView;
|
||||||
BButton* fToggleBreakpointButton;
|
BButton* fToggleBreakpointButton;
|
||||||
BButton* fRemoveBreakpointButton;
|
BButton* fRemoveBreakpointButton;
|
||||||
@@ -57,6 +64,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class BreakpointsView::Listener {
|
class BreakpointsView::Listener {
|
||||||
public:
|
public:
|
||||||
virtual ~Listener();
|
virtual ~Listener();
|
||||||
@@ -68,6 +76,14 @@ public:
|
|||||||
bool enabled) = 0;
|
bool enabled) = 0;
|
||||||
virtual void ClearBreakpointRequested(
|
virtual void ClearBreakpointRequested(
|
||||||
UserBreakpoint* breakpoint) = 0;
|
UserBreakpoint* breakpoint) = 0;
|
||||||
|
|
||||||
|
virtual void WatchpointSelectionChanged(
|
||||||
|
Watchpoint* Watchpoint) = 0;
|
||||||
|
virtual void SetWatchpointEnabledRequested(
|
||||||
|
Watchpoint* breakpoint,
|
||||||
|
bool enabled) = 0;
|
||||||
|
virtual void ClearWatchpointRequested(
|
||||||
|
Watchpoint* watchpoint) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
#include "TypeComponentPath.h"
|
#include "TypeComponentPath.h"
|
||||||
#include "UserInterface.h"
|
#include "UserInterface.h"
|
||||||
#include "Variable.h"
|
#include "Variable.h"
|
||||||
|
#include "WatchPromptWindow.h"
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -247,6 +248,27 @@ TeamWindow::MessageReceived(BMessage* message)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
case MSG_SHOW_WATCH_VARIABLE_PROMPT:
|
||||||
|
{
|
||||||
|
target_addr_t address;
|
||||||
|
uint32 type;
|
||||||
|
int32 length;
|
||||||
|
|
||||||
|
if (message->FindUInt64("address", &address) != B_OK
|
||||||
|
|| message->FindUInt32("type", &type) != B_OK
|
||||||
|
|| message->FindInt32("length", &length) != B_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
WatchPromptWindow* window = WatchPromptWindow::Create(address,
|
||||||
|
type, length, fListener);
|
||||||
|
window->Show();
|
||||||
|
} catch (...) {
|
||||||
|
// TODO: notify user
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case B_REFS_RECEIVED:
|
case B_REFS_RECEIVED:
|
||||||
{
|
{
|
||||||
entry_ref locatedPath;
|
entry_ref locatedPath;
|
||||||
@@ -334,6 +356,18 @@ TeamWindow::MessageReceived(BMessage* message)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case MSG_WATCHPOINT_CHANGED:
|
||||||
|
{
|
||||||
|
Watchpoint* watchpoint;
|
||||||
|
if (message->FindPointer("watchpoint", (void**)&watchpoint) != B_OK)
|
||||||
|
break;
|
||||||
|
BReference<Watchpoint> watchpointReference(watchpoint, true);
|
||||||
|
|
||||||
|
_HandleWatchpointChanged(watchpoint);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
case MSG_FUNCTION_SOURCE_CODE_CHANGED:
|
case MSG_FUNCTION_SOURCE_CODE_CHANGED:
|
||||||
{
|
{
|
||||||
_HandleSourceCodeChanged();
|
_HandleSourceCodeChanged();
|
||||||
@@ -562,6 +596,28 @@ TeamWindow::ClearBreakpointRequested(target_addr_t address)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TeamWindow::WatchpointSelectionChanged(Watchpoint* watchpoint)
|
||||||
|
{
|
||||||
|
fBreakpointsView->SetBreakpoint(NULL, watchpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TeamWindow::SetWatchpointEnabledRequested(Watchpoint* watchpoint,
|
||||||
|
bool enabled)
|
||||||
|
{
|
||||||
|
fListener->SetWatchpointEnabledRequested(watchpoint, enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TeamWindow::ClearWatchpointRequested(Watchpoint* watchpoint)
|
||||||
|
{
|
||||||
|
fListener->ClearWatchpointRequested(watchpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TeamWindow::ValueNodeValueRequested(CpuState* cpuState,
|
TeamWindow::ValueNodeValueRequested(CpuState* cpuState,
|
||||||
ValueNodeContainer* container, ValueNode* valueNode)
|
ValueNodeContainer* container, ValueNode* valueNode)
|
||||||
@@ -618,6 +674,18 @@ TeamWindow::UserBreakpointChanged(const Team::UserBreakpointEvent& event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TeamWindow::WatchpointChanged(const Team::WatchpointEvent& event)
|
||||||
|
{
|
||||||
|
BMessage message(MSG_WATCHPOINT_CHANGED);
|
||||||
|
BReference<Watchpoint> watchpointReference(event.GetWatchpoint());
|
||||||
|
if (message.AddPointer("watchpoint", event.GetWatchpoint()) == B_OK
|
||||||
|
&& PostMessage(&message) == B_OK) {
|
||||||
|
watchpointReference.Detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TeamWindow::FunctionSourceCodeChanged(Function* function)
|
TeamWindow::FunctionSourceCodeChanged(Function* function)
|
||||||
{
|
{
|
||||||
@@ -901,7 +969,7 @@ TeamWindow::_SetActiveBreakpoint(UserBreakpoint* breakpoint)
|
|||||||
_ScrollToActiveFunction();
|
_ScrollToActiveFunction();
|
||||||
}
|
}
|
||||||
|
|
||||||
fBreakpointsView->SetBreakpoint(fActiveBreakpoint);
|
fBreakpointsView->SetBreakpoint(fActiveBreakpoint, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1244,6 +1312,13 @@ TeamWindow::_HandleUserBreakpointChanged(UserBreakpoint* breakpoint)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TeamWindow::_HandleWatchpointChanged(Watchpoint* watchpoint)
|
||||||
|
{
|
||||||
|
fBreakpointsView->WatchpointChanged(watchpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TeamWindow::_HandleResolveMissingSourceFile(entry_ref& locatedPath)
|
TeamWindow::_HandleResolveMissingSourceFile(entry_ref& locatedPath)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -95,6 +95,15 @@ private:
|
|||||||
virtual void ClearBreakpointRequested(
|
virtual void ClearBreakpointRequested(
|
||||||
UserBreakpoint* breakpoint);
|
UserBreakpoint* breakpoint);
|
||||||
|
|
||||||
|
virtual void WatchpointSelectionChanged(
|
||||||
|
Watchpoint* Watchpoint);
|
||||||
|
virtual void SetWatchpointEnabledRequested(
|
||||||
|
Watchpoint* breakpoint,
|
||||||
|
bool enabled);
|
||||||
|
virtual void ClearWatchpointRequested(
|
||||||
|
Watchpoint* watchpoint);
|
||||||
|
|
||||||
|
|
||||||
// SourceView::Listener
|
// SourceView::Listener
|
||||||
virtual void SetBreakpointRequested(target_addr_t address,
|
virtual void SetBreakpointRequested(target_addr_t address,
|
||||||
bool enabled);
|
bool enabled);
|
||||||
@@ -116,6 +125,8 @@ private:
|
|||||||
const Team::ImageEvent& event);
|
const Team::ImageEvent& event);
|
||||||
virtual void UserBreakpointChanged(
|
virtual void UserBreakpointChanged(
|
||||||
const Team::UserBreakpointEvent& event);
|
const Team::UserBreakpointEvent& event);
|
||||||
|
virtual void WatchpointChanged(
|
||||||
|
const Team::WatchpointEvent& event);
|
||||||
|
|
||||||
// Function::Listener
|
// Function::Listener
|
||||||
virtual void FunctionSourceCodeChanged(Function* function);
|
virtual void FunctionSourceCodeChanged(Function* function);
|
||||||
@@ -142,6 +153,8 @@ private:
|
|||||||
void _HandleSourceCodeChanged();
|
void _HandleSourceCodeChanged();
|
||||||
void _HandleUserBreakpointChanged(
|
void _HandleUserBreakpointChanged(
|
||||||
UserBreakpoint* breakpoint);
|
UserBreakpoint* breakpoint);
|
||||||
|
void _HandleWatchpointChanged(
|
||||||
|
Watchpoint* watchpoint);
|
||||||
void _HandleResolveMissingSourceFile(entry_ref&
|
void _HandleResolveMissingSourceFile(entry_ref&
|
||||||
locatedPath);
|
locatedPath);
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
|
#include <debugger.h>
|
||||||
|
|
||||||
#include <Looper.h>
|
#include <Looper.h>
|
||||||
#include <PopUpMenu.h>
|
#include <PopUpMenu.h>
|
||||||
#include <ToolTip.h>
|
#include <ToolTip.h>
|
||||||
@@ -1684,6 +1686,22 @@ VariablesView::MessageReceived(BMessage* message)
|
|||||||
node->NodeChild()->SetNode(valueNode);
|
node->NodeChild()->SetNode(valueNode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MSG_SHOW_WATCH_VARIABLE_PROMPT:
|
||||||
|
{
|
||||||
|
ModelNode* node = reinterpret_cast<ModelNode*>(
|
||||||
|
fVariableTable->SelectionModel()->NodeAt(0));
|
||||||
|
ValueLocation* location = node->NodeChild()->Location();
|
||||||
|
ValuePieceLocation piece = location->PieceAt(0);
|
||||||
|
if (piece.type != VALUE_PIECE_LOCATION_MEMORY)
|
||||||
|
break;
|
||||||
|
|
||||||
|
BMessage looperMessage(*message);
|
||||||
|
looperMessage.AddUInt64("address", piece.address);
|
||||||
|
looperMessage.AddInt32("length", piece.size);
|
||||||
|
looperMessage.AddUInt32("type", B_DATA_READ_WRITE_WATCHPOINT);
|
||||||
|
Looper()->PostMessage(&looperMessage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case MSG_VALUE_NODE_CHANGED:
|
case MSG_VALUE_NODE_CHANGED:
|
||||||
{
|
{
|
||||||
ValueNodeChild* nodeChild;
|
ValueNodeChild* nodeChild;
|
||||||
@@ -1977,34 +1995,45 @@ VariablesView::_GetContextActionsForNode(ModelNode* node,
|
|||||||
if (location->PieceAt(0).type != VALUE_PIECE_LOCATION_MEMORY)
|
if (location->PieceAt(0).type != VALUE_PIECE_LOCATION_MEMORY)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
BMessage* message = new BMessage(MSG_SHOW_INSPECTOR_WINDOW);
|
BMessage* message = NULL;
|
||||||
if (message == NULL)
|
status_t result = _AddContextAction("Inspect", MSG_SHOW_INSPECTOR_WINDOW,
|
||||||
return B_NO_MEMORY;
|
actions, message);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
ObjectDeleter<BMessage> messageDeleter(message);
|
|
||||||
message->AddUInt64("address", location->PieceAt(0).address);
|
message->AddUInt64("address", location->PieceAt(0).address);
|
||||||
|
|
||||||
ActionMenuItem* item = new(std::nothrow) ActionMenuItem("Inspect",
|
result = _AddContextAction("Cast as" B_UTF8_ELLIPSIS,
|
||||||
message);
|
MSG_SHOW_TYPECAST_NODE_PROMPT, actions, message);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = _AddContextAction("Watch" B_UTF8_ELLIPSIS,
|
||||||
|
MSG_SHOW_WATCH_VARIABLE_PROMPT, actions, message);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
VariablesView::_AddContextAction(const char* action, uint32 what,
|
||||||
|
ContextActionList* actions, BMessage*& _message)
|
||||||
|
{
|
||||||
|
_message = new BMessage(what);
|
||||||
|
if (_message == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
ObjectDeleter<BMessage> messageDeleter(_message);
|
||||||
|
|
||||||
|
ActionMenuItem* item = new(std::nothrow) ActionMenuItem(action,
|
||||||
|
_message);
|
||||||
if (item == NULL)
|
if (item == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
messageDeleter.Detach();
|
messageDeleter.Detach();
|
||||||
ObjectDeleter<ActionMenuItem> actionDeleter(item);
|
ObjectDeleter<ActionMenuItem> actionDeleter(item);
|
||||||
if (!actions->AddItem(item))
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
message = new(std::nothrow)BMessage(MSG_SHOW_TYPECAST_NODE_PROMPT);
|
|
||||||
if (message == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
item = new(std::nothrow) ActionMenuItem("Cast as" B_UTF8_ELLIPSIS,
|
|
||||||
message);
|
|
||||||
if (item == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
messageDeleter.Detach();
|
|
||||||
|
|
||||||
if (!actions->AddItem(item))
|
if (!actions->AddItem(item))
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,9 @@ private:
|
|||||||
void _RequestNodeValue(ModelNode* node);
|
void _RequestNodeValue(ModelNode* node);
|
||||||
status_t _GetContextActionsForNode(ModelNode* node,
|
status_t _GetContextActionsForNode(ModelNode* node,
|
||||||
ContextActionList* actions);
|
ContextActionList* actions);
|
||||||
|
status_t _AddContextAction(const char* action,
|
||||||
|
uint32 what, ContextActionList* actions,
|
||||||
|
BMessage*& _message);
|
||||||
void _FinishContextMenu(bool force);
|
void _FinishContextMenu(bool force);
|
||||||
void _SaveViewState() const;
|
void _SaveViewState() const;
|
||||||
void _RestoreViewState();
|
void _RestoreViewState();
|
||||||
|
|||||||
@@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Rene Gollent, rene@gollent.com.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#include "WatchPromptWindow.h"
|
||||||
|
|
||||||
|
#include <Alert.h>
|
||||||
|
#include <Button.h>
|
||||||
|
#include <LayoutBuilder.h>
|
||||||
|
#include <Menu.h>
|
||||||
|
#include <MenuField.h>
|
||||||
|
#include <MenuItem.h>
|
||||||
|
#include <String.h>
|
||||||
|
#include <TextControl.h>
|
||||||
|
|
||||||
|
#include <ExpressionParser.h>
|
||||||
|
|
||||||
|
#include "MessageCodes.h"
|
||||||
|
#include "UserInterface.h"
|
||||||
|
#include "Watchpoint.h"
|
||||||
|
|
||||||
|
|
||||||
|
WatchPromptWindow::WatchPromptWindow(target_addr_t address, uint32 type,
|
||||||
|
int32 length, UserInterfaceListener* listener)
|
||||||
|
:
|
||||||
|
BWindow(BRect(), "Edit Watchpoint", B_FLOATING_WINDOW,
|
||||||
|
B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE),
|
||||||
|
fInitialAddress(address),
|
||||||
|
fInitialType(type),
|
||||||
|
fInitialLength(length),
|
||||||
|
fAddressInput(NULL),
|
||||||
|
fLengthInput(NULL),
|
||||||
|
fTypeField(NULL),
|
||||||
|
fListener(listener)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WatchPromptWindow::~WatchPromptWindow()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WatchPromptWindow*
|
||||||
|
WatchPromptWindow::Create(target_addr_t address, uint32 type, int32 length,
|
||||||
|
UserInterfaceListener* listener)
|
||||||
|
{
|
||||||
|
WatchPromptWindow* self = new WatchPromptWindow(address, type, length,
|
||||||
|
listener);
|
||||||
|
|
||||||
|
try {
|
||||||
|
self->_Init();
|
||||||
|
} catch (...) {
|
||||||
|
delete self;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WatchPromptWindow::_Init()
|
||||||
|
{
|
||||||
|
BString text;
|
||||||
|
text.SetToFormat("0x%" B_PRIx64, fInitialAddress);
|
||||||
|
fAddressInput = new BTextControl("Address:", text, NULL);
|
||||||
|
|
||||||
|
text.SetToFormat("%" B_PRId32, fInitialLength);
|
||||||
|
fLengthInput = new BTextControl("Length:", text, NULL);
|
||||||
|
|
||||||
|
BMenu* typeMenu = new BMenu("Watch Type");
|
||||||
|
typeMenu->AddItem(new BMenuItem("Read", NULL));
|
||||||
|
typeMenu->AddItem(new BMenuItem("Write", NULL));
|
||||||
|
typeMenu->AddItem(new BMenuItem("Read/Write", NULL));
|
||||||
|
fTypeField = new BMenuField("Type:", typeMenu);
|
||||||
|
BLayoutItem* labelItem = fTypeField->CreateLabelLayoutItem();
|
||||||
|
labelItem->View()->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
|
BLayoutBuilder::Group<>(this, B_VERTICAL)
|
||||||
|
.SetInsets(4.0f, 4.0f, 4.0f, 4.0f)
|
||||||
|
.AddGroup(B_HORIZONTAL, 4.0f)
|
||||||
|
.Add(fAddressInput)
|
||||||
|
.End()
|
||||||
|
.AddGroup(B_HORIZONTAL, 4.0f)
|
||||||
|
.Add(fLengthInput)
|
||||||
|
.Add(labelItem)
|
||||||
|
.Add(fTypeField->CreateMenuBarLayoutItem())
|
||||||
|
.End()
|
||||||
|
.AddGroup(B_HORIZONTAL, 4.0f)
|
||||||
|
.AddGlue()
|
||||||
|
.Add((fWatchButton = new BButton("Set",
|
||||||
|
new BMessage(MSG_SET_WATCHPOINT))))
|
||||||
|
.Add((fCancelButton = new BButton("Cancel",
|
||||||
|
new BMessage(B_QUIT_REQUESTED))))
|
||||||
|
.End();
|
||||||
|
|
||||||
|
fWatchButton->SetTarget(this);
|
||||||
|
fCancelButton->SetTarget(this);
|
||||||
|
|
||||||
|
fTypeField->Menu()->SetLabelFromMarked(true);
|
||||||
|
fTypeField->Menu()->ItemAt(fInitialType)->SetMarked(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WatchPromptWindow::Show()
|
||||||
|
{
|
||||||
|
CenterOnScreen();
|
||||||
|
BWindow::Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WatchPromptWindow::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
switch (message->what) {
|
||||||
|
case MSG_SET_WATCHPOINT:
|
||||||
|
{
|
||||||
|
target_addr_t address = 0;
|
||||||
|
int32 length = 0;
|
||||||
|
ExpressionParser parser;
|
||||||
|
parser.SetSupportHexInput(true);
|
||||||
|
BString errorMessage;
|
||||||
|
try {
|
||||||
|
address = parser.EvaluateToInt64(fAddressInput->Text());
|
||||||
|
length = (int32)parser.EvaluateToInt64(fLengthInput->Text());
|
||||||
|
} catch(ParseException parseError) {
|
||||||
|
errorMessage.SetToFormat("Failed to parse data: %s",
|
||||||
|
parseError.message.String());
|
||||||
|
} catch(...) {
|
||||||
|
errorMessage.SetToFormat(
|
||||||
|
"Unknown error while parsing address");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!errorMessage.IsEmpty()) {
|
||||||
|
BAlert* alert = new(std::nothrow) BAlert("Edit Watchpoint",
|
||||||
|
errorMessage.String(), "Close");
|
||||||
|
if (alert != NULL)
|
||||||
|
alert->Go();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fListener->ClearWatchpointRequested(fInitialAddress);
|
||||||
|
fListener->SetWatchpointRequested(address, fTypeField->Menu()
|
||||||
|
->IndexOf(fTypeField->Menu()->FindMarked()), length, true);
|
||||||
|
|
||||||
|
PostMessage(B_QUIT_REQUESTED);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
BWindow::MessageReceived(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Rene Gollent, rene@gollent.com.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef WATCH_PROMPT_WINDOW_H
|
||||||
|
#define WATCH_PROMPT_WINDOW_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Window.h>
|
||||||
|
|
||||||
|
#include "types/Types.h"
|
||||||
|
|
||||||
|
|
||||||
|
class BTextControl;
|
||||||
|
class Watchpoint;
|
||||||
|
class BMenuField;
|
||||||
|
class UserInterfaceListener;
|
||||||
|
|
||||||
|
|
||||||
|
class WatchPromptWindow : public BWindow
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// edit existing watchpoint
|
||||||
|
WatchPromptWindow(target_addr_t address,
|
||||||
|
uint32 type, int32 length,
|
||||||
|
UserInterfaceListener* listener);
|
||||||
|
|
||||||
|
~WatchPromptWindow();
|
||||||
|
|
||||||
|
static WatchPromptWindow* Create(target_addr_t address, uint32 type,
|
||||||
|
int32 length,
|
||||||
|
UserInterfaceListener* listener);
|
||||||
|
// throws
|
||||||
|
|
||||||
|
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
|
virtual void Show();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _Init();
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
target_addr_t fInitialAddress;
|
||||||
|
uint32 fInitialType;
|
||||||
|
int32 fInitialLength;
|
||||||
|
BTextControl* fAddressInput;
|
||||||
|
BTextControl* fLengthInput;
|
||||||
|
BMenuField* fTypeField;
|
||||||
|
UserInterfaceListener* fListener;
|
||||||
|
BButton* fWatchButton;
|
||||||
|
BButton* fCancelButton;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WATCH_PROMPT_WINDOW_H
|
||||||
@@ -873,7 +873,7 @@ MainWindow::_Initialize(BDiskDevice* disk, partition_id selectedPartition,
|
|||||||
|
|
||||||
// TODO: diskSystem.IsFileSystem() seems like a better fit here?
|
// TODO: diskSystem.IsFileSystem() seems like a better fit here?
|
||||||
if (diskSystemName == "Be File System"
|
if (diskSystemName == "Be File System"
|
||||||
|| diskSystemName == "NTFS File System") {
|
|| diskSystemName == "NT File System") {
|
||||||
InitParamsPanel* panel = new InitParamsPanel(this, diskSystemName,
|
InitParamsPanel* panel = new InitParamsPanel(this, diskSystemName,
|
||||||
partition);
|
partition);
|
||||||
if (panel->Go(name, parameters) == GO_CANCELED)
|
if (panel->Go(name, parameters) == GO_CANCELED)
|
||||||
|
|||||||
@@ -727,7 +727,7 @@ ShowImageWindow::MessageReceived(BMessage* message)
|
|||||||
strCaption << i;
|
strCaption << i;
|
||||||
|
|
||||||
BMenuItem* item = new BMenuItem(strCaption.String(), goTo,
|
BMenuItem* item = new BMenuItem(strCaption.String(), goTo,
|
||||||
B_SHIFT_KEY, shortcut);
|
shortcut, B_SHIFT_KEY);
|
||||||
if (currentPage == i)
|
if (currentPage == i)
|
||||||
item->SetMarked(true);
|
item->SetMarked(true);
|
||||||
fGoToPageMenu->AddItem(item);
|
fGoToPageMenu->AddItem(item);
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ AppearancePrefView::AppearancePrefView(const char* name,
|
|||||||
};
|
};
|
||||||
|
|
||||||
fBlinkCursor = new BCheckBox(
|
fBlinkCursor = new BCheckBox(
|
||||||
B_TRANSLATE("Blink the cursor"),
|
B_TRANSLATE("Blinking cursor"),
|
||||||
new BMessage(MSG_BLINK_CURSOR_CHANGED));
|
new BMessage(MSG_BLINK_CURSOR_CHANGED));
|
||||||
|
|
||||||
fWarnOnExit = new BCheckBox(
|
fWarnOnExit = new BCheckBox(
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ static const char* const PREF_SHELL = "Shell";
|
|||||||
static const char* const PREF_TEXT_ENCODING = "Text encoding";
|
static const char* const PREF_TEXT_ENCODING = "Text encoding";
|
||||||
static const char* const PREF_GUI_LANGUAGE = "Language";
|
static const char* const PREF_GUI_LANGUAGE = "Language";
|
||||||
|
|
||||||
static const char* const PREF_BLINK_CURSOR = "Blink the cursor";
|
static const char* const PREF_BLINK_CURSOR = "Blinking cursor";
|
||||||
static const char* const PREF_WARN_ON_EXIT = "Warn on exit";
|
static const char* const PREF_WARN_ON_EXIT = "Warn on exit";
|
||||||
|
|
||||||
static const char* const PREF_TAB_TITLE = "Tab title";
|
static const char* const PREF_TAB_TITLE = "Tab title";
|
||||||
|
|||||||
@@ -328,4 +328,62 @@ OffsetToCopy__5BRectff(BRect* self, float dx, float dy)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif // __GNUC__ == 2
|
#elif __GNUC__ == 4
|
||||||
|
// TODO: remove this when new GCC 4 packages have to be built anyway
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" BRect
|
||||||
|
_ZN5BRect11InsetByCopyE6BPoint(BRect* self, BPoint point)
|
||||||
|
{
|
||||||
|
BRect copy(*self);
|
||||||
|
copy.InsetBy(point);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" BRect
|
||||||
|
_ZN5BRect11InsetByCopyEff(BRect* self, float dx, float dy)
|
||||||
|
{
|
||||||
|
BRect copy(*self);
|
||||||
|
copy.InsetBy(dx, dy);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" BRect
|
||||||
|
_ZN5BRect12OffsetByCopyE6BPoint(BRect* self, BPoint point)
|
||||||
|
{
|
||||||
|
BRect copy(*self);
|
||||||
|
copy.OffsetBy(point);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" BRect
|
||||||
|
_ZN5BRect12OffsetByCopyEff(BRect* self, float dx, float dy)
|
||||||
|
{
|
||||||
|
BRect copy(*self);
|
||||||
|
copy.OffsetBy(dx, dy);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" BRect
|
||||||
|
_ZN5BRect12OffsetToCopyE6BPoint(BRect* self, BPoint point)
|
||||||
|
{
|
||||||
|
BRect copy(*self);
|
||||||
|
copy.OffsetTo(point);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" BRect
|
||||||
|
_ZN5BRect12OffsetToCopyEff(BRect* self, float dx, float dy)
|
||||||
|
{
|
||||||
|
BRect copy(*self);
|
||||||
|
copy.OffsetTo(dx, dy);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __GNUC__ == 4
|
||||||
|
|||||||
@@ -10,21 +10,38 @@
|
|||||||
|
|
||||||
#include <asm_defs.h>
|
#include <asm_defs.h>
|
||||||
|
|
||||||
|
#include "asm_offsets.h"
|
||||||
|
|
||||||
.text
|
.text
|
||||||
|
|
||||||
|
|
||||||
|
/* int mmu_read_c1(void); */
|
||||||
|
FUNCTION(mmu_read_c1):
|
||||||
|
mrc p15, 0, r0, c1, c0, 0
|
||||||
|
bx lr
|
||||||
|
FUNCTION_END(mmu_read_c1)
|
||||||
|
|
||||||
|
|
||||||
|
/* void mmu_write_c1(int val); */
|
||||||
|
FUNCTION(mmu_write_c1):
|
||||||
|
mcr p15, 0, r0, c1, c0, 0
|
||||||
|
bx lr
|
||||||
|
FUNCTION_END(mmu_write_c1)
|
||||||
|
|
||||||
|
|
||||||
|
/* NOTE: the I bit in cpsr (bit 7) is *set* to disable... */
|
||||||
|
|
||||||
|
|
||||||
/* void arch_int_enable_interrupts(void) */
|
/* void arch_int_enable_interrupts(void) */
|
||||||
FUNCTION(arch_int_enable_interrupts):
|
FUNCTION(arch_int_enable_interrupts):
|
||||||
mrs r0, cpsr
|
mrs r0, cpsr
|
||||||
bic r0, r0, #(1<<7) /* clear the I bit */
|
bic r0, r0, #(1<<7)
|
||||||
msr cpsr_c, r0
|
msr cpsr_c, r0
|
||||||
bx lr
|
bx lr
|
||||||
FUNCTION_END(arch_int_enable_interrupts)
|
FUNCTION_END(arch_int_enable_interrupts)
|
||||||
|
|
||||||
|
|
||||||
/* int arch_int_disable_interrupts(void)
|
/* int arch_int_disable_interrupts(void) */
|
||||||
*/
|
|
||||||
FUNCTION(arch_int_disable_interrupts):
|
FUNCTION(arch_int_disable_interrupts):
|
||||||
mrs r0, cpsr
|
mrs r0, cpsr
|
||||||
orr r1, r0, #(1<<7)
|
orr r1, r0, #(1<<7)
|
||||||
@@ -33,8 +50,7 @@ FUNCTION(arch_int_disable_interrupts):
|
|||||||
FUNCTION_END(arch_int_disable_interrupts)
|
FUNCTION_END(arch_int_disable_interrupts)
|
||||||
|
|
||||||
|
|
||||||
/* void arch_int_restore_interrupts(int oldState)
|
/* void arch_int_restore_interrupts(int oldState) */
|
||||||
*/
|
|
||||||
FUNCTION(arch_int_restore_interrupts):
|
FUNCTION(arch_int_restore_interrupts):
|
||||||
mrs r1, cpsr
|
mrs r1, cpsr
|
||||||
and r0, r0, #(1<<7)
|
and r0, r0, #(1<<7)
|
||||||
@@ -65,3 +81,57 @@ FUNCTION(arm_context_switch):
|
|||||||
ldmfd sp!, { r0-r12, lr }
|
ldmfd sp!, { r0-r12, lr }
|
||||||
bx lr
|
bx lr
|
||||||
FUNCTION_END(arm_context_switch)
|
FUNCTION_END(arm_context_switch)
|
||||||
|
|
||||||
|
/* addr_t arm_get_fsr(void); */
|
||||||
|
FUNCTION(arm_get_fsr):
|
||||||
|
mrc p15, 0, r0, c5, c0, 0 @ get FSR
|
||||||
|
bx lr
|
||||||
|
FUNCTION_END(arm_get_fsr)
|
||||||
|
|
||||||
|
/* addr_t arm_get_far(void); */
|
||||||
|
FUNCTION(arm_get_far):
|
||||||
|
mrc p15, 0, r0, c6, c0, 0 @ get FAR
|
||||||
|
bx lr
|
||||||
|
FUNCTION_END(arm_get_far)
|
||||||
|
|
||||||
|
/*! \fn void arch_debug_call_with_fault_handler(cpu_ent* cpu,
|
||||||
|
jmp_buf jumpBuffer, void (*function)(void*), void* parameter)
|
||||||
|
|
||||||
|
Called by debug_call_with_fault_handler() to do the dirty work of setting
|
||||||
|
the fault handler and calling the function. If the function causes a page
|
||||||
|
fault, the arch_debug_call_with_fault_handler() calls longjmp() with the
|
||||||
|
given \a jumpBuffer. Otherwise it returns normally.
|
||||||
|
|
||||||
|
debug_call_with_fault_handler() has already saved the CPU's fault_handler
|
||||||
|
and fault_handler_stack_pointer and will reset them later, so
|
||||||
|
arch_debug_call_with_fault_handler() doesn't need to care about it.
|
||||||
|
|
||||||
|
\param cpu The \c cpu_ent for the current CPU.
|
||||||
|
\param jumpBuffer Buffer to be used for longjmp().
|
||||||
|
\param function The function to be called.
|
||||||
|
\param parameter The parameter to be passed to the function to be called.
|
||||||
|
*/
|
||||||
|
FUNCTION(arch_debug_call_with_fault_handler):
|
||||||
|
stmfd sp!, { r4, lr }
|
||||||
|
|
||||||
|
// Set fault handler address, and fault handler stack pointer address. We
|
||||||
|
// don't need to save the previous values, since that's done by the caller.
|
||||||
|
ldr r4, =1f
|
||||||
|
str r4, [ r0, #CPU_ENT_fault_handler ]
|
||||||
|
str sp, [ r0, #CPU_ENT_fault_handler_stack_pointer ]
|
||||||
|
mov r4, r1
|
||||||
|
|
||||||
|
// call the function
|
||||||
|
mov r0, r3
|
||||||
|
blx r2
|
||||||
|
|
||||||
|
// regular return
|
||||||
|
ldmfd sp!, { r4, lr }
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
// fault -- return via longjmp(jumpBuffer, 1)
|
||||||
|
1:
|
||||||
|
mov r0, r4
|
||||||
|
mov r1, #1
|
||||||
|
bl longjmp
|
||||||
|
FUNCTION_END(arch_debug_call_with_fault_handler)
|
||||||
|
|||||||
@@ -251,14 +251,9 @@ arch_debug_stack_trace(void)
|
|||||||
void *
|
void *
|
||||||
arch_debug_get_caller(void)
|
arch_debug_get_caller(void)
|
||||||
{
|
{
|
||||||
#warning ARM:IMPLEMENT
|
/* Return the thread id as the kernel (for example the lock code) actually
|
||||||
// TODO: implement me
|
gets a somewhat valid indication of the caller back. */
|
||||||
//return __builtin_frame_address(1);
|
return (void*) thread_get_current_thread_id();
|
||||||
// struct stack_frame *frame;
|
|
||||||
//frame = __builtin_frame_address(0);
|
|
||||||
// frame = get_current_stack_frame();
|
|
||||||
// return (void *)frame->previous->return_address;
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -316,17 +311,7 @@ arch_debug_init(kernel_args *args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
/* arch_debug_call_with_fault_handler is in arch_asm.S */
|
||||||
arch_debug_call_with_fault_handler(cpu_ent* cpu, jmp_buf jumpBuffer,
|
|
||||||
void (*function)(void*), void* parameter)
|
|
||||||
{
|
|
||||||
// TODO: Implement fault handling! Most likely in assembly.
|
|
||||||
// (see src/system/kernel/arch/x86/arch_x86.S)
|
|
||||||
|
|
||||||
// For now, just call the function and hope we don't crash :P
|
|
||||||
function(parameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
arch_debug_unset_current_thread(void)
|
arch_debug_unset_current_thread(void)
|
||||||
|
|||||||
@@ -9,6 +9,49 @@
|
|||||||
|
|
||||||
#include <asm_defs.h>
|
#include <asm_defs.h>
|
||||||
|
|
||||||
|
#define CPSR_MODE_MASK 0x1f
|
||||||
|
#define CPSR_MODE_USR 0x10
|
||||||
|
#define CPSR_MODE_FIQ 0x11
|
||||||
|
#define CPSR_MODE_IRQ 0x12
|
||||||
|
#define CPSR_MODE_SVC 0x13
|
||||||
|
#define CPSR_MODE_ABT 0x17
|
||||||
|
#define CPSR_MODE_UND 0x1b
|
||||||
|
|
||||||
|
/* The following two macros are taken from FreeBSD... */
|
||||||
|
|
||||||
|
.macro PUSHFRAMEINSVC
|
||||||
|
stmdb sp, {r0-r3} /* Save 4 registers */
|
||||||
|
mov r0, lr /* Save xxx32 r14 */
|
||||||
|
mov r1, sp /* Save xxx32 sp */
|
||||||
|
mrs r3, spsr /* Save xxx32 spsr */
|
||||||
|
mrs r2, cpsr /* Get the CPSR */
|
||||||
|
bic r2, r2, #(CPSR_MODE_MASK)/* Fix for SVC mode */
|
||||||
|
orr r2, r2, #(CPSR_MODE_SVC)
|
||||||
|
msr cpsr_c, r2 /* Punch into SVC mode */
|
||||||
|
mov r2, sp /* Save SVC sp */
|
||||||
|
str r0, [sp, #-4]! /* Push return address */
|
||||||
|
str lr, [sp, #-4]! /* Push SVC lr */
|
||||||
|
str r2, [sp, #-4]! /* Push SVC sp */
|
||||||
|
msr spsr_all, r3 /* Restore correct spsr */
|
||||||
|
ldmdb r1, {r0-r3} /* Restore 4 regs from xxx mode */
|
||||||
|
sub sp, sp, #(4*15) /* Adjust the stack pointer */
|
||||||
|
stmia sp, {r0-r12} /* Push the user mode registers */
|
||||||
|
add r0, sp, #(4*13) /* Adjust the stack pointer */
|
||||||
|
stmia r0, {r13-r14}^ /* Push the user mode registers */
|
||||||
|
mov r0, r0 /* NOP for previous instruction */
|
||||||
|
mrs r0, spsr_all
|
||||||
|
str r0, [sp, #-4]! /* Save spsr */
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro PULLFRAMEFROMSVCANDEXIT
|
||||||
|
ldr r0, [sp], #0x0004 /* Get the SPSR from stack */
|
||||||
|
msr spsr_all, r0 /* restore SPSR */
|
||||||
|
ldmia sp, {r0-r14}^ /* Restore registers (usr mode) */
|
||||||
|
mov r0, r0 /* NOP for previous instruction */
|
||||||
|
add sp, sp, #(4*15) /* Adjust the stack pointer */
|
||||||
|
ldmia sp, {sp, lr, pc}^ /* Restore lr and exit */
|
||||||
|
.endm
|
||||||
|
|
||||||
.text
|
.text
|
||||||
|
|
||||||
.globl _vectors_start
|
.globl _vectors_start
|
||||||
@@ -43,134 +86,139 @@ _vectors_end:
|
|||||||
|
|
||||||
|
|
||||||
.rept 64
|
.rept 64
|
||||||
.word 0xaabbccdd
|
.word 0xdeadbeef
|
||||||
.endr
|
.endr
|
||||||
abort_stack:
|
abort_stack:
|
||||||
.word .
|
.word . - 4
|
||||||
|
.word 0xdeadbeef
|
||||||
|
|
||||||
|
.rept 64
|
||||||
|
.word 0xcafebabe
|
||||||
|
.endr
|
||||||
|
irq_stack:
|
||||||
|
.word . - 4
|
||||||
|
.word 0xcafebabe
|
||||||
|
|
||||||
|
.rept 64
|
||||||
|
.word 0xaaaabbbb
|
||||||
|
.endr
|
||||||
|
fiq_stack:
|
||||||
|
.word . - 4
|
||||||
|
.word 0xaaaabbbb
|
||||||
|
|
||||||
|
.rept 64
|
||||||
|
.word 0xccccdddd
|
||||||
|
.endr
|
||||||
|
und_stack:
|
||||||
|
.word . - 4
|
||||||
|
.word 0xccccdddd
|
||||||
|
|
||||||
|
|
||||||
FUNCTION(arm_undefined):
|
FUNCTION(arm_undefined):
|
||||||
stmfd sp!, { r0-r12, r14 }
|
PUSHFRAMEINSVC
|
||||||
sub sp, sp, #12
|
|
||||||
mov r0, sp
|
mov r0, sp
|
||||||
mrs r1, spsr
|
bl arch_arm_undefined
|
||||||
stmia r0, { r1, r13-r14 }
|
|
||||||
b arch_arm_undefined
|
PULLFRAMEFROMSVCANDEXIT
|
||||||
b .
|
FUNCTION_END(arm_undefined)
|
||||||
|
|
||||||
|
|
||||||
FUNCTION(arm_syscall):
|
FUNCTION(arm_syscall):
|
||||||
stmfd sp!, { r0-r12, r14 }
|
PUSHFRAMEINSVC
|
||||||
sub sp, sp, #12
|
|
||||||
mov r0, sp
|
mov r0, sp
|
||||||
mrs r1, spsr
|
bl arch_arm_syscall
|
||||||
stmia r0, { r1, r13-r14 }
|
|
||||||
b arch_arm_syscall
|
PULLFRAMEFROMSVCANDEXIT
|
||||||
b .
|
FUNCTION_END(arm_syscall)
|
||||||
|
|
||||||
|
|
||||||
FUNCTION(arm_prefetch_abort):
|
FUNCTION(arm_prefetch_abort):
|
||||||
ldr sp, abort_stack
|
#ifdef __XSCALE__
|
||||||
stmfd sp!, { r0-r12, r14 }
|
nop /* Make absolutely sure any pending */
|
||||||
sub sp, sp, #12
|
nop /* imprecise aborts have occurred. */
|
||||||
mov r0, sp
|
#endif
|
||||||
mrs r1, spsr
|
add lr, lr, #4
|
||||||
stmia r0, { r1, r13-r14 }
|
PUSHFRAMEINSVC
|
||||||
b arch_arm_prefetch_abort
|
|
||||||
b .
|
mov r0, sp
|
||||||
|
bl arch_arm_prefetch_abort
|
||||||
|
|
||||||
|
PULLFRAMEFROMSVCANDEXIT
|
||||||
|
FUNCTION_END(arm_prefetch_abort)
|
||||||
|
|
||||||
|
|
||||||
FUNCTION(arm_data_abort):
|
FUNCTION(arm_data_abort):
|
||||||
ldr sp, abort_stack
|
#ifdef __XSCALE__
|
||||||
/* XXX only deals with interrupting supervisor mode */
|
nop /* Make absolutely sure any pending */
|
||||||
|
nop /* imprecise aborts have occurred. */
|
||||||
|
#endif
|
||||||
|
sub lr, lr, #8 /* Adjust the lr */
|
||||||
|
PUSHFRAMEINSVC
|
||||||
|
|
||||||
/* save r4-r6 and use as a temporary place to save while we switch into supervisor mode */
|
mov r0, sp
|
||||||
stmia r13, { r4-r6 }
|
|
||||||
mov r4, r13
|
|
||||||
sub r5, lr, #8
|
|
||||||
mrs r6, spsr
|
|
||||||
|
|
||||||
/* move into supervisor mode. irq/fiq disabled */
|
|
||||||
msr cpsr_c, #0x13
|
|
||||||
|
|
||||||
/* save the return address */
|
|
||||||
stmfd sp!, { r5 }
|
|
||||||
|
|
||||||
/* save C trashed regs, supervisor lr */
|
|
||||||
stmfd sp!, { r0-r3, r12, lr }
|
|
||||||
|
|
||||||
/* save spsr */
|
|
||||||
stmfd sp!, { r6 }
|
|
||||||
|
|
||||||
/* restore r4-r6 */
|
|
||||||
ldmia r4, { r4-r6 }
|
|
||||||
|
|
||||||
/* call into higher level code */
|
|
||||||
mrc p15, 0, r2, c5, c0, 0 @ get FSR
|
|
||||||
mrc p15, 0, r3, c6, c0, 0 @ get FAR
|
|
||||||
sub sp, sp, #20
|
|
||||||
mov r0, sp /* iframe */
|
|
||||||
stmia r0, { r6,r2,r3,r4,r5 }
|
|
||||||
bl arch_arm_data_abort
|
bl arch_arm_data_abort
|
||||||
add sp, sp, #20
|
|
||||||
|
|
||||||
/* restore spsr */
|
PULLFRAMEFROMSVCANDEXIT
|
||||||
ldmfd sp!, { r0 }
|
|
||||||
msr spsr_cxsf, r0
|
|
||||||
|
|
||||||
/* restore back to where we came from */
|
|
||||||
ldmfd sp!, { r0-r3, r12, lr, pc }^
|
|
||||||
|
|
||||||
FUNCTION(arm_reserved):
|
FUNCTION(arm_reserved):
|
||||||
b .
|
b .
|
||||||
|
FUNCTION_END(arm_reserved)
|
||||||
|
|
||||||
FUNCTION(arm_irq):
|
FUNCTION(arm_irq):
|
||||||
ldr sp, abort_stack
|
sub lr, lr, #4
|
||||||
/* XXX only deals with interrupting supervisor mode */
|
PUSHFRAMEINSVC
|
||||||
|
|
||||||
/* save r4-r6 and use as a temporary place to save while we switch into supervisor mode */
|
|
||||||
stmia r13, { r4-r6 }
|
|
||||||
mov r4, r13
|
|
||||||
sub r5, lr, #4
|
|
||||||
mrs r6, spsr
|
|
||||||
|
|
||||||
/* move into supervisor mode. irq/fiq disabled */
|
|
||||||
msr cpsr_c, #(3<<6 | 0x13)
|
|
||||||
|
|
||||||
/* save the return address */
|
|
||||||
stmfd sp!, { r5 }
|
|
||||||
|
|
||||||
/* save C trashed regs, supervisor lr */
|
|
||||||
stmfd sp!, { r0-r3, r12, lr }
|
|
||||||
|
|
||||||
/* save spsr */
|
|
||||||
stmfd sp!, { r6 }
|
|
||||||
|
|
||||||
/* restore r4-r6 */
|
|
||||||
ldmia r4, { r4-r6 }
|
|
||||||
|
|
||||||
/* call into higher level code */
|
|
||||||
mov r0, sp /* iframe */
|
mov r0, sp /* iframe */
|
||||||
bl arch_arm_irq
|
bl arch_arm_irq
|
||||||
|
|
||||||
/* restore spsr */
|
PULLFRAMEFROMSVCANDEXIT
|
||||||
ldmfd sp!, { r0 }
|
FUNCTION_END(arm_irq)
|
||||||
msr spsr_cxsf, r0
|
|
||||||
|
|
||||||
/* restore back to where we came from */
|
|
||||||
ldmfd sp!, { r0-r3, r12, lr, pc }^
|
|
||||||
|
|
||||||
.bss
|
|
||||||
.align 2
|
|
||||||
.global irq_save_spot
|
|
||||||
irq_save_spot:
|
|
||||||
.word 0 /* r4 */
|
|
||||||
.word 0 /* r5 */
|
|
||||||
.word 0 /* r6 */
|
|
||||||
|
|
||||||
.text
|
|
||||||
FUNCTION(arm_fiq):
|
FUNCTION(arm_fiq):
|
||||||
ldr sp, abort_stack
|
|
||||||
sub lr, lr, #4
|
sub lr, lr, #4
|
||||||
stmfd sp!, { r0-r3, r12, lr }
|
PUSHFRAMEINSVC
|
||||||
|
|
||||||
|
mov r0, sp /* iframe */
|
||||||
bl arch_arm_fiq
|
bl arch_arm_fiq
|
||||||
|
|
||||||
ldmfd sp!, { r0-r3, r12, pc }^
|
PULLFRAMEFROMSVCANDEXIT
|
||||||
|
FUNCTION_END(arm_fiq)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
FUNCTION(arm_vector_init):
|
||||||
|
mrs r1, cpsr
|
||||||
|
bic r1, r1, #CPSR_MODE_MASK
|
||||||
|
|
||||||
|
/* move into modes and set initial sp */
|
||||||
|
mov r0, r1
|
||||||
|
orr r0, r0, #CPSR_MODE_FIQ
|
||||||
|
msr cpsr_c, r0
|
||||||
|
ldr sp, fiq_stack
|
||||||
|
|
||||||
|
mov r0, r1
|
||||||
|
orr r0, r0, #CPSR_MODE_IRQ
|
||||||
|
msr cpsr_c, r0
|
||||||
|
ldr sp, irq_stack
|
||||||
|
|
||||||
|
mov r0, r1
|
||||||
|
orr r0, r0, #CPSR_MODE_ABT
|
||||||
|
msr cpsr_c, r0
|
||||||
|
ldr sp, abort_stack
|
||||||
|
|
||||||
|
mov r0, r1
|
||||||
|
orr r0, r0, #CPSR_MODE_UND
|
||||||
|
msr cpsr_c, r0
|
||||||
|
ldr sp, und_stack
|
||||||
|
|
||||||
|
/* ... and return back to supervisor mode */
|
||||||
|
mov r0, r1
|
||||||
|
orr r0, r0, #CPSR_MODE_SVC
|
||||||
|
msr cpsr_c, r0
|
||||||
|
|
||||||
|
bx lr
|
||||||
|
FUNCTION_END(arm_vector_init)
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
#define TRACE_ARCH_INT
|
//#define TRACE_ARCH_INT
|
||||||
#ifdef TRACE_ARCH_INT
|
#ifdef TRACE_ARCH_INT
|
||||||
# define TRACE(x) dprintf x
|
# define TRACE(x) dprintf x
|
||||||
#else
|
#else
|
||||||
@@ -61,30 +61,11 @@ static void *sVectorPageAddress;
|
|||||||
static area_id sUserVectorPageArea;
|
static area_id sUserVectorPageArea;
|
||||||
static void *sUserVectorPageAddress;
|
static void *sUserVectorPageAddress;
|
||||||
|
|
||||||
// current fault handler
|
|
||||||
addr_t gFaultHandler;
|
|
||||||
|
|
||||||
// An iframe stack used in the early boot process when we don't have
|
// An iframe stack used in the early boot process when we don't have
|
||||||
// threads yet.
|
// threads yet.
|
||||||
struct iframe_stack gBootFrameStack;
|
struct iframe_stack gBootFrameStack;
|
||||||
|
|
||||||
|
|
||||||
uint32
|
|
||||||
mmu_read_c1()
|
|
||||||
{
|
|
||||||
uint32 controlReg = 0;
|
|
||||||
asm volatile("MRC p15, 0, %[c1out], c1, c0, 0":[c1out] "=r" (controlReg));
|
|
||||||
return controlReg;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
mmu_write_c1(uint32 value)
|
|
||||||
{
|
|
||||||
asm volatile("MCR p15, 0, %[c1in], c1, c0, 0"::[c1in] "r" (value));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
arch_int_enable_io_interrupt(int irq)
|
arch_int_enable_io_interrupt(int irq)
|
||||||
{
|
{
|
||||||
@@ -117,29 +98,32 @@ arch_int_disable_io_interrupt(int irq)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_iframe(struct iframe *frame)
|
print_iframe(const char *event, struct iframe *frame)
|
||||||
{
|
{
|
||||||
|
if (event)
|
||||||
|
dprintf("Exception: %s\n", event);
|
||||||
|
|
||||||
|
dprintf("R00=%08lx R01=%08lx R02=%08lx R03=%08lx\n"
|
||||||
|
"R04=%08lx R05=%08lx R06=%08lx R07=%08lx\n",
|
||||||
|
frame->r0, frame->r1, frame->r2, frame->r3,
|
||||||
|
frame->r4, frame->r5, frame->r6, frame->r7);
|
||||||
|
dprintf("R08=%08lx R09=%08lx R10=%08lx R11=%08lx\n"
|
||||||
|
"R12=%08lx R13=%08lx R14=%08lx CPSR=%08lx\n",
|
||||||
|
frame->r8, frame->r9, frame->r10, frame->r11,
|
||||||
|
frame->r12, frame->usr_sp, frame->usr_lr, frame->spsr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
arch_int_init(kernel_args *args)
|
arch_int_init(kernel_args *args)
|
||||||
{
|
{
|
||||||
// see if high vectors are enabled
|
|
||||||
if (mmu_read_c1() & (1<<13))
|
|
||||||
dprintf("High vectors already enabled\n");
|
|
||||||
else {
|
|
||||||
mmu_write_c1(mmu_read_c1() | (1<<13));
|
|
||||||
|
|
||||||
if (!(mmu_read_c1() & (1<<13)))
|
|
||||||
dprintf("Unable to enable high vectors!\n");
|
|
||||||
else
|
|
||||||
dprintf("Enabled high vectors\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" void arm_vector_init(void);
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
arch_int_init_post_vm(kernel_args *args)
|
arch_int_init_post_vm(kernel_args *args)
|
||||||
{
|
{
|
||||||
@@ -163,6 +147,20 @@ arch_int_init_post_vm(kernel_args *args)
|
|||||||
// copy vectors into the newly created area
|
// copy vectors into the newly created area
|
||||||
memcpy(sVectorPageAddress, &_vectors_start, VECTORPAGE_SIZE);
|
memcpy(sVectorPageAddress, &_vectors_start, VECTORPAGE_SIZE);
|
||||||
|
|
||||||
|
arm_vector_init();
|
||||||
|
|
||||||
|
// see if high vectors are enabled
|
||||||
|
if (mmu_read_c1() & (1<<13))
|
||||||
|
dprintf("High vectors already enabled\n");
|
||||||
|
else {
|
||||||
|
mmu_write_c1(mmu_read_c1() | (1<<13));
|
||||||
|
|
||||||
|
if (!(mmu_read_c1() & (1<<13)))
|
||||||
|
dprintf("Unable to enable high vectors!\n");
|
||||||
|
else
|
||||||
|
dprintf("Enabled high vectors\n");
|
||||||
|
}
|
||||||
|
|
||||||
sPxaInterruptArea = map_physical_memory("pxa_intc", PXA_INTERRUPT_PHYS_BASE,
|
sPxaInterruptArea = map_physical_memory("pxa_intc", PXA_INTERRUPT_PHYS_BASE,
|
||||||
PXA_INTERRUPT_SIZE, 0, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&sPxaInterruptBase);
|
PXA_INTERRUPT_SIZE, 0, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&sPxaInterruptBase);
|
||||||
|
|
||||||
@@ -179,7 +177,6 @@ arch_int_init_post_vm(kernel_args *args)
|
|||||||
status_t
|
status_t
|
||||||
arch_int_init_io(kernel_args* args)
|
arch_int_init_io(kernel_args* args)
|
||||||
{
|
{
|
||||||
TRACE(("arch_int_init_io(%p)\n", args));
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,35 +190,101 @@ arch_int_init_post_device_manager(struct kernel_args *args)
|
|||||||
|
|
||||||
extern "C" void arch_arm_undefined(struct iframe *iframe)
|
extern "C" void arch_arm_undefined(struct iframe *iframe)
|
||||||
{
|
{
|
||||||
panic("Undefined instruction!");
|
print_iframe("Undefined Instruction", iframe);
|
||||||
|
panic("not handled!");
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void arch_arm_syscall(struct iframe *iframe)
|
extern "C" void arch_arm_syscall(struct iframe *iframe)
|
||||||
{
|
{
|
||||||
panic("Software interrupt!\n");
|
print_iframe("Software interrupt", iframe);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void arch_arm_data_abort(struct iframe *iframe)
|
extern "C" void arch_arm_data_abort(struct iframe *frame)
|
||||||
{
|
{
|
||||||
addr_t newip;
|
Thread *thread = thread_get_current_thread();
|
||||||
status_t res = vm_page_fault(iframe->r2 /* FAR */, iframe->r4 /* lr */,
|
bool isUser = (frame->spsr & 0x1f) == 0x10;
|
||||||
true /* TODO how to determine read/write? */,
|
addr_t far = arm_get_far();
|
||||||
false /* only kernelspace for now */,
|
bool isWrite = true;
|
||||||
&newip);
|
addr_t newip = 0;
|
||||||
|
|
||||||
if (res != B_HANDLED_INTERRUPT) {
|
#ifdef TRACE_ARCH_INT
|
||||||
panic("Data Abort: %08x %08x %08x %08x (res=%lx)", iframe->r0 /* spsr */,
|
print_iframe("Data Abort", frame);
|
||||||
iframe->r1 /* FSR */, iframe->r2 /* FAR */,
|
#endif
|
||||||
iframe->r4 /* lr */,
|
|
||||||
res);
|
if (debug_debugger_running()) {
|
||||||
} else {
|
// If this CPU or this thread has a fault handler, we're allowed to be
|
||||||
//panic("vm_page_fault was ok (%08lx/%08lx)!", iframe->r2 /* FAR */, iframe->r0 /* spsr */);
|
// here.
|
||||||
|
if (thread != NULL) {
|
||||||
|
cpu_ent* cpu = &gCPU[smp_get_current_cpu()];
|
||||||
|
|
||||||
|
if (cpu->fault_handler != 0) {
|
||||||
|
debug_set_page_fault_info(far, frame->pc,
|
||||||
|
isWrite ? DEBUG_PAGE_FAULT_WRITE : 0);
|
||||||
|
frame->svc_sp = cpu->fault_handler_stack_pointer;
|
||||||
|
frame->pc = cpu->fault_handler;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thread->fault_handler != 0) {
|
||||||
|
kprintf("ERROR: thread::fault_handler used in kernel "
|
||||||
|
"debugger!\n");
|
||||||
|
debug_set_page_fault_info(far, frame->pc,
|
||||||
|
isWrite ? DEBUG_PAGE_FAULT_WRITE : 0);
|
||||||
|
frame->pc = thread->fault_handler;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise, not really
|
||||||
|
panic("page fault in debugger without fault handler! Touching "
|
||||||
|
"address %p from pc %p\n", (void *)far, (void *)frame->pc);
|
||||||
|
return;
|
||||||
|
} else if ((frame->spsr & (1 << 7)) != 0) {
|
||||||
|
// interrupts disabled
|
||||||
|
|
||||||
|
// If a page fault handler is installed, we're allowed to be here.
|
||||||
|
// TODO: Now we are generally allowing user_memcpy() with interrupts
|
||||||
|
// disabled, which in most cases is a bug. We should add some thread
|
||||||
|
// flag allowing to explicitly indicate that this handling is desired.
|
||||||
|
if (thread && thread->fault_handler != 0) {
|
||||||
|
if (frame->pc != thread->fault_handler) {
|
||||||
|
frame->pc = thread->fault_handler;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The fault happened at the fault handler address. This is a
|
||||||
|
// certain infinite loop.
|
||||||
|
panic("page fault, interrupts disabled, fault handler loop. "
|
||||||
|
"Touching address %p from pc %p\n", (void*)far,
|
||||||
|
(void*)frame->pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we are not running the kernel startup the page fault was not
|
||||||
|
// allowed to happen and we must panic.
|
||||||
|
panic("page fault, but interrupts were disabled. Touching address "
|
||||||
|
"%p from pc %p\n", (void *)far, (void *)frame->pc);
|
||||||
|
return;
|
||||||
|
} else if (thread != NULL && thread->page_faults_allowed < 1) {
|
||||||
|
panic("page fault not allowed at this place. Touching address "
|
||||||
|
"%p from pc %p\n", (void *)far, (void *)frame->pc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
enable_interrupts();
|
||||||
|
|
||||||
|
vm_page_fault(far, frame->pc, isWrite, isUser, &newip);
|
||||||
|
|
||||||
|
if (newip != 0) {
|
||||||
|
// the page fault handler wants us to modify the iframe to set the
|
||||||
|
// IP the cpu will return to to be this ip
|
||||||
|
frame->pc = newip;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void arch_arm_prefetch_abort(struct iframe *iframe)
|
extern "C" void arch_arm_prefetch_abort(struct iframe *iframe)
|
||||||
{
|
{
|
||||||
panic("Prefetch Abort: %08x %08x %08x", iframe->r0, iframe->r1, iframe->r2);
|
print_iframe("Prefetch Abort", iframe);
|
||||||
|
panic("not handled!");
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void arch_arm_irq(struct iframe *iframe)
|
extern "C" void arch_arm_irq(struct iframe *iframe)
|
||||||
|
|||||||
@@ -6,52 +6,17 @@
|
|||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
* All rights reserved. Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//#include <arch_platform.h>
|
|
||||||
|
|
||||||
#include <new>
|
|
||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
#include <arch/platform.h>
|
#include <arch/platform.h>
|
||||||
#include <boot/kernel_args.h>
|
#include <boot/kernel_args.h>
|
||||||
//#include <platform/openfirmware/openfirmware.h>
|
|
||||||
#include <real_time_clock.h>
|
#include <real_time_clock.h>
|
||||||
#include <util/kernel_cpp.h>
|
#include <util/kernel_cpp.h>
|
||||||
|
#include <kernel/debug.h>
|
||||||
|
|
||||||
#if 0
|
|
||||||
static M68KPlatform *sM68KPlatform;
|
|
||||||
|
|
||||||
|
|
||||||
// constructor
|
|
||||||
M68KPlatform::M68KPlatform(platform_type platformType,
|
|
||||||
m68k_platform_type m68kPlatformType)
|
|
||||||
: fPlatformType(platformType),
|
|
||||||
fM68KPlatformType(m68kPlatformType)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// destructor
|
|
||||||
M68KPlatform::~M68KPlatform()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Default
|
|
||||||
M68KPlatform *
|
|
||||||
M68KPlatform::Default()
|
|
||||||
{
|
|
||||||
return sM68KPlatform;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// # pragma mark -
|
|
||||||
#endif
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
arch_platform_init(struct kernel_args *kernelArgs)
|
arch_platform_init(struct kernel_args *kernelArgs)
|
||||||
{
|
{
|
||||||
#warning ARM:WRITEME
|
// NOTE: dprintf() is off-limits here, too early...
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,8 +24,7 @@ arch_platform_init(struct kernel_args *kernelArgs)
|
|||||||
status_t
|
status_t
|
||||||
arch_platform_init_post_vm(struct kernel_args *kernelArgs)
|
arch_platform_init_post_vm(struct kernel_args *kernelArgs)
|
||||||
{
|
{
|
||||||
#warning ARM:WRITEME
|
// now we can use the heap and create areas
|
||||||
//sM68KPlatform->InitPostVM(kernelArgs);
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,5 +32,6 @@ arch_platform_init_post_vm(struct kernel_args *kernelArgs)
|
|||||||
status_t
|
status_t
|
||||||
arch_platform_init_post_thread(struct kernel_args *kernelArgs)
|
arch_platform_init_post_thread(struct kernel_args *kernelArgs)
|
||||||
{
|
{
|
||||||
|
// now we can create and use semaphores
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define TRACE_ARCH_THREAD
|
//#define TRACE_ARCH_THREAD
|
||||||
#ifdef TRACE_ARCH_THREAD
|
#ifdef TRACE_ARCH_THREAD
|
||||||
# define TRACE(x) dprintf x
|
# define TRACE(x) dprintf x
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -19,6 +19,15 @@
|
|||||||
#include <arch/timer.h>
|
#include <arch/timer.h>
|
||||||
#include <arch/cpu.h>
|
#include <arch/cpu.h>
|
||||||
|
|
||||||
|
|
||||||
|
//#define TRACE_ARCH_TIMER
|
||||||
|
#ifdef TRACE_ARCH_TIMER
|
||||||
|
# define TRACE(x) dprintf x
|
||||||
|
#else
|
||||||
|
# define TRACE(x) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define PXA_TIMERS_PHYS_BASE 0x40A00000
|
#define PXA_TIMERS_PHYS_BASE 0x40A00000
|
||||||
#define PXA_TIMERS_SIZE 0x000000C0
|
#define PXA_TIMERS_SIZE 0x000000C0
|
||||||
#define PXA_TIMERS_INTERRUPT 7 /* OST_4_11 */
|
#define PXA_TIMERS_INTERRUPT 7 /* OST_4_11 */
|
||||||
@@ -29,7 +38,6 @@
|
|||||||
#define PXA_OSMR4 0x20
|
#define PXA_OSMR4 0x20
|
||||||
#define PXA_OMCR4 0x30
|
#define PXA_OMCR4 0x30
|
||||||
|
|
||||||
#define TRACE(x) //dprintf x
|
|
||||||
|
|
||||||
static area_id sPxaTimersArea;
|
static area_id sPxaTimersArea;
|
||||||
static uint32 *sPxaTimersBase;
|
static uint32 *sPxaTimersBase;
|
||||||
@@ -48,7 +56,7 @@ pxa_timer_interrupt(void *data)
|
|||||||
void
|
void
|
||||||
arch_timer_set_hardware_timer(bigtime_t timeout)
|
arch_timer_set_hardware_timer(bigtime_t timeout)
|
||||||
{
|
{
|
||||||
TRACE(("arch_timer_set_hardware_timer(%lld): %p\n", timeout, sPxaTimersBase));
|
TRACE(("arch_timer_set_hardware_timer(%lld)\n", timeout));
|
||||||
|
|
||||||
if (sPxaTimersBase) {
|
if (sPxaTimersBase) {
|
||||||
sPxaTimersBase[PXA_OIER] |= (1 << 4);
|
sPxaTimersBase[PXA_OIER] |= (1 << 4);
|
||||||
@@ -62,7 +70,7 @@ arch_timer_set_hardware_timer(bigtime_t timeout)
|
|||||||
void
|
void
|
||||||
arch_timer_clear_hardware_timer()
|
arch_timer_clear_hardware_timer()
|
||||||
{
|
{
|
||||||
TRACE(("arch_timer_clear_hardware_timer: %p\n", sPxaTimersBase));
|
TRACE(("arch_timer_clear_hardware_timer\n"));
|
||||||
|
|
||||||
if (sPxaTimersBase) {
|
if (sPxaTimersBase) {
|
||||||
sPxaTimersBase[PXA_OMCR4] = 0; // disable our timer
|
sPxaTimersBase[PXA_OMCR4] = 0; // disable our timer
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2007-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// This file is used to get C structure offsets into assembly code.
|
||||||
|
// The build system assembles the file and processes the output to create
|
||||||
|
// a header file with macro definitions, that can be included from assembly
|
||||||
|
// code.
|
||||||
|
|
||||||
|
|
||||||
|
#include <computed_asm_macros.h>
|
||||||
|
|
||||||
|
#include <arch_cpu.h>
|
||||||
|
#include <cpu.h>
|
||||||
|
#include <ksignal.h>
|
||||||
|
#include <ksyscalls.h>
|
||||||
|
#include <thread_types.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define DEFINE_MACRO(macro, value) DEFINE_COMPUTED_ASM_MACRO(macro, value)
|
||||||
|
|
||||||
|
#define DEFINE_OFFSET_MACRO(prefix, structure, member) \
|
||||||
|
DEFINE_MACRO(prefix##_##member, offsetof(struct structure, member));
|
||||||
|
|
||||||
|
#define DEFINE_SIZEOF_MACRO(prefix, structure) \
|
||||||
|
DEFINE_MACRO(prefix##_sizeof, sizeof(struct structure));
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
dummy()
|
||||||
|
{
|
||||||
|
// struct cpu_ent
|
||||||
|
DEFINE_OFFSET_MACRO(CPU_ENT, cpu_ent, fault_handler);
|
||||||
|
DEFINE_OFFSET_MACRO(CPU_ENT, cpu_ent, fault_handler_stack_pointer);
|
||||||
|
|
||||||
|
// struct Thread
|
||||||
|
DEFINE_OFFSET_MACRO(THREAD, Thread, time_lock);
|
||||||
|
DEFINE_OFFSET_MACRO(THREAD, Thread, kernel_time);
|
||||||
|
DEFINE_OFFSET_MACRO(THREAD, Thread, user_time);
|
||||||
|
DEFINE_OFFSET_MACRO(THREAD, Thread, last_time);
|
||||||
|
DEFINE_OFFSET_MACRO(THREAD, Thread, in_kernel);
|
||||||
|
DEFINE_OFFSET_MACRO(THREAD, Thread, flags);
|
||||||
|
DEFINE_OFFSET_MACRO(THREAD, Thread, kernel_stack_top);
|
||||||
|
DEFINE_OFFSET_MACRO(THREAD, Thread, fault_handler);
|
||||||
|
|
||||||
|
// struct iframe
|
||||||
|
DEFINE_SIZEOF_MACRO(IFRAME, iframe);
|
||||||
|
|
||||||
|
// struct signal_frame_data
|
||||||
|
DEFINE_SIZEOF_MACRO(SIGNAL_FRAME_DATA, signal_frame_data);
|
||||||
|
DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, info);
|
||||||
|
DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, context);
|
||||||
|
DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, user_data);
|
||||||
|
DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, handler);
|
||||||
|
|
||||||
|
// struct ucontext_t
|
||||||
|
DEFINE_OFFSET_MACRO(UCONTEXT_T, __ucontext_t, uc_mcontext);
|
||||||
|
|
||||||
|
// struct siginfo_t
|
||||||
|
DEFINE_OFFSET_MACRO(SIGINFO_T, __siginfo_t, si_signo);
|
||||||
|
}
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
#include "paging/arm_physical_page_mapper_large_memory.h"
|
#include "paging/arm_physical_page_mapper_large_memory.h"
|
||||||
|
|
||||||
|
|
||||||
#define TRACE_ARM_PAGING_METHOD_32_BIT
|
//#define TRACE_ARM_PAGING_METHOD_32_BIT
|
||||||
#ifdef TRACE_ARM_PAGING_METHOD_32_BIT
|
#ifdef TRACE_ARM_PAGING_METHOD_32_BIT
|
||||||
# define TRACE(x...) dprintf(x)
|
# define TRACE(x...) dprintf(x)
|
||||||
#else
|
#else
|
||||||
@@ -169,7 +169,8 @@ void
|
|||||||
ARMPagingMethod32Bit::PhysicalPageSlotPool::Map(phys_addr_t physicalAddress,
|
ARMPagingMethod32Bit::PhysicalPageSlotPool::Map(phys_addr_t physicalAddress,
|
||||||
addr_t virtualAddress)
|
addr_t virtualAddress)
|
||||||
{
|
{
|
||||||
page_table_entry& pte = fPageTable[(virtualAddress - fVirtualBase) / B_PAGE_SIZE];
|
page_table_entry& pte = fPageTable[
|
||||||
|
(virtualAddress - fVirtualBase) / B_PAGE_SIZE];
|
||||||
pte = (physicalAddress & ARM_PTE_ADDRESS_MASK)
|
pte = (physicalAddress & ARM_PTE_ADDRESS_MASK)
|
||||||
| ARM_PTE_TYPE_SMALL_PAGE;
|
| ARM_PTE_TYPE_SMALL_PAGE;
|
||||||
|
|
||||||
@@ -298,7 +299,7 @@ ARMPagingMethod32Bit::Init(kernel_args* args,
|
|||||||
x86_write_cr4(x86_read_cr4() | IA32_CR4_GLOBAL_PAGES);
|
x86_write_cr4(x86_read_cr4() | IA32_CR4_GLOBAL_PAGES);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
TRACE("vm_translation_map_init: done\n");
|
TRACE("ARMPagingMethod32Bit::Init(): done\n");
|
||||||
|
|
||||||
*_physicalPageMapper = fPhysicalPageMapper;
|
*_physicalPageMapper = fPhysicalPageMapper;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
@@ -249,14 +249,12 @@ ARMVMTranslationMap32Bit::Unmap(addr_t start, addr_t end)
|
|||||||
ARM_PTE_TYPE_MASK);
|
ARM_PTE_TYPE_MASK);
|
||||||
fMapCount--;
|
fMapCount--;
|
||||||
|
|
||||||
#if 0 /* IRA */
|
if (true /* (oldEntry & ARM_PTE_ACCESSED) != 0*/) {
|
||||||
if ((oldEntry & ARM_PTE_ACCESSED) != 0) {
|
|
||||||
// Note, that we only need to invalidate the address, if the
|
// Note, that we only need to invalidate the address, if the
|
||||||
// accessed flags was set, since only then the entry could have
|
// accessed flags was set, since only then the entry could have
|
||||||
// been in any TLB.
|
// been in any TLB.
|
||||||
InvalidatePage(start);
|
InvalidatePage(start);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
} while (start != 0 && start < end);
|
} while (start != 0 && start < end);
|
||||||
|
|
||||||
@@ -301,8 +299,8 @@ ARMVMTranslationMap32Bit::UnmapPage(VMArea* area, addr_t address,
|
|||||||
|
|
||||||
fMapCount--;
|
fMapCount--;
|
||||||
|
|
||||||
#if 0 //IRA
|
|
||||||
if ((oldEntry & ARM_PTE_ACCESSED) != 0) {
|
if (true /*(oldEntry & ARM_PTE_ACCESSED) != 0*/) { // XXX IRA
|
||||||
// Note, that we only need to invalidate the address, if the
|
// Note, that we only need to invalidate the address, if the
|
||||||
// accessed flags was set, since only then the entry could have been
|
// accessed flags was set, since only then the entry could have been
|
||||||
// in any TLB.
|
// in any TLB.
|
||||||
@@ -320,14 +318,14 @@ ARMVMTranslationMap32Bit::UnmapPage(VMArea* area, addr_t address,
|
|||||||
// Interestingly FreeBSD seems to ignore this problem as well
|
// Interestingly FreeBSD seems to ignore this problem as well
|
||||||
// (cf. pmap_remove_all()), unless I've missed something.
|
// (cf. pmap_remove_all()), unless I've missed something.
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
locker.Detach();
|
locker.Detach();
|
||||||
// PageUnmapped() will unlock for us
|
// PageUnmapped() will unlock for us
|
||||||
#if 0 //IRA
|
|
||||||
PageUnmapped(area, (oldEntry & ARM_PTE_ADDRESS_MASK) / B_PAGE_SIZE,
|
PageUnmapped(area, (oldEntry & ARM_PTE_ADDRESS_MASK) / B_PAGE_SIZE,
|
||||||
(oldEntry & ARM_PTE_ACCESSED) != 0, (oldEntry & ARM_PTE_DIRTY) != 0,
|
true /*(oldEntry & ARM_PTE_ACCESSED) != 0*/, true /*(oldEntry & ARM_PTE_DIRTY) != 0*/,
|
||||||
updatePageQueue);
|
updatePageQueue);
|
||||||
#endif
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,14 +373,13 @@ ARMVMTranslationMap32Bit::UnmapPages(VMArea* area, addr_t base, size_t size,
|
|||||||
|
|
||||||
fMapCount--;
|
fMapCount--;
|
||||||
|
|
||||||
#if 0 //IRA
|
if (true /*(oldEntry & ARM_PTE_ACCESSED) != 0*/) { // XXX IRA
|
||||||
if ((oldEntry & ARM_PTE_ACCESSED) != 0) {
|
|
||||||
// Note, that we only need to invalidate the address, if the
|
// Note, that we only need to invalidate the address, if the
|
||||||
// accessed flags was set, since only then the entry could have
|
// accessed flags was set, since only then the entry could have
|
||||||
// been in any TLB.
|
// been in any TLB.
|
||||||
InvalidatePage(start);
|
InvalidatePage(start);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (area->cache_type != CACHE_TYPE_DEVICE) {
|
if (area->cache_type != CACHE_TYPE_DEVICE) {
|
||||||
// get the page
|
// get the page
|
||||||
vm_page* page = vm_lookup_page(
|
vm_page* page = vm_lookup_page(
|
||||||
@@ -390,13 +387,13 @@ ARMVMTranslationMap32Bit::UnmapPages(VMArea* area, addr_t base, size_t size,
|
|||||||
ASSERT(page != NULL);
|
ASSERT(page != NULL);
|
||||||
|
|
||||||
DEBUG_PAGE_ACCESS_START(page);
|
DEBUG_PAGE_ACCESS_START(page);
|
||||||
#if 0
|
|
||||||
// transfer the accessed/dirty flags to the page
|
// transfer the accessed/dirty flags to the page
|
||||||
if ((oldEntry & ARM_PTE_ACCESSED) != 0)
|
if (/*(oldEntry & ARM_PTE_ACCESSED) != 0*/ true) // XXX IRA
|
||||||
page->accessed = true;
|
page->accessed = true;
|
||||||
if ((oldEntry & ARM_PTE_DIRTY) != 0)
|
if (/*(oldEntry & ARM_PTE_DIRTY) != 0 */ true)
|
||||||
page->modified = true;
|
page->modified = true;
|
||||||
#endif
|
|
||||||
// remove the mapping object/decrement the wired_count of the
|
// remove the mapping object/decrement the wired_count of the
|
||||||
// page
|
// page
|
||||||
if (area->wiring == B_NO_LOCK) {
|
if (area->wiring == B_NO_LOCK) {
|
||||||
@@ -512,19 +509,19 @@ ARMVMTranslationMap32Bit::UnmapArea(VMArea* area, bool deletingAddressSpace,
|
|||||||
"has no page table entry", page, area, address);
|
"has no page table entry", page, area, address);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
// transfer the accessed/dirty flags to the page and invalidate
|
// transfer the accessed/dirty flags to the page and invalidate
|
||||||
// the mapping, if necessary
|
// the mapping, if necessary
|
||||||
if ((oldEntry & ARM_PTE_ACCESSED) != 0) {
|
if (true /*(oldEntry & ARM_PTE_ACCESSED) != 0*/) { // XXX IRA
|
||||||
page->accessed = true;
|
page->accessed = true;
|
||||||
|
|
||||||
if (!deletingAddressSpace)
|
if (!deletingAddressSpace)
|
||||||
InvalidatePage(address);
|
InvalidatePage(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((oldEntry & ARM_PTE_DIRTY) != 0)
|
if (true /*(oldEntry & ARM_PTE_DIRTY) != 0*/)
|
||||||
page->modified = true;
|
page->modified = true;
|
||||||
#endif
|
|
||||||
if (pageFullyUnmapped) {
|
if (pageFullyUnmapped) {
|
||||||
DEBUG_PAGE_ACCESS_START(page);
|
DEBUG_PAGE_ACCESS_START(page);
|
||||||
|
|
||||||
@@ -640,7 +637,7 @@ ARMVMTranslationMap32Bit::QueryInterrupt(addr_t va, phys_addr_t *_physical,
|
|||||||
| ((entry & ARM_PTE_ACCESSED) != 0 ? PAGE_ACCESSED : 0)
|
| ((entry & ARM_PTE_ACCESSED) != 0 ? PAGE_ACCESSED : 0)
|
||||||
| ((entry & ARM_PTE_PRESENT) != 0 ? PAGE_PRESENT : 0);
|
| ((entry & ARM_PTE_PRESENT) != 0 ? PAGE_PRESENT : 0);
|
||||||
#else
|
#else
|
||||||
*_flags = B_KERNEL_WRITE_AREA | B_KERNEL_READ_AREA;
|
*_flags = B_KERNEL_WRITE_AREA | B_KERNEL_READ_AREA | PAGE_PRESENT;
|
||||||
#endif
|
#endif
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -752,7 +749,7 @@ ARMVMTranslationMap32Bit::ClearFlags(addr_t va, uint32 flags)
|
|||||||
|
|
||||||
pinner.Unlock();
|
pinner.Unlock();
|
||||||
|
|
||||||
if ((oldEntry & flagsToClear) != 0)
|
//XXX IRA if ((oldEntry & flagsToClear) != 0)
|
||||||
InvalidatePage(va);
|
InvalidatePage(va);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -820,10 +817,9 @@ ARMVMTranslationMap32Bit::ClearAccessedAndModified(VMArea* area, addr_t address,
|
|||||||
|
|
||||||
pinner.Unlock();
|
pinner.Unlock();
|
||||||
|
|
||||||
#if 0 //IRA
|
_modified = true /* (oldEntry & ARM_PTE_DIRTY) != 0 */; // XXX IRA
|
||||||
_modified = (oldEntry & ARM_PTE_DIRTY) != 0;
|
|
||||||
|
|
||||||
if ((oldEntry & ARM_PTE_ACCESSED) != 0) {
|
if (true /*(oldEntry & ARM_PTE_ACCESSED) != 0*/) {
|
||||||
// Note, that we only need to invalidate the address, if the
|
// Note, that we only need to invalidate the address, if the
|
||||||
// accessed flags was set, since only then the entry could have been
|
// accessed flags was set, since only then the entry could have been
|
||||||
// in any TLB.
|
// in any TLB.
|
||||||
@@ -833,9 +829,6 @@ ARMVMTranslationMap32Bit::ClearAccessedAndModified(VMArea* area, addr_t address,
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
_modified = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!unmapIfUnaccessed)
|
if (!unmapIfUnaccessed)
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -107,12 +107,12 @@ KPath::InitCheck() const
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
KPath::SetPath(const char *path, bool normalize, bool traverseLeafLink)
|
KPath::SetPath(const char* path, bool normalize, bool traverseLeafLink)
|
||||||
{
|
{
|
||||||
if (!fBuffer)
|
if (fBuffer == NULL)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
|
|
||||||
if (path) {
|
if (path != NULL) {
|
||||||
if (normalize) {
|
if (normalize) {
|
||||||
// normalize path
|
// normalize path
|
||||||
status_t error = vfs_normalize_path(path, fBuffer, fBufferSize,
|
status_t error = vfs_normalize_path(path, fBuffer, fBufferSize,
|
||||||
@@ -148,10 +148,10 @@ KPath::Path() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char *
|
char*
|
||||||
KPath::LockBuffer()
|
KPath::LockBuffer()
|
||||||
{
|
{
|
||||||
if (!fBuffer || fLocked)
|
if (fBuffer == NULL || fLocked)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
fLocked = true;
|
fLocked = true;
|
||||||
@@ -193,7 +193,7 @@ KPath::DetachBuffer()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char *
|
const char*
|
||||||
KPath::Leaf() const
|
KPath::Leaf() const
|
||||||
{
|
{
|
||||||
if (!fBuffer)
|
if (!fBuffer)
|
||||||
@@ -212,9 +212,9 @@ KPath::Leaf() const
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
KPath::ReplaceLeaf(const char *newLeaf)
|
KPath::ReplaceLeaf(const char* newLeaf)
|
||||||
{
|
{
|
||||||
const char *leaf = Leaf();
|
const char* leaf = Leaf();
|
||||||
if (!leaf)
|
if (!leaf)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
|
|
||||||
@@ -237,7 +237,7 @@ bool
|
|||||||
KPath::RemoveLeaf()
|
KPath::RemoveLeaf()
|
||||||
{
|
{
|
||||||
// get the leaf -- bail out, if not initialized or only the "/" is left
|
// get the leaf -- bail out, if not initialized or only the "/" is left
|
||||||
const char *leaf = Leaf();
|
const char* leaf = Leaf();
|
||||||
if (!leaf || leaf == fBuffer)
|
if (!leaf || leaf == fBuffer)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -252,12 +252,12 @@ KPath::RemoveLeaf()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
KPath::Append(const char *component, bool isComponent)
|
KPath::Append(const char* component, bool isComponent)
|
||||||
{
|
{
|
||||||
// check initialization and parameter
|
// check initialization and parameter
|
||||||
if (!fBuffer)
|
if (fBuffer == NULL)
|
||||||
return B_NO_INIT;
|
return B_NO_INIT;
|
||||||
if (!component)
|
if (component == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
if (fPathLength == 0)
|
if (fPathLength == 0)
|
||||||
return SetPath(component);
|
return SetPath(component);
|
||||||
|
|||||||
Reference in New Issue
Block a user