Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 298883 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunchDelegate.java (-7 / +7 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2008, 2009  QNX Software Systems and others.
2
 * Copyright (c) 2010 QNX Software Systems and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 9-14 Link Here
9
 * QNX Software Systems   - Initial API and implementation
9
 * QNX Software Systems   - Initial API and implementation
10
 * Windriver and Ericsson - Updated for DSF
10
 * Windriver and Ericsson - Updated for DSF
11
 * IBM Corporation 
11
 * IBM Corporation 
12
 * Ericsson               - Added support for Mac OS
12
 *******************************************************************************/
13
 *******************************************************************************/
13
package org.eclipse.cdt.dsf.gdb.launching; 
14
package org.eclipse.cdt.dsf.gdb.launching; 
14
15
Lines 382-387 Link Here
382
	}
383
	}
383
	
384
	
384
	private boolean isNonStopSupported(String version) {
385
	private boolean isNonStopSupported(String version) {
386
		if (version.startsWith(LaunchUtils.MACOS_GDB_PREFIX)) {
387
			// Mac OS's GDB does not support Non-Stop
388
			return false;
389
		}
390
		
385
		if (NON_STOP_FIRST_VERSION.compareTo(version) <= 0) {
391
		if (NON_STOP_FIRST_VERSION.compareTo(version) <= 0) {
386
			return true;
392
			return true;
387
		}
393
		}
Lines 395-406 Link Here
395
			return new GdbDebugServicesFactoryNS(version);
401
			return new GdbDebugServicesFactoryNS(version);
396
		}
402
		}
397
403
398
		if (version.startsWith("6.6") ||  //$NON-NLS-1$
399
			version.startsWith("6.7") ||  //$NON-NLS-1$
400
			version.startsWith("6.8")) {  //$NON-NLS-1$
401
			return new GdbDebugServicesFactory(version);
402
		}
403
404
		return new GdbDebugServicesFactory(version);
404
		return new GdbDebugServicesFactory(version);
405
	}
405
	}
406
}
406
}
(-)src/org/eclipse/cdt/dsf/gdb/launching/LaunchUtils.java (-2 / +29 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2008 Ericsson and others.
2
 * Copyright (c) 2010 Ericsson and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 7-12 Link Here
7
 *
7
 *
8
 * Contributors:
8
 * Contributors:
9
 * Ericsson   - Initial API and implementation
9
 * Ericsson   - Initial API and implementation
10
 * Ericsson   - Added support for Mac OS
10
 *******************************************************************************/
11
 *******************************************************************************/
11
package org.eclipse.cdt.dsf.gdb.launching;
12
package org.eclipse.cdt.dsf.gdb.launching;
12
13
Lines 43-48 Link Here
43
44
44
public class LaunchUtils {
45
public class LaunchUtils {
45
46
47
	/**
48
	 * A prefix that we use to indicate that a GDB version is for MAC OS
49
	 * @since 2.1
50
	 */
51
	public static final String MACOS_GDB_PREFIX = "APPLE"; //$NON-NLS-1$
52
	
46
   	/**
53
   	/**
47
	 * Verify the following things about the project:
54
	 * Verify the following things about the project:
48
	 * - is a valid project name given
55
	 * - is a valid project name given
Lines 212-218 Link Here
212
     */
219
     */
213
	public static String getGDBVersionFromText(String versionOutput) {
220
	public static String getGDBVersionFromText(String versionOutput) {
214
        String version = "";//$NON-NLS-1$
221
        String version = "";//$NON-NLS-1$
215
        
222
223
        // First look for the case of Apple's GDB, since the version must be handled differently
224
        // The format is:
225
        // GNU gdb 6.3.50-20050815 (Apple version gdb-696) (Sat Oct 20 18:20:28 GMT 2007)
226
        // GNU gdb 6.3.50-20050815 (Apple version gdb-966) (Tue Mar 10 02:43:13 UTC 2009)
227
        // GNU gdb 6.3.50-20050815 (Apple version gdb-1346) (Fri Sep 18 20:40:51 UTC 2009)
228
        // Also, it seems the version that changes is the "Apple version" so that is the
229
        // one we will extract.  The normal GDB version is fixed and won't help us.
230
        if (versionOutput.toLowerCase().indexOf("apple") != -1) {  //$NON-NLS-1$
231
        	// Add a prefix to indicate we are dealing with an Apple GDB
232
        	version = MACOS_GDB_PREFIX;
233
    		Pattern pattern = Pattern.compile(" \\(Apple version gdb-(\\d*)\\)",  Pattern.MULTILINE); //$NON-NLS-1$
234
235
    		Matcher matcher = pattern.matcher(versionOutput);
236
    		if (matcher.find()) {
237
    			version += matcher.group(1);
238
    		}
239
    		
240
    		return version;
241
        }
242
        		
216
		// These are the GDB version patterns I have seen up to now
243
		// These are the GDB version patterns I have seen up to now
217
		// The pattern works for all of them extracting the version of 6.8.50.20080730
244
		// The pattern works for all of them extracting the version of 6.8.50.20080730
218
		// GNU gdb 6.8.50.20080730
245
		// GNU gdb 6.8.50.20080730
(-)src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java (-5 / +72 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2008 Ericsson and others.
2
 * Copyright (c) 2010 Ericsson and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 7-13 Link Here
7
 * 
7
 * 
8
 * Contributors:
8
 * Contributors:
9
 *     Ericsson - initial API and implementation
9
 *     Ericsson - initial API and implementation
10
 *     Nokia - create and use backend service. 
10
 *     Nokia    - create and use backend service.
11
 *     Ericsson - Added support for Mac OS
11
 *******************************************************************************/
12
 *******************************************************************************/
12
package org.eclipse.cdt.dsf.gdb.service;
13
package org.eclipse.cdt.dsf.gdb.service;
13
14
Lines 24-37 Link Here
24
import org.eclipse.cdt.dsf.debug.service.ISourceLookup;
25
import org.eclipse.cdt.dsf.debug.service.ISourceLookup;
25
import org.eclipse.cdt.dsf.debug.service.IStack;
26
import org.eclipse.cdt.dsf.debug.service.IStack;
26
import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
27
import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
28
import org.eclipse.cdt.dsf.gdb.launching.LaunchUtils;
27
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl;
29
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl;
28
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_0;
30
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_0;
31
import org.eclipse.cdt.dsf.gdb.service.macos.MacOSGDBExpressions;
29
import org.eclipse.cdt.dsf.mi.service.CSourceLookup;
32
import org.eclipse.cdt.dsf.mi.service.CSourceLookup;
30
import org.eclipse.cdt.dsf.mi.service.MIExpressions;
31
import org.eclipse.cdt.dsf.mi.service.IMIBackend;
33
import org.eclipse.cdt.dsf.mi.service.IMIBackend;
32
import org.eclipse.cdt.dsf.mi.service.MIBreakpoints;
34
import org.eclipse.cdt.dsf.mi.service.MIBreakpoints;
33
import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager;
35
import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager;
34
import org.eclipse.cdt.dsf.mi.service.MIDisassembly;
36
import org.eclipse.cdt.dsf.mi.service.MIDisassembly;
37
import org.eclipse.cdt.dsf.mi.service.MIExpressions;
35
import org.eclipse.cdt.dsf.mi.service.MIMemory;
38
import org.eclipse.cdt.dsf.mi.service.MIMemory;
36
import org.eclipse.cdt.dsf.mi.service.MIModules;
39
import org.eclipse.cdt.dsf.mi.service.MIModules;
37
import org.eclipse.cdt.dsf.mi.service.MIRegisters;
40
import org.eclipse.cdt.dsf.mi.service.MIRegisters;
Lines 44-53 Link Here
44
	// This should eventually be "7.0" once GDB 7.0 is released
47
	// This should eventually be "7.0" once GDB 7.0 is released
45
	private static final String GDB_7_0_VERSION = "6.8.50.20090218"; //$NON-NLS-1$
48
	private static final String GDB_7_0_VERSION = "6.8.50.20090218"; //$NON-NLS-1$
46
	
49
	
50
	// Contains the GDB version string such as
51
	// 7.0
52
	// 6.8.50.20090218
53
	// For MacOS, it contains the Apple version number, such as
54
	// 969
55
	// 1465
47
	private final String fVersion;
56
	private final String fVersion;
48
	
57
	
58
	// Indicate if we are dealing with a Mac OS GDB
59
	private boolean fIsMacOSGdb = false;
60
	
49
	public GdbDebugServicesFactory(String version) {
61
	public GdbDebugServicesFactory(String version) {
50
		fVersion = version;
62
		if (version.startsWith(LaunchUtils.MACOS_GDB_PREFIX)) {
63
			fIsMacOSGdb = true;
64
			fVersion = version.substring(LaunchUtils.MACOS_GDB_PREFIX.length());
65
		} else {
66
			fVersion = version;
67
		}
51
	}
68
	}
52
	
69
	
53
	public String getVersion() { return fVersion; }
70
	public String getVersion() { return fVersion; }
Lines 73-88 Link Here
73
			}
90
			}
74
		}
91
		}
75
92
76
77
        return super.createService(clazz, session);
93
        return super.createService(clazz, session);
78
	}
94
	}
79
95
80
	protected MIBreakpointsManager createBreakpointManagerService(DsfSession session) {
96
	protected MIBreakpointsManager createBreakpointManagerService(DsfSession session) {
97
		if (fIsMacOSGdb) {
98
			return new MIBreakpointsManager(session, CDebugCorePlugin.PLUGIN_ID);
99
		}
81
		return new MIBreakpointsManager(session, CDebugCorePlugin.PLUGIN_ID);
100
		return new MIBreakpointsManager(session, CDebugCorePlugin.PLUGIN_ID);
82
	}
101
	}
83
102
84
	@Override
103
	@Override
85
	protected IBreakpoints createBreakpointService(DsfSession session) {
104
	protected IBreakpoints createBreakpointService(DsfSession session) {
105
		if (fIsMacOSGdb) {
106
			return new MIBreakpoints(session);
107
		}
108
		
86
		if (GDB_7_0_VERSION.compareTo(fVersion) <= 0) {
109
		if (GDB_7_0_VERSION.compareTo(fVersion) <= 0) {
87
			return new GDBBreakpoints_7_0(session);
110
			return new GDBBreakpoints_7_0(session);
88
		}
111
		}
Lines 90-95 Link Here
90
	}
113
	}
91
	
114
	
92
	protected ICommandControl createCommandControl(DsfSession session, ILaunchConfiguration config) {
115
	protected ICommandControl createCommandControl(DsfSession session, ILaunchConfiguration config) {
116
		if (fIsMacOSGdb) {
117
			return new GDBControl(session, config);
118
		}
119
		
93
		if (GDB_7_0_VERSION.compareTo(fVersion) <= 0) {
120
		if (GDB_7_0_VERSION.compareTo(fVersion) <= 0) {
94
			return new GDBControl_7_0(session, config);
121
			return new GDBControl_7_0(session, config);
95
		}
122
		}
Lines 97-117 Link Here
97
	}
124
	}
98
125
99
	protected IMIBackend createBackendGDBService(DsfSession session, ILaunchConfiguration lc) {
126
	protected IMIBackend createBackendGDBService(DsfSession session, ILaunchConfiguration lc) {
127
		if (fIsMacOSGdb) {
128
			return new GDBBackend(session, lc);
129
		}
130
		
100
		return new GDBBackend(session, lc);
131
		return new GDBBackend(session, lc);
101
	}
132
	}
102
133
103
	@Override
134
	@Override
104
	protected IDisassembly createDisassemblyService(DsfSession session) {
135
	protected IDisassembly createDisassemblyService(DsfSession session) {
136
		if (fIsMacOSGdb) {
137
			return new MIDisassembly(session);
138
		}
139
		
105
		return new MIDisassembly(session);
140
		return new MIDisassembly(session);
106
	}
141
	}
107
	
142
	
108
	@Override
143
	@Override
109
	protected IExpressions createExpressionService(DsfSession session) {
144
	protected IExpressions createExpressionService(DsfSession session) {
145
		if (fIsMacOSGdb) {
146
			return new MacOSGDBExpressions(session);
147
		}
148
		
110
		return new MIExpressions(session);
149
		return new MIExpressions(session);
111
	}
150
	}
112
151
113
	@Override
152
	@Override
114
	protected IMemory createMemoryService(DsfSession session) {
153
	protected IMemory createMemoryService(DsfSession session) {
154
		if (fIsMacOSGdb) {
155
			return new MIMemory(session);
156
		}
157
		
115
		if (GDB_7_0_VERSION.compareTo(fVersion) <= 0) {
158
		if (GDB_7_0_VERSION.compareTo(fVersion) <= 0) {
116
			return new GDBMemory_7_0(session);
159
			return new GDBMemory_7_0(session);
117
		}
160
		}
Lines 121-131 Link Here
121
164
122
	@Override
165
	@Override
123
	protected IModules createModulesService(DsfSession session) {
166
	protected IModules createModulesService(DsfSession session) {
167
		if (fIsMacOSGdb) {
168
			return new MIModules(session);
169
		}
170
		
124
		return new MIModules(session);
171
		return new MIModules(session);
125
	}
172
	}
126
		
173
		
127
	@Override
174
	@Override
128
	protected IProcesses createProcessesService(DsfSession session) {
175
	protected IProcesses createProcessesService(DsfSession session) {
176
		if (fIsMacOSGdb) {
177
			return new GDBProcesses(session);
178
		}
179
		
129
		if (GDB_7_0_VERSION.compareTo(fVersion) <= 0) {
180
		if (GDB_7_0_VERSION.compareTo(fVersion) <= 0) {
130
			return new GDBProcesses_7_0(session);
181
			return new GDBProcesses_7_0(session);
131
		}
182
		}
Lines 134-144 Link Here
134
185
135
	@Override
186
	@Override
136
	protected IRegisters createRegistersService(DsfSession session) {
187
	protected IRegisters createRegistersService(DsfSession session) {
188
		if (fIsMacOSGdb) {
189
			return new MIRegisters(session);
190
		}
191
		
137
		return new MIRegisters(session);
192
		return new MIRegisters(session);
138
	}
193
	}
139
194
140
	@Override
195
	@Override
141
	protected IRunControl createRunControlService(DsfSession session) {
196
	protected IRunControl createRunControlService(DsfSession session) {
197
		if (fIsMacOSGdb) {
198
			return new GDBRunControl(session);
199
		}
200
		
142
		if (GDB_7_0_VERSION.compareTo(fVersion) <= 0) {
201
		if (GDB_7_0_VERSION.compareTo(fVersion) <= 0) {
143
			return new GDBRunControl_7_0(session);
202
			return new GDBRunControl_7_0(session);
144
		}
203
		}
Lines 147-157 Link Here
147
206
148
	@Override
207
	@Override
149
	protected ISourceLookup createSourceLookupService(DsfSession session) {
208
	protected ISourceLookup createSourceLookupService(DsfSession session) {
209
		if (fIsMacOSGdb) {
210
			return new CSourceLookup(session);
211
		}
212
		
150
		return new CSourceLookup(session);
213
		return new CSourceLookup(session);
151
	}
214
	}
152
	
215
	
153
	@Override
216
	@Override
154
	protected IStack createStackService(DsfSession session) {
217
	protected IStack createStackService(DsfSession session) {
218
		if (fIsMacOSGdb) {
219
			return new MIStack(session);
220
		}
221
		
155
		return new MIStack(session);
222
		return new MIStack(session);
156
	}
223
	}
157
}
224
}
(-)src/org/eclipse/cdt/dsf/gdb/service/macos/MacOSGDBExpressions.java (+38 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 Wind River Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     Wind River Systems - initial API and implementation
10
 *     Ericsson 		  - Modified for handling of multiple execution contexts
11
 *     Ericsson           - Created the MacOS version
12
 *******************************************************************************/
13
package org.eclipse.cdt.dsf.gdb.service.macos;
14
15
import org.eclipse.cdt.dsf.mi.service.MIExpressions;
16
import org.eclipse.cdt.dsf.mi.service.MIVariableManager;
17
import org.eclipse.cdt.dsf.service.DsfSession;
18
19
/**
20
 * This class implements a debugger expression evaluator as a DSF service. The
21
 * primary interface that clients of this class should use is IExpressions.
22
 * 
23
 * This class used to be name ExpressionService in the 1.1 release.
24
 * 
25
 * @since 2.1
26
 */
27
public class MacOSGDBExpressions extends MIExpressions {
28
29
    public MacOSGDBExpressions(DsfSession session) {
30
        super(session);
31
    }
32
33
    
34
    @Override
35
    protected MIVariableManager createMIVariableManager() {
36
        return new MacOSGDBVariableManager(getSession(), getServicesTracker());
37
    }
38
}
(-)src/org/eclipse/cdt/dsf/gdb/service/macos/MacOSGDBVariableManager.java (+236 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 Monta Vista and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     Monta Vista - initial API and implementation
10
 *     Ericsson    - Modified for handling of multiple execution contexts
11
 *     Ericsson    - Major updates for GDB/MI implementation
12
 *     Ericsson    - Major re-factoring to deal with children
13
 *     Ericsson           - Created the MacOS version
14
 *******************************************************************************/
15
package org.eclipse.cdt.dsf.gdb.service.macos;
16
17
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
18
import org.eclipse.cdt.dsf.mi.service.MIVariableManager;
19
import org.eclipse.cdt.dsf.mi.service.command.commands.macos.MacOSMIVarUpdate;
20
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarChange;
21
import org.eclipse.cdt.dsf.mi.service.command.output.macos.MacOSMIVarUpdateInfo;
22
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
23
import org.eclipse.cdt.dsf.service.DsfSession;
24
25
/**
26
 * Manages a list of variable objects as created through GDB/MI commands.
27
 * 
28
 * This class is passed expression-meta-commands which have their own cache.
29
 * Therefore, we don't use the standard MICommandCache in this class.
30
 * In fact, we can't even use it, because many variableObject MI commands,
31
 * should not be cached as they alter the state of the back-end.
32
 * 
33
 * Design details:
34
 * ==============
35
 * 
36
 * GDB variable object information
37
 * -------------------------------
38
 * o Variable objects are recursively hierarchical, where children can be created through 
39
 *   the parent.
40
 * o A varObject created with -var-create is a ROOT
41
 * o A varObject created with -var-list-children, is not a root
42
 * o Only varObject with no children or varObjects that are pointers can change values 
43
 *   and therefore 
44
 *   those objects can be used with -var-assign
45
 * o After a program stops, a varObject must be 'updated' before used 
46
 * o Only root varObject can be updated with -var-update, which will trigger all
47
 *   of the root's descendants to be updated.
48
 * o Once updated, a varObject need not be updated until the program resumes again;
49
 *   this is true even after -var-assign is used (because it does an implicit -var-update)
50
 * o -var-update will return the list of all modifiable descendants of the udpated root which
51
 *   have changed
52
 * o -var-update will indicate if a root is out-of-scope (which implies that all
53
 *   its descendants are out-of-scope)
54
 * o if a varObject is out-of-scope, another varObject may be valid for the same
55
 *   expression as the out-of-scope varObject
56
 * o deleting a varObject will delete all its descendants, therefore, it is only
57
 *   necessary to delete roots
58
 * 
59
 * 
60
 * Class details
61
 * -------------
62
 * - We have an MIVariableObject class which represents a variable object in GDB
63
 * 
64
 * - MIVariableObject includes a buffered value for each allowed format.
65
 * 
66
 * - We have an MIRootVariableObject class inheriting from MIVariableObject to describe
67
 *   root varObjects created with -var-create.  Objects created with -var-list-children
68
 *   are MIVariableObjects only.  The root class will keep track of if the root object 
69
 *   needs to be updated, if the root object is out-of-scope, and of a list of all 
70
 *   modifiable descendants of this root.  The list of modifiable descendants is 
71
 *   accessed using the gdb-given name to allow quick updates from the -var-update 
72
 *   result (see below.)
73
 * 
74
 * - we do not use -var-list-children for arrays, but create them manually
75
 *  
76
 * - when the program stops, we should mark all roots as needing to be updated. 
77
 * To achieve this efficiently, we have a dedicated list of roots that are updated.
78
 * When the program stops, we go through this list, remove each element and mark it
79
 * as needing to be updated.
80
 * 
81
 * - when a varObject is accessed, if its root must be updated, the var-update
82
 * command shall be used.  The result of that command will indicate all
83
 * modifiable descendants that have changed.  We also use --all-values with -var-update
84
 * to get the new value (in the current format) for each modified descendant.  Using the list of modifiable
85
 * descendants of the root, we can quickly update the changed ones to invalidate their buffered
86
 * values and store the new current format value.
87
 * 
88
 * - all values of non-modifiable varObjects (except arrays) will be set to {...}
89
 * without going to the back-end
90
 * 
91
 * - requesting the value of an array varObject will trigger the creation of a new
92
 * varObject for the array's address.  Note that we must still use a variable
93
 * object and not the command -data-evaluate-expression, because we still need to get
94
 * the array address in multiple formats.
95
 * 
96
 * - we keep an LRU (Least Recently Used) structure of all variable objects.  This LRU
97
 * will be bounded to a maximum allowed number of variable objects.  Whenever we get an
98
 * object from the LRU cleanup will be done if the maximum size has been reached.
99
 * The LRU will not delete a parent varObject until all its children are deleted; this is
100
 * achieved by touching each of the parents of an object whenever that object is put or get
101
 *
102
 * - It may happen that when accessing a varObject we find its root to be
103
 * out-of-scope.  The expression for which we are trying to access a varObject
104
 * could still be valid, and therefore we should try to create a new varObject for
105
 * that expression.  This can happen for example if two methods use the same name
106
 * for a variable. In the case when we find that a varObject is out-of-scope (when
107
 * its root is out-of-scope) the following should be done:
108
 *  - replace the varObject in the LRU with a newly created one in GDB
109
 *  - if the old object was a root, delete it in GDB.
110
 *  
111
 * - In GDB, -var-update will only report a change if -var-evaluate-expression has
112
 *   changed -- in the current format--.  This means that situations like
113
 *    double z = 1.2;
114
 *    z = 1.4;
115
 *   Will not report a change if the format is anything else than natural.
116
 *   This is because 1.2 and 1.4 are both printed as 1, 0x1, etc
117
 *   Since we cache the values of every format, we must know if the value has
118
 *   change in -any- format, not just the current one.
119
 *   To solve this, we always keep the display format of variable objects (and their
120
 *   children) to the natural format; we believe that if the value changes in any
121
 *   format, it guarantees that it will change in the natural format.
122
 *   The simplest way to do this is that whenever we change the format
123
 *   of a variable object, we immediately set it back to natural with a second
124
 *   var-set-format command.
125
 *   Note that versions of GDB after 6.7 will allows to issue -var-evaluate-expression
126
 *   with a specified format, therefore allowing us to never use -var-set-format, and
127
 *   consequently, to easily keep the display format of all variable objects to natural.
128
 *   
129
 *   @since 2.1
130
 */
131
public class MacOSGDBVariableManager extends MIVariableManager {
132
133
    public MacOSGDBVariableManager(DsfSession session, DsfServicesTracker tracker) {
134
        super(session, tracker);
135
    }
136
137
	private class MacOSGDBRootVariableObject extends MIRootVariableObject {
138
139
		public MacOSGDBRootVariableObject(VariableObjectId id) {
140
			super(id);
141
		}
142
143
		@Override
144
		public void update(final DataRequestMonitor<Boolean> rm) {
145
146
			if (isOutOfScope()) {
147
		    	rm.setData(false);
148
				rm.done();
149
			} else if (currentState != STATE_READY) {
150
				// Object is not fully created or is being updated
151
				// so add RequestMonitor to pending queue
152
				updatesPending.add(rm);
153
			} else if (isOutOfDate() == false) {
154
				rm.setData(false);
155
				rm.done();
156
			} else {
157
				// Object needs to be updated in the back-end
158
				currentState = STATE_UPDATING;
159
160
				// In GDB, var-update will only report a change if -var-evaluate-expression has
161
				// changed -- in the current format--.  This means that situations like
162
				// double z = 1.2;
163
				// z = 1.4;
164
				// Will not report a change if the format is anything else than natural.
165
				// This is because 1.2 and 1.4 are both printed as 1, 0x1, etc
166
				// Since we cache the values of every format, we must know if -any- format has
167
				// changed, not just the current one.
168
				// To solve this, we always do an update in the natural format; I am not aware
169
				// of any case where the natural format would stay the same, but another format
170
				// would change.  However, since a var-update update all children as well,
171
			    // we must make sure these children are also in the natural format
172
				// The simplest way to do this is that whenever we change the format
173
				// of a variable object, we immediately set it back to natural with a second
174
				// var-set-format command.  This is done in the getValue() method
175
				getCommandControl().queueCommand(
176
						new MacOSMIVarUpdate(getRootToUpdate().getControlDMContext(), getGdbName()),
177
						new DataRequestMonitor<MacOSMIVarUpdateInfo>(getSession().getExecutor(), rm) {
178
							@Override
179
							protected void handleCompleted() {
180
								currentState = STATE_READY;
181
								
182
								if (isSuccess()) {
183
									markAsOutOfDate(false);
184
185
									MIVarChange[] changes = getData().getMIVarChanges();
186
									if (changes.length > 0 && changes[0].isInScope() == false) {
187
										// Object is out-of-scope
188
										outOfScope = true;
189
										
190
										// We can delete this root in GDB right away.  This is safe, even
191
									 	// if the root has children, because they are also out-of-scope.
192
										// We -must- also remove this entry from our LRU.  If we don't
193
										// we can end-up with a race condition that create this object
194
										// twice, or have an infinite loop while never re-creating the object.
195
										// The can happen if we update a child first then we request 
196
										// the root later,
197
										removeVariable(getInternalId());
198
199
										rm.setData(true);
200
										rm.done();
201
									} else {
202
										// The root object is now up-to-date, we must parse the changes, if any.
203
										processChanges(changes);
204
205
										// We only mark this root as updated in our list if it is in-scope.
206
										// For out-of-scope object, we don't ever need to re-update them so
207
										// we don't need to add them to this list.
208
										rootVariableUpdated(MacOSGDBRootVariableObject.this);
209
210
										rm.setData(false);
211
										rm.done();
212
									}
213
214
									while (updatesPending.size() > 0) {
215
										DataRequestMonitor<Boolean> pendingRm = updatesPending.poll();
216
										pendingRm.setData(false);
217
										pendingRm.done();
218
									}
219
								} else {
220
									// We were not able to update for some reason
221
									rm.setData(false);
222
									rm.done();
223
224
									while (updatesPending.size() > 0) {
225
										DataRequestMonitor<Boolean> pendingRm = updatesPending.poll();
226
										pendingRm.setStatus(getStatus());
227
										pendingRm.done();
228
									}
229
								}
230
							}
231
						});
232
		    }
233
		}
234
	}
235
	
236
}
(-)src/org/eclipse/cdt/dsf/mi/service/MIExpressions.java (+10 lines)
Lines 464-469 Link Here
464
	}
464
	}
465
465
466
	/**
466
	/**
467
	 * Creates the MI variable manager to be used by this expression service.
468
	 * Overriding classes may override to provide a custom services tracker. 
469
	 * 
470
	 * @since 2.1
471
	 */
472
	protected MIVariableManager createMIVariableManager() {
473
	    return new MIVariableManager(getSession(), getServicesTracker());
474
	}
475
	
476
	/**
467
	 * This method shuts down this service. It unregisters the service, stops
477
	 * This method shuts down this service. It unregisters the service, stops
468
	 * receiving service events, and calls the superclass shutdown() method to
478
	 * receiving service events, and calls the superclass shutdown() method to
469
	 * finish the shutdown process.
479
	 * finish the shutdown process.
(-)src/org/eclipse/cdt/dsf/mi/service/MIVariableManager.java (-11 / +65 lines)
Lines 697-703 Link Here
697
	        							}
697
	        							}
698
698
699
	        							if (childVar == null) {
699
	        							if (childVar == null) {
700
	        								childVar = new MIVariableObject(childId, MIVariableObject.this);
700
	        								childVar = createChildVariable(childId, MIVariableObject.this);
701
	        								childVar.setGdbName(child.getVarName());
701
	        								childVar.setGdbName(child.getVarName());
702
	        								childVar.setExpressionData(
702
	        								childVar.setExpressionData(
703
	        										childFullExpression,
703
	        										childFullExpression,
Lines 770-775 Link Here
770
		}
770
		}
771
		
771
		
772
		/**
772
		/**
773
         * @since 2.1
774
         */
775
		protected MIVariableObject createChildVariable(VariableObjectId id, MIVariableObject parentObj) {
776
		    return new MIVariableObject(id, parentObj);
777
		}
778
		
779
		/**
773
		 * This method builds a child expression based on its parent's expression.
780
		 * This method builds a child expression based on its parent's expression.
774
		 * It is a fallback solution for when GDB doesn't support the var-info-path-expression.
781
		 * It is a fallback solution for when GDB doesn't support the var-info-path-expression.
775
		 * 
782
		 * 
Lines 914-920 Link Here
914
		}
921
		}
915
	}
922
	}
916
	
923
	
917
	private class MIRootVariableObject extends MIVariableObject {
924
	/**
925
     * @since 2.1
926
     */
927
	public class MIRootVariableObject extends MIVariableObject {
918
928
919
		// Only root variables go through the GDB creation process
929
		// Only root variables go through the GDB creation process
920
		protected static final int STATE_NOT_CREATED = 10;
930
		protected static final int STATE_NOT_CREATED = 10;
Lines 941-947 Link Here
941
951
942
		public boolean isUpdating() { return currentState == STATE_UPDATING; }
952
		public boolean isUpdating() { return currentState == STATE_UPDATING; }
943
953
944
		public void markAsOutOfDate() { outOfDate = true; }
954
        public void markAsOutOfDate() {
955
            markAsOutOfDate(true);
956
        }
957
        
958
		public void markAsOutOfDate(boolean outOfDate) { this.outOfDate = outOfDate; }
959
		
960
		public boolean isOutOfDate() {
961
		    return outOfDate;
962
		}
945
		
963
		
946
		// Remember that we must add ourself as a modifiable descendant if our value can change
964
		// Remember that we must add ourself as a modifiable descendant if our value can change
947
		public void addModifiableDescendant(String gdbName, MIVariableObject descendant) {
965
		public void addModifiableDescendant(String gdbName, MIVariableObject descendant) {
Lines 1033-1039 Link Here
1033
				// Object is not fully created or is being updated
1051
				// Object is not fully created or is being updated
1034
				// so add RequestMonitor to pending queue
1052
				// so add RequestMonitor to pending queue
1035
				updatesPending.add(rm);
1053
				updatesPending.add(rm);
1036
			} else if (outOfDate == false) {
1054
			} else if (isOutOfDate() == false) {
1037
				rm.setData(false);
1055
				rm.setData(false);
1038
				rm.done();
1056
				rm.done();
1039
			} else {
1057
			} else {
Lines 1063-1069 Link Here
1063
								currentState = STATE_READY;
1081
								currentState = STATE_READY;
1064
								
1082
								
1065
								if (isSuccess()) {
1083
								if (isSuccess()) {
1066
									outOfDate = false;
1084
									markAsOutOfDate(false);
1067
1085
1068
									MIVarChange[] changes = getData().getMIVarChanges();
1086
									MIVarChange[] changes = getData().getMIVarChanges();
1069
									if (changes.length > 0 && changes[0].isInScope() == false) {
1087
									if (changes.length > 0 && changes[0].isInScope() == false) {
Lines 1077-1083 Link Here
1077
										// twice, or have an infinite loop while never re-creating the object.
1095
										// twice, or have an infinite loop while never re-creating the object.
1078
										// The can happen if we update a child first then we request 
1096
										// The can happen if we update a child first then we request 
1079
										// the root later,
1097
										// the root later,
1080
										lruVariableList.remove(getInternalId());
1098
										removeVariable(getInternalId());
1081
1099
1082
										rm.setData(true);
1100
										rm.setData(true);
1083
										rm.done();
1101
										rm.done();
Lines 1088-1094 Link Here
1088
										// We only mark this root as updated in our list if it is in-scope.
1106
										// We only mark this root as updated in our list if it is in-scope.
1089
										// For out-of-scope object, we don't ever need to re-update them so
1107
										// For out-of-scope object, we don't ever need to re-update them so
1090
										// we don't need to add them to this list.
1108
										// we don't need to add them to this list.
1091
										updatedRootList.add(MIRootVariableObject.this);
1109
										rootVariableUpdated(MIRootVariableObject.this);
1092
1110
1093
										rm.setData(false);
1111
										rm.setData(false);
1094
										rm.done();
1112
										rm.done();
Lines 1153-1160 Link Here
1153
	 *     
1171
	 *     
1154
	 * Note that if no frameContext is specified (only Execution, or even only Container), which can
1172
	 * Note that if no frameContext is specified (only Execution, or even only Container), which can
1155
	 * characterize a global variable for example, we will only use the available information.
1173
	 * characterize a global variable for example, we will only use the available information.
1174
	 * @since 2.1
1156
	 */
1175
	 */
1157
	private class VariableObjectId {
1176
	public class VariableObjectId {
1158
		// We don't use the expression context because it is not safe to compare them
1177
		// We don't use the expression context because it is not safe to compare them
1159
		// See bug 187718.  So we store the expression itself, and it's parent execution context.
1178
		// See bug 187718.  So we store the expression itself, and it's parent execution context.
1160
		String fExpression = null;
1179
		String fExpression = null;
Lines 1338-1343 Link Here
1338
    	fSession.removeServiceEventListener(this);
1357
    	fSession.removeServiceEventListener(this);
1339
	}
1358
	}
1340
1359
1360
    /**
1361
     * @since 2.1
1362
     */
1363
	protected DsfSession getSession() {
1364
	    return fSession;
1365
	}
1366
	
1367
	/**
1368
     * @since 2.1
1369
     */
1370
	protected ICommandControl getCommandControl() {
1371
	    return fCommandControl;
1372
	}
1373
	
1374
    /**
1375
     * @since 2.1
1376
     */
1377
	protected MIRootVariableObject createRootVariableObject(VariableObjectId id) {
1378
	    return new MIRootVariableObject(id);
1379
	}
1380
	
1381
    /**
1382
     * @since 2.1
1383
     */
1384
	protected void rootVariableUpdated(MIRootVariableObject rootObj) {
1385
	    updatedRootList.add(rootObj);
1386
	}
1387
	
1388
    /**
1389
     * @since 2.1
1390
     */
1391
	protected void removeVariable(VariableObjectId id) {
1392
	    lruVariableList.remove(id);
1393
	}
1394
	
1341
	/** 
1395
	/** 
1342
	 * This method returns a variable object based on the specified
1396
	 * This method returns a variable object based on the specified
1343
	 * ExpressionDMC, creating it in GDB if it was not created already.
1397
	 * ExpressionDMC, creating it in GDB if it was not created already.
Lines 1443-1449 Link Here
1443
			protected void handleCompleted() {
1497
			protected void handleCompleted() {
1444
				if (isSuccess()) {
1498
				if (isSuccess()) {
1445
					// Also store the object as a varObj that is up-to-date
1499
					// Also store the object as a varObj that is up-to-date
1446
					updatedRootList.add(newVarObj);
1500
    				rootVariableUpdated(newVarObj);	
1447
					// VarObj can now be used by others
1501
					// VarObj can now be used by others
1448
					newVarObj.creationCompleted(true);
1502
					newVarObj.creationCompleted(true);
1449
1503
Lines 1625-1631 Link Here
1625
    					}
1679
    					}
1626
    				});
1680
    				});
1627
    	
1681
    	
1628
    	} else if (command instanceof MIDataEvaluateExpression) {
1682
    	} else if (command instanceof MIDataEvaluateExpression<?>) {
1629
    		// This does not use the variable objects but sends the command directly to the back-end
1683
    		// This does not use the variable objects but sends the command directly to the back-end
1630
			fCommandControl.queueCommand(command, rm);
1684
			fCommandControl.queueCommand(command, rm);
1631
    	} else {
1685
    	} else {
Lines 1684-1690 Link Here
1684
    public void markAllOutOfDate() {
1738
    public void markAllOutOfDate() {
1685
    	MIRootVariableObject root;
1739
    	MIRootVariableObject root;
1686
    	while ((root = updatedRootList.poll()) != null) {
1740
    	while ((root = updatedRootList.poll()) != null) {
1687
    		root.markAsOutOfDate();
1741
    		root.markAsOutOfDate(true);
1688
    	}       
1742
    	}       
1689
    }
1743
    }
1690
1744
(-)src/org/eclipse/cdt/dsf/mi/service/command/commands/macos/MacOSMIVarUpdate.java (+49 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 QNX Software Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     QNX Software Systems - Initial API and implementation
10
 *     Wind River Systems   - Modified for new DSF Reference Implementation
11
 *     Ericsson				- Modified for handling of frame contexts
12
 *******************************************************************************/
13
14
package org.eclipse.cdt.dsf.mi.service.command.commands.macos;
15
16
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
17
import org.eclipse.cdt.dsf.mi.service.command.commands.MICommand;
18
import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
19
import org.eclipse.cdt.dsf.mi.service.command.output.macos.MacOSMIVarUpdateInfo;
20
21
/**
22
 * 
23
 *     -var-update [print-values] {NAME | "*"}
24
 *
25
 *  Update the value of the variable object NAME by evaluating its
26
 *  expression after fetching all the new values from memory or registers.
27
 *  A `*' causes all existing variable objects to be updated.
28
 *  If print-values has a value for of 0 or --no-values, print only the names of the variables; 
29
 *  if print-values is 1 or --all-values, also print their values; 
30
 *  if it is 2 or --simple-values print the name and value for simple data types and just 
31
 *  the name for arrays, structures and unions. 
32
 *  
33
 *  It seems that for MacOS, we must use the full string for print-values, such as
34
 *  --all-values.
35
 * 
36
 * @since 2.1
37
 */
38
public class MacOSMIVarUpdate extends MICommand<MacOSMIVarUpdateInfo> {
39
40
	public MacOSMIVarUpdate(ICommandControlDMContext dmc, String name) {
41
		// Must use --all-values instead of 1 for Mac OS
42
		super(dmc, "-var-update", new String[] { "--all-values", name }); //$NON-NLS-1$//$NON-NLS-2$
43
	}
44
	
45
    @Override
46
    public MacOSMIVarUpdateInfo getResult(MIOutput out) {
47
        return new MacOSMIVarUpdateInfo(out);
48
    }
49
}
(-)src/org/eclipse/cdt/dsf/mi/service/command/output/macos/MacOSMIVarUpdateInfo.java (+123 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 QNX Software Systems and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     QNX Software Systems - Initial API and implementation
10
 *     Ericsson             - Created version for Mac OS
11
 *******************************************************************************/
12
package org.eclipse.cdt.dsf.mi.service.command.output.macos;
13
14
import java.util.ArrayList;
15
import java.util.List;
16
17
import org.eclipse.cdt.dsf.mi.service.command.output.MIConst;
18
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
19
import org.eclipse.cdt.dsf.mi.service.command.output.MIList;
20
import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
21
import org.eclipse.cdt.dsf.mi.service.command.output.MIResult;
22
import org.eclipse.cdt.dsf.mi.service.command.output.MIResultRecord;
23
import org.eclipse.cdt.dsf.mi.service.command.output.MITuple;
24
import org.eclipse.cdt.dsf.mi.service.command.output.MIValue;
25
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarChange;
26
27
/**
28
 * GDB/MI var-update for Mac OS.
29
 * -var-update *
30
 * ^done,changelist=[varobj={name="var1",in_scope="true",type_changed="false"}],time={.....}
31
 * 
32
 * @since 2.1
33
 */
34
public class MacOSMIVarUpdateInfo extends MIInfo {
35
36
	MIVarChange[] changeList;
37
38
	public MacOSMIVarUpdateInfo(MIOutput record) {
39
		super(record);
40
        List<MIVarChange> aList = new ArrayList<MIVarChange>();
41
        if (isDone()) {
42
            MIOutput out = getMIOutput();
43
            MIResultRecord rr = out.getMIResultRecord();
44
            if (rr != null) {
45
                MIResult[] results =  rr.getMIResults();
46
                for (int i = 0; i < results.length; i++) {
47
                    String var = results[i].getVariable();
48
                    if (var.equals("changelist")) { //$NON-NLS-1$
49
                        MIValue value = results[i].getMIValue();
50
                        if (value instanceof MITuple) {
51
                            parseChangeList((MITuple)value, aList);
52
                        } else if (value instanceof MIList) {
53
                            parseChangeList((MIList)value, aList);
54
                        }
55
                    }
56
                }
57
            }
58
        }
59
        changeList = aList.toArray(new MIVarChange[aList.size()]);
60
	}
61
62
	public MIVarChange[] getMIVarChanges() {
63
		return changeList;
64
	}
65
66
	/**
67
	 * For MI2 the format is now a MIList.
68
	 * @param tuple
69
	 * @param aList
70
	 */
71
	void parseChangeList(MIList miList, List<MIVarChange> aList) {
72
		// The MIList in Apple gdb contains MIResults instead of MIValues. It looks like:
73
		// ^done,changelist=[varobj={name="var1",in_scope="true",type_changed="false"}],time={.....}
74
		// Bug 250037
75
		MIResult[] results = miList.getMIResults();
76
		for (int i = 0; i < results.length; i++) {
77
			String var = results[i].getVariable();
78
			if (var.equals("varobj")) { //$NON-NLS-1$
79
				MIValue value = results[i].getMIValue();
80
				if (value instanceof MITuple) {
81
					parseChangeList((MITuple)value, aList);
82
				} else if (value instanceof MIList) {
83
					parseChangeList((MIList)value, aList);
84
				}
85
			}
86
		}
87
	} 
88
	
89
	void parseChangeList(MITuple tuple, List<MIVarChange> aList) {
90
		MIResult[] results = tuple.getMIResults();
91
		MIVarChange change = null;
92
		for (int i = 0; i < results.length; i++) {
93
			String var = results[i].getVariable();
94
			MIValue value = results[i].getMIValue();
95
			if (value instanceof MITuple) {
96
				parseChangeList((MITuple)value, aList);
97
			}
98
			else
99
			{
100
				String str = ""; //$NON-NLS-1$
101
				if (value instanceof MIConst) {
102
					str = ((MIConst)value).getString();
103
				}
104
				if (var.equals("name")) { //$NON-NLS-1$
105
					change = new MIVarChange(str);
106
					aList.add(change);
107
				} else if (var.equals("value")) { //$NON-NLS-1$
108
					if (change != null) {
109
						change.setValue(str);
110
					}
111
				} else if (var.equals("in_scope")) { //$NON-NLS-1$
112
					if (change != null) {
113
						change.setInScope("true".equals(str)); //$NON-NLS-1$
114
					}
115
				} else if (var.equals("type_changed")) { //$NON-NLS-1$
116
					if (change != null) {
117
						change.setChanged("true".equals(str)); //$NON-NLS-1$
118
					}
119
				}				
120
			}
121
		}
122
	}
123
}

Return to bug 298883