~ubuntu-branches/debian/sid/eclipse-cdt/sid

« back to all changes in this revision

Viewing changes to dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIListThreadGroupsInfo.java

  • Committer: Package Import Robot
  • Author(s): Jakub Adam
  • Date: 2011-10-06 21:15:04 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20111006211504-8dutmljjih0zikfv
Tags: 8.0.1-1
* New upstream release.
* Split the JNI packages into a separate architecture dependent
  package and made eclipse-cdt architecture independent.
* Install JNI libraries into multiarch aware location
* Bumped Standards-Version to 3.9.2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*******************************************************************************
 
2
 * Copyright (c) 2008, 2010 Ericsson 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
 *     Ericsson - Initial API and implementation
 
10
 *******************************************************************************/
 
11
 
 
12
package org.eclipse.cdt.dsf.mi.service.command.output;
 
13
 
 
14
import java.util.ArrayList;
 
15
import java.util.List;
 
16
import java.util.regex.Matcher;
 
17
import java.util.regex.Pattern;
 
18
 
 
19
import org.eclipse.cdt.dsf.concurrent.Immutable;
 
20
 
 
21
/**
 
22
 * GDB/MI thread group parsing.
 
23
 * 
 
24
 *  The description field can be different depending on the target we are connected to.
 
25
 *
 
26
 *  -list-thread-groups --available:
 
27
 *  ^done,groups=[{id="161",type="process",description="name: JIM_InstallerProcess, type 555481, locked: N, system: N, state: Idle"},
 
28
 *                {id="162",type="process",description="name: JIM_TcpSetupHandlerProcess, type 555505, locked: N, system: N, state: Idle"},
 
29
 *                {id="165",type="process",description="name: JUnitProcess2_PT, type 1094608, locked: N, system: N, state: Idle"},
 
30
 *                {id="166",type="process",description="name: JUnitProcess_PT, type 1094605, locked: N, system: N, state: Idle"}]
 
31
 *
 
32
 *                {id="3602",type="process",description="/usr/sbin/dhcdbd --system",user="root"}
 
33
 *          
 
34
 *  -list-thread-groups: 
 
35
 *  ^done,groups=[{id="162",type="process",pid="162"}]
 
36
 *
 
37
 *  -list-thread-groups GROUPID, in the case of a running thread or a stopped thread:
 
38
 *  ^done,threads=[{id="1",target-id="Thread 162.32942",details="JUnitProcess_PT (Ready) 1030373359 44441",frame={level="0",addr="0x00000000",func="??",args=[]},state="stopped"}]
 
39
 *  ^done,threads=[{id="1",target-id="Thread 162.32942",details="JUnitProcess_PT Idle 981333916 42692",state="running"}]
 
40
 *  
 
41
 *  As of GDB 7.1, a new 'core' output field has been added.  This field is a list 
 
42
 *  of integers, each identifying a core that one thread of the group is running on. 
 
43
 *  This field may be absent if such information is not available.
 
44
 *  
 
45
 *  -list-thread-groups
 
46
 *  ^done,groups=[{id="12779",type="process",pid="12779",cores=["3"]}]
 
47
 *    
 
48
 *  -list-thread-groups 12779
 
49
 *   ^done,threads=[{id="10",
 
50
 *                   target-id="Thread 0xb3d58ba0 (LWP 12876)",
 
51
 *                   frame={level="0",addr="0xb7e21b88",func="clone",args=[],from="/lib/libc.so.6"},
 
52
 *                   state="stopped",
 
53
 *                   core="3"},
 
54
 *                  {id="3",
 
55
 *                   target-id="Thread 0xb755fba0 (LWP 12811)",
 
56
 *                   frame={level="0",addr="0xffffe410",func="__kernel_vsyscall",args=[]},
 
57
 *                   state="stopped",
 
58
 *                   core="3"},
 
59
 *                  {id="2",
 
60
 *                   target-id="Thread 0xb7d60ba0 (LWP 12810)",
 
61
 *                   frame={level="0",addr="0xffffe410",func="__kernel_vsyscall",args=[]},
 
62
 *                   state="stopped",
 
63
 *                   core="3"},
 
64
 *                  {id="1",
 
65
 *                   target-id="Thread 0xb7d616b0 (LWP 12779)",
 
66
 *                   frame={level="0",addr="0x08048609",func="main",args=[],file="../src/NonStop.cpp",fullname="/local/runtime-TestDSF/NonStop/src/NonStop.cpp",line="44"},
 
67
 *                   state="stopped",
 
68
 *                   core="3"}]
 
69
 *                   
 
70
 *  As of GDB 7.1, the --recurse option has been added and causes a different output
 
71
 *  
 
72
 *  -list-thread-groups --recurse 1
 
73
 *  ^done,groups=[{id="12779",
 
74
 *                 type="process",
 
75
 *                 pid="12779",
 
76
 *                 cores=["3"],
 
77
 *                 threads=[{id="10",
 
78
 *                           target-id="Thread 0xb3d58ba0 (LWP 12876)",
 
79
 *                           frame={level="0",addr="0xb7e21b88",func="clone",args=[],from="/lib/libc.so.6"},
 
80
 *                           state="stopped",
 
81
 *                           core="3"},
 
82
 *                          {id="3",
 
83
 *                           target-id="Thread 0xb755fba0 (LWP 12811)",
 
84
 *                           frame={level="0",addr="0xffffe410",func="__kernel_vsyscall",args=[]},
 
85
 *                           state="stopped",
 
86
 *                           core="3"},
 
87
 *                          {id="2",
 
88
 *                           target-id="Thread 0xb7d60ba0 (LWP 12810)",
 
89
 *                           frame={level="0",addr="0xffffe410",func="__kernel_vsyscall",args=[]},
 
90
 *                           state="stopped",
 
91
 *                           core="3"},
 
92
 *                          {id="1",
 
93
 *                           target-id="Thread 0xb7d616b0 (LWP 12779)",
 
94
 *                           frame={level="0",addr="0x08048609",func="main",args=[],file="../src/NonStop.cpp",fullname="/local/runtime-TestDSF/NonStop/src/NonStop.cpp",line="44"},
 
95
 *                           state="stopped",
 
96
 *                           core="3"}
 
97
 *                         ]
 
98
 *                }]
 
99
 *  
 
100
 * Example of outputs by version on Linux
 
101
 * 
 
102
 * GDB 7.0
 
103
 *  
 
104
 *  (when no inferior is running)
 
105
 * -list-thread-groups
 
106
 * ^done,groups=[]
 
107
 *
 
108
 * (with an inferior running)
 
109
 * -list-thread-groups
 
110
 * ^done,groups=[{id="19386",type="process",pid="19386"}]
 
111
 * 
 
112
 * -list-thread-groups 19386
 
113
 * ^done,threads=[{id="1",target-id="process 19386",frame={level="0",addr="0x08048618",func="main",args=[],file="a.cc",fullname="/local/lmckhou/testing/a.cc",line="9"},state="stopped"}]
 
114
 * 
 
115
 * -list-thread-groups --available 
 
116
 * ^done,groups=[{id="19371",type="process",description="gdb.7.0 -i mi testing/a.out",user="lmckhou"},{id="19386",type="process",description="/local/lmckhou/testing/a.out",user="lmckhou"},{id="19413",type="process",description="sleep 5",user="lmckhou"}]
 
117
 * 
 
118
 * GDB 7.1
 
119
 * 
 
120
 * (when no inferior is running)
 
121
 * -list-thread-groups
 
122
 * ^done,groups=[{id="0",type="process",pid="0"}]
 
123
 * 
 
124
 * (with an inferior running)
 
125
 * -list-thread-groups
 
126
 * ^done,groups=[{id="19424",type="process",pid="19424",cores=["3"]}]
 
127
 * 
 
128
 * -list-thread-groups 19424
 
129
 * ^done,threads=[{id="1",target-id="process 19424",frame={level="0",addr="0x08048618",func="main",args=[],file="a.cc",fullname="/local/lmckhou/testing/a.cc",line="9"},state="stopped",core="3"}]
 
130
 * 
 
131
 * -list-thread-groups --available
 
132
 * ^done,groups=[{id="19418",type="process",description="gdb.7.1 -i mi testing/a.out",user="lmckhou"},{id="19424",type="process",description="/local/lmckhou/testing/a.out",user="lmckhou"},{id="19438",type="process",description="sleep 5",user="lmckhou"}]
 
133
 * 
 
134
 * GDB 7.2
 
135
 * 
 
136
 * (when no inferior is running)
 
137
 * -list-thread-groups
 
138
 * ^done,groups=[{id="i1",type="process",executable="/local/lmckhou/testing/a.out"}]
 
139
 * 
 
140
 * (with an inferior running)
 
141
 * -list-thread-groups
 
142
 * ^done,groups=[{id="i1",type="process",pid="19451",executable="/local/lmckhou/testing/a.out",cores=["2"]}]
 
143
 * 
 
144
 * -list-thread-groups i1
 
145
 * ^done,threads=[{id="1",target-id="process 19451",frame={level="0",addr="0x08048618",func="main",args=[],file="a.cc",fullname="/local/lmckhou/testing/a.cc",line="9"},state="stopped",core="2"}]
 
146
 * 
 
147
 * -list-thread-groups --available
 
148
 * ^done,groups=[{id="19445",type="process",description="gdb.7.2 -i mi testing/a.out",user="lmckhou"},{id="19451",type="process",description="/local/lmckhou/testing/a.out",user="lmckhou"},{id="19462",type="process",description="sleep 5",user="lmckhou"}]
 
149
 *
 
150
 * @since 1.1
 
151
 */
 
152
 
 
153
public class MIListThreadGroupsInfo extends MIInfo {
 
154
        
 
155
        /**
 
156
         * @noextend This interface is not intended to be extended by clients.
 
157
         * @noimplement This interface is not intended to be implemented by clients.
 
158
         */
 
159
        public interface IThreadGroupInfo {
 
160
                String getGroupId();
 
161
                String getPid();
 
162
                String getName();
 
163
                String getDesciption();
 
164
                /**@since 4.0 */
 
165
                String getUser();
 
166
                /**@since 4.0 */
 
167
                String getType();
 
168
                /**@since 4.0 */
 
169
                String[] getCores();
 
170
                /**@since 4.0 */
 
171
                String getExecutable();
 
172
        }
 
173
        
 
174
        @Immutable
 
175
        private static class ThreadGroupInfo implements IThreadGroupInfo {
 
176
                final String fGroupId;
 
177
                final String fDescription;
 
178
                final String fName;
 
179
                final String fType;
 
180
                final String fUser;
 
181
                final String fPid;
 
182
                final String[] fCores;
 
183
                final String fExecutable;
 
184
                
 
185
                public ThreadGroupInfo(String id, String description, String type, String pid, 
 
186
                                               String user, String[] cores, String exec) {
 
187
                        fGroupId = id;
 
188
                        fDescription = description;
 
189
                        fType = type;
 
190
                        fUser = user;
 
191
                        fPid = pid;
 
192
                        fCores = cores;                         
 
193
                        
 
194
                        fExecutable = exec;
 
195
                        
 
196
                        fName = parseName(fDescription);
 
197
                }
 
198
                
 
199
                private static String parseName(String desc) {
 
200
                        String name = ""; //$NON-NLS-1$
 
201
 
 
202
                        // Find the string "name: " followed by the smallest set of characters that
 
203
                        // is followed by a comma, or by the end of the line.
 
204
                        Pattern pattern = Pattern.compile("name: (.*?)(, |$)", Pattern.MULTILINE); //$NON-NLS-1$
 
205
                Matcher matcher = pattern.matcher(desc);
 
206
                if (matcher.find()) {
 
207
                        name = matcher.group(1);
 
208
                } else {
 
209
                        // If we didn't get the form "name: " then we expect to have the form
 
210
                        // "/usr/sbin/dhcdbd --system"
 
211
                        name = desc.split("\\s", 2)[0]; //$NON-NLS-1$
 
212
                }
 
213
 
 
214
                        return name;
 
215
                }
 
216
                
 
217
                public String getGroupId() { return fGroupId; }
 
218
                public String getPid() { return fPid; }
 
219
 
 
220
                public String getName() { return fName; }
 
221
 
 
222
                public String getDesciption() { return fDescription; }
 
223
                public String[] getCores() { return fCores; }
 
224
                public String getUser() { return fUser; }
 
225
 
 
226
                public String getType() { return fType; }
 
227
                public String getExecutable() { return fExecutable; }
 
228
        }
 
229
        
 
230
        
 
231
        private IThreadGroupInfo[] fGroupList;
 
232
        private MIThreadInfoInfo fThreadInfo;
 
233
        
 
234
    public MIListThreadGroupsInfo(MIOutput out) {
 
235
        super(out);
 
236
        parse();
 
237
        }
 
238
        
 
239
        public IThreadGroupInfo[] getGroupList() { return fGroupList; }
 
240
        public MIThreadInfoInfo getThreadInfo() { return fThreadInfo; }
 
241
        
 
242
        private void parse() {
 
243
                if (isDone()) {
 
244
                        MIOutput out = getMIOutput();
 
245
                        MIResultRecord rr = out.getMIResultRecord();
 
246
                        if (rr != null) {
 
247
                                MIResult[] results =  rr.getMIResults();
 
248
                                for (int i = 0; i < results.length; i++) {
 
249
                                        String var = results[i].getVariable();
 
250
                                        if (var.equals("groups")) { //$NON-NLS-1$
 
251
                                                MIValue val = results[i].getMIValue();
 
252
                                                if (val instanceof MIList) {
 
253
                                                        parseGroups((MIList)val);
 
254
                                                }
 
255
                                        } else if (var.equals("threads")) { //$NON-NLS-1$
 
256
                                                // Re-use the MIThreadInfoInfo parsing
 
257
                                                fThreadInfo = new MIThreadInfoInfo(out);
 
258
                                        }
 
259
                                }
 
260
                        }
 
261
                }
 
262
                if (fGroupList == null) {
 
263
                        fGroupList = new IThreadGroupInfo[0];
 
264
                }
 
265
                if (fThreadInfo == null) {
 
266
                        fThreadInfo = new MIThreadInfoInfo(null);
 
267
                }
 
268
        }
 
269
 
 
270
        private void parseGroups(MIList list) {
 
271
                MIValue[] values = list.getMIValues();
 
272
                fGroupList = new IThreadGroupInfo[values.length];
 
273
                for (int i = 0; i < values.length; i++) {
 
274
                        MIResult[] results = ((MITuple)values[i]).getMIResults();
 
275
                        String id, desc, type, pid, exec, user;
 
276
                        id = desc = type = pid = exec = user = "";//$NON-NLS-1$
 
277
                        
 
278
                        String[] cores = null;
 
279
                        
 
280
                        for (MIResult result : results) {
 
281
                                String var = result.getVariable();
 
282
                                if (var.equals("id")) { //$NON-NLS-1$
 
283
                                        MIValue value = result.getMIValue();
 
284
                                        if (value instanceof MIConst) {
 
285
                                                String str = ((MIConst)value).getCString();
 
286
                                                id = str.trim();
 
287
                                        }
 
288
                                } else if (var.equals("description")) { //$NON-NLS-1$
 
289
                                        MIValue value = result.getMIValue();
 
290
                                        if (value instanceof MIConst) {
 
291
                                                String str = ((MIConst)value).getCString();
 
292
                                                desc = str.trim();
 
293
                                        }
 
294
                                } else if (var.equals("type")) { //$NON-NLS-1$
 
295
                                        MIValue value = result.getMIValue();
 
296
                                        if (value instanceof MIConst) {
 
297
                                                String str = ((MIConst)value).getCString();
 
298
                                                type = str.trim();
 
299
                                        }
 
300
                                } else if (var.equals("pid")) { //$NON-NLS-1$
 
301
                                        MIValue value = result.getMIValue();
 
302
                                        if (value instanceof MIConst) {
 
303
                                                String str = ((MIConst)value).getCString();
 
304
                                                pid = str.trim();
 
305
                                        }
 
306
                                }  else if (var.equals("user")) { //$NON-NLS-1$
 
307
                                        MIValue value = result.getMIValue();
 
308
                                        if (value instanceof MIConst) {
 
309
                                                String str = ((MIConst)value).getCString();
 
310
                                                user = str.trim();
 
311
                                        }
 
312
                                } else if (var.equals("cores")) { //$NON-NLS-1$
 
313
                                        // Staring with GDB 7.1
 
314
                                        MIValue value = result.getMIValue();
 
315
                                        if (value instanceof MIList) {
 
316
                                                cores = parseCores((MIList)value);
 
317
                                        }
 
318
                                } else if (var.equals("executable")) { //$NON-NLS-1$
 
319
                                        // Staring with GDB 7.2
 
320
                                        MIValue value = result.getMIValue();
 
321
                                        if (value instanceof MIConst) {
 
322
                                                String str = ((MIConst)value).getCString();
 
323
                                                exec = str.trim();
 
324
                                        }
 
325
                                }
 
326
                        }
 
327
                        // In the case of -list-thread-groups --available, the pid field is not present, but the
 
328
                        // pid is used as the main id.  To know we are in this case, we check that we have
 
329
                        // a description, that only happens for -list-thread-groups --available
 
330
                        // We must check this because with GDB 7.2, there will be no pid field as a result
 
331
                        // of -list-thread-groups, if no process is actually running yet.
 
332
                        if (pid.equals("") && !desc.equals("")) { //$NON-NLS-1$ //$NON-NLS-2$
 
333
                                pid = id;
 
334
                        }
 
335
                        fGroupList[i] = new ThreadGroupInfo(id, desc, type, pid, user, cores, exec);
 
336
                }
 
337
        }
 
338
        
 
339
        private String[] parseCores(MIList list) {
 
340
                List<String> cores = new ArrayList<String>();
 
341
                
 
342
                MIValue[] values = list.getMIValues();
 
343
                for (int i = 0; i < values.length; i++) {
 
344
                        if (values[i] instanceof MIConst) {
 
345
                                cores.add(((MIConst)values[i]).getCString());
 
346
                        }
 
347
                }
 
348
                return cores.toArray(new String[cores.size()]);
 
349
        }
 
350
}