Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 165785 Details for
Bug 280631
[debug view][cdi] Thread list in Debug view not updated with non-Linux target
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read
this important communication.
[patch]
Updated fix based on Marc's code review
patch_280631_2 (text/plain), 19.19 KB, created by
John Cortell
on 2010-04-22 12:07:22 EDT
(
hide
)
Description:
Updated fix based on Marc's code review
Filename:
MIME Type:
Creator:
John Cortell
Created:
2010-04-22 12:07:22 EDT
Size:
19.19 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P org.eclipse.cdt.doc.user >Index: contexts_CDT_DEBUGGER_DSFGDB.xml >=================================================================== >RCS file: /cvsroot/tools/org.eclipse.cdt/all/org.eclipse.cdt.doc.user/contexts_CDT_DEBUGGER_DSFGDB.xml,v >retrieving revision 1.1 >diff -u -r1.1 contexts_CDT_DEBUGGER_DSFGDB.xml >--- contexts_CDT_DEBUGGER_DSFGDB.xml 20 Apr 2010 22:53:36 -0000 1.1 >+++ contexts_CDT_DEBUGGER_DSFGDB.xml 22 Apr 2010 16:06:06 -0000 >@@ -15,6 +15,9 @@ > <description>Control the behavior of the C/C++ debugger when debugging with GDB, specifically when using a GDB (DSF) launcher.</description> > <topic href="reference/cdt_u_dsfgdb.htm" label="GDB Preferences"/> > </context> >+<context id="update_threadlist_button_context" title="About this checkbox"> >+ <description>This checkbox controls whether the CDT debugger will ask gdb for the target program's thread list on each suspend event (breakpoint-hit, step, etc). Normally, this isn't necessary, as GDB sends notifications in realtime when a thread is created or destroyed. However, some lightweight GDB remote stubs won't send these notifications. As such, the CDT debugger doesn't find out about new or destroyed threads unless it polls gdb. Turn on this option if you are debugging such a target (typically an embedded one).</description> >+</context> > > > </contexts> >#P org.eclipse.cdt.dsf.gdb >Index: src/org/eclipse/cdt/dsf/gdb/IGDBLaunchConfigurationConstants.java >=================================================================== >RCS file: /cvsroot/tools/org.eclipse.cdt/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/IGDBLaunchConfigurationConstants.java,v >retrieving revision 1.3 >diff -u -r1.3 IGDBLaunchConfigurationConstants.java >--- src/org/eclipse/cdt/dsf/gdb/IGDBLaunchConfigurationConstants.java 28 Feb 2009 15:26:23 -0000 1.3 >+++ src/org/eclipse/cdt/dsf/gdb/IGDBLaunchConfigurationConstants.java 22 Apr 2010 16:06:07 -0000 >@@ -81,6 +81,14 @@ > * @since 2.0 > */ > public static final String ATTR_DEBUGGER_REVERSE = GdbPlugin.PLUGIN_ID + ".REVERSE"; //$NON-NLS-1$ >+ >+ /** >+ * Launch configuration attribute key. Boolean value. See >+ * IGDBBackend.getUpdateThreadListOnSuspend() >+ * >+ * @since 3.0 >+ */ >+ public static final String ATTR_DEBUGGER_UPDATE_THREADLIST_ON_SUSPEND = GdbPlugin.PLUGIN_ID + ".UPDATE_THREADLIST_ON_SUSPEND"; //$NON-NLS-1$ > > /** > * Launch configuration attribute value. The key is ATTR_DEBUG_NAME. >@@ -114,4 +122,13 @@ > * @since 2.0 > */ > public static final boolean DEBUGGER_REVERSE_DEFAULT = false; >+ >+ /** >+ * Launch configuration attribute value. The key is >+ * ATTR_DEBUGGER_UPDATE_THREADLIST_ON_SUSPEND >+ * >+ * @since 3.0 >+ */ >+ public static final boolean DEBUGGER_UPDATE_THREADLIST_ON_SUSPEND_DEFAULT = false; >+ > } >Index: src/org/eclipse/cdt/dsf/gdb/service/GDBBackend.java >=================================================================== >RCS file: /cvsroot/tools/org.eclipse.cdt/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend.java,v >retrieving revision 1.9 >diff -u -r1.9 GDBBackend.java >--- src/org/eclipse/cdt/dsf/gdb/service/GDBBackend.java 1 Apr 2010 22:21:42 -0000 1.9 >+++ src/org/eclipse/cdt/dsf/gdb/service/GDBBackend.java 22 Apr 2010 16:06:07 -0000 >@@ -335,6 +335,14 @@ > return !fLaunchConfiguration.getAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, true); > } > >+ /** @since 3.0 */ >+ public boolean getUpdateThreadListOnSuspend() throws CoreException { >+ return fLaunchConfiguration >+ .getAttribute( >+ IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_UPDATE_THREADLIST_ON_SUSPEND, >+ IGDBLaunchConfigurationConstants.DEBUGGER_UPDATE_THREADLIST_ON_SUSPEND_DEFAULT); >+ } >+ > /* > * Launch GDB process. > * Allow subclass to override. >Index: src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_0.java >=================================================================== >RCS file: /cvsroot/tools/org.eclipse.cdt/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_0.java,v >retrieving revision 1.15 >diff -u -r1.15 GDBProcesses_7_0.java >--- src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_0.java 9 Apr 2010 23:00:03 -0000 1.15 >+++ src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_0.java 22 Apr 2010 16:06:07 -0000 >@@ -65,6 +65,7 @@ > import org.eclipse.cdt.dsf.service.AbstractDsfService; > import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; > import org.eclipse.cdt.dsf.service.DsfSession; >+import org.eclipse.core.runtime.CoreException; > import org.eclipse.core.runtime.IStatus; > import org.eclipse.core.runtime.Status; > import org.osgi.framework.BundleContext; >@@ -882,6 +883,16 @@ > } else { > // This will happen in non-stop mode > } >+ >+ // If user is debugging a gdb target that doesn't send thread >+ // creation events, make sure we don't use cached thread >+ // information. Reset the cache after every suspend. See bugzilla >+ // 280631 >+ try { >+ if (fBackend.getUpdateThreadListOnSuspend()) { >+ fThreadCommandCache.reset(e.getDMContext()); >+ } >+ } catch (CoreException exc) {} > } > > // Event handler when a thread or threadGroup starts >Index: src/org/eclipse/cdt/dsf/gdb/service/IGDBBackend.java >=================================================================== >RCS file: /cvsroot/tools/org.eclipse.cdt/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBBackend.java,v >retrieving revision 1.4 >diff -u -r1.4 IGDBBackend.java >--- src/org/eclipse/cdt/dsf/gdb/service/IGDBBackend.java 12 Mar 2010 17:29:17 -0000 1.4 >+++ src/org/eclipse/cdt/dsf/gdb/service/IGDBBackend.java 22 Apr 2010 16:06:07 -0000 >@@ -133,4 +133,18 @@ > * @return true if the ongoing session is attaching to a remote target. > */ > public boolean getIsAttachSession(); >+ >+ /** >+ * Indicates whether the CDT debugger should ask gdb for the target >+ * program's thread list on each suspend event (breakpoint-hit, step, etc). >+ * Normally, this isn't necessary, as GDB sends notifications in realtime >+ * when a thread is created or destroyed. However, some lightweight GDB >+ * remote stubs won't send these notifications. As such, the CDT debugger >+ * doesn't find out about new or destroyed threads unless it polls gdb. The >+ * user will enable this behavior if he is debugging such a target >+ * (typically an embedded one) >+ * >+ * @since 3.0 >+ */ >+ public boolean getUpdateThreadListOnSuspend() throws CoreException; > } >Index: src/org/eclipse/cdt/dsf/mi/service/MIProcesses.java >=================================================================== >RCS file: /cvsroot/tools/org.eclipse.cdt/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIProcesses.java,v >retrieving revision 1.5 >diff -u -r1.5 MIProcesses.java >--- src/org/eclipse/cdt/dsf/mi/service/MIProcesses.java 3 Mar 2010 14:35:50 -0000 1.5 >+++ src/org/eclipse/cdt/dsf/mi/service/MIProcesses.java 22 Apr 2010 16:06:07 -0000 >@@ -33,6 +33,7 @@ > import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService; > import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext; > import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; >+import org.eclipse.cdt.dsf.gdb.service.IGDBBackend; > import org.eclipse.cdt.dsf.mi.service.command.CommandFactory; > import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoThreadsInfo; > import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; >@@ -40,6 +41,7 @@ > import org.eclipse.cdt.dsf.service.AbstractDsfService; > import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; > import org.eclipse.cdt.dsf.service.DsfSession; >+import org.eclipse.core.runtime.CoreException; > import org.eclipse.core.runtime.IStatus; > import org.eclipse.core.runtime.Status; > import org.osgi.framework.BundleContext; >@@ -305,6 +307,7 @@ > private ICommandControlService fCommandControl; > private CommandCache fContainerCommandCache; > private CommandFactory fCommandFactory; >+ private IGDBBackend fGdbBackend; > > private static final String FAKE_THREAD_ID = "0"; //$NON-NLS-1$ > // The unique id should be an empty string so that the views know not to display the fake id >@@ -350,6 +353,8 @@ > > fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory(); > >+ fGdbBackend = getServicesTracker().getService(IGDBBackend.class); >+ > // This cache stores the result of a command when received; also, this cache > // is manipulated when receiving events. Currently, events are received after > // three scheduling of the executor, while command results after only one. This >@@ -638,12 +643,19 @@ > */ > @DsfServiceEventHandler > public void eventDispatched(ISuspendedDMEvent e) { >- if (e instanceof IContainerSuspendedDMEvent) { >- // This will happen in all-stop mode >- fContainerCommandCache.setContextAvailable(e.getDMContext(), true); >- } else { >- // This will happen in non-stop mode >- } >+ assert e instanceof IContainerSuspendedDMEvent : "Unexpected type of suspended event: " + e.getClass().toString(); //$NON-NLS-1$ >+ >+ fContainerCommandCache.setContextAvailable(e.getDMContext(), true); >+ >+ // If user is debugging a gdb target that doesn't send thread >+ // creation events, make sure we don't use cached thread >+ // information. Reset the cache after every suspend. See bugzilla >+ // 280631 >+ try { >+ if (fGdbBackend.getUpdateThreadListOnSuspend()) { >+ fContainerCommandCache.reset(e.getDMContext()); >+ } >+ } catch (CoreException exc) {} > } > > /** >#P org.eclipse.cdt.dsf.gdb.ui >Index: src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/GdbDebuggerPage.java >=================================================================== >RCS file: /cvsroot/tools/org.eclipse.cdt/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/GdbDebuggerPage.java,v >retrieving revision 1.4 >diff -u -r1.4 GdbDebuggerPage.java >--- src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/GdbDebuggerPage.java 21 Apr 2010 17:43:55 -0000 1.4 >+++ src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/GdbDebuggerPage.java 22 Apr 2010 16:06:08 -0000 >@@ -17,6 +17,7 @@ > > import org.eclipse.cdt.debug.ui.AbstractCDebuggerPage; > import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants; >+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin; > import org.eclipse.cdt.utils.ui.controls.ControlFactory; > import org.eclipse.core.runtime.CoreException; > import org.eclipse.debug.core.ILaunchConfiguration; >@@ -36,6 +37,7 @@ > import org.eclipse.swt.widgets.TabFolder; > import org.eclipse.swt.widgets.TabItem; > import org.eclipse.swt.widgets.Text; >+import org.eclipse.ui.PlatformUI; > > /** > * The dynamic tab for gdb-based debugger implementations. >@@ -47,6 +49,7 @@ > protected Text fGDBInitText; > protected Button fNonStopCheckBox; > protected Button fReverseCheckBox; >+ protected Button fUpdateThreadlistOnSuspend; > > private IMILaunchConfigurationComponent fSolibBlock; > private boolean fIsInitializing = false; >@@ -71,6 +74,8 @@ > IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT); > configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_REVERSE, > IGDBLaunchConfigurationConstants.DEBUGGER_REVERSE_DEFAULT); >+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_UPDATE_THREADLIST_ON_SUSPEND, >+ IGDBLaunchConfigurationConstants.DEBUGGER_UPDATE_THREADLIST_ON_SUSPEND_DEFAULT); > > if (fSolibBlock != null) > fSolibBlock.setDefaults(configuration); >@@ -90,46 +95,45 @@ > return valid; > } > >- public void initializeFrom(ILaunchConfiguration configuration) { >- setInitializing(true); >- String gdbCommand = IGDBLaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT; >- String gdbInit = IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT; >- boolean nonStopMode = IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT; >- boolean reverseEnabled = IGDBLaunchConfigurationConstants.DEBUGGER_REVERSE_DEFAULT; >- >- try { >- gdbCommand = configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUG_NAME, >- IGDBLaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT); >- } >- catch(CoreException e) { >- } >- try { >- gdbInit = configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_GDB_INIT, >- IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT); >+ /** utility method to cut down on clutter */ >+ private String getStringAttr(ILaunchConfiguration config, String attributeName, String defaultValue) { >+ try { >+ return config.getAttribute(attributeName, defaultValue); > } >- catch(CoreException e) { >+ catch (CoreException exc) { >+ return defaultValue; > } >- >- try { >- nonStopMode = configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP, >- IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT); >+ } >+ /** utility method to cut down on clutter */ >+ private boolean getBooleanAttr(ILaunchConfiguration config, String attributeName, boolean defaultValue) { >+ try { >+ return config.getAttribute(attributeName, defaultValue); > } >- catch(CoreException e) { >+ catch (CoreException exc) { >+ return defaultValue; > } >+ } >+ >+ public void initializeFrom(ILaunchConfiguration configuration) { >+ setInitializing(true); >+ String gdbCommand = getStringAttr(configuration, IGDBLaunchConfigurationConstants.ATTR_DEBUG_NAME, >+ IGDBLaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT); >+ String gdbInit = getStringAttr(configuration, IGDBLaunchConfigurationConstants.ATTR_GDB_INIT, >+ IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT); >+ boolean nonStopMode = getBooleanAttr(configuration, IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP, >+ IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT); >+ boolean reverseEnabled = getBooleanAttr(configuration, IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_REVERSE, >+ IGDBLaunchConfigurationConstants.DEBUGGER_REVERSE_DEFAULT); >+ boolean updateThreadsOnSuspend = getBooleanAttr(configuration, IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_UPDATE_THREADLIST_ON_SUSPEND, >+ IGDBLaunchConfigurationConstants.DEBUGGER_UPDATE_THREADLIST_ON_SUSPEND_DEFAULT); > >- try { >- reverseEnabled = configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_REVERSE, >- IGDBLaunchConfigurationConstants.DEBUGGER_REVERSE_DEFAULT); >- } >- catch(CoreException e) { >- } >- > if (fSolibBlock != null) > fSolibBlock.initializeFrom(configuration); > fGDBCommandText.setText(gdbCommand); > fGDBInitText.setText(gdbInit); > fNonStopCheckBox.setSelection(nonStopMode); > fReverseCheckBox.setSelection(reverseEnabled); >+ fUpdateThreadlistOnSuspend.setSelection(updateThreadsOnSuspend); > > setInitializing(false); > } >@@ -143,6 +147,8 @@ > fNonStopCheckBox.getSelection()); > configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_REVERSE, > fReverseCheckBox.getSelection()); >+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_UPDATE_THREADLIST_ON_SUSPEND, >+ fUpdateThreadlistOnSuspend.getSelection()); > > if (fSolibBlock != null) > fSolibBlock.performApply(configuration); >@@ -284,32 +290,15 @@ > > // TODO: Ideally, this field should be disabled if the back-end doesn't support non-stop debugging > // TODO: Find a way to determine if non-stop is supported (i.e. find the GDB version) then grey out the check box if necessary >- fNonStopCheckBox = ControlFactory.createCheckBox(subComp, LaunchUIMessages.getString("GDBDebuggerPage.nonstop_mode")); //$NON-NLS-1$ >- fNonStopCheckBox.addSelectionListener( new SelectionAdapter() { >- @Override >- public void widgetSelected(SelectionEvent e) { >- updateLaunchConfigurationDialog(); >- } >- }); >+ fNonStopCheckBox = addCheckbox(subComp, LaunchUIMessages.getString("GDBDebuggerPage.nonstop_mode")); //$NON-NLS-1$ > > // TODO: Ideally, this field should be disabled if the back-end doesn't support reverse debugging > // TODO: Find a way to determine if reverse is supported (i.e. find the GDB version) then grey out the check box if necessary >- fReverseCheckBox = ControlFactory.createCheckBox(subComp, LaunchUIMessages.getString("GDBDebuggerPage.reverse_Debugging")); //$NON-NLS-1$ >- fReverseCheckBox.addSelectionListener( new SelectionAdapter() { >- @Override >- public void widgetSelected(SelectionEvent e) { >- updateLaunchConfigurationDialog(); >- } >- }); >+ fReverseCheckBox = addCheckbox(subComp, LaunchUIMessages.getString("GDBDebuggerPage.reverse_Debugging")); //$NON-NLS-1$ > >- >- // fit options one per line >- gd = new GridData(); >- gd.horizontalSpan = 3; >- fNonStopCheckBox.setLayoutData(gd); >- gd = new GridData(); >- gd.horizontalSpan = 3; >- fReverseCheckBox.setLayoutData(gd); >+ fUpdateThreadlistOnSuspend = addCheckbox(subComp, LaunchUIMessages.getString("GDBDebuggerPage.update_thread_list_on_suspend")); //$NON-NLS-1$ >+ // This checkbox needs an explanation. Attach context help to it. >+ PlatformUI.getWorkbench().getHelpSystem().setHelp(fUpdateThreadlistOnSuspend, GdbUIPlugin.PLUGIN_ID + ".update_threadlist_button_context"); //$NON-NLS-1$ > } > > public void createSolibTab(TabFolder tabFolder) { >@@ -323,6 +312,22 @@ > ((Observable)fSolibBlock).addObserver(this); > } > >+ /** Used to add a checkbox to the tab. Each checkbox has its own line. */ >+ private Button addCheckbox(Composite parent, String label) { >+ Button button = ControlFactory.createCheckBox(parent, label); >+ button .addSelectionListener(new SelectionAdapter() { >+ @Override >+ public void widgetSelected(SelectionEvent e) { >+ updateLaunchConfigurationDialog(); >+ } >+ }); >+ GridData gd = new GridData(); >+ gd.horizontalSpan = 3; >+ button.setLayoutData(gd); >+ >+ return button; >+ } >+ > /* > * (non-Javadoc) > * >Index: src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/LaunchUIMessages.properties >=================================================================== >RCS file: /cvsroot/tools/org.eclipse.cdt/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/LaunchUIMessages.properties,v >retrieving revision 1.4 >diff -u -r1.4 LaunchUIMessages.properties >--- src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/LaunchUIMessages.properties 21 Apr 2010 17:43:55 -0000 1.4 >+++ src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/LaunchUIMessages.properties 22 Apr 2010 16:06:08 -0000 >@@ -23,6 +23,7 @@ > GDBDebuggerPage.shared_libraries=Shared Libraries > GDBDebuggerPage.nonstop_mode=Non-stop mode (Note: Requires non-stop GDB) > GDBDebuggerPage.reverse_Debugging=Enable Reverse Debugging at startup (Note: Requires Reverse GDB) >+GDBDebuggerPage.update_thread_list_on_suspend=Force thread list update on suspend > StandardGDBDebuggerPage.0=Debugger executable must be specified. > StandardGDBDebuggerPage.1=GDB Debugger Options > StandardGDBDebuggerPage.2=Main
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
john.cortell
:
iplog-
john.cortell
:
review?
Actions:
View
|
Diff
Attachments on
bug 280631
:
158286
|
165669
|
165681
|
165683
| 165785 |
165918