diff --git a/llvm/org.eclipse.cdt.llvm.dsf.lldb.core/src/org/eclipse/cdt/llvm/dsf/lldb/core/internal/LLDBTrait.java b/llvm/org.eclipse.cdt.llvm.dsf.lldb.core/src/org/eclipse/cdt/llvm/dsf/lldb/core/internal/LLDBTrait.java new file mode 100644 index 00000000000..1ad707e452e --- /dev/null +++ b/llvm/org.eclipse.cdt.llvm.dsf.lldb.core/src/org/eclipse/cdt/llvm/dsf/lldb/core/internal/LLDBTrait.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2017 Ericsson. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ + +package org.eclipse.cdt.llvm.dsf.lldb.core.internal; + +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.cdt.llvm.dsf.lldb.core.internal.launching.LLDBLaunch; +import org.eclipse.debug.core.ILaunch; + +/** + * Constants related to traits of LLDB. + * + * A trait describe what LLDB can or cannot do. This is used to create a mapping + * between LLDB versions and what they can do so that the code can do the proper + * thing. For example, earlier versions would not be able to work with + * breakpoints inserted with a full path. The trait + * {@link #BROKEN_BREAKPOINT_INSERT_FULL_PATH_LLVM_BUG_28709} was introduced + * because of bug https://llvm.org/bugs/show_bug.cgi?id=28709 + * + * The code can call {@link #isTraitOf(DsfSession)} to know whether or know the + * session (i.e. running LLDB) has that trait. + * + * @noimplement This interface is not intended to be implemented by clients. + * @noreference This enum is not intended to be referenced by clients. + */ +public enum LLDBTrait { + /** + * Trait for LLDBs affected by https://llvm.org/bugs/show_bug.cgi?id=28709. + * Inserting a breakpoint with full path would not work. + * TODO: Remove for versions < 4.0.0 eventually + */ + BROKEN_BREAKPOINT_INSERT_FULL_PATH_LLVM_BUG_28709; + + /** + * Returns whether or not the given session has this trait. + * + * @param session the debug session + * @return true if the given session has this trait for the LLDB, false otherwise + */ + public boolean isTraitOf(DsfSession session) { + Object launch = session.getModelAdapter(ILaunch.class); + if (!(launch instanceof LLDBLaunch)) { + LLDBCorePlugin.log( + "Could not determine if session has LLDB trait " + this + " because launch is of unexpected type " //$NON-NLS-1$ //$NON-NLS-2$ + + launch.getClass() + ". Some features might not work as expected.", //$NON-NLS-1$ + new Throwable()); + return false; + } + LLDBLaunch lldbLaunch = (LLDBLaunch) launch; + return lldbLaunch.hasTrait(this); + } +} diff --git a/llvm/org.eclipse.cdt.llvm.dsf.lldb.core/src/org/eclipse/cdt/llvm/dsf/lldb/core/internal/launching/LLDBLaunch.java b/llvm/org.eclipse.cdt.llvm.dsf.lldb.core/src/org/eclipse/cdt/llvm/dsf/lldb/core/internal/launching/LLDBLaunch.java index 7dfe254953f..c7eebd6035f 100644 --- a/llvm/org.eclipse.cdt.llvm.dsf.lldb.core/src/org/eclipse/cdt/llvm/dsf/lldb/core/internal/launching/LLDBLaunch.java +++ b/llvm/org.eclipse.cdt.llvm.dsf.lldb.core/src/org/eclipse/cdt/llvm/dsf/lldb/core/internal/launching/LLDBLaunch.java @@ -14,6 +14,8 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.text.MessageFormat; +import java.util.HashSet; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -22,6 +24,7 @@ import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch; import org.eclipse.cdt.llvm.dsf.lldb.core.ILLDBDebugPreferenceConstants; import org.eclipse.cdt.llvm.dsf.lldb.core.ILLDBLaunchConfigurationConstants; import org.eclipse.cdt.llvm.dsf.lldb.core.internal.ILLDBConstants; +import org.eclipse.cdt.llvm.dsf.lldb.core.internal.LLDBTrait; import org.eclipse.cdt.llvm.dsf.lldb.core.internal.LLDBCorePlugin; import org.eclipse.cdt.utils.CommandLineUtil; import org.eclipse.cdt.utils.spawner.ProcessFactory; @@ -51,6 +54,7 @@ public class LLDBLaunch extends GdbLaunch { private IntegerTuple fLldbVersion; private IntegerTuple fLldbRevision; + private Set fTraits; /** * Constructs a launch. @@ -183,6 +187,7 @@ public class LLDBLaunch extends GdbLaunch { detailedException)); } } + computeTraits(); } catch (IOException e) { // Since we can't use lldb-mi for version checking, we try to use // the lldb executable but it's possible that it's not there at all @@ -206,6 +211,27 @@ public class LLDBLaunch extends GdbLaunch { } } + private void computeTraits() { + if (fTraits == null) { + fTraits = new HashSet<>(); + + // Here are some LLDB/Xcode version mappings + // 360.1.65 => Xcode 8.1.0 + // 360.1.70 => Xcode 8.2.1, 8.2.0 + // 370.0.30 => Xcode 8.3.0 Beta 4 + // + // Note that a LLDB built from source on macOS can report the same + // Apple-style version even for different LLDB/Clang-style version + // For example, 3.9.1 and 4.0.0 both report 360.99.0, how + // inconvenient! But this will only affect people building it from + // source, not LLDB included in Xcode. + + if (fLldbVersion != null && fLldbVersion.compareTo(new IntegerTuple(4, 0, 0)) < 0 || fLldbRevision != null && fLldbRevision.compareTo(new IntegerTuple(370, 0, 30)) < 0) { + fTraits.add(LLDBTrait.BROKEN_BREAKPOINT_INSERT_FULL_PATH_LLVM_BUG_28709); + } + } + } + /** * Read from the specified stream and return what was read. * @@ -375,4 +401,15 @@ public class LLDBLaunch extends GdbLaunch { } return path.toOSString(); } + + /** + * Returns whether or not the LLDB use by this launch has the given trait. + * + * @param trait + * the trait to check + * @return if the launch has this trait for the LLDB, false otherwise + */ + public boolean hasTrait (LLDBTrait trait) { + return fTraits.contains(trait); + } } diff --git a/llvm/org.eclipse.cdt.llvm.dsf.lldb.core/src/org/eclipse/cdt/llvm/dsf/lldb/core/internal/service/LLDBBreakpoints.java b/llvm/org.eclipse.cdt.llvm.dsf.lldb.core/src/org/eclipse/cdt/llvm/dsf/lldb/core/internal/service/LLDBBreakpoints.java index c78855c0cce..b63a37adf74 100644 --- a/llvm/org.eclipse.cdt.llvm.dsf.lldb.core/src/org/eclipse/cdt/llvm/dsf/lldb/core/internal/service/LLDBBreakpoints.java +++ b/llvm/org.eclipse.cdt.llvm.dsf.lldb.core/src/org/eclipse/cdt/llvm/dsf/lldb/core/internal/service/LLDBBreakpoints.java @@ -13,6 +13,7 @@ import java.util.Map; import org.eclipse.cdt.dsf.debug.service.IBreakpoints; import org.eclipse.cdt.dsf.gdb.service.GDBBreakpoints_7_4; import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.cdt.llvm.dsf.lldb.core.internal.LLDBTrait; import org.eclipse.core.runtime.Path; /** @@ -35,25 +36,32 @@ public class LLDBBreakpoints extends GDBBreakpoints_7_4 { @Override protected String formatLocation(Map attributes) { - // FIXME: ***Big hack*** lldb-mi's -breakpoint-insert doesn't handle - // locations that look like absolute paths (leading /). This will have - // to be fixed upstream because the work-around is not ideal: we only - // use the last segment to insert the breakpoint. This is not good if - // there are two files of the same name in the inferior. - // See https://llvm.org/bugs/show_bug.cgi?id=28709 - String location = super.formatLocation(attributes); - return adjustDebuggerPath(location); + if (LLDBTrait.BROKEN_BREAKPOINT_INSERT_FULL_PATH_LLVM_BUG_28709.isTraitOf(getSession())) { + // FIXME: ***Big hack*** lldb-mi's -breakpoint-insert doesn't handle + // locations that look like absolute paths (leading /). This will have + // to be fixed upstream because the work-around is not ideal: we only + // use the last segment to insert the breakpoint. This is not good if + // there are two files of the same name in the inferior. + // See https://llvm.org/bugs/show_bug.cgi?id=28709 + String location = super.formatLocation(attributes); + return adjustDebuggerPath(location); + } + + return super.formatLocation(attributes); } @Override public String adjustDebuggerPath(String originalPath) { - // FIXME: See also #formatLocation for hack explanation. This one needs - // to be overridden for moveToLine, runToLine and stepIntoSelection - // (Once this hack is removed, they should be tested). - Path path = new Path(originalPath); - if (path.isAbsolute()) { - return path.lastSegment(); + if (LLDBTrait.BROKEN_BREAKPOINT_INSERT_FULL_PATH_LLVM_BUG_28709.isTraitOf(getSession())) { + // FIXME: See also #formatLocation for hack explanation. This one needs + // to be overridden for moveToLine, runToLine and stepIntoSelection + // (Once this hack is removed, they should be tested). + Path path = new Path(originalPath); + if (path.isAbsolute()) { + return path.lastSegment(); + } } + return super.adjustDebuggerPath(originalPath); } }