Merge branch 'master' into sam460ex

This commit is contained in:
François Revol 2012-11-08 10:25:41 +01:00
commit 17c270bd4f
72 changed files with 1988 additions and 1259 deletions

View File

@ -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 ;

View File

@ -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 ;
}

View File

@ -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
}

View File

@ -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

View File

@ -0,0 +1,14 @@
- Need the ability to save crash reports.
- CLI needs to be more fully implemented.
- General expression evaluation parser. Once implemented, should supplant the primitive one currently used for C/C++ typecasting support, as well as being exposed for user expression input.
- Conditional breakpoint/watchpoints. Contingent on above general expression parser.
- Remote debug interface support.
- Kernel debug support.
- Architecture needs to be able to report back the hardware debugging capabilities/limitations of the target platform.
- WatchpointManager needs to be able to use the aforementioned information from Architecture in order to more intelligently
manage/restrict watchpoint usage (especially once expression watchpoints come into play).
- More complete DWARF3/4 support.
- x86-64 support.
- Support for retrieving/displaying function return values (arch-specific).
- Syntax highlighting in source view.
- Detection of mouse hovering over a variable in SourceView and showing value in tooltip (probably requires expression parsing support).

View File

@ -0,0 +1,2 @@
* Does not support < ARMv5
* Requires support for high vectors

View File

@ -0,0 +1,19 @@
* Figure out how to get page flags (modified/accessed) and implement it ;)
* Fix serial port mapping. Currently kernel uses the haiku_loader identity
mapping for it, but this lives in user virtual address space...
(Need to not use identity mapping in haiku_loader but just
map_physical_memory() there too so it can be handed over without issues).
* Seperate ARM architecture/System-On-Chip IP code. Needed very early on
(Interrupt Controller, Timer IP block). Should use FDT for this too.
* Use FDT to remove all the seperate board definitions in the build. Use a
"minimal ARM architecture version" as the compile flag for ARM support.
This to be able to optimize a kernel build for a specific SoC (or family).
* Research stack unwinding to implement backtrace support for KDL & friends.
* Add KDL hangman to the boot floppy image for more enjoyment during porting....
* Userland...........

View File

@ -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 */

View File

@ -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);

View File

@ -33,7 +33,7 @@
using std::nothrow;
#define kPartitionTypeNTFS "NTFS File System"
#define kPartitionTypeNTFS "NT File System"
static const uint32 kDiskSystemFlags =
0

View File

@ -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);

View File

@ -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))

View File

@ -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)

View File

@ -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",

View File

@ -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

View File

@ -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 },

View File

@ -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

View File

@ -1,698 +0,0 @@
/*
* Copyright 2012, Rene Gollent, rene@gollent.com.
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "Jobs.h"
#include <AutoLocker.h>
#include <memory_private.h>
#include "Architecture.h"
#include "BitBuffer.h"
#include "CpuState.h"
#include "DebuggerInterface.h"
#include "DisassembledCode.h"
#include "FileSourceCode.h"
#include "Function.h"
#include "Image.h"
#include "ImageDebugInfo.h"
#include "Register.h"
#include "SourceCode.h"
#include "SpecificImageDebugInfo.h"
#include "StackFrameDebugInfo.h"
#include "StackFrameValueInfos.h"
#include "StackFrameValues.h"
#include "StackTrace.h"
#include "Team.h"
#include "TeamDebugInfo.h"
#include "TeamMemory.h"
#include "TeamMemoryBlock.h"
#include "TeamTypeInformation.h"
#include "Thread.h"
#include "Tracing.h"
#include "Type.h"
#include "TypeComponentPath.h"
#include "Value.h"
#include "ValueLoader.h"
#include "ValueLocation.h"
#include "ValueNode.h"
#include "ValueNodeContainer.h"
#include "Variable.h"
// #pragma mark - GetThreadStateJob
GetThreadStateJob::GetThreadStateJob(DebuggerInterface* debuggerInterface,
Thread* thread)
:
fKey(thread, JOB_TYPE_GET_THREAD_STATE),
fDebuggerInterface(debuggerInterface),
fThread(thread)
{
fThread->AcquireReference();
}
GetThreadStateJob::~GetThreadStateJob()
{
fThread->ReleaseReference();
}
const JobKey&
GetThreadStateJob::Key() const
{
return fKey;
}
status_t
GetThreadStateJob::Do()
{
CpuState* state = NULL;
status_t error = fDebuggerInterface->GetCpuState(fThread->ID(), state);
BReference<CpuState> reference(state, true);
AutoLocker<Team> locker(fThread->GetTeam());
if (fThread->State() != THREAD_STATE_UNKNOWN)
return B_OK;
if (error == B_OK) {
fThread->SetState(THREAD_STATE_STOPPED);
fThread->SetCpuState(state);
} else if (error == B_BAD_THREAD_STATE) {
fThread->SetState(THREAD_STATE_RUNNING);
} else
return error;
return B_OK;
}
// #pragma mark - GetCpuStateJob
GetCpuStateJob::GetCpuStateJob(DebuggerInterface* debuggerInterface,
Thread* thread)
:
fKey(thread, JOB_TYPE_GET_CPU_STATE),
fDebuggerInterface(debuggerInterface),
fThread(thread)
{
fThread->AcquireReference();
}
GetCpuStateJob::~GetCpuStateJob()
{
fThread->ReleaseReference();
}
const JobKey&
GetCpuStateJob::Key() const
{
return fKey;
}
status_t
GetCpuStateJob::Do()
{
CpuState* state;
status_t error = fDebuggerInterface->GetCpuState(fThread->ID(), state);
if (error != B_OK)
return error;
BReference<CpuState> reference(state, true);
AutoLocker<Team> locker(fThread->GetTeam());
if (fThread->State() == THREAD_STATE_STOPPED)
fThread->SetCpuState(state);
return B_OK;
}
// #pragma mark - GetStackTraceJob
GetStackTraceJob::GetStackTraceJob(DebuggerInterface* debuggerInterface,
Architecture* architecture, Thread* thread)
:
fKey(thread, JOB_TYPE_GET_STACK_TRACE),
fDebuggerInterface(debuggerInterface),
fArchitecture(architecture),
fThread(thread)
{
fThread->AcquireReference();
fCpuState = fThread->GetCpuState();
if (fCpuState != NULL)
fCpuState->AcquireReference();
}
GetStackTraceJob::~GetStackTraceJob()
{
if (fCpuState != NULL)
fCpuState->ReleaseReference();
fThread->ReleaseReference();
}
const JobKey&
GetStackTraceJob::Key() const
{
return fKey;
}
status_t
GetStackTraceJob::Do()
{
if (fCpuState == NULL)
return B_BAD_VALUE;
// get the stack trace
StackTrace* stackTrace;
status_t error = fArchitecture->CreateStackTrace(fThread->GetTeam(), this,
fCpuState, stackTrace);
if (error != B_OK)
return error;
BReference<StackTrace> stackTraceReference(stackTrace, true);
// set the stack trace, unless something has changed
AutoLocker<Team> locker(fThread->GetTeam());
if (fThread->GetCpuState() == fCpuState)
fThread->SetStackTrace(stackTrace);
return B_OK;
}
status_t
GetStackTraceJob::GetImageDebugInfo(Image* image, ImageDebugInfo*& _info)
{
AutoLocker<Team> teamLocker(fThread->GetTeam());
while (image->GetImageDebugInfo() == NULL) {
// schedule a job, if not loaded
ImageDebugInfo* info;
status_t error = LoadImageDebugInfoJob::ScheduleIfNecessary(GetWorker(),
image, &info);
if (error != B_OK)
return error;
if (info != NULL) {
_info = info;
return B_OK;
}
teamLocker.Unlock();
// wait for the job to finish
switch (WaitFor(SimpleJobKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO))) {
case JOB_DEPENDENCY_SUCCEEDED:
case JOB_DEPENDENCY_NOT_FOUND:
// "Not found" can happen due to a race condition between
// unlocking the worker and starting to wait.
break;
case JOB_DEPENDENCY_FAILED:
case JOB_DEPENDENCY_ABORTED:
default:
return B_ERROR;
}
teamLocker.Lock();
}
_info = image->GetImageDebugInfo();
_info->AcquireReference();
return B_OK;
}
// #pragma mark - LoadImageDebugInfoJob
LoadImageDebugInfoJob::LoadImageDebugInfoJob(Image* image)
:
fKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO),
fImage(image)
{
fImage->AcquireReference();
}
LoadImageDebugInfoJob::~LoadImageDebugInfoJob()
{
fImage->ReleaseReference();
}
const JobKey&
LoadImageDebugInfoJob::Key() const
{
return fKey;
}
status_t
LoadImageDebugInfoJob::Do()
{
// get an image info for the image
AutoLocker<Team> locker(fImage->GetTeam());
ImageInfo imageInfo(fImage->Info());
locker.Unlock();
// create the debug info
ImageDebugInfo* debugInfo;
status_t error = fImage->GetTeam()->DebugInfo()->LoadImageDebugInfo(
imageInfo, fImage->ImageFile(), debugInfo);
// set the result
locker.Lock();
if (error == B_OK) {
error = fImage->SetImageDebugInfo(debugInfo, IMAGE_DEBUG_INFO_LOADED);
debugInfo->ReleaseReference();
} else
fImage->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_UNAVAILABLE);
return error;
}
/*static*/ status_t
LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image,
ImageDebugInfo** _imageDebugInfo)
{
AutoLocker<Team> teamLocker(image->GetTeam());
// If already loaded, we're done.
if (image->GetImageDebugInfo() != NULL) {
if (_imageDebugInfo != NULL) {
*_imageDebugInfo = image->GetImageDebugInfo();
(*_imageDebugInfo)->AcquireReference();
}
return B_OK;
}
// If already loading, the caller has to wait, if desired.
if (image->ImageDebugInfoState() == IMAGE_DEBUG_INFO_LOADING) {
if (_imageDebugInfo != NULL)
*_imageDebugInfo = NULL;
return B_OK;
}
// If an earlier load attempt failed, bail out.
if (image->ImageDebugInfoState() != IMAGE_DEBUG_INFO_NOT_LOADED)
return B_ERROR;
// schedule a job
LoadImageDebugInfoJob* job = new(std::nothrow) LoadImageDebugInfoJob(image);
if (job == NULL)
return B_NO_MEMORY;
status_t error = worker->ScheduleJob(job);
if (error != B_OK) {
image->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_UNAVAILABLE);
return error;
}
image->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_LOADING);
if (_imageDebugInfo != NULL)
*_imageDebugInfo = NULL;
return B_OK;
}
// #pragma mark - LoadSourceCodeJob
LoadSourceCodeJob::LoadSourceCodeJob(
DebuggerInterface* debuggerInterface, Architecture* architecture,
Team* team, FunctionInstance* functionInstance, bool loadForFunction)
:
fKey(functionInstance, JOB_TYPE_LOAD_SOURCE_CODE),
fDebuggerInterface(debuggerInterface),
fArchitecture(architecture),
fTeam(team),
fFunctionInstance(functionInstance),
fLoadForFunction(loadForFunction)
{
fFunctionInstance->AcquireReference();
}
LoadSourceCodeJob::~LoadSourceCodeJob()
{
fFunctionInstance->ReleaseReference();
}
const JobKey&
LoadSourceCodeJob::Key() const
{
return fKey;
}
status_t
LoadSourceCodeJob::Do()
{
// if requested, try loading the source code for the function
Function* function = fFunctionInstance->GetFunction();
if (fLoadForFunction) {
FileSourceCode* sourceCode;
status_t error = fTeam->DebugInfo()->LoadSourceCode(
function->SourceFile(), sourceCode);
AutoLocker<Team> locker(fTeam);
if (error == B_OK) {
function->SetSourceCode(sourceCode, FUNCTION_SOURCE_LOADED);
sourceCode->ReleaseReference();
return B_OK;
}
function->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE);
}
// Only try to load the function instance code, if it's not overridden yet.
AutoLocker<Team> locker(fTeam);
if (fFunctionInstance->SourceCodeState() != FUNCTION_SOURCE_LOADING)
return B_OK;
locker.Unlock();
// disassemble the function
DisassembledCode* sourceCode = NULL;
status_t error = fTeam->DebugInfo()->DisassembleFunction(fFunctionInstance,
sourceCode);
// set the result
locker.Lock();
if (error == B_OK) {
if (fFunctionInstance->SourceCodeState() == FUNCTION_SOURCE_LOADING) {
fFunctionInstance->SetSourceCode(sourceCode,
FUNCTION_SOURCE_LOADED);
sourceCode->ReleaseReference();
}
} else
fFunctionInstance->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE);
return error;
}
// #pragma mark - ResolveValueNodeValueJob
ResolveValueNodeValueJob::ResolveValueNodeValueJob(
DebuggerInterface* debuggerInterface, Architecture* architecture,
CpuState* cpuState, TeamTypeInformation* typeInformation,
ValueNodeContainer* container, ValueNode* valueNode)
:
fKey(valueNode, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE),
fDebuggerInterface(debuggerInterface),
fArchitecture(architecture),
fCpuState(cpuState),
fTypeInformation(typeInformation),
fContainer(container),
fValueNode(valueNode)
{
if (fCpuState != NULL)
fCpuState->AcquireReference();
fContainer->AcquireReference();
fValueNode->AcquireReference();
}
ResolveValueNodeValueJob::~ResolveValueNodeValueJob()
{
if (fCpuState != NULL)
fCpuState->ReleaseReference();
fContainer->ReleaseReference();
fValueNode->ReleaseReference();
}
const JobKey&
ResolveValueNodeValueJob::Key() const
{
return fKey;
}
status_t
ResolveValueNodeValueJob::Do()
{
// check whether the node still belongs to the container
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
if (fValueNode->Container() != fContainer)
return B_BAD_VALUE;
// if already resolved, we're done
status_t nodeResolutionState
= fValueNode->LocationAndValueResolutionState();
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
return nodeResolutionState;
containerLocker.Unlock();
// resolve
status_t error = _ResolveNodeValue();
if (error != B_OK) {
nodeResolutionState = fValueNode->LocationAndValueResolutionState();
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
return nodeResolutionState;
containerLocker.Lock();
fValueNode->SetLocationAndValue(NULL, NULL, error);
containerLocker.Unlock();
}
return error;
}
status_t
ResolveValueNodeValueJob::_ResolveNodeValue()
{
// get the node child and parent node
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
ValueNodeChild* nodeChild = fValueNode->NodeChild();
BReference<ValueNodeChild> nodeChildReference(nodeChild);
ValueNode* parentNode = nodeChild->Parent();
BReference<ValueNode> parentNodeReference(parentNode);
// Check whether the node child location has been resolved already
// (successfully).
status_t nodeChildResolutionState = nodeChild->LocationResolutionState();
bool nodeChildDone = nodeChildResolutionState != VALUE_NODE_UNRESOLVED;
if (nodeChildDone && nodeChildResolutionState != B_OK)
return nodeChildResolutionState;
// If the child node location has not been resolved yet, check whether the
// parent node location and value have been resolved already (successfully).
bool parentDone = true;
if (!nodeChildDone && parentNode != NULL) {
status_t parentResolutionState
= parentNode->LocationAndValueResolutionState();
parentDone = parentResolutionState != VALUE_NODE_UNRESOLVED;
if (parentDone && parentResolutionState != B_OK)
return parentResolutionState;
}
containerLocker.Unlock();
// resolve the parent node location and value, if necessary
if (!parentDone) {
status_t error = _ResolveParentNodeValue(parentNode);
if (error != B_OK) {
TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
"node: %p (\"%s\"): _ResolveParentNodeValue(%p) failed\n",
fValueNode, fValueNode->Name().String(), parentNode);
return error;
}
if (State() == JOB_STATE_WAITING)
return B_OK;
}
// resolve the node child location, if necessary
if (!nodeChildDone) {
status_t error = _ResolveNodeChildLocation(nodeChild);
if (error != B_OK) {
TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
"node: %p (\"%s\"): _ResolveNodeChildLocation(%p) failed\n",
fValueNode, fValueNode->Name().String(), nodeChild);
return error;
}
}
// resolve the node location and value
ValueLoader valueLoader(fArchitecture, fDebuggerInterface,
fTypeInformation, fCpuState);
ValueLocation* location;
Value* value;
status_t error = fValueNode->ResolvedLocationAndValue(&valueLoader,
location, value);
if (error != B_OK) {
TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
"node: %p (\"%s\"): fValueNode->ResolvedLocationAndValue() "
"failed\n", fValueNode, fValueNode->Name().String());
return error;
}
BReference<ValueLocation> locationReference(location, true);
BReference<Value> valueReference(value, true);
// set location and value on the node
containerLocker.Lock();
status_t nodeResolutionState
= fValueNode->LocationAndValueResolutionState();
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
return nodeResolutionState;
fValueNode->SetLocationAndValue(location, value, B_OK);
containerLocker.Unlock();
return B_OK;
}
status_t
ResolveValueNodeValueJob::_ResolveNodeChildLocation(ValueNodeChild* nodeChild)
{
// resolve the location
ValueLoader valueLoader(fArchitecture, fDebuggerInterface,
fTypeInformation, fCpuState);
ValueLocation* location = NULL;
status_t error = nodeChild->ResolveLocation(&valueLoader, location);
BReference<ValueLocation> locationReference(location, true);
// set the location on the node child
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
status_t nodeChildResolutionState = nodeChild->LocationResolutionState();
if (nodeChildResolutionState == VALUE_NODE_UNRESOLVED)
nodeChild->SetLocation(location, error);
else
error = nodeChildResolutionState;
return error;
}
status_t
ResolveValueNodeValueJob::_ResolveParentNodeValue(ValueNode* parentNode)
{
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
if (parentNode->Container() != fContainer)
return B_BAD_VALUE;
// if the parent node already has a value, we're done
status_t nodeResolutionState
= parentNode->LocationAndValueResolutionState();
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
return nodeResolutionState;
// check whether a job is already in progress
AutoLocker<Worker> workerLocker(GetWorker());
SimpleJobKey jobKey(parentNode, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE);
if (GetWorker()->GetJob(jobKey) == NULL) {
workerLocker.Unlock();
// schedule the job
status_t error = GetWorker()->ScheduleJob(
new(std::nothrow) ResolveValueNodeValueJob(fDebuggerInterface,
fArchitecture, fCpuState, fTypeInformation, fContainer,
parentNode));
if (error != B_OK) {
// scheduling failed -- set the value to invalid
parentNode->SetLocationAndValue(NULL, NULL, error);
return error;
}
}
// wait for the job to finish
workerLocker.Unlock();
containerLocker.Unlock();
switch (WaitFor(jobKey)) {
case JOB_DEPENDENCY_SUCCEEDED:
case JOB_DEPENDENCY_NOT_FOUND:
// "Not found" can happen due to a race condition between
// unlocking the worker and starting to wait.
break;
case JOB_DEPENDENCY_ACTIVE:
return B_OK;
case JOB_DEPENDENCY_FAILED:
case JOB_DEPENDENCY_ABORTED:
default:
return B_ERROR;
}
containerLocker.Lock();
// now there should be a value for the node
nodeResolutionState = parentNode->LocationAndValueResolutionState();
return nodeResolutionState != VALUE_NODE_UNRESOLVED
? nodeResolutionState : B_ERROR;
}
RetrieveMemoryBlockJob::RetrieveMemoryBlockJob(Team* team,
TeamMemory* teamMemory, TeamMemoryBlock* memoryBlock)
:
fKey(memoryBlock, JOB_TYPE_GET_MEMORY_BLOCK),
fTeam(team),
fTeamMemory(teamMemory),
fMemoryBlock(memoryBlock)
{
fTeamMemory->AcquireReference();
fMemoryBlock->AcquireReference();
}
RetrieveMemoryBlockJob::~RetrieveMemoryBlockJob()
{
fTeamMemory->ReleaseReference();
fMemoryBlock->ReleaseReference();
}
const JobKey&
RetrieveMemoryBlockJob::Key() const
{
return fKey;
}
status_t
RetrieveMemoryBlockJob::Do()
{
ssize_t result = fTeamMemory->ReadMemory(fMemoryBlock->BaseAddress(),
fMemoryBlock->Data(), fMemoryBlock->Size());
if (result < 0)
return result;
uint32 protection = 0;
uint32 locking = 0;
status_t error = get_memory_properties(fTeam->ID(),
(const void *)fMemoryBlock->BaseAddress(), &protection, &locking);
if (error != B_OK)
return error;
fMemoryBlock->SetWritable((protection & B_WRITE_AREA) != 0);
fMemoryBlock->MarkValid();
return B_OK;
}

View File

@ -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'
};

View File

@ -46,7 +46,7 @@
#include "ValueNodeContainer.h"
#include "Variable.h"
#include "WatchpointManager.h"
#include "WatchpointSetting.h"
// #pragma mark - ImageHandler
@ -1583,21 +1583,6 @@ TeamDebugger::_LoadSettings()
breakpointSetting->IsEnabled());
}
// create the saved watchpoints;
for (int32 i = 0; const WatchpointSetting* watchpointSetting
= fTeamSettings.WatchpointAt(i); i++) {
Watchpoint* watchpoint = new(std::nothrow) Watchpoint(
watchpointSetting->Address(), watchpointSetting->Type(),
watchpointSetting->Length());
if (watchpoint == NULL)
return;
BReference<Watchpoint> watchpointReference(watchpoint, true);
// install it
fWatchpointManager->InstallWatchpoint(watchpoint,
watchpointSetting->IsEnabled());
}
const TeamUiSettings* uiSettings = fTeamSettings.UiSettingFor(
fUserInterface->ID());
if (uiSettings != NULL)

View File

@ -74,6 +74,12 @@ WatchpointManager::InstallWatchpoint(Watchpoint* watchpoint,
watchpoint->SetInstalled(false);
}
if (error == B_OK) {
if (fTeam->WatchpointAtAddress(watchpoint->Address()) == NULL)
fTeam->AddWatchpoint(watchpoint);
fTeam->NotifyWatchpointChanged(watchpoint);
}
return error;
}
@ -84,12 +90,16 @@ WatchpointManager::UninstallWatchpoint(Watchpoint* watchpoint)
AutoLocker<BLocker> installLocker(fLock);
AutoLocker<Team> teamLocker(fTeam);
fTeam->RemoveWatchpoint(watchpoint);
if (!watchpoint->IsInstalled())
return;
status_t error = fDebuggerInterface->UninstallWatchpoint(
watchpoint->Address());
if (error == B_OK)
if (error == B_OK) {
watchpoint->SetInstalled(false);
}
fTeam->NotifyWatchpointChanged(watchpoint);
}
}

View File

@ -0,0 +1,56 @@
/*
* Copyright 2012, Rene Gollent, rene@gollent.com.
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "Jobs.h"
#include <AutoLocker.h>
#include "CpuState.h"
#include "DebuggerInterface.h"
#include "Team.h"
#include "Thread.h"
GetCpuStateJob::GetCpuStateJob(DebuggerInterface* debuggerInterface,
Thread* thread)
:
fKey(thread, JOB_TYPE_GET_CPU_STATE),
fDebuggerInterface(debuggerInterface),
fThread(thread)
{
fThread->AcquireReference();
}
GetCpuStateJob::~GetCpuStateJob()
{
fThread->ReleaseReference();
}
const JobKey&
GetCpuStateJob::Key() const
{
return fKey;
}
status_t
GetCpuStateJob::Do()
{
CpuState* state;
status_t error = fDebuggerInterface->GetCpuState(fThread->ID(), state);
if (error != B_OK)
return error;
BReference<CpuState> reference(state, true);
AutoLocker<Team> locker(fThread->GetTeam());
if (fThread->State() == THREAD_STATE_STOPPED)
fThread->SetCpuState(state);
return B_OK;
}

View File

@ -0,0 +1,116 @@
/*
* Copyright 2012, Rene Gollent, rene@gollent.com.
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "Jobs.h"
#include <AutoLocker.h>
#include "Architecture.h"
#include "CpuState.h"
#include "DebuggerInterface.h"
#include "ImageDebugInfo.h"
#include "StackTrace.h"
#include "Thread.h"
#include "Team.h"
GetStackTraceJob::GetStackTraceJob(DebuggerInterface* debuggerInterface,
Architecture* architecture, Thread* thread)
:
fKey(thread, JOB_TYPE_GET_STACK_TRACE),
fDebuggerInterface(debuggerInterface),
fArchitecture(architecture),
fThread(thread)
{
fThread->AcquireReference();
fCpuState = fThread->GetCpuState();
if (fCpuState != NULL)
fCpuState->AcquireReference();
}
GetStackTraceJob::~GetStackTraceJob()
{
if (fCpuState != NULL)
fCpuState->ReleaseReference();
fThread->ReleaseReference();
}
const JobKey&
GetStackTraceJob::Key() const
{
return fKey;
}
status_t
GetStackTraceJob::Do()
{
if (fCpuState == NULL)
return B_BAD_VALUE;
// get the stack trace
StackTrace* stackTrace;
status_t error = fArchitecture->CreateStackTrace(fThread->GetTeam(), this,
fCpuState, stackTrace);
if (error != B_OK)
return error;
BReference<StackTrace> stackTraceReference(stackTrace, true);
// set the stack trace, unless something has changed
AutoLocker<Team> locker(fThread->GetTeam());
if (fThread->GetCpuState() == fCpuState)
fThread->SetStackTrace(stackTrace);
return B_OK;
}
status_t
GetStackTraceJob::GetImageDebugInfo(Image* image, ImageDebugInfo*& _info)
{
AutoLocker<Team> teamLocker(fThread->GetTeam());
while (image->GetImageDebugInfo() == NULL) {
// schedule a job, if not loaded
ImageDebugInfo* info;
status_t error = LoadImageDebugInfoJob::ScheduleIfNecessary(GetWorker(),
image, &info);
if (error != B_OK)
return error;
if (info != NULL) {
_info = info;
return B_OK;
}
teamLocker.Unlock();
// wait for the job to finish
switch (WaitFor(SimpleJobKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO))) {
case JOB_DEPENDENCY_SUCCEEDED:
case JOB_DEPENDENCY_NOT_FOUND:
// "Not found" can happen due to a race condition between
// unlocking the worker and starting to wait.
break;
case JOB_DEPENDENCY_FAILED:
case JOB_DEPENDENCY_ABORTED:
default:
return B_ERROR;
}
teamLocker.Lock();
}
_info = image->GetImageDebugInfo();
_info->AcquireReference();
return B_OK;
}

View File

@ -0,0 +1,62 @@
/*
* Copyright 2012, Rene Gollent, rene@gollent.com.
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "Jobs.h"
#include <AutoLocker.h>
#include "CpuState.h"
#include "DebuggerInterface.h"
#include "Team.h"
#include "Thread.h"
GetThreadStateJob::GetThreadStateJob(DebuggerInterface* debuggerInterface,
Thread* thread)
:
fKey(thread, JOB_TYPE_GET_THREAD_STATE),
fDebuggerInterface(debuggerInterface),
fThread(thread)
{
fThread->AcquireReference();
}
GetThreadStateJob::~GetThreadStateJob()
{
fThread->ReleaseReference();
}
const JobKey&
GetThreadStateJob::Key() const
{
return fKey;
}
status_t
GetThreadStateJob::Do()
{
CpuState* state = NULL;
status_t error = fDebuggerInterface->GetCpuState(fThread->ID(), state);
BReference<CpuState> reference(state, true);
AutoLocker<Team> locker(fThread->GetTeam());
if (fThread->State() != THREAD_STATE_UNKNOWN)
return B_OK;
if (error == B_OK) {
fThread->SetState(THREAD_STATE_STOPPED);
fThread->SetCpuState(state);
} else if (error == B_BAD_THREAD_STATE) {
fThread->SetState(THREAD_STATE_RUNNING);
} else
return error;
return B_OK;
}

View File

@ -0,0 +1,106 @@
/*
* Copyright 2012, Rene Gollent, rene@gollent.com.
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "Jobs.h"
#include <AutoLocker.h>
#include "Image.h"
#include "ImageDebugInfo.h"
#include "TeamDebugInfo.h"
#include "Team.h"
LoadImageDebugInfoJob::LoadImageDebugInfoJob(Image* image)
:
fKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO),
fImage(image)
{
fImage->AcquireReference();
}
LoadImageDebugInfoJob::~LoadImageDebugInfoJob()
{
fImage->ReleaseReference();
}
const JobKey&
LoadImageDebugInfoJob::Key() const
{
return fKey;
}
status_t
LoadImageDebugInfoJob::Do()
{
// get an image info for the image
AutoLocker<Team> locker(fImage->GetTeam());
ImageInfo imageInfo(fImage->Info());
locker.Unlock();
// create the debug info
ImageDebugInfo* debugInfo;
status_t error = fImage->GetTeam()->DebugInfo()->LoadImageDebugInfo(
imageInfo, fImage->ImageFile(), debugInfo);
// set the result
locker.Lock();
if (error == B_OK) {
error = fImage->SetImageDebugInfo(debugInfo, IMAGE_DEBUG_INFO_LOADED);
debugInfo->ReleaseReference();
} else
fImage->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_UNAVAILABLE);
return error;
}
/*static*/ status_t
LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image,
ImageDebugInfo** _imageDebugInfo)
{
AutoLocker<Team> teamLocker(image->GetTeam());
// If already loaded, we're done.
if (image->GetImageDebugInfo() != NULL) {
if (_imageDebugInfo != NULL) {
*_imageDebugInfo = image->GetImageDebugInfo();
(*_imageDebugInfo)->AcquireReference();
}
return B_OK;
}
// If already loading, the caller has to wait, if desired.
if (image->ImageDebugInfoState() == IMAGE_DEBUG_INFO_LOADING) {
if (_imageDebugInfo != NULL)
*_imageDebugInfo = NULL;
return B_OK;
}
// If an earlier load attempt failed, bail out.
if (image->ImageDebugInfoState() != IMAGE_DEBUG_INFO_NOT_LOADED)
return B_ERROR;
// schedule a job
LoadImageDebugInfoJob* job = new(std::nothrow) LoadImageDebugInfoJob(image);
if (job == NULL)
return B_NO_MEMORY;
status_t error = worker->ScheduleJob(job);
if (error != B_OK) {
image->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_UNAVAILABLE);
return error;
}
image->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_LOADING);
if (_imageDebugInfo != NULL)
*_imageDebugInfo = NULL;
return B_OK;
}

View File

@ -0,0 +1,93 @@
/*
* Copyright 2012, Rene Gollent, rene@gollent.com.
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "Jobs.h"
#include <AutoLocker.h>
#include "Architecture.h"
#include "DebuggerInterface.h"
#include "DisassembledCode.h"
#include "Function.h"
#include "FunctionInstance.h"
#include "FileSourceCode.h"
#include "Team.h"
#include "TeamDebugInfo.h"
LoadSourceCodeJob::LoadSourceCodeJob(
DebuggerInterface* debuggerInterface, Architecture* architecture,
Team* team, FunctionInstance* functionInstance, bool loadForFunction)
:
fKey(functionInstance, JOB_TYPE_LOAD_SOURCE_CODE),
fDebuggerInterface(debuggerInterface),
fArchitecture(architecture),
fTeam(team),
fFunctionInstance(functionInstance),
fLoadForFunction(loadForFunction)
{
fFunctionInstance->AcquireReference();
}
LoadSourceCodeJob::~LoadSourceCodeJob()
{
fFunctionInstance->ReleaseReference();
}
const JobKey&
LoadSourceCodeJob::Key() const
{
return fKey;
}
status_t
LoadSourceCodeJob::Do()
{
// if requested, try loading the source code for the function
Function* function = fFunctionInstance->GetFunction();
if (fLoadForFunction) {
FileSourceCode* sourceCode;
status_t error = fTeam->DebugInfo()->LoadSourceCode(
function->SourceFile(), sourceCode);
AutoLocker<Team> locker(fTeam);
if (error == B_OK) {
function->SetSourceCode(sourceCode, FUNCTION_SOURCE_LOADED);
sourceCode->ReleaseReference();
return B_OK;
}
function->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE);
}
// Only try to load the function instance code, if it's not overridden yet.
AutoLocker<Team> locker(fTeam);
if (fFunctionInstance->SourceCodeState() != FUNCTION_SOURCE_LOADING)
return B_OK;
locker.Unlock();
// disassemble the function
DisassembledCode* sourceCode = NULL;
status_t error = fTeam->DebugInfo()->DisassembleFunction(fFunctionInstance,
sourceCode);
// set the result
locker.Lock();
if (error == B_OK) {
if (fFunctionInstance->SourceCodeState() == FUNCTION_SOURCE_LOADING) {
fFunctionInstance->SetSourceCode(sourceCode,
FUNCTION_SOURCE_LOADED);
sourceCode->ReleaseReference();
}
} else
fFunctionInstance->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE);
return error;
}

View File

@ -0,0 +1,254 @@
/*
* Copyright 2012, Rene Gollent, rene@gollent.com.
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "Jobs.h"
#include <AutoLocker.h>
#include "Architecture.h"
#include "CpuState.h"
#include "DebuggerInterface.h"
#include "TeamTypeInformation.h"
#include "Tracing.h"
#include "Value.h"
#include "ValueLoader.h"
#include "ValueLocation.h"
#include "ValueNode.h"
#include "ValueNodeContainer.h"
ResolveValueNodeValueJob::ResolveValueNodeValueJob(
DebuggerInterface* debuggerInterface, Architecture* architecture,
CpuState* cpuState, TeamTypeInformation* typeInformation,
ValueNodeContainer* container, ValueNode* valueNode)
:
fKey(valueNode, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE),
fDebuggerInterface(debuggerInterface),
fArchitecture(architecture),
fCpuState(cpuState),
fTypeInformation(typeInformation),
fContainer(container),
fValueNode(valueNode)
{
if (fCpuState != NULL)
fCpuState->AcquireReference();
fContainer->AcquireReference();
fValueNode->AcquireReference();
}
ResolveValueNodeValueJob::~ResolveValueNodeValueJob()
{
if (fCpuState != NULL)
fCpuState->ReleaseReference();
fContainer->ReleaseReference();
fValueNode->ReleaseReference();
}
const JobKey&
ResolveValueNodeValueJob::Key() const
{
return fKey;
}
status_t
ResolveValueNodeValueJob::Do()
{
// check whether the node still belongs to the container
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
if (fValueNode->Container() != fContainer)
return B_BAD_VALUE;
// if already resolved, we're done
status_t nodeResolutionState
= fValueNode->LocationAndValueResolutionState();
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
return nodeResolutionState;
containerLocker.Unlock();
// resolve
status_t error = _ResolveNodeValue();
if (error != B_OK) {
nodeResolutionState = fValueNode->LocationAndValueResolutionState();
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
return nodeResolutionState;
containerLocker.Lock();
fValueNode->SetLocationAndValue(NULL, NULL, error);
containerLocker.Unlock();
}
return error;
}
status_t
ResolveValueNodeValueJob::_ResolveNodeValue()
{
// get the node child and parent node
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
ValueNodeChild* nodeChild = fValueNode->NodeChild();
BReference<ValueNodeChild> nodeChildReference(nodeChild);
ValueNode* parentNode = nodeChild->Parent();
BReference<ValueNode> parentNodeReference(parentNode);
// Check whether the node child location has been resolved already
// (successfully).
status_t nodeChildResolutionState = nodeChild->LocationResolutionState();
bool nodeChildDone = nodeChildResolutionState != VALUE_NODE_UNRESOLVED;
if (nodeChildDone && nodeChildResolutionState != B_OK)
return nodeChildResolutionState;
// If the child node location has not been resolved yet, check whether the
// parent node location and value have been resolved already (successfully).
bool parentDone = true;
if (!nodeChildDone && parentNode != NULL) {
status_t parentResolutionState
= parentNode->LocationAndValueResolutionState();
parentDone = parentResolutionState != VALUE_NODE_UNRESOLVED;
if (parentDone && parentResolutionState != B_OK)
return parentResolutionState;
}
containerLocker.Unlock();
// resolve the parent node location and value, if necessary
if (!parentDone) {
status_t error = _ResolveParentNodeValue(parentNode);
if (error != B_OK) {
TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
"node: %p (\"%s\"): _ResolveParentNodeValue(%p) failed\n",
fValueNode, fValueNode->Name().String(), parentNode);
return error;
}
if (State() == JOB_STATE_WAITING)
return B_OK;
}
// resolve the node child location, if necessary
if (!nodeChildDone) {
status_t error = _ResolveNodeChildLocation(nodeChild);
if (error != B_OK) {
TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
"node: %p (\"%s\"): _ResolveNodeChildLocation(%p) failed\n",
fValueNode, fValueNode->Name().String(), nodeChild);
return error;
}
}
// resolve the node location and value
ValueLoader valueLoader(fArchitecture, fDebuggerInterface,
fTypeInformation, fCpuState);
ValueLocation* location;
Value* value;
status_t error = fValueNode->ResolvedLocationAndValue(&valueLoader,
location, value);
if (error != B_OK) {
TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
"node: %p (\"%s\"): fValueNode->ResolvedLocationAndValue() "
"failed\n", fValueNode, fValueNode->Name().String());
return error;
}
BReference<ValueLocation> locationReference(location, true);
BReference<Value> valueReference(value, true);
// set location and value on the node
containerLocker.Lock();
status_t nodeResolutionState
= fValueNode->LocationAndValueResolutionState();
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
return nodeResolutionState;
fValueNode->SetLocationAndValue(location, value, B_OK);
containerLocker.Unlock();
return B_OK;
}
status_t
ResolveValueNodeValueJob::_ResolveNodeChildLocation(ValueNodeChild* nodeChild)
{
// resolve the location
ValueLoader valueLoader(fArchitecture, fDebuggerInterface,
fTypeInformation, fCpuState);
ValueLocation* location = NULL;
status_t error = nodeChild->ResolveLocation(&valueLoader, location);
BReference<ValueLocation> locationReference(location, true);
// set the location on the node child
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
status_t nodeChildResolutionState = nodeChild->LocationResolutionState();
if (nodeChildResolutionState == VALUE_NODE_UNRESOLVED)
nodeChild->SetLocation(location, error);
else
error = nodeChildResolutionState;
return error;
}
status_t
ResolveValueNodeValueJob::_ResolveParentNodeValue(ValueNode* parentNode)
{
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
if (parentNode->Container() != fContainer)
return B_BAD_VALUE;
// if the parent node already has a value, we're done
status_t nodeResolutionState
= parentNode->LocationAndValueResolutionState();
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
return nodeResolutionState;
// check whether a job is already in progress
AutoLocker<Worker> workerLocker(GetWorker());
SimpleJobKey jobKey(parentNode, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE);
if (GetWorker()->GetJob(jobKey) == NULL) {
workerLocker.Unlock();
// schedule the job
status_t error = GetWorker()->ScheduleJob(
new(std::nothrow) ResolveValueNodeValueJob(fDebuggerInterface,
fArchitecture, fCpuState, fTypeInformation, fContainer,
parentNode));
if (error != B_OK) {
// scheduling failed -- set the value to invalid
parentNode->SetLocationAndValue(NULL, NULL, error);
return error;
}
}
// wait for the job to finish
workerLocker.Unlock();
containerLocker.Unlock();
switch (WaitFor(jobKey)) {
case JOB_DEPENDENCY_SUCCEEDED:
case JOB_DEPENDENCY_NOT_FOUND:
// "Not found" can happen due to a race condition between
// unlocking the worker and starting to wait.
break;
case JOB_DEPENDENCY_ACTIVE:
return B_OK;
case JOB_DEPENDENCY_FAILED:
case JOB_DEPENDENCY_ABORTED:
default:
return B_ERROR;
}
containerLocker.Lock();
// now there should be a value for the node
nodeResolutionState = parentNode->LocationAndValueResolutionState();
return nodeResolutionState != VALUE_NODE_UNRESOLVED
? nodeResolutionState : B_ERROR;
}

View File

@ -0,0 +1,62 @@
/*
* Copyright 2012, Rene Gollent, rene@gollent.com.
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "Jobs.h"
#include <AutoLocker.h>
#include <memory_private.h>
#include "Team.h"
#include "TeamMemory.h"
#include "TeamMemoryBlock.h"
RetrieveMemoryBlockJob::RetrieveMemoryBlockJob(Team* team,
TeamMemory* teamMemory, TeamMemoryBlock* memoryBlock)
:
fKey(memoryBlock, JOB_TYPE_GET_MEMORY_BLOCK),
fTeam(team),
fTeamMemory(teamMemory),
fMemoryBlock(memoryBlock)
{
fTeamMemory->AcquireReference();
fMemoryBlock->AcquireReference();
}
RetrieveMemoryBlockJob::~RetrieveMemoryBlockJob()
{
fTeamMemory->ReleaseReference();
fMemoryBlock->ReleaseReference();
}
const JobKey&
RetrieveMemoryBlockJob::Key() const
{
return fKey;
}
status_t
RetrieveMemoryBlockJob::Do()
{
ssize_t result = fTeamMemory->ReadMemory(fMemoryBlock->BaseAddress(),
fMemoryBlock->Data(), fMemoryBlock->Size());
if (result < 0)
return result;
uint32 protection = 0;
uint32 locking = 0;
status_t error = get_memory_properties(fTeam->ID(),
(const void *)fMemoryBlock->BaseAddress(), &protection, &locking);
if (error != B_OK)
return error;
fMemoryBlock->SetWritable((protection & B_WRITE_AREA) != 0);
fMemoryBlock->MarkValid();
return B_OK;
}

View File

@ -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();

View File

@ -145,6 +145,8 @@ public:
TargetAddressRange range,
BObjectList<Watchpoint>& watchpoints)
const;
const WatchpointList& Watchpoints() const
{ return fWatchpoints; }
status_t GetStatementAtAddress(target_addr_t address,
FunctionInstance*& _function,
@ -187,7 +189,6 @@ private:
typedef BObjectList<Breakpoint> BreakpointList;
typedef DoublyLinkedList<Listener> ListenerList;
typedef BObjectList<Watchpoint> WatchpointList;
private:
void _NotifyThreadAdded(Thread* thread);

View File

@ -6,6 +6,7 @@
#define WATCHPOINT_H
#include <ObjectList.h>
#include <Referenceable.h>
#include "types/Types.h"
@ -49,4 +50,7 @@ private:
};
typedef BObjectList<Watchpoint> WatchpointList;
#endif // WATCHPOINT_H

View File

@ -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
{

View File

@ -15,7 +15,6 @@ class BMessage;
class Team;
class BreakpointSetting;
class TeamUiSettings;
class WatchpointSetting;
class TeamSettings {
@ -34,9 +33,6 @@ public:
int32 CountBreakpoints() const;
const BreakpointSetting* BreakpointAt(int32 index) const;
int32 CountWatchpoints() const;
const WatchpointSetting* WatchpointAt(int32 index) const;
int32 CountUiSettings() const;
const TeamUiSettings* UiSettingAt(int32 index) const;
const TeamUiSettings* UiSettingFor(const char* id) const;
@ -48,14 +44,12 @@ public:
private:
typedef BObjectList<BreakpointSetting> BreakpointList;
typedef BObjectList<TeamUiSettings> UiSettingsList;
typedef BObjectList<WatchpointSetting> WatchpointList;
private:
void _Unset();
private:
BreakpointList fBreakpoints;
WatchpointList fWatchpoints;
UiSettingsList fUiSettings;
BString fTeamName;
};

View File

@ -1,100 +0,0 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2012, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
#include "WatchpointSetting.h"
#include <Message.h>
#include "Watchpoint.h"
WatchpointSetting::WatchpointSetting()
:
fAddress(0),
fType(0),
fLength(0),
fEnabled(false)
{
}
WatchpointSetting::WatchpointSetting(const WatchpointSetting& other)
:
fAddress(other.fAddress),
fType(other.fType),
fLength(other.fLength),
fEnabled(other.fEnabled)
{
}
WatchpointSetting::~WatchpointSetting()
{
}
status_t
WatchpointSetting::SetTo(const Watchpoint& watchpoint, bool enabled)
{
fAddress = watchpoint.Address();
fType = watchpoint.Type();
fLength = watchpoint.Length();
fEnabled = enabled;
return B_OK;
}
status_t
WatchpointSetting::SetTo(const BMessage& archive)
{
if (archive.FindUInt64("address", &fAddress) != B_OK)
fAddress = 0;
if (archive.FindUInt32("type", &fType) != B_OK)
fType = 0;
if (archive.FindInt32("length", &fLength) != B_OK)
fLength = 0;
if (archive.FindBool("enabled", &fEnabled) != B_OK)
fEnabled = false;
return B_OK;
}
status_t
WatchpointSetting::WriteTo(BMessage& archive) const
{
archive.MakeEmpty();
status_t error;
if ((error = archive.AddUInt64("address", fAddress)) != B_OK
|| (error = archive.AddUInt32("type", fType)) != B_OK
|| (error = archive.AddInt32("length", fLength)) != B_OK
|| (error = archive.AddBool("enabled", fEnabled)) != B_OK) {
return error;
}
return B_OK;
}
WatchpointSetting&
WatchpointSetting::operator=(const WatchpointSetting& other)
{
if (this == &other)
return *this;
fAddress = other.fAddress;
fType = other.fType;
fLength = other.fLength;
fEnabled = other.fEnabled;
return *this;
}

View File

@ -1,46 +0,0 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2012, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
#ifndef WATCHPOINT_SETTING_H
#define WATCHPOINT_SETTING_H
#include <String.h>
#include "types/Types.h"
class BMessage;
class Watchpoint;
class WatchpointSetting {
public:
WatchpointSetting();
WatchpointSetting(
const WatchpointSetting& other);
~WatchpointSetting();
status_t SetTo(const Watchpoint& watchpoint,
bool enabled);
status_t SetTo(const BMessage& archive);
status_t WriteTo(BMessage& archive) const;
target_addr_t Address() const { return fAddress; }
uint32 Type() const { return fType; }
int32 Length() const { return fLength; }
bool IsEnabled() const { return fEnabled; }
WatchpointSetting& operator=(const WatchpointSetting& other);
private:
target_addr_t fAddress;
uint32 fType;
int32 fLength;
bool fEnabled;
};
#endif // BREAKPOINT_SETTING_H

View File

@ -18,9 +18,10 @@
#include "GuiSettingsUtils.h"
#include "LocatableFile.h"
#include "table/TableColumns.h"
#include "TargetAddressTableColumn.h"
#include "Team.h"
#include "UserBreakpoint.h"
#include "TargetAddressTableColumn.h"
#include "Watchpoint.h"
// #pragma mark - BreakpointsTableModel
@ -32,16 +33,18 @@ public:
:
fTeam(team)
{
Update(NULL);
UpdateBreakpoint(NULL);
UpdateWatchpoint(NULL);
}
~BreakpointsTableModel()
{
fTeam = NULL;
Update(NULL);
UpdateBreakpoint(NULL);
UpdateWatchpoint(NULL);
}
bool Update(UserBreakpoint* changedBreakpoint)
bool UpdateBreakpoint(UserBreakpoint* changedBreakpoint)
{
if (fTeam == NULL) {
for (int32 i = 0;
@ -93,6 +96,59 @@ public:
return true;
}
bool UpdateWatchpoint(Watchpoint* changedWatchpoint)
{
if (fTeam == NULL) {
for (int32 i = 0;
Watchpoint* watchpoint = fWatchpoints.ItemAt(i);
i++) {
watchpoint->ReleaseReference();
}
fWatchpoints.MakeEmpty();
return true;
}
AutoLocker<Team> locker(fTeam);
int32 breakpointCount = fBreakpoints.CountItems();
int32 index = 0;
int32 teamIndex = 0;
Watchpoint* newWatchpoint = fTeam->WatchpointAt(teamIndex);
// remove no longer existing breakpoints
while (Watchpoint* oldWatchpoint = fWatchpoints.ItemAt(index)) {
if (oldWatchpoint == newWatchpoint) {
if (oldWatchpoint == changedWatchpoint)
NotifyRowsChanged(index + breakpointCount, 1);
index++;
teamIndex++;
newWatchpoint = fTeam->WatchpointAt(teamIndex);
} else {
// TODO: Not particularly efficient!
fWatchpoints.RemoveItemAt(index);
oldWatchpoint->ReleaseReference();
NotifyRowsRemoved(index + breakpointCount, 1);
}
}
// add new breakpoints
int32 countBefore = fWatchpoints.CountItems();
while (newWatchpoint != NULL) {
if (!fWatchpoints.AddItem(newWatchpoint))
return false;
newWatchpoint->AcquireReference();
teamIndex++;
newWatchpoint = fTeam->WatchpointAt(teamIndex);
}
int32 count = fWatchpoints.CountItems();
if (count > countBefore)
NotifyRowsAdded(countBefore + breakpointCount, count - countBefore);
return true;
}
virtual int32 CountColumns() const
{
return 5;
@ -100,10 +156,33 @@ public:
virtual int32 CountRows() const
{
return fBreakpoints.CountItems();
return fBreakpoints.CountItems() + fWatchpoints.CountItems();
}
virtual bool GetValueAt(int32 rowIndex, int32 columnIndex, BVariant& value)
{
int32 breakpointCount = fBreakpoints.CountItems();
if (rowIndex < breakpointCount)
return _GetBreakpointValueAt(rowIndex, columnIndex, value);
return _GetWatchpointValueAt(rowIndex - breakpointCount, columnIndex,
value);
}
UserBreakpoint* BreakpointAt(int32 index) const
{
return fBreakpoints.ItemAt(index);
}
Watchpoint* WatchpointAt(int32 index) const
{
return fWatchpoints.ItemAt(index - fBreakpoints.CountItems());
}
private:
bool _GetBreakpointValueAt(int32 rowIndex, int32 columnIndex,
BVariant &value)
{
UserBreakpoint* breakpoint = fBreakpoints.ItemAt(rowIndex);
if (breakpoint == NULL)
@ -145,14 +224,36 @@ public:
}
}
UserBreakpoint* BreakpointAt(int32 index) const
bool _GetWatchpointValueAt(int32 rowIndex, int32 columnIndex,
BVariant& value)
{
return fBreakpoints.ItemAt(index);
Watchpoint* watchpoint = fWatchpoints.ItemAt(rowIndex);
if (watchpoint == NULL)
return false;
switch (columnIndex) {
case 0:
value.SetTo((int32)watchpoint->IsEnabled());
return true;
case 1:
value.SetTo("Watchpoint");
return true;
case 2:
return false;
case 3:
return false;
case 4:
value.SetTo(watchpoint->Address());
return true;
default:
return false;
}
}
private:
Team* fTeam;
BObjectList<UserBreakpoint> fBreakpoints;
BObjectList<Watchpoint> fWatchpoints;
};
@ -202,7 +303,8 @@ BreakpointListView::UnsetListener()
void
BreakpointListView::SetBreakpoint(UserBreakpoint* breakpoint)
BreakpointListView::SetBreakpoint(UserBreakpoint* breakpoint,
Watchpoint* watchpoint)
{
if (breakpoint == fBreakpoint)
return;
@ -232,7 +334,14 @@ BreakpointListView::SetBreakpoint(UserBreakpoint* breakpoint)
void
BreakpointListView::UserBreakpointChanged(UserBreakpoint* breakpoint)
{
fBreakpointsTableModel->Update(breakpoint);
fBreakpointsTableModel->UpdateBreakpoint(breakpoint);
}
void
BreakpointListView::WatchpointChanged(Watchpoint* watchpoint)
{
fBreakpointsTableModel->UpdateWatchpoint(watchpoint);
}
@ -271,8 +380,13 @@ BreakpointListView::TableSelectionChanged(Table* table)
TableSelectionModel* selectionModel = table->SelectionModel();
UserBreakpoint* breakpoint = fBreakpointsTableModel->BreakpointAt(
selectionModel->RowAt(0));
fListener->BreakpointSelectionChanged(breakpoint);
if (breakpoint != NULL)
fListener->BreakpointSelectionChanged(breakpoint);
else {
Watchpoint* watchpoint = fBreakpointsTableModel->WatchpointAt(
selectionModel->RowAt(0));
fListener->WatchpointSelectionChanged(watchpoint);
}
}

View File

@ -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;
};

View File

@ -68,20 +68,26 @@ BreakpointsView::UnsetListener()
void
BreakpointsView::SetBreakpoint(UserBreakpoint* breakpoint)
BreakpointsView::SetBreakpoint(UserBreakpoint* breakpoint, Watchpoint* watchpoint)
{
if (breakpoint == fBreakpoint)
if (breakpoint == fBreakpoint && watchpoint == fWatchpoint)
return;
if (fWatchpoint != NULL)
fWatchpoint->ReleaseReference();
if (fBreakpoint != NULL)
fBreakpoint->ReleaseReference();
fWatchpoint = watchpoint;
fBreakpoint = breakpoint;
if (fBreakpoint != NULL)
fBreakpoint->AcquireReference();
else if (fWatchpoint != NULL)
fWatchpoint->AcquireReference();
fListView->SetBreakpoint(breakpoint);
fListView->SetBreakpoint(breakpoint, watchpoint);
_UpdateButtons();
}
@ -96,21 +102,49 @@ BreakpointsView::UserBreakpointChanged(UserBreakpoint* breakpoint)
}
void
BreakpointsView::WatchpointChanged(Watchpoint* watchpoint)
{
fListView->WatchpointChanged(watchpoint);
_UpdateButtons();
}
void
BreakpointsView::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_ENABLE_BREAKPOINT:
if (fListener != NULL && fBreakpoint != NULL)
fListener->SetBreakpointEnabledRequested(fBreakpoint, true);
if (fListener != NULL) {
if (fBreakpoint != NULL) {
fListener->SetBreakpointEnabledRequested(fBreakpoint,
true);
} else if (fWatchpoint != NULL) {
fListener->SetWatchpointEnabledRequested(fWatchpoint,
true);
}
}
break;
case MSG_DISABLE_BREAKPOINT:
if (fListener != NULL && fBreakpoint != NULL)
fListener->SetBreakpointEnabledRequested(fBreakpoint, false);
if (fListener != NULL) {
if (fBreakpoint != NULL) {
fListener->SetBreakpointEnabledRequested(fBreakpoint,
false);
} else if (fWatchpoint != NULL) {
fListener->SetWatchpointEnabledRequested(fWatchpoint,
false);
}
}
break;
case MSG_CLEAR_BREAKPOINT:
if (fListener != NULL && fBreakpoint != NULL)
fListener->ClearBreakpointRequested(fBreakpoint);
if (fListener != NULL) {
if (fBreakpoint != NULL) {
fListener->ClearBreakpointRequested(fBreakpoint);
} else if (fWatchpoint != NULL) {
fListener->ClearWatchpointRequested(fWatchpoint);
}
}
break;
default:
BGroupView::MessageReceived(message);
@ -159,6 +193,14 @@ BreakpointsView::BreakpointSelectionChanged(UserBreakpoint* breakpoint)
}
void
BreakpointsView::WatchpointSelectionChanged(Watchpoint* watchpoint)
{
if (fListener != NULL)
fListener->WatchpointSelectionChanged(watchpoint);
}
void
BreakpointsView::_Init()
{
@ -182,8 +224,19 @@ BreakpointsView::_UpdateButtons()
{
AutoLocker<Team> teamLocker(fTeam);
bool enabled = false;
bool valid = false;
if (fBreakpoint != NULL && fBreakpoint->IsValid()) {
if (fBreakpoint->IsEnabled()) {
valid = true;
enabled = fBreakpoint->IsEnabled();
} else if (fWatchpoint != NULL) {
valid = true;
enabled = fWatchpoint->IsEnabled();
}
if (valid) {
if (enabled) {
fToggleBreakpointButton->SetLabel("Disable");
fToggleBreakpointButton->SetMessage(
new BMessage(MSG_DISABLE_BREAKPOINT));

View File

@ -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;
};

View File

@ -44,6 +44,7 @@
#include "TypeComponentPath.h"
#include "UserInterface.h"
#include "Variable.h"
#include "WatchPromptWindow.h"
enum {
@ -247,6 +248,27 @@ TeamWindow::MessageReceived(BMessage* message)
break;
}
case MSG_SHOW_WATCH_VARIABLE_PROMPT:
{
target_addr_t address;
uint32 type;
int32 length;
if (message->FindUInt64("address", &address) != B_OK
|| message->FindUInt32("type", &type) != B_OK
|| message->FindInt32("length", &length) != B_OK) {
break;
}
try {
WatchPromptWindow* window = WatchPromptWindow::Create(address,
type, length, fListener);
window->Show();
} catch (...) {
// TODO: notify user
}
break;
}
case B_REFS_RECEIVED:
{
entry_ref locatedPath;
@ -334,6 +356,18 @@ TeamWindow::MessageReceived(BMessage* message)
break;
}
case MSG_WATCHPOINT_CHANGED:
{
Watchpoint* watchpoint;
if (message->FindPointer("watchpoint", (void**)&watchpoint) != B_OK)
break;
BReference<Watchpoint> watchpointReference(watchpoint, true);
_HandleWatchpointChanged(watchpoint);
break;
}
case MSG_FUNCTION_SOURCE_CODE_CHANGED:
{
_HandleSourceCodeChanged();
@ -562,6 +596,28 @@ TeamWindow::ClearBreakpointRequested(target_addr_t address)
}
void
TeamWindow::WatchpointSelectionChanged(Watchpoint* watchpoint)
{
fBreakpointsView->SetBreakpoint(NULL, watchpoint);
}
void
TeamWindow::SetWatchpointEnabledRequested(Watchpoint* watchpoint,
bool enabled)
{
fListener->SetWatchpointEnabledRequested(watchpoint, enabled);
}
void
TeamWindow::ClearWatchpointRequested(Watchpoint* watchpoint)
{
fListener->ClearWatchpointRequested(watchpoint);
}
void
TeamWindow::ValueNodeValueRequested(CpuState* cpuState,
ValueNodeContainer* container, ValueNode* valueNode)
@ -618,6 +674,18 @@ TeamWindow::UserBreakpointChanged(const Team::UserBreakpointEvent& event)
}
void
TeamWindow::WatchpointChanged(const Team::WatchpointEvent& event)
{
BMessage message(MSG_WATCHPOINT_CHANGED);
BReference<Watchpoint> watchpointReference(event.GetWatchpoint());
if (message.AddPointer("watchpoint", event.GetWatchpoint()) == B_OK
&& PostMessage(&message) == B_OK) {
watchpointReference.Detach();
}
}
void
TeamWindow::FunctionSourceCodeChanged(Function* function)
{
@ -901,7 +969,7 @@ TeamWindow::_SetActiveBreakpoint(UserBreakpoint* breakpoint)
_ScrollToActiveFunction();
}
fBreakpointsView->SetBreakpoint(fActiveBreakpoint);
fBreakpointsView->SetBreakpoint(fActiveBreakpoint, NULL);
}
@ -1244,6 +1312,13 @@ TeamWindow::_HandleUserBreakpointChanged(UserBreakpoint* breakpoint)
}
void
TeamWindow::_HandleWatchpointChanged(Watchpoint* watchpoint)
{
fBreakpointsView->WatchpointChanged(watchpoint);
}
void
TeamWindow::_HandleResolveMissingSourceFile(entry_ref& locatedPath)
{

View File

@ -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);

View File

@ -11,6 +11,8 @@
#include <new>
#include <debugger.h>
#include <Looper.h>
#include <PopUpMenu.h>
#include <ToolTip.h>
@ -1684,6 +1686,22 @@ VariablesView::MessageReceived(BMessage* message)
node->NodeChild()->SetNode(valueNode);
break;
}
case MSG_SHOW_WATCH_VARIABLE_PROMPT:
{
ModelNode* node = reinterpret_cast<ModelNode*>(
fVariableTable->SelectionModel()->NodeAt(0));
ValueLocation* location = node->NodeChild()->Location();
ValuePieceLocation piece = location->PieceAt(0);
if (piece.type != VALUE_PIECE_LOCATION_MEMORY)
break;
BMessage looperMessage(*message);
looperMessage.AddUInt64("address", piece.address);
looperMessage.AddInt32("length", piece.size);
looperMessage.AddUInt32("type", B_DATA_READ_WRITE_WATCHPOINT);
Looper()->PostMessage(&looperMessage);
break;
}
case MSG_VALUE_NODE_CHANGED:
{
ValueNodeChild* nodeChild;
@ -1977,34 +1995,45 @@ VariablesView::_GetContextActionsForNode(ModelNode* node,
if (location->PieceAt(0).type != VALUE_PIECE_LOCATION_MEMORY)
return B_OK;
BMessage* message = new BMessage(MSG_SHOW_INSPECTOR_WINDOW);
if (message == NULL)
return B_NO_MEMORY;
BMessage* message = NULL;
status_t result = _AddContextAction("Inspect", MSG_SHOW_INSPECTOR_WINDOW,
actions, message);
if (result != B_OK)
return result;
ObjectDeleter<BMessage> messageDeleter(message);
message->AddUInt64("address", location->PieceAt(0).address);
ActionMenuItem* item = new(std::nothrow) ActionMenuItem("Inspect",
message);
result = _AddContextAction("Cast as" B_UTF8_ELLIPSIS,
MSG_SHOW_TYPECAST_NODE_PROMPT, actions, message);
if (result != B_OK)
return result;
result = _AddContextAction("Watch" B_UTF8_ELLIPSIS,
MSG_SHOW_WATCH_VARIABLE_PROMPT, actions, message);
if (result != B_OK)
return result;
return B_OK;
}
status_t
VariablesView::_AddContextAction(const char* action, uint32 what,
ContextActionList* actions, BMessage*& _message)
{
_message = new BMessage(what);
if (_message == NULL)
return B_NO_MEMORY;
ObjectDeleter<BMessage> messageDeleter(_message);
ActionMenuItem* item = new(std::nothrow) ActionMenuItem(action,
_message);
if (item == NULL)
return B_NO_MEMORY;
messageDeleter.Detach();
ObjectDeleter<ActionMenuItem> actionDeleter(item);
if (!actions->AddItem(item))
return B_NO_MEMORY;
message = new(std::nothrow)BMessage(MSG_SHOW_TYPECAST_NODE_PROMPT);
if (message == NULL)
return B_NO_MEMORY;
item = new(std::nothrow) ActionMenuItem("Cast as" B_UTF8_ELLIPSIS,
message);
if (item == NULL)
return B_NO_MEMORY;
messageDeleter.Detach();
if (!actions->AddItem(item))
return B_NO_MEMORY;

View File

@ -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();

View File

@ -0,0 +1,154 @@
/*
* Copyright 2012, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
#include "WatchPromptWindow.h"
#include <Alert.h>
#include <Button.h>
#include <LayoutBuilder.h>
#include <Menu.h>
#include <MenuField.h>
#include <MenuItem.h>
#include <String.h>
#include <TextControl.h>
#include <ExpressionParser.h>
#include "MessageCodes.h"
#include "UserInterface.h"
#include "Watchpoint.h"
WatchPromptWindow::WatchPromptWindow(target_addr_t address, uint32 type,
int32 length, UserInterfaceListener* listener)
:
BWindow(BRect(), "Edit Watchpoint", B_FLOATING_WINDOW,
B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE),
fInitialAddress(address),
fInitialType(type),
fInitialLength(length),
fAddressInput(NULL),
fLengthInput(NULL),
fTypeField(NULL),
fListener(listener)
{
}
WatchPromptWindow::~WatchPromptWindow()
{
}
WatchPromptWindow*
WatchPromptWindow::Create(target_addr_t address, uint32 type, int32 length,
UserInterfaceListener* listener)
{
WatchPromptWindow* self = new WatchPromptWindow(address, type, length,
listener);
try {
self->_Init();
} catch (...) {
delete self;
throw;
}
return self;
}
void
WatchPromptWindow::_Init()
{
BString text;
text.SetToFormat("0x%" B_PRIx64, fInitialAddress);
fAddressInput = new BTextControl("Address:", text, NULL);
text.SetToFormat("%" B_PRId32, fInitialLength);
fLengthInput = new BTextControl("Length:", text, NULL);
BMenu* typeMenu = new BMenu("Watch Type");
typeMenu->AddItem(new BMenuItem("Read", NULL));
typeMenu->AddItem(new BMenuItem("Write", NULL));
typeMenu->AddItem(new BMenuItem("Read/Write", NULL));
fTypeField = new BMenuField("Type:", typeMenu);
BLayoutItem* labelItem = fTypeField->CreateLabelLayoutItem();
labelItem->View()->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
BLayoutBuilder::Group<>(this, B_VERTICAL)
.SetInsets(4.0f, 4.0f, 4.0f, 4.0f)
.AddGroup(B_HORIZONTAL, 4.0f)
.Add(fAddressInput)
.End()
.AddGroup(B_HORIZONTAL, 4.0f)
.Add(fLengthInput)
.Add(labelItem)
.Add(fTypeField->CreateMenuBarLayoutItem())
.End()
.AddGroup(B_HORIZONTAL, 4.0f)
.AddGlue()
.Add((fWatchButton = new BButton("Set",
new BMessage(MSG_SET_WATCHPOINT))))
.Add((fCancelButton = new BButton("Cancel",
new BMessage(B_QUIT_REQUESTED))))
.End();
fWatchButton->SetTarget(this);
fCancelButton->SetTarget(this);
fTypeField->Menu()->SetLabelFromMarked(true);
fTypeField->Menu()->ItemAt(fInitialType)->SetMarked(true);
}
void
WatchPromptWindow::Show()
{
CenterOnScreen();
BWindow::Show();
}
void
WatchPromptWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_SET_WATCHPOINT:
{
target_addr_t address = 0;
int32 length = 0;
ExpressionParser parser;
parser.SetSupportHexInput(true);
BString errorMessage;
try {
address = parser.EvaluateToInt64(fAddressInput->Text());
length = (int32)parser.EvaluateToInt64(fLengthInput->Text());
} catch(ParseException parseError) {
errorMessage.SetToFormat("Failed to parse data: %s",
parseError.message.String());
} catch(...) {
errorMessage.SetToFormat(
"Unknown error while parsing address");
}
if (!errorMessage.IsEmpty()) {
BAlert* alert = new(std::nothrow) BAlert("Edit Watchpoint",
errorMessage.String(), "Close");
if (alert != NULL)
alert->Go();
break;
}
fListener->ClearWatchpointRequested(fInitialAddress);
fListener->SetWatchpointRequested(address, fTypeField->Menu()
->IndexOf(fTypeField->Menu()->FindMarked()), length, true);
PostMessage(B_QUIT_REQUESTED);
break;
}
default:
BWindow::MessageReceived(message);
break;
}
}

View File

@ -0,0 +1,56 @@
/*
* Copyright 2012, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
#ifndef WATCH_PROMPT_WINDOW_H
#define WATCH_PROMPT_WINDOW_H
#include <Window.h>
#include "types/Types.h"
class BTextControl;
class Watchpoint;
class BMenuField;
class UserInterfaceListener;
class WatchPromptWindow : public BWindow
{
public:
// edit existing watchpoint
WatchPromptWindow(target_addr_t address,
uint32 type, int32 length,
UserInterfaceListener* listener);
~WatchPromptWindow();
static WatchPromptWindow* Create(target_addr_t address, uint32 type,
int32 length,
UserInterfaceListener* listener);
// throws
virtual void MessageReceived(BMessage* message);
virtual void Show();
private:
void _Init();
private:
target_addr_t fInitialAddress;
uint32 fInitialType;
int32 fInitialLength;
BTextControl* fAddressInput;
BTextControl* fLengthInput;
BMenuField* fTypeField;
UserInterfaceListener* fListener;
BButton* fWatchButton;
BButton* fCancelButton;
};
#endif // WATCH_PROMPT_WINDOW_H

View File

@ -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)

View File

@ -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);

View File

@ -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(

View File

@ -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";

View File

@ -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

View File

@ -10,21 +10,38 @@
#include <asm_defs.h>
#include "asm_offsets.h"
.text
/* int mmu_read_c1(void); */
FUNCTION(mmu_read_c1):
mrc p15, 0, r0, c1, c0, 0
bx lr
FUNCTION_END(mmu_read_c1)
/* void mmu_write_c1(int val); */
FUNCTION(mmu_write_c1):
mcr p15, 0, r0, c1, c0, 0
bx lr
FUNCTION_END(mmu_write_c1)
/* NOTE: the I bit in cpsr (bit 7) is *set* to disable... */
/* void arch_int_enable_interrupts(void) */
FUNCTION(arch_int_enable_interrupts):
mrs r0, cpsr
bic r0, r0, #(1<<7) /* clear the I bit */
bic r0, r0, #(1<<7)
msr cpsr_c, r0
bx lr
FUNCTION_END(arch_int_enable_interrupts)
/* int arch_int_disable_interrupts(void)
*/
/* int arch_int_disable_interrupts(void) */
FUNCTION(arch_int_disable_interrupts):
mrs r0, cpsr
orr r1, r0, #(1<<7)
@ -33,8 +50,7 @@ FUNCTION(arch_int_disable_interrupts):
FUNCTION_END(arch_int_disable_interrupts)
/* void arch_int_restore_interrupts(int oldState)
*/
/* void arch_int_restore_interrupts(int oldState) */
FUNCTION(arch_int_restore_interrupts):
mrs r1, cpsr
and r0, r0, #(1<<7)
@ -65,3 +81,57 @@ FUNCTION(arm_context_switch):
ldmfd sp!, { r0-r12, lr }
bx lr
FUNCTION_END(arm_context_switch)
/* addr_t arm_get_fsr(void); */
FUNCTION(arm_get_fsr):
mrc p15, 0, r0, c5, c0, 0 @ get FSR
bx lr
FUNCTION_END(arm_get_fsr)
/* addr_t arm_get_far(void); */
FUNCTION(arm_get_far):
mrc p15, 0, r0, c6, c0, 0 @ get FAR
bx lr
FUNCTION_END(arm_get_far)
/*! \fn void arch_debug_call_with_fault_handler(cpu_ent* cpu,
jmp_buf jumpBuffer, void (*function)(void*), void* parameter)
Called by debug_call_with_fault_handler() to do the dirty work of setting
the fault handler and calling the function. If the function causes a page
fault, the arch_debug_call_with_fault_handler() calls longjmp() with the
given \a jumpBuffer. Otherwise it returns normally.
debug_call_with_fault_handler() has already saved the CPU's fault_handler
and fault_handler_stack_pointer and will reset them later, so
arch_debug_call_with_fault_handler() doesn't need to care about it.
\param cpu The \c cpu_ent for the current CPU.
\param jumpBuffer Buffer to be used for longjmp().
\param function The function to be called.
\param parameter The parameter to be passed to the function to be called.
*/
FUNCTION(arch_debug_call_with_fault_handler):
stmfd sp!, { r4, lr }
// Set fault handler address, and fault handler stack pointer address. We
// don't need to save the previous values, since that's done by the caller.
ldr r4, =1f
str r4, [ r0, #CPU_ENT_fault_handler ]
str sp, [ r0, #CPU_ENT_fault_handler_stack_pointer ]
mov r4, r1
// call the function
mov r0, r3
blx r2
// regular return
ldmfd sp!, { r4, lr }
bx lr
// fault -- return via longjmp(jumpBuffer, 1)
1:
mov r0, r4
mov r1, #1
bl longjmp
FUNCTION_END(arch_debug_call_with_fault_handler)

View File

@ -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)

View File

@ -9,6 +9,49 @@
#include <asm_defs.h>
#define CPSR_MODE_MASK 0x1f
#define CPSR_MODE_USR 0x10
#define CPSR_MODE_FIQ 0x11
#define CPSR_MODE_IRQ 0x12
#define CPSR_MODE_SVC 0x13
#define CPSR_MODE_ABT 0x17
#define CPSR_MODE_UND 0x1b
/* The following two macros are taken from FreeBSD... */
.macro PUSHFRAMEINSVC
stmdb sp, {r0-r3} /* Save 4 registers */
mov r0, lr /* Save xxx32 r14 */
mov r1, sp /* Save xxx32 sp */
mrs r3, spsr /* Save xxx32 spsr */
mrs r2, cpsr /* Get the CPSR */
bic r2, r2, #(CPSR_MODE_MASK)/* Fix for SVC mode */
orr r2, r2, #(CPSR_MODE_SVC)
msr cpsr_c, r2 /* Punch into SVC mode */
mov r2, sp /* Save SVC sp */
str r0, [sp, #-4]! /* Push return address */
str lr, [sp, #-4]! /* Push SVC lr */
str r2, [sp, #-4]! /* Push SVC sp */
msr spsr_all, r3 /* Restore correct spsr */
ldmdb r1, {r0-r3} /* Restore 4 regs from xxx mode */
sub sp, sp, #(4*15) /* Adjust the stack pointer */
stmia sp, {r0-r12} /* Push the user mode registers */
add r0, sp, #(4*13) /* Adjust the stack pointer */
stmia r0, {r13-r14}^ /* Push the user mode registers */
mov r0, r0 /* NOP for previous instruction */
mrs r0, spsr_all
str r0, [sp, #-4]! /* Save spsr */
.endm
.macro PULLFRAMEFROMSVCANDEXIT
ldr r0, [sp], #0x0004 /* Get the SPSR from stack */
msr spsr_all, r0 /* restore SPSR */
ldmia sp, {r0-r14}^ /* Restore registers (usr mode) */
mov r0, r0 /* NOP for previous instruction */
add sp, sp, #(4*15) /* Adjust the stack pointer */
ldmia sp, {sp, lr, pc}^ /* Restore lr and exit */
.endm
.text
.globl _vectors_start
@ -43,134 +86,139 @@ _vectors_end:
.rept 64
.word 0xaabbccdd
.word 0xdeadbeef
.endr
abort_stack:
.word .
.word . - 4
.word 0xdeadbeef
.rept 64
.word 0xcafebabe
.endr
irq_stack:
.word . - 4
.word 0xcafebabe
.rept 64
.word 0xaaaabbbb
.endr
fiq_stack:
.word . - 4
.word 0xaaaabbbb
.rept 64
.word 0xccccdddd
.endr
und_stack:
.word . - 4
.word 0xccccdddd
FUNCTION(arm_undefined):
stmfd sp!, { r0-r12, r14 }
sub sp, sp, #12
mov r0, sp
mrs r1, spsr
stmia r0, { r1, r13-r14 }
b arch_arm_undefined
b .
PUSHFRAMEINSVC
mov r0, sp
bl arch_arm_undefined
PULLFRAMEFROMSVCANDEXIT
FUNCTION_END(arm_undefined)
FUNCTION(arm_syscall):
stmfd sp!, { r0-r12, r14 }
sub sp, sp, #12
mov r0, sp
mrs r1, spsr
stmia r0, { r1, r13-r14 }
b arch_arm_syscall
b .
PUSHFRAMEINSVC
mov r0, sp
bl arch_arm_syscall
PULLFRAMEFROMSVCANDEXIT
FUNCTION_END(arm_syscall)
FUNCTION(arm_prefetch_abort):
ldr sp, abort_stack
stmfd sp!, { r0-r12, r14 }
sub sp, sp, #12
mov r0, sp
mrs r1, spsr
stmia r0, { r1, r13-r14 }
b arch_arm_prefetch_abort
b .
#ifdef __XSCALE__
nop /* Make absolutely sure any pending */
nop /* imprecise aborts have occurred. */
#endif
add lr, lr, #4
PUSHFRAMEINSVC
mov r0, sp
bl arch_arm_prefetch_abort
PULLFRAMEFROMSVCANDEXIT
FUNCTION_END(arm_prefetch_abort)
FUNCTION(arm_data_abort):
ldr sp, abort_stack
/* XXX only deals with interrupting supervisor mode */
#ifdef __XSCALE__
nop /* Make absolutely sure any pending */
nop /* imprecise aborts have occurred. */
#endif
sub lr, lr, #8 /* Adjust the lr */
PUSHFRAMEINSVC
/* save r4-r6 and use as a temporary place to save while we switch into supervisor mode */
stmia r13, { r4-r6 }
mov r4, r13
sub r5, lr, #8
mrs r6, spsr
/* move into supervisor mode. irq/fiq disabled */
msr cpsr_c, #0x13
/* save the return address */
stmfd sp!, { r5 }
/* save C trashed regs, supervisor lr */
stmfd sp!, { r0-r3, r12, lr }
/* save spsr */
stmfd sp!, { r6 }
/* restore r4-r6 */
ldmia r4, { r4-r6 }
/* call into higher level code */
mrc p15, 0, r2, c5, c0, 0 @ get FSR
mrc p15, 0, r3, c6, c0, 0 @ get FAR
sub sp, sp, #20
mov r0, sp /* iframe */
stmia r0, { r6,r2,r3,r4,r5 }
mov r0, sp
bl arch_arm_data_abort
add sp, sp, #20
/* restore spsr */
ldmfd sp!, { r0 }
msr spsr_cxsf, r0
PULLFRAMEFROMSVCANDEXIT
/* restore back to where we came from */
ldmfd sp!, { r0-r3, r12, lr, pc }^
FUNCTION(arm_reserved):
b .
FUNCTION_END(arm_reserved)
FUNCTION(arm_irq):
ldr sp, abort_stack
/* XXX only deals with interrupting supervisor mode */
sub lr, lr, #4
PUSHFRAMEINSVC
/* save r4-r6 and use as a temporary place to save while we switch into supervisor mode */
stmia r13, { r4-r6 }
mov r4, r13
sub r5, lr, #4
mrs r6, spsr
/* move into supervisor mode. irq/fiq disabled */
msr cpsr_c, #(3<<6 | 0x13)
/* save the return address */
stmfd sp!, { r5 }
/* save C trashed regs, supervisor lr */
stmfd sp!, { r0-r3, r12, lr }
/* save spsr */
stmfd sp!, { r6 }
/* restore r4-r6 */
ldmia r4, { r4-r6 }
/* call into higher level code */
mov r0, sp /* iframe */
bl arch_arm_irq
/* restore spsr */
ldmfd sp!, { r0 }
msr spsr_cxsf, r0
PULLFRAMEFROMSVCANDEXIT
FUNCTION_END(arm_irq)
/* restore back to where we came from */
ldmfd sp!, { r0-r3, r12, lr, pc }^
.bss
.align 2
.global irq_save_spot
irq_save_spot:
.word 0 /* r4 */
.word 0 /* r5 */
.word 0 /* r6 */
.text
FUNCTION(arm_fiq):
ldr sp, abort_stack
sub lr, lr, #4
stmfd sp!, { r0-r3, r12, lr }
PUSHFRAMEINSVC
mov r0, sp /* iframe */
bl arch_arm_fiq
ldmfd sp!, { r0-r3, r12, pc }^
PULLFRAMEFROMSVCANDEXIT
FUNCTION_END(arm_fiq)
FUNCTION(arm_vector_init):
mrs r1, cpsr
bic r1, r1, #CPSR_MODE_MASK
/* move into modes and set initial sp */
mov r0, r1
orr r0, r0, #CPSR_MODE_FIQ
msr cpsr_c, r0
ldr sp, fiq_stack
mov r0, r1
orr r0, r0, #CPSR_MODE_IRQ
msr cpsr_c, r0
ldr sp, irq_stack
mov r0, r1
orr r0, r0, #CPSR_MODE_ABT
msr cpsr_c, r0
ldr sp, abort_stack
mov r0, r1
orr r0, r0, #CPSR_MODE_UND
msr cpsr_c, r0
ldr sp, und_stack
/* ... and return back to supervisor mode */
mov r0, r1
orr r0, r0, #CPSR_MODE_SVC
msr cpsr_c, r0
bx lr
FUNCTION_END(arm_vector_init)

View File

@ -31,7 +31,7 @@
#include <string.h>
#define TRACE_ARCH_INT
//#define TRACE_ARCH_INT
#ifdef TRACE_ARCH_INT
# define TRACE(x) dprintf x
#else
@ -61,30 +61,11 @@ static void *sVectorPageAddress;
static area_id sUserVectorPageArea;
static void *sUserVectorPageAddress;
// current fault handler
addr_t gFaultHandler;
// An iframe stack used in the early boot process when we don't have
// threads yet.
struct iframe_stack gBootFrameStack;
uint32
mmu_read_c1()
{
uint32 controlReg = 0;
asm volatile("MRC p15, 0, %[c1out], c1, c0, 0":[c1out] "=r" (controlReg));
return controlReg;
}
void
mmu_write_c1(uint32 value)
{
asm volatile("MCR p15, 0, %[c1in], c1, c0, 0"::[c1in] "r" (value));
}
void
arch_int_enable_io_interrupt(int irq)
{
@ -117,29 +98,32 @@ arch_int_disable_io_interrupt(int irq)
static void
print_iframe(struct iframe *frame)
print_iframe(const char *event, struct iframe *frame)
{
if (event)
dprintf("Exception: %s\n", event);
dprintf("R00=%08lx R01=%08lx R02=%08lx R03=%08lx\n"
"R04=%08lx R05=%08lx R06=%08lx R07=%08lx\n",
frame->r0, frame->r1, frame->r2, frame->r3,
frame->r4, frame->r5, frame->r6, frame->r7);
dprintf("R08=%08lx R09=%08lx R10=%08lx R11=%08lx\n"
"R12=%08lx R13=%08lx R14=%08lx CPSR=%08lx\n",
frame->r8, frame->r9, frame->r10, frame->r11,
frame->r12, frame->usr_sp, frame->usr_lr, frame->spsr);
}
status_t
arch_int_init(kernel_args *args)
{
// see if high vectors are enabled
if (mmu_read_c1() & (1<<13))
dprintf("High vectors already enabled\n");
else {
mmu_write_c1(mmu_read_c1() | (1<<13));
if (!(mmu_read_c1() & (1<<13)))
dprintf("Unable to enable high vectors!\n");
else
dprintf("Enabled high vectors\n");
}
return B_OK;
}
extern "C" void arm_vector_init(void);
status_t
arch_int_init_post_vm(kernel_args *args)
{
@ -163,6 +147,20 @@ arch_int_init_post_vm(kernel_args *args)
// copy vectors into the newly created area
memcpy(sVectorPageAddress, &_vectors_start, VECTORPAGE_SIZE);
arm_vector_init();
// see if high vectors are enabled
if (mmu_read_c1() & (1<<13))
dprintf("High vectors already enabled\n");
else {
mmu_write_c1(mmu_read_c1() | (1<<13));
if (!(mmu_read_c1() & (1<<13)))
dprintf("Unable to enable high vectors!\n");
else
dprintf("Enabled high vectors\n");
}
sPxaInterruptArea = map_physical_memory("pxa_intc", PXA_INTERRUPT_PHYS_BASE,
PXA_INTERRUPT_SIZE, 0, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&sPxaInterruptBase);
@ -179,7 +177,6 @@ arch_int_init_post_vm(kernel_args *args)
status_t
arch_int_init_io(kernel_args* args)
{
TRACE(("arch_int_init_io(%p)\n", args));
return B_OK;
}
@ -193,35 +190,101 @@ arch_int_init_post_device_manager(struct kernel_args *args)
extern "C" void arch_arm_undefined(struct iframe *iframe)
{
panic("Undefined instruction!");
print_iframe("Undefined Instruction", iframe);
panic("not handled!");
}
extern "C" void arch_arm_syscall(struct iframe *iframe)
{
panic("Software interrupt!\n");
print_iframe("Software interrupt", iframe);
}
extern "C" void arch_arm_data_abort(struct iframe *iframe)
extern "C" void arch_arm_data_abort(struct iframe *frame)
{
addr_t newip;
status_t res = vm_page_fault(iframe->r2 /* FAR */, iframe->r4 /* lr */,
true /* TODO how to determine read/write? */,
false /* only kernelspace for now */,
&newip);
Thread *thread = thread_get_current_thread();
bool isUser = (frame->spsr & 0x1f) == 0x10;
addr_t far = arm_get_far();
bool isWrite = true;
addr_t newip = 0;
if (res != B_HANDLED_INTERRUPT) {
panic("Data Abort: %08x %08x %08x %08x (res=%lx)", iframe->r0 /* spsr */,
iframe->r1 /* FSR */, iframe->r2 /* FAR */,
iframe->r4 /* lr */,
res);
} else {
//panic("vm_page_fault was ok (%08lx/%08lx)!", iframe->r2 /* FAR */, iframe->r0 /* spsr */);
#ifdef TRACE_ARCH_INT
print_iframe("Data Abort", frame);
#endif
if (debug_debugger_running()) {
// If this CPU or this thread has a fault handler, we're allowed to be
// here.
if (thread != NULL) {
cpu_ent* cpu = &gCPU[smp_get_current_cpu()];
if (cpu->fault_handler != 0) {
debug_set_page_fault_info(far, frame->pc,
isWrite ? DEBUG_PAGE_FAULT_WRITE : 0);
frame->svc_sp = cpu->fault_handler_stack_pointer;
frame->pc = cpu->fault_handler;
return;
}
if (thread->fault_handler != 0) {
kprintf("ERROR: thread::fault_handler used in kernel "
"debugger!\n");
debug_set_page_fault_info(far, frame->pc,
isWrite ? DEBUG_PAGE_FAULT_WRITE : 0);
frame->pc = thread->fault_handler;
return;
}
}
// otherwise, not really
panic("page fault in debugger without fault handler! Touching "
"address %p from pc %p\n", (void *)far, (void *)frame->pc);
return;
} else if ((frame->spsr & (1 << 7)) != 0) {
// interrupts disabled
// If a page fault handler is installed, we're allowed to be here.
// TODO: Now we are generally allowing user_memcpy() with interrupts
// disabled, which in most cases is a bug. We should add some thread
// flag allowing to explicitly indicate that this handling is desired.
if (thread && thread->fault_handler != 0) {
if (frame->pc != thread->fault_handler) {
frame->pc = thread->fault_handler;
return;
}
// The fault happened at the fault handler address. This is a
// certain infinite loop.
panic("page fault, interrupts disabled, fault handler loop. "
"Touching address %p from pc %p\n", (void*)far,
(void*)frame->pc);
}
// If we are not running the kernel startup the page fault was not
// allowed to happen and we must panic.
panic("page fault, but interrupts were disabled. Touching address "
"%p from pc %p\n", (void *)far, (void *)frame->pc);
return;
} else if (thread != NULL && thread->page_faults_allowed < 1) {
panic("page fault not allowed at this place. Touching address "
"%p from pc %p\n", (void *)far, (void *)frame->pc);
return;
}
enable_interrupts();
vm_page_fault(far, frame->pc, isWrite, isUser, &newip);
if (newip != 0) {
// the page fault handler wants us to modify the iframe to set the
// IP the cpu will return to to be this ip
frame->pc = newip;
}
}
extern "C" void arch_arm_prefetch_abort(struct iframe *iframe)
{
panic("Prefetch Abort: %08x %08x %08x", iframe->r0, iframe->r1, iframe->r2);
print_iframe("Prefetch Abort", iframe);
panic("not handled!");
}
extern "C" void arch_arm_irq(struct iframe *iframe)

View File

@ -6,52 +6,17 @@
* All rights reserved. Distributed under the terms of the MIT License.
*/
//#include <arch_platform.h>
#include <new>
#include <KernelExport.h>
#include <arch/platform.h>
#include <boot/kernel_args.h>
//#include <platform/openfirmware/openfirmware.h>
#include <real_time_clock.h>
#include <util/kernel_cpp.h>
#if 0
static M68KPlatform *sM68KPlatform;
// constructor
M68KPlatform::M68KPlatform(platform_type platformType,
m68k_platform_type m68kPlatformType)
: fPlatformType(platformType),
fM68KPlatformType(m68kPlatformType)
{
}
// destructor
M68KPlatform::~M68KPlatform()
{
}
// Default
M68KPlatform *
M68KPlatform::Default()
{
return sM68KPlatform;
}
// # pragma mark -
#endif
#include <kernel/debug.h>
status_t
arch_platform_init(struct kernel_args *kernelArgs)
{
#warning ARM:WRITEME
// NOTE: dprintf() is off-limits here, too early...
return B_OK;
}
@ -59,8 +24,7 @@ arch_platform_init(struct kernel_args *kernelArgs)
status_t
arch_platform_init_post_vm(struct kernel_args *kernelArgs)
{
#warning ARM:WRITEME
//sM68KPlatform->InitPostVM(kernelArgs);
// now we can use the heap and create areas
return B_OK;
}
@ -68,5 +32,6 @@ arch_platform_init_post_vm(struct kernel_args *kernelArgs)
status_t
arch_platform_init_post_thread(struct kernel_args *kernelArgs)
{
// now we can create and use semaphores
return B_OK;
}

View File

@ -28,7 +28,7 @@
#include <string.h>
#define TRACE_ARCH_THREAD
//#define TRACE_ARCH_THREAD
#ifdef TRACE_ARCH_THREAD
# define TRACE(x) dprintf x
#else

View File

@ -19,6 +19,15 @@
#include <arch/timer.h>
#include <arch/cpu.h>
//#define TRACE_ARCH_TIMER
#ifdef TRACE_ARCH_TIMER
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
#define PXA_TIMERS_PHYS_BASE 0x40A00000
#define PXA_TIMERS_SIZE 0x000000C0
#define PXA_TIMERS_INTERRUPT 7 /* OST_4_11 */
@ -29,7 +38,6 @@
#define PXA_OSMR4 0x20
#define PXA_OMCR4 0x30
#define TRACE(x) //dprintf x
static area_id sPxaTimersArea;
static uint32 *sPxaTimersBase;
@ -48,7 +56,7 @@ pxa_timer_interrupt(void *data)
void
arch_timer_set_hardware_timer(bigtime_t timeout)
{
TRACE(("arch_timer_set_hardware_timer(%lld): %p\n", timeout, sPxaTimersBase));
TRACE(("arch_timer_set_hardware_timer(%lld)\n", timeout));
if (sPxaTimersBase) {
sPxaTimersBase[PXA_OIER] |= (1 << 4);
@ -62,7 +70,7 @@ arch_timer_set_hardware_timer(bigtime_t timeout)
void
arch_timer_clear_hardware_timer()
{
TRACE(("arch_timer_clear_hardware_timer: %p\n", sPxaTimersBase));
TRACE(("arch_timer_clear_hardware_timer\n"));
if (sPxaTimersBase) {
sPxaTimersBase[PXA_OMCR4] = 0; // disable our timer

View File

@ -0,0 +1,62 @@
/*
* Copyright 2007-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
// This file is used to get C structure offsets into assembly code.
// The build system assembles the file and processes the output to create
// a header file with macro definitions, that can be included from assembly
// code.
#include <computed_asm_macros.h>
#include <arch_cpu.h>
#include <cpu.h>
#include <ksignal.h>
#include <ksyscalls.h>
#include <thread_types.h>
#define DEFINE_MACRO(macro, value) DEFINE_COMPUTED_ASM_MACRO(macro, value)
#define DEFINE_OFFSET_MACRO(prefix, structure, member) \
DEFINE_MACRO(prefix##_##member, offsetof(struct structure, member));
#define DEFINE_SIZEOF_MACRO(prefix, structure) \
DEFINE_MACRO(prefix##_sizeof, sizeof(struct structure));
void
dummy()
{
// struct cpu_ent
DEFINE_OFFSET_MACRO(CPU_ENT, cpu_ent, fault_handler);
DEFINE_OFFSET_MACRO(CPU_ENT, cpu_ent, fault_handler_stack_pointer);
// struct Thread
DEFINE_OFFSET_MACRO(THREAD, Thread, time_lock);
DEFINE_OFFSET_MACRO(THREAD, Thread, kernel_time);
DEFINE_OFFSET_MACRO(THREAD, Thread, user_time);
DEFINE_OFFSET_MACRO(THREAD, Thread, last_time);
DEFINE_OFFSET_MACRO(THREAD, Thread, in_kernel);
DEFINE_OFFSET_MACRO(THREAD, Thread, flags);
DEFINE_OFFSET_MACRO(THREAD, Thread, kernel_stack_top);
DEFINE_OFFSET_MACRO(THREAD, Thread, fault_handler);
// struct iframe
DEFINE_SIZEOF_MACRO(IFRAME, iframe);
// struct signal_frame_data
DEFINE_SIZEOF_MACRO(SIGNAL_FRAME_DATA, signal_frame_data);
DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, info);
DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, context);
DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, user_data);
DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, handler);
// struct ucontext_t
DEFINE_OFFSET_MACRO(UCONTEXT_T, __ucontext_t, uc_mcontext);
// struct siginfo_t
DEFINE_OFFSET_MACRO(SIGINFO_T, __siginfo_t, si_signo);
}

View File

@ -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;

View File

@ -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;

View File

@ -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);