Source Code Cross Referenced for GdbDebugger.java in  » IDE-Netbeans » cnd » org » netbeans » modules » cnd » debugger » gdb » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Netbeans » cnd » org.netbeans.modules.cnd.debugger.gdb 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:
0042:        package org.netbeans.modules.cnd.debugger.gdb;
0043:
0044:        import java.beans.PropertyChangeEvent;
0045:        import java.beans.PropertyChangeListener;
0046:        import java.beans.PropertyChangeSupport;
0047:        import java.io.BufferedReader;
0048:        import java.io.File;
0049:        import java.io.IOException;
0050:        import java.io.InputStreamReader;
0051:        import java.util.ArrayList;
0052:        import java.util.Collection;
0053:        import java.util.Collections;
0054:        import java.util.HashMap;
0055:        import java.util.List;
0056:        import java.util.Map;
0057:        import java.util.Timer;
0058:        import java.util.TimerTask;
0059:        import java.util.logging.Logger;
0060:        import javax.swing.SwingUtilities;
0061:        import org.netbeans.api.debugger.DebuggerEngine;
0062:        import org.netbeans.api.debugger.DebuggerInfo;
0063:        import org.netbeans.api.debugger.DebuggerManager;
0064:        import org.netbeans.api.debugger.Properties;
0065:        import org.netbeans.api.debugger.Session;
0066:        import org.netbeans.api.project.Project;
0067:        import org.netbeans.api.project.ProjectInformation;
0068:        import org.netbeans.modules.cnd.debugger.gdb.breakpoints.BreakpointImpl;
0069:        import org.netbeans.modules.cnd.debugger.gdb.breakpoints.GdbBreakpoint;
0070:        import org.netbeans.modules.cnd.debugger.gdb.disassembly.Disassembly;
0071:        import org.netbeans.modules.cnd.debugger.gdb.event.GdbBreakpointEvent;
0072:        import org.netbeans.modules.cnd.debugger.gdb.expr.Expression;
0073:        import org.netbeans.modules.cnd.debugger.gdb.profiles.GdbProfile;
0074:        import org.netbeans.modules.cnd.debugger.gdb.proxy.GdbMiDefinitions;
0075:        import org.netbeans.modules.cnd.debugger.gdb.proxy.GdbProxy;
0076:        import org.netbeans.modules.cnd.debugger.gdb.timer.GdbTimer;
0077:        import org.netbeans.modules.cnd.debugger.gdb.utils.CommandBuffer;
0078:        import org.netbeans.modules.cnd.debugger.gdb.utils.GdbUtils;
0079:        import org.netbeans.modules.cnd.makeproject.api.MakeArtifact;
0080:        import org.netbeans.modules.cnd.makeproject.api.ProjectActionEvent;
0081:        import org.netbeans.modules.cnd.makeproject.api.configurations.ConfigurationDescriptorProvider;
0082:        import org.netbeans.modules.cnd.makeproject.api.configurations.MakeConfiguration;
0083:        import org.netbeans.modules.cnd.makeproject.api.configurations.MakeConfigurationDescriptor;
0084:        import org.netbeans.modules.cnd.makeproject.api.runprofiles.RunProfile;
0085:        import org.netbeans.modules.cnd.settings.CppSettings;
0086:        import org.netbeans.spi.debugger.ContextProvider;
0087:        import org.netbeans.spi.debugger.DebuggerEngineProvider;
0088:        import org.openide.DialogDisplayer;
0089:        import org.openide.ErrorManager;
0090:        import org.openide.NotifyDescriptor;
0091:        import org.openide.filesystems.FileUtil;
0092:        import org.openide.modules.InstalledFileLocator;
0093:        import org.openide.util.Utilities;
0094:        import org.openide.util.NbBundle;
0095:        import org.openide.util.RequestProcessor;
0096:        import org.openide.windows.InputOutput;
0097:
0098:        /**
0099:         * Represents one GDB debugger session.
0100:         *
0101:         * <br><br>
0102:         * <b>How to obtain it from DebuggerEngine:</b>
0103:         * <pre style="background-color: rgb(255, 255, 153);">
0104:         *    GdbDebugger cndDebugger = (GdbDebugger) debuggerEngine.lookup
0105:         *        (GdbDebugger.class);</pre>
0106:         */
0107:        public class GdbDebugger implements  PropertyChangeListener,
0108:                GdbMiDefinitions {
0109:
0110:            public static final String PROP_STATE = "state"; // NOI18N
0111:            public static final String PROP_CURRENT_THREAD = "currentThread"; // NOI18N
0112:            public static final String PROP_CURRENT_CALL_STACK_FRAME = "currentCallStackFrame"; // NOI18N
0113:            public static final String PROP_KILLTERM = "killTerm"; // NOI18N
0114:            public static final String PROP_SHARED_LIB_LOADED = "sharedLibLoaded"; // NOI18N
0115:
0116:            public static final String STATE_NONE = "state_none"; // NOI18N
0117:            public static final String STATE_STARTING = "state_starting"; // NOI18N
0118:            public static final String STATE_LOADING = "state_loading"; // NOI18N
0119:            public static final String STATE_LOADED = "state_loaded"; // NOI18N
0120:            public static final String STATE_READY = "state_ready"; // NOI18N
0121:            public static final String STATE_RUNNING = "state_running"; // NOI18N
0122:            public static final String STATE_STOPPED = "state_stopped"; // NOI18N
0123:            public static final String STATE_SILENT_STOP = "state_silent_stop"; // NOI18N
0124:            public static final String STATE_EXITED = "state_exited"; // NOI18N
0125:
0126:            private static final int DEBUG_ATTACH = 999;
0127:
0128:            /* Some breakpoint flags used only on Windows XP (with Cygwin) */
0129:            public static final int GDB_TMP_BREAKPOINT = GdbBreakpoint.SUSPEND_ALL + 1;
0130:
0131:            /** ID of GDB Debugger Engine for C */
0132:            public static final String ENGINE_ID = "netbeans-cnd-GdbSession/C"; // NOI18N
0133:
0134:            /** ID of GDB Debugger Session */
0135:            public static final String SESSION_ID = "netbeans-cnd-GdbSession"; // NOI18N
0136:
0137:            /** ID of GDB Debugger SessionProvider */
0138:            public static final String SESSION_PROVIDER_ID = "netbeans-cnd-GdbSessionProvider"; // NOI18N
0139:
0140:            /** Dis update */
0141:            public static final String DIS_UPDATE = "dis_update"; // NOI18N
0142:
0143:            private GdbProxy gdb;
0144:            private ContextProvider lookupProvider;
0145:            private String state = STATE_NONE;
0146:            private PropertyChangeSupport pcs;
0147:            private String runDirectory;
0148:            private ArrayList<CallStackFrame> callstack = new ArrayList<CallStackFrame>();
0149:            private GdbEngineProvider gdbEngineProvider;
0150:            private CallStackFrame currentCallStackFrame;
0151:            public final Object LOCK = new Object();
0152:            private long programPID = 0;
0153:            private double gdbVersion = 6.4;
0154:            private boolean continueAfterFirstStop = true;
0155:            private ArrayList<GdbVariable> localVariables = new ArrayList<GdbVariable>();
0156:            private Map<Integer, BreakpointImpl> pendingBreakpointMap = new HashMap<Integer, BreakpointImpl>();
0157:            private Map<String, BreakpointImpl> breakpointList = Collections
0158:                    .synchronizedMap(new HashMap<String, BreakpointImpl>());
0159:            private static Map<String, TypeInfo> ticache = new HashMap<String, TypeInfo>();
0160:            private static Logger log = Logger.getLogger("gdb.logger"); // NOI18N
0161:            private int currentToken = 0;
0162:            private String currentThreadID = "1"; // NOI18N
0163:            private static final String[] emptyThreadsList = new String[0];
0164:            private String[] threadsList = emptyThreadsList;
0165:            private Timer startupTimer = null;
0166:            private boolean cygwin = false;
0167:            private boolean cplusplus = false;
0168:            private String firstBPfullname;
0169:            private String firstBPfile;
0170:            private String firstBPline;
0171:            private InputOutput iotab;
0172:            private boolean firstOutput;
0173:            private boolean dlopenPending;
0174:            private String lastShare;
0175:            private int shareToken;
0176:            private final Disassembly disassembly;
0177:
0178:            public GdbDebugger(ContextProvider lookupProvider) {
0179:                this .lookupProvider = lookupProvider;
0180:                pcs = new PropertyChangeSupport(this );
0181:                firstOutput = true;
0182:                dlopenPending = false;
0183:                addPropertyChangeListener(this );
0184:                List l = lookupProvider.lookup(null,
0185:                        DebuggerEngineProvider.class);
0186:                int i, k = l.size();
0187:                for (i = 0; i < k; i++) {
0188:                    if (l.get(i) instanceof  GdbEngineProvider) {
0189:                        gdbEngineProvider = (GdbEngineProvider) l.get(i);
0190:                    }
0191:                }
0192:                if (gdbEngineProvider == null) {
0193:                    throw new IllegalArgumentException(
0194:                            "GdbEngineProvider must be used to start GdbDebugger!"); // NOI18N
0195:                }
0196:                threadsViewInit();
0197:                disassembly = new Disassembly(this );
0198:            }
0199:
0200:            public ContextProvider getLookup() {
0201:                return lookupProvider;
0202:            }
0203:
0204:            public void startDebugger() {
0205:                ProjectActionEvent pae;
0206:                GdbProfile profile;
0207:                String termpath = null;
0208:                GdbTimer.getTimer("Startup").start("Startup1"); // NOI18N
0209:                GdbTimer.getTimer("Stop").start("Stop1"); // NOI18N
0210:
0211:                setStarting();
0212:                try {
0213:                    pae = lookupProvider.lookupFirst(null,
0214:                            ProjectActionEvent.class);
0215:                    iotab = lookupProvider.lookupFirst(null, InputOutput.class);
0216:                    if (iotab != null) {
0217:                        iotab.setErrSeparated(false);
0218:                    }
0219:                    runDirectory = pae.getProfile().getRunDirectory().replace(
0220:                            "\\", "/")
0221:                            + "/"; // NOI18N
0222:                    profile = (GdbProfile) pae.getConfiguration().getAuxObject(
0223:                            GdbProfile.GDB_PROFILE_ID);
0224:                    int conType = pae.getProfile().getConsoleType().getValue();
0225:                    if (!Utilities.isWindows()
0226:                            && conType != RunProfile.CONSOLE_TYPE_OUTPUT_WINDOW
0227:                            && pae.getID() != DEBUG_ATTACH) {
0228:                        termpath = pae.getProfile().getTerminalPath();
0229:                    }
0230:                    if (!Boolean.getBoolean("gdb.suppress-timeout")) {
0231:                        startupTimer = new Timer("GDB Startup Timer Thread"); // NOI18N
0232:                        startupTimer.schedule(new TimerTask() {
0233:                            public void run() {
0234:                                DialogDisplayer.getDefault().notify(
0235:                                        new NotifyDescriptor.Message(NbBundle
0236:                                                .getMessage(GdbDebugger.class,
0237:                                                        "ERR_StartupTimeout"))); // NOI18N
0238:                                setExited();
0239:                                finish(true);
0240:                            }
0241:                        }, 30000);
0242:                    }
0243:                    //            String gdbCommand = profile.getGdbPath(profile.getGdbCommand(), pae.getProfile().getRunDirectory());
0244:                    String gdbCommand = profile
0245:                            .getGdbPath((MakeConfiguration) pae
0246:                                    .getConfiguration());
0247:                    if (gdbCommand.toLowerCase().contains("cygwin")) { // NOI18N
0248:                        cygwin = true;
0249:                    }
0250:                    gdb = new GdbProxy(this , gdbCommand, pae.getProfile()
0251:                            .getEnvironment().getenv(), runDirectory, termpath);
0252:                    gdb.gdb_version();
0253:                    gdb.environment_directory(runDirectory);
0254:                    gdb.gdb_show("language"); // NOI18N
0255:                    gdb.gdb_set("print repeat", // NOI18N
0256:                            Integer.toString(CppSettings.getDefault()
0257:                                    .getArrayRepeatThreshold()));
0258:                    gdb.data_list_register_names("");
0259:                    if (pae.getID() == DEBUG_ATTACH) {
0260:                        programPID = lookupProvider.lookupFirst(null,
0261:                                Long.class);
0262:                        CommandBuffer cb = new CommandBuffer();
0263:                        gdb.target_attach(cb, Long.toString(programPID));
0264:                        cb.waitForCompletion();
0265:                        String err = cb.getError();
0266:                        if (err != null || cb.timedOut()) {
0267:                            final String msg;
0268:                            if (err == null) {
0269:                                msg = NbBundle.getMessage(GdbDebugger.class,
0270:                                        "ERR_AttachTimeout"); // NOI18N
0271:                            } else if (err.toLowerCase().contains(
0272:                                    "no such process")
0273:                                    || // NOI18N
0274:                                    err
0275:                                            .toLowerCase()
0276:                                            .contains(
0277:                                                    "couldn't open /proc file for process ")) { // NOI18N
0278:                                msg = NbBundle.getMessage(GdbDebugger.class,
0279:                                        "ERR_NoSuchProcess"); // NOI18N
0280:                            } else {
0281:                                msg = NbBundle.getMessage(GdbDebugger.class,
0282:                                        "ERR_CantAttach"); // NOI18N
0283:                            }
0284:                            SwingUtilities.invokeLater(new Runnable() {
0285:                                public void run() {
0286:                                    DialogDisplayer.getDefault().notify(
0287:                                            new NotifyDescriptor.Message(msg));
0288:                                    setExited();
0289:                                    finish(false);
0290:                                }
0291:                            });
0292:                        } else {
0293:                            final String path = getFullPath(runDirectory, pae
0294:                                    .getExecutable());
0295:
0296:                            // 1) see if path was explicitly loaded by target_attach (this is system dependent)
0297:                            if (!symbolsRead(cb.toString(), path)) {
0298:                                // 2) see if we can validate via /proc (or perhaps other platform specific means)
0299:                                if (validAttachViaSlashProc(programPID, path)) { // Linux or Solaris
0300:                                    if (Utilities.getOperatingSystem() == Utilities.OS_SOLARIS) {
0301:                                        gdb.file_symbol_file(path);
0302:                                    }
0303:                                    setLoading();
0304:                                } else {
0305:                                    // 3) send an "info files" command to gdb. Its response should say what symbols
0306:                                    // are read.
0307:                                    cb = new CommandBuffer();
0308:                                    gdb.info_files(cb);
0309:                                    cb.waitForCompletion();
0310:                                    if (symbolsReadFromInfoFiles(cb.toString(),
0311:                                            path)) {
0312:                                        setLoading();
0313:                                    } else {
0314:                                        final String msg = NbBundle.getMessage(
0315:                                                GdbDebugger.class,
0316:                                                "ERR_AttachValidationFailure"); // NOI18N
0317:                                        SwingUtilities
0318:                                                .invokeLater(new Runnable() {
0319:                                                    public void run() {
0320:                                                        DialogDisplayer
0321:                                                                .getDefault()
0322:                                                                .notify(
0323:                                                                        new NotifyDescriptor.Message(
0324:                                                                                msg));
0325:                                                        setExited();
0326:                                                        finish(false);
0327:                                                    }
0328:                                                });
0329:                                    }
0330:                                }
0331:                            } else {
0332:                                setLoading();
0333:                            }
0334:                        }
0335:                    } else {
0336:                        gdb.file_exec_and_symbols(getProgramName(pae
0337:                                .getExecutable()));
0338:
0339:                        if (Utilities.isWindows()) {
0340:                            if (conType != RunProfile.CONSOLE_TYPE_OUTPUT_WINDOW) {
0341:                                gdb.set_new_console();
0342:                            }
0343:                        }
0344:                        if (pae.getID() == ProjectActionEvent.DEBUG_STEPINTO) {
0345:                            continueAfterFirstStop = false; // step into project
0346:                        }
0347:                        gdb.break_insert(GDB_TMP_BREAKPOINT, "main"); // NOI18N
0348:                        if (Utilities.isWindows()) {
0349:                            // WinAPI apps don't have a "main" function. Use "WinMain" if Windows.
0350:                            gdb.break_insert(GDB_TMP_BREAKPOINT, "WinMain"); // NOI18N
0351:                        }
0352:                        try {
0353:                            gdb.exec_run(pae.getProfile().getArgsFlat());
0354:                        } catch (Exception ex) {
0355:                            ErrorManager.getDefault().notify(ex);
0356:                            lookupProvider.lookupFirst(null, Session.class)
0357:                                    .kill();
0358:                        }
0359:                        if (Utilities.isWindows()) {
0360:                            CommandBuffer cb = new CommandBuffer();
0361:                            gdb.info_threads(cb); // we get the PID from this...
0362:                            String msg = cb.waitForCompletion();
0363:                            if (msg.startsWith("* 1 thread ")) { // NOI18N
0364:                                int pos = msg.indexOf('.');
0365:                                if (pos > 0) {
0366:                                    try {
0367:                                        programPID = Long.valueOf(msg
0368:                                                .substring(11, pos));
0369:                                    } catch (NumberFormatException ex) {
0370:                                        log
0371:                                                .warning("Failed to get PID from \"info threads\""); // NOI18N
0372:                                    }
0373:                                }
0374:                            }
0375:                        } else if (Utilities.getOperatingSystem() != Utilities.OS_MAC) {
0376:                            gdb.info_proc(); // we get the PID from this...
0377:                        }
0378:                    }
0379:                } catch (Exception ex) {
0380:                    if (startupTimer != null) {
0381:                        startupTimer.cancel();
0382:                    }
0383:                    String msg = ex.getLocalizedMessage();
0384:                    if (msg == null || msg.length() == 0) {
0385:                        msg = ex.getMessage();
0386:                    }
0387:                    if (msg == null || msg.length() == 0) {
0388:                        msg = NbBundle.getMessage(GdbDebugger.class,
0389:                                "ERR_UnSpecifiedStartError");
0390:                    }
0391:                    DialogDisplayer.getDefault().notify(
0392:                            new NotifyDescriptor.Message(msg));
0393:                    setExited();
0394:                    finish(false);
0395:                }
0396:            }
0397:
0398:            private String getFullPath(String rundir, String path) {
0399:                if (Utilities.isWindows() && Character.isLetter(path.charAt(0))
0400:                        && path.charAt(1) == ':') {
0401:                    return path;
0402:                } else if (Utilities.isUnix() && path.charAt(0) == '/') {
0403:                    return path;
0404:                } else {
0405:                    return rundir + '/' + path;
0406:                }
0407:            }
0408:
0409:            public void showCurrentSource() {
0410:                final CallStackFrame csf = getCurrentCallStackFrame();
0411:                if (csf != null) {
0412:                    SwingUtilities.invokeLater(new Runnable() {
0413:                        public void run() {
0414:                            // show current line
0415:                            EditorContextBridge.showSource(csf);
0416:                        }
0417:                    });
0418:                }
0419:            }
0420:
0421:            public String[] getThreadsList() {
0422:                if (state.equals(STATE_STOPPED)) {
0423:                    if (threadsList == emptyThreadsList) {
0424:                        while (gdb == null) {
0425:                            try {
0426:                                Thread.sleep(100); // called before session startup had completed...
0427:                            } catch (InterruptedException ex) {
0428:                            }
0429:                        }
0430:                        CommandBuffer cb = new CommandBuffer();
0431:                        gdb.info_threads(cb);
0432:                        String results = cb.waitForCompletion();
0433:                        if (results.length() > 0) {
0434:                            List<String> list = new ArrayList<String>();
0435:                            StringBuilder sb = new StringBuilder();
0436:                            for (String line : results.split("\\\\n")) { // NOI18N
0437:                                if (line.startsWith("    ")) { // NOI18N
0438:                                    sb.append(" "
0439:                                            + line.replace("\\n", "").trim()); // NOI18N
0440:                                } else {
0441:                                    if (sb.length() > 0) {
0442:                                        list.add(sb.toString());
0443:                                        sb.delete(0, sb.length());
0444:                                    }
0445:                                    line = line.trim();
0446:                                    char ch = line.charAt(0);
0447:                                    if (ch == '*' || Character.isDigit(ch)) {
0448:                                        sb.append(line);
0449:                                    }
0450:                                }
0451:                            }
0452:                            if (sb.length() > 0) {
0453:                                list.add(sb.toString());
0454:                            }
0455:                            threadsList = list.toArray(new String[list.size()]);
0456:                            return threadsList;
0457:                        }
0458:                    }
0459:                } else {
0460:                    return new String[] { NbBundle.getMessage(
0461:                            GdbDebugger.class, "CTL_NoThreadInfoWhileRunning") // NOI18N
0462:                    };
0463:                }
0464:                return threadsList;
0465:            }
0466:
0467:            public int getThreadCount() {
0468:                return 1;
0469:            }
0470:
0471:            private void resetThreadInfo() {
0472:                threadsList = emptyThreadsList;
0473:            }
0474:
0475:            private String getProgramName(String program) {
0476:                StringBuilder programName = new StringBuilder();
0477:
0478:                for (int i = 0; i < program.length(); i++) {
0479:                    if (program.charAt(i) == '\\') {
0480:                        programName.append('/');
0481:                    } else {
0482:                        if (program.charAt(i) == ' ') {
0483:                            programName.append("\\ "); // NOI18N
0484:                        } else {
0485:                            programName.append(program.charAt(i));
0486:                        }
0487:                    }
0488:                }
0489:                return programName.toString();
0490:            }
0491:
0492:            /** Get the gdb version */
0493:            public double getGdbVersion() {
0494:                return gdbVersion;
0495:            }
0496:
0497:            public void propertyChange(PropertyChangeEvent evt) {
0498:                if (evt.getPropertyName().equals(PROP_STATE)) {
0499:                    if (evt.getNewValue().equals(STATE_LOADING)) {
0500:                        CommandBuffer cb = new CommandBuffer();
0501:                        shareToken = gdb.info_share();
0502:                        cb.setID(shareToken);
0503:                    } else if (evt.getNewValue().equals(STATE_READY)) {
0504:                        if (Utilities.isWindows()) {
0505:                            gdb.break_insert("dlopen"); // NOI18N
0506:                        } else {
0507:                            gdb.gdb_set("stop-on-solib-events", "1"); // NOI18N
0508:                        }
0509:                        if (continueAfterFirstStop) {
0510:                            continueAfterFirstStop = false;
0511:                            setRunning();
0512:                        } else {
0513:                            gdb.stack_list_frames();
0514:                            setStopped();
0515:                        }
0516:                    } else if (evt.getNewValue() == STATE_STOPPED) {
0517:                        updateLocalVariables(0);
0518:                        gdb.data_list_register_values("");
0519:                    } else if (evt.getNewValue() == STATE_SILENT_STOP) {
0520:                        interrupt();
0521:                    } else if (evt.getNewValue() == STATE_RUNNING
0522:                            && (evt.getOldValue() == STATE_SILENT_STOP || evt
0523:                                    .getOldValue() == STATE_READY)) {
0524:                        gdb.exec_continue();
0525:                    } else if (evt.getNewValue() == STATE_EXITED) {
0526:                        finish(false);
0527:                    }
0528:                } else if (evt.getPropertyName().equals(PROP_CURRENT_THREAD)) {
0529:                    updateCurrentCallStack();
0530:                    updateLocalVariables(0);
0531:                    gdb.data_list_register_values("");
0532:                }
0533:            }
0534:
0535:            private boolean symbolsRead(String results, String exepath) {
0536:                int pos = -1;
0537:                for (String line : results.split("\\\\n")) { // NOI18N
0538:                    if (line.contains("Reading symbols from ") || // NOI18N
0539:                            (Utilities.getOperatingSystem() == Utilities.OS_MAC && line
0540:                                    .contains("Symbols from "))) { // NOI18N
0541:                        if (Utilities.isWindows()
0542:                                && (pos = line.indexOf("/cygdrive/")) != -1) { // NOI18N
0543:                            line = line.substring(0, pos)
0544:                                    + line.substring(pos + 10, pos + 11)
0545:                                            .toUpperCase() + ':'
0546:                                    + line.substring(pos + 11);
0547:                        }
0548:                        String ep = line.substring(21, line.length() - 8);
0549:                        if (ep.equals(exepath)
0550:                                || (Utilities.isWindows() && ep.equals(exepath
0551:                                        + ".exe"))) { // NOI18N
0552:                            return true;
0553:                        }
0554:                    }
0555:                }
0556:                return false;
0557:            }
0558:
0559:            private boolean symbolsReadFromInfoFiles(String results,
0560:                    String exepath) {
0561:                for (String line : results.split("\\\\n")) { // NOI18N
0562:                    if (line.contains("Symbols from ")) { // NOI18N
0563:                        String ep = line.substring(15, line.length() - 3);
0564:                        if (ep.equals(exepath)) { // NOI18N
0565:                            return true;
0566:                        }
0567:                    }
0568:                }
0569:                return false;
0570:            }
0571:
0572:            /**
0573:             * Check that the executable matches the pid. This is system dependent and doesn't necessarily cause
0574:             * an attach failure if we can't validate.
0575:             * 
0576:             * @return true if the project matches the attached to executable
0577:             */
0578:            private boolean validAttachViaSlashProc(long pid, String exepath) {
0579:                if (!Utilities.isWindows()) {
0580:                    String procdir = "/proc/" + Long.toString(pid); // NOI18N
0581:                    File pathfile = new File(procdir, "path/a.out"); // NOI18N - Solaris only?
0582:                    if (!pathfile.exists()) {
0583:                        pathfile = new File(procdir, "exe"); // NOI18N - Linux?
0584:                    }
0585:                    if (pathfile.exists()) {
0586:                        File exefile = new File(exepath);
0587:                        if (exefile.exists()) {
0588:                            String path = getPathFromSymlink(pathfile
0589:                                    .getAbsolutePath());
0590:                            if (path.equals(exefile.getAbsolutePath())) {
0591:                                return true;
0592:                            }
0593:                        }
0594:                    }
0595:                }
0596:                return false;
0597:            }
0598:
0599:            private String getPathFromSymlink(String apath) {
0600:                SymlinkCommand slink = new SymlinkCommand(apath);
0601:                return slink.getPath();
0602:            }
0603:
0604:            private static class SymlinkCommand {
0605:
0606:                private String path;
0607:                private ProcessBuilder pb;
0608:                private String linkline;
0609:
0610:                SymlinkCommand(String path) {
0611:                    this .path = path;
0612:                    linkline = null;
0613:                    File file = new File("/bin/ls"); // NOI18N
0614:
0615:                    if (file.exists()) {
0616:                        List<String> list = new ArrayList<String>();
0617:                        list.add("/bin/ls"); // NOI18N
0618:                        list.add("-l"); // NOI18N
0619:                        list.add(path);
0620:                        pb = new ProcessBuilder(list);
0621:                        pb.redirectErrorStream(true);
0622:                    } else {
0623:                        pb = null;
0624:                    }
0625:                }
0626:
0627:                public String getPath() {
0628:                    if (pb != null) {
0629:                        try {
0630:                            Process process = pb.start();
0631:                            BufferedReader br = new BufferedReader(
0632:                                    new InputStreamReader(process
0633:                                            .getInputStream()));
0634:                            String line = br.readLine(); // just read 1st line...
0635:                            br.close();
0636:                            int pos = line.indexOf("->"); // NOI18N
0637:                            if (pos > 0) {
0638:                                return line.substring(pos + 2).trim();
0639:                            }
0640:                        } catch (IOException ioe) {
0641:                        }
0642:
0643:                    }
0644:                    return linkline;
0645:                }
0646:            }
0647:
0648:            public GdbProxy getGdbProxy() {
0649:                return gdb;
0650:            }
0651:
0652:            /**
0653:             * Finish debugging session. Terminates execution of the inferior program, exits debugger,
0654:             * closes terminal and console.
0655:             * 
0656:             * Note: gdb can be null if we get an exception while starting a debug session.
0657:             */
0658:            public void finish(boolean killTerm) {
0659:                if (!state.equals(STATE_NONE)) {
0660:                    if (killTerm) {
0661:                        firePropertyChange(PROP_KILLTERM, true, false);
0662:                    }
0663:                    if (gdb != null) {
0664:                        if (state.equals(STATE_RUNNING)) {
0665:                            ProjectActionEvent pae = lookupProvider
0666:                                    .lookupFirst(null, ProjectActionEvent.class);
0667:                            gdb.exec_interrupt();
0668:                            if (pae.getID() == DEBUG_ATTACH) {
0669:                                gdb.target_detach();
0670:                            } else {
0671:                                gdb.exec_abort();
0672:                            }
0673:                        }
0674:                        gdb.gdb_exit();
0675:                    }
0676:
0677:                    stackUpdate(new ArrayList<String>());
0678:                    setState(STATE_NONE);
0679:                    programPID = 0;
0680:                    gdbEngineProvider.getDestructor().killEngine();
0681:                    Disassembly.close();
0682:                    GdbTimer.getTimer("Step").reset(); // NOI18N
0683:                }
0684:            }
0685:
0686:            /**
0687:             * The user has pressed the stop-out button while in the topmost function (main). gdb/mi
0688:             * doesn't allow this and we've received an error. Set a temporary breakpoint in exit and
0689:             * continue to the breakpoint. This will perform the action the user requested.
0690:             */
0691:            private void finish_from_main() {
0692:                gdb.break_insert(GDB_TMP_BREAKPOINT, "exit"); // NOI18N
0693:                gdb.exec_continue();
0694:            }
0695:
0696:            public long getProcessID() {
0697:                return programPID;
0698:            }
0699:
0700:            public void unexpectedGdbExit(int rc) {
0701:                String msg;
0702:
0703:                if (rc < 0) {
0704:                    msg = NbBundle.getMessage(GdbDebugger.class,
0705:                            "ERR_UnexpectedGdbExit"); // NOI18N
0706:                } else {
0707:                    msg = NbBundle.getMessage(GdbDebugger.class,
0708:                            "ERR_UnexpectedGdbExitRC", rc); // NOI18N
0709:                }
0710:
0711:                NotifyDescriptor nd = new NotifyDescriptor(
0712:                        msg,
0713:                        NbBundle.getMessage(GdbDebugger.class,
0714:                                "TITLE_UnexpectedGdbFailure"), // NOI18N
0715:                        NotifyDescriptor.DEFAULT_OPTION,
0716:                        NotifyDescriptor.ERROR_MESSAGE,
0717:                        new Object[] { NotifyDescriptor.OK_OPTION },
0718:                        NotifyDescriptor.OK_OPTION);
0719:                DialogDisplayer.getDefault().notify(nd);
0720:                finish(false);
0721:            }
0722:
0723:            /** Sends request to get arguments and local variables */
0724:            private void updateLocalVariables(int frame) {
0725:                synchronized (LOCK) {
0726:                    synchronized (localVariables) {
0727:                        localVariables.clear(); // clear old variables so we can store new ones here
0728:                    }
0729:                    gdb.stack_select_frame(frame);
0730:                    gdb.stack_list_arguments(1, frame, frame);
0731:                    gdb.stack_list_locals(ALL_VALUES);
0732:                }
0733:            }
0734:
0735:            private void updateCurrentCallStack() {
0736:                gdb.stack_list_frames();
0737:            }
0738:
0739:            /** Handle geb responses starting with '^' */
0740:            public void resultRecord(int token, String msg) {
0741:                CommandBuffer cb;
0742:                Integer itok = Integer.valueOf(token);
0743:
0744:                currentToken = token + 1;
0745:                if (msg.startsWith("^done,bkpt=")) { // NOI18N (-break-insert)
0746:                    msg = msg.substring(12, msg.length() - 1);
0747:                    breakpointValidation(token, GdbUtils
0748:                            .createMapFromString(msg));
0749:                    if (getState().equals(STATE_SILENT_STOP)
0750:                            && pendingBreakpointMap.isEmpty()) {
0751:                        setRunning();
0752:                    }
0753:                } else if (msg.startsWith("^done,stack=")) { // NOI18N (-stack-list-frames)
0754:                    if (state.equals(STATE_STOPPED)) { // Ignore data if we've resumed running
0755:                        stackUpdate(GdbUtils.createListFromString((msg
0756:                                .substring(13, msg.length() - 1))));
0757:                    }
0758:                } else if (msg.startsWith("^done,locals=")) { // NOI18N (-stack-list-locals)
0759:                    if (state.equals(STATE_STOPPED)) { // Ignore data if we've resumed running
0760:                        addLocalsToLocalVariables(msg.substring(13));
0761:                    } else {
0762:                        log
0763:                                .finest("GD.resultRecord: Skipping results from -stack-list-locals (not stopped)");
0764:                    }
0765:                } else if (msg.startsWith("^done,stack-args=")) { // NOI18N (-stack-list-arguments)
0766:                    if (state.equals(STATE_STOPPED)) { // Ignore data if we've resumed running
0767:                        addArgsToLocalVariables(msg.substring(17));
0768:                    } else {
0769:                        log
0770:                                .finest("GD.resultRecord: Skipping results from -stack-list-arguments (not stopped)");
0771:                    }
0772:                } else if (msg.startsWith("^done,new-thread-id=")) { // NOI18N (-thread-select)
0773:                    String tid = msg.substring(21, msg.indexOf('"', 22));
0774:                    if (!tid.equals(currentThreadID)) {
0775:                        String otid = currentThreadID;
0776:                        currentThreadID = tid;
0777:                        log
0778:                                .finest("GD.resultRecord: Thread change, firing PROP_CURRENT_THREAD");
0779:                        firePropertyChange(PROP_CURRENT_THREAD, otid,
0780:                                currentThreadID);
0781:                    }
0782:                } else if (msg.startsWith("^done,value=")
0783:                        && msg.contains("auto; currently c")) { // NOI18N
0784:                    if (msg.contains("auto; currently c++")) { // NOI18N
0785:                        cplusplus = true;
0786:                    }
0787:                } else if (msg.startsWith("^done,value=")) { // NOI18N (-data-evaluate-expression)
0788:                    cb = CommandBuffer.getCommandBuffer(itok);
0789:                    if (cb != null) {
0790:                        cb.append(msg.substring(13, msg.length() - 1));
0791:                        cb.done();
0792:                    }
0793:                } else if (msg.startsWith("^done,thread-id=") && // NOI18N
0794:                        Utilities.getOperatingSystem() == Utilities.OS_MAC) {
0795:                    cb = CommandBuffer.getCommandBuffer(itok);
0796:                    if (cb != null) {
0797:                        cb.done();
0798:                    }
0799:                } else if (msg.startsWith(Disassembly.RESPONSE_HEADER)) {
0800:                    disassembly.update(msg);
0801:                } else if (msg.startsWith(Disassembly.REGISTER_NAMES_HEADER)) {
0802:                    disassembly.updateRegNames(msg);
0803:                } else if (msg.startsWith(Disassembly.REGISTER_VALUES_HEADER)) {
0804:                    disassembly.updateRegValues(msg);
0805:                } else if (msg.equals("^done")
0806:                        && getState().equals(STATE_SILENT_STOP)) { // NOI18N
0807:                    log.fine("GD.resultRecord[" + token
0808:                            + "]: Got \"^done\" in silent stop");
0809:                    setRunning();
0810:                } else if (msg.equals("^done")) { // NOI18N
0811:                    cb = CommandBuffer.getCommandBuffer(itok);
0812:                    if (cb != null) {
0813:                        cb.done();
0814:                        if (token == shareToken) {
0815:                            lastShare = cb.toString();
0816:                        }
0817:                    } else if (pendingBreakpointMap.get(itok) != null) {
0818:                        breakpointValidation(token, null);
0819:                    }
0820:                } else if (msg.startsWith("^running")
0821:                        && getState().equals(STATE_STOPPED)) { // NOI18N
0822:                    setRunning();
0823:                } else if (msg.startsWith("^error,msg=")) { // NOI18N
0824:                    msg = msg.substring(11);
0825:                    cb = CommandBuffer.getCommandBuffer(itok);
0826:
0827:                    if (cb != null) {
0828:                        cb.error(msg);
0829:                    } else if (msg.equals("\"Can't attach to process.\"")) { // NOI18N
0830:                        DialogDisplayer.getDefault().notify(
0831:                                new NotifyDescriptor.Message(NbBundle
0832:                                        .getMessage(GdbDebugger.class,
0833:                                                "ERR_CantAttach"))); // NOI18N
0834:                        (lookupProvider.lookupFirst(null, Session.class))
0835:                                .kill();
0836:                    } else if (msg.startsWith("\"No symbol ")
0837:                            && msg.endsWith(" in current context.\"")) { // NOI18N
0838:                        String type = msg.substring(13, msg.length() - 23);
0839:                        log.warning("Failed type lookup for " + type);
0840:                    } else if (msg
0841:                            .equals("\"\\\"finish\\\" not meaningful in the outermost frame.\"")) { // NOI18N
0842:                        finish_from_main();
0843:                    } else if (msg.contains("(corrupt stack?)")) { // NOI18N
0844:                        DialogDisplayer.getDefault().notify(
0845:                                new NotifyDescriptor.Message(NbBundle
0846:                                        .getMessage(GdbDebugger.class,
0847:                                                "ERR_CorruptedStack"))); // NOI18N
0848:                        (lookupProvider.lookupFirst(null, Session.class))
0849:                                .kill();
0850:                    } else if (msg.contains("error reading line numbers")) { // NOI18N
0851:                        DialogDisplayer.getDefault().notify(
0852:                                new NotifyDescriptor.Message(NbBundle
0853:                                        .getMessage(GdbDebugger.class,
0854:                                                "ERR_CantReadLineNumbers"))); // NOI18N
0855:                    } else if (msg.contains("No symbol table is loaded")) { // NOI18N
0856:                        DialogDisplayer.getDefault().notify(
0857:                                new NotifyDescriptor.Message(NbBundle
0858:                                        .getMessage(GdbDebugger.class,
0859:                                                "ERR_NoSymbolTable"))); // NOI18N
0860:                        (lookupProvider.lookupFirst(null, Session.class))
0861:                                .kill();
0862:                    } else if (msg.contains("Cannot access memory at address")) { // NOI18N
0863:                        // ignore - probably dereferencing an uninitialized pointer
0864:                    } else if (msg
0865:                            .contains("mi_cmd_break_insert: Garbage following <location>")) { // NOI18N
0866:                        // ignore - probably a breakpoint from another project
0867:                    } else if (msg.contains("Undefined mi command: ")
0868:                            && msg.contains("(missing implementation")) { // NOI18N
0869:                        // ignore - gdb/mi defines commands which haven't been implemented yet
0870:                    } else if (pendingBreakpointMap.remove(Integer
0871:                            .valueOf(token)) != null) {
0872:                        if (pendingBreakpointMap.isEmpty()
0873:                                && state.equals(STATE_LOADING)) {
0874:                            setReady();
0875:                        }
0876:                    } else if (!state.equals(STATE_NONE)) {
0877:                        // ignore errors after we've terminated (they could have been in the input queue)
0878:                        log.warning("Unexpected gdb error: " + msg);
0879:                    }
0880:                }
0881:            }
0882:
0883:            public void fireDisUpdate() {
0884:                firePropertyChange(DIS_UPDATE, 0, 1);
0885:            }
0886:
0887:            /** Handle gdb responses starting with '*' */
0888:            public void execAsyncOutput(int token, String msg) {
0889:                if (msg.startsWith("*stopped")) { // NOI18N
0890:                    Map<String, String> map = GdbUtils.createMapFromString(msg
0891:                            .substring(9));
0892:                    stopped(token, map);
0893:                }
0894:            }
0895:
0896:            /** Handle gdb responses starting with '~' */
0897:            public void consoleStreamOutput(int token, String omsg) {
0898:                CommandBuffer cb = CommandBuffer.getCommandBuffer(Integer
0899:                        .valueOf(token));
0900:                String msg;
0901:
0902:                if (omsg.endsWith("\\n")) { // NOI18N
0903:                    msg = omsg.substring(0, omsg.length() - 2);
0904:                } else {
0905:                    msg = omsg;
0906:                }
0907:                if (cb != null) {
0908:                    cb.append(omsg);
0909:                } else if (msg.startsWith("GNU gdb ") && startupTimer != null) { // NOI18N
0910:                    // Cancel the startup timer - we've got our first response from gdb
0911:                    startupTimer.cancel();
0912:                    startupTimer = null;
0913:
0914:                    // Now process the version information
0915:                    int first = msg.indexOf('.');
0916:                    int last = msg.lastIndexOf('.');
0917:                    try {
0918:                        if (first == last) {
0919:                            gdbVersion = Double.parseDouble(msg.substring(8));
0920:                        } else {
0921:                            gdbVersion = Double.parseDouble(msg.substring(8,
0922:                                    last));
0923:                        }
0924:                    } catch (NumberFormatException ex) {
0925:                    }
0926:                    if (msg.contains("cygwin")) { // NOI18N
0927:                        cygwin = true;
0928:                    }
0929:                } else if (msg.startsWith("Breakpoint ")
0930:                        && msg.contains(" at 0x")) { // NOI18N
0931:                    // Due to a gdb bug (6.6 and earlier) we use a "break" command for multi-byte filenames
0932:                    int pos = msg.indexOf(' ', 12);
0933:                    String num = msg.substring(11, pos);
0934:                    Map<String, String> map = new HashMap<String, String>();
0935:                    map.put("number", num); // NOI18N
0936:                    breakpointValidation(token, map);
0937:                    if (getState().equals(STATE_SILENT_STOP)
0938:                            && pendingBreakpointMap.isEmpty()) {
0939:                        setRunning();
0940:                    }
0941:                } else if (msg.startsWith("Copyright ")
0942:                        || // NOI18N
0943:                        msg.startsWith("GDB is free software,")
0944:                        || // NOI18N
0945:                        msg.startsWith("welcome to change it and")
0946:                        || // NOI18N
0947:                        msg.contains("show copying")
0948:                        || // NOI18N
0949:                        msg
0950:                                .startsWith("There is absolutely no warranty for GDB")
0951:                        || // NOI18N
0952:                        msg.startsWith("Source directories searched: ") || // NOI18N
0953:                        msg.startsWith("This GDB was configured as")) { // NOI18N
0954:                    // do nothing (but don't print these expected messages)
0955:                } else if (programPID == 0 && msg.startsWith("process ")) { // NOI18N (Unix method)
0956:                    int pos = msg.indexOf(' ', 8);
0957:                    String text;
0958:                    if (pos > 0) {
0959:                        text = msg.substring(8, pos);
0960:                    } else {
0961:                        text = msg.substring(8);
0962:                    }
0963:                    try {
0964:                        programPID = Long.parseLong(text);
0965:                    } catch (NumberFormatException ex) {
0966:                        log.warning("Failed to get PID from \"info proc\""); // NOI18N
0967:                    }
0968:                } else if (programPID == 0) {
0969:                    if (msg.startsWith("* 1 thread ")) { // NOI18N
0970:                        int pos = msg.indexOf('.');
0971:                        if (pos > 0) {
0972:                            try {
0973:                                programPID = Long.valueOf(msg
0974:                                        .substring(11, pos));
0975:                            } catch (NumberFormatException ex) {
0976:                                log
0977:                                        .warning("Failed to get PID from \"info threads\""); // NOI18N
0978:                            }
0979:                        }
0980:                    } else if (msg.startsWith("[Switching to process ")) { // NOI18N
0981:                        int pos = msg.indexOf(' ', 22);
0982:                        if (pos > 0) {
0983:                            try {
0984:                                programPID = Long.valueOf(msg
0985:                                        .substring(22, pos));
0986:                            } catch (NumberFormatException ex) {
0987:                            }
0988:                        }
0989:                    }
0990:                } else if (msg
0991:                        .startsWith("Stopped due to shared library event")) { // NOI18N
0992:                    dlopenPending = true;
0993:                }
0994:            }
0995:
0996:            /** Handle gdb responses starting with '&' */
0997:            public void logStreamOutput(String msg) {
0998:                if (msg.startsWith("&\"No source file named ")) { // NOI18N
0999:                    breakpointValidation(currentToken, msg.substring(2, msg
1000:                            .length() - 3));
1001:                } else if (msg.startsWith("&\"info proc")
1002:                        || // NOI18N
1003:                        msg.startsWith("&\"info threads")
1004:                        || // NOI18N
1005:                        msg.startsWith("&\"directory ")
1006:                        || // NOI18N
1007:                        msg.startsWith("&\"set new-console")
1008:                        || // NOI18N
1009:                        msg.startsWith("&\"whatis ")
1010:                        || // NOI18N
1011:                        msg
1012:                                .startsWith("&\"warning: Temporarily disabling breakpoints for unloaded shared library")
1013:                        || // NOI18N
1014:                        msg.contains("/usr/lib/ld.so")) { // NOI18N
1015:                    // ignore these messages
1016:                } else {
1017:                    log.finest("GD.logStreamOutput: " + msg); // NOI18N
1018:                }
1019:            }
1020:
1021:            /** Handle gdb responses starting with '+' */
1022:            public void statusAsyncOutput(int token, String msg) {
1023:                log.finest("GD.statusAsyncOutput[" + token + "]: " + msg); // NOI18N
1024:            }
1025:
1026:            /** Handle gdb responses starting with '=' */
1027:            public void notifyAsyncOutput(int token, String msg) {
1028:                log.finest("GD.notifyAsyncOutput[" + token + "]: " + msg); // NOI18N
1029:            }
1030:
1031:            /** Handle gdb responses starting with '@' */
1032:            public void targetStreamOutput(String msg) {
1033:                log.finest("GD.targetStreamOutput: " + msg); // NOI18N
1034:            }
1035:
1036:            /**
1037:             * Handle gdb output. The only tricking thing here is that most versions of gdb on
1038:             * Solaris output some proc flags to stdout. So for Solaris, I skip the 1st output
1039:             * if it starts with "PR_" (the proc flag header).
1040:             */
1041:            public void output(String msg) {
1042:                if (iotab != null) {
1043:                    if (!(firstOutput
1044:                            && Utilities.getOperatingSystem() == Utilities.OS_SOLARIS && msg
1045:                            .startsWith("PR_"))) { // NOI18N
1046:                        firstOutput = false;
1047:                        iotab.getOut().println(msg);
1048:                    }
1049:                }
1050:            }
1051:
1052:            private void addArgsToLocalVariables(String info) {
1053:                int pos;
1054:                if (info.startsWith("[frame={level=")
1055:                        && (pos = info.indexOf(",args=[")) > 0
1056:                        && info.endsWith("]}]")) { // NOI18N
1057:                    info = info.substring(pos + 7, info.length() - 3);
1058:                } else if (Utilities.getOperatingSystem() == Utilities.OS_MAC
1059:                        && info.startsWith("{frame={level=")
1060:                        && (pos = info.indexOf(",args={")) > 0
1061:                        && info.endsWith("}}}")) { // NOI18N
1062:                    info = info.substring(pos + 7, info.length() - 3);
1063:                }
1064:                Collection<GdbVariable> v = GdbUtils.createArgumentList(info);
1065:                if (!v.isEmpty()) {
1066:                    log
1067:                            .finest("GD.addArgsToLocalVariables: Starting to add Args to localVariables"); // NOI18N
1068:                    synchronized (localVariables) {
1069:                        localVariables.addAll(v);
1070:                    }
1071:                    log.finest("GD.addArgsToLocalVariables: Added " + v.size()
1072:                            + " args");
1073:                }
1074:            }
1075:
1076:            private void addLocalsToLocalVariables(String info) {
1077:                Collection<GdbVariable> v = GdbUtils.createLocalsList(info
1078:                        .substring(1, info.length() - 1));
1079:                if (!v.isEmpty()) {
1080:                    log
1081:                            .finest("GD.addLocalsToLocalVariables: Starting to add locals to localVariables"); // NOI18N
1082:                    synchronized (localVariables) {
1083:                        for (GdbVariable var : v) {
1084:                            if (!localVariables.contains(var)) {
1085:                                localVariables.add(var);
1086:                            }
1087:                        }
1088:                    }
1089:                    log.finest("GD.addLocalsToLocalVariables: Added "
1090:                            + v.size() + " locals");
1091:                }
1092:            }
1093:
1094:            public String updateVariable(String name, String value) {
1095:                CommandBuffer cb = new CommandBuffer();
1096:                gdb.data_evaluate_expression(cb, name + '=' + value);
1097:                return cb.waitForCompletion();
1098:            }
1099:
1100:            // currently not called - should do more than set state (see JPDADebuggerImpl)
1101:            public void suspend() {
1102:                setState(STATE_STOPPED);
1103:            }
1104:
1105:            /**
1106:             * Interrupts execution of the inferior program. 
1107:             * This method is called when "Pause" button is pressed.
1108:             *
1109:             * @return null if action is accepted, otherwise return error message
1110:             */
1111:            public void interrupt() {
1112:                gdb.exec_interrupt();
1113:            }
1114:
1115:            /**
1116:             * Send a kill command to the debuggee.
1117:             *
1118:             * @param signal The signal to send (as defined by "kill -l")
1119:             */
1120:            public void kill(int signal) {
1121:                if (programPID > 0) { // Never send a kill if PID is 0
1122:                    kill(signal, programPID);
1123:                }
1124:            }
1125:
1126:            /**
1127:             * Send a kill command to the debuggee.
1128:             *
1129:             * @param signal The signal to send (as defined by "kill -l")
1130:             * @param pid The process ID to send the signal to
1131:             */
1132:            public void kill(int signal, long pid) {
1133:                if (pid > 0) {
1134:                    ArrayList<String> killcmd = new ArrayList<String>();
1135:                    File f;
1136:
1137:                    if (Utilities.isWindows()) {
1138:                        f = InstalledFileLocator.getDefault().locate(
1139:                                "bin/GdbKillProc.exe", null, false); // NOI18N
1140:                        if (f.exists()) {
1141:                            killcmd.add(f.getAbsolutePath());
1142:                        }
1143:                    } else {
1144:                        f = new File("/usr/bin/kill"); // NOI18N
1145:                        if (f.exists()) {
1146:                            killcmd.add(f.getAbsolutePath());
1147:                        } else {
1148:                            f = new File("/bin/kill"); // NOI18N
1149:                            if (f.exists()) {
1150:                                killcmd.add(f.getAbsolutePath());
1151:                            }
1152:                        }
1153:                    }
1154:                    if (killcmd.size() > 0) {
1155:                        killcmd.add("-s"); // NOI18N
1156:                        killcmd.add((Utilities.isMac() && signal == 2) ? "TRAP"
1157:                                : Integer.toString(signal)); // NOI18N
1158:                        killcmd.add(Long.toString(pid));
1159:                        ProcessBuilder pb = new ProcessBuilder(killcmd);
1160:                        try {
1161:                            pb.start();
1162:                        } catch (IOException ex) {
1163:                            ex.printStackTrace();
1164:                        }
1165:                        gdb.getLogger().logMessage(
1166:                                "External Command: " + killcmd.toString()); // NOI18N
1167:                    }
1168:                }
1169:            }
1170:
1171:            /**
1172:             * Resumes execution of the inferior program, until a
1173:             * breakpoint is encountered, or until the inferior exits.
1174:             */
1175:            public void resume() {
1176:                setState(STATE_RUNNING);
1177:                gdb.exec_continue();
1178:            }
1179:
1180:            /**
1181:             * Resumes execution of the inferior program, stopping when the beginning of the
1182:             * next source line is reached, if the next source line is not a function call.
1183:             * If it is, stop at the first instruction of the called function.
1184:             */
1185:            public void stepInto() {
1186:                GdbTimer.getTimer("Step").start("Step1", 10); // NOI18N
1187:                setState(STATE_RUNNING);
1188:                gdb.exec_step();
1189:            }
1190:
1191:            /**
1192:             * Resumes execution of the inferior program, stopping
1193:             * when the beginning of the next source line is reached.
1194:             */
1195:            public void stepOver() {
1196:                setState(STATE_RUNNING);
1197:                gdb.exec_next();
1198:            }
1199:
1200:            /**
1201:             */
1202:            public void stepI() {
1203:                setState(STATE_RUNNING);
1204:                gdb.exec_instruction();
1205:            }
1206:
1207:            /**
1208:             * Resumes execution of the inferior program until
1209:             * the top function is exited.
1210:             * Note: Slight cemantic change in NB 6.1. In NB 6.0 the current
1211:             * frame was stepped out of. In NB 6.1, the top frame is stepped
1212:             * out of. This makes the behavior match the Java debugger in NB.
1213:             */
1214:            public void stepOut() {
1215:                if (callstack.size() > 0 || isValidStackFrame(callstack.get(1))) {
1216:                    setState(STATE_RUNNING);
1217:                    gdb.stack_select_frame(0);
1218:                    gdb.exec_finish();
1219:                } else {
1220:                    DialogDisplayer.getDefault().notify(
1221:                            new NotifyDescriptor.Message(NbBundle.getMessage(
1222:                                    GdbDebugger.class,
1223:                                    "ERR_InvalidCallStackFrame"))); // NOI18N
1224:                }
1225:            }
1226:
1227:            /**
1228:             * Returns current state of gdb debugger.
1229:             *
1230:             * @return current state of gdb debugger
1231:             */
1232:            public String getState() {
1233:                return state;
1234:            }
1235:
1236:            private void setState(String state) {
1237:                if (state.equals(this .state)) {
1238:                    return;
1239:                }
1240:                String oldState = this .state;
1241:                this .state = state;
1242:                firePropertyChange(PROP_STATE, oldState, state);
1243:            }
1244:
1245:            public void setStarting() {
1246:                setState(STATE_STARTING);
1247:            }
1248:
1249:            public void setLoading() {
1250:                setState(STATE_LOADING);
1251:            }
1252:
1253:            public void setReady() {
1254:                setState(STATE_READY);
1255:            }
1256:
1257:            public void setRunning() {
1258:                setState(STATE_RUNNING);
1259:            }
1260:
1261:            public void setStopped() {
1262:                setState(STATE_STOPPED);
1263:            }
1264:
1265:            public void setSilentStop() {
1266:                setState(STATE_SILENT_STOP);
1267:            }
1268:
1269:            public void setExited() {
1270:                setState(STATE_EXITED);
1271:            }
1272:
1273:            public Boolean evaluateIn(Expression expression, final Object frame) {
1274:                return Boolean.FALSE;
1275:            }
1276:
1277:            /**
1278:             * Helper method that fires JPDABreakpointEvent on JPDABreakpoints.
1279:             *
1280:             * @param breakpoint a breakpoint to be changed
1281:             * @param event a event to be fired
1282:             */
1283:            public void fireBreakpointEvent(GdbBreakpoint breakpoint,
1284:                    GdbBreakpointEvent event) {
1285:                breakpoint.fireGdbBreakpointChange(event);
1286:            }
1287:
1288:            /**
1289:             * Called from GdbProxy when the target debuggee is stopped.
1290:             * 
1291:             * Note: The token parameter isn't used but is useful for conditional
1292:             * breakpoints during debugging...
1293:             *
1294:             * @param token The token responsible for this stop
1295:             * @param reason A reason why program is stopped
1296:             */
1297:            public void stopped(int token, Map<String, String> map) {
1298:                String reason = map.get("reason"); // NOI18N
1299:
1300:                if (state.equals(STATE_STARTING)) {
1301:                    setLoading();
1302:                    return;
1303:                }
1304:                if (!state.equals(STATE_RUNNING)) {
1305:                    log
1306:                            .warning("GdbDebugger.stopped while not in STATE_RUNNING");
1307:                    return;
1308:                }
1309:
1310:                log.finest("GD.stopped[" + GdbUtils.threadId() + "]:\n"); // NOI18N
1311:                resetThreadInfo();
1312:                if (reason != null) {
1313:                    setCurrentCallStackFrameNoFire(null); // will be reset when stack updates
1314:                    if (reason.equals("exited-normally")) { // NOI18N
1315:                        setExited();
1316:                        finish(false);
1317:                    } else if (reason.equals("breakpoint-hit")) { // NOI18N
1318:                        String tid = map.get("thread-id"); // NOI18N
1319:                        if (tid != null && !tid.equals(currentThreadID)) {
1320:                            currentThreadID = tid;
1321:                        }
1322:                        BreakpointImpl impl = getBreakpointList().get(
1323:                                map.get("bkptno")); // NOI18N
1324:                        if (impl == null) {
1325:                            String frame = map.get("frame"); // NOI18N
1326:                            if (frame != null && frame.contains("dlopen")) { // NOI18N
1327:                                dlopenPending = true;
1328:                                gdb.exec_finish();
1329:                                return;
1330:                            }
1331:                        } else {
1332:                            GdbBreakpoint breakpoint = impl.getBreakpoint();
1333:                            if (breakpoint.getSuspend() == GdbBreakpoint.SUSPEND_NONE) {
1334:                                fireBreakpointEvent(
1335:                                        breakpoint,
1336:                                        new GdbBreakpointEvent(
1337:                                                breakpoint,
1338:                                                this ,
1339:                                                GdbBreakpointEvent.CONDITION_NONE,
1340:                                                null));
1341:                                gdb.exec_continue();
1342:                            } else {
1343:                                updateCurrentCallStack();
1344:                                fireBreakpointEvent(
1345:                                        breakpoint,
1346:                                        new GdbBreakpointEvent(
1347:                                                breakpoint,
1348:                                                this ,
1349:                                                GdbBreakpointEvent.CONDITION_NONE,
1350:                                                null));
1351:                                setStopped();
1352:                            }
1353:                        }
1354:                        if (dlopenPending) {
1355:                            dlopenPending = false;
1356:                            checkSharedLibs(false);
1357:                        }
1358:                        GdbTimer.getTimer("Startup").stop("Startup1"); // NOI18N
1359:                        GdbTimer.getTimer("Startup").report("Startup1"); // NOI18N
1360:                        GdbTimer.getTimer("Startup").free(); // NOI18N
1361:                        GdbTimer.getTimer("Stop").mark("Stop1");// NOI18N
1362:                    } else if (reason.equals("exited-signalled")) { // NOI18N
1363:                        String signal = map.get("signal-name"); // NOI18N
1364:                        if (signal != null) {
1365:                            DialogDisplayer.getDefault().notify(
1366:                                    new NotifyDescriptor.Message(NbBundle
1367:                                            .getMessage(GdbDebugger.class,
1368:                                                    "ERR_ExitedFromSignal",
1369:                                                    signal))); // NOI18N
1370:                            setExited();
1371:                            finish(false);
1372:                        }
1373:                    } else if (reason.equals("end-stepping-range")) { // NOI18N
1374:                        gdb.stack_list_frames();
1375:                        setStopped();
1376:                        if (GdbTimer.getTimer("Step").getSkipCount() == 0) { // NOI18N
1377:                            GdbTimer.getTimer("Step").stop("Step1");// NOI18N
1378:                            GdbTimer.getTimer("Step").report("Step1");// NOI18N
1379:                        }
1380:                    } else if (reason.equals("signal-received")) { // NOI18N
1381:                        if (getState().equals(STATE_RUNNING)) {
1382:                            String tid = map.get("thread-id"); // NOI18N
1383:                            if (tid != null && !tid.equals(currentThreadID)) {
1384:                                currentThreadID = tid;
1385:                            }
1386:                            gdb.stack_list_frames();
1387:                            setStopped();
1388:                        }
1389:                    } else if (reason.equals("function-finished")
1390:                            && dlopenPending) { // NOI18N
1391:                        dlopenPending = false;
1392:                        checkSharedLibs(false);
1393:                    } else {
1394:                        if (!reason.startsWith("exited")) { // NOI18N
1395:                            gdb.stack_list_frames();
1396:                            setStopped();
1397:                        } else {
1398:                            setStopped();
1399:                            // Disable debugging buttons
1400:                            setExited();
1401:                        }
1402:                    }
1403:                } else if (dlopenPending) {
1404:                    dlopenPending = false;
1405:                    checkSharedLibs(true);
1406:                } else {
1407:                    gdb.stack_list_frames();
1408:                    setStopped();
1409:                }
1410:            }
1411:
1412:            /**
1413:             * Compare the current set of shared libraries with the previous set. Run in a
1414:             * different thread because we're probably being called from the GdbReaderRP
1415:             * thread and CommandBuffer.waitForCompletion() doesn't work on that thread.
1416:             */
1417:            private void checkSharedLibs(final boolean continueRunning) {
1418:                RequestProcessor.getDefault().post(new Runnable() {
1419:                    public void run() {
1420:                        CommandBuffer cb = new CommandBuffer();
1421:                        gdb.info_share(cb);
1422:                        String share = cb.waitForCompletion();
1423:                        if (share.length() > 0 && !share.equals(lastShare)) {
1424:                            if (share.length() > lastShare.length()) {
1425:                                // dlopened a shared library
1426:                                log
1427:                                        .fine("GD.checkSharedLibs: Added a shared library");
1428:                                firePropertyChange(PROP_SHARED_LIB_LOADED,
1429:                                        lastShare, share);
1430:                                lastShare = share;
1431:                            } else {
1432:                                // dlclosed a shared library
1433:                                log
1434:                                        .fine("GD.checkSharedLibs: Closed a shared library");
1435:                            }
1436:                        }
1437:                        if (continueRunning) {
1438:                            gdb.exec_continue();
1439:                        }
1440:                    }
1441:                });
1442:            }
1443:
1444:            private void threadsViewInit() {
1445:                Properties props = Properties.getDefault().getProperties(
1446:                        "debugger").getProperties("views"); // NOI18N
1447:                props.getProperties("ThreadState").setBoolean("visible", false); // NOI18N
1448:                props.getProperties("ThreadSuspended").setBoolean("visible",
1449:                        false); // NOI18N
1450:            }
1451:
1452:            public void addPendingBreakpoint(int token, BreakpointImpl impl) {
1453:                pendingBreakpointMap.put(new Integer(token), impl);
1454:            }
1455:
1456:            /**
1457:             * Callback method for break_insert Gdb/MI command.
1458:             *
1459:             * @param reason a reason why program is stopped
1460:             */
1461:            private void breakpointValidation(int token, Object o) {
1462:                BreakpointImpl impl = pendingBreakpointMap.get(Integer
1463:                        .valueOf(token));
1464:
1465:                if (impl != null) { // impl is null for the temporary bp set at main during startup
1466:                    if (o instanceof  String) {
1467:                        impl.addError((String) o);
1468:                    } else if (o instanceof  Map || o == null) {
1469:                        pendingBreakpointMap.remove(Integer.valueOf(token));
1470:                        impl.completeValidation((Map<String, String>) o);
1471:                        if (o != null && impl.getBreakpoint().isEnabled()) {
1472:                            Map<String, String> map = (Map) o;
1473:                            String fullname = map.get("fullname"); // NOI18N
1474:                            String file = map.get("file"); // NOI18N
1475:                            String line = map.get("line"); // NOI18N
1476:                            if (firstBPfullname != null
1477:                                    && firstBPfullname.equals(fullname)
1478:                                    && firstBPline != null
1479:                                    && firstBPline.equals(line)) {
1480:                                continueAfterFirstStop = false;
1481:                            } else if (Utilities.getOperatingSystem() == Utilities.OS_MAC
1482:                                    && firstBPfile != null
1483:                                    && firstBPfile.equals(file)
1484:                                    && firstBPline != null
1485:                                    && firstBPline.equals(line)) {
1486:                                continueAfterFirstStop = false;
1487:                            }
1488:                        }
1489:                    }
1490:                    if (pendingBreakpointMap.isEmpty()
1491:                            && state.equals(STATE_LOADING)) {
1492:                        setReady();
1493:                    }
1494:                } else if (o instanceof  Map) { // first breakpoint
1495:                    Map<String, String> map = (Map) o;
1496:                    String number = map.get("number"); // NOI18N
1497:                    String fullname = map.get("fullname"); // NOI18N
1498:                    String file = map.get("file"); // NOI18N
1499:                    String line = map.get("line"); // NOI18N
1500:                    String func = map.get("func"); // NOI18N
1501:                    if (number != null && ((number.equals("1")) || // NOI18N
1502:                            (number.equals("2") && func != null
1503:                                    && func.equals("WinMain") && Utilities
1504:                                    .isWindows()))) { // NOI18N
1505:                        firstBPfullname = fullname;
1506:                        firstBPfile = file;
1507:                        firstBPline = line;
1508:                    }
1509:                }
1510:            }
1511:
1512:            /**
1513:             * This utility method helps to start a new Cnd debugger session. 
1514:             *
1515:             * @param hostName a name of computer to attach to
1516:             * @param portNumber a port number
1517:             */
1518:            public static void attach(String pid, ProjectInformation pinfo)
1519:                    throws DebuggerStartException {
1520:                Project project = pinfo.getProject();
1521:                ConfigurationDescriptorProvider cdp = (ConfigurationDescriptorProvider) project
1522:                        .getLookup().lookup(
1523:                                ConfigurationDescriptorProvider.class);
1524:                if (cdp != null) {
1525:                    MakeConfigurationDescriptor mcd = (MakeConfigurationDescriptor) cdp
1526:                            .getConfigurationDescriptor();
1527:                    MakeConfiguration conf = (MakeConfiguration) mcd.getConfs()
1528:                            .getActive();
1529:                    MakeArtifact ma = new MakeArtifact(mcd, conf);
1530:                    String runDirectory = conf.getProfile().getRunDirectory()
1531:                            .replace("\\", "/"); // NOI18N
1532:                    String path = runDirectory + '/' + ma.getOutput();
1533:                    if (isExecutable(conf, path)) {
1534:                        ProjectActionEvent pae = new ProjectActionEvent(
1535:                                project, DEBUG_ATTACH, pinfo.getDisplayName(),
1536:                                path, conf, null, false);
1537:                        DebuggerEngine[] es = DebuggerManager
1538:                                .getDebuggerManager().startDebugging(
1539:                                        DebuggerInfo.create(
1540:                                                SESSION_PROVIDER_ID,
1541:                                                new Object[] { pae,
1542:                                                        Long.valueOf(pid) }));
1543:                        if (es == null) {
1544:                            throw new DebuggerStartException(
1545:                                    new InternalError());
1546:                        }
1547:                    } else {
1548:                        final String msg = NbBundle.getMessage(
1549:                                GdbDebugger.class,
1550:                                "ERR_AttachValidationFailure"); // NOI18N
1551:                        SwingUtilities.invokeLater(new Runnable() {
1552:                            public void run() {
1553:                                DialogDisplayer.getDefault().notify(
1554:                                        new NotifyDescriptor.Message(msg));
1555:                            }
1556:                        });
1557:                    }
1558:                }
1559:            }
1560:
1561:            /**
1562:             * Use various heuristics to verify that either the project produces an executable
1563:             * or that the path is to an executable.
1564:             * 
1565:             * @param conf A Makefile project configuration
1566:             * @param path The absolute pathname to the file
1567:             * @return true iff the input parameters get an executable
1568:             */
1569:            private static boolean isExecutable(MakeConfiguration conf,
1570:                    String path) {
1571:                File file;
1572:
1573:                if (conf.isApplicationConfiguration()) {
1574:                    return true;
1575:                } else if (conf.isMakefileConfiguration()) {
1576:                    if (Utilities.isWindows()) {
1577:                        if (path.endsWith(".dll")) { // NOI18N
1578:                            return false;
1579:                        } else if (!path.endsWith(".exe")) { // NOI18N
1580:                            path = path + ".exe"; // NOI18N
1581:                        }
1582:                        file = new File(path);
1583:                        if (file.exists()) {
1584:                            return true;
1585:                        }
1586:                    }
1587:                    file = new File(path);
1588:                    if (file.exists()) {
1589:                        String mime_type = FileUtil.getMIMEType(FileUtil
1590:                                .toFileObject(file));
1591:                        if (mime_type != null
1592:                                && mime_type.startsWith("application/x-exe")) { // NOI18N
1593:                            return true;
1594:                        }
1595:                    }
1596:                    return false;
1597:                } else {
1598:                    return false;
1599:                }
1600:            }
1601:
1602:            /**
1603:             *  Called when GdbProxy receives the results of a -stack-list-frames command.
1604:             */
1605:            private void stackUpdate(List<String> stack) {
1606:                synchronized (callstack) {
1607:                    callstack.clear();
1608:
1609:                    for (int i = 0; i < stack.size(); i++) {
1610:                        String line = stack.get(i);
1611:                        Map<String, String> map = GdbUtils
1612:                                .createMapFromString(line.substring(6));
1613:
1614:                        String func = map.get("func"); // NOI18N
1615:                        String file = map.get("file"); // NOI18N
1616:                        String fullname = map.get("fullname"); // NOI18N
1617:                        String lnum = map.get("line"); // NOI18N
1618:                        String addr = map.get("addr"); // NOI18N
1619:                        if (fullname == null && file != null) {
1620:                            if (file.charAt(0) == '/') {
1621:                                fullname = file;
1622:                                log
1623:                                        .finest("GD.stackUpdate: Setting fullname from file"); // NOI18N
1624:                            } else {
1625:                                fullname = runDirectory + file;
1626:                                log
1627:                                        .finest("GD.stackUpdate: Setting fullname from runDirectory + file"); // NOI18N
1628:                            }
1629:                        }
1630:
1631:                        callstack.add(i, new CallStackFrame(this , func, file,
1632:                                fullname, lnum, addr, i));
1633:                    }
1634:                }
1635:
1636:                if (!stack.isEmpty()) {
1637:                    pcs.firePropertyChange(PROP_CURRENT_CALL_STACK_FRAME, 0, 1);
1638:                }
1639:            }
1640:
1641:            public void setCurrentThread(String tline) {
1642:                if (tline.length() > 0) {
1643:                    if (Character.isDigit(tline.charAt(0))) {
1644:                        int idx = tline.indexOf(' ');
1645:                        if (idx > 0) {
1646:                            resetThreadInfo();
1647:                            gdb.thread_select(tline.substring(0, idx));
1648:                        }
1649:                    }
1650:                }
1651:            }
1652:
1653:            /**
1654:             * Returns list of cached local variables for this debugger. This typically gets
1655:             * called from an evaluator thread. If we don't have the type, it should be coming
1656:             * on the GdbReaderRP thread so we wait for it.
1657:             *
1658:             * @return list of local variables
1659:             */
1660:            public List<GdbVariable> getLocalVariables() {
1661:                assert !(Thread.currentThread().getName().equals("GdbReaderRP"));
1662:                synchronized (localVariables) {
1663:                    return (List<GdbVariable>) localVariables.clone();
1664:                }
1665:            }
1666:
1667:            public String evaluateToolTip(String expression) {
1668:                CommandBuffer cb = new CommandBuffer();
1669:
1670:                if (expression.indexOf('(') != -1) {
1671:                    suspendBreakpointsAndSignals();
1672:                    gdb.data_evaluate_expression(cb, '"' + expression + '"'); // NOI18N
1673:                    restoreBreakpointsAndSignals();
1674:                } else {
1675:                    gdb.data_evaluate_expression(cb, '"' + expression + '"'); // NOI18N
1676:                }
1677:                String response = cb.waitForCompletion();
1678:                if (response.startsWith("@0x")) { // NOI18N
1679:                    cb = new CommandBuffer();
1680:                    gdb.print(cb, expression);
1681:                    response = cb.waitForCompletion();
1682:                    if (response.length() > 0 && response.charAt(0) == '$') {
1683:                        int pos = response.indexOf('=');
1684:                        if (pos != -1 && (pos + 2) < response.length()) {
1685:                            response = response.substring(pos + 2,
1686:                                    response.length()).replace("\\n", "")
1687:                                    .trim(); // NOI18N
1688:                        }
1689:                    }
1690:                }
1691:                return response.length() > 0 ? response : null;
1692:            }
1693:
1694:            public Map<String, TypeInfo> getTypeInfoCache() {
1695:                return ticache;
1696:            }
1697:
1698:            public String requestValue(String name) {
1699:                assert !Thread.currentThread().getName().equals("GdbReaderRP"); // NOI18N
1700:
1701:                if (state.equals(STATE_STOPPED)) {
1702:                    CommandBuffer cb = new CommandBuffer();
1703:                    gdb.data_evaluate_expression(cb, name);
1704:                    String info = cb.waitForCompletion();
1705:                    if (info.length() == 0
1706:                            || cb.getState() != CommandBuffer.STATE_OK) {
1707:                        if (cb.getState() == CommandBuffer.STATE_ERROR) {
1708:                            log.fine("GD.requestValue[" + cb.getID()
1709:                                    + "]: Error [" + cb.getError() + "]"); // NOI18N
1710:                            return '>' + cb.getError() + '<';
1711:                        } else {
1712:                            log.fine("GD.requestValue[" + cb.getID()
1713:                                    + "]: Failure [" + // NOI18N
1714:                                    info.length() + ", " + cb.getState() + "]"); // NOI18N
1715:                            return "";
1716:                        }
1717:                    } else {
1718:                        return info;
1719:                    }
1720:                } else {
1721:                    return null;
1722:                }
1723:            }
1724:
1725:            public String requestWhatis(String name) {
1726:                assert !Thread.currentThread().getName().equals("GdbReaderRP"); // NOI18N
1727:
1728:                if (state.equals(STATE_STOPPED) && name != null
1729:                        && name.length() > 0) {
1730:                    CommandBuffer cb = new CommandBuffer();
1731:                    gdb.whatis(cb, name);
1732:                    String info = cb.waitForCompletion();
1733:                    if (info.length() == 0
1734:                            || cb.getState() != CommandBuffer.STATE_OK) {
1735:                        if (cb.getState() == CommandBuffer.STATE_ERROR) {
1736:                            log.fine("GD.requestWhatis[" + cb.getID()
1737:                                    + "]: Error [" + cb.getError() + "]"); // NOI18N
1738:                            //                    return '>' + cb.getError() + '<'; Show error in Value field...
1739:                            return "";
1740:                        } else {
1741:                            log.fine("GD.requestWhatis[" + cb.getID()
1742:                                    + "]: Failure [" + // NOI18N
1743:                                    info.length() + ", " + cb.getState() + "]"); // NOI18N
1744:                            return "";
1745:                        }
1746:                    } else {
1747:                        return info.substring(7, info.length() - 2);
1748:                    }
1749:                } else {
1750:                    return null;
1751:                }
1752:            }
1753:
1754:            public String requestSymbolType(String type) {
1755:                assert !Thread.currentThread().getName().equals("GdbReaderRP"); // NOI18N
1756:
1757:                if (state.equals(STATE_STOPPED) && type != null
1758:                        && type.length() > 0) {
1759:                    CommandBuffer cb = new CommandBuffer();
1760:                    gdb.symbol_type(cb, type);
1761:                    String info = cb.waitForCompletion();
1762:                    if (info.length() == 0
1763:                            || cb.getState() != CommandBuffer.STATE_OK) {
1764:                        if (cb.getState() == CommandBuffer.STATE_ERROR) {
1765:                            log.fine("GD.requestSymbolType[" + cb.getID()
1766:                                    + "]: Error [" + cb.getError() + "]"); // NOI18N
1767:                            //                    return '>' + cb.getError() + '<';  Show error in Value field...
1768:                            return "";
1769:                        } else {
1770:                            log.fine("GD.requestSymbolType[" + cb.getID()
1771:                                    + "]: Failure ["
1772:                                    + // NOI18N
1773:                                    info.length() + ", " + cb.getState()
1774:                                    + "]. Returning original type"); // NOI18N
1775:                            return type;
1776:                        }
1777:                    } else {
1778:                        log.fine("GD.requestSymbolType[" + cb.getID() + "]: "
1779:                                + type + " --> [" + info + "]");
1780:                        return info.substring(7, info.length() - 2);
1781:                    }
1782:                } else {
1783:                    return null;
1784:                }
1785:            }
1786:
1787:            /**
1788:             * Suspend all breakpoints. This is used to suspend breakpoints during Watch
1789:             * updates so functions called don't stop.
1790:             */
1791:            private void suspendBreakpointsAndSignals() {
1792:                for (BreakpointImpl impl : getBreakpointList().values()) {
1793:                    if (impl.getBreakpoint().isEnabled()) {
1794:                        gdb.break_disable(impl.getBreakpointNumber());
1795:                    }
1796:                }
1797:                gdb.set_unwindonsignal("on"); // NOI18N
1798:            }
1799:
1800:            /**
1801:             * Resume all breakpoints. This is used to re-enable breakpoints after a Watch
1802:             * update.
1803:             */
1804:            private void restoreBreakpointsAndSignals() {
1805:                gdb.set_unwindonsignal("off"); // NOI18N
1806:                for (BreakpointImpl impl : getBreakpointList().values()) {
1807:                    if (impl.getBreakpoint().isEnabled()) {
1808:                        gdb.break_enable(impl.getBreakpointNumber());
1809:                    }
1810:                }
1811:            }
1812:
1813:            /**
1814:             * Returns call stack for this debugger.
1815:             *
1816:             * @return call stack
1817:             */
1818:            public ArrayList<CallStackFrame> getCallStack() {
1819:                return callstack;
1820:            }
1821:
1822:            /**
1823:             * Returns call stack for this debugger.
1824:             *
1825:             * @param from Starting frame
1826:             * @param to Ending frame (one beyond what we want)
1827:             * @return call stack
1828:             */
1829:            public CallStackFrame[] getCallStackFrames(int from, int to) {
1830:                int cnt = to - from;
1831:
1832:                if ((from + cnt) <= getStackDepth()) {
1833:                    CallStackFrame[] frames = new CallStackFrame[cnt];
1834:                    for (int i = 0; i < cnt; i++) {
1835:                        frames[i] = callstack.get(from + i);
1836:                    }
1837:                    return frames;
1838:                } else {
1839:                    return new CallStackFrame[0];
1840:                }
1841:            }
1842:
1843:            public int getStackDepth() {
1844:                return callstack.size();
1845:            }
1846:
1847:            /**
1848:             * Returns current stack frame or null.
1849:             *
1850:             * @return current stack frame or null
1851:             */
1852:            public synchronized CallStackFrame getCurrentCallStackFrame() {
1853:                if (currentCallStackFrame != null) {
1854:                    return currentCallStackFrame;
1855:                } else if (!callstack.isEmpty()) {
1856:                    return callstack.get(0);
1857:                }
1858:                return null;
1859:            }
1860:
1861:            /**
1862:             * Sets a stack frame current.
1863:             *
1864:             * @param Frame to make current (or null)
1865:             */
1866:            public void setCurrentCallStackFrame(CallStackFrame callStackFrame) {
1867:                if (isValidStackFrame(callStackFrame)) {
1868:                    CallStackFrame old = setCurrentCallStackFrameNoFire(callStackFrame);
1869:                    updateLocalVariables(callStackFrame.getFrameNumber());
1870:                    if (old == callStackFrame) {
1871:                        return;
1872:                    }
1873:                    pcs.firePropertyChange(PROP_CURRENT_CALL_STACK_FRAME, old,
1874:                            callStackFrame);
1875:                } else {
1876:                    DialogDisplayer.getDefault().notify(
1877:                            new NotifyDescriptor.Message(NbBundle.getMessage(
1878:                                    GdbDebugger.class,
1879:                                    "ERR_InvalidCallStackFrame"))); // NOI18N
1880:
1881:                }
1882:            }
1883:
1884:            private CallStackFrame setCurrentCallStackFrameNoFire(
1885:                    CallStackFrame callStackFrame) {
1886:                CallStackFrame old;
1887:
1888:                synchronized (this ) {
1889:                    old = getCurrentCallStackFrame();
1890:                    if (callStackFrame == old) {
1891:                        return callStackFrame;
1892:                    }
1893:                    currentCallStackFrame = callStackFrame;
1894:                }
1895:                return old;
1896:            }
1897:
1898:            public boolean isValidStackFrame(CallStackFrame csf) {
1899:                return csf.getFileName() != null && csf.getFullname() != null
1900:                        && csf.getFunctionName() != null;
1901:            }
1902:
1903:            public boolean isStepOutValid() {
1904:                return callstack.size() == 1
1905:                        || (callstack.size() > 1 && isValidStackFrame(callstack
1906:                                .get(1)));
1907:            }
1908:
1909:            public void popTopmostCall() {
1910:                if (callstack.size() > 0 && isValidStackFrame(callstack.get(1))) {
1911:                    gdb.stack_select_frame(0);
1912:                    gdb.exec_finish();
1913:                } else {
1914:                    DialogDisplayer.getDefault().notify(
1915:                            new NotifyDescriptor.Message(NbBundle.getMessage(
1916:                                    GdbDebugger.class,
1917:                                    "ERR_InvalidCallStackFrame"))); // NOI18N
1918:                }
1919:            }
1920:
1921:            public Map<String, BreakpointImpl> getBreakpointList() {
1922:                return breakpointList;
1923:            }
1924:
1925:            /**
1926:             *  Gdb/mi doesn't handle spaces in paths (see http://sourceware.org/ml/gdb/2006-02/msg00283.html
1927:             *  for more details). So try an alternate if the path has embedded spaces.
1928:             *
1929:             *  @param path The absolute path to convert
1930:             *  @return The possibly modified path
1931:             */
1932:            public String getBestPath(String path) {
1933:                if (path.indexOf(' ') == -1
1934:                        && Utilities.getOperatingSystem() != Utilities.OS_MAC) {
1935:                    return path;
1936:                } else if (path.startsWith(runDirectory)) {
1937:                    return (path.substring(runDirectory.length()));
1938:                } else {
1939:                    int pos = path.lastIndexOf('/');
1940:                    if (pos != -1) {
1941:                        return path.substring(pos + 1);
1942:                    }
1943:                    // Don't delete the following code yet. Neet to understand breakpoints outside the current
1944:                    // project better! This might still be relevant.
1945:                    //            String rdir;
1946:                    //            if (runDirectory.endsWith("/")) { // NOI18N
1947:                    //                rdir = runDirectory.substring(0, runDirectory.length() - 1);
1948:                    //            } else {
1949:                    //                rdir = runDirectory;
1950:                    //            }
1951:                    //            int rdir_pos = rdir.indexOf('/');
1952:                    //            int path_pos = path.indexOf('/');
1953:                    //            int match = -1;
1954:                    //            while (rdir_pos == path_pos && rdir_pos != -1) {
1955:                    //                if (path.substring(0, rdir_pos).equals(rdir.substring(0, rdir_pos))) {
1956:                    //                    match = rdir_pos;
1957:                    //                }
1958:                    //                rdir_pos = rdir.indexOf('/', rdir_pos + 1);
1959:                    //                path_pos = path.indexOf('/', path_pos + 1);
1960:                    //            }
1961:                    //            if (match != -1) {
1962:                    //                path_pos = path.substring(0, path_pos).lastIndexOf('/'); // we want the previous path_pos
1963:                    //                int count = 1;
1964:                    //                while (rdir_pos != -1) {
1965:                    //                    count++;
1966:                    //                    rdir_pos = rdir.indexOf('/', rdir_pos + 1);
1967:                    //                }
1968:                    //                StringBuilder rpath = new StringBuilder();
1969:                    //                while (count-- > 0) {
1970:                    //                    rpath.append("../");
1971:                    //                }
1972:                    //                return rpath.toString()  + path.substring(path_pos + 1);
1973:                    //            }
1974:                }
1975:                return path;
1976:            }
1977:
1978:            /**
1979:             *  Get the directory we run in.
1980:             */
1981:            public String getRunDirectory() {
1982:                return runDirectory;
1983:            }
1984:
1985:            /**
1986:             * Returns <code>true</code> if this debugger supports fix & continue
1987:             * (HotSwap).
1988:             *
1989:             * @return <code>true</code> if this debugger supports fix & continue
1990:             */
1991:            public boolean canFixClasses() {
1992:                return false;
1993:            }
1994:
1995:            /**
1996:             * Returns <code>true</code> if this debugger supports Pop action.
1997:             *
1998:             * @return <code>true</code> if this debugger supports Pop action
1999:             */
2000:            public boolean canPopFrames() {
2001:                return true;
2002:            }
2003:
2004:            /**
2005:             * Determines if the target debuggee can be modified.
2006:             *
2007:             * @return <code>true</code> if the target debuggee can be modified or when
2008:             *         this information is not available (on JDK 1.4).
2009:             * @since 2.3
2010:             */
2011:            public boolean canBeModified() {
2012:                return true;
2013:            }
2014:
2015:            /**
2016:             * Adds property change listener.
2017:             *
2018:             * @param propertyName a name of property to listen on
2019:             * @param l new listener.
2020:             */
2021:            public void addPropertyChangeListener(String propertyName,
2022:                    PropertyChangeListener l) {
2023:                pcs.addPropertyChangeListener(propertyName, l);
2024:            }
2025:
2026:            /**
2027:             *  Adds property change listener.
2028:             *
2029:             * @param l new listener.
2030:             */
2031:            public void addPropertyChangeListener(PropertyChangeListener l) {
2032:                pcs.addPropertyChangeListener(l);
2033:            }
2034:
2035:            /**
2036:             * Removes property change listener.
2037:             *
2038:             * @param propertyName a name of property to listen on
2039:             * @param l removed listener.
2040:             */
2041:            public void removePropertyChangeListener(String propertyName,
2042:                    PropertyChangeListener l) {
2043:                pcs.removePropertyChangeListener(propertyName, l);
2044:            }
2045:
2046:            /**
2047:             *  Removes property change listener.
2048:             *
2049:             * @param l removed listener.
2050:             */
2051:            public void removePropertyChangeListener(PropertyChangeListener l) {
2052:                pcs.removePropertyChangeListener(l);
2053:            }
2054:
2055:            private void firePropertyChange(String name, Object o, Object n) {
2056:                pcs.firePropertyChange(name, o, n);
2057:            }
2058:
2059:            public int getCurrentToken() {
2060:                return currentToken;
2061:            }
2062:
2063:            public boolean isCygwin() {
2064:                return cygwin;
2065:            }
2066:
2067:            public boolean isCplusPlus() {
2068:                return cplusplus;
2069:            }
2070:
2071:            public Disassembly getDisassembly() {
2072:                return disassembly;
2073:            }
2074:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.