diff --git a/build/jam/OptionalPackages b/build/jam/OptionalPackages index 01b1fb7b20..3875fc71df 100644 --- a/build/jam/OptionalPackages +++ b/build/jam/OptionalPackages @@ -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 ; diff --git a/build/jam/ReleaseBuildProfiles b/build/jam/ReleaseBuildProfiles index 8de37d93db..0fc925fdf6 100644 --- a/build/jam/ReleaseBuildProfiles +++ b/build/jam/ReleaseBuildProfiles @@ -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 ; } diff --git a/build/scripts/build_cross_tools b/build/scripts/build_cross_tools index 37382620d3..cc7c63d3c4 100755 --- a/build/scripts/build_cross_tools +++ b/build/scripts/build_cross_tools @@ -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 } diff --git a/build/scripts/build_cross_tools_gcc4 b/build/scripts/build_cross_tools_gcc4 index 976ff9d3f5..320420f8ea 100755 --- a/build/scripts/build_cross_tools_gcc4 +++ b/build/scripts/build_cross_tools_gcc4 @@ -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 diff --git a/docs/develop/debugger/todo.txt b/docs/develop/debugger/todo.txt new file mode 100644 index 0000000000..f4b91850ad --- /dev/null +++ b/docs/develop/debugger/todo.txt @@ -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). diff --git a/docs/develop/ports/arm/limitations.txt b/docs/develop/ports/arm/limitations.txt new file mode 100644 index 0000000000..7d080c831d --- /dev/null +++ b/docs/develop/ports/arm/limitations.txt @@ -0,0 +1,2 @@ +* Does not support < ARMv5 +* Requires support for high vectors diff --git a/docs/develop/ports/arm/todo.txt b/docs/develop/ports/arm/todo.txt new file mode 100644 index 0000000000..fae21763fc --- /dev/null +++ b/docs/develop/ports/arm/todo.txt @@ -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........... diff --git a/headers/private/kernel/arch/arm/arch_cpu.h b/headers/private/kernel/arch/arm/arch_cpu.h index 97ae14637c..34364a8004 100644 --- a/headers/private/kernel/arch/arm/arch_cpu.h +++ b/headers/private/kernel/arch/arm/arch_cpu.h @@ -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 */ diff --git a/src/add-ons/disk_systems/ntfs/InitializeParameterEditor.cpp b/src/add-ons/disk_systems/ntfs/InitializeParameterEditor.cpp index ac44bfc8cf..ba14586b9f 100644 --- a/src/add-ons/disk_systems/ntfs/InitializeParameterEditor.cpp +++ b/src/add-ons/disk_systems/ntfs/InitializeParameterEditor.cpp @@ -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); diff --git a/src/add-ons/disk_systems/ntfs/NTFSAddOn.cpp b/src/add-ons/disk_systems/ntfs/NTFSAddOn.cpp index 75a2ac53f2..cde20e614e 100644 --- a/src/add-ons/disk_systems/ntfs/NTFSAddOn.cpp +++ b/src/add-ons/disk_systems/ntfs/NTFSAddOn.cpp @@ -33,7 +33,7 @@ using std::nothrow; -#define kPartitionTypeNTFS "NTFS File System" +#define kPartitionTypeNTFS "NT File System" static const uint32 kDiskSystemFlags = 0 diff --git a/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/glue.c b/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/glue.c index 997689e0af..13911c7144 100644 --- a/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/glue.c +++ b/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/glue.c @@ -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); diff --git a/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/if_msk.c b/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/if_msk.c index be4ac5dc8d..377a1589b2 100644 --- a/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/if_msk.c +++ b/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/if_msk.c @@ -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)) diff --git a/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/if_mskreg.h b/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/if_mskreg.h index 583f5e88ef..75ef99ba9d 100644 --- a/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/if_mskreg.h +++ b/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/if_mskreg.h @@ -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) diff --git a/src/add-ons/kernel/drivers/network/usb_asix/AX88772Device.cpp b/src/add-ons/kernel/drivers/network/usb_asix/AX88772Device.cpp index 728917fe66..8bb1e4b9a7 100644 --- a/src/add-ons/kernel/drivers/network/usb_asix/AX88772Device.cpp +++ b/src/add-ons/kernel/drivers/network/usb_asix/AX88772Device.cpp @@ -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", diff --git a/src/add-ons/kernel/file_systems/ntfs/kernel_interface.c b/src/add-ons/kernel/file_systems/ntfs/kernel_interface.c index d4128fceab..d2835f3798 100644 --- a/src/add-ons/kernel/file_systems/ntfs/kernel_interface.c +++ b/src/add-ons/kernel/file_systems/ntfs/kernel_interface.c @@ -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 diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp index 7633290a57..644e540b7f 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp @@ -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 }, diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 727155ef50..3eb68ae8c2 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -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 diff --git a/src/apps/debugger/Jobs.cpp b/src/apps/debugger/Jobs.cpp deleted file mode 100644 index bfd2fe11dc..0000000000 --- a/src/apps/debugger/Jobs.cpp +++ /dev/null @@ -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 -#include - -#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 reference(state, true); - - AutoLocker 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 reference(state, true); - - AutoLocker 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 stackTraceReference(stackTrace, true); - - // set the stack trace, unless something has changed - AutoLocker locker(fThread->GetTeam()); - - if (fThread->GetCpuState() == fCpuState) - fThread->SetStackTrace(stackTrace); - - return B_OK; -} - - -status_t -GetStackTraceJob::GetImageDebugInfo(Image* image, ImageDebugInfo*& _info) -{ - AutoLocker 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 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 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 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 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 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 containerLocker(fContainer); - ValueNodeChild* nodeChild = fValueNode->NodeChild(); - BReference nodeChildReference(nodeChild); - - ValueNode* parentNode = nodeChild->Parent(); - BReference 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 locationReference(location, true); - BReference 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 locationReference(location, true); - - // set the location on the node child - AutoLocker 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 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 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; -} diff --git a/src/apps/debugger/MessageCodes.h b/src/apps/debugger/MessageCodes.h index 75a2df88f3..b3e0f9717b 100644 --- a/src/apps/debugger/MessageCodes.h +++ b/src/apps/debugger/MessageCodes.h @@ -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' }; diff --git a/src/apps/debugger/TeamDebugger.cpp b/src/apps/debugger/controllers/TeamDebugger.cpp similarity index 98% rename from src/apps/debugger/TeamDebugger.cpp rename to src/apps/debugger/controllers/TeamDebugger.cpp index 26378e1019..e316d8b7f8 100644 --- a/src/apps/debugger/TeamDebugger.cpp +++ b/src/apps/debugger/controllers/TeamDebugger.cpp @@ -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 watchpointReference(watchpoint, true); - - // install it - fWatchpointManager->InstallWatchpoint(watchpoint, - watchpointSetting->IsEnabled()); - } - const TeamUiSettings* uiSettings = fTeamSettings.UiSettingFor( fUserInterface->ID()); if (uiSettings != NULL) diff --git a/src/apps/debugger/TeamDebugger.h b/src/apps/debugger/controllers/TeamDebugger.h similarity index 100% rename from src/apps/debugger/TeamDebugger.h rename to src/apps/debugger/controllers/TeamDebugger.h diff --git a/src/apps/debugger/ThreadHandler.cpp b/src/apps/debugger/controllers/ThreadHandler.cpp similarity index 100% rename from src/apps/debugger/ThreadHandler.cpp rename to src/apps/debugger/controllers/ThreadHandler.cpp diff --git a/src/apps/debugger/ThreadHandler.h b/src/apps/debugger/controllers/ThreadHandler.h similarity index 100% rename from src/apps/debugger/ThreadHandler.h rename to src/apps/debugger/controllers/ThreadHandler.h diff --git a/src/apps/debugger/BreakpointManager.cpp b/src/apps/debugger/debug_managers/BreakpointManager.cpp similarity index 100% rename from src/apps/debugger/BreakpointManager.cpp rename to src/apps/debugger/debug_managers/BreakpointManager.cpp diff --git a/src/apps/debugger/BreakpointManager.h b/src/apps/debugger/debug_managers/BreakpointManager.h similarity index 100% rename from src/apps/debugger/BreakpointManager.h rename to src/apps/debugger/debug_managers/BreakpointManager.h diff --git a/src/apps/debugger/TeamMemoryBlockManager.cpp b/src/apps/debugger/debug_managers/TeamMemoryBlockManager.cpp similarity index 100% rename from src/apps/debugger/TeamMemoryBlockManager.cpp rename to src/apps/debugger/debug_managers/TeamMemoryBlockManager.cpp diff --git a/src/apps/debugger/TeamMemoryBlockManager.h b/src/apps/debugger/debug_managers/TeamMemoryBlockManager.h similarity index 100% rename from src/apps/debugger/TeamMemoryBlockManager.h rename to src/apps/debugger/debug_managers/TeamMemoryBlockManager.h diff --git a/src/apps/debugger/WatchpointManager.cpp b/src/apps/debugger/debug_managers/WatchpointManager.cpp similarity index 86% rename from src/apps/debugger/WatchpointManager.cpp rename to src/apps/debugger/debug_managers/WatchpointManager.cpp index e5854a06be..9b21554c09 100644 --- a/src/apps/debugger/WatchpointManager.cpp +++ b/src/apps/debugger/debug_managers/WatchpointManager.cpp @@ -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 installLocker(fLock); AutoLocker 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); -} \ No newline at end of file + fTeam->NotifyWatchpointChanged(watchpoint); + } +} diff --git a/src/apps/debugger/WatchpointManager.h b/src/apps/debugger/debug_managers/WatchpointManager.h similarity index 100% rename from src/apps/debugger/WatchpointManager.h rename to src/apps/debugger/debug_managers/WatchpointManager.h diff --git a/src/apps/debugger/jobs/GetCPUStateJob.cpp b/src/apps/debugger/jobs/GetCPUStateJob.cpp new file mode 100644 index 0000000000..2d28c4cd79 --- /dev/null +++ b/src/apps/debugger/jobs/GetCPUStateJob.cpp @@ -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 + +#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 reference(state, true); + + AutoLocker locker(fThread->GetTeam()); + + if (fThread->State() == THREAD_STATE_STOPPED) + fThread->SetCpuState(state); + + return B_OK; +} diff --git a/src/apps/debugger/jobs/GetStackTraceJob.cpp b/src/apps/debugger/jobs/GetStackTraceJob.cpp new file mode 100644 index 0000000000..61a1c724d8 --- /dev/null +++ b/src/apps/debugger/jobs/GetStackTraceJob.cpp @@ -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 + +#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 stackTraceReference(stackTrace, true); + + // set the stack trace, unless something has changed + AutoLocker locker(fThread->GetTeam()); + + if (fThread->GetCpuState() == fCpuState) + fThread->SetStackTrace(stackTrace); + + return B_OK; +} + + +status_t +GetStackTraceJob::GetImageDebugInfo(Image* image, ImageDebugInfo*& _info) +{ + AutoLocker 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; +} diff --git a/src/apps/debugger/jobs/GetThreadStateJob.cpp b/src/apps/debugger/jobs/GetThreadStateJob.cpp new file mode 100644 index 0000000000..61ae3dd026 --- /dev/null +++ b/src/apps/debugger/jobs/GetThreadStateJob.cpp @@ -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 + +#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 reference(state, true); + + AutoLocker 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; +} diff --git a/src/apps/debugger/Jobs.h b/src/apps/debugger/jobs/Jobs.h similarity index 100% rename from src/apps/debugger/Jobs.h rename to src/apps/debugger/jobs/Jobs.h diff --git a/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp b/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp new file mode 100644 index 0000000000..dc1706c29f --- /dev/null +++ b/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp @@ -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 + +#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 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 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; +} diff --git a/src/apps/debugger/jobs/LoadSourceCodeJob.cpp b/src/apps/debugger/jobs/LoadSourceCodeJob.cpp new file mode 100644 index 0000000000..4cb60a0a31 --- /dev/null +++ b/src/apps/debugger/jobs/LoadSourceCodeJob.cpp @@ -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 + +#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 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 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; +} diff --git a/src/apps/debugger/jobs/ResolveValueNodeJob.cpp b/src/apps/debugger/jobs/ResolveValueNodeJob.cpp new file mode 100644 index 0000000000..c810ad5c3e --- /dev/null +++ b/src/apps/debugger/jobs/ResolveValueNodeJob.cpp @@ -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 + +#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 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 containerLocker(fContainer); + ValueNodeChild* nodeChild = fValueNode->NodeChild(); + BReference nodeChildReference(nodeChild); + + ValueNode* parentNode = nodeChild->Parent(); + BReference 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 locationReference(location, true); + BReference 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 locationReference(location, true); + + // set the location on the node child + AutoLocker 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 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 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; +} diff --git a/src/apps/debugger/jobs/RetrieveMemoryBlockJob.cpp b/src/apps/debugger/jobs/RetrieveMemoryBlockJob.cpp new file mode 100644 index 0000000000..888bfa4ae8 --- /dev/null +++ b/src/apps/debugger/jobs/RetrieveMemoryBlockJob.cpp @@ -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 +#include + +#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; +} diff --git a/src/apps/debugger/model/Team.cpp b/src/apps/debugger/model/Team.cpp index 3a379c20e1..0f3a6a240a 100644 --- a/src/apps/debugger/model/Team.cpp +++ b/src/apps/debugger/model/Team.cpp @@ -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(); diff --git a/src/apps/debugger/model/Team.h b/src/apps/debugger/model/Team.h index 03dd5f5038..d11e76728f 100644 --- a/src/apps/debugger/model/Team.h +++ b/src/apps/debugger/model/Team.h @@ -145,6 +145,8 @@ public: TargetAddressRange range, BObjectList& watchpoints) const; + const WatchpointList& Watchpoints() const + { return fWatchpoints; } status_t GetStatementAtAddress(target_addr_t address, FunctionInstance*& _function, @@ -187,7 +189,6 @@ private: typedef BObjectList BreakpointList; typedef DoublyLinkedList ListenerList; - typedef BObjectList WatchpointList; private: void _NotifyThreadAdded(Thread* thread); diff --git a/src/apps/debugger/model/Watchpoint.h b/src/apps/debugger/model/Watchpoint.h index a9d591f829..fa1ac20f19 100644 --- a/src/apps/debugger/model/Watchpoint.h +++ b/src/apps/debugger/model/Watchpoint.h @@ -6,6 +6,7 @@ #define WATCHPOINT_H +#include #include #include "types/Types.h" @@ -49,4 +50,7 @@ private: }; +typedef BObjectList WatchpointList; + + #endif // WATCHPOINT_H diff --git a/src/apps/debugger/settings/TeamSettings.cpp b/src/apps/debugger/settings/TeamSettings.cpp index fbed4c8f74..605202dcf8 100644 --- a/src/apps/debugger/settings/TeamSettings.cpp +++ b/src/apps/debugger/settings/TeamSettings.cpp @@ -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 { diff --git a/src/apps/debugger/settings/TeamSettings.h b/src/apps/debugger/settings/TeamSettings.h index 3bc74e3d87..f41f2bf8bd 100644 --- a/src/apps/debugger/settings/TeamSettings.h +++ b/src/apps/debugger/settings/TeamSettings.h @@ -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 BreakpointList; typedef BObjectList UiSettingsList; - typedef BObjectList WatchpointList; private: void _Unset(); private: BreakpointList fBreakpoints; - WatchpointList fWatchpoints; UiSettingsList fUiSettings; BString fTeamName; }; diff --git a/src/apps/debugger/settings/WatchpointSetting.cpp b/src/apps/debugger/settings/WatchpointSetting.cpp deleted file mode 100644 index 0872e148dd..0000000000 --- a/src/apps/debugger/settings/WatchpointSetting.cpp +++ /dev/null @@ -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 - -#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; -} diff --git a/src/apps/debugger/settings/WatchpointSetting.h b/src/apps/debugger/settings/WatchpointSetting.h deleted file mode 100644 index 14fd16ceb4..0000000000 --- a/src/apps/debugger/settings/WatchpointSetting.h +++ /dev/null @@ -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 - -#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 diff --git a/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.cpp b/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.cpp index a9ef8f870b..b1698c8f41 100644 --- a/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.cpp @@ -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 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 fBreakpoints; + BObjectList 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); + } } diff --git a/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.h b/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.h index 73ebc0e3bf..317ca5be71 100644 --- a/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.h +++ b/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.h @@ -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; }; diff --git a/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.cpp b/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.cpp index 176d6cab3b..f7e58e2ba1 100644 --- a/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.cpp @@ -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 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)); diff --git a/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.h b/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.h index 2240252ee7..02bef310b6 100644 --- a/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.h +++ b/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.h @@ -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; }; diff --git a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp index 4da2045c39..862895233b 100644 --- a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp @@ -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 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 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) { diff --git a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h index 9d979723e6..d371a5b694 100644 --- a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h +++ b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h @@ -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); diff --git a/src/apps/debugger/user_interface/gui/team_window/VariablesView.cpp b/src/apps/debugger/user_interface/gui/team_window/VariablesView.cpp index e5a6be1c50..744a2d1e86 100644 --- a/src/apps/debugger/user_interface/gui/team_window/VariablesView.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/VariablesView.cpp @@ -11,6 +11,8 @@ #include +#include + #include #include #include @@ -1684,6 +1686,22 @@ VariablesView::MessageReceived(BMessage* message) node->NodeChild()->SetNode(valueNode); break; } + case MSG_SHOW_WATCH_VARIABLE_PROMPT: + { + ModelNode* node = reinterpret_cast( + 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 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 messageDeleter(_message); + + ActionMenuItem* item = new(std::nothrow) ActionMenuItem(action, + _message); if (item == NULL) return B_NO_MEMORY; messageDeleter.Detach(); ObjectDeleter 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; diff --git a/src/apps/debugger/user_interface/gui/team_window/VariablesView.h b/src/apps/debugger/user_interface/gui/team_window/VariablesView.h index 7c09b73f98..974190068d 100644 --- a/src/apps/debugger/user_interface/gui/team_window/VariablesView.h +++ b/src/apps/debugger/user_interface/gui/team_window/VariablesView.h @@ -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(); diff --git a/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.cpp b/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.cpp new file mode 100644 index 0000000000..2718ce80ff --- /dev/null +++ b/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.cpp @@ -0,0 +1,154 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ +#include "WatchPromptWindow.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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; + } + +} diff --git a/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.h b/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.h new file mode 100644 index 0000000000..465fdd696c --- /dev/null +++ b/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.h @@ -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 + +#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 diff --git a/src/apps/debugger/Worker.cpp b/src/apps/debugger/util/Worker.cpp similarity index 100% rename from src/apps/debugger/Worker.cpp rename to src/apps/debugger/util/Worker.cpp diff --git a/src/apps/debugger/Worker.h b/src/apps/debugger/util/Worker.h similarity index 100% rename from src/apps/debugger/Worker.h rename to src/apps/debugger/util/Worker.h diff --git a/src/apps/drivesetup/MainWindow.cpp b/src/apps/drivesetup/MainWindow.cpp index 922c40d681..c8ab45f0a5 100644 --- a/src/apps/drivesetup/MainWindow.cpp +++ b/src/apps/drivesetup/MainWindow.cpp @@ -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) diff --git a/src/apps/showimage/ShowImageWindow.cpp b/src/apps/showimage/ShowImageWindow.cpp index 22144762b3..b79059e54c 100644 --- a/src/apps/showimage/ShowImageWindow.cpp +++ b/src/apps/showimage/ShowImageWindow.cpp @@ -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); diff --git a/src/apps/terminal/AppearPrefView.cpp b/src/apps/terminal/AppearPrefView.cpp index eea2156a5b..4f9bcca934 100644 --- a/src/apps/terminal/AppearPrefView.cpp +++ b/src/apps/terminal/AppearPrefView.cpp @@ -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( diff --git a/src/apps/terminal/TermConst.h b/src/apps/terminal/TermConst.h index cf0a31c2c6..05174b11c5 100644 --- a/src/apps/terminal/TermConst.h +++ b/src/apps/terminal/TermConst.h @@ -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"; diff --git a/src/kits/interface/Rect.cpp b/src/kits/interface/Rect.cpp index 20b51308ff..d8d66d8f4b 100644 --- a/src/kits/interface/Rect.cpp +++ b/src/kits/interface/Rect.cpp @@ -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 diff --git a/src/system/kernel/arch/arm/arch_asm.S b/src/system/kernel/arch/arm/arch_asm.S index c417a91742..c51089c718 100644 --- a/src/system/kernel/arch/arm/arch_asm.S +++ b/src/system/kernel/arch/arm/arch_asm.S @@ -10,21 +10,38 @@ #include +#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) diff --git a/src/system/kernel/arch/arm/arch_debug.cpp b/src/system/kernel/arch/arm/arch_debug.cpp index 0b6449053a..daae859148 100644 --- a/src/system/kernel/arch/arm/arch_debug.cpp +++ b/src/system/kernel/arch/arm/arch_debug.cpp @@ -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) diff --git a/src/system/kernel/arch/arm/arch_exceptions.S b/src/system/kernel/arch/arm/arch_exceptions.S index cffb1f87f8..41a88d9f9c 100644 --- a/src/system/kernel/arch/arm/arch_exceptions.S +++ b/src/system/kernel/arch/arm/arch_exceptions.S @@ -9,6 +9,49 @@ #include +#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) diff --git a/src/system/kernel/arch/arm/arch_int.cpp b/src/system/kernel/arch/arm/arch_int.cpp index 97a735aa4a..5c37f36a77 100644 --- a/src/system/kernel/arch/arm/arch_int.cpp +++ b/src/system/kernel/arch/arm/arch_int.cpp @@ -31,7 +31,7 @@ #include -#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) diff --git a/src/system/kernel/arch/arm/arch_platform.cpp b/src/system/kernel/arch/arm/arch_platform.cpp index f3721a6aca..a018654b1d 100644 --- a/src/system/kernel/arch/arm/arch_platform.cpp +++ b/src/system/kernel/arch/arm/arch_platform.cpp @@ -6,52 +6,17 @@ * All rights reserved. Distributed under the terms of the MIT License. */ -//#include - -#include - #include #include #include -//#include #include #include - - -#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 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; } diff --git a/src/system/kernel/arch/arm/arch_thread.cpp b/src/system/kernel/arch/arm/arch_thread.cpp index 2ae92ae4cc..3f7950e380 100644 --- a/src/system/kernel/arch/arm/arch_thread.cpp +++ b/src/system/kernel/arch/arm/arch_thread.cpp @@ -28,7 +28,7 @@ #include -#define TRACE_ARCH_THREAD +//#define TRACE_ARCH_THREAD #ifdef TRACE_ARCH_THREAD # define TRACE(x) dprintf x #else diff --git a/src/system/kernel/arch/arm/arch_timer.cpp b/src/system/kernel/arch/arm/arch_timer.cpp index 2bda04042c..5cf8574279 100644 --- a/src/system/kernel/arch/arm/arch_timer.cpp +++ b/src/system/kernel/arch/arm/arch_timer.cpp @@ -19,6 +19,15 @@ #include #include + +//#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 diff --git a/src/system/kernel/arch/arm/asm_offsets.cpp b/src/system/kernel/arch/arm/asm_offsets.cpp new file mode 100644 index 0000000000..64e85057d7 --- /dev/null +++ b/src/system/kernel/arch/arm/asm_offsets.cpp @@ -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 + +#include +#include +#include +#include +#include + + +#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); +} diff --git a/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp b/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp index 9214286f02..91bfa29a22 100644 --- a/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp +++ b/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp @@ -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; diff --git a/src/system/kernel/arch/arm/paging/32bit/ARMVMTranslationMap32Bit.cpp b/src/system/kernel/arch/arm/paging/32bit/ARMVMTranslationMap32Bit.cpp index 2d19cb8f9a..ba70d0fa59 100644 --- a/src/system/kernel/arch/arm/paging/32bit/ARMVMTranslationMap32Bit.cpp +++ b/src/system/kernel/arch/arm/paging/32bit/ARMVMTranslationMap32Bit.cpp @@ -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; diff --git a/src/system/kernel/fs/KPath.cpp b/src/system/kernel/fs/KPath.cpp index a7c55e31f6..2de6ae2805 100644 --- a/src/system/kernel/fs/KPath.cpp +++ b/src/system/kernel/fs/KPath.cpp @@ -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);