From d111de5e7f85cad3251fc733a5d1f12fef81d170 Mon Sep 17 00:00:00 2001 From: Siarzhuk Zharski Date: Tue, 6 Nov 2012 20:05:48 +0100 Subject: [PATCH 01/31] KeymapSwitcher package updated to version 1.2.7.5 * Fixed issue with unwanted keymap switching in case UnZip started in * background (expanding optional packages during Haiku build, for * example). UnZip executable has no background application flag * for unknown reason. +alpha4 --- build/jam/OptionalPackages | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/jam/OptionalPackages b/build/jam/OptionalPackages index 01b1fb7b20..742664f5b5 100644 --- a/build/jam/OptionalPackages +++ b/build/jam/OptionalPackages @@ -1160,12 +1160,12 @@ 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 ; } 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 ; } AddSymlinkToHaikuImage home config settings deskbar Preferences : /boot/common/bin/KeymapSwitcher ; From 5c09b872a624abda70ce52014a142fbe98b17b0e Mon Sep 17 00:00:00 2001 From: Siarzhuk Zharski Date: Tue, 6 Nov 2012 20:19:41 +0100 Subject: [PATCH 02/31] Added KeymapSwitcher package into release build profile. +alpha4 --- build/jam/ReleaseBuildProfiles | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/jam/ReleaseBuildProfiles b/build/jam/ReleaseBuildProfiles index 8de37d93db..0fc925fdf6 100644 --- a/build/jam/ReleaseBuildProfiles +++ b/build/jam/ReleaseBuildProfiles @@ -25,7 +25,8 @@ switch $(HAIKU_BUILD_PROFILE) { WebPositive WonderBrush ; AddOptionalHaikuImagePackages CVS Development Git Mercurial Python Subversion OpenSSH OpenSSL ; - AddOptionalHaikuImagePackages Nano P7zip Welcome BeBook XZ-Utils ; + AddOptionalHaikuImagePackages KeymapSwitcher Nano P7zip Welcome + BeBook XZ-Utils ; AddOptionalHaikuImagePackages wpa_supplicant ; } From 1cd0e20c569e8887701162691f9bdf922c04676f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 6 Nov 2012 20:54:34 +0100 Subject: [PATCH 03/31] Unbroke GCC4 BRect const compatibility. * This can be removed again next time all GCC4 packages are rebuilt for whatever reason. --- src/kits/interface/Rect.cpp | 60 ++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/src/kits/interface/Rect.cpp b/src/kits/interface/Rect.cpp index 20b51308ff..d8d66d8f4b 100644 --- a/src/kits/interface/Rect.cpp +++ b/src/kits/interface/Rect.cpp @@ -328,4 +328,62 @@ OffsetToCopy__5BRectff(BRect* self, float dx, float dy) } -#endif // __GNUC__ == 2 +#elif __GNUC__ == 4 +// TODO: remove this when new GCC 4 packages have to be built anyway + + +extern "C" BRect +_ZN5BRect11InsetByCopyE6BPoint(BRect* self, BPoint point) +{ + BRect copy(*self); + copy.InsetBy(point); + return copy; +} + + +extern "C" BRect +_ZN5BRect11InsetByCopyEff(BRect* self, float dx, float dy) +{ + BRect copy(*self); + copy.InsetBy(dx, dy); + return copy; +} + + +extern "C" BRect +_ZN5BRect12OffsetByCopyE6BPoint(BRect* self, BPoint point) +{ + BRect copy(*self); + copy.OffsetBy(point); + return copy; +} + + +extern "C" BRect +_ZN5BRect12OffsetByCopyEff(BRect* self, float dx, float dy) +{ + BRect copy(*self); + copy.OffsetBy(dx, dy); + return copy; +} + + +extern "C" BRect +_ZN5BRect12OffsetToCopyE6BPoint(BRect* self, BPoint point) +{ + BRect copy(*self); + copy.OffsetTo(point); + return copy; +} + + +extern "C" BRect +_ZN5BRect12OffsetToCopyEff(BRect* self, float dx, float dy) +{ + BRect copy(*self); + copy.OffsetTo(dx, dy); + return copy; +} + + +#endif // __GNUC__ == 4 From 2a2e3bafa2daaf31ff8be2c7b6782529f63774e3 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Tue, 6 Nov 2012 20:54:18 +0100 Subject: [PATCH 04/31] Add UI hooks for watchpoints. This gets basic watchpoint support working. Right clicking on a variable and picking Watch now opens a prompt with the inferred address, size and watch type for the user to adjust. Still needs some work to get them to show/be modifiable in the breakpoints tab and to get them to respect architectural restrictions (i.e. on x86 we can realistically only do 2 hardware watchpoints and those are restricted to write watch), at least until we support software emulated watchpoints. --- src/apps/debugger/Jamfile | 1 + src/apps/debugger/MessageCodes.h | 3 +- .../gui/team_window/TeamWindow.cpp | 22 +++ .../gui/team_window/VariablesView.cpp | 69 +++++--- .../gui/team_window/VariablesView.h | 3 + .../gui/team_window/WatchPromptWindow.cpp | 154 ++++++++++++++++++ .../gui/team_window/WatchPromptWindow.h | 56 +++++++ 7 files changed, 287 insertions(+), 21 deletions(-) create mode 100644 src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.cpp create mode 100644 src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.h diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 727155ef50..167979b6e7 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -211,6 +211,7 @@ Application Debugger : TeamWindow.cpp ThreadListView.cpp VariablesView.cpp + WatchPromptWindow.cpp # user_interface/gui/util ActionMenuItem.cpp diff --git a/src/apps/debugger/MessageCodes.h b/src/apps/debugger/MessageCodes.h index 75a2df88f3..59ec092cac 100644 --- a/src/apps/debugger/MessageCodes.h +++ b/src/apps/debugger/MessageCodes.h @@ -53,7 +53,8 @@ enum { MSG_INSPECTOR_WINDOW_CLOSED = 'irwc', MSG_INSPECT_ADDRESS = 'isad', MSG_SHOW_TYPECAST_NODE_PROMPT = 'stnp', - MSG_TYPECAST_NODE = 'tyno' + MSG_TYPECAST_NODE = 'tyno', + MSG_SHOW_WATCH_VARIABLE_PROMPT = 'swvp' }; diff --git a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp index 4da2045c39..1fc4fd86dc 100644 --- a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp @@ -44,6 +44,7 @@ #include "TypeComponentPath.h" #include "UserInterface.h" #include "Variable.h" +#include "WatchPromptWindow.h" enum { @@ -247,6 +248,27 @@ TeamWindow::MessageReceived(BMessage* message) break; } + case MSG_SHOW_WATCH_VARIABLE_PROMPT: + { + target_addr_t address; + uint32 type; + int32 length; + + if (message->FindUInt64("address", &address) != B_OK + || message->FindUInt32("type", &type) != B_OK + || message->FindInt32("length", &length) != B_OK) { + break; + } + + try { + WatchPromptWindow* window = WatchPromptWindow::Create(address, + type, length, fListener); + window->Show(); + } catch (...) { + // TODO: notify user + } + break; + } case B_REFS_RECEIVED: { entry_ref locatedPath; diff --git a/src/apps/debugger/user_interface/gui/team_window/VariablesView.cpp b/src/apps/debugger/user_interface/gui/team_window/VariablesView.cpp index e5a6be1c50..744a2d1e86 100644 --- a/src/apps/debugger/user_interface/gui/team_window/VariablesView.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/VariablesView.cpp @@ -11,6 +11,8 @@ #include +#include + #include #include #include @@ -1684,6 +1686,22 @@ VariablesView::MessageReceived(BMessage* message) node->NodeChild()->SetNode(valueNode); break; } + case MSG_SHOW_WATCH_VARIABLE_PROMPT: + { + ModelNode* node = reinterpret_cast( + fVariableTable->SelectionModel()->NodeAt(0)); + ValueLocation* location = node->NodeChild()->Location(); + ValuePieceLocation piece = location->PieceAt(0); + if (piece.type != VALUE_PIECE_LOCATION_MEMORY) + break; + + BMessage looperMessage(*message); + looperMessage.AddUInt64("address", piece.address); + looperMessage.AddInt32("length", piece.size); + looperMessage.AddUInt32("type", B_DATA_READ_WRITE_WATCHPOINT); + Looper()->PostMessage(&looperMessage); + break; + } case MSG_VALUE_NODE_CHANGED: { ValueNodeChild* nodeChild; @@ -1977,34 +1995,45 @@ VariablesView::_GetContextActionsForNode(ModelNode* node, if (location->PieceAt(0).type != VALUE_PIECE_LOCATION_MEMORY) return B_OK; - BMessage* message = new BMessage(MSG_SHOW_INSPECTOR_WINDOW); - if (message == NULL) - return B_NO_MEMORY; + BMessage* message = NULL; + status_t result = _AddContextAction("Inspect", MSG_SHOW_INSPECTOR_WINDOW, + actions, message); + if (result != B_OK) + return result; - ObjectDeleter messageDeleter(message); message->AddUInt64("address", location->PieceAt(0).address); - ActionMenuItem* item = new(std::nothrow) ActionMenuItem("Inspect", - message); + result = _AddContextAction("Cast as" B_UTF8_ELLIPSIS, + MSG_SHOW_TYPECAST_NODE_PROMPT, actions, message); + if (result != B_OK) + return result; + + result = _AddContextAction("Watch" B_UTF8_ELLIPSIS, + MSG_SHOW_WATCH_VARIABLE_PROMPT, actions, message); + if (result != B_OK) + return result; + + return B_OK; +} + + +status_t +VariablesView::_AddContextAction(const char* action, uint32 what, + ContextActionList* actions, BMessage*& _message) +{ + _message = new BMessage(what); + if (_message == NULL) + return B_NO_MEMORY; + + ObjectDeleter messageDeleter(_message); + + ActionMenuItem* item = new(std::nothrow) ActionMenuItem(action, + _message); if (item == NULL) return B_NO_MEMORY; messageDeleter.Detach(); ObjectDeleter actionDeleter(item); - if (!actions->AddItem(item)) - return B_NO_MEMORY; - - message = new(std::nothrow)BMessage(MSG_SHOW_TYPECAST_NODE_PROMPT); - if (message == NULL) - return B_NO_MEMORY; - - item = new(std::nothrow) ActionMenuItem("Cast as" B_UTF8_ELLIPSIS, - message); - if (item == NULL) - return B_NO_MEMORY; - - messageDeleter.Detach(); - if (!actions->AddItem(item)) return B_NO_MEMORY; diff --git a/src/apps/debugger/user_interface/gui/team_window/VariablesView.h b/src/apps/debugger/user_interface/gui/team_window/VariablesView.h index 7c09b73f98..974190068d 100644 --- a/src/apps/debugger/user_interface/gui/team_window/VariablesView.h +++ b/src/apps/debugger/user_interface/gui/team_window/VariablesView.h @@ -72,6 +72,9 @@ private: void _RequestNodeValue(ModelNode* node); status_t _GetContextActionsForNode(ModelNode* node, ContextActionList* actions); + status_t _AddContextAction(const char* action, + uint32 what, ContextActionList* actions, + BMessage*& _message); void _FinishContextMenu(bool force); void _SaveViewState() const; void _RestoreViewState(); diff --git a/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.cpp b/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.cpp new file mode 100644 index 0000000000..0c81483ea3 --- /dev/null +++ b/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.cpp @@ -0,0 +1,154 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ +#include "WatchPromptWindow.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "MessageCodes.h" +#include "UserInterface.h" +#include "Watchpoint.h" + + +WatchPromptWindow::WatchPromptWindow(target_addr_t address, uint32 type, + int32 length, UserInterfaceListener* listener) + : + BWindow(BRect(), "Edit Watchpoint", B_FLOATING_WINDOW, + B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE), + fInitialAddress(address), + fInitialType(type), + fInitialLength(length), + fAddressInput(NULL), + fLengthInput(NULL), + fTypeField(NULL), + fListener(listener) +{ +} + + +WatchPromptWindow::~WatchPromptWindow() +{ +} + + +WatchPromptWindow* +WatchPromptWindow::Create(target_addr_t address, uint32 type, int32 length, + UserInterfaceListener* listener) +{ + WatchPromptWindow* self = new WatchPromptWindow(address, type, length, + listener); + + try { + self->_Init(); + } catch (...) { + delete self; + throw; + } + + return self; + +} + +void +WatchPromptWindow::_Init() +{ + BString text; + text.SetToFormat("0x%" B_PRIx64, fInitialAddress); + fAddressInput = new BTextControl("Address:", text, NULL); + + text.SetToFormat("%" B_PRId32, fInitialLength); + fLengthInput = new BTextControl("Length:", text, NULL); + + BMenu* typeMenu = new BMenu("Watch Type"); + typeMenu->AddItem(new BMenuItem("Read", NULL)); + typeMenu->AddItem(new BMenuItem("Write", NULL)); + typeMenu->AddItem(new BMenuItem("Read/Write", NULL)); + fTypeField = new BMenuField("Type:", typeMenu); + BLayoutItem* labelItem = fTypeField->CreateLabelLayoutItem(); + labelItem->View()->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + BLayoutBuilder::Group<>(this, B_VERTICAL) + .SetInsets(4.0f, 4.0f, 4.0f, 4.0f) + .AddGroup(B_HORIZONTAL, 4.0f) + .Add(fAddressInput) + .End() + .AddGroup(B_HORIZONTAL, 4.0f) + .Add(fLengthInput) + .Add(labelItem) + .Add(fTypeField->CreateMenuBarLayoutItem()) + .End() + .AddGroup(B_HORIZONTAL, 4.0f) + .AddGlue() + .Add((fWatchButton = new BButton("Set", + new BMessage(MSG_SET_WATCHPOINT)))) + .Add((fCancelButton = new BButton("Cancel", + new BMessage(B_QUIT_REQUESTED)))) + .End(); + + fWatchButton->SetTarget(this); + fCancelButton->SetTarget(this); + + fTypeField->Menu()->SetLabelFromMarked(true); + fTypeField->Menu()->ItemAt(fInitialType)->SetMarked(true); +} + +void +WatchPromptWindow::Show() +{ + CenterOnScreen(); + BWindow::Show(); +} + +void +WatchPromptWindow::MessageReceived(BMessage* message) +{ + switch (message->what) { + case MSG_SET_WATCHPOINT: + { + target_addr_t address; + int32 length; + ExpressionParser parser; + parser.SetSupportHexInput(true); + BString errorMessage; + try { + address = parser.EvaluateToInt64(fAddressInput->Text()); + length = (int32)parser.EvaluateToInt64(fLengthInput->Text()); + } catch(ParseException parseError) { + errorMessage.SetToFormat("Failed to parse data: %s", + parseError.message.String()); + } catch(...) { + errorMessage.SetToFormat( + "Unknown error while parsing address"); + } + + if (!errorMessage.IsEmpty()) { + BAlert* alert = new(std::nothrow) BAlert("Edit Watchpoint", + errorMessage.String(), "Close"); + if (alert != NULL) + alert->Go(); + break; + } + + fListener->ClearWatchpointRequested(fInitialAddress); + fListener->SetWatchpointRequested(address, fTypeField->Menu() + ->IndexOf(fTypeField->Menu()->FindMarked()), length, true); + + PostMessage(B_QUIT_REQUESTED); + + break; + } + default: + BWindow::MessageReceived(message); + break; + } + +} diff --git a/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.h b/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.h new file mode 100644 index 0000000000..465fdd696c --- /dev/null +++ b/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.h @@ -0,0 +1,56 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ +#ifndef WATCH_PROMPT_WINDOW_H +#define WATCH_PROMPT_WINDOW_H + + +#include + +#include "types/Types.h" + + +class BTextControl; +class Watchpoint; +class BMenuField; +class UserInterfaceListener; + + +class WatchPromptWindow : public BWindow +{ +public: + // edit existing watchpoint + WatchPromptWindow(target_addr_t address, + uint32 type, int32 length, + UserInterfaceListener* listener); + + ~WatchPromptWindow(); + + static WatchPromptWindow* Create(target_addr_t address, uint32 type, + int32 length, + UserInterfaceListener* listener); + // throws + + + virtual void MessageReceived(BMessage* message); + + virtual void Show(); + +private: + void _Init(); + + +private: + target_addr_t fInitialAddress; + uint32 fInitialType; + int32 fInitialLength; + BTextControl* fAddressInput; + BTextControl* fLengthInput; + BMenuField* fTypeField; + UserInterfaceListener* fListener; + BButton* fWatchButton; + BButton* fCancelButton; +}; + +#endif // WATCH_PROMPT_WINDOW_H From 7c9e4b9a44c60a3b713c2e78418e7a8e82856e5f Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Tue, 6 Nov 2012 21:57:24 +0100 Subject: [PATCH 05/31] Fix gcc2 warning. --- .../user_interface/gui/team_window/WatchPromptWindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.cpp b/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.cpp index 0c81483ea3..2718ce80ff 100644 --- a/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.cpp @@ -114,8 +114,8 @@ WatchPromptWindow::MessageReceived(BMessage* message) switch (message->what) { case MSG_SET_WATCHPOINT: { - target_addr_t address; - int32 length; + target_addr_t address = 0; + int32 length = 0; ExpressionParser parser; parser.SetSupportHexInput(true); BString errorMessage; From 79936aa57161152c2d2f464cafaa7934b9af40fb Mon Sep 17 00:00:00 2001 From: Siarzhuk Zharski Date: Tue, 6 Nov 2012 22:16:51 +0100 Subject: [PATCH 06/31] Ensure that KeymapSwitcher does not get stripped on Release build. See #8603 for history. --- build/jam/OptionalPackages | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/build/jam/OptionalPackages b/build/jam/OptionalPackages index 742664f5b5..978e7041a3 100644 --- a/build/jam/OptionalPackages +++ b/build/jam/OptionalPackages @@ -1161,11 +1161,13 @@ if [ IsOptionalHaikuImagePackageAdded KeymapSwitcher ] { if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage KeymapSwitcher-1.2.7-r1a4-x86-gcc4-2012-11-01.zip - : $(baseURL)/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-11-01.zip - : $(baseURL)/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 ; From f8cdd319702dc5b4387ca75ba96cca4291f01263 Mon Sep 17 00:00:00 2001 From: Adrien Destugues - PulkoMandy Date: Tue, 6 Nov 2012 22:51:59 +0100 Subject: [PATCH 07/31] =?UTF-8?q?Update=20to=20fRiSS=20version=200.7=20=C2?= =?UTF-8?q?+alpha4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build/jam/OptionalPackages | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/jam/OptionalPackages b/build/jam/OptionalPackages index 978e7041a3..3875fc71df 100644 --- a/build/jam/OptionalPackages +++ b/build/jam/OptionalPackages @@ -973,12 +973,12 @@ if [ IsOptionalHaikuImagePackageAdded friss ] { } else { if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - friss-29-r1a4-x86-gcc4-2012-09-09.zip - : $(baseURL)/friss-29-r1a4-x86-gcc4-2012-09-09.zip ; + friss-33-r1a4-x86-gcc4-2012-11-06.zip + : $(baseURL)/friss-33-r1a4-x86-gcc4-2012-11-06.zip ; } else { InstallOptionalHaikuImagePackage - friss-29-r1a4-x86-gcc2-2012-08-28.zip - : $(baseURL)/friss-29-r1a4-x86-gcc2-2012-08-28.zip ; + friss-33-r1a4-x86-gcc2-2012-11-06.zip + : $(baseURL)/friss-33-r1a4-x86-gcc2-2012-11-06.zip ; } # AddSymlinkToHaikuImage home config settings deskbar Desktop\ applets # : /boot/apps/FRiSS/FRiSS ; From a8199d692aa28895e7e9a4cbd77121c8879ba4a4 Mon Sep 17 00:00:00 2001 From: threedeyes <3dEyes@gmail.com> Date: Wed, 7 Nov 2012 08:39:30 +0000 Subject: [PATCH 08/31] Fixed wrong parameters order --- src/apps/showimage/ShowImageWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/showimage/ShowImageWindow.cpp b/src/apps/showimage/ShowImageWindow.cpp index 22144762b3..b79059e54c 100644 --- a/src/apps/showimage/ShowImageWindow.cpp +++ b/src/apps/showimage/ShowImageWindow.cpp @@ -727,7 +727,7 @@ ShowImageWindow::MessageReceived(BMessage* message) strCaption << i; BMenuItem* item = new BMenuItem(strCaption.String(), goTo, - B_SHIFT_KEY, shortcut); + shortcut, B_SHIFT_KEY); if (currentPage == i) item->SetMarked(true); fGoToPageMenu->AddItem(item); From 1aa6f649535f5f2e1b9edd42bf48137a3ccd8723 Mon Sep 17 00:00:00 2001 From: threedeyes <3dEyes@gmail.com> Date: Wed, 7 Nov 2012 09:24:46 +0000 Subject: [PATCH 09/31] NTFS: renamed [NTFS File System] to [NT File System] to be consistent with Be File System --- src/add-ons/disk_systems/ntfs/InitializeParameterEditor.cpp | 2 +- src/add-ons/disk_systems/ntfs/NTFSAddOn.cpp | 2 +- src/add-ons/kernel/file_systems/ntfs/kernel_interface.c | 2 +- src/apps/drivesetup/MainWindow.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/add-ons/disk_systems/ntfs/InitializeParameterEditor.cpp b/src/add-ons/disk_systems/ntfs/InitializeParameterEditor.cpp index ac44bfc8cf..ba14586b9f 100644 --- a/src/add-ons/disk_systems/ntfs/InitializeParameterEditor.cpp +++ b/src/add-ons/disk_systems/ntfs/InitializeParameterEditor.cpp @@ -82,7 +82,7 @@ InitializeNTFSEditor::PartitionNameChanged(const char* name) void InitializeNTFSEditor::_CreateViewControls() { - fNameTC = new BTextControl("Name:", "Haiku", NULL); + fNameTC = new BTextControl("Name:", "New NTFS Volume", NULL); fNameTC->SetModificationMessage(new BMessage(MSG_NAME_CHANGED)); // TODO find out what is the max length for this specific FS partition name fNameTC->TextView()->SetMaxBytes(31); diff --git a/src/add-ons/disk_systems/ntfs/NTFSAddOn.cpp b/src/add-ons/disk_systems/ntfs/NTFSAddOn.cpp index 75a2ac53f2..cde20e614e 100644 --- a/src/add-ons/disk_systems/ntfs/NTFSAddOn.cpp +++ b/src/add-ons/disk_systems/ntfs/NTFSAddOn.cpp @@ -33,7 +33,7 @@ using std::nothrow; -#define kPartitionTypeNTFS "NTFS File System" +#define kPartitionTypeNTFS "NT File System" static const uint32 kDiskSystemFlags = 0 diff --git a/src/add-ons/kernel/file_systems/ntfs/kernel_interface.c b/src/add-ons/kernel/file_systems/ntfs/kernel_interface.c index d4128fceab..d2835f3798 100644 --- a/src/add-ons/kernel/file_systems/ntfs/kernel_interface.c +++ b/src/add-ons/kernel/file_systems/ntfs/kernel_interface.c @@ -169,7 +169,7 @@ static file_system_module_info sNTFSFileSystem = { }, "ntfs", // short_name - "NTFS File System", // pretty_name + "NT File System", // pretty_name B_DISK_SYSTEM_SUPPORTS_INITIALIZING | B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME | B_DISK_SYSTEM_SUPPORTS_WRITING, // DDM flags diff --git a/src/apps/drivesetup/MainWindow.cpp b/src/apps/drivesetup/MainWindow.cpp index 922c40d681..c8ab45f0a5 100644 --- a/src/apps/drivesetup/MainWindow.cpp +++ b/src/apps/drivesetup/MainWindow.cpp @@ -873,7 +873,7 @@ MainWindow::_Initialize(BDiskDevice* disk, partition_id selectedPartition, // TODO: diskSystem.IsFileSystem() seems like a better fit here? if (diskSystemName == "Be File System" - || diskSystemName == "NTFS File System") { + || diskSystemName == "NT File System") { InitParamsPanel* panel = new InitParamsPanel(this, diskSystemName, partition); if (panel->Go(name, parameters) == GO_CANCELED) From cfeeb9ae6f2bc120a726de9470642016d774c3d8 Mon Sep 17 00:00:00 2001 From: threedeyes <3dEyes@gmail.com> Date: Wed, 7 Nov 2012 10:43:49 +0000 Subject: [PATCH 10/31] Enable NTFS partition type in PartitionMap. Now we can create ntfs partitions. --- src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp index 7633290a57..644e540b7f 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp @@ -118,7 +118,7 @@ static const struct partition_type kPartitionTypes[] = { { 0x85, /*"Linux extendend partition"*/INTEL_EXTENDED_PARTITION_NAME, false }, { 0x86, "NTFS volume set", false }, - { 0x87, "NTFS volume set", false }, + { 0x87, "NTFS volume set", true }, { 0x88, "Linux plaintext", false }, { 0x8e, "Linux LVM", false }, { 0x93, "Amoeba", false }, From 63dffc0194e460381e535f9dcc64b5bf6fc9ae5f Mon Sep 17 00:00:00 2001 From: Humdinger Date: Wed, 7 Nov 2012 13:22:33 +0100 Subject: [PATCH 11/31] Improved string of new Terminal setting. --- src/apps/terminal/AppearPrefView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/terminal/AppearPrefView.cpp b/src/apps/terminal/AppearPrefView.cpp index eea2156a5b..4f9bcca934 100644 --- a/src/apps/terminal/AppearPrefView.cpp +++ b/src/apps/terminal/AppearPrefView.cpp @@ -83,7 +83,7 @@ AppearancePrefView::AppearancePrefView(const char* name, }; fBlinkCursor = new BCheckBox( - B_TRANSLATE("Blink the cursor"), + B_TRANSLATE("Blinking cursor"), new BMessage(MSG_BLINK_CURSOR_CHANGED)); fWarnOnExit = new BCheckBox( From c72218a0940104999fd0a354f6d308954a8c6867 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Fri, 2 Nov 2012 15:37:11 +0100 Subject: [PATCH 12/31] Disable duplicated interrupt disable code in marvell yukon. Since we now implement HAIKU_CHECK_DISABLE_INTERRUPTS there is no need to do it again in the interrupt handler. Further, store and carry over the interrupt status from the hook to the interrupt handler as that is cleaner and just in case reading the register somehow clears it. May help with #8454. --- .../kernel/drivers/network/marvell_yukon/dev/msk/glue.c | 9 ++++++++- .../drivers/network/marvell_yukon/dev/msk/if_msk.c | 6 ++++++ .../drivers/network/marvell_yukon/dev/msk/if_mskreg.h | 3 +++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/glue.c b/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/glue.c index 997689e0af..6b76ab605b 100644 --- a/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/glue.c +++ b/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/glue.c @@ -51,10 +51,17 @@ HAIKU_CHECK_DISABLE_INTERRUPTS(device_t dev) return 0; } + sc->haiku_interrupt_status = status; return 1; } -NO_HAIKU_REENABLE_INTERRUPTS(); +void +HAIKU_REENABLE_INTERRUPTS(device_t dev) +{ + struct msk_softc *sc = device_get_softc(dev); + CSR_WRITE_4(sc, B0_Y2_SP_ICR, 2); +} + HAIKU_DRIVER_REQUIREMENTS(FBSD_TASKQUEUES | FBSD_FAST_TASKQUEUE | FBSD_SWI_TASKQUEUE); diff --git a/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/if_msk.c b/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/if_msk.c index be4ac5dc8d..377a1589b2 100644 --- a/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/if_msk.c +++ b/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/if_msk.c @@ -3610,6 +3610,7 @@ msk_intr(void *xsc) sc = xsc; MSK_LOCK(sc); +#ifndef __HAIKU__ /* Reading B0_Y2_SP_ISRC2 masks further interrupts. */ status = CSR_READ_4(sc, B0_Y2_SP_ISRC2); if (status == 0 || status == 0xffffffff || @@ -3619,6 +3620,9 @@ msk_intr(void *xsc) MSK_UNLOCK(sc); return; } +#else + status = sc->haiku_interrupt_status; +#endif sc_if0 = sc->msk_if[MSK_PORT_A]; sc_if1 = sc->msk_if[MSK_PORT_B]; @@ -3655,8 +3659,10 @@ msk_intr(void *xsc) if ((status & Y2_IS_STAT_BMU) != 0 && domore == 0) CSR_WRITE_4(sc, STAT_CTRL, SC_STAT_CLR_IRQ); +#ifndef __HAIKU__ /* Reenable interrupts. */ CSR_WRITE_4(sc, B0_Y2_SP_ICR, 2); +#endif if (ifp0 != NULL && (ifp0->if_drv_flags & IFF_DRV_RUNNING) != 0 && !IFQ_DRV_IS_EMPTY(&ifp0->if_snd)) diff --git a/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/if_mskreg.h b/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/if_mskreg.h index 583f5e88ef..75ef99ba9d 100644 --- a/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/if_mskreg.h +++ b/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/if_mskreg.h @@ -2520,6 +2520,9 @@ struct msk_softc { int msk_process_limit; int msk_stat_cons; struct mtx msk_mtx; +#ifdef __HAIKU__ + uint32_t haiku_interrupt_status; +#endif }; #define MSK_LOCK(_sc) mtx_lock(&(_sc)->msk_mtx) From 1b1484de7bba5cd4d50205b9d1daf5be2e1ad9dd Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Fri, 2 Nov 2012 15:39:16 +0100 Subject: [PATCH 13/31] Workaround possible spurious interrupts in marvell yukon. This comes from a similar patch in FreeBSD r234666 but does the check and acknowledge in the case where we don't have any other interrupts. Since the interrupt isn't used it is never unmasked and therefore the check against the interrupt mask will always fail if the TWSI IRQ is the only interrupt that happened. In that case an interrupt storm would be triggered that lasts until any other valid interrupt comes along, is handled and both are acknowledged. This may help with #8454 on some cards that exhibit the spurious TWSI IRQs. --- .../kernel/drivers/network/marvell_yukon/dev/msk/glue.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/glue.c b/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/glue.c index 6b76ab605b..13911c7144 100644 --- a/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/glue.c +++ b/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/glue.c @@ -47,6 +47,11 @@ 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; } From c1e45a1e822c70ef67254ce678bd9edaf37eded6 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Wed, 7 Nov 2012 14:45:53 +0100 Subject: [PATCH 14/31] Persist watchpoints in TeamSettings. --- src/apps/debugger/settings/TeamSettings.cpp | 45 +++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/apps/debugger/settings/TeamSettings.cpp b/src/apps/debugger/settings/TeamSettings.cpp index fbed4c8f74..c379f40054 100644 --- a/src/apps/debugger/settings/TeamSettings.cpp +++ b/src/apps/debugger/settings/TeamSettings.cpp @@ -119,6 +119,24 @@ TeamSettings::SetTo(const BMessage& archive) } } + // add watchpoints + for (int32 i = 0; archive.FindMessage("watchpoints", i, &childArchive) + == B_OK; i++) { + WatchpointSetting* watchpointSetting + = new(std::nothrow) WatchpointSetting; + if (watchpointSetting == NULL) + return B_NO_MEMORY; + + error = watchpointSetting->SetTo(childArchive); + if (error == B_OK && !fWatchpoints.AddItem(watchpointSetting)) + error = B_NO_MEMORY; + if (error != B_OK) { + delete watchpointSetting; + return error; + } + } + + // add UI settings for (int32 i = 0; archive.FindMessage("uisettings", i, &childArchive) == B_OK; i++) { @@ -155,6 +173,17 @@ TeamSettings::WriteTo(BMessage& archive) const return error; } + for (int32 i = 0; WatchpointSetting* watchpoint = fWatchpoints.ItemAt(i); + i++) { + error = watchpoint->WriteTo(childArchive); + if (error != B_OK) + return error; + + error = archive.AddMessage("watchpoints", &childArchive); + if (error != B_OK) + return error; + } + for (int32 i = 0; TeamUiSettings* uiSetting = fUiSettings.ItemAt(i); i++) { error = uiSetting->WriteTo(childArchive); @@ -255,6 +284,16 @@ TeamSettings::operator=(const TeamSettings& other) } } + for (int32 i = 0; WatchpointSetting* watchpoint + = other.fWatchpoints.ItemAt(i); i++) { + WatchpointSetting* clonedWatchpoint + = new WatchpointSetting(*watchpoint); + if (!fWatchpoints.AddItem(clonedWatchpoint)) { + delete clonedWatchpoint; + throw std::bad_alloc(); + } + } + for (int32 i = 0; TeamUiSettings* uiSetting = other.fUiSettings.ItemAt(i); i++) { TeamUiSettings* clonedSetting @@ -277,10 +316,16 @@ TeamSettings::_Unset() delete breakpoint; } + for (int32 i = 0; WatchpointSetting* watchpoint = fWatchpoints.ItemAt(i); + i++) { + delete watchpoint; + } + for (int32 i = 0; TeamUiSettings* uiSetting = fUiSettings.ItemAt(i); i++) delete uiSetting; fBreakpoints.MakeEmpty(); + fWatchpoints.MakeEmpty(); fUiSettings.MakeEmpty(); fTeamName.Truncate(0); From 12c53499e76d8d0e63a94eb738bbe13f387cb0dd Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Wed, 7 Nov 2012 14:50:17 +0100 Subject: [PATCH 15/31] More UI support for watchpointgs. - BreakpointTableModel now encapsulates both breakpoints and watchpoints. - Extended BreakpointView and TeamWindow to handle enable/disable/removing watchpoints as well. --- src/apps/debugger/MessageCodes.h | 1 + src/apps/debugger/WatchpointManager.cpp | 14 +- src/apps/debugger/model/Team.cpp | 3 + src/apps/debugger/model/Team.h | 3 +- src/apps/debugger/model/Watchpoint.h | 4 + .../gui/team_window/BreakpointListView.cpp | 136 ++++++++++++++++-- .../gui/team_window/BreakpointListView.h | 11 +- .../gui/team_window/BreakpointsView.cpp | 73 ++++++++-- .../gui/team_window/BreakpointsView.h | 18 ++- .../gui/team_window/TeamWindow.cpp | 55 ++++++- .../gui/team_window/TeamWindow.h | 13 ++ 11 files changed, 304 insertions(+), 27 deletions(-) diff --git a/src/apps/debugger/MessageCodes.h b/src/apps/debugger/MessageCodes.h index 59ec092cac..b3e0f9717b 100644 --- a/src/apps/debugger/MessageCodes.h +++ b/src/apps/debugger/MessageCodes.h @@ -29,6 +29,7 @@ enum { MSG_IMAGE_FILE_CHANGED = 'ifch', MSG_FUNCTION_SOURCE_CODE_CHANGED = 'fnsc', MSG_USER_BREAKPOINT_CHANGED = 'ubrc', + MSG_WATCHPOINT_CHANGED = 'wapc', MSG_DEBUGGER_EVENT = 'dbge', MSG_LOAD_SETTINGS = 'ldst', diff --git a/src/apps/debugger/WatchpointManager.cpp b/src/apps/debugger/WatchpointManager.cpp index e5854a06be..9b21554c09 100644 --- a/src/apps/debugger/WatchpointManager.cpp +++ b/src/apps/debugger/WatchpointManager.cpp @@ -74,6 +74,12 @@ WatchpointManager::InstallWatchpoint(Watchpoint* watchpoint, watchpoint->SetInstalled(false); } + if (error == B_OK) { + if (fTeam->WatchpointAtAddress(watchpoint->Address()) == NULL) + fTeam->AddWatchpoint(watchpoint); + fTeam->NotifyWatchpointChanged(watchpoint); + } + return error; } @@ -84,12 +90,16 @@ WatchpointManager::UninstallWatchpoint(Watchpoint* watchpoint) AutoLocker installLocker(fLock); AutoLocker teamLocker(fTeam); + fTeam->RemoveWatchpoint(watchpoint); + if (!watchpoint->IsInstalled()) return; status_t error = fDebuggerInterface->UninstallWatchpoint( watchpoint->Address()); - if (error == B_OK) + if (error == B_OK) { watchpoint->SetInstalled(false); -} \ No newline at end of file + fTeam->NotifyWatchpointChanged(watchpoint); + } +} diff --git a/src/apps/debugger/model/Team.cpp b/src/apps/debugger/model/Team.cpp index 3a379c20e1..0f3a6a240a 100644 --- a/src/apps/debugger/model/Team.cpp +++ b/src/apps/debugger/model/Team.cpp @@ -92,6 +92,9 @@ Team::~Team() for (int32 i = 0; Breakpoint* breakpoint = fBreakpoints.ItemAt(i); i++) breakpoint->ReleaseReference(); + for (int32 i = 0; Watchpoint* watchpoint = fWatchpoints.ItemAt(i); i++) + watchpoint->ReleaseReference(); + while (Image* image = fImages.RemoveHead()) image->ReleaseReference(); diff --git a/src/apps/debugger/model/Team.h b/src/apps/debugger/model/Team.h index 03dd5f5038..d11e76728f 100644 --- a/src/apps/debugger/model/Team.h +++ b/src/apps/debugger/model/Team.h @@ -145,6 +145,8 @@ public: TargetAddressRange range, BObjectList& watchpoints) const; + const WatchpointList& Watchpoints() const + { return fWatchpoints; } status_t GetStatementAtAddress(target_addr_t address, FunctionInstance*& _function, @@ -187,7 +189,6 @@ private: typedef BObjectList BreakpointList; typedef DoublyLinkedList ListenerList; - typedef BObjectList WatchpointList; private: void _NotifyThreadAdded(Thread* thread); diff --git a/src/apps/debugger/model/Watchpoint.h b/src/apps/debugger/model/Watchpoint.h index a9d591f829..fa1ac20f19 100644 --- a/src/apps/debugger/model/Watchpoint.h +++ b/src/apps/debugger/model/Watchpoint.h @@ -6,6 +6,7 @@ #define WATCHPOINT_H +#include #include #include "types/Types.h" @@ -49,4 +50,7 @@ private: }; +typedef BObjectList WatchpointList; + + #endif // WATCHPOINT_H diff --git a/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.cpp b/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.cpp index a9ef8f870b..b1698c8f41 100644 --- a/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.cpp @@ -18,9 +18,10 @@ #include "GuiSettingsUtils.h" #include "LocatableFile.h" #include "table/TableColumns.h" +#include "TargetAddressTableColumn.h" #include "Team.h" #include "UserBreakpoint.h" -#include "TargetAddressTableColumn.h" +#include "Watchpoint.h" // #pragma mark - BreakpointsTableModel @@ -32,16 +33,18 @@ public: : fTeam(team) { - Update(NULL); + UpdateBreakpoint(NULL); + UpdateWatchpoint(NULL); } ~BreakpointsTableModel() { fTeam = NULL; - Update(NULL); + UpdateBreakpoint(NULL); + UpdateWatchpoint(NULL); } - bool Update(UserBreakpoint* changedBreakpoint) + bool UpdateBreakpoint(UserBreakpoint* changedBreakpoint) { if (fTeam == NULL) { for (int32 i = 0; @@ -93,6 +96,59 @@ public: return true; } + bool UpdateWatchpoint(Watchpoint* changedWatchpoint) + { + if (fTeam == NULL) { + for (int32 i = 0; + Watchpoint* watchpoint = fWatchpoints.ItemAt(i); + i++) { + watchpoint->ReleaseReference(); + } + fWatchpoints.MakeEmpty(); + + return true; + } + + AutoLocker locker(fTeam); + + int32 breakpointCount = fBreakpoints.CountItems(); + int32 index = 0; + int32 teamIndex = 0; + Watchpoint* newWatchpoint = fTeam->WatchpointAt(teamIndex); + // remove no longer existing breakpoints + while (Watchpoint* oldWatchpoint = fWatchpoints.ItemAt(index)) { + if (oldWatchpoint == newWatchpoint) { + if (oldWatchpoint == changedWatchpoint) + NotifyRowsChanged(index + breakpointCount, 1); + index++; + teamIndex++; + newWatchpoint = fTeam->WatchpointAt(teamIndex); + } else { + // TODO: Not particularly efficient! + fWatchpoints.RemoveItemAt(index); + oldWatchpoint->ReleaseReference(); + NotifyRowsRemoved(index + breakpointCount, 1); + } + } + + // add new breakpoints + int32 countBefore = fWatchpoints.CountItems(); + while (newWatchpoint != NULL) { + if (!fWatchpoints.AddItem(newWatchpoint)) + return false; + + newWatchpoint->AcquireReference(); + teamIndex++; + newWatchpoint = fTeam->WatchpointAt(teamIndex); + } + + int32 count = fWatchpoints.CountItems(); + if (count > countBefore) + NotifyRowsAdded(countBefore + breakpointCount, count - countBefore); + + return true; + } + virtual int32 CountColumns() const { return 5; @@ -100,10 +156,33 @@ public: virtual int32 CountRows() const { - return fBreakpoints.CountItems(); + return fBreakpoints.CountItems() + fWatchpoints.CountItems(); } virtual bool GetValueAt(int32 rowIndex, int32 columnIndex, BVariant& value) + { + int32 breakpointCount = fBreakpoints.CountItems(); + if (rowIndex < breakpointCount) + return _GetBreakpointValueAt(rowIndex, columnIndex, value); + + return _GetWatchpointValueAt(rowIndex - breakpointCount, columnIndex, + value); + } + + UserBreakpoint* BreakpointAt(int32 index) const + { + return fBreakpoints.ItemAt(index); + } + + Watchpoint* WatchpointAt(int32 index) const + { + return fWatchpoints.ItemAt(index - fBreakpoints.CountItems()); + } + +private: + + bool _GetBreakpointValueAt(int32 rowIndex, int32 columnIndex, + BVariant &value) { UserBreakpoint* breakpoint = fBreakpoints.ItemAt(rowIndex); if (breakpoint == NULL) @@ -145,14 +224,36 @@ public: } } - UserBreakpoint* BreakpointAt(int32 index) const + bool _GetWatchpointValueAt(int32 rowIndex, int32 columnIndex, + BVariant& value) { - return fBreakpoints.ItemAt(index); + Watchpoint* watchpoint = fWatchpoints.ItemAt(rowIndex); + if (watchpoint == NULL) + return false; + + switch (columnIndex) { + case 0: + value.SetTo((int32)watchpoint->IsEnabled()); + return true; + case 1: + value.SetTo("Watchpoint"); + return true; + case 2: + return false; + case 3: + return false; + case 4: + value.SetTo(watchpoint->Address()); + return true; + default: + return false; + } } private: Team* fTeam; BObjectList fBreakpoints; + BObjectList fWatchpoints; }; @@ -202,7 +303,8 @@ BreakpointListView::UnsetListener() void -BreakpointListView::SetBreakpoint(UserBreakpoint* breakpoint) +BreakpointListView::SetBreakpoint(UserBreakpoint* breakpoint, + Watchpoint* watchpoint) { if (breakpoint == fBreakpoint) return; @@ -232,7 +334,14 @@ BreakpointListView::SetBreakpoint(UserBreakpoint* breakpoint) void BreakpointListView::UserBreakpointChanged(UserBreakpoint* breakpoint) { - fBreakpointsTableModel->Update(breakpoint); + fBreakpointsTableModel->UpdateBreakpoint(breakpoint); +} + + +void +BreakpointListView::WatchpointChanged(Watchpoint* watchpoint) +{ + fBreakpointsTableModel->UpdateWatchpoint(watchpoint); } @@ -271,8 +380,13 @@ BreakpointListView::TableSelectionChanged(Table* table) TableSelectionModel* selectionModel = table->SelectionModel(); UserBreakpoint* breakpoint = fBreakpointsTableModel->BreakpointAt( selectionModel->RowAt(0)); - - fListener->BreakpointSelectionChanged(breakpoint); + if (breakpoint != NULL) + fListener->BreakpointSelectionChanged(breakpoint); + else { + Watchpoint* watchpoint = fBreakpointsTableModel->WatchpointAt( + selectionModel->RowAt(0)); + fListener->WatchpointSelectionChanged(watchpoint); + } } diff --git a/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.h b/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.h index 73ebc0e3bf..317ca5be71 100644 --- a/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.h +++ b/src/apps/debugger/user_interface/gui/team_window/BreakpointListView.h @@ -13,6 +13,7 @@ class Team; class UserBreakpoint; +class Watchpoint; class BreakpointListView : public BGroupView, private TableListener { @@ -29,9 +30,13 @@ public: void UnsetListener(); - void SetBreakpoint(UserBreakpoint* breakpoint); + void SetBreakpoint(UserBreakpoint* breakpoint, + Watchpoint* watchpoint); + void UserBreakpointChanged( UserBreakpoint* breakpoint); + void WatchpointChanged( + Watchpoint* breakpoint); void LoadSettings(const BMessage& settings); status_t SaveSettings(BMessage& settings); @@ -48,6 +53,7 @@ private: private: Team* fTeam; UserBreakpoint* fBreakpoint; + Watchpoint* fWatchpoint; Table* fBreakpointsTable; BreakpointsTableModel* fBreakpointsTableModel; Listener* fListener; @@ -60,6 +66,9 @@ public: virtual void BreakpointSelectionChanged( UserBreakpoint* breakpoint) = 0; + + virtual void WatchpointSelectionChanged( + Watchpoint* watchpoint) = 0; }; diff --git a/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.cpp b/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.cpp index 176d6cab3b..f7e58e2ba1 100644 --- a/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.cpp @@ -68,20 +68,26 @@ BreakpointsView::UnsetListener() void -BreakpointsView::SetBreakpoint(UserBreakpoint* breakpoint) +BreakpointsView::SetBreakpoint(UserBreakpoint* breakpoint, Watchpoint* watchpoint) { - if (breakpoint == fBreakpoint) + if (breakpoint == fBreakpoint && watchpoint == fWatchpoint) return; + if (fWatchpoint != NULL) + fWatchpoint->ReleaseReference(); + if (fBreakpoint != NULL) fBreakpoint->ReleaseReference(); + fWatchpoint = watchpoint; fBreakpoint = breakpoint; if (fBreakpoint != NULL) fBreakpoint->AcquireReference(); + else if (fWatchpoint != NULL) + fWatchpoint->AcquireReference(); - fListView->SetBreakpoint(breakpoint); + fListView->SetBreakpoint(breakpoint, watchpoint); _UpdateButtons(); } @@ -96,21 +102,49 @@ BreakpointsView::UserBreakpointChanged(UserBreakpoint* breakpoint) } +void +BreakpointsView::WatchpointChanged(Watchpoint* watchpoint) +{ + fListView->WatchpointChanged(watchpoint); + + _UpdateButtons(); +} + + void BreakpointsView::MessageReceived(BMessage* message) { switch (message->what) { case MSG_ENABLE_BREAKPOINT: - if (fListener != NULL && fBreakpoint != NULL) - fListener->SetBreakpointEnabledRequested(fBreakpoint, true); + if (fListener != NULL) { + if (fBreakpoint != NULL) { + fListener->SetBreakpointEnabledRequested(fBreakpoint, + true); + } else if (fWatchpoint != NULL) { + fListener->SetWatchpointEnabledRequested(fWatchpoint, + true); + } + } break; case MSG_DISABLE_BREAKPOINT: - if (fListener != NULL && fBreakpoint != NULL) - fListener->SetBreakpointEnabledRequested(fBreakpoint, false); + if (fListener != NULL) { + if (fBreakpoint != NULL) { + fListener->SetBreakpointEnabledRequested(fBreakpoint, + false); + } else if (fWatchpoint != NULL) { + fListener->SetWatchpointEnabledRequested(fWatchpoint, + false); + } + } break; case MSG_CLEAR_BREAKPOINT: - if (fListener != NULL && fBreakpoint != NULL) - fListener->ClearBreakpointRequested(fBreakpoint); + if (fListener != NULL) { + if (fBreakpoint != NULL) { + fListener->ClearBreakpointRequested(fBreakpoint); + } else if (fWatchpoint != NULL) { + fListener->ClearWatchpointRequested(fWatchpoint); + } + } break; default: BGroupView::MessageReceived(message); @@ -159,6 +193,14 @@ BreakpointsView::BreakpointSelectionChanged(UserBreakpoint* breakpoint) } +void +BreakpointsView::WatchpointSelectionChanged(Watchpoint* watchpoint) +{ + if (fListener != NULL) + fListener->WatchpointSelectionChanged(watchpoint); +} + + void BreakpointsView::_Init() { @@ -182,8 +224,19 @@ BreakpointsView::_UpdateButtons() { AutoLocker teamLocker(fTeam); + bool enabled = false; + bool valid = false; + if (fBreakpoint != NULL && fBreakpoint->IsValid()) { - if (fBreakpoint->IsEnabled()) { + valid = true; + enabled = fBreakpoint->IsEnabled(); + } else if (fWatchpoint != NULL) { + valid = true; + enabled = fWatchpoint->IsEnabled(); + } + + if (valid) { + if (enabled) { fToggleBreakpointButton->SetLabel("Disable"); fToggleBreakpointButton->SetMessage( new BMessage(MSG_DISABLE_BREAKPOINT)); diff --git a/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.h b/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.h index 2240252ee7..02bef310b6 100644 --- a/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.h +++ b/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.h @@ -28,9 +28,13 @@ public: void UnsetListener(); - void SetBreakpoint(UserBreakpoint* breakpoint); + void SetBreakpoint(UserBreakpoint* breakpoint, + Watchpoint* watchpoint); + void UserBreakpointChanged( UserBreakpoint* breakpoint); + void WatchpointChanged( + Watchpoint* watchpoint); virtual void MessageReceived(BMessage* message); virtual void AttachedToWindow(); @@ -42,6 +46,8 @@ private: // BreakpointListView::Listener virtual void BreakpointSelectionChanged( UserBreakpoint* breakpoint); + virtual void WatchpointSelectionChanged( + Watchpoint* watchpoint); void _Init(); @@ -50,6 +56,7 @@ private: private: Team* fTeam; UserBreakpoint* fBreakpoint; + Watchpoint* fWatchpoint; BreakpointListView* fListView; BButton* fToggleBreakpointButton; BButton* fRemoveBreakpointButton; @@ -57,6 +64,7 @@ private: }; + class BreakpointsView::Listener { public: virtual ~Listener(); @@ -68,6 +76,14 @@ public: bool enabled) = 0; virtual void ClearBreakpointRequested( UserBreakpoint* breakpoint) = 0; + + virtual void WatchpointSelectionChanged( + Watchpoint* Watchpoint) = 0; + virtual void SetWatchpointEnabledRequested( + Watchpoint* breakpoint, + bool enabled) = 0; + virtual void ClearWatchpointRequested( + Watchpoint* watchpoint) = 0; }; diff --git a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp index 1fc4fd86dc..862895233b 100644 --- a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp @@ -356,6 +356,18 @@ TeamWindow::MessageReceived(BMessage* message) break; } + case MSG_WATCHPOINT_CHANGED: + { + Watchpoint* watchpoint; + if (message->FindPointer("watchpoint", (void**)&watchpoint) != B_OK) + break; + BReference watchpointReference(watchpoint, true); + + _HandleWatchpointChanged(watchpoint); + break; + + } + case MSG_FUNCTION_SOURCE_CODE_CHANGED: { _HandleSourceCodeChanged(); @@ -584,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) @@ -640,6 +674,18 @@ TeamWindow::UserBreakpointChanged(const Team::UserBreakpointEvent& event) } +void +TeamWindow::WatchpointChanged(const Team::WatchpointEvent& event) +{ + BMessage message(MSG_WATCHPOINT_CHANGED); + BReference watchpointReference(event.GetWatchpoint()); + if (message.AddPointer("watchpoint", event.GetWatchpoint()) == B_OK + && PostMessage(&message) == B_OK) { + watchpointReference.Detach(); + } +} + + void TeamWindow::FunctionSourceCodeChanged(Function* function) { @@ -923,7 +969,7 @@ TeamWindow::_SetActiveBreakpoint(UserBreakpoint* breakpoint) _ScrollToActiveFunction(); } - fBreakpointsView->SetBreakpoint(fActiveBreakpoint); + fBreakpointsView->SetBreakpoint(fActiveBreakpoint, NULL); } @@ -1266,6 +1312,13 @@ TeamWindow::_HandleUserBreakpointChanged(UserBreakpoint* breakpoint) } +void +TeamWindow::_HandleWatchpointChanged(Watchpoint* watchpoint) +{ + fBreakpointsView->WatchpointChanged(watchpoint); +} + + void TeamWindow::_HandleResolveMissingSourceFile(entry_ref& locatedPath) { diff --git a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h index 9d979723e6..d371a5b694 100644 --- a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h +++ b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h @@ -95,6 +95,15 @@ private: virtual void ClearBreakpointRequested( UserBreakpoint* breakpoint); + virtual void WatchpointSelectionChanged( + Watchpoint* Watchpoint); + virtual void SetWatchpointEnabledRequested( + Watchpoint* breakpoint, + bool enabled); + virtual void ClearWatchpointRequested( + Watchpoint* watchpoint); + + // SourceView::Listener virtual void SetBreakpointRequested(target_addr_t address, bool enabled); @@ -116,6 +125,8 @@ private: const Team::ImageEvent& event); virtual void UserBreakpointChanged( const Team::UserBreakpointEvent& event); + virtual void WatchpointChanged( + const Team::WatchpointEvent& event); // Function::Listener virtual void FunctionSourceCodeChanged(Function* function); @@ -142,6 +153,8 @@ private: void _HandleSourceCodeChanged(); void _HandleUserBreakpointChanged( UserBreakpoint* breakpoint); + void _HandleWatchpointChanged( + Watchpoint* watchpoint); void _HandleResolveMissingSourceFile(entry_ref& locatedPath); From 0ba9bff27d88633aa0f9a6477342aa79fccbf4f7 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Wed, 7 Nov 2012 15:26:18 +0100 Subject: [PATCH 16/31] Revert preservation of watchpoints in settings. --- src/apps/debugger/Jamfile | 1 - src/apps/debugger/TeamDebugger.cpp | 17 +-- src/apps/debugger/settings/TeamSettings.cpp | 77 -------------- src/apps/debugger/settings/TeamSettings.h | 6 -- .../debugger/settings/WatchpointSetting.cpp | 100 ------------------ .../debugger/settings/WatchpointSetting.h | 46 -------- 6 files changed, 1 insertion(+), 246 deletions(-) delete mode 100644 src/apps/debugger/settings/WatchpointSetting.cpp delete mode 100644 src/apps/debugger/settings/WatchpointSetting.h diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 167979b6e7..7ee2bf140b 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -150,7 +150,6 @@ Application Debugger : TeamSettings.cpp TeamUiSettings.cpp TeamUiSettingsFactory.cpp - WatchpointSetting.cpp # settings/generic Setting.cpp diff --git a/src/apps/debugger/TeamDebugger.cpp b/src/apps/debugger/TeamDebugger.cpp index 26378e1019..e316d8b7f8 100644 --- a/src/apps/debugger/TeamDebugger.cpp +++ b/src/apps/debugger/TeamDebugger.cpp @@ -46,7 +46,7 @@ #include "ValueNodeContainer.h" #include "Variable.h" #include "WatchpointManager.h" -#include "WatchpointSetting.h" + // #pragma mark - ImageHandler @@ -1583,21 +1583,6 @@ TeamDebugger::_LoadSettings() breakpointSetting->IsEnabled()); } - // create the saved watchpoints; - for (int32 i = 0; const WatchpointSetting* watchpointSetting - = fTeamSettings.WatchpointAt(i); i++) { - Watchpoint* watchpoint = new(std::nothrow) Watchpoint( - watchpointSetting->Address(), watchpointSetting->Type(), - watchpointSetting->Length()); - if (watchpoint == NULL) - return; - BReference watchpointReference(watchpoint, true); - - // install it - fWatchpointManager->InstallWatchpoint(watchpoint, - watchpointSetting->IsEnabled()); - } - const TeamUiSettings* uiSettings = fTeamSettings.UiSettingFor( fUserInterface->ID()); if (uiSettings != NULL) diff --git a/src/apps/debugger/settings/TeamSettings.cpp b/src/apps/debugger/settings/TeamSettings.cpp index c379f40054..605202dcf8 100644 --- a/src/apps/debugger/settings/TeamSettings.cpp +++ b/src/apps/debugger/settings/TeamSettings.cpp @@ -18,7 +18,6 @@ #include "TeamUiSettings.h" #include "TeamUiSettingsFactory.h" #include "UserBreakpoint.h" -#include "WatchpointSetting.h" TeamSettings::TeamSettings() @@ -71,23 +70,6 @@ TeamSettings::SetTo(Team* team) } } - // add watchpoints - for (int32 i = 0; Watchpoint* watchpoint = team->WatchpointAt(i); i++) { - WatchpointSetting* watchpointSetting - = new(std::nothrow) WatchpointSetting; - if (watchpointSetting == NULL) - return B_NO_MEMORY; - - status_t error = watchpointSetting->SetTo(*watchpoint, - watchpoint->IsEnabled()); - if (error == B_OK && !fWatchpoints.AddItem(watchpointSetting)) - error = B_NO_MEMORY; - if (error != B_OK) { - delete watchpointSetting; - return error; - } - } - return B_OK; } @@ -119,24 +101,6 @@ TeamSettings::SetTo(const BMessage& archive) } } - // add watchpoints - for (int32 i = 0; archive.FindMessage("watchpoints", i, &childArchive) - == B_OK; i++) { - WatchpointSetting* watchpointSetting - = new(std::nothrow) WatchpointSetting; - if (watchpointSetting == NULL) - return B_NO_MEMORY; - - error = watchpointSetting->SetTo(childArchive); - if (error == B_OK && !fWatchpoints.AddItem(watchpointSetting)) - error = B_NO_MEMORY; - if (error != B_OK) { - delete watchpointSetting; - return error; - } - } - - // add UI settings for (int32 i = 0; archive.FindMessage("uisettings", i, &childArchive) == B_OK; i++) { @@ -173,17 +137,6 @@ TeamSettings::WriteTo(BMessage& archive) const return error; } - for (int32 i = 0; WatchpointSetting* watchpoint = fWatchpoints.ItemAt(i); - i++) { - error = watchpoint->WriteTo(childArchive); - if (error != B_OK) - return error; - - error = archive.AddMessage("watchpoints", &childArchive); - if (error != B_OK) - return error; - } - for (int32 i = 0; TeamUiSettings* uiSetting = fUiSettings.ItemAt(i); i++) { error = uiSetting->WriteTo(childArchive); @@ -213,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 { @@ -284,16 +223,6 @@ TeamSettings::operator=(const TeamSettings& other) } } - for (int32 i = 0; WatchpointSetting* watchpoint - = other.fWatchpoints.ItemAt(i); i++) { - WatchpointSetting* clonedWatchpoint - = new WatchpointSetting(*watchpoint); - if (!fWatchpoints.AddItem(clonedWatchpoint)) { - delete clonedWatchpoint; - throw std::bad_alloc(); - } - } - for (int32 i = 0; TeamUiSettings* uiSetting = other.fUiSettings.ItemAt(i); i++) { TeamUiSettings* clonedSetting @@ -316,16 +245,10 @@ TeamSettings::_Unset() delete breakpoint; } - for (int32 i = 0; WatchpointSetting* watchpoint = fWatchpoints.ItemAt(i); - i++) { - delete watchpoint; - } - for (int32 i = 0; TeamUiSettings* uiSetting = fUiSettings.ItemAt(i); i++) delete uiSetting; fBreakpoints.MakeEmpty(); - fWatchpoints.MakeEmpty(); fUiSettings.MakeEmpty(); fTeamName.Truncate(0); diff --git a/src/apps/debugger/settings/TeamSettings.h b/src/apps/debugger/settings/TeamSettings.h index 3bc74e3d87..f41f2bf8bd 100644 --- a/src/apps/debugger/settings/TeamSettings.h +++ b/src/apps/debugger/settings/TeamSettings.h @@ -15,7 +15,6 @@ class BMessage; class Team; class BreakpointSetting; class TeamUiSettings; -class WatchpointSetting; class TeamSettings { @@ -34,9 +33,6 @@ public: int32 CountBreakpoints() const; const BreakpointSetting* BreakpointAt(int32 index) const; - int32 CountWatchpoints() const; - const WatchpointSetting* WatchpointAt(int32 index) const; - int32 CountUiSettings() const; const TeamUiSettings* UiSettingAt(int32 index) const; const TeamUiSettings* UiSettingFor(const char* id) const; @@ -48,14 +44,12 @@ public: private: typedef BObjectList BreakpointList; typedef BObjectList UiSettingsList; - typedef BObjectList WatchpointList; private: void _Unset(); private: BreakpointList fBreakpoints; - WatchpointList fWatchpoints; UiSettingsList fUiSettings; BString fTeamName; }; diff --git a/src/apps/debugger/settings/WatchpointSetting.cpp b/src/apps/debugger/settings/WatchpointSetting.cpp deleted file mode 100644 index 0872e148dd..0000000000 --- a/src/apps/debugger/settings/WatchpointSetting.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2012, Rene Gollent, rene@gollent.com. - * Distributed under the terms of the MIT License. - */ - - -#include "WatchpointSetting.h" - -#include - -#include "Watchpoint.h" - - -WatchpointSetting::WatchpointSetting() - : - fAddress(0), - fType(0), - fLength(0), - fEnabled(false) -{ -} - - -WatchpointSetting::WatchpointSetting(const WatchpointSetting& other) - : - fAddress(other.fAddress), - fType(other.fType), - fLength(other.fLength), - fEnabled(other.fEnabled) -{ -} - - -WatchpointSetting::~WatchpointSetting() -{ -} - - -status_t -WatchpointSetting::SetTo(const Watchpoint& watchpoint, bool enabled) -{ - fAddress = watchpoint.Address(); - fType = watchpoint.Type(); - fLength = watchpoint.Length(); - fEnabled = enabled; - - return B_OK; -} - - -status_t -WatchpointSetting::SetTo(const BMessage& archive) -{ - if (archive.FindUInt64("address", &fAddress) != B_OK) - fAddress = 0; - - if (archive.FindUInt32("type", &fType) != B_OK) - fType = 0; - - if (archive.FindInt32("length", &fLength) != B_OK) - fLength = 0; - - if (archive.FindBool("enabled", &fEnabled) != B_OK) - fEnabled = false; - - return B_OK; -} - - -status_t -WatchpointSetting::WriteTo(BMessage& archive) const -{ - archive.MakeEmpty(); - - status_t error; - if ((error = archive.AddUInt64("address", fAddress)) != B_OK - || (error = archive.AddUInt32("type", fType)) != B_OK - || (error = archive.AddInt32("length", fLength)) != B_OK - || (error = archive.AddBool("enabled", fEnabled)) != B_OK) { - return error; - } - - return B_OK; -} - - -WatchpointSetting& -WatchpointSetting::operator=(const WatchpointSetting& other) -{ - if (this == &other) - return *this; - - fAddress = other.fAddress; - fType = other.fType; - fLength = other.fLength; - fEnabled = other.fEnabled; - - return *this; -} diff --git a/src/apps/debugger/settings/WatchpointSetting.h b/src/apps/debugger/settings/WatchpointSetting.h deleted file mode 100644 index 14fd16ceb4..0000000000 --- a/src/apps/debugger/settings/WatchpointSetting.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2012, Rene Gollent, rene@gollent.com. - * Distributed under the terms of the MIT License. - */ -#ifndef WATCHPOINT_SETTING_H -#define WATCHPOINT_SETTING_H - - -#include - -#include "types/Types.h" - -class BMessage; -class Watchpoint; - - -class WatchpointSetting { -public: - WatchpointSetting(); - WatchpointSetting( - const WatchpointSetting& other); - ~WatchpointSetting(); - - status_t SetTo(const Watchpoint& watchpoint, - bool enabled); - status_t SetTo(const BMessage& archive); - status_t WriteTo(BMessage& archive) const; - - target_addr_t Address() const { return fAddress; } - uint32 Type() const { return fType; } - int32 Length() const { return fLength; } - - bool IsEnabled() const { return fEnabled; } - - WatchpointSetting& operator=(const WatchpointSetting& other); - -private: - target_addr_t fAddress; - uint32 fType; - int32 fLength; - bool fEnabled; -}; - - -#endif // BREAKPOINT_SETTING_H From 0e5d97e97e32eae4023d4223d6ac6527c76cabd7 Mon Sep 17 00:00:00 2001 From: "Ithamar R. Adema" Date: Tue, 6 Nov 2012 11:01:13 +0100 Subject: [PATCH 17/31] ARM/vm: small formatting change and trace fix. Copy some minor changes over from the X86 paging implementation to keep the two reasonably aligned. Smaller diff ;-) --- .../kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp b/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp index 9214286f02..cfcd630dd5 100644 --- a/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp +++ b/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp @@ -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; From ff163585ecf0e47c4b411129fdc13572db53cd9d Mon Sep 17 00:00:00 2001 From: "Ithamar R. Adema" Date: Tue, 6 Nov 2012 11:02:54 +0100 Subject: [PATCH 18/31] ARM/threads: Disable debug output Tracing was accidently switched on by a previous commit. --- src/system/kernel/arch/arm/arch_thread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/system/kernel/arch/arm/arch_thread.cpp b/src/system/kernel/arch/arm/arch_thread.cpp index 2ae92ae4cc..3f7950e380 100644 --- a/src/system/kernel/arch/arm/arch_thread.cpp +++ b/src/system/kernel/arch/arm/arch_thread.cpp @@ -28,7 +28,7 @@ #include -#define TRACE_ARCH_THREAD +//#define TRACE_ARCH_THREAD #ifdef TRACE_ARCH_THREAD # define TRACE(x) dprintf x #else From 0cf5ecba126fe8215db0b079adfb1a6f9ac49e11 Mon Sep 17 00:00:00 2001 From: "Ithamar R. Adema" Date: Tue, 6 Nov 2012 11:06:04 +0100 Subject: [PATCH 19/31] ARM: Add asm_offsets.cpp This will generate asm_offsets.h which makes our assembly code easier to maintain by preventing hardcoded offsets for fields within structures. (copied from X86 and removed the X86 specifics) --- src/system/kernel/arch/arm/asm_offsets.cpp | 62 ++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/system/kernel/arch/arm/asm_offsets.cpp diff --git a/src/system/kernel/arch/arm/asm_offsets.cpp b/src/system/kernel/arch/arm/asm_offsets.cpp new file mode 100644 index 0000000000..64e85057d7 --- /dev/null +++ b/src/system/kernel/arch/arm/asm_offsets.cpp @@ -0,0 +1,62 @@ +/* + * Copyright 2007-2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +// This file is used to get C structure offsets into assembly code. +// The build system assembles the file and processes the output to create +// a header file with macro definitions, that can be included from assembly +// code. + + +#include + +#include +#include +#include +#include +#include + + +#define DEFINE_MACRO(macro, value) DEFINE_COMPUTED_ASM_MACRO(macro, value) + +#define DEFINE_OFFSET_MACRO(prefix, structure, member) \ + DEFINE_MACRO(prefix##_##member, offsetof(struct structure, member)); + +#define DEFINE_SIZEOF_MACRO(prefix, structure) \ + DEFINE_MACRO(prefix##_sizeof, sizeof(struct structure)); + + +void +dummy() +{ + // struct cpu_ent + DEFINE_OFFSET_MACRO(CPU_ENT, cpu_ent, fault_handler); + DEFINE_OFFSET_MACRO(CPU_ENT, cpu_ent, fault_handler_stack_pointer); + + // struct Thread + DEFINE_OFFSET_MACRO(THREAD, Thread, time_lock); + DEFINE_OFFSET_MACRO(THREAD, Thread, kernel_time); + DEFINE_OFFSET_MACRO(THREAD, Thread, user_time); + DEFINE_OFFSET_MACRO(THREAD, Thread, last_time); + DEFINE_OFFSET_MACRO(THREAD, Thread, in_kernel); + DEFINE_OFFSET_MACRO(THREAD, Thread, flags); + DEFINE_OFFSET_MACRO(THREAD, Thread, kernel_stack_top); + DEFINE_OFFSET_MACRO(THREAD, Thread, fault_handler); + + // struct iframe + DEFINE_SIZEOF_MACRO(IFRAME, iframe); + + // struct signal_frame_data + DEFINE_SIZEOF_MACRO(SIGNAL_FRAME_DATA, signal_frame_data); + DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, info); + DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, context); + DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, user_data); + DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, handler); + + // struct ucontext_t + DEFINE_OFFSET_MACRO(UCONTEXT_T, __ucontext_t, uc_mcontext); + + // struct siginfo_t + DEFINE_OFFSET_MACRO(SIGINFO_T, __siginfo_t, si_signo); +} From f86b5828486b661145eb15952ec14648c9bb8d9b Mon Sep 17 00:00:00 2001 From: "Ithamar R. Adema" Date: Tue, 6 Nov 2012 11:41:12 +0100 Subject: [PATCH 20/31] ARM: Cleanup of port support code. This also implements the fault handler correctly now, and cleans up the exception handling. Seems a lot more stable now, no unexpected panics or faults happening anymore. --- headers/private/kernel/arch/arm/arch_cpu.h | 22 +- src/system/kernel/arch/arm/arch_asm.S | 80 +++++- src/system/kernel/arch/arm/arch_debug.cpp | 23 +- src/system/kernel/arch/arm/arch_exceptions.S | 252 +++++++++++------- src/system/kernel/arch/arm/arch_int.cpp | 165 ++++++++---- src/system/kernel/arch/arm/arch_platform.cpp | 43 +-- src/system/kernel/arch/arm/arch_timer.cpp | 14 +- .../arm/paging/32bit/ARMPagingMethod32Bit.cpp | 2 +- .../paging/32bit/ARMVMTranslationMap32Bit.cpp | 49 ++-- 9 files changed, 400 insertions(+), 250 deletions(-) diff --git a/headers/private/kernel/arch/arm/arch_cpu.h b/headers/private/kernel/arch/arm/arch_cpu.h index 97ae14637c..34364a8004 100644 --- a/headers/private/kernel/arch/arm/arch_cpu.h +++ b/headers/private/kernel/arch/arm/arch_cpu.h @@ -12,6 +12,7 @@ /* raw exception frames */ struct iframe { + uint32 spsr; uint32 r0; uint32 r1; uint32 r2; @@ -25,10 +26,11 @@ struct iframe { uint32 r10; uint32 r11; uint32 r12; - uint32 r13; - uint32 lr; + uint32 usr_sp; + uint32 usr_lr; + uint32 svc_sp; + uint32 svc_lr; uint32 pc; - uint32 cpsr; } _PACKED; typedef struct arch_cpu_info { @@ -40,6 +42,20 @@ extern int arch_mmu_type; extern int arch_platform; extern int arch_machine; +#ifdef __cplusplus +extern "C" { +#endif + +extern addr_t arm_get_far(void); +extern int32 arm_get_fsr(void); + +extern int mmu_read_c1(void); +extern int mmu_write_c1(int val); + +#ifdef __cplusplus +}; +#endif + #endif // !_ASSEMBLER #endif /* _KERNEL_ARCH_ARM_CPU_H */ diff --git a/src/system/kernel/arch/arm/arch_asm.S b/src/system/kernel/arch/arm/arch_asm.S index c417a91742..c51089c718 100644 --- a/src/system/kernel/arch/arm/arch_asm.S +++ b/src/system/kernel/arch/arm/arch_asm.S @@ -10,21 +10,38 @@ #include +#include "asm_offsets.h" + .text +/* int mmu_read_c1(void); */ +FUNCTION(mmu_read_c1): + mrc p15, 0, r0, c1, c0, 0 + bx lr +FUNCTION_END(mmu_read_c1) + + +/* void mmu_write_c1(int val); */ +FUNCTION(mmu_write_c1): + mcr p15, 0, r0, c1, c0, 0 + bx lr +FUNCTION_END(mmu_write_c1) + + +/* NOTE: the I bit in cpsr (bit 7) is *set* to disable... */ + /* void arch_int_enable_interrupts(void) */ FUNCTION(arch_int_enable_interrupts): mrs r0, cpsr - bic r0, r0, #(1<<7) /* clear the I bit */ + bic r0, r0, #(1<<7) msr cpsr_c, r0 bx lr FUNCTION_END(arch_int_enable_interrupts) -/* int arch_int_disable_interrupts(void) - */ +/* int arch_int_disable_interrupts(void) */ FUNCTION(arch_int_disable_interrupts): mrs r0, cpsr orr r1, r0, #(1<<7) @@ -33,8 +50,7 @@ FUNCTION(arch_int_disable_interrupts): FUNCTION_END(arch_int_disable_interrupts) -/* void arch_int_restore_interrupts(int oldState) - */ +/* void arch_int_restore_interrupts(int oldState) */ FUNCTION(arch_int_restore_interrupts): mrs r1, cpsr and r0, r0, #(1<<7) @@ -65,3 +81,57 @@ FUNCTION(arm_context_switch): ldmfd sp!, { r0-r12, lr } bx lr FUNCTION_END(arm_context_switch) + +/* addr_t arm_get_fsr(void); */ +FUNCTION(arm_get_fsr): + mrc p15, 0, r0, c5, c0, 0 @ get FSR + bx lr +FUNCTION_END(arm_get_fsr) + +/* addr_t arm_get_far(void); */ +FUNCTION(arm_get_far): + mrc p15, 0, r0, c6, c0, 0 @ get FAR + bx lr +FUNCTION_END(arm_get_far) + +/*! \fn void arch_debug_call_with_fault_handler(cpu_ent* cpu, + jmp_buf jumpBuffer, void (*function)(void*), void* parameter) + + Called by debug_call_with_fault_handler() to do the dirty work of setting + the fault handler and calling the function. If the function causes a page + fault, the arch_debug_call_with_fault_handler() calls longjmp() with the + given \a jumpBuffer. Otherwise it returns normally. + + debug_call_with_fault_handler() has already saved the CPU's fault_handler + and fault_handler_stack_pointer and will reset them later, so + arch_debug_call_with_fault_handler() doesn't need to care about it. + + \param cpu The \c cpu_ent for the current CPU. + \param jumpBuffer Buffer to be used for longjmp(). + \param function The function to be called. + \param parameter The parameter to be passed to the function to be called. +*/ +FUNCTION(arch_debug_call_with_fault_handler): + stmfd sp!, { r4, lr } + + // Set fault handler address, and fault handler stack pointer address. We + // don't need to save the previous values, since that's done by the caller. + ldr r4, =1f + str r4, [ r0, #CPU_ENT_fault_handler ] + str sp, [ r0, #CPU_ENT_fault_handler_stack_pointer ] + mov r4, r1 + + // call the function + mov r0, r3 + blx r2 + + // regular return + ldmfd sp!, { r4, lr } + bx lr + + // fault -- return via longjmp(jumpBuffer, 1) +1: + mov r0, r4 + mov r1, #1 + bl longjmp +FUNCTION_END(arch_debug_call_with_fault_handler) diff --git a/src/system/kernel/arch/arm/arch_debug.cpp b/src/system/kernel/arch/arm/arch_debug.cpp index 0b6449053a..daae859148 100644 --- a/src/system/kernel/arch/arm/arch_debug.cpp +++ b/src/system/kernel/arch/arm/arch_debug.cpp @@ -251,14 +251,9 @@ arch_debug_stack_trace(void) void * arch_debug_get_caller(void) { -#warning ARM:IMPLEMENT - // TODO: implement me - //return __builtin_frame_address(1); -// struct stack_frame *frame; - //frame = __builtin_frame_address(0); -// frame = get_current_stack_frame(); -// return (void *)frame->previous->return_address; - return NULL; + /* Return the thread id as the kernel (for example the lock code) actually + gets a somewhat valid indication of the caller back. */ + return (void*) thread_get_current_thread_id(); } @@ -316,17 +311,7 @@ arch_debug_init(kernel_args *args) } -void -arch_debug_call_with_fault_handler(cpu_ent* cpu, jmp_buf jumpBuffer, - void (*function)(void*), void* parameter) -{ - // TODO: Implement fault handling! Most likely in assembly. - // (see src/system/kernel/arch/x86/arch_x86.S) - - // For now, just call the function and hope we don't crash :P - function(parameter); -} - +/* arch_debug_call_with_fault_handler is in arch_asm.S */ void arch_debug_unset_current_thread(void) diff --git a/src/system/kernel/arch/arm/arch_exceptions.S b/src/system/kernel/arch/arm/arch_exceptions.S index cffb1f87f8..41a88d9f9c 100644 --- a/src/system/kernel/arch/arm/arch_exceptions.S +++ b/src/system/kernel/arch/arm/arch_exceptions.S @@ -9,6 +9,49 @@ #include +#define CPSR_MODE_MASK 0x1f +#define CPSR_MODE_USR 0x10 +#define CPSR_MODE_FIQ 0x11 +#define CPSR_MODE_IRQ 0x12 +#define CPSR_MODE_SVC 0x13 +#define CPSR_MODE_ABT 0x17 +#define CPSR_MODE_UND 0x1b + +/* The following two macros are taken from FreeBSD... */ + + .macro PUSHFRAMEINSVC + stmdb sp, {r0-r3} /* Save 4 registers */ + mov r0, lr /* Save xxx32 r14 */ + mov r1, sp /* Save xxx32 sp */ + mrs r3, spsr /* Save xxx32 spsr */ + mrs r2, cpsr /* Get the CPSR */ + bic r2, r2, #(CPSR_MODE_MASK)/* Fix for SVC mode */ + orr r2, r2, #(CPSR_MODE_SVC) + msr cpsr_c, r2 /* Punch into SVC mode */ + mov r2, sp /* Save SVC sp */ + str r0, [sp, #-4]! /* Push return address */ + str lr, [sp, #-4]! /* Push SVC lr */ + str r2, [sp, #-4]! /* Push SVC sp */ + msr spsr_all, r3 /* Restore correct spsr */ + ldmdb r1, {r0-r3} /* Restore 4 regs from xxx mode */ + sub sp, sp, #(4*15) /* Adjust the stack pointer */ + stmia sp, {r0-r12} /* Push the user mode registers */ + add r0, sp, #(4*13) /* Adjust the stack pointer */ + stmia r0, {r13-r14}^ /* Push the user mode registers */ + mov r0, r0 /* NOP for previous instruction */ + mrs r0, spsr_all + str r0, [sp, #-4]! /* Save spsr */ + .endm + + .macro PULLFRAMEFROMSVCANDEXIT + ldr r0, [sp], #0x0004 /* Get the SPSR from stack */ + msr spsr_all, r0 /* restore SPSR */ + ldmia sp, {r0-r14}^ /* Restore registers (usr mode) */ + mov r0, r0 /* NOP for previous instruction */ + add sp, sp, #(4*15) /* Adjust the stack pointer */ + ldmia sp, {sp, lr, pc}^ /* Restore lr and exit */ + .endm + .text .globl _vectors_start @@ -43,134 +86,139 @@ _vectors_end: .rept 64 - .word 0xaabbccdd + .word 0xdeadbeef .endr abort_stack: - .word . + .word . - 4 + .word 0xdeadbeef + + .rept 64 + .word 0xcafebabe + .endr +irq_stack: + .word . - 4 + .word 0xcafebabe + + .rept 64 + .word 0xaaaabbbb + .endr +fiq_stack: + .word . - 4 + .word 0xaaaabbbb + + .rept 64 + .word 0xccccdddd + .endr +und_stack: + .word . - 4 + .word 0xccccdddd + FUNCTION(arm_undefined): - stmfd sp!, { r0-r12, r14 } - sub sp, sp, #12 - mov r0, sp - mrs r1, spsr - stmia r0, { r1, r13-r14 } - b arch_arm_undefined - b . + PUSHFRAMEINSVC + + mov r0, sp + bl arch_arm_undefined + + PULLFRAMEFROMSVCANDEXIT +FUNCTION_END(arm_undefined) + FUNCTION(arm_syscall): - stmfd sp!, { r0-r12, r14 } - sub sp, sp, #12 - mov r0, sp - mrs r1, spsr - stmia r0, { r1, r13-r14 } - b arch_arm_syscall - b . - + PUSHFRAMEINSVC + + mov r0, sp + bl arch_arm_syscall + + PULLFRAMEFROMSVCANDEXIT +FUNCTION_END(arm_syscall) + + FUNCTION(arm_prefetch_abort): - ldr sp, abort_stack - stmfd sp!, { r0-r12, r14 } - sub sp, sp, #12 - mov r0, sp - mrs r1, spsr - stmia r0, { r1, r13-r14 } - b arch_arm_prefetch_abort - b . +#ifdef __XSCALE__ + nop /* Make absolutely sure any pending */ + nop /* imprecise aborts have occurred. */ +#endif + add lr, lr, #4 + PUSHFRAMEINSVC + + mov r0, sp + bl arch_arm_prefetch_abort + + PULLFRAMEFROMSVCANDEXIT +FUNCTION_END(arm_prefetch_abort) + FUNCTION(arm_data_abort): - ldr sp, abort_stack - /* XXX only deals with interrupting supervisor mode */ +#ifdef __XSCALE__ + nop /* Make absolutely sure any pending */ + nop /* imprecise aborts have occurred. */ +#endif + sub lr, lr, #8 /* Adjust the lr */ + PUSHFRAMEINSVC - /* save r4-r6 and use as a temporary place to save while we switch into supervisor mode */ - stmia r13, { r4-r6 } - mov r4, r13 - sub r5, lr, #8 - mrs r6, spsr - - /* move into supervisor mode. irq/fiq disabled */ - msr cpsr_c, #0x13 - - /* save the return address */ - stmfd sp!, { r5 } - - /* save C trashed regs, supervisor lr */ - stmfd sp!, { r0-r3, r12, lr } - - /* save spsr */ - stmfd sp!, { r6 } - - /* restore r4-r6 */ - ldmia r4, { r4-r6 } - - /* call into higher level code */ - mrc p15, 0, r2, c5, c0, 0 @ get FSR - mrc p15, 0, r3, c6, c0, 0 @ get FAR - sub sp, sp, #20 - mov r0, sp /* iframe */ - stmia r0, { r6,r2,r3,r4,r5 } + mov r0, sp bl arch_arm_data_abort - add sp, sp, #20 - /* restore spsr */ - ldmfd sp!, { r0 } - msr spsr_cxsf, r0 + PULLFRAMEFROMSVCANDEXIT - /* restore back to where we came from */ - ldmfd sp!, { r0-r3, r12, lr, pc }^ FUNCTION(arm_reserved): b . - +FUNCTION_END(arm_reserved) + FUNCTION(arm_irq): - ldr sp, abort_stack - /* XXX only deals with interrupting supervisor mode */ + sub lr, lr, #4 + PUSHFRAMEINSVC - /* save r4-r6 and use as a temporary place to save while we switch into supervisor mode */ - stmia r13, { r4-r6 } - mov r4, r13 - sub r5, lr, #4 - mrs r6, spsr - - /* move into supervisor mode. irq/fiq disabled */ - msr cpsr_c, #(3<<6 | 0x13) - - /* save the return address */ - stmfd sp!, { r5 } - - /* save C trashed regs, supervisor lr */ - stmfd sp!, { r0-r3, r12, lr } - - /* save spsr */ - stmfd sp!, { r6 } - - /* restore r4-r6 */ - ldmia r4, { r4-r6 } - - /* call into higher level code */ mov r0, sp /* iframe */ bl arch_arm_irq - /* restore spsr */ - ldmfd sp!, { r0 } - msr spsr_cxsf, r0 + PULLFRAMEFROMSVCANDEXIT +FUNCTION_END(arm_irq) - /* restore back to where we came from */ - ldmfd sp!, { r0-r3, r12, lr, pc }^ -.bss -.align 2 - .global irq_save_spot -irq_save_spot: - .word 0 /* r4 */ - .word 0 /* r5 */ - .word 0 /* r6 */ - -.text FUNCTION(arm_fiq): - ldr sp, abort_stack sub lr, lr, #4 - stmfd sp!, { r0-r3, r12, lr } + PUSHFRAMEINSVC + mov r0, sp /* iframe */ bl arch_arm_fiq - ldmfd sp!, { r0-r3, r12, pc }^ + PULLFRAMEFROMSVCANDEXIT +FUNCTION_END(arm_fiq) + + +FUNCTION(arm_vector_init): + mrs r1, cpsr + bic r1, r1, #CPSR_MODE_MASK + + /* move into modes and set initial sp */ + mov r0, r1 + orr r0, r0, #CPSR_MODE_FIQ + msr cpsr_c, r0 + ldr sp, fiq_stack + + mov r0, r1 + orr r0, r0, #CPSR_MODE_IRQ + msr cpsr_c, r0 + ldr sp, irq_stack + + mov r0, r1 + orr r0, r0, #CPSR_MODE_ABT + msr cpsr_c, r0 + ldr sp, abort_stack + + mov r0, r1 + orr r0, r0, #CPSR_MODE_UND + msr cpsr_c, r0 + ldr sp, und_stack + + /* ... and return back to supervisor mode */ + mov r0, r1 + orr r0, r0, #CPSR_MODE_SVC + msr cpsr_c, r0 + + bx lr +FUNCTION_END(arm_vector_init) diff --git a/src/system/kernel/arch/arm/arch_int.cpp b/src/system/kernel/arch/arm/arch_int.cpp index 97a735aa4a..f61298d6f7 100644 --- a/src/system/kernel/arch/arm/arch_int.cpp +++ b/src/system/kernel/arch/arm/arch_int.cpp @@ -31,7 +31,7 @@ #include -#define TRACE_ARCH_INT +//#define TRACE_ARCH_INT #ifdef TRACE_ARCH_INT # define TRACE(x) dprintf x #else @@ -61,30 +61,11 @@ static void *sVectorPageAddress; static area_id sUserVectorPageArea; static void *sUserVectorPageAddress; -// current fault handler -addr_t gFaultHandler; - // An iframe stack used in the early boot process when we don't have // threads yet. struct iframe_stack gBootFrameStack; -uint32 -mmu_read_c1() -{ - uint32 controlReg = 0; - asm volatile("MRC p15, 0, %[c1out], c1, c0, 0":[c1out] "=r" (controlReg)); - return controlReg; -} - - -void -mmu_write_c1(uint32 value) -{ - asm volatile("MCR p15, 0, %[c1in], c1, c0, 0"::[c1in] "r" (value)); -} - - void arch_int_enable_io_interrupt(int irq) { @@ -117,29 +98,32 @@ arch_int_disable_io_interrupt(int irq) static void -print_iframe(struct iframe *frame) +print_iframe(const char *event, struct iframe *frame) { + if (event) + dprintf("Exception: %s\n", event); + + dprintf("R00=%08lx R01=%08lx R02=%08lx R03=%08lx\n" + "R04=%08lx R05=%08lx R06=%08lx R07=%08lx\n", + frame->r0, frame->r1, frame->r2, frame->r3, + frame->r4, frame->r5, frame->r6, frame->r7); + dprintf("R08=%08lx R09=%08lx R10=%08lx R11=%08lx\n" + "R12=%08lx R13=%08lx R14=%08lx CPSR=%08lx\n", + frame->r8, frame->r9, frame->r10, frame->r11, + frame->r12, frame->usr_sp, frame->usr_lr, frame->spsr); } status_t arch_int_init(kernel_args *args) { - // see if high vectors are enabled - if (mmu_read_c1() & (1<<13)) - dprintf("High vectors already enabled\n"); - else { - mmu_write_c1(mmu_read_c1() | (1<<13)); - - if (!(mmu_read_c1() & (1<<13))) - dprintf("Unable to enable high vectors!\n"); - else - dprintf("Enabled high vectors\n"); - } - return B_OK; } + +extern "C" void arm_vector_init(void); + + status_t arch_int_init_post_vm(kernel_args *args) { @@ -163,6 +147,20 @@ arch_int_init_post_vm(kernel_args *args) // copy vectors into the newly created area memcpy(sVectorPageAddress, &_vectors_start, VECTORPAGE_SIZE); + arm_vector_init(); + + // see if high vectors are enabled + if (mmu_read_c1() & (1<<13)) + dprintf("High vectors already enabled\n"); + else { + mmu_write_c1(mmu_read_c1() | (1<<13)); + + if (!(mmu_read_c1() & (1<<13))) + dprintf("Unable to enable high vectors!\n"); + else + dprintf("Enabled high vectors\n"); + } + sPxaInterruptArea = map_physical_memory("pxa_intc", PXA_INTERRUPT_PHYS_BASE, PXA_INTERRUPT_SIZE, 0, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&sPxaInterruptBase); @@ -179,7 +177,6 @@ arch_int_init_post_vm(kernel_args *args) status_t arch_int_init_io(kernel_args* args) { - TRACE(("arch_int_init_io(%p)\n", args)); return B_OK; } @@ -193,35 +190,103 @@ 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) { + kprintf("CPU fault handler set! %p %p\n", + (void*)cpu->fault_handler, (void*)cpu->fault_handler_stack_pointer); + debug_set_page_fault_info(far, frame->pc, + isWrite ? DEBUG_PAGE_FAULT_WRITE : 0); + frame->svc_sp = cpu->fault_handler_stack_pointer; + frame->pc = cpu->fault_handler; + return; + } + + if (thread->fault_handler != 0) { + kprintf("ERROR: thread::fault_handler used in kernel " + "debugger!\n"); + debug_set_page_fault_info(far, frame->pc, + isWrite ? DEBUG_PAGE_FAULT_WRITE : 0); + frame->pc = thread->fault_handler; + return; + } + } + + // otherwise, not really + panic("page fault in debugger without fault handler! Touching " + "address %p from pc %p\n", (void *)far, (void *)frame->pc); + return; + } else if ((frame->spsr & (1 << 7)) != 0) { + // interrupts disabled + + // If a page fault handler is installed, we're allowed to be here. + // TODO: Now we are generally allowing user_memcpy() with interrupts + // disabled, which in most cases is a bug. We should add some thread + // flag allowing to explicitly indicate that this handling is desired. + if (thread && thread->fault_handler != 0) { + if (frame->pc != thread->fault_handler) { + frame->pc = thread->fault_handler; + return; + } + + // The fault happened at the fault handler address. This is a + // certain infinite loop. + panic("page fault, interrupts disabled, fault handler loop. " + "Touching address %p from pc %p\n", (void*)far, + (void*)frame->pc); + } + + // If we are not running the kernel startup the page fault was not + // allowed to happen and we must panic. + panic("page fault, but interrupts were disabled. Touching address " + "%p from pc %p\n", (void *)far, (void *)frame->pc); + return; + } else if (thread != NULL && thread->page_faults_allowed < 1) { + panic("page fault not allowed at this place. Touching address " + "%p from pc %p\n", (void *)far, (void *)frame->pc); + return; + } + + enable_interrupts(); + + vm_page_fault(far, frame->pc, isWrite, isUser, &newip); + + if (newip != 0) { + // the page fault handler wants us to modify the iframe to set the + // IP the cpu will return to to be this ip + frame->pc = newip; } } extern "C" void arch_arm_prefetch_abort(struct iframe *iframe) { - panic("Prefetch Abort: %08x %08x %08x", iframe->r0, iframe->r1, iframe->r2); + print_iframe("Prefetch Abort", iframe); + panic("not handled!"); } extern "C" void arch_arm_irq(struct iframe *iframe) diff --git a/src/system/kernel/arch/arm/arch_platform.cpp b/src/system/kernel/arch/arm/arch_platform.cpp index f3721a6aca..a018654b1d 100644 --- a/src/system/kernel/arch/arm/arch_platform.cpp +++ b/src/system/kernel/arch/arm/arch_platform.cpp @@ -6,52 +6,17 @@ * All rights reserved. Distributed under the terms of the MIT License. */ -//#include - -#include - #include #include #include -//#include #include #include - - -#if 0 -static M68KPlatform *sM68KPlatform; - - -// constructor -M68KPlatform::M68KPlatform(platform_type platformType, - m68k_platform_type m68kPlatformType) - : fPlatformType(platformType), - fM68KPlatformType(m68kPlatformType) -{ -} - - -// destructor -M68KPlatform::~M68KPlatform() -{ -} - - -// Default -M68KPlatform * -M68KPlatform::Default() -{ - return sM68KPlatform; -} - - -// # pragma mark - -#endif +#include status_t arch_platform_init(struct kernel_args *kernelArgs) { - #warning ARM:WRITEME + // NOTE: dprintf() is off-limits here, too early... return B_OK; } @@ -59,8 +24,7 @@ arch_platform_init(struct kernel_args *kernelArgs) status_t arch_platform_init_post_vm(struct kernel_args *kernelArgs) { - #warning ARM:WRITEME - //sM68KPlatform->InitPostVM(kernelArgs); + // now we can use the heap and create areas return B_OK; } @@ -68,5 +32,6 @@ arch_platform_init_post_vm(struct kernel_args *kernelArgs) status_t arch_platform_init_post_thread(struct kernel_args *kernelArgs) { + // now we can create and use semaphores return B_OK; } diff --git a/src/system/kernel/arch/arm/arch_timer.cpp b/src/system/kernel/arch/arm/arch_timer.cpp index 2bda04042c..5cf8574279 100644 --- a/src/system/kernel/arch/arm/arch_timer.cpp +++ b/src/system/kernel/arch/arm/arch_timer.cpp @@ -19,6 +19,15 @@ #include #include + +//#define TRACE_ARCH_TIMER +#ifdef TRACE_ARCH_TIMER +# define TRACE(x) dprintf x +#else +# define TRACE(x) ; +#endif + + #define PXA_TIMERS_PHYS_BASE 0x40A00000 #define PXA_TIMERS_SIZE 0x000000C0 #define PXA_TIMERS_INTERRUPT 7 /* OST_4_11 */ @@ -29,7 +38,6 @@ #define PXA_OSMR4 0x20 #define PXA_OMCR4 0x30 -#define TRACE(x) //dprintf x static area_id sPxaTimersArea; static uint32 *sPxaTimersBase; @@ -48,7 +56,7 @@ pxa_timer_interrupt(void *data) void arch_timer_set_hardware_timer(bigtime_t timeout) { - TRACE(("arch_timer_set_hardware_timer(%lld): %p\n", timeout, sPxaTimersBase)); + TRACE(("arch_timer_set_hardware_timer(%lld)\n", timeout)); if (sPxaTimersBase) { sPxaTimersBase[PXA_OIER] |= (1 << 4); @@ -62,7 +70,7 @@ arch_timer_set_hardware_timer(bigtime_t timeout) void arch_timer_clear_hardware_timer() { - TRACE(("arch_timer_clear_hardware_timer: %p\n", sPxaTimersBase)); + TRACE(("arch_timer_clear_hardware_timer\n")); if (sPxaTimersBase) { sPxaTimersBase[PXA_OMCR4] = 0; // disable our timer diff --git a/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp b/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp index cfcd630dd5..91bfa29a22 100644 --- a/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp +++ b/src/system/kernel/arch/arm/paging/32bit/ARMPagingMethod32Bit.cpp @@ -30,7 +30,7 @@ #include "paging/arm_physical_page_mapper_large_memory.h" -#define TRACE_ARM_PAGING_METHOD_32_BIT +//#define TRACE_ARM_PAGING_METHOD_32_BIT #ifdef TRACE_ARM_PAGING_METHOD_32_BIT # define TRACE(x...) dprintf(x) #else diff --git a/src/system/kernel/arch/arm/paging/32bit/ARMVMTranslationMap32Bit.cpp b/src/system/kernel/arch/arm/paging/32bit/ARMVMTranslationMap32Bit.cpp index 2d19cb8f9a..ba70d0fa59 100644 --- a/src/system/kernel/arch/arm/paging/32bit/ARMVMTranslationMap32Bit.cpp +++ b/src/system/kernel/arch/arm/paging/32bit/ARMVMTranslationMap32Bit.cpp @@ -249,14 +249,12 @@ ARMVMTranslationMap32Bit::Unmap(addr_t start, addr_t end) ARM_PTE_TYPE_MASK); fMapCount--; -#if 0 /* IRA */ - if ((oldEntry & ARM_PTE_ACCESSED) != 0) { + if (true /* (oldEntry & ARM_PTE_ACCESSED) != 0*/) { // Note, that we only need to invalidate the address, if the // accessed flags was set, since only then the entry could have // been in any TLB. InvalidatePage(start); } -#endif } } while (start != 0 && start < end); @@ -301,8 +299,8 @@ ARMVMTranslationMap32Bit::UnmapPage(VMArea* area, addr_t address, fMapCount--; -#if 0 //IRA - if ((oldEntry & ARM_PTE_ACCESSED) != 0) { + + if (true /*(oldEntry & ARM_PTE_ACCESSED) != 0*/) { // XXX IRA // Note, that we only need to invalidate the address, if the // accessed flags was set, since only then the entry could have been // in any TLB. @@ -320,14 +318,14 @@ ARMVMTranslationMap32Bit::UnmapPage(VMArea* area, addr_t address, // Interestingly FreeBSD seems to ignore this problem as well // (cf. pmap_remove_all()), unless I've missed something. } -#endif + locker.Detach(); // PageUnmapped() will unlock for us -#if 0 //IRA + PageUnmapped(area, (oldEntry & ARM_PTE_ADDRESS_MASK) / B_PAGE_SIZE, - (oldEntry & ARM_PTE_ACCESSED) != 0, (oldEntry & ARM_PTE_DIRTY) != 0, + true /*(oldEntry & ARM_PTE_ACCESSED) != 0*/, true /*(oldEntry & ARM_PTE_DIRTY) != 0*/, updatePageQueue); -#endif + return B_OK; } @@ -375,14 +373,13 @@ ARMVMTranslationMap32Bit::UnmapPages(VMArea* area, addr_t base, size_t size, fMapCount--; -#if 0 //IRA - if ((oldEntry & ARM_PTE_ACCESSED) != 0) { + if (true /*(oldEntry & ARM_PTE_ACCESSED) != 0*/) { // XXX IRA // Note, that we only need to invalidate the address, if the // accessed flags was set, since only then the entry could have // been in any TLB. InvalidatePage(start); } -#endif + if (area->cache_type != CACHE_TYPE_DEVICE) { // get the page vm_page* page = vm_lookup_page( @@ -390,13 +387,13 @@ ARMVMTranslationMap32Bit::UnmapPages(VMArea* area, addr_t base, size_t size, ASSERT(page != NULL); DEBUG_PAGE_ACCESS_START(page); -#if 0 + // transfer the accessed/dirty flags to the page - if ((oldEntry & ARM_PTE_ACCESSED) != 0) + if (/*(oldEntry & ARM_PTE_ACCESSED) != 0*/ true) // XXX IRA page->accessed = true; - if ((oldEntry & ARM_PTE_DIRTY) != 0) + if (/*(oldEntry & ARM_PTE_DIRTY) != 0 */ true) page->modified = true; -#endif + // remove the mapping object/decrement the wired_count of the // page if (area->wiring == B_NO_LOCK) { @@ -512,19 +509,19 @@ ARMVMTranslationMap32Bit::UnmapArea(VMArea* area, bool deletingAddressSpace, "has no page table entry", page, area, address); continue; } -#if 0 + // transfer the accessed/dirty flags to the page and invalidate // the mapping, if necessary - if ((oldEntry & ARM_PTE_ACCESSED) != 0) { + if (true /*(oldEntry & ARM_PTE_ACCESSED) != 0*/) { // XXX IRA page->accessed = true; if (!deletingAddressSpace) InvalidatePage(address); } - if ((oldEntry & ARM_PTE_DIRTY) != 0) + if (true /*(oldEntry & ARM_PTE_DIRTY) != 0*/) page->modified = true; -#endif + if (pageFullyUnmapped) { DEBUG_PAGE_ACCESS_START(page); @@ -640,7 +637,7 @@ ARMVMTranslationMap32Bit::QueryInterrupt(addr_t va, phys_addr_t *_physical, | ((entry & ARM_PTE_ACCESSED) != 0 ? PAGE_ACCESSED : 0) | ((entry & ARM_PTE_PRESENT) != 0 ? PAGE_PRESENT : 0); #else - *_flags = B_KERNEL_WRITE_AREA | B_KERNEL_READ_AREA; + *_flags = B_KERNEL_WRITE_AREA | B_KERNEL_READ_AREA | PAGE_PRESENT; #endif return B_OK; } @@ -752,7 +749,7 @@ ARMVMTranslationMap32Bit::ClearFlags(addr_t va, uint32 flags) pinner.Unlock(); - if ((oldEntry & flagsToClear) != 0) + //XXX IRA if ((oldEntry & flagsToClear) != 0) InvalidatePage(va); return B_OK; @@ -820,10 +817,9 @@ ARMVMTranslationMap32Bit::ClearAccessedAndModified(VMArea* area, addr_t address, pinner.Unlock(); -#if 0 //IRA - _modified = (oldEntry & ARM_PTE_DIRTY) != 0; + _modified = true /* (oldEntry & ARM_PTE_DIRTY) != 0 */; // XXX IRA - if ((oldEntry & ARM_PTE_ACCESSED) != 0) { + if (true /*(oldEntry & ARM_PTE_ACCESSED) != 0*/) { // Note, that we only need to invalidate the address, if the // accessed flags was set, since only then the entry could have been // in any TLB. @@ -833,9 +829,6 @@ ARMVMTranslationMap32Bit::ClearAccessedAndModified(VMArea* area, addr_t address, return true; } -#else - _modified = false; -#endif if (!unmapIfUnaccessed) return false; From 9f512d6188a30b25d42a40b542dfd19a28d472bf Mon Sep 17 00:00:00 2001 From: "Ithamar R. Adema" Date: Wed, 7 Nov 2012 17:05:16 +0100 Subject: [PATCH 21/31] document architectural limitations of ARM port Sure there are more, but this is at least a start for now ;) --- docs/develop/ports/arm/limitations.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 docs/develop/ports/arm/limitations.txt diff --git a/docs/develop/ports/arm/limitations.txt b/docs/develop/ports/arm/limitations.txt new file mode 100644 index 0000000000..7d080c831d --- /dev/null +++ b/docs/develop/ports/arm/limitations.txt @@ -0,0 +1,2 @@ +* Does not support < ARMv5 +* Requires support for high vectors From e2b8ceb23c2f85f51e4541a11fd1838be45a3e2c Mon Sep 17 00:00:00 2001 From: "Ithamar R. Adema" Date: Wed, 7 Nov 2012 17:08:15 +0100 Subject: [PATCH 22/31] ARM/int: remove CPU fault handler debug output --- src/system/kernel/arch/arm/arch_int.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/system/kernel/arch/arm/arch_int.cpp b/src/system/kernel/arch/arm/arch_int.cpp index f61298d6f7..5c37f36a77 100644 --- a/src/system/kernel/arch/arm/arch_int.cpp +++ b/src/system/kernel/arch/arm/arch_int.cpp @@ -218,8 +218,6 @@ extern "C" void arch_arm_data_abort(struct iframe *frame) cpu_ent* cpu = &gCPU[smp_get_current_cpu()]; if (cpu->fault_handler != 0) { - kprintf("CPU fault handler set! %p %p\n", - (void*)cpu->fault_handler, (void*)cpu->fault_handler_stack_pointer); debug_set_page_fault_info(far, frame->pc, isWrite ? DEBUG_PAGE_FAULT_WRITE : 0); frame->svc_sp = cpu->fault_handler_stack_pointer; From b0cef9d95624e1e6621347753939abf36cb96497 Mon Sep 17 00:00:00 2001 From: "Ithamar R. Adema" Date: Wed, 7 Nov 2012 17:20:47 +0100 Subject: [PATCH 23/31] ARM/docs: add a TODO with the major open issues for this port. Personally I find KDL hangman the biggest blocker, but oh well... --- docs/develop/ports/arm/todo.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 docs/develop/ports/arm/todo.txt diff --git a/docs/develop/ports/arm/todo.txt b/docs/develop/ports/arm/todo.txt new file mode 100644 index 0000000000..fae21763fc --- /dev/null +++ b/docs/develop/ports/arm/todo.txt @@ -0,0 +1,19 @@ +* Figure out how to get page flags (modified/accessed) and implement it ;) + +* Fix serial port mapping. Currently kernel uses the haiku_loader identity + mapping for it, but this lives in user virtual address space... + (Need to not use identity mapping in haiku_loader but just + map_physical_memory() there too so it can be handed over without issues). + +* Seperate ARM architecture/System-On-Chip IP code. Needed very early on + (Interrupt Controller, Timer IP block). Should use FDT for this too. + +* Use FDT to remove all the seperate board definitions in the build. Use a + "minimal ARM architecture version" as the compile flag for ARM support. + This to be able to optimize a kernel build for a specific SoC (or family). + +* Research stack unwinding to implement backtrace support for KDL & friends. + +* Add KDL hangman to the boot floppy image for more enjoyment during porting.... + +* Userland........... From a095f503dc5601255e7e03fc8b430eeea080d1c6 Mon Sep 17 00:00:00 2001 From: Humdinger Date: Wed, 7 Nov 2012 19:49:51 +0100 Subject: [PATCH 24/31] Changing 'Blinking cursor' in settings too. +alpha4. quick, quick.. --- src/apps/terminal/TermConst.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/terminal/TermConst.h b/src/apps/terminal/TermConst.h index cf0a31c2c6..05174b11c5 100644 --- a/src/apps/terminal/TermConst.h +++ b/src/apps/terminal/TermConst.h @@ -133,7 +133,7 @@ static const char* const PREF_SHELL = "Shell"; static const char* const PREF_TEXT_ENCODING = "Text encoding"; static const char* const PREF_GUI_LANGUAGE = "Language"; -static const char* const PREF_BLINK_CURSOR = "Blink the cursor"; +static const char* const PREF_BLINK_CURSOR = "Blinking cursor"; static const char* const PREF_WARN_ON_EXIT = "Warn on exit"; static const char* const PREF_TAB_TITLE = "Tab title"; From 71d45a0f7617c453858d6aceff57c27c156d074e Mon Sep 17 00:00:00 2001 From: czeidler Date: Wed, 7 Nov 2012 20:25:38 +0100 Subject: [PATCH 25/31] Coding style. --- src/system/kernel/fs/KPath.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/system/kernel/fs/KPath.cpp b/src/system/kernel/fs/KPath.cpp index a7c55e31f6..021bcc8dc4 100644 --- a/src/system/kernel/fs/KPath.cpp +++ b/src/system/kernel/fs/KPath.cpp @@ -193,7 +193,7 @@ KPath::DetachBuffer() } -const char * +const char* KPath::Leaf() const { if (!fBuffer) @@ -212,7 +212,7 @@ KPath::Leaf() const status_t -KPath::ReplaceLeaf(const char *newLeaf) +KPath::ReplaceLeaf(const char* newLeaf) { const char *leaf = Leaf(); if (!leaf) From 9abf4591d5b44b2e3e52190c2b2a427a81be2691 Mon Sep 17 00:00:00 2001 From: czeidler Date: Wed, 7 Nov 2012 21:45:43 +0100 Subject: [PATCH 26/31] Ok there are some more, thanks Rene. --- src/system/kernel/fs/KPath.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/system/kernel/fs/KPath.cpp b/src/system/kernel/fs/KPath.cpp index 021bcc8dc4..2de6ae2805 100644 --- a/src/system/kernel/fs/KPath.cpp +++ b/src/system/kernel/fs/KPath.cpp @@ -107,12 +107,12 @@ KPath::InitCheck() const status_t -KPath::SetPath(const char *path, bool normalize, bool traverseLeafLink) +KPath::SetPath(const char* path, bool normalize, bool traverseLeafLink) { - if (!fBuffer) + if (fBuffer == NULL) return B_NO_INIT; - if (path) { + if (path != NULL) { if (normalize) { // normalize path status_t error = vfs_normalize_path(path, fBuffer, fBufferSize, @@ -148,10 +148,10 @@ KPath::Path() const } -char * +char* KPath::LockBuffer() { - if (!fBuffer || fLocked) + if (fBuffer == NULL || fLocked) return NULL; fLocked = true; @@ -214,7 +214,7 @@ KPath::Leaf() const status_t 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); From d006487564e9eae1bd065562bbb4c00c9bcd3273 Mon Sep 17 00:00:00 2001 From: Oliver Tappe Date: Wed, 7 Nov 2012 21:38:03 +0100 Subject: [PATCH 27/31] Force POSIX-locale when building the buildtools * using a non-POSIX locale may break the build (especially makeinfo), so we explicitly set the locale to POSIX --- build/scripts/build_cross_tools | 3 +++ build/scripts/build_cross_tools_gcc4 | 2 ++ 2 files changed, 5 insertions(+) diff --git a/build/scripts/build_cross_tools b/build/scripts/build_cross_tools index 37382620d3..218a825509 100755 --- a/build/scripts/build_cross_tools +++ b/build/scripts/build_cross_tools @@ -89,6 +89,9 @@ 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 \ diff --git a/build/scripts/build_cross_tools_gcc4 b/build/scripts/build_cross_tools_gcc4 index 976ff9d3f5..320420f8ea 100755 --- a/build/scripts/build_cross_tools_gcc4 +++ b/build/scripts/build_cross_tools_gcc4 @@ -110,6 +110,8 @@ mkdir -p $installDir $objDir $binutilsObjDir $gccObjDir $tmpIncludeDir \ $tmpLibDir || exit 1 mkdir -p $installDir/lib/gcc/$haikuMachine/$gccVersion +# force the POSIX locale, as the build (makeinfo) might choke otherwise +export LC_ALL=POSIX # build binutils cd $binutilsObjDir From 29468041f9a2dcc863ceb6c52007fff769d8fd97 Mon Sep 17 00:00:00 2001 From: Oliver Tappe Date: Wed, 7 Nov 2012 21:56:20 +0100 Subject: [PATCH 28/31] Explicitly use -j1 when building gcc2 * specifying -j1 guards against potential multi-job arguments in MAKEFLAGS --- build/scripts/build_cross_tools | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/scripts/build_cross_tools b/build/scripts/build_cross_tools index 218a825509..cc7c63d3c4 100755 --- a/build/scripts/build_cross_tools +++ b/build/scripts/build_cross_tools @@ -97,7 +97,7 @@ 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 @@ -157,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 } From 2862f14d6875d949e62282bb52d45588f8185826 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Wed, 7 Nov 2012 19:26:00 +0100 Subject: [PATCH 29/31] Added todo list. Lists missing/incomplete Debugger features. Not exhaustive. --- docs/develop/debugger/todo.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 docs/develop/debugger/todo.txt diff --git a/docs/develop/debugger/todo.txt b/docs/develop/debugger/todo.txt new file mode 100644 index 0000000000..f4b91850ad --- /dev/null +++ b/docs/develop/debugger/todo.txt @@ -0,0 +1,14 @@ +- Need the ability to save crash reports. +- CLI needs to be more fully implemented. +- General expression evaluation parser. Once implemented, should supplant the primitive one currently used for C/C++ typecasting support, as well as being exposed for user expression input. +- Conditional breakpoint/watchpoints. Contingent on above general expression parser. +- Remote debug interface support. +- Kernel debug support. +- Architecture needs to be able to report back the hardware debugging capabilities/limitations of the target platform. +- WatchpointManager needs to be able to use the aforementioned information from Architecture in order to more intelligently + manage/restrict watchpoint usage (especially once expression watchpoints come into play). +- More complete DWARF3/4 support. +- x86-64 support. +- Support for retrieving/displaying function return values (arch-specific). +- Syntax highlighting in source view. +- Detection of mouse hovering over a variable in SourceView and showing value in tooltip (probably requires expression parsing support). From 4549786bad3ebe97704626f9cc73afa64f92415f Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Wed, 7 Nov 2012 23:16:27 +0100 Subject: [PATCH 30/31] Code reorganization. --- src/apps/debugger/Jamfile | 29 +- src/apps/debugger/Jobs.cpp | 698 ------------------ .../{ => controllers}/TeamDebugger.cpp | 0 .../debugger/{ => controllers}/TeamDebugger.h | 0 .../{ => controllers}/ThreadHandler.cpp | 0 .../{ => controllers}/ThreadHandler.h | 0 .../BreakpointManager.cpp | 0 .../{ => debug_managers}/BreakpointManager.h | 0 .../TeamMemoryBlockManager.cpp | 0 .../TeamMemoryBlockManager.h | 0 .../WatchpointManager.cpp | 0 .../{ => debug_managers}/WatchpointManager.h | 0 src/apps/debugger/jobs/GetCPUStateJob.cpp | 56 ++ src/apps/debugger/jobs/GetStackTraceJob.cpp | 116 +++ src/apps/debugger/jobs/GetThreadStateJob.cpp | 62 ++ src/apps/debugger/{ => jobs}/Jobs.h | 0 .../debugger/jobs/LoadImageDebugInfoJob.cpp | 106 +++ src/apps/debugger/jobs/LoadSourceCodeJob.cpp | 93 +++ .../debugger/jobs/ResolveValueNodeJob.cpp | 254 +++++++ .../debugger/jobs/RetrieveMemoryBlockJob.cpp | 62 ++ src/apps/debugger/{ => util}/Worker.cpp | 0 src/apps/debugger/{ => util}/Worker.h | 0 22 files changed, 771 insertions(+), 705 deletions(-) delete mode 100644 src/apps/debugger/Jobs.cpp rename src/apps/debugger/{ => controllers}/TeamDebugger.cpp (100%) rename src/apps/debugger/{ => controllers}/TeamDebugger.h (100%) rename src/apps/debugger/{ => controllers}/ThreadHandler.cpp (100%) rename src/apps/debugger/{ => controllers}/ThreadHandler.h (100%) rename src/apps/debugger/{ => debug_managers}/BreakpointManager.cpp (100%) rename src/apps/debugger/{ => debug_managers}/BreakpointManager.h (100%) rename src/apps/debugger/{ => debug_managers}/TeamMemoryBlockManager.cpp (100%) rename src/apps/debugger/{ => debug_managers}/TeamMemoryBlockManager.h (100%) rename src/apps/debugger/{ => debug_managers}/WatchpointManager.cpp (100%) rename src/apps/debugger/{ => debug_managers}/WatchpointManager.h (100%) create mode 100644 src/apps/debugger/jobs/GetCPUStateJob.cpp create mode 100644 src/apps/debugger/jobs/GetStackTraceJob.cpp create mode 100644 src/apps/debugger/jobs/GetThreadStateJob.cpp rename src/apps/debugger/{ => jobs}/Jobs.h (100%) create mode 100644 src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp create mode 100644 src/apps/debugger/jobs/LoadSourceCodeJob.cpp create mode 100644 src/apps/debugger/jobs/ResolveValueNodeJob.cpp create mode 100644 src/apps/debugger/jobs/RetrieveMemoryBlockJob.cpp rename src/apps/debugger/{ => util}/Worker.cpp (100%) rename src/apps/debugger/{ => util}/Worker.h (100%) diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 7ee2bf140b..3eb68ae8c2 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -9,11 +9,14 @@ UsePrivateSystemHeaders ; SEARCH_SOURCE += [ FDirName $(SUBDIR) arch ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) arch x86 ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) controllers ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_info ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_managers ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) elf ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) files ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) ids ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) jobs ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) model ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) settings ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) settings generic ] ; @@ -55,14 +58,7 @@ SourceHdrs ; Application Debugger : - BreakpointManager.cpp Debugger.cpp - Jobs.cpp - TeamMemoryBlockManager.cpp - TeamDebugger.cpp - ThreadHandler.cpp - WatchpointManager.cpp - Worker.cpp # arch Architecture.cpp @@ -75,6 +71,15 @@ Application Debugger : ArchitectureX86.cpp CpuStateX86.cpp + # controllers + TeamDebugger.cpp + ThreadHandler.cpp + + # debug_managers + BreakpointManager.cpp + TeamMemoryBlockManager.cpp + WatchpointManager.cpp + # debug_info BasicFunctionDebugInfo.cpp DebuggerImageDebugInfo.cpp @@ -117,6 +122,15 @@ Application Debugger : ObjectID.cpp FunctionParameterID.cpp + # jobs + GetCPUStateJob.cpp + GetStackTraceJob.cpp + GetThreadStateJob.cpp + LoadImageDebugInfoJob.cpp + LoadSourceCodeJob.cpp + ResolveValueNodeJob.cpp + RetrieveMemoryBlockJob.cpp + # model Breakpoint.cpp DisassembledCode.cpp @@ -236,6 +250,7 @@ Application Debugger : BitBuffer.cpp IntegerFormatter.cpp StringUtils.cpp + Worker.cpp # value TypeHandler.cpp diff --git a/src/apps/debugger/Jobs.cpp b/src/apps/debugger/Jobs.cpp deleted file mode 100644 index bfd2fe11dc..0000000000 --- a/src/apps/debugger/Jobs.cpp +++ /dev/null @@ -1,698 +0,0 @@ -/* - * Copyright 2012, Rene Gollent, rene@gollent.com. - * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. - * Distributed under the terms of the MIT License. - */ - -#include "Jobs.h" - -#include -#include - -#include "Architecture.h" -#include "BitBuffer.h" -#include "CpuState.h" -#include "DebuggerInterface.h" -#include "DisassembledCode.h" -#include "FileSourceCode.h" -#include "Function.h" -#include "Image.h" -#include "ImageDebugInfo.h" -#include "Register.h" -#include "SourceCode.h" -#include "SpecificImageDebugInfo.h" -#include "StackFrameDebugInfo.h" -#include "StackFrameValueInfos.h" -#include "StackFrameValues.h" -#include "StackTrace.h" -#include "Team.h" -#include "TeamDebugInfo.h" -#include "TeamMemory.h" -#include "TeamMemoryBlock.h" -#include "TeamTypeInformation.h" -#include "Thread.h" -#include "Tracing.h" -#include "Type.h" -#include "TypeComponentPath.h" -#include "Value.h" -#include "ValueLoader.h" -#include "ValueLocation.h" -#include "ValueNode.h" -#include "ValueNodeContainer.h" -#include "Variable.h" - - -// #pragma mark - GetThreadStateJob - - -GetThreadStateJob::GetThreadStateJob(DebuggerInterface* debuggerInterface, - Thread* thread) - : - fKey(thread, JOB_TYPE_GET_THREAD_STATE), - fDebuggerInterface(debuggerInterface), - fThread(thread) -{ - fThread->AcquireReference(); -} - - -GetThreadStateJob::~GetThreadStateJob() -{ - fThread->ReleaseReference(); -} - - -const JobKey& -GetThreadStateJob::Key() const -{ - return fKey; -} - - -status_t -GetThreadStateJob::Do() -{ - CpuState* state = NULL; - status_t error = fDebuggerInterface->GetCpuState(fThread->ID(), state); - BReference reference(state, true); - - AutoLocker locker(fThread->GetTeam()); - - if (fThread->State() != THREAD_STATE_UNKNOWN) - return B_OK; - - if (error == B_OK) { - fThread->SetState(THREAD_STATE_STOPPED); - fThread->SetCpuState(state); - } else if (error == B_BAD_THREAD_STATE) { - fThread->SetState(THREAD_STATE_RUNNING); - } else - return error; - - return B_OK; -} - - -// #pragma mark - GetCpuStateJob - - -GetCpuStateJob::GetCpuStateJob(DebuggerInterface* debuggerInterface, - Thread* thread) - : - fKey(thread, JOB_TYPE_GET_CPU_STATE), - fDebuggerInterface(debuggerInterface), - fThread(thread) -{ - fThread->AcquireReference(); -} - - -GetCpuStateJob::~GetCpuStateJob() -{ - fThread->ReleaseReference(); -} - - -const JobKey& -GetCpuStateJob::Key() const -{ - return fKey; -} - - -status_t -GetCpuStateJob::Do() -{ - CpuState* state; - status_t error = fDebuggerInterface->GetCpuState(fThread->ID(), state); - if (error != B_OK) - return error; - BReference reference(state, true); - - AutoLocker locker(fThread->GetTeam()); - - if (fThread->State() == THREAD_STATE_STOPPED) - fThread->SetCpuState(state); - - return B_OK; -} - - -// #pragma mark - GetStackTraceJob - - -GetStackTraceJob::GetStackTraceJob(DebuggerInterface* debuggerInterface, - Architecture* architecture, Thread* thread) - : - fKey(thread, JOB_TYPE_GET_STACK_TRACE), - fDebuggerInterface(debuggerInterface), - fArchitecture(architecture), - fThread(thread) -{ - fThread->AcquireReference(); - - fCpuState = fThread->GetCpuState(); - if (fCpuState != NULL) - fCpuState->AcquireReference(); -} - - -GetStackTraceJob::~GetStackTraceJob() -{ - if (fCpuState != NULL) - fCpuState->ReleaseReference(); - - fThread->ReleaseReference(); -} - - -const JobKey& -GetStackTraceJob::Key() const -{ - return fKey; -} - - -status_t -GetStackTraceJob::Do() -{ - if (fCpuState == NULL) - return B_BAD_VALUE; - - // get the stack trace - StackTrace* stackTrace; - status_t error = fArchitecture->CreateStackTrace(fThread->GetTeam(), this, - fCpuState, stackTrace); - if (error != B_OK) - return error; - BReference stackTraceReference(stackTrace, true); - - // set the stack trace, unless something has changed - AutoLocker locker(fThread->GetTeam()); - - if (fThread->GetCpuState() == fCpuState) - fThread->SetStackTrace(stackTrace); - - return B_OK; -} - - -status_t -GetStackTraceJob::GetImageDebugInfo(Image* image, ImageDebugInfo*& _info) -{ - AutoLocker teamLocker(fThread->GetTeam()); - - while (image->GetImageDebugInfo() == NULL) { - // schedule a job, if not loaded - ImageDebugInfo* info; - status_t error = LoadImageDebugInfoJob::ScheduleIfNecessary(GetWorker(), - image, &info); - if (error != B_OK) - return error; - - if (info != NULL) { - _info = info; - return B_OK; - } - - teamLocker.Unlock(); - - // wait for the job to finish - switch (WaitFor(SimpleJobKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO))) { - case JOB_DEPENDENCY_SUCCEEDED: - case JOB_DEPENDENCY_NOT_FOUND: - // "Not found" can happen due to a race condition between - // unlocking the worker and starting to wait. - break; - case JOB_DEPENDENCY_FAILED: - case JOB_DEPENDENCY_ABORTED: - default: - return B_ERROR; - } - - teamLocker.Lock(); - } - - _info = image->GetImageDebugInfo(); - _info->AcquireReference(); - - return B_OK; -} - - -// #pragma mark - LoadImageDebugInfoJob - - -LoadImageDebugInfoJob::LoadImageDebugInfoJob(Image* image) - : - fKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO), - fImage(image) -{ - fImage->AcquireReference(); -} - - -LoadImageDebugInfoJob::~LoadImageDebugInfoJob() -{ - fImage->ReleaseReference(); -} - - -const JobKey& -LoadImageDebugInfoJob::Key() const -{ - return fKey; -} - - -status_t -LoadImageDebugInfoJob::Do() -{ - // get an image info for the image - AutoLocker locker(fImage->GetTeam()); - ImageInfo imageInfo(fImage->Info()); - locker.Unlock(); - - // create the debug info - ImageDebugInfo* debugInfo; - status_t error = fImage->GetTeam()->DebugInfo()->LoadImageDebugInfo( - imageInfo, fImage->ImageFile(), debugInfo); - - // set the result - locker.Lock(); - if (error == B_OK) { - error = fImage->SetImageDebugInfo(debugInfo, IMAGE_DEBUG_INFO_LOADED); - debugInfo->ReleaseReference(); - } else - fImage->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_UNAVAILABLE); - - return error; -} - - -/*static*/ status_t -LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image, - ImageDebugInfo** _imageDebugInfo) -{ - AutoLocker teamLocker(image->GetTeam()); - - // If already loaded, we're done. - if (image->GetImageDebugInfo() != NULL) { - if (_imageDebugInfo != NULL) { - *_imageDebugInfo = image->GetImageDebugInfo(); - (*_imageDebugInfo)->AcquireReference(); - } - return B_OK; - } - - // If already loading, the caller has to wait, if desired. - if (image->ImageDebugInfoState() == IMAGE_DEBUG_INFO_LOADING) { - if (_imageDebugInfo != NULL) - *_imageDebugInfo = NULL; - return B_OK; - } - - // If an earlier load attempt failed, bail out. - if (image->ImageDebugInfoState() != IMAGE_DEBUG_INFO_NOT_LOADED) - return B_ERROR; - - // schedule a job - LoadImageDebugInfoJob* job = new(std::nothrow) LoadImageDebugInfoJob(image); - if (job == NULL) - return B_NO_MEMORY; - - status_t error = worker->ScheduleJob(job); - if (error != B_OK) { - image->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_UNAVAILABLE); - return error; - } - - image->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_LOADING); - - if (_imageDebugInfo != NULL) - *_imageDebugInfo = NULL; - return B_OK; -} - - -// #pragma mark - LoadSourceCodeJob - - -LoadSourceCodeJob::LoadSourceCodeJob( - DebuggerInterface* debuggerInterface, Architecture* architecture, - Team* team, FunctionInstance* functionInstance, bool loadForFunction) - : - fKey(functionInstance, JOB_TYPE_LOAD_SOURCE_CODE), - fDebuggerInterface(debuggerInterface), - fArchitecture(architecture), - fTeam(team), - fFunctionInstance(functionInstance), - fLoadForFunction(loadForFunction) -{ - fFunctionInstance->AcquireReference(); -} - - -LoadSourceCodeJob::~LoadSourceCodeJob() -{ - fFunctionInstance->ReleaseReference(); -} - - -const JobKey& -LoadSourceCodeJob::Key() const -{ - return fKey; -} - - -status_t -LoadSourceCodeJob::Do() -{ - // if requested, try loading the source code for the function - Function* function = fFunctionInstance->GetFunction(); - if (fLoadForFunction) { - FileSourceCode* sourceCode; - status_t error = fTeam->DebugInfo()->LoadSourceCode( - function->SourceFile(), sourceCode); - - AutoLocker locker(fTeam); - - if (error == B_OK) { - function->SetSourceCode(sourceCode, FUNCTION_SOURCE_LOADED); - sourceCode->ReleaseReference(); - return B_OK; - } - - function->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE); - } - - // Only try to load the function instance code, if it's not overridden yet. - AutoLocker locker(fTeam); - if (fFunctionInstance->SourceCodeState() != FUNCTION_SOURCE_LOADING) - return B_OK; - locker.Unlock(); - - // disassemble the function - DisassembledCode* sourceCode = NULL; - status_t error = fTeam->DebugInfo()->DisassembleFunction(fFunctionInstance, - sourceCode); - - // set the result - locker.Lock(); - if (error == B_OK) { - if (fFunctionInstance->SourceCodeState() == FUNCTION_SOURCE_LOADING) { - fFunctionInstance->SetSourceCode(sourceCode, - FUNCTION_SOURCE_LOADED); - sourceCode->ReleaseReference(); - } - } else - fFunctionInstance->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE); - - return error; -} - - -// #pragma mark - ResolveValueNodeValueJob - - -ResolveValueNodeValueJob::ResolveValueNodeValueJob( - DebuggerInterface* debuggerInterface, Architecture* architecture, - CpuState* cpuState, TeamTypeInformation* typeInformation, - ValueNodeContainer* container, ValueNode* valueNode) - : - fKey(valueNode, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE), - fDebuggerInterface(debuggerInterface), - fArchitecture(architecture), - fCpuState(cpuState), - fTypeInformation(typeInformation), - fContainer(container), - fValueNode(valueNode) -{ - if (fCpuState != NULL) - fCpuState->AcquireReference(); - fContainer->AcquireReference(); - fValueNode->AcquireReference(); -} - - -ResolveValueNodeValueJob::~ResolveValueNodeValueJob() -{ - if (fCpuState != NULL) - fCpuState->ReleaseReference(); - fContainer->ReleaseReference(); - fValueNode->ReleaseReference(); -} - - -const JobKey& -ResolveValueNodeValueJob::Key() const -{ - return fKey; -} - - -status_t -ResolveValueNodeValueJob::Do() -{ - // check whether the node still belongs to the container - AutoLocker containerLocker(fContainer); - if (fValueNode->Container() != fContainer) - return B_BAD_VALUE; - - // if already resolved, we're done - status_t nodeResolutionState - = fValueNode->LocationAndValueResolutionState(); - if (nodeResolutionState != VALUE_NODE_UNRESOLVED) - return nodeResolutionState; - - containerLocker.Unlock(); - - // resolve - status_t error = _ResolveNodeValue(); - if (error != B_OK) { - nodeResolutionState = fValueNode->LocationAndValueResolutionState(); - if (nodeResolutionState != VALUE_NODE_UNRESOLVED) - return nodeResolutionState; - - containerLocker.Lock(); - fValueNode->SetLocationAndValue(NULL, NULL, error); - containerLocker.Unlock(); - } - - return error; -} - - -status_t -ResolveValueNodeValueJob::_ResolveNodeValue() -{ - // get the node child and parent node - AutoLocker containerLocker(fContainer); - ValueNodeChild* nodeChild = fValueNode->NodeChild(); - BReference nodeChildReference(nodeChild); - - ValueNode* parentNode = nodeChild->Parent(); - BReference parentNodeReference(parentNode); - - // Check whether the node child location has been resolved already - // (successfully). - status_t nodeChildResolutionState = nodeChild->LocationResolutionState(); - bool nodeChildDone = nodeChildResolutionState != VALUE_NODE_UNRESOLVED; - if (nodeChildDone && nodeChildResolutionState != B_OK) - return nodeChildResolutionState; - - // If the child node location has not been resolved yet, check whether the - // parent node location and value have been resolved already (successfully). - bool parentDone = true; - if (!nodeChildDone && parentNode != NULL) { - status_t parentResolutionState - = parentNode->LocationAndValueResolutionState(); - parentDone = parentResolutionState != VALUE_NODE_UNRESOLVED; - if (parentDone && parentResolutionState != B_OK) - return parentResolutionState; - } - - containerLocker.Unlock(); - - // resolve the parent node location and value, if necessary - if (!parentDone) { - status_t error = _ResolveParentNodeValue(parentNode); - if (error != B_OK) { - TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value " - "node: %p (\"%s\"): _ResolveParentNodeValue(%p) failed\n", - fValueNode, fValueNode->Name().String(), parentNode); - return error; - } - - if (State() == JOB_STATE_WAITING) - return B_OK; - } - - // resolve the node child location, if necessary - if (!nodeChildDone) { - status_t error = _ResolveNodeChildLocation(nodeChild); - if (error != B_OK) { - TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value " - "node: %p (\"%s\"): _ResolveNodeChildLocation(%p) failed\n", - fValueNode, fValueNode->Name().String(), nodeChild); - return error; - } - } - - // resolve the node location and value - ValueLoader valueLoader(fArchitecture, fDebuggerInterface, - fTypeInformation, fCpuState); - ValueLocation* location; - Value* value; - status_t error = fValueNode->ResolvedLocationAndValue(&valueLoader, - location, value); - if (error != B_OK) { - TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value " - "node: %p (\"%s\"): fValueNode->ResolvedLocationAndValue() " - "failed\n", fValueNode, fValueNode->Name().String()); - return error; - } - BReference locationReference(location, true); - BReference valueReference(value, true); - - // set location and value on the node - containerLocker.Lock(); - status_t nodeResolutionState - = fValueNode->LocationAndValueResolutionState(); - if (nodeResolutionState != VALUE_NODE_UNRESOLVED) - return nodeResolutionState; - fValueNode->SetLocationAndValue(location, value, B_OK); - containerLocker.Unlock(); - - return B_OK; -} - - -status_t -ResolveValueNodeValueJob::_ResolveNodeChildLocation(ValueNodeChild* nodeChild) -{ - // resolve the location - ValueLoader valueLoader(fArchitecture, fDebuggerInterface, - fTypeInformation, fCpuState); - ValueLocation* location = NULL; - status_t error = nodeChild->ResolveLocation(&valueLoader, location); - BReference locationReference(location, true); - - // set the location on the node child - AutoLocker containerLocker(fContainer); - status_t nodeChildResolutionState = nodeChild->LocationResolutionState(); - if (nodeChildResolutionState == VALUE_NODE_UNRESOLVED) - nodeChild->SetLocation(location, error); - else - error = nodeChildResolutionState; - - return error; -} - - -status_t -ResolveValueNodeValueJob::_ResolveParentNodeValue(ValueNode* parentNode) -{ - AutoLocker containerLocker(fContainer); - - if (parentNode->Container() != fContainer) - return B_BAD_VALUE; - - // if the parent node already has a value, we're done - status_t nodeResolutionState - = parentNode->LocationAndValueResolutionState(); - if (nodeResolutionState != VALUE_NODE_UNRESOLVED) - return nodeResolutionState; - - // check whether a job is already in progress - AutoLocker workerLocker(GetWorker()); - SimpleJobKey jobKey(parentNode, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE); - if (GetWorker()->GetJob(jobKey) == NULL) { - workerLocker.Unlock(); - - // schedule the job - status_t error = GetWorker()->ScheduleJob( - new(std::nothrow) ResolveValueNodeValueJob(fDebuggerInterface, - fArchitecture, fCpuState, fTypeInformation, fContainer, - parentNode)); - if (error != B_OK) { - // scheduling failed -- set the value to invalid - parentNode->SetLocationAndValue(NULL, NULL, error); - return error; - } - } - - // wait for the job to finish - workerLocker.Unlock(); - containerLocker.Unlock(); - - switch (WaitFor(jobKey)) { - case JOB_DEPENDENCY_SUCCEEDED: - case JOB_DEPENDENCY_NOT_FOUND: - // "Not found" can happen due to a race condition between - // unlocking the worker and starting to wait. - break; - case JOB_DEPENDENCY_ACTIVE: - return B_OK; - case JOB_DEPENDENCY_FAILED: - case JOB_DEPENDENCY_ABORTED: - default: - return B_ERROR; - } - - containerLocker.Lock(); - - // now there should be a value for the node - nodeResolutionState = parentNode->LocationAndValueResolutionState(); - return nodeResolutionState != VALUE_NODE_UNRESOLVED - ? nodeResolutionState : B_ERROR; -} - - -RetrieveMemoryBlockJob::RetrieveMemoryBlockJob(Team* team, - TeamMemory* teamMemory, TeamMemoryBlock* memoryBlock) - : - fKey(memoryBlock, JOB_TYPE_GET_MEMORY_BLOCK), - fTeam(team), - fTeamMemory(teamMemory), - fMemoryBlock(memoryBlock) -{ - fTeamMemory->AcquireReference(); - fMemoryBlock->AcquireReference(); -} - - -RetrieveMemoryBlockJob::~RetrieveMemoryBlockJob() -{ - fTeamMemory->ReleaseReference(); - fMemoryBlock->ReleaseReference(); -} - - -const JobKey& -RetrieveMemoryBlockJob::Key() const -{ - return fKey; -} - - -status_t -RetrieveMemoryBlockJob::Do() -{ - ssize_t result = fTeamMemory->ReadMemory(fMemoryBlock->BaseAddress(), - fMemoryBlock->Data(), fMemoryBlock->Size()); - if (result < 0) - return result; - - uint32 protection = 0; - uint32 locking = 0; - status_t error = get_memory_properties(fTeam->ID(), - (const void *)fMemoryBlock->BaseAddress(), &protection, &locking); - if (error != B_OK) - return error; - - fMemoryBlock->SetWritable((protection & B_WRITE_AREA) != 0); - fMemoryBlock->MarkValid(); - return B_OK; -} diff --git a/src/apps/debugger/TeamDebugger.cpp b/src/apps/debugger/controllers/TeamDebugger.cpp similarity index 100% rename from src/apps/debugger/TeamDebugger.cpp rename to src/apps/debugger/controllers/TeamDebugger.cpp diff --git a/src/apps/debugger/TeamDebugger.h b/src/apps/debugger/controllers/TeamDebugger.h similarity index 100% rename from src/apps/debugger/TeamDebugger.h rename to src/apps/debugger/controllers/TeamDebugger.h diff --git a/src/apps/debugger/ThreadHandler.cpp b/src/apps/debugger/controllers/ThreadHandler.cpp similarity index 100% rename from src/apps/debugger/ThreadHandler.cpp rename to src/apps/debugger/controllers/ThreadHandler.cpp diff --git a/src/apps/debugger/ThreadHandler.h b/src/apps/debugger/controllers/ThreadHandler.h similarity index 100% rename from src/apps/debugger/ThreadHandler.h rename to src/apps/debugger/controllers/ThreadHandler.h diff --git a/src/apps/debugger/BreakpointManager.cpp b/src/apps/debugger/debug_managers/BreakpointManager.cpp similarity index 100% rename from src/apps/debugger/BreakpointManager.cpp rename to src/apps/debugger/debug_managers/BreakpointManager.cpp diff --git a/src/apps/debugger/BreakpointManager.h b/src/apps/debugger/debug_managers/BreakpointManager.h similarity index 100% rename from src/apps/debugger/BreakpointManager.h rename to src/apps/debugger/debug_managers/BreakpointManager.h diff --git a/src/apps/debugger/TeamMemoryBlockManager.cpp b/src/apps/debugger/debug_managers/TeamMemoryBlockManager.cpp similarity index 100% rename from src/apps/debugger/TeamMemoryBlockManager.cpp rename to src/apps/debugger/debug_managers/TeamMemoryBlockManager.cpp diff --git a/src/apps/debugger/TeamMemoryBlockManager.h b/src/apps/debugger/debug_managers/TeamMemoryBlockManager.h similarity index 100% rename from src/apps/debugger/TeamMemoryBlockManager.h rename to src/apps/debugger/debug_managers/TeamMemoryBlockManager.h diff --git a/src/apps/debugger/WatchpointManager.cpp b/src/apps/debugger/debug_managers/WatchpointManager.cpp similarity index 100% rename from src/apps/debugger/WatchpointManager.cpp rename to src/apps/debugger/debug_managers/WatchpointManager.cpp diff --git a/src/apps/debugger/WatchpointManager.h b/src/apps/debugger/debug_managers/WatchpointManager.h similarity index 100% rename from src/apps/debugger/WatchpointManager.h rename to src/apps/debugger/debug_managers/WatchpointManager.h diff --git a/src/apps/debugger/jobs/GetCPUStateJob.cpp b/src/apps/debugger/jobs/GetCPUStateJob.cpp new file mode 100644 index 0000000000..2d28c4cd79 --- /dev/null +++ b/src/apps/debugger/jobs/GetCPUStateJob.cpp @@ -0,0 +1,56 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "Jobs.h" + +#include + +#include "CpuState.h" +#include "DebuggerInterface.h" +#include "Team.h" +#include "Thread.h" + + +GetCpuStateJob::GetCpuStateJob(DebuggerInterface* debuggerInterface, + Thread* thread) + : + fKey(thread, JOB_TYPE_GET_CPU_STATE), + fDebuggerInterface(debuggerInterface), + fThread(thread) +{ + fThread->AcquireReference(); +} + + +GetCpuStateJob::~GetCpuStateJob() +{ + fThread->ReleaseReference(); +} + + +const JobKey& +GetCpuStateJob::Key() const +{ + return fKey; +} + + +status_t +GetCpuStateJob::Do() +{ + CpuState* state; + status_t error = fDebuggerInterface->GetCpuState(fThread->ID(), state); + if (error != B_OK) + return error; + BReference reference(state, true); + + AutoLocker locker(fThread->GetTeam()); + + if (fThread->State() == THREAD_STATE_STOPPED) + fThread->SetCpuState(state); + + return B_OK; +} diff --git a/src/apps/debugger/jobs/GetStackTraceJob.cpp b/src/apps/debugger/jobs/GetStackTraceJob.cpp new file mode 100644 index 0000000000..61a1c724d8 --- /dev/null +++ b/src/apps/debugger/jobs/GetStackTraceJob.cpp @@ -0,0 +1,116 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "Jobs.h" + +#include + +#include "Architecture.h" +#include "CpuState.h" +#include "DebuggerInterface.h" +#include "ImageDebugInfo.h" +#include "StackTrace.h" +#include "Thread.h" +#include "Team.h" + + +GetStackTraceJob::GetStackTraceJob(DebuggerInterface* debuggerInterface, + Architecture* architecture, Thread* thread) + : + fKey(thread, JOB_TYPE_GET_STACK_TRACE), + fDebuggerInterface(debuggerInterface), + fArchitecture(architecture), + fThread(thread) +{ + fThread->AcquireReference(); + + fCpuState = fThread->GetCpuState(); + if (fCpuState != NULL) + fCpuState->AcquireReference(); +} + + +GetStackTraceJob::~GetStackTraceJob() +{ + if (fCpuState != NULL) + fCpuState->ReleaseReference(); + + fThread->ReleaseReference(); +} + + +const JobKey& +GetStackTraceJob::Key() const +{ + return fKey; +} + + +status_t +GetStackTraceJob::Do() +{ + if (fCpuState == NULL) + return B_BAD_VALUE; + + // get the stack trace + StackTrace* stackTrace; + status_t error = fArchitecture->CreateStackTrace(fThread->GetTeam(), this, + fCpuState, stackTrace); + if (error != B_OK) + return error; + BReference stackTraceReference(stackTrace, true); + + // set the stack trace, unless something has changed + AutoLocker locker(fThread->GetTeam()); + + if (fThread->GetCpuState() == fCpuState) + fThread->SetStackTrace(stackTrace); + + return B_OK; +} + + +status_t +GetStackTraceJob::GetImageDebugInfo(Image* image, ImageDebugInfo*& _info) +{ + AutoLocker teamLocker(fThread->GetTeam()); + + while (image->GetImageDebugInfo() == NULL) { + // schedule a job, if not loaded + ImageDebugInfo* info; + status_t error = LoadImageDebugInfoJob::ScheduleIfNecessary(GetWorker(), + image, &info); + if (error != B_OK) + return error; + + if (info != NULL) { + _info = info; + return B_OK; + } + + teamLocker.Unlock(); + + // wait for the job to finish + switch (WaitFor(SimpleJobKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO))) { + case JOB_DEPENDENCY_SUCCEEDED: + case JOB_DEPENDENCY_NOT_FOUND: + // "Not found" can happen due to a race condition between + // unlocking the worker and starting to wait. + break; + case JOB_DEPENDENCY_FAILED: + case JOB_DEPENDENCY_ABORTED: + default: + return B_ERROR; + } + + teamLocker.Lock(); + } + + _info = image->GetImageDebugInfo(); + _info->AcquireReference(); + + return B_OK; +} diff --git a/src/apps/debugger/jobs/GetThreadStateJob.cpp b/src/apps/debugger/jobs/GetThreadStateJob.cpp new file mode 100644 index 0000000000..61ae3dd026 --- /dev/null +++ b/src/apps/debugger/jobs/GetThreadStateJob.cpp @@ -0,0 +1,62 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "Jobs.h" + +#include + +#include "CpuState.h" +#include "DebuggerInterface.h" +#include "Team.h" +#include "Thread.h" + + +GetThreadStateJob::GetThreadStateJob(DebuggerInterface* debuggerInterface, + Thread* thread) + : + fKey(thread, JOB_TYPE_GET_THREAD_STATE), + fDebuggerInterface(debuggerInterface), + fThread(thread) +{ + fThread->AcquireReference(); +} + + +GetThreadStateJob::~GetThreadStateJob() +{ + fThread->ReleaseReference(); +} + + +const JobKey& +GetThreadStateJob::Key() const +{ + return fKey; +} + + +status_t +GetThreadStateJob::Do() +{ + CpuState* state = NULL; + status_t error = fDebuggerInterface->GetCpuState(fThread->ID(), state); + BReference reference(state, true); + + AutoLocker locker(fThread->GetTeam()); + + if (fThread->State() != THREAD_STATE_UNKNOWN) + return B_OK; + + if (error == B_OK) { + fThread->SetState(THREAD_STATE_STOPPED); + fThread->SetCpuState(state); + } else if (error == B_BAD_THREAD_STATE) { + fThread->SetState(THREAD_STATE_RUNNING); + } else + return error; + + return B_OK; +} diff --git a/src/apps/debugger/Jobs.h b/src/apps/debugger/jobs/Jobs.h similarity index 100% rename from src/apps/debugger/Jobs.h rename to src/apps/debugger/jobs/Jobs.h diff --git a/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp b/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp new file mode 100644 index 0000000000..dc1706c29f --- /dev/null +++ b/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp @@ -0,0 +1,106 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "Jobs.h" + +#include + +#include "Image.h" +#include "ImageDebugInfo.h" +#include "TeamDebugInfo.h" +#include "Team.h" + + +LoadImageDebugInfoJob::LoadImageDebugInfoJob(Image* image) + : + fKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO), + fImage(image) +{ + fImage->AcquireReference(); +} + + +LoadImageDebugInfoJob::~LoadImageDebugInfoJob() +{ + fImage->ReleaseReference(); +} + + +const JobKey& +LoadImageDebugInfoJob::Key() const +{ + return fKey; +} + + +status_t +LoadImageDebugInfoJob::Do() +{ + // get an image info for the image + AutoLocker locker(fImage->GetTeam()); + ImageInfo imageInfo(fImage->Info()); + locker.Unlock(); + + // create the debug info + ImageDebugInfo* debugInfo; + status_t error = fImage->GetTeam()->DebugInfo()->LoadImageDebugInfo( + imageInfo, fImage->ImageFile(), debugInfo); + + // set the result + locker.Lock(); + if (error == B_OK) { + error = fImage->SetImageDebugInfo(debugInfo, IMAGE_DEBUG_INFO_LOADED); + debugInfo->ReleaseReference(); + } else + fImage->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_UNAVAILABLE); + + return error; +} + + +/*static*/ status_t +LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image, + ImageDebugInfo** _imageDebugInfo) +{ + AutoLocker teamLocker(image->GetTeam()); + + // If already loaded, we're done. + if (image->GetImageDebugInfo() != NULL) { + if (_imageDebugInfo != NULL) { + *_imageDebugInfo = image->GetImageDebugInfo(); + (*_imageDebugInfo)->AcquireReference(); + } + return B_OK; + } + + // If already loading, the caller has to wait, if desired. + if (image->ImageDebugInfoState() == IMAGE_DEBUG_INFO_LOADING) { + if (_imageDebugInfo != NULL) + *_imageDebugInfo = NULL; + return B_OK; + } + + // If an earlier load attempt failed, bail out. + if (image->ImageDebugInfoState() != IMAGE_DEBUG_INFO_NOT_LOADED) + return B_ERROR; + + // schedule a job + LoadImageDebugInfoJob* job = new(std::nothrow) LoadImageDebugInfoJob(image); + if (job == NULL) + return B_NO_MEMORY; + + status_t error = worker->ScheduleJob(job); + if (error != B_OK) { + image->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_UNAVAILABLE); + return error; + } + + image->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_LOADING); + + if (_imageDebugInfo != NULL) + *_imageDebugInfo = NULL; + return B_OK; +} diff --git a/src/apps/debugger/jobs/LoadSourceCodeJob.cpp b/src/apps/debugger/jobs/LoadSourceCodeJob.cpp new file mode 100644 index 0000000000..4cb60a0a31 --- /dev/null +++ b/src/apps/debugger/jobs/LoadSourceCodeJob.cpp @@ -0,0 +1,93 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "Jobs.h" + +#include + +#include "Architecture.h" +#include "DebuggerInterface.h" +#include "DisassembledCode.h" +#include "Function.h" +#include "FunctionInstance.h" +#include "FileSourceCode.h" +#include "Team.h" +#include "TeamDebugInfo.h" + + +LoadSourceCodeJob::LoadSourceCodeJob( + DebuggerInterface* debuggerInterface, Architecture* architecture, + Team* team, FunctionInstance* functionInstance, bool loadForFunction) + : + fKey(functionInstance, JOB_TYPE_LOAD_SOURCE_CODE), + fDebuggerInterface(debuggerInterface), + fArchitecture(architecture), + fTeam(team), + fFunctionInstance(functionInstance), + fLoadForFunction(loadForFunction) +{ + fFunctionInstance->AcquireReference(); +} + + +LoadSourceCodeJob::~LoadSourceCodeJob() +{ + fFunctionInstance->ReleaseReference(); +} + + +const JobKey& +LoadSourceCodeJob::Key() const +{ + return fKey; +} + + +status_t +LoadSourceCodeJob::Do() +{ + // if requested, try loading the source code for the function + Function* function = fFunctionInstance->GetFunction(); + if (fLoadForFunction) { + FileSourceCode* sourceCode; + status_t error = fTeam->DebugInfo()->LoadSourceCode( + function->SourceFile(), sourceCode); + + AutoLocker locker(fTeam); + + if (error == B_OK) { + function->SetSourceCode(sourceCode, FUNCTION_SOURCE_LOADED); + sourceCode->ReleaseReference(); + return B_OK; + } + + function->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE); + } + + // Only try to load the function instance code, if it's not overridden yet. + AutoLocker locker(fTeam); + if (fFunctionInstance->SourceCodeState() != FUNCTION_SOURCE_LOADING) + return B_OK; + locker.Unlock(); + + // disassemble the function + DisassembledCode* sourceCode = NULL; + status_t error = fTeam->DebugInfo()->DisassembleFunction(fFunctionInstance, + sourceCode); + + // set the result + locker.Lock(); + if (error == B_OK) { + if (fFunctionInstance->SourceCodeState() == FUNCTION_SOURCE_LOADING) { + fFunctionInstance->SetSourceCode(sourceCode, + FUNCTION_SOURCE_LOADED); + sourceCode->ReleaseReference(); + } + } else + fFunctionInstance->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE); + + return error; +} diff --git a/src/apps/debugger/jobs/ResolveValueNodeJob.cpp b/src/apps/debugger/jobs/ResolveValueNodeJob.cpp new file mode 100644 index 0000000000..c810ad5c3e --- /dev/null +++ b/src/apps/debugger/jobs/ResolveValueNodeJob.cpp @@ -0,0 +1,254 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "Jobs.h" + +#include + +#include "Architecture.h" +#include "CpuState.h" +#include "DebuggerInterface.h" +#include "TeamTypeInformation.h" +#include "Tracing.h" +#include "Value.h" +#include "ValueLoader.h" +#include "ValueLocation.h" +#include "ValueNode.h" +#include "ValueNodeContainer.h" + + +ResolveValueNodeValueJob::ResolveValueNodeValueJob( + DebuggerInterface* debuggerInterface, Architecture* architecture, + CpuState* cpuState, TeamTypeInformation* typeInformation, + ValueNodeContainer* container, ValueNode* valueNode) + : + fKey(valueNode, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE), + fDebuggerInterface(debuggerInterface), + fArchitecture(architecture), + fCpuState(cpuState), + fTypeInformation(typeInformation), + fContainer(container), + fValueNode(valueNode) +{ + if (fCpuState != NULL) + fCpuState->AcquireReference(); + fContainer->AcquireReference(); + fValueNode->AcquireReference(); +} + + +ResolveValueNodeValueJob::~ResolveValueNodeValueJob() +{ + if (fCpuState != NULL) + fCpuState->ReleaseReference(); + fContainer->ReleaseReference(); + fValueNode->ReleaseReference(); +} + + +const JobKey& +ResolveValueNodeValueJob::Key() const +{ + return fKey; +} + + +status_t +ResolveValueNodeValueJob::Do() +{ + // check whether the node still belongs to the container + AutoLocker containerLocker(fContainer); + if (fValueNode->Container() != fContainer) + return B_BAD_VALUE; + + // if already resolved, we're done + status_t nodeResolutionState + = fValueNode->LocationAndValueResolutionState(); + if (nodeResolutionState != VALUE_NODE_UNRESOLVED) + return nodeResolutionState; + + containerLocker.Unlock(); + + // resolve + status_t error = _ResolveNodeValue(); + if (error != B_OK) { + nodeResolutionState = fValueNode->LocationAndValueResolutionState(); + if (nodeResolutionState != VALUE_NODE_UNRESOLVED) + return nodeResolutionState; + + containerLocker.Lock(); + fValueNode->SetLocationAndValue(NULL, NULL, error); + containerLocker.Unlock(); + } + + return error; +} + + +status_t +ResolveValueNodeValueJob::_ResolveNodeValue() +{ + // get the node child and parent node + AutoLocker containerLocker(fContainer); + ValueNodeChild* nodeChild = fValueNode->NodeChild(); + BReference nodeChildReference(nodeChild); + + ValueNode* parentNode = nodeChild->Parent(); + BReference parentNodeReference(parentNode); + + // Check whether the node child location has been resolved already + // (successfully). + status_t nodeChildResolutionState = nodeChild->LocationResolutionState(); + bool nodeChildDone = nodeChildResolutionState != VALUE_NODE_UNRESOLVED; + if (nodeChildDone && nodeChildResolutionState != B_OK) + return nodeChildResolutionState; + + // If the child node location has not been resolved yet, check whether the + // parent node location and value have been resolved already (successfully). + bool parentDone = true; + if (!nodeChildDone && parentNode != NULL) { + status_t parentResolutionState + = parentNode->LocationAndValueResolutionState(); + parentDone = parentResolutionState != VALUE_NODE_UNRESOLVED; + if (parentDone && parentResolutionState != B_OK) + return parentResolutionState; + } + + containerLocker.Unlock(); + + // resolve the parent node location and value, if necessary + if (!parentDone) { + status_t error = _ResolveParentNodeValue(parentNode); + if (error != B_OK) { + TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value " + "node: %p (\"%s\"): _ResolveParentNodeValue(%p) failed\n", + fValueNode, fValueNode->Name().String(), parentNode); + return error; + } + + if (State() == JOB_STATE_WAITING) + return B_OK; + } + + // resolve the node child location, if necessary + if (!nodeChildDone) { + status_t error = _ResolveNodeChildLocation(nodeChild); + if (error != B_OK) { + TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value " + "node: %p (\"%s\"): _ResolveNodeChildLocation(%p) failed\n", + fValueNode, fValueNode->Name().String(), nodeChild); + return error; + } + } + + // resolve the node location and value + ValueLoader valueLoader(fArchitecture, fDebuggerInterface, + fTypeInformation, fCpuState); + ValueLocation* location; + Value* value; + status_t error = fValueNode->ResolvedLocationAndValue(&valueLoader, + location, value); + if (error != B_OK) { + TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value " + "node: %p (\"%s\"): fValueNode->ResolvedLocationAndValue() " + "failed\n", fValueNode, fValueNode->Name().String()); + return error; + } + BReference locationReference(location, true); + BReference valueReference(value, true); + + // set location and value on the node + containerLocker.Lock(); + status_t nodeResolutionState + = fValueNode->LocationAndValueResolutionState(); + if (nodeResolutionState != VALUE_NODE_UNRESOLVED) + return nodeResolutionState; + fValueNode->SetLocationAndValue(location, value, B_OK); + containerLocker.Unlock(); + + return B_OK; +} + + +status_t +ResolveValueNodeValueJob::_ResolveNodeChildLocation(ValueNodeChild* nodeChild) +{ + // resolve the location + ValueLoader valueLoader(fArchitecture, fDebuggerInterface, + fTypeInformation, fCpuState); + ValueLocation* location = NULL; + status_t error = nodeChild->ResolveLocation(&valueLoader, location); + BReference locationReference(location, true); + + // set the location on the node child + AutoLocker containerLocker(fContainer); + status_t nodeChildResolutionState = nodeChild->LocationResolutionState(); + if (nodeChildResolutionState == VALUE_NODE_UNRESOLVED) + nodeChild->SetLocation(location, error); + else + error = nodeChildResolutionState; + + return error; +} + + +status_t +ResolveValueNodeValueJob::_ResolveParentNodeValue(ValueNode* parentNode) +{ + AutoLocker containerLocker(fContainer); + + if (parentNode->Container() != fContainer) + return B_BAD_VALUE; + + // if the parent node already has a value, we're done + status_t nodeResolutionState + = parentNode->LocationAndValueResolutionState(); + if (nodeResolutionState != VALUE_NODE_UNRESOLVED) + return nodeResolutionState; + + // check whether a job is already in progress + AutoLocker workerLocker(GetWorker()); + SimpleJobKey jobKey(parentNode, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE); + if (GetWorker()->GetJob(jobKey) == NULL) { + workerLocker.Unlock(); + + // schedule the job + status_t error = GetWorker()->ScheduleJob( + new(std::nothrow) ResolveValueNodeValueJob(fDebuggerInterface, + fArchitecture, fCpuState, fTypeInformation, fContainer, + parentNode)); + if (error != B_OK) { + // scheduling failed -- set the value to invalid + parentNode->SetLocationAndValue(NULL, NULL, error); + return error; + } + } + + // wait for the job to finish + workerLocker.Unlock(); + containerLocker.Unlock(); + + switch (WaitFor(jobKey)) { + case JOB_DEPENDENCY_SUCCEEDED: + case JOB_DEPENDENCY_NOT_FOUND: + // "Not found" can happen due to a race condition between + // unlocking the worker and starting to wait. + break; + case JOB_DEPENDENCY_ACTIVE: + return B_OK; + case JOB_DEPENDENCY_FAILED: + case JOB_DEPENDENCY_ABORTED: + default: + return B_ERROR; + } + + containerLocker.Lock(); + + // now there should be a value for the node + nodeResolutionState = parentNode->LocationAndValueResolutionState(); + return nodeResolutionState != VALUE_NODE_UNRESOLVED + ? nodeResolutionState : B_ERROR; +} diff --git a/src/apps/debugger/jobs/RetrieveMemoryBlockJob.cpp b/src/apps/debugger/jobs/RetrieveMemoryBlockJob.cpp new file mode 100644 index 0000000000..888bfa4ae8 --- /dev/null +++ b/src/apps/debugger/jobs/RetrieveMemoryBlockJob.cpp @@ -0,0 +1,62 @@ +/* + * Copyright 2012, Rene Gollent, rene@gollent.com. + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "Jobs.h" + +#include +#include + +#include "Team.h" +#include "TeamMemory.h" +#include "TeamMemoryBlock.h" + + +RetrieveMemoryBlockJob::RetrieveMemoryBlockJob(Team* team, + TeamMemory* teamMemory, TeamMemoryBlock* memoryBlock) + : + fKey(memoryBlock, JOB_TYPE_GET_MEMORY_BLOCK), + fTeam(team), + fTeamMemory(teamMemory), + fMemoryBlock(memoryBlock) +{ + fTeamMemory->AcquireReference(); + fMemoryBlock->AcquireReference(); +} + + +RetrieveMemoryBlockJob::~RetrieveMemoryBlockJob() +{ + fTeamMemory->ReleaseReference(); + fMemoryBlock->ReleaseReference(); +} + + +const JobKey& +RetrieveMemoryBlockJob::Key() const +{ + return fKey; +} + + +status_t +RetrieveMemoryBlockJob::Do() +{ + ssize_t result = fTeamMemory->ReadMemory(fMemoryBlock->BaseAddress(), + fMemoryBlock->Data(), fMemoryBlock->Size()); + if (result < 0) + return result; + + uint32 protection = 0; + uint32 locking = 0; + status_t error = get_memory_properties(fTeam->ID(), + (const void *)fMemoryBlock->BaseAddress(), &protection, &locking); + if (error != B_OK) + return error; + + fMemoryBlock->SetWritable((protection & B_WRITE_AREA) != 0); + fMemoryBlock->MarkValid(); + return B_OK; +} diff --git a/src/apps/debugger/Worker.cpp b/src/apps/debugger/util/Worker.cpp similarity index 100% rename from src/apps/debugger/Worker.cpp rename to src/apps/debugger/util/Worker.cpp diff --git a/src/apps/debugger/Worker.h b/src/apps/debugger/util/Worker.h similarity index 100% rename from src/apps/debugger/Worker.h rename to src/apps/debugger/util/Worker.h From 62cff38e78655844c423a71e796f7ab60fa8b61b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Wed, 7 Nov 2012 23:45:14 +0100 Subject: [PATCH 31/31] usb_asix: fix for 88772B * select RX header format type 1 for AX88772B. * should help with #8238 --- .../network/usb_asix/AX88772Device.cpp | 25 +++++-------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/src/add-ons/kernel/drivers/network/usb_asix/AX88772Device.cpp b/src/add-ons/kernel/drivers/network/usb_asix/AX88772Device.cpp index 728917fe66..8bb1e4b9a7 100644 --- a/src/add-ons/kernel/drivers/network/usb_asix/AX88772Device.cpp +++ b/src/add-ons/kernel/drivers/network/usb_asix/AX88772Device.cpp @@ -368,12 +368,6 @@ AX88772Device::_SetupAX88772() snooze(150000); - result = WriteRXControlRegister(0); - if (result != B_OK) { - TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", 0, result); - return result; - } - return B_OK; } @@ -449,12 +443,6 @@ AX88772Device::_SetupAX88772A() if (result != B_OK) return result; - result = WriteRXControlRegister(0); - if (result != B_OK) { - TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", 0, result); - return result; - } - fIPG[0] = 0x15; fIPG[1] = 0x16; fIPG[2] = 0x1A; @@ -481,12 +469,6 @@ AX88772Device::_SetupAX88772B() if (result != B_OK) return result; - result = WriteRXControlRegister(0); - if (result != B_OK) { - TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", 0, result); - return result; - } - fIPG[0] = 0x15; fIPG[1] = 0x16; fIPG[2] = 0x1A; @@ -513,6 +495,9 @@ AX88772Device::StartDevice() "%d bytes of %d written.\n", actualLength, sizeof(fIPG)); } + + uint16 rxcontrol = 0; + // AX88772B uses different maximum frame burst configuration. if (fDeviceInfo.fType == DeviceInfo::AX88772B) { result = gUSBModule->send_request(fDevice, @@ -526,9 +511,11 @@ AX88772Device::StartDevice() TRACE_ALWAYS("Error of writing frame burst:%#010x\n", result); return result; } + + rxcontrol = RXCTL_USB_MFB; } - uint16 rxcontrol = RXCTL_START | RXCTL_BROADCAST; + rxcontrol |= RXCTL_START | RXCTL_BROADCAST; result = WriteRXControlRegister(rxcontrol); if (result != B_OK) { TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n",