Merge branch 'master' into sam460ex
This commit is contained in:
commit
17c270bd4f
@ -973,12 +973,12 @@ if [ IsOptionalHaikuImagePackageAdded friss ] {
|
||||
} else {
|
||||
if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
InstallOptionalHaikuImagePackage
|
||||
friss-29-r1a4-x86-gcc4-2012-09-09.zip
|
||||
: $(baseURL)/friss-29-r1a4-x86-gcc4-2012-09-09.zip ;
|
||||
friss-33-r1a4-x86-gcc4-2012-11-06.zip
|
||||
: $(baseURL)/friss-33-r1a4-x86-gcc4-2012-11-06.zip ;
|
||||
} else {
|
||||
InstallOptionalHaikuImagePackage
|
||||
friss-29-r1a4-x86-gcc2-2012-08-28.zip
|
||||
: $(baseURL)/friss-29-r1a4-x86-gcc2-2012-08-28.zip ;
|
||||
friss-33-r1a4-x86-gcc2-2012-11-06.zip
|
||||
: $(baseURL)/friss-33-r1a4-x86-gcc2-2012-11-06.zip ;
|
||||
}
|
||||
# AddSymlinkToHaikuImage home config settings deskbar Desktop\ applets
|
||||
# : /boot/apps/FRiSS/FRiSS ;
|
||||
@ -1160,12 +1160,14 @@ if [ IsOptionalHaikuImagePackageAdded KeymapSwitcher ] {
|
||||
} else {
|
||||
if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
InstallOptionalHaikuImagePackage
|
||||
KeymapSwitcher-1.2.7-r1a4-x86-gcc4-2012-09-09.zip
|
||||
: $(baseURL)/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-11-01.zip
|
||||
: : : false ;
|
||||
} else {
|
||||
InstallOptionalHaikuImagePackage
|
||||
KeymapSwitcher-1.2.7-r1a4-x86-gcc2-2012-08-31.zip
|
||||
: $(baseURL)/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-11-01.zip
|
||||
: : : false ;
|
||||
}
|
||||
AddSymlinkToHaikuImage home config settings deskbar Preferences
|
||||
: /boot/common/bin/KeymapSwitcher ;
|
||||
|
@ -25,7 +25,8 @@ switch $(HAIKU_BUILD_PROFILE) {
|
||||
WebPositive WonderBrush ;
|
||||
AddOptionalHaikuImagePackages CVS Development Git Mercurial
|
||||
Python Subversion OpenSSH OpenSSL ;
|
||||
AddOptionalHaikuImagePackages Nano P7zip Welcome BeBook XZ-Utils ;
|
||||
AddOptionalHaikuImagePackages KeymapSwitcher Nano P7zip Welcome
|
||||
BeBook XZ-Utils ;
|
||||
AddOptionalHaikuImagePackages wpa_supplicant ;
|
||||
}
|
||||
|
||||
|
@ -89,12 +89,15 @@ mkdir -p $installDir $objDir $binutilsObjDir $gccObjDir $tmpIncludeDir \
|
||||
$tmpLibDir || exit 1
|
||||
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
|
||||
cd $binutilsObjDir
|
||||
CFLAGS="-O2" CXXFLAGS="-O2" $buildToolsDir/binutils/configure \
|
||||
--prefix=$installDir --target=i586-pc-haiku --disable-nls \
|
||||
--enable-shared=yes --disable-werror || exit 1
|
||||
make $additionalMakeArgs || exit 1
|
||||
make -j1 $additionalMakeArgs || exit 1
|
||||
make $additionalMakeArgs install || exit 1
|
||||
|
||||
PATH=$PATH:$installDir/bin
|
||||
@ -154,7 +157,7 @@ eval "sed $sedExpr Makefile.bak > Makefile" || exit 1
|
||||
rm Makefile.bak
|
||||
|
||||
# make gcc
|
||||
make cross || {
|
||||
make -j1 cross || {
|
||||
echo "ERROR: Building gcc failed." >&2
|
||||
exit 1
|
||||
}
|
||||
|
@ -110,6 +110,8 @@ mkdir -p $installDir $objDir $binutilsObjDir $gccObjDir $tmpIncludeDir \
|
||||
$tmpLibDir || exit 1
|
||||
mkdir -p $installDir/lib/gcc/$haikuMachine/$gccVersion
|
||||
|
||||
# force the POSIX locale, as the build (makeinfo) might choke otherwise
|
||||
export LC_ALL=POSIX
|
||||
|
||||
# build binutils
|
||||
cd $binutilsObjDir
|
||||
|
14
docs/develop/debugger/todo.txt
Normal file
14
docs/develop/debugger/todo.txt
Normal file
@ -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).
|
2
docs/develop/ports/arm/limitations.txt
Normal file
2
docs/develop/ports/arm/limitations.txt
Normal file
@ -0,0 +1,2 @@
|
||||
* Does not support < ARMv5
|
||||
* Requires support for high vectors
|
19
docs/develop/ports/arm/todo.txt
Normal file
19
docs/develop/ports/arm/todo.txt
Normal file
@ -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 */
|
||||
struct iframe {
|
||||
uint32 spsr;
|
||||
uint32 r0;
|
||||
uint32 r1;
|
||||
uint32 r2;
|
||||
@ -25,10 +26,11 @@ struct iframe {
|
||||
uint32 r10;
|
||||
uint32 r11;
|
||||
uint32 r12;
|
||||
uint32 r13;
|
||||
uint32 lr;
|
||||
uint32 usr_sp;
|
||||
uint32 usr_lr;
|
||||
uint32 svc_sp;
|
||||
uint32 svc_lr;
|
||||
uint32 pc;
|
||||
uint32 cpsr;
|
||||
} _PACKED;
|
||||
|
||||
typedef struct arch_cpu_info {
|
||||
@ -40,6 +42,20 @@ extern int arch_mmu_type;
|
||||
extern int arch_platform;
|
||||
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 /* _KERNEL_ARCH_ARM_CPU_H */
|
||||
|
@ -82,7 +82,7 @@ InitializeNTFSEditor::PartitionNameChanged(const char* name)
|
||||
void
|
||||
InitializeNTFSEditor::_CreateViewControls()
|
||||
{
|
||||
fNameTC = new BTextControl("Name:", "Haiku", NULL);
|
||||
fNameTC = new BTextControl("Name:", "New NTFS Volume", NULL);
|
||||
fNameTC->SetModificationMessage(new BMessage(MSG_NAME_CHANGED));
|
||||
// TODO find out what is the max length for this specific FS partition name
|
||||
fNameTC->TextView()->SetMaxBytes(31);
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
using std::nothrow;
|
||||
|
||||
#define kPartitionTypeNTFS "NTFS File System"
|
||||
#define kPartitionTypeNTFS "NT File System"
|
||||
|
||||
static const uint32 kDiskSystemFlags =
|
||||
0
|
||||
|
@ -47,14 +47,26 @@ HAIKU_CHECK_DISABLE_INTERRUPTS(device_t dev)
|
||||
if (status == 0 || status == 0xffffffff ||
|
||||
(sc->msk_pflags & MSK_FLAG_SUSPEND) != 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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sc->haiku_interrupt_status = status;
|
||||
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);
|
||||
|
@ -3610,6 +3610,7 @@ msk_intr(void *xsc)
|
||||
sc = xsc;
|
||||
MSK_LOCK(sc);
|
||||
|
||||
#ifndef __HAIKU__
|
||||
/* Reading B0_Y2_SP_ISRC2 masks further interrupts. */
|
||||
status = CSR_READ_4(sc, B0_Y2_SP_ISRC2);
|
||||
if (status == 0 || status == 0xffffffff ||
|
||||
@ -3619,6 +3620,9 @@ msk_intr(void *xsc)
|
||||
MSK_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
status = sc->haiku_interrupt_status;
|
||||
#endif
|
||||
|
||||
sc_if0 = sc->msk_if[MSK_PORT_A];
|
||||
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)
|
||||
CSR_WRITE_4(sc, STAT_CTRL, SC_STAT_CLR_IRQ);
|
||||
|
||||
#ifndef __HAIKU__
|
||||
/* Reenable interrupts. */
|
||||
CSR_WRITE_4(sc, B0_Y2_SP_ICR, 2);
|
||||
#endif
|
||||
|
||||
if (ifp0 != NULL && (ifp0->if_drv_flags & IFF_DRV_RUNNING) != 0 &&
|
||||
!IFQ_DRV_IS_EMPTY(&ifp0->if_snd))
|
||||
|
@ -2520,6 +2520,9 @@ struct msk_softc {
|
||||
int msk_process_limit;
|
||||
int msk_stat_cons;
|
||||
struct mtx msk_mtx;
|
||||
#ifdef __HAIKU__
|
||||
uint32_t haiku_interrupt_status;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define MSK_LOCK(_sc) mtx_lock(&(_sc)->msk_mtx)
|
||||
|
@ -368,12 +368,6 @@ AX88772Device::_SetupAX88772()
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -449,12 +443,6 @@ AX88772Device::_SetupAX88772A()
|
||||
if (result != B_OK)
|
||||
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[1] = 0x16;
|
||||
fIPG[2] = 0x1A;
|
||||
@ -481,12 +469,6 @@ AX88772Device::_SetupAX88772B()
|
||||
if (result != B_OK)
|
||||
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[1] = 0x16;
|
||||
fIPG[2] = 0x1A;
|
||||
@ -513,6 +495,9 @@ AX88772Device::StartDevice()
|
||||
"%d bytes of %d written.\n", actualLength, sizeof(fIPG));
|
||||
|
||||
}
|
||||
|
||||
uint16 rxcontrol = 0;
|
||||
|
||||
// AX88772B uses different maximum frame burst configuration.
|
||||
if (fDeviceInfo.fType == DeviceInfo::AX88772B) {
|
||||
result = gUSBModule->send_request(fDevice,
|
||||
@ -526,9 +511,11 @@ AX88772Device::StartDevice()
|
||||
TRACE_ALWAYS("Error of writing frame burst:%#010x\n", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
rxcontrol = RXCTL_USB_MFB;
|
||||
}
|
||||
|
||||
uint16 rxcontrol = RXCTL_START | RXCTL_BROADCAST;
|
||||
rxcontrol |= RXCTL_START | RXCTL_BROADCAST;
|
||||
result = WriteRXControlRegister(rxcontrol);
|
||||
if (result != B_OK) {
|
||||
TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n",
|
||||
|
@ -169,7 +169,7 @@ static file_system_module_info sNTFSFileSystem = {
|
||||
},
|
||||
|
||||
"ntfs", // short_name
|
||||
"NTFS File System", // pretty_name
|
||||
"NT File System", // pretty_name
|
||||
B_DISK_SYSTEM_SUPPORTS_INITIALIZING
|
||||
| B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME
|
||||
| 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,
|
||||
false },
|
||||
{ 0x86, "NTFS volume set", false },
|
||||
{ 0x87, "NTFS volume set", false },
|
||||
{ 0x87, "NTFS volume set", true },
|
||||
{ 0x88, "Linux plaintext", false },
|
||||
{ 0x8e, "Linux LVM", false },
|
||||
{ 0x93, "Amoeba", false },
|
||||
|
@ -9,11 +9,14 @@ UsePrivateSystemHeaders ;
|
||||
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) arch ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) arch x86 ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) controllers ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_info ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_managers ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) elf ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) files ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) ids ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) jobs ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) model ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) settings ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) settings generic ] ;
|
||||
@ -55,14 +58,7 @@ SourceHdrs
|
||||
;
|
||||
|
||||
Application Debugger :
|
||||
BreakpointManager.cpp
|
||||
Debugger.cpp
|
||||
Jobs.cpp
|
||||
TeamMemoryBlockManager.cpp
|
||||
TeamDebugger.cpp
|
||||
ThreadHandler.cpp
|
||||
WatchpointManager.cpp
|
||||
Worker.cpp
|
||||
|
||||
# arch
|
||||
Architecture.cpp
|
||||
@ -75,6 +71,15 @@ Application Debugger :
|
||||
ArchitectureX86.cpp
|
||||
CpuStateX86.cpp
|
||||
|
||||
# controllers
|
||||
TeamDebugger.cpp
|
||||
ThreadHandler.cpp
|
||||
|
||||
# debug_managers
|
||||
BreakpointManager.cpp
|
||||
TeamMemoryBlockManager.cpp
|
||||
WatchpointManager.cpp
|
||||
|
||||
# debug_info
|
||||
BasicFunctionDebugInfo.cpp
|
||||
DebuggerImageDebugInfo.cpp
|
||||
@ -117,6 +122,15 @@ Application Debugger :
|
||||
ObjectID.cpp
|
||||
FunctionParameterID.cpp
|
||||
|
||||
# jobs
|
||||
GetCPUStateJob.cpp
|
||||
GetStackTraceJob.cpp
|
||||
GetThreadStateJob.cpp
|
||||
LoadImageDebugInfoJob.cpp
|
||||
LoadSourceCodeJob.cpp
|
||||
ResolveValueNodeJob.cpp
|
||||
RetrieveMemoryBlockJob.cpp
|
||||
|
||||
# model
|
||||
Breakpoint.cpp
|
||||
DisassembledCode.cpp
|
||||
@ -150,7 +164,6 @@ Application Debugger :
|
||||
TeamSettings.cpp
|
||||
TeamUiSettings.cpp
|
||||
TeamUiSettingsFactory.cpp
|
||||
WatchpointSetting.cpp
|
||||
|
||||
# settings/generic
|
||||
Setting.cpp
|
||||
@ -211,6 +224,7 @@ Application Debugger :
|
||||
TeamWindow.cpp
|
||||
ThreadListView.cpp
|
||||
VariablesView.cpp
|
||||
WatchPromptWindow.cpp
|
||||
|
||||
# user_interface/gui/util
|
||||
ActionMenuItem.cpp
|
||||
@ -236,6 +250,7 @@ Application Debugger :
|
||||
BitBuffer.cpp
|
||||
IntegerFormatter.cpp
|
||||
StringUtils.cpp
|
||||
Worker.cpp
|
||||
|
||||
# value
|
||||
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_FUNCTION_SOURCE_CODE_CHANGED = 'fnsc',
|
||||
MSG_USER_BREAKPOINT_CHANGED = 'ubrc',
|
||||
MSG_WATCHPOINT_CHANGED = 'wapc',
|
||||
MSG_DEBUGGER_EVENT = 'dbge',
|
||||
MSG_LOAD_SETTINGS = 'ldst',
|
||||
|
||||
@ -53,7 +54,8 @@ enum {
|
||||
MSG_INSPECTOR_WINDOW_CLOSED = 'irwc',
|
||||
MSG_INSPECT_ADDRESS = 'isad',
|
||||
MSG_SHOW_TYPECAST_NODE_PROMPT = 'stnp',
|
||||
MSG_TYPECAST_NODE = 'tyno'
|
||||
MSG_TYPECAST_NODE = 'tyno',
|
||||
MSG_SHOW_WATCH_VARIABLE_PROMPT = 'swvp'
|
||||
};
|
||||
|
||||
|
||||
|
@ -46,7 +46,7 @@
|
||||
#include "ValueNodeContainer.h"
|
||||
#include "Variable.h"
|
||||
#include "WatchpointManager.h"
|
||||
#include "WatchpointSetting.h"
|
||||
|
||||
|
||||
// #pragma mark - ImageHandler
|
||||
|
||||
@ -1583,21 +1583,6 @@ TeamDebugger::_LoadSettings()
|
||||
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(
|
||||
fUserInterface->ID());
|
||||
if (uiSettings != NULL)
|
@ -74,6 +74,12 @@ WatchpointManager::InstallWatchpoint(Watchpoint* watchpoint,
|
||||
watchpoint->SetInstalled(false);
|
||||
}
|
||||
|
||||
if (error == B_OK) {
|
||||
if (fTeam->WatchpointAtAddress(watchpoint->Address()) == NULL)
|
||||
fTeam->AddWatchpoint(watchpoint);
|
||||
fTeam->NotifyWatchpointChanged(watchpoint);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -84,12 +90,16 @@ WatchpointManager::UninstallWatchpoint(Watchpoint* watchpoint)
|
||||
AutoLocker<BLocker> installLocker(fLock);
|
||||
AutoLocker<Team> teamLocker(fTeam);
|
||||
|
||||
fTeam->RemoveWatchpoint(watchpoint);
|
||||
|
||||
if (!watchpoint->IsInstalled())
|
||||
return;
|
||||
|
||||
status_t error = fDebuggerInterface->UninstallWatchpoint(
|
||||
watchpoint->Address());
|
||||
|
||||
if (error == B_OK)
|
||||
if (error == B_OK) {
|
||||
watchpoint->SetInstalled(false);
|
||||
}
|
||||
fTeam->NotifyWatchpointChanged(watchpoint);
|
||||
}
|
||||
}
|
56
src/apps/debugger/jobs/GetCPUStateJob.cpp
Normal file
56
src/apps/debugger/jobs/GetCPUStateJob.cpp
Normal file
@ -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;
|
||||
}
|
116
src/apps/debugger/jobs/GetStackTraceJob.cpp
Normal file
116
src/apps/debugger/jobs/GetStackTraceJob.cpp
Normal file
@ -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;
|
||||
}
|
62
src/apps/debugger/jobs/GetThreadStateJob.cpp
Normal file
62
src/apps/debugger/jobs/GetThreadStateJob.cpp
Normal file
@ -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;
|
||||
}
|
106
src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp
Normal file
106
src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp
Normal file
@ -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;
|
||||
}
|
93
src/apps/debugger/jobs/LoadSourceCodeJob.cpp
Normal file
93
src/apps/debugger/jobs/LoadSourceCodeJob.cpp
Normal file
@ -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;
|
||||
}
|
254
src/apps/debugger/jobs/ResolveValueNodeJob.cpp
Normal file
254
src/apps/debugger/jobs/ResolveValueNodeJob.cpp
Normal file
@ -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;
|
||||
}
|
62
src/apps/debugger/jobs/RetrieveMemoryBlockJob.cpp
Normal file
62
src/apps/debugger/jobs/RetrieveMemoryBlockJob.cpp
Normal file
@ -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++)
|
||||
breakpoint->ReleaseReference();
|
||||
|
||||
for (int32 i = 0; Watchpoint* watchpoint = fWatchpoints.ItemAt(i); i++)
|
||||
watchpoint->ReleaseReference();
|
||||
|
||||
while (Image* image = fImages.RemoveHead())
|
||||
image->ReleaseReference();
|
||||
|
||||
|
@ -145,6 +145,8 @@ public:
|
||||
TargetAddressRange range,
|
||||
BObjectList<Watchpoint>& watchpoints)
|
||||
const;
|
||||
const WatchpointList& Watchpoints() const
|
||||
{ return fWatchpoints; }
|
||||
|
||||
status_t GetStatementAtAddress(target_addr_t address,
|
||||
FunctionInstance*& _function,
|
||||
@ -187,7 +189,6 @@ private:
|
||||
|
||||
typedef BObjectList<Breakpoint> BreakpointList;
|
||||
typedef DoublyLinkedList<Listener> ListenerList;
|
||||
typedef BObjectList<Watchpoint> WatchpointList;
|
||||
|
||||
private:
|
||||
void _NotifyThreadAdded(Thread* thread);
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define WATCHPOINT_H
|
||||
|
||||
|
||||
#include <ObjectList.h>
|
||||
#include <Referenceable.h>
|
||||
|
||||
#include "types/Types.h"
|
||||
@ -49,4 +50,7 @@ private:
|
||||
};
|
||||
|
||||
|
||||
typedef BObjectList<Watchpoint> WatchpointList;
|
||||
|
||||
|
||||
#endif // WATCHPOINT_H
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "TeamUiSettings.h"
|
||||
#include "TeamUiSettingsFactory.h"
|
||||
#include "UserBreakpoint.h"
|
||||
#include "WatchpointSetting.h"
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
TeamSettings::CountUiSettings() const
|
||||
{
|
||||
|
@ -15,7 +15,6 @@ class BMessage;
|
||||
class Team;
|
||||
class BreakpointSetting;
|
||||
class TeamUiSettings;
|
||||
class WatchpointSetting;
|
||||
|
||||
|
||||
class TeamSettings {
|
||||
@ -34,9 +33,6 @@ public:
|
||||
int32 CountBreakpoints() const;
|
||||
const BreakpointSetting* BreakpointAt(int32 index) const;
|
||||
|
||||
int32 CountWatchpoints() const;
|
||||
const WatchpointSetting* WatchpointAt(int32 index) const;
|
||||
|
||||
int32 CountUiSettings() const;
|
||||
const TeamUiSettings* UiSettingAt(int32 index) const;
|
||||
const TeamUiSettings* UiSettingFor(const char* id) const;
|
||||
@ -48,14 +44,12 @@ public:
|
||||
private:
|
||||
typedef BObjectList<BreakpointSetting> BreakpointList;
|
||||
typedef BObjectList<TeamUiSettings> UiSettingsList;
|
||||
typedef BObjectList<WatchpointSetting> WatchpointList;
|
||||
|
||||
private:
|
||||
void _Unset();
|
||||
|
||||
private:
|
||||
BreakpointList fBreakpoints;
|
||||
WatchpointList fWatchpoints;
|
||||
UiSettingsList fUiSettings;
|
||||
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 "LocatableFile.h"
|
||||
#include "table/TableColumns.h"
|
||||
#include "TargetAddressTableColumn.h"
|
||||
#include "Team.h"
|
||||
#include "UserBreakpoint.h"
|
||||
#include "TargetAddressTableColumn.h"
|
||||
#include "Watchpoint.h"
|
||||
|
||||
|
||||
// #pragma mark - BreakpointsTableModel
|
||||
@ -32,16 +33,18 @@ public:
|
||||
:
|
||||
fTeam(team)
|
||||
{
|
||||
Update(NULL);
|
||||
UpdateBreakpoint(NULL);
|
||||
UpdateWatchpoint(NULL);
|
||||
}
|
||||
|
||||
~BreakpointsTableModel()
|
||||
{
|
||||
fTeam = NULL;
|
||||
Update(NULL);
|
||||
UpdateBreakpoint(NULL);
|
||||
UpdateWatchpoint(NULL);
|
||||
}
|
||||
|
||||
bool Update(UserBreakpoint* changedBreakpoint)
|
||||
bool UpdateBreakpoint(UserBreakpoint* changedBreakpoint)
|
||||
{
|
||||
if (fTeam == NULL) {
|
||||
for (int32 i = 0;
|
||||
@ -93,6 +96,59 @@ public:
|
||||
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
|
||||
{
|
||||
return 5;
|
||||
@ -100,10 +156,33 @@ public:
|
||||
|
||||
virtual int32 CountRows() const
|
||||
{
|
||||
return fBreakpoints.CountItems();
|
||||
return fBreakpoints.CountItems() + fWatchpoints.CountItems();
|
||||
}
|
||||
|
||||
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);
|
||||
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:
|
||||
Team* fTeam;
|
||||
BObjectList<UserBreakpoint> fBreakpoints;
|
||||
BObjectList<Watchpoint> fWatchpoints;
|
||||
};
|
||||
|
||||
|
||||
@ -202,7 +303,8 @@ BreakpointListView::UnsetListener()
|
||||
|
||||
|
||||
void
|
||||
BreakpointListView::SetBreakpoint(UserBreakpoint* breakpoint)
|
||||
BreakpointListView::SetBreakpoint(UserBreakpoint* breakpoint,
|
||||
Watchpoint* watchpoint)
|
||||
{
|
||||
if (breakpoint == fBreakpoint)
|
||||
return;
|
||||
@ -232,7 +334,14 @@ BreakpointListView::SetBreakpoint(UserBreakpoint* breakpoint)
|
||||
void
|
||||
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();
|
||||
UserBreakpoint* breakpoint = fBreakpointsTableModel->BreakpointAt(
|
||||
selectionModel->RowAt(0));
|
||||
|
||||
fListener->BreakpointSelectionChanged(breakpoint);
|
||||
if (breakpoint != NULL)
|
||||
fListener->BreakpointSelectionChanged(breakpoint);
|
||||
else {
|
||||
Watchpoint* watchpoint = fBreakpointsTableModel->WatchpointAt(
|
||||
selectionModel->RowAt(0));
|
||||
fListener->WatchpointSelectionChanged(watchpoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
class Team;
|
||||
class UserBreakpoint;
|
||||
class Watchpoint;
|
||||
|
||||
|
||||
class BreakpointListView : public BGroupView, private TableListener {
|
||||
@ -29,9 +30,13 @@ public:
|
||||
|
||||
void UnsetListener();
|
||||
|
||||
void SetBreakpoint(UserBreakpoint* breakpoint);
|
||||
void SetBreakpoint(UserBreakpoint* breakpoint,
|
||||
Watchpoint* watchpoint);
|
||||
|
||||
void UserBreakpointChanged(
|
||||
UserBreakpoint* breakpoint);
|
||||
void WatchpointChanged(
|
||||
Watchpoint* breakpoint);
|
||||
|
||||
void LoadSettings(const BMessage& settings);
|
||||
status_t SaveSettings(BMessage& settings);
|
||||
@ -48,6 +53,7 @@ private:
|
||||
private:
|
||||
Team* fTeam;
|
||||
UserBreakpoint* fBreakpoint;
|
||||
Watchpoint* fWatchpoint;
|
||||
Table* fBreakpointsTable;
|
||||
BreakpointsTableModel* fBreakpointsTableModel;
|
||||
Listener* fListener;
|
||||
@ -60,6 +66,9 @@ public:
|
||||
|
||||
virtual void BreakpointSelectionChanged(
|
||||
UserBreakpoint* breakpoint) = 0;
|
||||
|
||||
virtual void WatchpointSelectionChanged(
|
||||
Watchpoint* watchpoint) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
@ -68,20 +68,26 @@ BreakpointsView::UnsetListener()
|
||||
|
||||
|
||||
void
|
||||
BreakpointsView::SetBreakpoint(UserBreakpoint* breakpoint)
|
||||
BreakpointsView::SetBreakpoint(UserBreakpoint* breakpoint, Watchpoint* watchpoint)
|
||||
{
|
||||
if (breakpoint == fBreakpoint)
|
||||
if (breakpoint == fBreakpoint && watchpoint == fWatchpoint)
|
||||
return;
|
||||
|
||||
if (fWatchpoint != NULL)
|
||||
fWatchpoint->ReleaseReference();
|
||||
|
||||
if (fBreakpoint != NULL)
|
||||
fBreakpoint->ReleaseReference();
|
||||
|
||||
fWatchpoint = watchpoint;
|
||||
fBreakpoint = breakpoint;
|
||||
|
||||
if (fBreakpoint != NULL)
|
||||
fBreakpoint->AcquireReference();
|
||||
else if (fWatchpoint != NULL)
|
||||
fWatchpoint->AcquireReference();
|
||||
|
||||
fListView->SetBreakpoint(breakpoint);
|
||||
fListView->SetBreakpoint(breakpoint, watchpoint);
|
||||
|
||||
_UpdateButtons();
|
||||
}
|
||||
@ -96,21 +102,49 @@ BreakpointsView::UserBreakpointChanged(UserBreakpoint* breakpoint)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BreakpointsView::WatchpointChanged(Watchpoint* watchpoint)
|
||||
{
|
||||
fListView->WatchpointChanged(watchpoint);
|
||||
|
||||
_UpdateButtons();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BreakpointsView::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case MSG_ENABLE_BREAKPOINT:
|
||||
if (fListener != NULL && fBreakpoint != NULL)
|
||||
fListener->SetBreakpointEnabledRequested(fBreakpoint, true);
|
||||
if (fListener != NULL) {
|
||||
if (fBreakpoint != NULL) {
|
||||
fListener->SetBreakpointEnabledRequested(fBreakpoint,
|
||||
true);
|
||||
} else if (fWatchpoint != NULL) {
|
||||
fListener->SetWatchpointEnabledRequested(fWatchpoint,
|
||||
true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MSG_DISABLE_BREAKPOINT:
|
||||
if (fListener != NULL && fBreakpoint != NULL)
|
||||
fListener->SetBreakpointEnabledRequested(fBreakpoint, false);
|
||||
if (fListener != NULL) {
|
||||
if (fBreakpoint != NULL) {
|
||||
fListener->SetBreakpointEnabledRequested(fBreakpoint,
|
||||
false);
|
||||
} else if (fWatchpoint != NULL) {
|
||||
fListener->SetWatchpointEnabledRequested(fWatchpoint,
|
||||
false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MSG_CLEAR_BREAKPOINT:
|
||||
if (fListener != NULL && fBreakpoint != NULL)
|
||||
fListener->ClearBreakpointRequested(fBreakpoint);
|
||||
if (fListener != NULL) {
|
||||
if (fBreakpoint != NULL) {
|
||||
fListener->ClearBreakpointRequested(fBreakpoint);
|
||||
} else if (fWatchpoint != NULL) {
|
||||
fListener->ClearWatchpointRequested(fWatchpoint);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BGroupView::MessageReceived(message);
|
||||
@ -159,6 +193,14 @@ BreakpointsView::BreakpointSelectionChanged(UserBreakpoint* breakpoint)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BreakpointsView::WatchpointSelectionChanged(Watchpoint* watchpoint)
|
||||
{
|
||||
if (fListener != NULL)
|
||||
fListener->WatchpointSelectionChanged(watchpoint);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BreakpointsView::_Init()
|
||||
{
|
||||
@ -182,8 +224,19 @@ BreakpointsView::_UpdateButtons()
|
||||
{
|
||||
AutoLocker<Team> teamLocker(fTeam);
|
||||
|
||||
bool enabled = false;
|
||||
bool valid = false;
|
||||
|
||||
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->SetMessage(
|
||||
new BMessage(MSG_DISABLE_BREAKPOINT));
|
||||
|
@ -28,9 +28,13 @@ public:
|
||||
|
||||
void UnsetListener();
|
||||
|
||||
void SetBreakpoint(UserBreakpoint* breakpoint);
|
||||
void SetBreakpoint(UserBreakpoint* breakpoint,
|
||||
Watchpoint* watchpoint);
|
||||
|
||||
void UserBreakpointChanged(
|
||||
UserBreakpoint* breakpoint);
|
||||
void WatchpointChanged(
|
||||
Watchpoint* watchpoint);
|
||||
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
virtual void AttachedToWindow();
|
||||
@ -42,6 +46,8 @@ private:
|
||||
// BreakpointListView::Listener
|
||||
virtual void BreakpointSelectionChanged(
|
||||
UserBreakpoint* breakpoint);
|
||||
virtual void WatchpointSelectionChanged(
|
||||
Watchpoint* watchpoint);
|
||||
|
||||
void _Init();
|
||||
|
||||
@ -50,6 +56,7 @@ private:
|
||||
private:
|
||||
Team* fTeam;
|
||||
UserBreakpoint* fBreakpoint;
|
||||
Watchpoint* fWatchpoint;
|
||||
BreakpointListView* fListView;
|
||||
BButton* fToggleBreakpointButton;
|
||||
BButton* fRemoveBreakpointButton;
|
||||
@ -57,6 +64,7 @@ private:
|
||||
};
|
||||
|
||||
|
||||
|
||||
class BreakpointsView::Listener {
|
||||
public:
|
||||
virtual ~Listener();
|
||||
@ -68,6 +76,14 @@ public:
|
||||
bool enabled) = 0;
|
||||
virtual void ClearBreakpointRequested(
|
||||
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 "UserInterface.h"
|
||||
#include "Variable.h"
|
||||
#include "WatchPromptWindow.h"
|
||||
|
||||
|
||||
enum {
|
||||
@ -247,6 +248,27 @@ TeamWindow::MessageReceived(BMessage* message)
|
||||
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:
|
||||
{
|
||||
entry_ref locatedPath;
|
||||
@ -334,6 +356,18 @@ TeamWindow::MessageReceived(BMessage* message)
|
||||
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:
|
||||
{
|
||||
_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
|
||||
TeamWindow::ValueNodeValueRequested(CpuState* cpuState,
|
||||
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
|
||||
TeamWindow::FunctionSourceCodeChanged(Function* function)
|
||||
{
|
||||
@ -901,7 +969,7 @@ TeamWindow::_SetActiveBreakpoint(UserBreakpoint* breakpoint)
|
||||
_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
|
||||
TeamWindow::_HandleResolveMissingSourceFile(entry_ref& locatedPath)
|
||||
{
|
||||
|
@ -95,6 +95,15 @@ private:
|
||||
virtual void ClearBreakpointRequested(
|
||||
UserBreakpoint* breakpoint);
|
||||
|
||||
virtual void WatchpointSelectionChanged(
|
||||
Watchpoint* Watchpoint);
|
||||
virtual void SetWatchpointEnabledRequested(
|
||||
Watchpoint* breakpoint,
|
||||
bool enabled);
|
||||
virtual void ClearWatchpointRequested(
|
||||
Watchpoint* watchpoint);
|
||||
|
||||
|
||||
// SourceView::Listener
|
||||
virtual void SetBreakpointRequested(target_addr_t address,
|
||||
bool enabled);
|
||||
@ -116,6 +125,8 @@ private:
|
||||
const Team::ImageEvent& event);
|
||||
virtual void UserBreakpointChanged(
|
||||
const Team::UserBreakpointEvent& event);
|
||||
virtual void WatchpointChanged(
|
||||
const Team::WatchpointEvent& event);
|
||||
|
||||
// Function::Listener
|
||||
virtual void FunctionSourceCodeChanged(Function* function);
|
||||
@ -142,6 +153,8 @@ private:
|
||||
void _HandleSourceCodeChanged();
|
||||
void _HandleUserBreakpointChanged(
|
||||
UserBreakpoint* breakpoint);
|
||||
void _HandleWatchpointChanged(
|
||||
Watchpoint* watchpoint);
|
||||
void _HandleResolveMissingSourceFile(entry_ref&
|
||||
locatedPath);
|
||||
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <debugger.h>
|
||||
|
||||
#include <Looper.h>
|
||||
#include <PopUpMenu.h>
|
||||
#include <ToolTip.h>
|
||||
@ -1684,6 +1686,22 @@ VariablesView::MessageReceived(BMessage* message)
|
||||
node->NodeChild()->SetNode(valueNode);
|
||||
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:
|
||||
{
|
||||
ValueNodeChild* nodeChild;
|
||||
@ -1977,34 +1995,45 @@ VariablesView::_GetContextActionsForNode(ModelNode* node,
|
||||
if (location->PieceAt(0).type != VALUE_PIECE_LOCATION_MEMORY)
|
||||
return B_OK;
|
||||
|
||||
BMessage* message = new BMessage(MSG_SHOW_INSPECTOR_WINDOW);
|
||||
if (message == NULL)
|
||||
return B_NO_MEMORY;
|
||||
BMessage* message = NULL;
|
||||
status_t result = _AddContextAction("Inspect", MSG_SHOW_INSPECTOR_WINDOW,
|
||||
actions, message);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
ObjectDeleter<BMessage> messageDeleter(message);
|
||||
message->AddUInt64("address", location->PieceAt(0).address);
|
||||
|
||||
ActionMenuItem* item = new(std::nothrow) ActionMenuItem("Inspect",
|
||||
message);
|
||||
result = _AddContextAction("Cast as" B_UTF8_ELLIPSIS,
|
||||
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)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
messageDeleter.Detach();
|
||||
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))
|
||||
return B_NO_MEMORY;
|
||||
|
||||
|
@ -72,6 +72,9 @@ private:
|
||||
void _RequestNodeValue(ModelNode* node);
|
||||
status_t _GetContextActionsForNode(ModelNode* node,
|
||||
ContextActionList* actions);
|
||||
status_t _AddContextAction(const char* action,
|
||||
uint32 what, ContextActionList* actions,
|
||||
BMessage*& _message);
|
||||
void _FinishContextMenu(bool force);
|
||||
void _SaveViewState() const;
|
||||
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?
|
||||
if (diskSystemName == "Be File System"
|
||||
|| diskSystemName == "NTFS File System") {
|
||||
|| diskSystemName == "NT File System") {
|
||||
InitParamsPanel* panel = new InitParamsPanel(this, diskSystemName,
|
||||
partition);
|
||||
if (panel->Go(name, parameters) == GO_CANCELED)
|
||||
|
@ -727,7 +727,7 @@ ShowImageWindow::MessageReceived(BMessage* message)
|
||||
strCaption << i;
|
||||
|
||||
BMenuItem* item = new BMenuItem(strCaption.String(), goTo,
|
||||
B_SHIFT_KEY, shortcut);
|
||||
shortcut, B_SHIFT_KEY);
|
||||
if (currentPage == i)
|
||||
item->SetMarked(true);
|
||||
fGoToPageMenu->AddItem(item);
|
||||
|
@ -83,7 +83,7 @@ AppearancePrefView::AppearancePrefView(const char* name,
|
||||
};
|
||||
|
||||
fBlinkCursor = new BCheckBox(
|
||||
B_TRANSLATE("Blink the cursor"),
|
||||
B_TRANSLATE("Blinking cursor"),
|
||||
new BMessage(MSG_BLINK_CURSOR_CHANGED));
|
||||
|
||||
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_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_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_offsets.h"
|
||||
|
||||
.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) */
|
||||
FUNCTION(arch_int_enable_interrupts):
|
||||
mrs r0, cpsr
|
||||
bic r0, r0, #(1<<7) /* clear the I bit */
|
||||
bic r0, r0, #(1<<7)
|
||||
msr cpsr_c, r0
|
||||
bx lr
|
||||
FUNCTION_END(arch_int_enable_interrupts)
|
||||
|
||||
|
||||
/* int arch_int_disable_interrupts(void)
|
||||
*/
|
||||
/* int arch_int_disable_interrupts(void) */
|
||||
FUNCTION(arch_int_disable_interrupts):
|
||||
mrs r0, cpsr
|
||||
orr r1, r0, #(1<<7)
|
||||
@ -33,8 +50,7 @@ FUNCTION(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):
|
||||
mrs r1, cpsr
|
||||
and r0, r0, #(1<<7)
|
||||
@ -65,3 +81,57 @@ FUNCTION(arm_context_switch):
|
||||
ldmfd sp!, { r0-r12, lr }
|
||||
bx lr
|
||||
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 *
|
||||
arch_debug_get_caller(void)
|
||||
{
|
||||
#warning ARM:IMPLEMENT
|
||||
// TODO: implement me
|
||||
//return __builtin_frame_address(1);
|
||||
// struct stack_frame *frame;
|
||||
//frame = __builtin_frame_address(0);
|
||||
// frame = get_current_stack_frame();
|
||||
// return (void *)frame->previous->return_address;
|
||||
return NULL;
|
||||
/* Return the thread id as the kernel (for example the lock code) actually
|
||||
gets a somewhat valid indication of the caller back. */
|
||||
return (void*) thread_get_current_thread_id();
|
||||
}
|
||||
|
||||
|
||||
@ -316,17 +311,7 @@ arch_debug_init(kernel_args *args)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
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);
|
||||
}
|
||||
|
||||
/* arch_debug_call_with_fault_handler is in arch_asm.S */
|
||||
|
||||
void
|
||||
arch_debug_unset_current_thread(void)
|
||||
|
@ -9,6 +9,49 @@
|
||||
|
||||
#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
|
||||
|
||||
.globl _vectors_start
|
||||
@ -43,134 +86,139 @@ _vectors_end:
|
||||
|
||||
|
||||
.rept 64
|
||||
.word 0xaabbccdd
|
||||
.word 0xdeadbeef
|
||||
.endr
|
||||
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):
|
||||
stmfd sp!, { r0-r12, r14 }
|
||||
sub sp, sp, #12
|
||||
mov r0, sp
|
||||
mrs r1, spsr
|
||||
stmia r0, { r1, r13-r14 }
|
||||
b arch_arm_undefined
|
||||
b .
|
||||
PUSHFRAMEINSVC
|
||||
|
||||
mov r0, sp
|
||||
bl arch_arm_undefined
|
||||
|
||||
PULLFRAMEFROMSVCANDEXIT
|
||||
FUNCTION_END(arm_undefined)
|
||||
|
||||
|
||||
FUNCTION(arm_syscall):
|
||||
stmfd sp!, { r0-r12, r14 }
|
||||
sub sp, sp, #12
|
||||
mov r0, sp
|
||||
mrs r1, spsr
|
||||
stmia r0, { r1, r13-r14 }
|
||||
b arch_arm_syscall
|
||||
b .
|
||||
|
||||
PUSHFRAMEINSVC
|
||||
|
||||
mov r0, sp
|
||||
bl arch_arm_syscall
|
||||
|
||||
PULLFRAMEFROMSVCANDEXIT
|
||||
FUNCTION_END(arm_syscall)
|
||||
|
||||
|
||||
FUNCTION(arm_prefetch_abort):
|
||||
ldr sp, abort_stack
|
||||
stmfd sp!, { r0-r12, r14 }
|
||||
sub sp, sp, #12
|
||||
mov r0, sp
|
||||
mrs r1, spsr
|
||||
stmia r0, { r1, r13-r14 }
|
||||
b arch_arm_prefetch_abort
|
||||
b .
|
||||
#ifdef __XSCALE__
|
||||
nop /* Make absolutely sure any pending */
|
||||
nop /* imprecise aborts have occurred. */
|
||||
#endif
|
||||
add lr, lr, #4
|
||||
PUSHFRAMEINSVC
|
||||
|
||||
mov r0, sp
|
||||
bl arch_arm_prefetch_abort
|
||||
|
||||
PULLFRAMEFROMSVCANDEXIT
|
||||
FUNCTION_END(arm_prefetch_abort)
|
||||
|
||||
|
||||
FUNCTION(arm_data_abort):
|
||||
ldr sp, abort_stack
|
||||
/* XXX only deals with interrupting supervisor mode */
|
||||
#ifdef __XSCALE__
|
||||
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 */
|
||||
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 }
|
||||
mov r0, sp
|
||||
bl arch_arm_data_abort
|
||||
add sp, sp, #20
|
||||
|
||||
/* restore spsr */
|
||||
ldmfd sp!, { r0 }
|
||||
msr spsr_cxsf, r0
|
||||
PULLFRAMEFROMSVCANDEXIT
|
||||
|
||||
/* restore back to where we came from */
|
||||
ldmfd sp!, { r0-r3, r12, lr, pc }^
|
||||
|
||||
FUNCTION(arm_reserved):
|
||||
b .
|
||||
|
||||
FUNCTION_END(arm_reserved)
|
||||
|
||||
FUNCTION(arm_irq):
|
||||
ldr sp, abort_stack
|
||||
/* XXX only deals with interrupting supervisor mode */
|
||||
sub lr, lr, #4
|
||||
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 */
|
||||
bl arch_arm_irq
|
||||
|
||||
/* restore spsr */
|
||||
ldmfd sp!, { r0 }
|
||||
msr spsr_cxsf, r0
|
||||
PULLFRAMEFROMSVCANDEXIT
|
||||
FUNCTION_END(arm_irq)
|
||||
|
||||
/* 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):
|
||||
ldr sp, abort_stack
|
||||
sub lr, lr, #4
|
||||
stmfd sp!, { r0-r3, r12, lr }
|
||||
PUSHFRAMEINSVC
|
||||
|
||||
mov r0, sp /* iframe */
|
||||
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>
|
||||
|
||||
|
||||
#define TRACE_ARCH_INT
|
||||
//#define TRACE_ARCH_INT
|
||||
#ifdef TRACE_ARCH_INT
|
||||
# define TRACE(x) dprintf x
|
||||
#else
|
||||
@ -61,30 +61,11 @@ static void *sVectorPageAddress;
|
||||
static area_id sUserVectorPageArea;
|
||||
static void *sUserVectorPageAddress;
|
||||
|
||||
// current fault handler
|
||||
addr_t gFaultHandler;
|
||||
|
||||
// An iframe stack used in the early boot process when we don't have
|
||||
// threads yet.
|
||||
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
|
||||
arch_int_enable_io_interrupt(int irq)
|
||||
{
|
||||
@ -117,29 +98,32 @@ arch_int_disable_io_interrupt(int irq)
|
||||
|
||||
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
extern "C" void arm_vector_init(void);
|
||||
|
||||
|
||||
status_t
|
||||
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
|
||||
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,
|
||||
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
|
||||
arch_int_init_io(kernel_args* args)
|
||||
{
|
||||
TRACE(("arch_int_init_io(%p)\n", args));
|
||||
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)
|
||||
{
|
||||
panic("Undefined instruction!");
|
||||
print_iframe("Undefined Instruction", iframe);
|
||||
panic("not handled!");
|
||||
}
|
||||
|
||||
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;
|
||||
status_t res = vm_page_fault(iframe->r2 /* FAR */, iframe->r4 /* lr */,
|
||||
true /* TODO how to determine read/write? */,
|
||||
false /* only kernelspace for now */,
|
||||
&newip);
|
||||
Thread *thread = thread_get_current_thread();
|
||||
bool isUser = (frame->spsr & 0x1f) == 0x10;
|
||||
addr_t far = arm_get_far();
|
||||
bool isWrite = true;
|
||||
addr_t newip = 0;
|
||||
|
||||
if (res != B_HANDLED_INTERRUPT) {
|
||||
panic("Data Abort: %08x %08x %08x %08x (res=%lx)", iframe->r0 /* spsr */,
|
||||
iframe->r1 /* FSR */, iframe->r2 /* FAR */,
|
||||
iframe->r4 /* lr */,
|
||||
res);
|
||||
} else {
|
||||
//panic("vm_page_fault was ok (%08lx/%08lx)!", iframe->r2 /* FAR */, iframe->r0 /* spsr */);
|
||||
#ifdef TRACE_ARCH_INT
|
||||
print_iframe("Data Abort", frame);
|
||||
#endif
|
||||
|
||||
if (debug_debugger_running()) {
|
||||
// If this CPU or this thread has a fault handler, we're allowed to be
|
||||
// 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)
|
||||
{
|
||||
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)
|
||||
|
@ -6,52 +6,17 @@
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
//#include <arch_platform.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <arch/platform.h>
|
||||
#include <boot/kernel_args.h>
|
||||
//#include <platform/openfirmware/openfirmware.h>
|
||||
#include <real_time_clock.h>
|
||||
#include <util/kernel_cpp.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
|
||||
#include <kernel/debug.h>
|
||||
|
||||
status_t
|
||||
arch_platform_init(struct kernel_args *kernelArgs)
|
||||
{
|
||||
#warning ARM:WRITEME
|
||||
// NOTE: dprintf() is off-limits here, too early...
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -59,8 +24,7 @@ arch_platform_init(struct kernel_args *kernelArgs)
|
||||
status_t
|
||||
arch_platform_init_post_vm(struct kernel_args *kernelArgs)
|
||||
{
|
||||
#warning ARM:WRITEME
|
||||
//sM68KPlatform->InitPostVM(kernelArgs);
|
||||
// now we can use the heap and create areas
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -68,5 +32,6 @@ arch_platform_init_post_vm(struct kernel_args *kernelArgs)
|
||||
status_t
|
||||
arch_platform_init_post_thread(struct kernel_args *kernelArgs)
|
||||
{
|
||||
// now we can create and use semaphores
|
||||
return B_OK;
|
||||
}
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define TRACE_ARCH_THREAD
|
||||
//#define TRACE_ARCH_THREAD
|
||||
#ifdef TRACE_ARCH_THREAD
|
||||
# define TRACE(x) dprintf x
|
||||
#else
|
||||
|
@ -19,6 +19,15 @@
|
||||
#include <arch/timer.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_SIZE 0x000000C0
|
||||
#define PXA_TIMERS_INTERRUPT 7 /* OST_4_11 */
|
||||
@ -29,7 +38,6 @@
|
||||
#define PXA_OSMR4 0x20
|
||||
#define PXA_OMCR4 0x30
|
||||
|
||||
#define TRACE(x) //dprintf x
|
||||
|
||||
static area_id sPxaTimersArea;
|
||||
static uint32 *sPxaTimersBase;
|
||||
@ -48,7 +56,7 @@ pxa_timer_interrupt(void *data)
|
||||
void
|
||||
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) {
|
||||
sPxaTimersBase[PXA_OIER] |= (1 << 4);
|
||||
@ -62,7 +70,7 @@ arch_timer_set_hardware_timer(bigtime_t timeout)
|
||||
void
|
||||
arch_timer_clear_hardware_timer()
|
||||
{
|
||||
TRACE(("arch_timer_clear_hardware_timer: %p\n", sPxaTimersBase));
|
||||
TRACE(("arch_timer_clear_hardware_timer\n"));
|
||||
|
||||
if (sPxaTimersBase) {
|
||||
sPxaTimersBase[PXA_OMCR4] = 0; // disable our timer
|
||||
|
62
src/system/kernel/arch/arm/asm_offsets.cpp
Normal file
62
src/system/kernel/arch/arm/asm_offsets.cpp
Normal file
@ -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"
|
||||
|
||||
|
||||
#define TRACE_ARM_PAGING_METHOD_32_BIT
|
||||
//#define TRACE_ARM_PAGING_METHOD_32_BIT
|
||||
#ifdef TRACE_ARM_PAGING_METHOD_32_BIT
|
||||
# define TRACE(x...) dprintf(x)
|
||||
#else
|
||||
@ -169,7 +169,8 @@ void
|
||||
ARMPagingMethod32Bit::PhysicalPageSlotPool::Map(phys_addr_t physicalAddress,
|
||||
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)
|
||||
| ARM_PTE_TYPE_SMALL_PAGE;
|
||||
|
||||
@ -298,7 +299,7 @@ ARMPagingMethod32Bit::Init(kernel_args* args,
|
||||
x86_write_cr4(x86_read_cr4() | IA32_CR4_GLOBAL_PAGES);
|
||||
}
|
||||
#endif
|
||||
TRACE("vm_translation_map_init: done\n");
|
||||
TRACE("ARMPagingMethod32Bit::Init(): done\n");
|
||||
|
||||
*_physicalPageMapper = fPhysicalPageMapper;
|
||||
return B_OK;
|
||||
|
@ -249,14 +249,12 @@ ARMVMTranslationMap32Bit::Unmap(addr_t start, addr_t end)
|
||||
ARM_PTE_TYPE_MASK);
|
||||
fMapCount--;
|
||||
|
||||
#if 0 /* IRA */
|
||||
if ((oldEntry & ARM_PTE_ACCESSED) != 0) {
|
||||
if (true /* (oldEntry & ARM_PTE_ACCESSED) != 0*/) {
|
||||
// Note, that we only need to invalidate the address, if the
|
||||
// accessed flags was set, since only then the entry could have
|
||||
// been in any TLB.
|
||||
InvalidatePage(start);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} while (start != 0 && start < end);
|
||||
|
||||
@ -301,8 +299,8 @@ ARMVMTranslationMap32Bit::UnmapPage(VMArea* area, addr_t address,
|
||||
|
||||
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
|
||||
// accessed flags was set, since only then the entry could have been
|
||||
// in any TLB.
|
||||
@ -320,14 +318,14 @@ ARMVMTranslationMap32Bit::UnmapPage(VMArea* area, addr_t address,
|
||||
// Interestingly FreeBSD seems to ignore this problem as well
|
||||
// (cf. pmap_remove_all()), unless I've missed something.
|
||||
}
|
||||
#endif
|
||||
|
||||
locker.Detach();
|
||||
// PageUnmapped() will unlock for us
|
||||
#if 0 //IRA
|
||||
|
||||
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);
|
||||
#endif
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -375,14 +373,13 @@ ARMVMTranslationMap32Bit::UnmapPages(VMArea* area, addr_t base, size_t size,
|
||||
|
||||
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
|
||||
// accessed flags was set, since only then the entry could have
|
||||
// been in any TLB.
|
||||
InvalidatePage(start);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (area->cache_type != CACHE_TYPE_DEVICE) {
|
||||
// get the page
|
||||
vm_page* page = vm_lookup_page(
|
||||
@ -390,13 +387,13 @@ ARMVMTranslationMap32Bit::UnmapPages(VMArea* area, addr_t base, size_t size,
|
||||
ASSERT(page != NULL);
|
||||
|
||||
DEBUG_PAGE_ACCESS_START(page);
|
||||
#if 0
|
||||
|
||||
// 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;
|
||||
if ((oldEntry & ARM_PTE_DIRTY) != 0)
|
||||
if (/*(oldEntry & ARM_PTE_DIRTY) != 0 */ true)
|
||||
page->modified = true;
|
||||
#endif
|
||||
|
||||
// remove the mapping object/decrement the wired_count of the
|
||||
// page
|
||||
if (area->wiring == B_NO_LOCK) {
|
||||
@ -512,19 +509,19 @@ ARMVMTranslationMap32Bit::UnmapArea(VMArea* area, bool deletingAddressSpace,
|
||||
"has no page table entry", page, area, address);
|
||||
continue;
|
||||
}
|
||||
#if 0
|
||||
|
||||
// transfer the accessed/dirty flags to the page and invalidate
|
||||
// the mapping, if necessary
|
||||
if ((oldEntry & ARM_PTE_ACCESSED) != 0) {
|
||||
if (true /*(oldEntry & ARM_PTE_ACCESSED) != 0*/) { // XXX IRA
|
||||
page->accessed = true;
|
||||
|
||||
if (!deletingAddressSpace)
|
||||
InvalidatePage(address);
|
||||
}
|
||||
|
||||
if ((oldEntry & ARM_PTE_DIRTY) != 0)
|
||||
if (true /*(oldEntry & ARM_PTE_DIRTY) != 0*/)
|
||||
page->modified = true;
|
||||
#endif
|
||||
|
||||
if (pageFullyUnmapped) {
|
||||
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_PRESENT) != 0 ? PAGE_PRESENT : 0);
|
||||
#else
|
||||
*_flags = B_KERNEL_WRITE_AREA | B_KERNEL_READ_AREA;
|
||||
*_flags = B_KERNEL_WRITE_AREA | B_KERNEL_READ_AREA | PAGE_PRESENT;
|
||||
#endif
|
||||
return B_OK;
|
||||
}
|
||||
@ -752,7 +749,7 @@ ARMVMTranslationMap32Bit::ClearFlags(addr_t va, uint32 flags)
|
||||
|
||||
pinner.Unlock();
|
||||
|
||||
if ((oldEntry & flagsToClear) != 0)
|
||||
//XXX IRA if ((oldEntry & flagsToClear) != 0)
|
||||
InvalidatePage(va);
|
||||
|
||||
return B_OK;
|
||||
@ -820,10 +817,9 @@ ARMVMTranslationMap32Bit::ClearAccessedAndModified(VMArea* area, addr_t address,
|
||||
|
||||
pinner.Unlock();
|
||||
|
||||
#if 0 //IRA
|
||||
_modified = (oldEntry & ARM_PTE_DIRTY) != 0;
|
||||
_modified = true /* (oldEntry & ARM_PTE_DIRTY) != 0 */; // XXX IRA
|
||||
|
||||
if ((oldEntry & ARM_PTE_ACCESSED) != 0) {
|
||||
if (true /*(oldEntry & ARM_PTE_ACCESSED) != 0*/) {
|
||||
// Note, that we only need to invalidate the address, if the
|
||||
// accessed flags was set, since only then the entry could have been
|
||||
// in any TLB.
|
||||
@ -833,9 +829,6 @@ ARMVMTranslationMap32Bit::ClearAccessedAndModified(VMArea* area, addr_t address,
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
_modified = false;
|
||||
#endif
|
||||
|
||||
if (!unmapIfUnaccessed)
|
||||
return false;
|
||||
|
@ -107,12 +107,12 @@ KPath::InitCheck() const
|
||||
|
||||
|
||||
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;
|
||||
|
||||
if (path) {
|
||||
if (path != NULL) {
|
||||
if (normalize) {
|
||||
// normalize path
|
||||
status_t error = vfs_normalize_path(path, fBuffer, fBufferSize,
|
||||
@ -148,10 +148,10 @@ KPath::Path() const
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
char*
|
||||
KPath::LockBuffer()
|
||||
{
|
||||
if (!fBuffer || fLocked)
|
||||
if (fBuffer == NULL || fLocked)
|
||||
return NULL;
|
||||
|
||||
fLocked = true;
|
||||
@ -193,7 +193,7 @@ KPath::DetachBuffer()
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
const char*
|
||||
KPath::Leaf() const
|
||||
{
|
||||
if (!fBuffer)
|
||||
@ -212,9 +212,9 @@ KPath::Leaf() const
|
||||
|
||||
|
||||
status_t
|
||||
KPath::ReplaceLeaf(const char *newLeaf)
|
||||
KPath::ReplaceLeaf(const char* newLeaf)
|
||||
{
|
||||
const char *leaf = Leaf();
|
||||
const char* leaf = Leaf();
|
||||
if (!leaf)
|
||||
return B_NO_INIT;
|
||||
|
||||
@ -237,7 +237,7 @@ bool
|
||||
KPath::RemoveLeaf()
|
||||
{
|
||||
// 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)
|
||||
return false;
|
||||
|
||||
@ -252,12 +252,12 @@ KPath::RemoveLeaf()
|
||||
|
||||
|
||||
status_t
|
||||
KPath::Append(const char *component, bool isComponent)
|
||||
KPath::Append(const char* component, bool isComponent)
|
||||
{
|
||||
// check initialization and parameter
|
||||
if (!fBuffer)
|
||||
if (fBuffer == NULL)
|
||||
return B_NO_INIT;
|
||||
if (!component)
|
||||
if (component == NULL)
|
||||
return B_BAD_VALUE;
|
||||
if (fPathLength == 0)
|
||||
return SetPath(component);
|
||||
|
Loading…
Reference in New Issue
Block a user