Vendor import of lldb trunk r300890:

https://llvm.org/svn/llvm-project/lldb/trunk@300890
This commit is contained in:
Dimitry Andric 2017-04-20 21:21:28 +00:00
parent 74a628f776
commit d44a35e87e
49 changed files with 2078 additions and 2389 deletions

View File

@ -433,7 +433,9 @@ endif()
find_package(Backtrace)
include(CheckIncludeFile)
check_include_file(termios.h HAVE_TERMIOS_H)
check_include_file(sys/event.h HAVE_SYS_EVENT_H)
# These checks exist in LLVM's configuration, so I want to match the LLVM names
# so that the check isn't duplicated, but we translate them into the LLDB names

View File

@ -625,6 +625,7 @@ public:
protected:
bool IsEqualTo(const ArchSpec &rhs, bool exact_match) const;
void UpdateCore();
llvm::Triple m_triple;
Core m_core = kCore_invalid;

View File

@ -128,6 +128,8 @@ public:
m_diagnostics.push_back(diagnostic);
}
void CopyDiagnostics(DiagnosticManager &otherDiagnostics);
size_t Printf(DiagnosticSeverity severity, const char *format, ...)
__attribute__((format(printf, 3, 4)));
size_t PutString(DiagnosticSeverity severity, llvm::StringRef str);

View File

@ -41,8 +41,6 @@ public:
bool HasAtLeast(Size s);
bool HasAny(Character c);
std::string GetUnlexed();
// This will assert if there are less than s characters preceding the cursor.

View File

@ -923,6 +923,8 @@
AF33B4BE1C1FA441001B28D9 /* NetBSDSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF33B4BC1C1FA441001B28D9 /* NetBSDSignals.cpp */; };
AF33B4BF1C1FA441001B28D9 /* NetBSDSignals.h in Headers */ = {isa = PBXBuildFile; fileRef = AF33B4BD1C1FA441001B28D9 /* NetBSDSignals.h */; };
AF37E10A17C861F20061E18E /* ProcessRunLock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF37E10917C861F20061E18E /* ProcessRunLock.cpp */; };
AF3A4AD21EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF3A4AD01EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.cpp */; };
AF3A4AD31EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = AF3A4AD11EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.h */; };
AF415AE71D949E4400FCE0D4 /* x86AssemblyInspectionEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF415AE51D949E4400FCE0D4 /* x86AssemblyInspectionEngine.cpp */; };
AF415AE81D949E4400FCE0D4 /* x86AssemblyInspectionEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = AF415AE61D949E4400FCE0D4 /* x86AssemblyInspectionEngine.h */; };
AF45FDE518A1F3AC0007051C /* AppleGetThreadItemInfoHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF45FDE318A1F3AC0007051C /* AppleGetThreadItemInfoHandler.cpp */; };
@ -2937,6 +2939,8 @@
AF33B4BC1C1FA441001B28D9 /* NetBSDSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NetBSDSignals.cpp; path = Utility/NetBSDSignals.cpp; sourceTree = "<group>"; };
AF33B4BD1C1FA441001B28D9 /* NetBSDSignals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NetBSDSignals.h; path = Utility/NetBSDSignals.h; sourceTree = "<group>"; };
AF37E10917C861F20061E18E /* ProcessRunLock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessRunLock.cpp; sourceTree = "<group>"; };
AF3A4AD01EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformRemoteDarwinDevice.cpp; sourceTree = "<group>"; };
AF3A4AD11EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformRemoteDarwinDevice.h; sourceTree = "<group>"; };
AF3F54AE1B3BA59C00186E73 /* CrashReason.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CrashReason.cpp; sourceTree = "<group>"; };
AF3F54AF1B3BA59C00186E73 /* CrashReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CrashReason.h; sourceTree = "<group>"; };
AF3F54B21B3BA5D500186E73 /* POSIXStopInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = POSIXStopInfo.cpp; sourceTree = "<group>"; };
@ -5426,6 +5430,8 @@
9455630D1BEAD0570073F75F /* PlatformiOSSimulatorCoreSimulatorSupport.mm */,
26C5577B132575AD008FD8FE /* PlatformMacOSX.cpp */,
26C5577C132575AD008FD8FE /* PlatformMacOSX.h */,
AF3A4AD01EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.cpp */,
AF3A4AD11EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.h */,
AF8AD6331BEC28C400150209 /* PlatformRemoteAppleTV.cpp */,
AF8AD6341BEC28C400150209 /* PlatformRemoteAppleTV.h */,
AF8AD6351BEC28C400150209 /* PlatformRemoteAppleWatch.cpp */,
@ -6469,6 +6475,7 @@
files = (
AF8AD6381BEC28C400150209 /* PlatformRemoteAppleTV.h in Headers */,
26EFB61C1BFE8D3E00544801 /* PlatformNetBSD.h in Headers */,
AF3A4AD31EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.h in Headers */,
AF33B4BF1C1FA441001B28D9 /* NetBSDSignals.h in Headers */,
AF6335E31C87B21E00F7D554 /* SymbolFilePDB.h in Headers */,
267F685A1CC02EBE0086832B /* RegisterInfos_s390x.h in Headers */,
@ -7284,6 +7291,7 @@
AE6897281B94F6DE0018845D /* DWARFASTParserGo.cpp in Sources */,
945261C41B9A11FC00BF138D /* LibCxxUnorderedMap.cpp in Sources */,
26CEB5F218762056008F575A /* CommandObjectGUI.cpp in Sources */,
AF3A4AD21EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.cpp in Sources */,
2689008013353E2200698AC0 /* CommandInterpreter.cpp in Sources */,
AF77E0A41A033D360096C0EA /* RegisterContextPOSIX_powerpc.cpp in Sources */,
4CDB8D6D1DBA91B6006C5B13 /* LibStdcppUniquePointer.cpp in Sources */,

View File

@ -23,8 +23,8 @@ class LibCxxAtomicTestCase(TestBase):
var.SetPreferSyntheticValue(True)
return var
@skipIf(compiler="gcc")
@skipIfWindows # libc++ not ported to Windows yet
@skipIf(compiler=["gcc"])
@add_test_categories(["libc++"])
def test(self):
"""Test that std::atomic as defined by libc++ is correctly printed by LLDB"""
self.build()

View File

@ -30,8 +30,7 @@ class LibcxxListDataFormatterTestCase(TestBase):
self.line4 = line_number('main.cpp',
'// Set fourth break point at this line.')
@skipIf(compiler="gcc")
@skipIfWindows # libc++ not ported to Windows yet
@add_test_categories(["libc++"])
def test_with_run_command(self):
"""Test that that file and class static variables display correctly."""
self.build()

View File

@ -17,55 +17,112 @@ class LibcxxSetDataFormatterTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
@skipIf(compiler="gcc")
@skipIfWindows # libc++ not ported to Windows yet
def setUp(self):
TestBase.setUp(self)
ns = 'ndk' if lldbplatformutil.target_is_android() else ''
self.namespace = 'std::__' + ns + '1'
def getVariableType(self, name):
var = self.frame().FindVariable(name)
self.assertTrue(var.IsValid())
return var.GetType().GetCanonicalType().GetName()
@add_test_categories(["libc++"])
def test_with_run_command(self):
"""Test that that file and class static variables display correctly."""
self.build()
self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
# bkpt = self.target().FindBreakpointByID(lldbutil.run_break_set_by_source_regexp (self, "Set break point at this line."))
bkpt = self.target().FindBreakpointByID(
lldbutil.run_break_set_by_source_regexp(self, "Set break point at this line."))
self.runCmd("run", RUN_SUCCEEDED)
# lldbutil.skip_if_library_missing(self, self.target(), lldbutil.PrintableRegex("libc\+\+"))
#
# # The stop reason of the thread should be breakpoint.
# self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
# substrs = ['stopped',
# 'stop reason = breakpoint'])
#
# # This is the function to remove the custom formats in order to have a
# # clean slate for the next test case.
# def cleanup():
# self.runCmd('type format clear', check=False)
# self.runCmd('type summary clear', check=False)
# self.runCmd('type filter clear', check=False)
# self.runCmd('type synth clear', check=False)
# self.runCmd("settings set target.max-children-count 256", check=False)
#
# # Execute the cleanup function during test case tear down.
# self.addTearDownHook(cleanup)
#
# self.expect('image list', substrs = self.getLibcPlusPlusLibs())
#
# self.expect("frame variable ii",substrs = ["size=0","{}"])
# lldbutil.continue_to_breakpoint(self.process(), bkpt)
# self.expect("frame variable ii",substrs = ["size=6","[0] = 0","[1] = 1", "[2] = 2", "[3] = 3", "[4] = 4", "[5] = 5"])
# lldbutil.continue_to_breakpoint(self.process(), bkpt)
# self.expect("frame variable ii",substrs = ["size=7","[2] = 2", "[3] = 3", "[6] = 6"])
# self.expect("frame variable ii[2]",substrs = [" = 2"])
# self.expect("p ii",substrs = ["size=7","[2] = 2", "[3] = 3", "[6] = 6"])
# lldbutil.continue_to_breakpoint(self.process(), bkpt)
# self.expect("frame variable ii",substrs = ["size=0","{}"])
# lldbutil.continue_to_breakpoint(self.process(), bkpt)
# self.expect("frame variable ii",substrs = ["size=0","{}"])
# self.expect("frame variable ss",substrs = ["size=0","{}"])
# lldbutil.continue_to_breakpoint(self.process(), bkpt)
# self.expect("frame variable ss",substrs = ["size=2",'[0] = "a"','[1] = "a very long string is right here"'])
# lldbutil.continue_to_breakpoint(self.process(), bkpt)
# self.expect("frame variable ss",substrs = ["size=4",'[2] = "b"','[3] = "c"','[0] = "a"','[1] = "a very long string is right here"'])
# self.expect("p ss",substrs = ["size=4",'[2] = "b"','[3] = "c"','[0] = "a"','[1] = "a very long string is right here"'])
# self.expect("frame variable ss[2]",substrs = [' = "b"'])
# lldbutil.continue_to_breakpoint(self.process(), bkpt)
# self.expect("frame variable ss",substrs = ["size=3",'[0] = "a"','[1] = "a very long string is right here"','[2] = "c"'])
# The stop reason of the thread should be breakpoint.
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
substrs=['stopped',
'stop reason = breakpoint'])
# This is the function to remove the custom formats in order to have a
# clean slate for the next test case.
def cleanup():
self.runCmd('type format clear', check=False)
self.runCmd('type summary clear', check=False)
self.runCmd('type filter clear', check=False)
self.runCmd('type synth clear', check=False)
self.runCmd(
"settings set target.max-children-count 256",
check=False)
# Execute the cleanup function during test case tear down.
self.addTearDownHook(cleanup)
ii_type = self.getVariableType("ii")
self.assertTrue(ii_type.startswith(self.namespace + "::set"),
"Type: " + ii_type)
self.expect("frame variable ii", substrs=["size=0", "{}"])
lldbutil.continue_to_breakpoint(self.process(), bkpt)
self.expect(
"frame variable ii",
substrs=["size=6",
"[0] = 0",
"[1] = 1",
"[2] = 2",
"[3] = 3",
"[4] = 4",
"[5] = 5"])
lldbutil.continue_to_breakpoint(self.process(), bkpt)
self.expect(
"frame variable ii",
substrs=["size=7",
"[2] = 2",
"[3] = 3",
"[6] = 6"])
self.expect("frame variable ii[2]", substrs=[" = 2"])
self.expect(
"p ii",
substrs=[
"size=7",
"[2] = 2",
"[3] = 3",
"[6] = 6"])
lldbutil.continue_to_breakpoint(self.process(), bkpt)
self.expect("frame variable ii", substrs=["size=0", "{}"])
lldbutil.continue_to_breakpoint(self.process(), bkpt)
self.expect("frame variable ii", substrs=["size=0", "{}"])
ss_type = self.getVariableType("ss")
self.assertTrue(ii_type.startswith(self.namespace + "::set"),
"Type: " + ss_type)
self.expect("frame variable ss", substrs=["size=0", "{}"])
lldbutil.continue_to_breakpoint(self.process(), bkpt)
self.expect(
"frame variable ss",
substrs=["size=2",
'[0] = "a"',
'[1] = "a very long string is right here"'])
lldbutil.continue_to_breakpoint(self.process(), bkpt)
self.expect(
"frame variable ss",
substrs=["size=4",
'[2] = "b"',
'[3] = "c"',
'[0] = "a"',
'[1] = "a very long string is right here"'])
self.expect(
"p ss",
substrs=["size=4",
'[2] = "b"',
'[3] = "c"',
'[0] = "a"',
'[1] = "a very long string is right here"'])
self.expect("frame variable ss[2]", substrs=[' = "b"'])
lldbutil.continue_to_breakpoint(self.process(), bkpt)
self.expect(
"frame variable ss",
substrs=["size=3",
'[0] = "a"',
'[1] = "a very long string is right here"',
'[2] = "c"'])

View File

@ -0,0 +1,6 @@
LEVEL = ../../make
C_SOURCES := main.c
CFLAGS_EXTRAS += -std=c99
include $(LEVEL)/Makefile.rules

View File

@ -0,0 +1,99 @@
"""
Make sure the frame variable -g, -a, and -l flags work.
"""
from __future__ import print_function
import os
import time
import re
import lldb
import lldbsuite.test.lldbutil as lldbutil
from lldbsuite.test.lldbtest import *
class TestFrameVar(TestBase):
mydir = TestBase.compute_mydir(__file__)
# If your test case doesn't stress debug info, the
# set this to true. That way it won't be run once for
# each debug info format.
NO_DEBUG_INFO_TESTCASE = True
def test_frame_var(self):
self.build()
self.do_test()
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
def do_test(self):
exe = os.path.join(os.getcwd(), "a.out")
# Create a target by the debugger.
target = self.dbg.CreateTarget(exe)
self.assertTrue(target, VALID_TARGET)
# Now create a breakpoint in main.c at the source matching
# "Set a breakpoint here"
breakpoint = target.BreakpointCreateBySourceRegex(
"Set a breakpoint here", lldb.SBFileSpec("main.c"))
self.assertTrue(breakpoint and
breakpoint.GetNumLocations() >= 1,
VALID_BREAKPOINT)
error = lldb.SBError()
# This is the launch info. If you want to launch with arguments or
# environment variables, add them using SetArguments or
# SetEnvironmentEntries
launch_info = lldb.SBLaunchInfo(None)
process = target.Launch(launch_info, error)
self.assertTrue(process, PROCESS_IS_VALID)
# Did we hit our breakpoint?
from lldbsuite.test.lldbutil import get_threads_stopped_at_breakpoint
threads = get_threads_stopped_at_breakpoint(process, breakpoint)
self.assertTrue(
len(threads) == 1,
"There should be a thread stopped at our breakpoint")
# The hit count for the breakpoint should be 1.
self.assertTrue(breakpoint.GetHitCount() == 1)
frame = threads[0].GetFrameAtIndex(0)
command_result = lldb.SBCommandReturnObject()
interp = self.dbg.GetCommandInterpreter()
# Just get args:
result = interp.HandleCommand("frame var -l", command_result)
self.assertEqual(result, lldb.eReturnStatusSuccessFinishResult, "frame var -a didn't succeed")
output = command_result.GetOutput()
self.assertTrue("argc" in output, "Args didn't find argc")
self.assertTrue("argv" in output, "Args didn't find argv")
self.assertTrue("test_var" not in output, "Args found a local")
self.assertTrue("g_var" not in output, "Args found a global")
# Just get locals:
result = interp.HandleCommand("frame var -a", command_result)
self.assertEqual(result, lldb.eReturnStatusSuccessFinishResult, "frame var -a didn't succeed")
output = command_result.GetOutput()
self.assertTrue("argc" not in output, "Locals found argc")
self.assertTrue("argv" not in output, "Locals found argv")
self.assertTrue("test_var" in output, "Locals didn't find test_var")
self.assertTrue("g_var" not in output, "Locals found a global")
# Get the file statics:
result = interp.HandleCommand("frame var -l -a -g", command_result)
self.assertEqual(result, lldb.eReturnStatusSuccessFinishResult, "frame var -a didn't succeed")
output = command_result.GetOutput()
self.assertTrue("argc" not in output, "Globals found argc")
self.assertTrue("argv" not in output, "Globals found argv")
self.assertTrue("test_var" not in output, "Globals found test_var")
self.assertTrue("g_var" in output, "Globals didn't find g_var")

View File

@ -0,0 +1,11 @@
#include <stdio.h>
int g_var = 200;
int
main(int argc, char **argv)
{
int test_var = 10;
printf ("Set a breakpoint here: %d %d.\n", test_var, g_var);
return 0;
}

View File

@ -0,0 +1,45 @@
"""
Make sure the !N and !-N commands work properly.
"""
from __future__ import print_function
import os
import time
import re
import lldb
import lldbsuite.test.lldbutil as lldbutil
from lldbsuite.test.lldbtest import *
class TestHistoryRecall(TestBase):
mydir = TestBase.compute_mydir(__file__)
# If your test case doesn't stress debug info, the
# set this to true. That way it won't be run once for
# each debug info format.
NO_DEBUG_INFO_TESTCASE = True
def test_history_recall(self):
"""Test the !N and !-N functionality of the command interpreter."""
self.sample_test()
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
def sample_test(self):
interp = self.dbg.GetCommandInterpreter()
result = lldb.SBCommandReturnObject()
interp.HandleCommand("command history", result, True)
interp.HandleCommand("platform list", result, True)
interp.HandleCommand("!0", result, False)
self.assertTrue(result.Succeeded(), "!0 command did not work: %s"%(result.GetError()))
self.assertTrue("command history" in result.GetOutput(), "!0 didn't rerun command history")
interp.HandleCommand("!-1", result, False)
self.assertTrue(result.Succeeded(), "!-1 command did not work: %s"%(result.GetError()))
self.assertTrue("host:" in result.GetOutput(), "!-1 didn't rerun platform list.")

View File

@ -39,7 +39,6 @@ class LinuxCoreTestCase(TestBase):
super(LinuxCoreTestCase, self).tearDown()
@skipIf(oslist=['windows'])
@skipIfDarwin # <rdar://problem/31380097>, fails started happening with r299199
@skipIf(triple='^mips')
def test_i386(self):
"""Test that lldb can read the process information from an i386 linux core file."""
@ -58,21 +57,18 @@ class LinuxCoreTestCase(TestBase):
self.do_test("linux-mips64el-gnuabi64", self._mips64_n64_pid, self._mips_regions)
@skipIf(oslist=['windows'])
@skipIfDarwin # <rdar://problem/31380097>, fails started happening with r299199
@skipIf(triple='^mips')
def test_x86_64(self):
"""Test that lldb can read the process information from an x86_64 linux core file."""
self.do_test("linux-x86_64", self._x86_64_pid, self._x86_64_regions)
@skipIf(oslist=['windows'])
@skipIfDarwin # <rdar://problem/31380097>, fails started happening with r299199
@skipIf(triple='^mips')
def test_s390x(self):
"""Test that lldb can read the process information from an s390x linux core file."""
self.do_test("linux-s390x", self._s390x_pid, self._s390x_regions)
@skipIf(oslist=['windows'])
@skipIfDarwin # <rdar://problem/31380097>, fails started happening with r299199
@skipIf(triple='^mips')
def test_same_pid_running(self):
"""Test that we read the information from the core correctly even if we have a running
@ -102,7 +98,6 @@ class LinuxCoreTestCase(TestBase):
self.RemoveTempFile("linux-x86_64-pid.core")
@skipIf(oslist=['windows'])
@skipIfDarwin # <rdar://problem/31380097>, fails started happening with r299199
@skipIf(triple='^mips')
def test_two_cores_same_pid(self):
"""Test that we handle the situation if we have two core files with the same PID
@ -132,7 +127,6 @@ class LinuxCoreTestCase(TestBase):
self.do_test("linux-x86_64", self._x86_64_pid, self._x86_64_regions)
@skipIf(oslist=['windows'])
@skipIfDarwin # <rdar://problem/31380097>, fails started happening with r299199
@skipIf(triple='^mips')
def test_FPR_SSE(self):
# check x86_64 core file

View File

@ -23,14 +23,12 @@ class GCoreTestCase(TestBase):
_x86_64_pid = 5669
@skipIf(oslist=['windows'])
@skipIfDarwin # <rdar://problem/31380097>, fails started happening with r299199
@skipIf(triple='^mips')
def test_i386(self):
"""Test that lldb can read the process information from an i386 linux core file."""
self.do_test("linux-i386", self._i386_pid)
@skipIf(oslist=['windows'])
@skipIfDarwin # <rdar://problem/31380097>, fails started happening with r299199
@skipIf(triple='^mips')
def test_x86_64(self):
"""Test that lldb can read the process information from an x86_64 linux core file."""

View File

@ -27,14 +27,12 @@ class LinuxCoreThreadsTestCase(TestBase):
_x86_64_tid = 5250
@skipIf(oslist=['windows'])
@skipIfDarwin # <rdar://problem/31380097>, fails started happening with r299199
@skipIf(triple='^mips')
def test_i386(self):
"""Test that lldb can read the process information from an i386 linux core file."""
self.do_test("linux-i386", self._i386_pid, self._i386_tid)
@skipIf(oslist=['windows'])
@skipIfDarwin # <rdar://problem/31380097>, fails started happening with r299199
@skipIf(triple='^mips')
def test_x86_64(self):
"""Test that lldb can read the process information from an x86_64 linux core file."""

View File

@ -1,17 +1,26 @@
#include <stdio.h>
#if defined(__arm__) || defined(__aarch64__)
// Clang does not accept regparm attribute on these platforms.
// Fortunately, the default calling convention passes arguments in registers
// anyway.
#define REGPARM(N)
#else
#define REGPARM(N) __attribute__((regparm(N)))
#endif
struct bar {
int m1;
int m2;
};
void f1(int a, struct bar *b) __attribute__((noinline)) __attribute__((regparm(2)));
void f1(int a, struct bar *b) __attribute__((noinline)) REGPARM(2);
void f1(int a, struct bar *b)
{
b->m2 = b->m1 + a; // set breakpoint here
}
void f2(struct bar *b) __attribute__((noinline)) __attribute__((regparm(1)));
void f2(struct bar *b) __attribute__((noinline)) REGPARM(1);
void f2(struct bar *b)
{
int c = b->m2;

View File

@ -57,16 +57,12 @@ class StaticVariableTestCase(TestBase):
startstr="(int) A::g_points[1].x = 11")
@expectedFailureAll(
oslist=lldbplatformutil.getDarwinOSTriples(),
bugnumber="<rdar://problem/28706946>")
@expectedFailureAll(
compiler=[
"clang",
"gcc"],
compiler=["gcc"],
bugnumber="Compiler emits incomplete debug info")
@expectedFailureAll(
oslist=['freebsd'],
bugnumber='llvm.org/pr20550 failing on FreeBSD-11')
compiler=["clang"],
compiler_version=["<", "3.8"],
bugnumber='llvm.org/pr20550')
@add_test_categories(['pyapi'])
def test_with_python_api(self):
"""Test Python APIs on file and class static variables."""
@ -105,11 +101,11 @@ class StaticVariableTestCase(TestBase):
if name == 'g_points':
self.assertTrue(
val.GetValueType() == lldb.eValueTypeVariableStatic)
self.assertTrue(val.GetNumChildren() == 2)
self.assertEqual(val.GetNumChildren(), 2)
elif name == 'A::g_points':
self.assertTrue(
val.GetValueType() == lldb.eValueTypeVariableGlobal)
self.assertTrue(val.GetNumChildren() == 2)
self.assertEqual(val.GetNumChildren(), 2)
child1 = val.GetChildAtIndex(1)
self.DebugSBValue(child1)
child1_x = child1.GetChildAtIndex(0)

View File

@ -50,7 +50,11 @@ class CommandObjectCommandsHistory : public CommandObjectParsed {
public:
CommandObjectCommandsHistory(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "command history",
"Dump the history of commands in this session.",
"Dump the history of commands in this session.\n"
"Commands in the history list can be run again "
"using \"!<INDEX>\". \"!-<OFFSET>\" will re-run "
"the command that is <OFFSET> commands from the end"
" of the list (counting the current command).",
nullptr),
m_options() {}

View File

@ -655,42 +655,62 @@ protected:
if (num_variables > 0) {
for (size_t i = 0; i < num_variables; i++) {
var_sp = variable_list->GetVariableAtIndex(i);
bool dump_variable = true;
std::string scope_string;
if (dump_variable && m_option_variable.show_scope)
scope_string = GetScopeString(var_sp).str();
switch (var_sp->GetScope())
{
case eValueTypeVariableGlobal:
if (!m_option_variable.show_globals)
continue;
break;
case eValueTypeVariableStatic:
if (!m_option_variable.show_globals)
continue;
break;
case eValueTypeVariableArgument:
if (!m_option_variable.show_args)
continue;
break;
case eValueTypeVariableLocal:
if (!m_option_variable.show_locals)
continue;
break;
default:
continue;
break;
}
std::string scope_string;
if (m_option_variable.show_scope)
scope_string = GetScopeString(var_sp).str();
if (dump_variable) {
// Use the variable object code to make sure we are
// using the same APIs as the public API will be
// using...
valobj_sp = frame->GetValueObjectForFrameVariable(
var_sp, m_varobj_options.use_dynamic);
if (valobj_sp) {
// When dumping all variables, don't print any variables
// that are not in scope to avoid extra unneeded output
if (valobj_sp->IsInScope()) {
if (!valobj_sp->GetTargetSP()
->GetDisplayRuntimeSupportValues() &&
valobj_sp->IsRuntimeSupportValue())
continue;
// Use the variable object code to make sure we are
// using the same APIs as the public API will be
// using...
valobj_sp = frame->GetValueObjectForFrameVariable(
var_sp, m_varobj_options.use_dynamic);
if (valobj_sp) {
// When dumping all variables, don't print any variables
// that are not in scope to avoid extra unneeded output
if (valobj_sp->IsInScope()) {
if (!valobj_sp->GetTargetSP()
->GetDisplayRuntimeSupportValues() &&
valobj_sp->IsRuntimeSupportValue())
continue;
if (!scope_string.empty())
s.PutCString(scope_string);
if (!scope_string.empty())
s.PutCString(scope_string);
if (m_option_variable.show_decl &&
var_sp->GetDeclaration().GetFile()) {
var_sp->GetDeclaration().DumpStopContext(&s, false);
s.PutCString(": ");
}
options.SetFormat(format);
options.SetVariableFormatDisplayLanguage(
valobj_sp->GetPreferredDisplayLanguage());
options.SetRootValueObjectName(
var_sp ? var_sp->GetName().AsCString() : nullptr);
valobj_sp->Dump(result.GetOutputStream(), options);
if (m_option_variable.show_decl &&
var_sp->GetDeclaration().GetFile()) {
var_sp->GetDeclaration().DumpStopContext(&s, false);
s.PutCString(": ");
}
options.SetFormat(format);
options.SetVariableFormatDisplayLanguage(
valobj_sp->GetPreferredDisplayLanguage());
options.SetRootValueObjectName(
var_sp ? var_sp->GetName().AsCString() : nullptr);
valobj_sp->Dump(result.GetOutputStream(), options);
}
}
}

View File

@ -834,19 +834,7 @@ lldb::ByteOrder ArchSpec::GetByteOrder() const {
bool ArchSpec::SetTriple(const llvm::Triple &triple) {
m_triple = triple;
llvm::StringRef arch_name(m_triple.getArchName());
const CoreDefinition *core_def = FindCoreDefinition(arch_name);
if (core_def) {
m_core = core_def->core;
// Set the byte order to the default byte order for an architecture.
// This can be modified if needed for cases when cores handle both
// big and little endian
m_byte_order = core_def->default_byte_order;
} else {
Clear();
}
UpdateCore();
return IsValid();
}
@ -994,8 +982,10 @@ void ArchSpec::MergeFrom(const ArchSpec &other) {
GetTriple().setVendor(other.GetTriple().getVendor());
if (TripleOSIsUnspecifiedUnknown() && !other.TripleOSIsUnspecifiedUnknown())
GetTriple().setOS(other.GetTriple().getOS());
if (GetTriple().getArch() == llvm::Triple::UnknownArch)
if (GetTriple().getArch() == llvm::Triple::UnknownArch) {
GetTriple().setArch(other.GetTriple().getArch());
UpdateCore();
}
if (GetTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
!TripleVendorWasSpecified()) {
if (other.TripleVendorWasSpecified())
@ -1190,6 +1180,20 @@ bool ArchSpec::IsEqualTo(const ArchSpec &rhs, bool exact_match) const {
return false;
}
void ArchSpec::UpdateCore() {
llvm::StringRef arch_name(m_triple.getArchName());
const CoreDefinition *core_def = FindCoreDefinition(arch_name);
if (core_def) {
m_core = core_def->core;
// Set the byte order to the default byte order for an architecture.
// This can be modified if needed for cases when cores handle both
// big and little endian
m_byte_order = core_def->default_byte_order;
} else {
Clear();
}
}
//===----------------------------------------------------------------------===//
// Helper methods.

View File

@ -2745,7 +2745,7 @@ bool Scalar::SignExtend(uint32_t sign_bit_pos) {
if (max_bit_pos == sign_bit_pos)
return true;
else if (sign_bit_pos < (max_bit_pos - 1)) {
llvm::APInt sign_bit = llvm::APInt::getSignBit(sign_bit_pos + 1);
llvm::APInt sign_bit = llvm::APInt::getSignMask(sign_bit_pos + 1);
llvm::APInt bitwize_and = m_integer & sign_bit;
if (bitwize_and.getBoolValue()) {
const llvm::APInt mask =

View File

@ -79,3 +79,12 @@ size_t DiagnosticManager::PutString(DiagnosticSeverity severity,
AddDiagnostic(str, severity, eDiagnosticOriginLLDB);
return str.size();
}
void DiagnosticManager::CopyDiagnostics(DiagnosticManager &otherDiagnostics) {
for (const DiagnosticList::value_type &other_diagnostic:
otherDiagnostics.Diagnostics()) {
AddDiagnostic(
other_diagnostic->GetMessage(), other_diagnostic->GetSeverity(),
other_diagnostic->getKind(), other_diagnostic->GetCompilerID());
}
}

View File

@ -47,13 +47,13 @@ CommandHistory::FindString(llvm::StringRef input_str) const {
size_t idx = 0;
if (input_str.front() == '-') {
if (input_str.drop_front(2).getAsInteger(0, idx))
if (input_str.drop_front(1).getAsInteger(0, idx))
return llvm::None;
if (idx >= m_history.size())
return llvm::None;
idx = m_history.size() - idx;
} else {
if (input_str.drop_front().getAsInteger(0, idx))
if (input_str.getAsInteger(0, idx))
return llvm::None;
if (idx >= m_history.size())
return llvm::None;

View File

@ -1810,6 +1810,7 @@ enum ExpressionStrings {
const int jit_max_expr_size = 512;
// Retrieve the string to JIT for the given expression
#define JIT_TEMPLATE_CONTEXT "void* ctxt = (void*)rsDebugGetContextWrapper(0x%" PRIx64 "); "
const char *JITTemplate(ExpressionStrings e) {
// Format strings containing the expressions we may need to evaluate.
static std::array<const char *, _eExprLast> runtime_expressions = {
@ -1817,57 +1818,65 @@ const char *JITTemplate(ExpressionStrings e) {
"(int*)_"
"Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocation"
"CubemapFace"
"(0x%" PRIx64 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", 0, 0)",
"(0x%" PRIx64 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", 0, 0)", // eExprGetOffsetPtr
// Type* rsaAllocationGetType(Context*, Allocation*)
"(void*)rsaAllocationGetType(0x%" PRIx64 ", 0x%" PRIx64 ")",
JIT_TEMPLATE_CONTEXT "(void*)rsaAllocationGetType(ctxt, 0x%" PRIx64 ")", // eExprAllocGetType
// rsaTypeGetNativeData(Context*, Type*, void* typeData, size) Pack the
// data in the following way mHal.state.dimX; mHal.state.dimY;
// mHal.state.dimZ; mHal.state.lodCount; mHal.state.faces; mElement; into
// typeData Need to specify 32 or 64 bit for uint_t since this differs
// between devices
"uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64
", 0x%" PRIx64 ", data, 6); data[0]", // X dim
"uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64
", 0x%" PRIx64 ", data, 6); data[1]", // Y dim
"uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64
", 0x%" PRIx64 ", data, 6); data[2]", // Z dim
"uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64
", 0x%" PRIx64 ", data, 6); data[5]", // Element ptr
JIT_TEMPLATE_CONTEXT
"uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(ctxt"
", 0x%" PRIx64 ", data, 6); data[0]", // eExprTypeDimX
JIT_TEMPLATE_CONTEXT
"uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(ctxt"
", 0x%" PRIx64 ", data, 6); data[1]", // eExprTypeDimY
JIT_TEMPLATE_CONTEXT
"uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(ctxt"
", 0x%" PRIx64 ", data, 6); data[2]", // eExprTypeDimZ
JIT_TEMPLATE_CONTEXT
"uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(ctxt"
", 0x%" PRIx64 ", data, 6); data[5]", // eExprTypeElemPtr
// rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size)
// Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into
// elemData
"uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64
", 0x%" PRIx64 ", data, 5); data[0]", // Type
"uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64
", 0x%" PRIx64 ", data, 5); data[1]", // Kind
"uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64
", 0x%" PRIx64 ", data, 5); data[3]", // Vector Size
"uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64
", 0x%" PRIx64 ", data, 5); data[4]", // Field Count
JIT_TEMPLATE_CONTEXT
"uint32_t data[5]; (void*)rsaElementGetNativeData(ctxt"
", 0x%" PRIx64 ", data, 5); data[0]", // eExprElementType
JIT_TEMPLATE_CONTEXT
"uint32_t data[5]; (void*)rsaElementGetNativeData(ctxt"
", 0x%" PRIx64 ", data, 5); data[1]", // eExprElementKind
JIT_TEMPLATE_CONTEXT
"uint32_t data[5]; (void*)rsaElementGetNativeData(ctxt"
", 0x%" PRIx64 ", data, 5); data[3]", // eExprElementVec
JIT_TEMPLATE_CONTEXT
"uint32_t data[5]; (void*)rsaElementGetNativeData(ctxt"
", 0x%" PRIx64 ", data, 5); data[4]", // eExprElementFieldCount
// rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t
// *ids, const char **names, size_t *arraySizes, uint32_t dataSize)
// Needed for Allocations of structs to gather details about
// fields/Subelements Element* of field
"void* ids[%" PRIu32 "]; const char* names[%" PRIu32
JIT_TEMPLATE_CONTEXT "void* ids[%" PRIu32 "]; const char* names[%" PRIu32
"]; size_t arr_size[%" PRIu32 "];"
"(void*)rsaElementGetSubElements(0x%" PRIx64 ", 0x%" PRIx64
", ids, names, arr_size, %" PRIu32 "); ids[%" PRIu32 "]",
"(void*)rsaElementGetSubElements(ctxt, 0x%" PRIx64
", ids, names, arr_size, %" PRIu32 "); ids[%" PRIu32 "]", // eExprSubelementsId
// Name of field
"void* ids[%" PRIu32 "]; const char* names[%" PRIu32
JIT_TEMPLATE_CONTEXT "void* ids[%" PRIu32 "]; const char* names[%" PRIu32
"]; size_t arr_size[%" PRIu32 "];"
"(void*)rsaElementGetSubElements(0x%" PRIx64 ", 0x%" PRIx64
", ids, names, arr_size, %" PRIu32 "); names[%" PRIu32 "]",
"(void*)rsaElementGetSubElements(ctxt, 0x%" PRIx64
", ids, names, arr_size, %" PRIu32 "); names[%" PRIu32 "]", // eExprSubelementsName
// Array size of field
"void* ids[%" PRIu32 "]; const char* names[%" PRIu32
JIT_TEMPLATE_CONTEXT "void* ids[%" PRIu32 "]; const char* names[%" PRIu32
"]; size_t arr_size[%" PRIu32 "];"
"(void*)rsaElementGetSubElements(0x%" PRIx64 ", 0x%" PRIx64
", ids, names, arr_size, %" PRIu32 "); arr_size[%" PRIu32 "]"}};
"(void*)rsaElementGetSubElements(ctxt, 0x%" PRIx64
", ids, names, arr_size, %" PRIu32 "); arr_size[%" PRIu32 "]"}}; // eExprSubelementsArrSize
return runtime_expressions[e];
}
@ -1979,8 +1988,8 @@ bool RenderScriptRuntime::JITTypePacked(AllocationDetails *alloc,
for (uint32_t i = 0; i < num_exprs; ++i) {
const char *fmt_str = JITTemplate(ExpressionStrings(eExprTypeDimX + i));
int written = snprintf(expr_bufs[i], jit_max_expr_size, fmt_str, bits,
*alloc->context.get(), *alloc->type_ptr.get());
int written = snprintf(expr_bufs[i], jit_max_expr_size, fmt_str,
*alloc->context.get(), bits, *alloc->type_ptr.get());
if (written < 0) {
if (log)
log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
@ -2105,7 +2114,7 @@ bool RenderScriptRuntime::JITSubelements(Element &elem,
const char *fmt_str =
JITTemplate(ExpressionStrings(eExprSubelementsId + expr_index));
int written = snprintf(expr_buffer, jit_max_expr_size, fmt_str,
field_count, field_count, field_count, context,
context, field_count, field_count, field_count,
*elem.element_ptr.get(), field_count, field_index);
if (written < 0) {
if (log)

View File

@ -5,6 +5,7 @@ list(APPEND PLUGIN_PLATFORM_MACOSX_SOURCES
PlatformRemoteiOS.cpp
PlatformRemoteAppleTV.cpp
PlatformRemoteAppleWatch.cpp
PlatformRemoteDarwinDevice.cpp
)
list(APPEND PLUGIN_PLATFORM_MACOSX_DARWIN_ONLY_SOURCES

View File

@ -569,6 +569,8 @@ bool PlatformDarwin::ARMGetSupportedArchitectureAtIndex(uint32_t idx,
#define OSNAME "tvos"
#elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
#define OSNAME "watchos"
#elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
#define OSNAME "bridgeos"
#else
#define OSNAME "ios"
#endif

View File

@ -508,9 +508,10 @@ PlatformDarwinKernel::GetKernelsAndKextsInDirectoryHelper(
ConstString file_spec_extension = file_spec.GetFileNameExtension();
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log)
log->Printf("PlatformDarwinKernel examining %s",
file_spec.GetPath().c_str());
Log *log_verbose(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM | LLDB_LOG_OPTION_VERBOSE));
if (log_verbose)
log_verbose->Printf ("PlatformDarwinKernel examining '%s'", file_spec.GetPath().c_str());
PlatformDarwinKernel *thisp = (PlatformDarwinKernel *)baton;
if (ft == llvm::sys::fs::file_type::regular_file ||
@ -520,9 +521,21 @@ PlatformDarwinKernel::GetKernelsAndKextsInDirectoryHelper(
strncmp(filename.GetCString(), "mach", 4) == 0) &&
file_spec_extension != g_dsym_suffix) {
if (KernelHasdSYMSibling(file_spec))
{
if (log)
{
log->Printf ("PlatformDarwinKernel registering kernel binary '%s' with dSYM sibling", file_spec.GetPath().c_str());
}
thisp->m_kernel_binaries_with_dsyms.push_back(file_spec);
}
else
{
if (log)
{
log->Printf ("PlatformDarwinKernel registering kernel binary '%s', no dSYM", file_spec.GetPath().c_str());
}
thisp->m_kernel_binaries_without_dsyms.push_back(file_spec);
}
return FileSpec::eEnumerateDirectoryResultNext;
}
} else if (ft == llvm::sys::fs::file_type::directory_file &&
@ -556,6 +569,8 @@ PlatformDarwinKernel::GetKernelsAndKextsInDirectoryHelper(
if (recurse && file_spec_extension != g_dsym_suffix &&
file_spec_extension != g_kext_suffix &&
file_spec_extension != g_bundle_suffix) {
if (log_verbose)
log_verbose->Printf ("PlatformDarwinKernel descending into directory '%s'", file_spec.GetPath().c_str());
return FileSpec::eEnumerateDirectoryResultEnter;
} else {
return FileSpec::eEnumerateDirectoryResultNext;
@ -564,6 +579,7 @@ PlatformDarwinKernel::GetKernelsAndKextsInDirectoryHelper(
void PlatformDarwinKernel::AddKextToMap(PlatformDarwinKernel *thisp,
const FileSpec &file_spec) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
CFCBundle bundle(file_spec.GetPath().c_str());
CFStringRef bundle_id(bundle.GetIdentifier());
if (bundle_id && CFGetTypeID(bundle_id) == CFStringGetTypeID()) {
@ -572,11 +588,23 @@ void PlatformDarwinKernel::AddKextToMap(PlatformDarwinKernel *thisp,
kCFStringEncodingUTF8)) {
ConstString bundle_conststr(bundle_id_buf);
if (KextHasdSYMSibling(file_spec))
{
if (log)
{
log->Printf ("PlatformDarwinKernel registering kext binary '%s' with dSYM sibling", file_spec.GetPath().c_str());
}
thisp->m_name_to_kext_path_map_with_dsyms.insert(
std::pair<ConstString, FileSpec>(bundle_conststr, file_spec));
}
else
{
if (log)
{
log->Printf ("PlatformDarwinKernel registering kext binary '%s', no dSYM", file_spec.GetPath().c_str());
}
thisp->m_name_to_kext_path_map_without_dsyms.insert(
std::pair<ConstString, FileSpec>(bundle_conststr, file_spec));
}
}
}
}

View File

@ -37,22 +37,7 @@ using namespace lldb_private;
/// Default Constructor
//------------------------------------------------------------------
PlatformRemoteAppleTV::PlatformRemoteAppleTV()
: PlatformDarwin(false), // This is a remote platform
m_sdk_directory_infos(), m_device_support_directory(),
m_device_support_directory_for_os_version(), m_build_update(),
m_last_module_sdk_idx(UINT32_MAX),
m_connected_module_sdk_idx(UINT32_MAX) {}
PlatformRemoteAppleTV::SDKDirectoryInfo::SDKDirectoryInfo(
const lldb_private::FileSpec &sdk_dir)
: directory(sdk_dir), build(), version_major(0), version_minor(0),
version_update(0), user_cached(false) {
llvm::StringRef dirname_str = sdk_dir.GetFilename().GetStringRef();
llvm::StringRef build_str;
std::tie(version_major, version_minor, version_update, build_str) =
ParseVersionBuildDir(dirname_str);
build.SetString(build_str);
}
: PlatformRemoteDarwinDevice () {}
//------------------------------------------------------------------
// Static Variables
@ -165,615 +150,6 @@ const char *PlatformRemoteAppleTV::GetDescriptionStatic() {
return "Remote Apple TV platform plug-in.";
}
void PlatformRemoteAppleTV::GetStatus(Stream &strm) {
Platform::GetStatus(strm);
const char *sdk_directory = GetDeviceSupportDirectoryForOSVersion();
if (sdk_directory)
strm.Printf(" SDK Path: \"%s\"\n", sdk_directory);
else
strm.PutCString(" SDK Path: error: unable to locate SDK\n");
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
for (uint32_t i = 0; i < num_sdk_infos; ++i) {
const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
strm.Printf(" SDK Roots: [%2u] \"%s\"\n", i,
sdk_dir_info.directory.GetPath().c_str());
}
}
Error PlatformRemoteAppleTV::ResolveExecutable(
const ModuleSpec &ms, lldb::ModuleSP &exe_module_sp,
const FileSpecList *module_search_paths_ptr) {
Error error;
// Nothing special to do here, just use the actual file and architecture
ModuleSpec resolved_module_spec(ms);
// Resolve any executable within a bundle on MacOSX
// TODO: verify that this handles shallow bundles, if not then implement one
// ourselves
Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
if (resolved_module_spec.GetFileSpec().Exists()) {
if (resolved_module_spec.GetArchitecture().IsValid() ||
resolved_module_spec.GetUUID().IsValid()) {
error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
nullptr, nullptr, nullptr);
if (exe_module_sp && exe_module_sp->GetObjectFile())
return error;
exe_module_sp.reset();
}
// No valid architecture was specified or the exact ARM slice wasn't
// found so ask the platform for the architectures that we should be
// using (in the correct order) and see if we can find a match that way
StreamString arch_names;
for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
idx, resolved_module_spec.GetArchitecture());
++idx) {
error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
nullptr, nullptr, nullptr);
// Did we find an executable using one of the
if (error.Success()) {
if (exe_module_sp && exe_module_sp->GetObjectFile())
break;
else
error.SetErrorToGenericError();
}
if (idx > 0)
arch_names.PutCString(", ");
arch_names.PutCString(
resolved_module_spec.GetArchitecture().GetArchitectureName());
}
if (error.Fail() || !exe_module_sp) {
if (resolved_module_spec.GetFileSpec().Readable()) {
error.SetErrorStringWithFormat(
"'%s' doesn't contain any '%s' platform architectures: %s",
resolved_module_spec.GetFileSpec().GetPath().c_str(),
GetPluginName().GetCString(), arch_names.GetData());
} else {
error.SetErrorStringWithFormat(
"'%s' is not readable",
resolved_module_spec.GetFileSpec().GetPath().c_str());
}
}
} else {
error.SetErrorStringWithFormat(
"'%s' does not exist",
resolved_module_spec.GetFileSpec().GetPath().c_str());
}
return error;
}
FileSpec::EnumerateDirectoryResult
PlatformRemoteAppleTV::GetContainedFilesIntoVectorOfStringsCallback(
void *baton, llvm::sys::fs::file_type ft, const FileSpec &file_spec) {
((PlatformRemoteAppleTV::SDKDirectoryInfoCollection *)baton)
->push_back(PlatformRemoteAppleTV::SDKDirectoryInfo(file_spec));
return FileSpec::eEnumerateDirectoryResultNext;
}
bool PlatformRemoteAppleTV::UpdateSDKDirectoryInfosIfNeeded() {
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
std::lock_guard<std::mutex> guard(m_sdk_dir_mutex);
if (m_sdk_directory_infos.empty()) {
const char *device_support_dir = GetDeviceSupportDirectory();
if (log) {
log->Printf("PlatformRemoteAppleTV::UpdateSDKDirectoryInfosIfNeeded Got "
"DeviceSupport directory %s",
device_support_dir);
}
if (device_support_dir) {
const bool find_directories = true;
const bool find_files = false;
const bool find_other = false;
SDKDirectoryInfoCollection builtin_sdk_directory_infos;
FileSpec::EnumerateDirectory(m_device_support_directory, find_directories,
find_files, find_other,
GetContainedFilesIntoVectorOfStringsCallback,
&builtin_sdk_directory_infos);
// Only add SDK directories that have symbols in them, some SDKs only
// contain
// developer disk images and no symbols, so they aren't useful to us.
FileSpec sdk_symbols_symlink_fspec;
for (const auto &sdk_directory_info : builtin_sdk_directory_infos) {
sdk_symbols_symlink_fspec = sdk_directory_info.directory;
sdk_symbols_symlink_fspec.AppendPathComponent("Symbols.Internal");
if (sdk_symbols_symlink_fspec.Exists()) {
m_sdk_directory_infos.push_back(sdk_directory_info);
if (log) {
log->Printf("PlatformRemoteAppleTV::"
"UpdateSDKDirectoryInfosIfNeeded added builtin SDK "
"directory %s",
sdk_symbols_symlink_fspec.GetPath().c_str());
}
} else {
sdk_symbols_symlink_fspec.GetFilename().SetCString("Symbols");
if (sdk_symbols_symlink_fspec.Exists())
m_sdk_directory_infos.push_back(sdk_directory_info);
if (log) {
log->Printf("PlatformRemoteAppleTV::"
"UpdateSDKDirectoryInfosIfNeeded added builtin SDK "
"directory %s",
sdk_symbols_symlink_fspec.GetPath().c_str());
}
}
}
const uint32_t num_installed = m_sdk_directory_infos.size();
FileSpec local_sdk_cache("~/Library/Developer/Xcode/tvOS DeviceSupport",
true);
if (!local_sdk_cache.Exists()) {
// Try looking for another possible name
local_sdk_cache = FileSpec(
"~/Library/Developer/Xcode/Apple TVOS DeviceSupport", true);
}
if (!local_sdk_cache.Exists()) {
// Try looking for another possible name
local_sdk_cache =
FileSpec("~/Library/Developer/Xcode/AppleTVOS DeviceSupport", true);
}
if (!local_sdk_cache.Exists()) {
// Try looking for another possible name
local_sdk_cache = FileSpec(
"~/Library/Developer/Xcode/AppleTV OS DeviceSupport", true);
}
if (!local_sdk_cache.Exists()) {
// Try looking for another possible name
local_sdk_cache = FileSpec(
"~/Library/Developer/Xcode/Apple TV OS DeviceSupport", true);
}
if (local_sdk_cache.Exists()) {
if (log) {
log->Printf("PlatformRemoteAppleTV::UpdateSDKDirectoryInfosIfNeeded "
"searching %s for additional SDKs",
local_sdk_cache.GetPath().c_str());
}
char path[PATH_MAX];
if (local_sdk_cache.GetPath(path, sizeof(path))) {
FileSpec::EnumerateDirectory(
path, find_directories, find_files, find_other,
GetContainedFilesIntoVectorOfStringsCallback,
&m_sdk_directory_infos);
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
// First try for an exact match of major, minor and update
for (uint32_t i = num_installed; i < num_sdk_infos; ++i) {
m_sdk_directory_infos[i].user_cached = true;
if (log) {
log->Printf("PlatformRemoteAppleTV::"
"UpdateSDKDirectoryInfosIfNeeded user SDK directory "
"%s",
m_sdk_directory_infos[i].directory.GetPath().c_str());
}
}
}
}
}
}
return !m_sdk_directory_infos.empty();
}
const PlatformRemoteAppleTV::SDKDirectoryInfo *
PlatformRemoteAppleTV::GetSDKDirectoryForCurrentOSVersion() {
uint32_t i;
if (UpdateSDKDirectoryInfosIfNeeded()) {
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
// Check to see if the user specified a build string. If they did, then
// be sure to match it.
std::vector<bool> check_sdk_info(num_sdk_infos, true);
ConstString build(m_sdk_build);
if (build) {
for (i = 0; i < num_sdk_infos; ++i)
check_sdk_info[i] = m_sdk_directory_infos[i].build == build;
}
// If we are connected we can find the version of the OS the platform
// us running on and select the right SDK
uint32_t major, minor, update;
if (GetOSVersion(major, minor, update)) {
if (UpdateSDKDirectoryInfosIfNeeded()) {
// First try for an exact match of major, minor and update
for (i = 0; i < num_sdk_infos; ++i) {
if (check_sdk_info[i]) {
if (m_sdk_directory_infos[i].version_major == major &&
m_sdk_directory_infos[i].version_minor == minor &&
m_sdk_directory_infos[i].version_update == update) {
return &m_sdk_directory_infos[i];
}
}
}
// First try for an exact match of major and minor
for (i = 0; i < num_sdk_infos; ++i) {
if (check_sdk_info[i]) {
if (m_sdk_directory_infos[i].version_major == major &&
m_sdk_directory_infos[i].version_minor == minor) {
return &m_sdk_directory_infos[i];
}
}
}
// Lastly try to match of major version only..
for (i = 0; i < num_sdk_infos; ++i) {
if (check_sdk_info[i]) {
if (m_sdk_directory_infos[i].version_major == major) {
return &m_sdk_directory_infos[i];
}
}
}
}
} else if (build) {
// No version, just a build number, search for the first one that matches
for (i = 0; i < num_sdk_infos; ++i)
if (check_sdk_info[i])
return &m_sdk_directory_infos[i];
}
}
return nullptr;
}
const PlatformRemoteAppleTV::SDKDirectoryInfo *
PlatformRemoteAppleTV::GetSDKDirectoryForLatestOSVersion() {
const PlatformRemoteAppleTV::SDKDirectoryInfo *result = nullptr;
if (UpdateSDKDirectoryInfosIfNeeded()) {
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
// First try for an exact match of major, minor and update
for (uint32_t i = 0; i < num_sdk_infos; ++i) {
const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
if (sdk_dir_info.version_major != UINT32_MAX) {
if (result == nullptr ||
sdk_dir_info.version_major > result->version_major) {
result = &sdk_dir_info;
} else if (sdk_dir_info.version_major == result->version_major) {
if (sdk_dir_info.version_minor > result->version_minor) {
result = &sdk_dir_info;
} else if (sdk_dir_info.version_minor == result->version_minor) {
if (sdk_dir_info.version_update > result->version_update) {
result = &sdk_dir_info;
}
}
}
}
}
}
return result;
}
const char *PlatformRemoteAppleTV::GetDeviceSupportDirectory() {
if (m_device_support_directory.empty()) {
const char *device_support_dir = GetDeveloperDirectory();
if (device_support_dir) {
m_device_support_directory.assign(device_support_dir);
m_device_support_directory.append(
"/Platforms/AppleTVOS.platform/DeviceSupport");
} else {
// Assign a single NULL character so we know we tried to find the device
// support directory and we don't keep trying to find it over and over.
m_device_support_directory.assign(1, '\0');
}
}
// We should have put a single NULL character into m_device_support_directory
// or it should have a valid path if the code gets here
assert(m_device_support_directory.empty() == false);
if (m_device_support_directory[0])
return m_device_support_directory.c_str();
return nullptr;
}
const char *PlatformRemoteAppleTV::GetDeviceSupportDirectoryForOSVersion() {
if (m_sdk_sysroot)
return m_sdk_sysroot.GetCString();
if (m_device_support_directory_for_os_version.empty()) {
const PlatformRemoteAppleTV::SDKDirectoryInfo *sdk_dir_info =
GetSDKDirectoryForCurrentOSVersion();
if (sdk_dir_info == nullptr)
sdk_dir_info = GetSDKDirectoryForLatestOSVersion();
if (sdk_dir_info) {
char path[PATH_MAX];
if (sdk_dir_info->directory.GetPath(path, sizeof(path))) {
m_device_support_directory_for_os_version = path;
return m_device_support_directory_for_os_version.c_str();
}
} else {
// Assign a single NULL character so we know we tried to find the device
// support directory and we don't keep trying to find it over and over.
m_device_support_directory_for_os_version.assign(1, '\0');
}
}
// We should have put a single NULL character into
// m_device_support_directory_for_os_version
// or it should have a valid path if the code gets here
assert(m_device_support_directory_for_os_version.empty() == false);
if (m_device_support_directory_for_os_version[0])
return m_device_support_directory_for_os_version.c_str();
return nullptr;
}
uint32_t
PlatformRemoteAppleTV::FindFileInAllSDKs(const char *platform_file_path,
FileSpecList &file_list) {
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
if (platform_file_path && platform_file_path[0] &&
UpdateSDKDirectoryInfosIfNeeded()) {
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
lldb_private::FileSpec local_file;
// First try for an exact match of major, minor and update
for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) {
LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file_path,
m_sdk_directory_infos[sdk_idx].directory);
if (GetFileInSDK(platform_file_path, sdk_idx, local_file)) {
file_list.Append(local_file);
}
}
}
return file_list.GetSize();
}
bool PlatformRemoteAppleTV::GetFileInSDK(const char *platform_file_path,
uint32_t sdk_idx,
lldb_private::FileSpec &local_file) {
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
if (sdk_idx < m_sdk_directory_infos.size()) {
std::string sdkroot_path =
m_sdk_directory_infos[sdk_idx].directory.GetPath();
if (!sdkroot_path.empty() && platform_file_path && platform_file_path[0]) {
// We may need to interpose "/Symbols/" or "/Symbols.Internal/" between
// the
// SDK root directory and the file path.
const char *paths_to_try[] = {"Symbols", "", "Symbols.Internal", nullptr};
for (size_t i = 0; paths_to_try[i] != nullptr; i++) {
local_file.SetFile(sdkroot_path, false);
if (paths_to_try[i][0] != '\0')
local_file.AppendPathComponent(paths_to_try[i]);
local_file.AppendPathComponent(platform_file_path);
local_file.ResolvePath();
if (local_file.Exists()) {
if (log)
log->Printf("Found a copy of %s in the SDK dir %s/%s",
platform_file_path, sdkroot_path.c_str(),
paths_to_try[i]);
return true;
}
local_file.Clear();
}
}
}
return false;
}
Error PlatformRemoteAppleTV::GetSymbolFile(const FileSpec &platform_file,
const UUID *uuid_ptr,
FileSpec &local_file) {
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
Error error;
char platform_file_path[PATH_MAX];
if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
char resolved_path[PATH_MAX];
const char *os_version_dir = GetDeviceSupportDirectoryForOSVersion();
if (os_version_dir) {
::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", os_version_dir,
platform_file_path);
local_file.SetFile(resolved_path, true);
if (local_file.Exists()) {
if (log) {
log->Printf("Found a copy of %s in the DeviceSupport dir %s",
platform_file_path, os_version_dir);
}
return error;
}
::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols.Internal/%s",
os_version_dir, platform_file_path);
local_file.SetFile(resolved_path, true);
if (local_file.Exists()) {
if (log) {
log->Printf(
"Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal",
platform_file_path, os_version_dir);
}
return error;
}
::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols/%s",
os_version_dir, platform_file_path);
local_file.SetFile(resolved_path, true);
if (local_file.Exists()) {
if (log) {
log->Printf("Found a copy of %s in the DeviceSupport dir %s/Symbols",
platform_file_path, os_version_dir);
}
return error;
}
}
local_file = platform_file;
if (local_file.Exists())
return error;
error.SetErrorStringWithFormat(
"unable to locate a platform file for '%s' in platform '%s'",
platform_file_path, GetPluginName().GetCString());
} else {
error.SetErrorString("invalid platform file argument");
}
return error;
}
Error PlatformRemoteAppleTV::GetSharedModule(
const ModuleSpec &module_spec, lldb_private::Process *process,
ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr,
ModuleSP *old_module_sp_ptr, bool *did_create_ptr) {
// For Apple TV, the SDK files are all cached locally on the host
// system. So first we ask for the file in the cached SDK,
// then we attempt to get a shared module for the right architecture
// with the right UUID.
const FileSpec &platform_file = module_spec.GetFileSpec();
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
Error error;
char platform_file_path[PATH_MAX];
if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
ModuleSpec platform_module_spec(module_spec);
UpdateSDKDirectoryInfosIfNeeded();
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
// If we are connected we migth be able to correctly deduce the SDK
// directory
// using the OS build.
const uint32_t connected_sdk_idx = GetConnectedSDKIndex();
if (connected_sdk_idx < num_sdk_infos) {
LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
m_sdk_directory_infos[connected_sdk_idx].directory);
if (GetFileInSDK(platform_file_path, connected_sdk_idx,
platform_module_spec.GetFileSpec())) {
module_sp.reset();
error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
if (module_sp) {
m_last_module_sdk_idx = connected_sdk_idx;
error.Clear();
return error;
}
}
}
// Try the last SDK index if it is set as most files from an SDK
// will tend to be valid in that same SDK.
if (m_last_module_sdk_idx < num_sdk_infos) {
LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file_path,
m_sdk_directory_infos[m_last_module_sdk_idx].directory);
if (GetFileInSDK(platform_file_path, m_last_module_sdk_idx,
platform_module_spec.GetFileSpec())) {
module_sp.reset();
error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
if (module_sp) {
error.Clear();
return error;
}
}
}
// First try for an exact match of major, minor and update
for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) {
if (m_last_module_sdk_idx == sdk_idx) {
// Skip the last module SDK index if we already searched
// it above
continue;
}
LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file_path,
m_sdk_directory_infos[sdk_idx].directory);
if (GetFileInSDK(platform_file_path, sdk_idx,
platform_module_spec.GetFileSpec())) {
// printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());
error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
if (module_sp) {
// Remember the index of the last SDK that we found a file
// in in case the wrong SDK was selected.
m_last_module_sdk_idx = sdk_idx;
error.Clear();
return error;
}
}
}
}
// Not the module we are looking for... Nothing to see here...
module_sp.reset();
// This may not be an SDK-related module. Try whether we can bring in the
// thing to our local cache.
error = GetSharedModuleWithLocalCache(module_spec, module_sp,
module_search_paths_ptr,
old_module_sp_ptr, did_create_ptr);
if (error.Success())
return error;
// See if the file is present in any of the module_search_paths_ptr
// directories.
if (!module_sp && module_search_paths_ptr && platform_file) {
// create a vector of all the file / directory names in platform_file
// e.g. this might be
// /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation
//
// We'll need to look in the module_search_paths_ptr directories for
// both "UIFoundation" and "UIFoundation.framework" -- most likely the
// latter will be the one we find there.
FileSpec platform_pull_apart(platform_file);
std::vector<std::string> path_parts;
ConstString unix_root_dir("/");
while (true) {
ConstString part = platform_pull_apart.GetLastPathComponent();
platform_pull_apart.RemoveLastPathComponent();
if (part.IsEmpty() || part == unix_root_dir)
break;
path_parts.push_back(part.AsCString());
}
const size_t path_parts_size = path_parts.size();
size_t num_module_search_paths = module_search_paths_ptr->GetSize();
for (size_t i = 0; i < num_module_search_paths; ++i) {
// Create a new FileSpec with this module_search_paths_ptr
// plus just the filename ("UIFoundation"), then the parent
// dir plus filename ("UIFoundation.framework/UIFoundation")
// etc - up to four names (to handle "Foo.framework/Contents/MacOS/Foo")
for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) {
FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i));
// Add the components backwards. For
// .../PrivateFrameworks/UIFoundation.framework/UIFoundation
// path_parts is
// [0] UIFoundation
// [1] UIFoundation.framework
// [2] PrivateFrameworks
//
// and if 'j' is 2, we want to append path_parts[1] and then
// path_parts[0], aka
// 'UIFoundation.framework/UIFoundation', to the module_search_paths_ptr
// path.
for (int k = j; k >= 0; --k) {
path_to_try.AppendPathComponent(path_parts[k]);
}
if (path_to_try.Exists()) {
ModuleSpec new_module_spec(module_spec);
new_module_spec.GetFileSpec() = path_to_try;
Error new_error(Platform::GetSharedModule(
new_module_spec, process, module_sp, NULL, old_module_sp_ptr,
did_create_ptr));
if (module_sp) {
module_sp->SetPlatformFileSpec(path_to_try);
return new_error;
}
}
}
}
}
const bool always_create = false;
error = ModuleList::GetSharedModule(
module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
did_create_ptr, always_create);
if (module_sp)
module_sp->SetPlatformFileSpec(platform_file);
return error;
}
bool PlatformRemoteAppleTV::GetSupportedArchitectureAtIndex(uint32_t idx,
ArchSpec &arch) {
ArchSpec system_arch(GetSystemArchitecture());
@ -860,23 +236,15 @@ bool PlatformRemoteAppleTV::GetSupportedArchitectureAtIndex(uint32_t idx,
return false;
}
uint32_t PlatformRemoteAppleTV::GetConnectedSDKIndex() {
if (IsConnected()) {
if (m_connected_module_sdk_idx == UINT32_MAX) {
std::string build;
if (GetRemoteOSBuildString(build)) {
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
for (uint32_t i = 0; i < num_sdk_infos; ++i) {
const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
if (strstr(sdk_dir_info.directory.GetFilename().AsCString(""),
build.c_str())) {
m_connected_module_sdk_idx = i;
}
}
}
}
} else {
m_connected_module_sdk_idx = UINT32_MAX;
}
return m_connected_module_sdk_idx;
void PlatformRemoteAppleTV::GetDeviceSupportDirectoryNames (std::vector<std::string> &dirnames)
{
dirnames.clear();
dirnames.push_back("tvOS DeviceSupport");
}
std::string PlatformRemoteAppleTV::GetPlatformName ()
{
return "AppleTVOS.platform";
}

View File

@ -20,9 +20,9 @@
#include "llvm/Support/FileSystem.h"
#include "PlatformDarwin.h"
#include "PlatformRemoteDarwinDevice.h"
class PlatformRemoteAppleTV : public PlatformDarwin {
class PlatformRemoteAppleTV : public PlatformRemoteDarwinDevice {
public:
PlatformRemoteAppleTV();
@ -42,9 +42,6 @@ public:
static const char *GetDescriptionStatic();
//------------------------------------------------------------
// Class Methods
//------------------------------------------------------------
//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
@ -57,80 +54,21 @@ public:
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
lldb_private::Error ResolveExecutable(
const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp,
const lldb_private::FileSpecList *module_search_paths_ptr) override;
const char *GetDescription() override { return GetDescriptionStatic(); }
void GetStatus(lldb_private::Stream &strm) override;
virtual lldb_private::Error
GetSymbolFile(const lldb_private::FileSpec &platform_file,
const lldb_private::UUID *uuid_ptr,
lldb_private::FileSpec &local_file);
lldb_private::Error
GetSharedModule(const lldb_private::ModuleSpec &module_spec,
lldb_private::Process *process, lldb::ModuleSP &module_sp,
const lldb_private::FileSpecList *module_search_paths_ptr,
lldb::ModuleSP *old_module_sp_ptr,
bool *did_create_ptr) override;
bool GetSupportedArchitectureAtIndex(uint32_t idx,
lldb_private::ArchSpec &arch) override;
void
AddClangModuleCompilationOptions(lldb_private::Target *target,
std::vector<std::string> &options) override {
return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
target, options, PlatformDarwin::SDKType::iPhoneOS);
}
protected:
struct SDKDirectoryInfo {
SDKDirectoryInfo(const lldb_private::FileSpec &sdk_dir_spec);
lldb_private::FileSpec directory;
lldb_private::ConstString build;
uint32_t version_major;
uint32_t version_minor;
uint32_t version_update;
bool user_cached;
};
typedef std::vector<SDKDirectoryInfo> SDKDirectoryInfoCollection;
std::mutex m_sdk_dir_mutex;
SDKDirectoryInfoCollection m_sdk_directory_infos;
std::string m_device_support_directory;
std::string m_device_support_directory_for_os_version;
std::string m_build_update;
uint32_t m_last_module_sdk_idx;
uint32_t m_connected_module_sdk_idx;
bool UpdateSDKDirectoryInfosIfNeeded();
//------------------------------------------------------------
// lldb_private::PlatformRemoteDarwinDevice functions
//------------------------------------------------------------
const char *GetDeviceSupportDirectory();
void GetDeviceSupportDirectoryNames (std::vector<std::string> &dirnames) override;
const char *GetDeviceSupportDirectoryForOSVersion();
const SDKDirectoryInfo *GetSDKDirectoryForLatestOSVersion();
const SDKDirectoryInfo *GetSDKDirectoryForCurrentOSVersion();
static lldb_private::FileSpec::EnumerateDirectoryResult
GetContainedFilesIntoVectorOfStringsCallback(
void *baton, llvm::sys::fs::file_type ft,
const lldb_private::FileSpec &file_spec);
uint32_t FindFileInAllSDKs(const char *platform_file_path,
lldb_private::FileSpecList &file_list);
bool GetFileInSDK(const char *platform_file_path, uint32_t sdk_idx,
lldb_private::FileSpec &local_file);
uint32_t FindFileInAllSDKs(const lldb_private::FileSpec &platform_file,
lldb_private::FileSpecList &file_list);
uint32_t GetConnectedSDKIndex();
std::string GetPlatformName () override;
private:
DISALLOW_COPY_AND_ASSIGN(PlatformRemoteAppleTV);

View File

@ -33,27 +33,6 @@
using namespace lldb;
using namespace lldb_private;
//------------------------------------------------------------------
/// Default Constructor
//------------------------------------------------------------------
PlatformRemoteAppleWatch::PlatformRemoteAppleWatch()
: PlatformDarwin(false), // This is a remote platform
m_sdk_directory_infos(), m_device_support_directory(),
m_device_support_directory_for_os_version(), m_build_update(),
m_last_module_sdk_idx(UINT32_MAX),
m_connected_module_sdk_idx(UINT32_MAX) {}
PlatformRemoteAppleWatch::SDKDirectoryInfo::SDKDirectoryInfo(
const lldb_private::FileSpec &sdk_dir)
: directory(sdk_dir), build(), version_major(0), version_minor(0),
version_update(0), user_cached(false) {
llvm::StringRef dirname_str = sdk_dir.GetFilename().GetStringRef();
llvm::StringRef build_str;
std::tie(version_major, version_minor, version_update, build_str) =
ParseVersionBuildDir(dirname_str);
build.SetString(build_str);
}
//------------------------------------------------------------------
// Static Variables
//------------------------------------------------------------------
@ -175,618 +154,11 @@ const char *PlatformRemoteAppleWatch::GetDescriptionStatic() {
return "Remote Apple Watch platform plug-in.";
}
void PlatformRemoteAppleWatch::GetStatus(Stream &strm) {
Platform::GetStatus(strm);
const char *sdk_directory = GetDeviceSupportDirectoryForOSVersion();
if (sdk_directory)
strm.Printf(" SDK Path: \"%s\"\n", sdk_directory);
else
strm.PutCString(" SDK Path: error: unable to locate SDK\n");
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
for (uint32_t i = 0; i < num_sdk_infos; ++i) {
const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
strm.Printf(" SDK Roots: [%2u] \"%s\"\n", i,
sdk_dir_info.directory.GetPath().c_str());
}
}
Error PlatformRemoteAppleWatch::ResolveExecutable(
const ModuleSpec &ms, lldb::ModuleSP &exe_module_sp,
const FileSpecList *module_search_paths_ptr) {
Error error;
// Nothing special to do here, just use the actual file and architecture
ModuleSpec resolved_module_spec(ms);
// Resolve any executable within a bundle on MacOSX
// TODO: verify that this handles shallow bundles, if not then implement one
// ourselves
Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
if (resolved_module_spec.GetFileSpec().Exists()) {
if (resolved_module_spec.GetArchitecture().IsValid() ||
resolved_module_spec.GetUUID().IsValid()) {
error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
nullptr, nullptr, nullptr);
if (exe_module_sp && exe_module_sp->GetObjectFile())
return error;
exe_module_sp.reset();
}
// No valid architecture was specified or the exact ARM slice wasn't
// found so ask the platform for the architectures that we should be
// using (in the correct order) and see if we can find a match that way
StreamString arch_names;
for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
idx, resolved_module_spec.GetArchitecture());
++idx) {
error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
nullptr, nullptr, nullptr);
// Did we find an executable using one of the
if (error.Success()) {
if (exe_module_sp && exe_module_sp->GetObjectFile())
break;
else
error.SetErrorToGenericError();
}
if (idx > 0)
arch_names.PutCString(", ");
arch_names.PutCString(
resolved_module_spec.GetArchitecture().GetArchitectureName());
}
if (error.Fail() || !exe_module_sp) {
if (resolved_module_spec.GetFileSpec().Readable()) {
error.SetErrorStringWithFormat(
"'%s' doesn't contain any '%s' platform architectures: %s",
resolved_module_spec.GetFileSpec().GetPath().c_str(),
GetPluginName().GetCString(), arch_names.GetData());
} else {
error.SetErrorStringWithFormat(
"'%s' is not readable",
resolved_module_spec.GetFileSpec().GetPath().c_str());
}
}
} else {
error.SetErrorStringWithFormat(
"'%s' does not exist",
resolved_module_spec.GetFileSpec().GetPath().c_str());
}
return error;
}
FileSpec::EnumerateDirectoryResult
PlatformRemoteAppleWatch::GetContainedFilesIntoVectorOfStringsCallback(
void *baton, llvm::sys::fs::file_type ft, const FileSpec &file_spec) {
((PlatformRemoteAppleWatch::SDKDirectoryInfoCollection *)baton)
->push_back(PlatformRemoteAppleWatch::SDKDirectoryInfo(file_spec));
return FileSpec::eEnumerateDirectoryResultNext;
}
bool PlatformRemoteAppleWatch::UpdateSDKDirectoryInfosIfNeeded() {
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
std::lock_guard<std::mutex> guard(m_sdk_dir_mutex);
if (m_sdk_directory_infos.empty()) {
const char *device_support_dir = GetDeviceSupportDirectory();
if (log) {
log->Printf("PlatformRemoteAppleWatch::UpdateSDKDirectoryInfosIfNeeded "
"Got DeviceSupport directory %s",
device_support_dir);
}
if (device_support_dir) {
const bool find_directories = true;
const bool find_files = false;
const bool find_other = false;
SDKDirectoryInfoCollection builtin_sdk_directory_infos;
FileSpec::EnumerateDirectory(m_device_support_directory, find_directories,
find_files, find_other,
GetContainedFilesIntoVectorOfStringsCallback,
&builtin_sdk_directory_infos);
// Only add SDK directories that have symbols in them, some SDKs only
// contain
// developer disk images and no symbols, so they aren't useful to us.
FileSpec sdk_symbols_symlink_fspec;
for (const auto &sdk_directory_info : builtin_sdk_directory_infos) {
sdk_symbols_symlink_fspec = sdk_directory_info.directory;
sdk_symbols_symlink_fspec.AppendPathComponent("Symbols.Internal");
if (sdk_symbols_symlink_fspec.Exists()) {
m_sdk_directory_infos.push_back(sdk_directory_info);
if (log) {
log->Printf("PlatformRemoteAppleWatch::"
"UpdateSDKDirectoryInfosIfNeeded added builtin SDK "
"directory %s",
sdk_symbols_symlink_fspec.GetPath().c_str());
}
} else {
sdk_symbols_symlink_fspec.GetFilename().SetCString("Symbols");
if (sdk_symbols_symlink_fspec.Exists())
m_sdk_directory_infos.push_back(sdk_directory_info);
if (log) {
log->Printf("PlatformRemoteAppleWatch::"
"UpdateSDKDirectoryInfosIfNeeded added builtin SDK "
"directory %s",
sdk_symbols_symlink_fspec.GetPath().c_str());
}
}
}
const uint32_t num_installed = m_sdk_directory_infos.size();
FileSpec local_sdk_cache(
"~/Library/Developer/Xcode/watchOS DeviceSupport", true);
if (!local_sdk_cache.Exists()) {
local_sdk_cache =
FileSpec("~/Library/Developer/Xcode/watch OS DeviceSupport", true);
}
if (!local_sdk_cache.Exists()) {
local_sdk_cache =
FileSpec("~/Library/Developer/Xcode/WatchOS DeviceSupport", true);
}
if (!local_sdk_cache.Exists()) {
local_sdk_cache =
FileSpec("~/Library/Developer/Xcode/Watch OS DeviceSupport", true);
}
if (local_sdk_cache.Exists()) {
if (log) {
log->Printf("PlatformRemoteAppleWatch::"
"UpdateSDKDirectoryInfosIfNeeded searching %s for "
"additional SDKs",
local_sdk_cache.GetPath().c_str());
}
char path[PATH_MAX];
if (local_sdk_cache.GetPath(path, sizeof(path))) {
FileSpec::EnumerateDirectory(
path, find_directories, find_files, find_other,
GetContainedFilesIntoVectorOfStringsCallback,
&m_sdk_directory_infos);
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
// First try for an exact match of major, minor and update
for (uint32_t i = num_installed; i < num_sdk_infos; ++i) {
m_sdk_directory_infos[i].user_cached = true;
if (log) {
log->Printf("PlatformRemoteAppleWatch::"
"UpdateSDKDirectoryInfosIfNeeded user SDK directory "
"%s",
m_sdk_directory_infos[i].directory.GetPath().c_str());
}
}
}
}
}
}
return !m_sdk_directory_infos.empty();
}
const PlatformRemoteAppleWatch::SDKDirectoryInfo *
PlatformRemoteAppleWatch::GetSDKDirectoryForCurrentOSVersion() {
uint32_t i;
if (UpdateSDKDirectoryInfosIfNeeded()) {
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
// Check to see if the user specified a build string. If they did, then
// be sure to match it.
std::vector<bool> check_sdk_info(num_sdk_infos, true);
ConstString build(m_sdk_build);
if (build) {
for (i = 0; i < num_sdk_infos; ++i)
check_sdk_info[i] = m_sdk_directory_infos[i].build == build;
}
// If we are connected we can find the version of the OS the platform
// us running on and select the right SDK
uint32_t major, minor, update;
if (GetOSVersion(major, minor, update)) {
if (UpdateSDKDirectoryInfosIfNeeded()) {
// First try for an exact match of major, minor and update
for (i = 0; i < num_sdk_infos; ++i) {
if (check_sdk_info[i]) {
if (m_sdk_directory_infos[i].version_major == major &&
m_sdk_directory_infos[i].version_minor == minor &&
m_sdk_directory_infos[i].version_update == update) {
return &m_sdk_directory_infos[i];
}
}
}
// First try for an exact match of major and minor
for (i = 0; i < num_sdk_infos; ++i) {
if (check_sdk_info[i]) {
if (m_sdk_directory_infos[i].version_major == major &&
m_sdk_directory_infos[i].version_minor == minor) {
return &m_sdk_directory_infos[i];
}
}
}
// Lastly try to match of major version only..
for (i = 0; i < num_sdk_infos; ++i) {
if (check_sdk_info[i]) {
if (m_sdk_directory_infos[i].version_major == major) {
return &m_sdk_directory_infos[i];
}
}
}
}
} else if (build) {
// No version, just a build number, search for the first one that matches
for (i = 0; i < num_sdk_infos; ++i)
if (check_sdk_info[i])
return &m_sdk_directory_infos[i];
}
}
return nullptr;
}
const PlatformRemoteAppleWatch::SDKDirectoryInfo *
PlatformRemoteAppleWatch::GetSDKDirectoryForLatestOSVersion() {
const PlatformRemoteAppleWatch::SDKDirectoryInfo *result = nullptr;
if (UpdateSDKDirectoryInfosIfNeeded()) {
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
// First try for an exact match of major, minor and update
for (uint32_t i = 0; i < num_sdk_infos; ++i) {
const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
if (sdk_dir_info.version_major != UINT32_MAX) {
if (result == nullptr ||
sdk_dir_info.version_major > result->version_major) {
result = &sdk_dir_info;
} else if (sdk_dir_info.version_major == result->version_major) {
if (sdk_dir_info.version_minor > result->version_minor) {
result = &sdk_dir_info;
} else if (sdk_dir_info.version_minor == result->version_minor) {
if (sdk_dir_info.version_update > result->version_update) {
result = &sdk_dir_info;
}
}
}
}
}
}
return result;
}
const char *PlatformRemoteAppleWatch::GetDeviceSupportDirectory() {
if (m_device_support_directory.empty()) {
const char *device_support_dir = GetDeveloperDirectory();
if (device_support_dir) {
m_device_support_directory.assign(device_support_dir);
m_device_support_directory.append(
"/Platforms/watchOS.platform/DeviceSupport");
FileSpec platform_device_support_dir(m_device_support_directory, true);
if (!platform_device_support_dir.Exists()) {
std::string alt_platform_dirname = device_support_dir;
alt_platform_dirname.append(
"/Platforms/WatchOS.platform/DeviceSupport");
FileSpec alt_platform_device_support_dir(m_device_support_directory,
true);
if (alt_platform_device_support_dir.Exists()) {
m_device_support_directory = alt_platform_dirname;
}
}
} else {
// Assign a single NULL character so we know we tried to find the device
// support directory and we don't keep trying to find it over and over.
m_device_support_directory.assign(1, '\0');
}
}
// We should have put a single NULL character into m_device_support_directory
// or it should have a valid path if the code gets here
assert(m_device_support_directory.empty() == false);
if (m_device_support_directory[0])
return m_device_support_directory.c_str();
return nullptr;
}
const char *PlatformRemoteAppleWatch::GetDeviceSupportDirectoryForOSVersion() {
if (m_sdk_sysroot)
return m_sdk_sysroot.GetCString();
if (m_device_support_directory_for_os_version.empty()) {
const PlatformRemoteAppleWatch::SDKDirectoryInfo *sdk_dir_info =
GetSDKDirectoryForCurrentOSVersion();
if (sdk_dir_info == nullptr)
sdk_dir_info = GetSDKDirectoryForLatestOSVersion();
if (sdk_dir_info) {
char path[PATH_MAX];
if (sdk_dir_info->directory.GetPath(path, sizeof(path))) {
m_device_support_directory_for_os_version = path;
return m_device_support_directory_for_os_version.c_str();
}
} else {
// Assign a single NULL character so we know we tried to find the device
// support directory and we don't keep trying to find it over and over.
m_device_support_directory_for_os_version.assign(1, '\0');
}
}
// We should have put a single NULL character into
// m_device_support_directory_for_os_version
// or it should have a valid path if the code gets here
assert(m_device_support_directory_for_os_version.empty() == false);
if (m_device_support_directory_for_os_version[0])
return m_device_support_directory_for_os_version.c_str();
return nullptr;
}
uint32_t
PlatformRemoteAppleWatch::FindFileInAllSDKs(const char *platform_file_path,
FileSpecList &file_list) {
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
if (platform_file_path && platform_file_path[0] &&
UpdateSDKDirectoryInfosIfNeeded()) {
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
lldb_private::FileSpec local_file;
// First try for an exact match of major, minor and update
for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) {
LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file_path,
m_sdk_directory_infos[sdk_idx].directory);
if (GetFileInSDK(platform_file_path, sdk_idx, local_file)) {
file_list.Append(local_file);
}
}
}
return file_list.GetSize();
}
bool PlatformRemoteAppleWatch::GetFileInSDK(
const char *platform_file_path, uint32_t sdk_idx,
lldb_private::FileSpec &local_file) {
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
if (sdk_idx < m_sdk_directory_infos.size()) {
std::string sdkroot_path =
m_sdk_directory_infos[sdk_idx].directory.GetPath();
if (!sdkroot_path.empty() && platform_file_path && platform_file_path[0]) {
// We may need to interpose "/Symbols/" or "/Symbols.Internal/" between
// the
// SDK root directory and the file path.
const char *paths_to_try[] = {"Symbols", "", "Symbols.Internal", nullptr};
for (size_t i = 0; paths_to_try[i] != nullptr; i++) {
local_file.SetFile(sdkroot_path, false);
if (paths_to_try[i][0] != '\0')
local_file.AppendPathComponent(paths_to_try[i]);
local_file.AppendPathComponent(platform_file_path);
local_file.ResolvePath();
if (local_file.Exists()) {
if (log)
log->Printf("Found a copy of %s in the SDK dir %s/%s",
platform_file_path, sdkroot_path.c_str(),
paths_to_try[i]);
return true;
}
local_file.Clear();
}
}
}
return false;
}
Error PlatformRemoteAppleWatch::GetSymbolFile(const FileSpec &platform_file,
const UUID *uuid_ptr,
FileSpec &local_file) {
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
Error error;
char platform_file_path[PATH_MAX];
if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
char resolved_path[PATH_MAX];
const char *os_version_dir = GetDeviceSupportDirectoryForOSVersion();
if (os_version_dir) {
::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", os_version_dir,
platform_file_path);
local_file.SetFile(resolved_path, true);
if (local_file.Exists()) {
if (log) {
log->Printf("Found a copy of %s in the DeviceSupport dir %s",
platform_file_path, os_version_dir);
}
return error;
}
::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols.Internal/%s",
os_version_dir, platform_file_path);
local_file.SetFile(resolved_path, true);
if (local_file.Exists()) {
if (log) {
log->Printf(
"Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal",
platform_file_path, os_version_dir);
}
return error;
}
::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols/%s",
os_version_dir, platform_file_path);
local_file.SetFile(resolved_path, true);
if (local_file.Exists()) {
if (log) {
log->Printf("Found a copy of %s in the DeviceSupport dir %s/Symbols",
platform_file_path, os_version_dir);
}
return error;
}
}
local_file = platform_file;
if (local_file.Exists())
return error;
error.SetErrorStringWithFormat(
"unable to locate a platform file for '%s' in platform '%s'",
platform_file_path, GetPluginName().GetCString());
} else {
error.SetErrorString("invalid platform file argument");
}
return error;
}
Error PlatformRemoteAppleWatch::GetSharedModule(
const ModuleSpec &module_spec, lldb_private::Process *process,
ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr,
ModuleSP *old_module_sp_ptr, bool *did_create_ptr) {
// For Apple Watch, the SDK files are all cached locally on the host
// system. So first we ask for the file in the cached SDK,
// then we attempt to get a shared module for the right architecture
// with the right UUID.
const FileSpec &platform_file = module_spec.GetFileSpec();
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
Error error;
char platform_file_path[PATH_MAX];
if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
ModuleSpec platform_module_spec(module_spec);
UpdateSDKDirectoryInfosIfNeeded();
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
// If we are connected we migth be able to correctly deduce the SDK
// directory
// using the OS build.
const uint32_t connected_sdk_idx = GetConnectedSDKIndex();
if (connected_sdk_idx < num_sdk_infos) {
LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
m_sdk_directory_infos[connected_sdk_idx].directory);
if (GetFileInSDK(platform_file_path, connected_sdk_idx,
platform_module_spec.GetFileSpec())) {
module_sp.reset();
error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
if (module_sp) {
m_last_module_sdk_idx = connected_sdk_idx;
error.Clear();
return error;
}
}
}
// Try the last SDK index if it is set as most files from an SDK
// will tend to be valid in that same SDK.
if (m_last_module_sdk_idx < num_sdk_infos) {
LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
m_sdk_directory_infos[m_last_module_sdk_idx].directory);
if (GetFileInSDK(platform_file_path, m_last_module_sdk_idx,
platform_module_spec.GetFileSpec())) {
module_sp.reset();
error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
if (module_sp) {
error.Clear();
return error;
}
}
}
// First try for an exact match of major, minor and update
for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) {
if (m_last_module_sdk_idx == sdk_idx) {
// Skip the last module SDK index if we already searched
// it above
continue;
}
LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
m_sdk_directory_infos[sdk_idx].directory);
if (GetFileInSDK(platform_file_path, sdk_idx,
platform_module_spec.GetFileSpec())) {
// printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());
error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
if (module_sp) {
// Remember the index of the last SDK that we found a file
// in in case the wrong SDK was selected.
m_last_module_sdk_idx = sdk_idx;
error.Clear();
return error;
}
}
}
}
// Not the module we are looking for... Nothing to see here...
module_sp.reset();
// This may not be an SDK-related module. Try whether we can bring in the
// thing to our local cache.
error = GetSharedModuleWithLocalCache(module_spec, module_sp,
module_search_paths_ptr,
old_module_sp_ptr, did_create_ptr);
if (error.Success())
return error;
// See if the file is present in any of the module_search_paths_ptr
// directories.
if (!module_sp && module_search_paths_ptr && platform_file) {
// create a vector of all the file / directory names in platform_file
// e.g. this might be
// /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation
//
// We'll need to look in the module_search_paths_ptr directories for
// both "UIFoundation" and "UIFoundation.framework" -- most likely the
// latter will be the one we find there.
FileSpec platform_pull_apart(platform_file);
std::vector<std::string> path_parts;
ConstString unix_root_dir("/");
while (true) {
ConstString part = platform_pull_apart.GetLastPathComponent();
platform_pull_apart.RemoveLastPathComponent();
if (part.IsEmpty() || part == unix_root_dir)
break;
path_parts.push_back(part.AsCString());
}
const size_t path_parts_size = path_parts.size();
size_t num_module_search_paths = module_search_paths_ptr->GetSize();
for (size_t i = 0; i < num_module_search_paths; ++i) {
// Create a new FileSpec with this module_search_paths_ptr
// plus just the filename ("UIFoundation"), then the parent
// dir plus filename ("UIFoundation.framework/UIFoundation")
// etc - up to four names (to handle "Foo.framework/Contents/MacOS/Foo")
for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) {
FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i));
// Add the components backwards. For
// .../PrivateFrameworks/UIFoundation.framework/UIFoundation
// path_parts is
// [0] UIFoundation
// [1] UIFoundation.framework
// [2] PrivateFrameworks
//
// and if 'j' is 2, we want to append path_parts[1] and then
// path_parts[0], aka
// 'UIFoundation.framework/UIFoundation', to the module_search_paths_ptr
// path.
for (int k = j; k >= 0; --k) {
path_to_try.AppendPathComponent(path_parts[k]);
}
if (path_to_try.Exists()) {
ModuleSpec new_module_spec(module_spec);
new_module_spec.GetFileSpec() = path_to_try;
Error new_error(Platform::GetSharedModule(
new_module_spec, process, module_sp, NULL, old_module_sp_ptr,
did_create_ptr));
if (module_sp) {
module_sp->SetPlatformFileSpec(path_to_try);
return new_error;
}
}
}
}
}
const bool always_create = false;
error = ModuleList::GetSharedModule(
module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
did_create_ptr, always_create);
if (module_sp)
module_sp->SetPlatformFileSpec(platform_file);
return error;
}
//------------------------------------------------------------------
/// Default Constructor
//------------------------------------------------------------------
PlatformRemoteAppleWatch::PlatformRemoteAppleWatch()
: PlatformRemoteDarwinDevice() {}
bool PlatformRemoteAppleWatch::GetSupportedArchitectureAtIndex(uint32_t idx,
ArchSpec &arch) {
@ -923,23 +295,13 @@ bool PlatformRemoteAppleWatch::GetSupportedArchitectureAtIndex(uint32_t idx,
return false;
}
uint32_t PlatformRemoteAppleWatch::GetConnectedSDKIndex() {
if (IsConnected()) {
if (m_connected_module_sdk_idx == UINT32_MAX) {
std::string build;
if (GetRemoteOSBuildString(build)) {
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
for (uint32_t i = 0; i < num_sdk_infos; ++i) {
const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
if (strstr(sdk_dir_info.directory.GetFilename().AsCString(""),
build.c_str())) {
m_connected_module_sdk_idx = i;
}
}
}
}
} else {
m_connected_module_sdk_idx = UINT32_MAX;
}
return m_connected_module_sdk_idx;
void PlatformRemoteAppleWatch::GetDeviceSupportDirectoryNames (std::vector<std::string> &dirnames)
{
dirnames.clear();
dirnames.push_back("watchOS DeviceSupport");
}
std::string PlatformRemoteAppleWatch::GetPlatformName ()
{
return "WatchOS.platform";
}

View File

@ -19,11 +19,11 @@
// Project includes
#include "lldb/Utility/FileSpec.h"
#include "PlatformDarwin.h"
#include "PlatformRemoteDarwinDevice.h"
#include "llvm/Support/FileSystem.h"
class PlatformRemoteAppleWatch : public PlatformDarwin {
class PlatformRemoteAppleWatch : public PlatformRemoteDarwinDevice {
public:
PlatformRemoteAppleWatch();
@ -44,9 +44,11 @@ public:
static const char *GetDescriptionStatic();
//------------------------------------------------------------
// Class Methods
// lldb_private::Platform functions
//------------------------------------------------------------
const char *GetDescription() override { return GetDescriptionStatic(); }
//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
@ -59,80 +61,19 @@ public:
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
lldb_private::Error ResolveExecutable(
const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp,
const lldb_private::FileSpecList *module_search_paths_ptr) override;
const char *GetDescription() override { return GetDescriptionStatic(); }
void GetStatus(lldb_private::Stream &strm) override;
virtual lldb_private::Error
GetSymbolFile(const lldb_private::FileSpec &platform_file,
const lldb_private::UUID *uuid_ptr,
lldb_private::FileSpec &local_file);
lldb_private::Error
GetSharedModule(const lldb_private::ModuleSpec &module_spec,
lldb_private::Process *process, lldb::ModuleSP &module_sp,
const lldb_private::FileSpecList *module_search_paths_ptr,
lldb::ModuleSP *old_module_sp_ptr,
bool *did_create_ptr) override;
bool GetSupportedArchitectureAtIndex(uint32_t idx,
lldb_private::ArchSpec &arch) override;
void
AddClangModuleCompilationOptions(lldb_private::Target *target,
std::vector<std::string> &options) override {
return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
target, options, PlatformDarwin::SDKType::iPhoneOS);
}
protected:
struct SDKDirectoryInfo {
SDKDirectoryInfo(const lldb_private::FileSpec &sdk_dir_spec);
lldb_private::FileSpec directory;
lldb_private::ConstString build;
uint32_t version_major;
uint32_t version_minor;
uint32_t version_update;
bool user_cached;
};
typedef std::vector<SDKDirectoryInfo> SDKDirectoryInfoCollection;
std::mutex m_sdk_dir_mutex;
SDKDirectoryInfoCollection m_sdk_directory_infos;
std::string m_device_support_directory;
std::string m_device_support_directory_for_os_version;
std::string m_build_update;
uint32_t m_last_module_sdk_idx;
uint32_t m_connected_module_sdk_idx;
bool UpdateSDKDirectoryInfosIfNeeded();
//------------------------------------------------------------
// lldb_private::PlatformRemoteDarwinDevice functions
//------------------------------------------------------------
const char *GetDeviceSupportDirectory();
void GetDeviceSupportDirectoryNames (std::vector<std::string> &dirnames) override;
const char *GetDeviceSupportDirectoryForOSVersion();
const SDKDirectoryInfo *GetSDKDirectoryForLatestOSVersion();
const SDKDirectoryInfo *GetSDKDirectoryForCurrentOSVersion();
static lldb_private::FileSpec::EnumerateDirectoryResult
GetContainedFilesIntoVectorOfStringsCallback(
void *baton, llvm::sys::fs::file_type ft,
const lldb_private::FileSpec &file_spec);
uint32_t FindFileInAllSDKs(const char *platform_file_path,
lldb_private::FileSpecList &file_list);
bool GetFileInSDK(const char *platform_file_path, uint32_t sdk_idx,
lldb_private::FileSpec &local_file);
uint32_t FindFileInAllSDKs(const lldb_private::FileSpec &platform_file,
lldb_private::FileSpecList &file_list);
uint32_t GetConnectedSDKIndex();
std::string GetPlatformName () override;
private:
DISALLOW_COPY_AND_ASSIGN(PlatformRemoteAppleWatch);

View File

@ -0,0 +1,712 @@
//===-- PlatformRemoteDarwinDevice.cpp -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "PlatformRemoteDarwinDevice.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/Host.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/Error.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
using namespace lldb;
using namespace lldb_private;
PlatformRemoteDarwinDevice::SDKDirectoryInfo::SDKDirectoryInfo(
const lldb_private::FileSpec &sdk_dir)
: directory(sdk_dir), build(), version_major(0), version_minor(0),
version_update(0), user_cached(false) {
llvm::StringRef dirname_str = sdk_dir.GetFilename().GetStringRef();
llvm::StringRef build_str;
std::tie(version_major, version_minor, version_update, build_str) =
ParseVersionBuildDir(dirname_str);
build.SetString(build_str);
}
//------------------------------------------------------------------
/// Default Constructor
//------------------------------------------------------------------
PlatformRemoteDarwinDevice::PlatformRemoteDarwinDevice()
: PlatformDarwin(false), // This is a remote platform
m_sdk_directory_infos(), m_device_support_directory(),
m_device_support_directory_for_os_version(), m_build_update(),
m_last_module_sdk_idx(UINT32_MAX),
m_connected_module_sdk_idx(UINT32_MAX) {}
//------------------------------------------------------------------
/// Destructor.
///
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
//------------------------------------------------------------------
PlatformRemoteDarwinDevice::~PlatformRemoteDarwinDevice() {}
void PlatformRemoteDarwinDevice::GetStatus(Stream &strm) {
Platform::GetStatus(strm);
const char *sdk_directory = GetDeviceSupportDirectoryForOSVersion();
if (sdk_directory)
strm.Printf(" SDK Path: \"%s\"\n", sdk_directory);
else
strm.PutCString(" SDK Path: error: unable to locate SDK\n");
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
for (uint32_t i = 0; i < num_sdk_infos; ++i) {
const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
strm.Printf(" SDK Roots: [%2u] \"%s\"\n", i,
sdk_dir_info.directory.GetPath().c_str());
}
}
Error PlatformRemoteDarwinDevice::ResolveExecutable(
const ModuleSpec &ms, lldb::ModuleSP &exe_module_sp,
const FileSpecList *module_search_paths_ptr) {
Error error;
// Nothing special to do here, just use the actual file and architecture
ModuleSpec resolved_module_spec(ms);
// Resolve any executable within a bundle on MacOSX
// TODO: verify that this handles shallow bundles, if not then implement one
// ourselves
Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
if (resolved_module_spec.GetFileSpec().Exists()) {
if (resolved_module_spec.GetArchitecture().IsValid() ||
resolved_module_spec.GetUUID().IsValid()) {
error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
NULL, NULL, NULL);
if (exe_module_sp && exe_module_sp->GetObjectFile())
return error;
exe_module_sp.reset();
}
// No valid architecture was specified or the exact ARM slice wasn't
// found so ask the platform for the architectures that we should be
// using (in the correct order) and see if we can find a match that way
StreamString arch_names;
for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
idx, resolved_module_spec.GetArchitecture());
++idx) {
error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
NULL, NULL, NULL);
// Did we find an executable using one of the
if (error.Success()) {
if (exe_module_sp && exe_module_sp->GetObjectFile())
break;
else
error.SetErrorToGenericError();
}
if (idx > 0)
arch_names.PutCString(", ");
arch_names.PutCString(
resolved_module_spec.GetArchitecture().GetArchitectureName());
}
if (error.Fail() || !exe_module_sp) {
if (resolved_module_spec.GetFileSpec().Readable()) {
error.SetErrorStringWithFormat(
"'%s' doesn't contain any '%s' platform architectures: %s",
resolved_module_spec.GetFileSpec().GetPath().c_str(),
GetPluginName().GetCString(), arch_names.GetData());
} else {
error.SetErrorStringWithFormat(
"'%s' is not readable",
resolved_module_spec.GetFileSpec().GetPath().c_str());
}
}
} else {
error.SetErrorStringWithFormat(
"'%s' does not exist",
resolved_module_spec.GetFileSpec().GetPath().c_str());
}
return error;
}
FileSpec::EnumerateDirectoryResult
PlatformRemoteDarwinDevice::GetContainedFilesIntoVectorOfStringsCallback(
void *baton, llvm::sys::fs::file_type ft, const FileSpec &file_spec) {
((PlatformRemoteDarwinDevice::SDKDirectoryInfoCollection *)baton)
->push_back(PlatformRemoteDarwinDevice::SDKDirectoryInfo(file_spec));
return FileSpec::eEnumerateDirectoryResultNext;
}
bool PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded() {
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
std::lock_guard<std::mutex> guard(m_sdk_dir_mutex);
if (m_sdk_directory_infos.empty()) {
// A --sysroot option was supplied - add it to our list of SDKs to check
if (m_sdk_sysroot) {
FileSpec sdk_sysroot_fspec(m_sdk_sysroot.GetCString(), true);
const SDKDirectoryInfo sdk_sysroot_directory_info(sdk_sysroot_fspec);
m_sdk_directory_infos.push_back(sdk_sysroot_directory_info);
if (log) {
log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded added "
"--sysroot SDK directory %s",
m_sdk_sysroot.GetCString());
}
return true;
}
const char *device_support_dir = GetDeviceSupportDirectory();
if (log) {
log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded Got "
"DeviceSupport directory %s",
device_support_dir);
}
if (device_support_dir) {
const bool find_directories = true;
const bool find_files = false;
const bool find_other = false;
SDKDirectoryInfoCollection builtin_sdk_directory_infos;
FileSpec::EnumerateDirectory(m_device_support_directory, find_directories,
find_files, find_other,
GetContainedFilesIntoVectorOfStringsCallback,
&builtin_sdk_directory_infos);
// Only add SDK directories that have symbols in them, some SDKs only
// contain
// developer disk images and no symbols, so they aren't useful to us.
FileSpec sdk_symbols_symlink_fspec;
for (const auto &sdk_directory_info : builtin_sdk_directory_infos) {
sdk_symbols_symlink_fspec = sdk_directory_info.directory;
sdk_symbols_symlink_fspec.AppendPathComponent("Symbols");
if (sdk_symbols_symlink_fspec.Exists()) {
m_sdk_directory_infos.push_back(sdk_directory_info);
if (log) {
log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded "
"added builtin SDK directory %s",
sdk_symbols_symlink_fspec.GetPath().c_str());
}
}
}
std::vector<std::string> device_support_dirnames;
GetDeviceSupportDirectoryNames (device_support_dirnames);
for (std::string &dirname : device_support_dirnames)
{
const uint32_t num_installed = m_sdk_directory_infos.size();
std::string local_sdk_cache_str = "~/Library/Developer/Xcode/";
local_sdk_cache_str += dirname;
FileSpec local_sdk_cache(local_sdk_cache_str.c_str(), true);
if (local_sdk_cache.Exists()) {
if (log) {
log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded "
"searching %s for additional SDKs",
local_sdk_cache.GetPath().c_str());
}
char path[PATH_MAX];
if (local_sdk_cache.GetPath(path, sizeof(path))) {
FileSpec::EnumerateDirectory(
path, find_directories, find_files, find_other,
GetContainedFilesIntoVectorOfStringsCallback,
&m_sdk_directory_infos);
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
// First try for an exact match of major, minor and update
for (uint32_t i = num_installed; i < num_sdk_infos; ++i) {
m_sdk_directory_infos[i].user_cached = true;
if (log) {
log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded "
"user SDK directory %s",
m_sdk_directory_infos[i].directory.GetPath().c_str());
}
}
}
}
}
}
}
return !m_sdk_directory_infos.empty();
}
const PlatformRemoteDarwinDevice::SDKDirectoryInfo *
PlatformRemoteDarwinDevice::GetSDKDirectoryForCurrentOSVersion() {
uint32_t i;
if (UpdateSDKDirectoryInfosIfNeeded()) {
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
// Check to see if the user specified a build string. If they did, then
// be sure to match it.
std::vector<bool> check_sdk_info(num_sdk_infos, true);
ConstString build(m_sdk_build);
if (build) {
for (i = 0; i < num_sdk_infos; ++i)
check_sdk_info[i] = m_sdk_directory_infos[i].build == build;
}
// If we are connected we can find the version of the OS the platform
// us running on and select the right SDK
uint32_t major, minor, update;
if (GetOSVersion(major, minor, update)) {
if (UpdateSDKDirectoryInfosIfNeeded()) {
// First try for an exact match of major, minor and update
for (i = 0; i < num_sdk_infos; ++i) {
if (check_sdk_info[i]) {
if (m_sdk_directory_infos[i].version_major == major &&
m_sdk_directory_infos[i].version_minor == minor &&
m_sdk_directory_infos[i].version_update == update) {
return &m_sdk_directory_infos[i];
}
}
}
// First try for an exact match of major and minor
for (i = 0; i < num_sdk_infos; ++i) {
if (check_sdk_info[i]) {
if (m_sdk_directory_infos[i].version_major == major &&
m_sdk_directory_infos[i].version_minor == minor) {
return &m_sdk_directory_infos[i];
}
}
}
// Lastly try to match of major version only..
for (i = 0; i < num_sdk_infos; ++i) {
if (check_sdk_info[i]) {
if (m_sdk_directory_infos[i].version_major == major) {
return &m_sdk_directory_infos[i];
}
}
}
}
} else if (build) {
// No version, just a build number, search for the first one that matches
for (i = 0; i < num_sdk_infos; ++i)
if (check_sdk_info[i])
return &m_sdk_directory_infos[i];
}
}
return NULL;
}
const PlatformRemoteDarwinDevice::SDKDirectoryInfo *
PlatformRemoteDarwinDevice::GetSDKDirectoryForLatestOSVersion() {
const PlatformRemoteDarwinDevice::SDKDirectoryInfo *result = NULL;
if (UpdateSDKDirectoryInfosIfNeeded()) {
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
// First try for an exact match of major, minor and update
for (uint32_t i = 0; i < num_sdk_infos; ++i) {
const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
if (sdk_dir_info.version_major != UINT32_MAX) {
if (result == NULL ||
sdk_dir_info.version_major > result->version_major) {
result = &sdk_dir_info;
} else if (sdk_dir_info.version_major == result->version_major) {
if (sdk_dir_info.version_minor > result->version_minor) {
result = &sdk_dir_info;
} else if (sdk_dir_info.version_minor == result->version_minor) {
if (sdk_dir_info.version_update > result->version_update) {
result = &sdk_dir_info;
}
}
}
}
}
}
return result;
}
const char *PlatformRemoteDarwinDevice::GetDeviceSupportDirectory() {
std::string platform_dir = "/Platforms/" + GetPlatformName() + "/DeviceSupport";
if (m_device_support_directory.empty()) {
const char *device_support_dir = GetDeveloperDirectory();
if (device_support_dir) {
m_device_support_directory.assign(device_support_dir);
m_device_support_directory.append(platform_dir.c_str());
} else {
// Assign a single NULL character so we know we tried to find the device
// support directory and we don't keep trying to find it over and over.
m_device_support_directory.assign(1, '\0');
}
}
// We should have put a single NULL character into m_device_support_directory
// or it should have a valid path if the code gets here
assert(m_device_support_directory.empty() == false);
if (m_device_support_directory[0])
return m_device_support_directory.c_str();
return NULL;
}
const char *PlatformRemoteDarwinDevice::GetDeviceSupportDirectoryForOSVersion() {
if (m_sdk_sysroot)
return m_sdk_sysroot.GetCString();
if (m_device_support_directory_for_os_version.empty()) {
const PlatformRemoteDarwinDevice::SDKDirectoryInfo *sdk_dir_info =
GetSDKDirectoryForCurrentOSVersion();
if (sdk_dir_info == NULL)
sdk_dir_info = GetSDKDirectoryForLatestOSVersion();
if (sdk_dir_info) {
char path[PATH_MAX];
if (sdk_dir_info->directory.GetPath(path, sizeof(path))) {
m_device_support_directory_for_os_version = path;
return m_device_support_directory_for_os_version.c_str();
}
} else {
// Assign a single NULL character so we know we tried to find the device
// support directory and we don't keep trying to find it over and over.
m_device_support_directory_for_os_version.assign(1, '\0');
}
}
// We should have put a single NULL character into
// m_device_support_directory_for_os_version
// or it should have a valid path if the code gets here
assert(m_device_support_directory_for_os_version.empty() == false);
if (m_device_support_directory_for_os_version[0])
return m_device_support_directory_for_os_version.c_str();
return NULL;
}
uint32_t PlatformRemoteDarwinDevice::FindFileInAllSDKs(const char *platform_file_path,
FileSpecList &file_list) {
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
if (platform_file_path && platform_file_path[0] &&
UpdateSDKDirectoryInfosIfNeeded()) {
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
lldb_private::FileSpec local_file;
// First try for an exact match of major, minor and update
for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) {
LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file_path,
m_sdk_directory_infos[sdk_idx].directory);
if (GetFileInSDK(platform_file_path, sdk_idx, local_file)) {
file_list.Append(local_file);
}
}
}
return file_list.GetSize();
}
bool PlatformRemoteDarwinDevice::GetFileInSDK(const char *platform_file_path,
uint32_t sdk_idx,
lldb_private::FileSpec &local_file) {
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
if (sdk_idx < m_sdk_directory_infos.size()) {
std::string sdkroot_path =
m_sdk_directory_infos[sdk_idx].directory.GetPath();
local_file.Clear();
if (!sdkroot_path.empty() && platform_file_path && platform_file_path[0]) {
// We may need to interpose "/Symbols/" or "/Symbols.Internal/" between
// the
// SDK root directory and the file path.
const char *paths_to_try[] = {"Symbols", "", "Symbols.Internal", nullptr};
for (size_t i = 0; paths_to_try[i] != nullptr; i++) {
local_file.SetFile(sdkroot_path, false);
if (paths_to_try[i][0] != '\0')
local_file.AppendPathComponent(paths_to_try[i]);
local_file.AppendPathComponent(platform_file_path);
local_file.ResolvePath();
if (local_file.Exists()) {
if (log)
log->Printf("Found a copy of %s in the SDK dir %s/%s",
platform_file_path, sdkroot_path.c_str(),
paths_to_try[i]);
return true;
}
local_file.Clear();
}
}
}
return false;
}
Error PlatformRemoteDarwinDevice::GetSymbolFile(const FileSpec &platform_file,
const UUID *uuid_ptr,
FileSpec &local_file) {
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
Error error;
char platform_file_path[PATH_MAX];
if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
char resolved_path[PATH_MAX];
const char *os_version_dir = GetDeviceSupportDirectoryForOSVersion();
if (os_version_dir) {
::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", os_version_dir,
platform_file_path);
local_file.SetFile(resolved_path, true);
if (local_file.Exists()) {
if (log) {
log->Printf("Found a copy of %s in the DeviceSupport dir %s",
platform_file_path, os_version_dir);
}
return error;
}
::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols.Internal/%s",
os_version_dir, platform_file_path);
local_file.SetFile(resolved_path, true);
if (local_file.Exists()) {
if (log) {
log->Printf(
"Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal",
platform_file_path, os_version_dir);
}
return error;
}
::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols/%s",
os_version_dir, platform_file_path);
local_file.SetFile(resolved_path, true);
if (local_file.Exists()) {
if (log) {
log->Printf("Found a copy of %s in the DeviceSupport dir %s/Symbols",
platform_file_path, os_version_dir);
}
return error;
}
}
local_file = platform_file;
if (local_file.Exists())
return error;
error.SetErrorStringWithFormat(
"unable to locate a platform file for '%s' in platform '%s'",
platform_file_path, GetPluginName().GetCString());
} else {
error.SetErrorString("invalid platform file argument");
}
return error;
}
Error PlatformRemoteDarwinDevice::GetSharedModule(
const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr,
bool *did_create_ptr) {
// For iOS, the SDK files are all cached locally on the host
// system. So first we ask for the file in the cached SDK,
// then we attempt to get a shared module for the right architecture
// with the right UUID.
const FileSpec &platform_file = module_spec.GetFileSpec();
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
Error error;
char platform_file_path[PATH_MAX];
if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
ModuleSpec platform_module_spec(module_spec);
UpdateSDKDirectoryInfosIfNeeded();
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
// If we are connected we migth be able to correctly deduce the SDK
// directory
// using the OS build.
const uint32_t connected_sdk_idx = GetConnectedSDKIndex();
if (connected_sdk_idx < num_sdk_infos) {
LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
m_sdk_directory_infos[connected_sdk_idx].directory);
if (GetFileInSDK(platform_file_path, connected_sdk_idx,
platform_module_spec.GetFileSpec())) {
module_sp.reset();
error = ResolveExecutable(platform_module_spec, module_sp, NULL);
if (module_sp) {
m_last_module_sdk_idx = connected_sdk_idx;
error.Clear();
return error;
}
}
}
// Try the last SDK index if it is set as most files from an SDK
// will tend to be valid in that same SDK.
if (m_last_module_sdk_idx < num_sdk_infos) {
LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
m_sdk_directory_infos[m_last_module_sdk_idx].directory);
if (GetFileInSDK(platform_file_path, m_last_module_sdk_idx,
platform_module_spec.GetFileSpec())) {
module_sp.reset();
error = ResolveExecutable(platform_module_spec, module_sp, NULL);
if (module_sp) {
error.Clear();
return error;
}
}
}
// First try for an exact match of major, minor and update:
// If a particalar SDK version was specified via --version or --build, look
// for a match on disk.
const SDKDirectoryInfo *current_sdk_info =
GetSDKDirectoryForCurrentOSVersion();
const uint32_t current_sdk_idx =
GetSDKIndexBySDKDirectoryInfo(current_sdk_info);
if (current_sdk_idx < num_sdk_infos &&
current_sdk_idx != m_last_module_sdk_idx) {
LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
m_sdk_directory_infos[current_sdk_idx].directory);
if (GetFileInSDK(platform_file_path, current_sdk_idx,
platform_module_spec.GetFileSpec())) {
module_sp.reset();
error = ResolveExecutable(platform_module_spec, module_sp, NULL);
if (module_sp) {
m_last_module_sdk_idx = current_sdk_idx;
error.Clear();
return error;
}
}
}
// Second try all SDKs that were found.
for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) {
if (m_last_module_sdk_idx == sdk_idx) {
// Skip the last module SDK index if we already searched
// it above
continue;
}
LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
m_sdk_directory_infos[sdk_idx].directory);
if (GetFileInSDK(platform_file_path, sdk_idx,
platform_module_spec.GetFileSpec())) {
// printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());
error = ResolveExecutable(platform_module_spec, module_sp, NULL);
if (module_sp) {
// Remember the index of the last SDK that we found a file
// in in case the wrong SDK was selected.
m_last_module_sdk_idx = sdk_idx;
error.Clear();
return error;
}
}
}
}
// Not the module we are looking for... Nothing to see here...
module_sp.reset();
// This may not be an SDK-related module. Try whether we can bring in the
// thing to our local cache.
error = GetSharedModuleWithLocalCache(module_spec, module_sp,
module_search_paths_ptr,
old_module_sp_ptr, did_create_ptr);
if (error.Success())
return error;
// See if the file is present in any of the module_search_paths_ptr
// directories.
if (!module_sp && module_search_paths_ptr && platform_file) {
// create a vector of all the file / directory names in platform_file
// e.g. this might be
// /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation
//
// We'll need to look in the module_search_paths_ptr directories for
// both "UIFoundation" and "UIFoundation.framework" -- most likely the
// latter will be the one we find there.
FileSpec platform_pull_apart(platform_file);
std::vector<std::string> path_parts;
ConstString unix_root_dir("/");
while (true) {
ConstString part = platform_pull_apart.GetLastPathComponent();
platform_pull_apart.RemoveLastPathComponent();
if (part.IsEmpty() || part == unix_root_dir)
break;
path_parts.push_back(part.AsCString());
}
const size_t path_parts_size = path_parts.size();
size_t num_module_search_paths = module_search_paths_ptr->GetSize();
for (size_t i = 0; i < num_module_search_paths; ++i) {
LLDB_LOGV(log, "searching for binary in search-path {0}",
module_search_paths_ptr->GetFileSpecAtIndex(i));
// Create a new FileSpec with this module_search_paths_ptr
// plus just the filename ("UIFoundation"), then the parent
// dir plus filename ("UIFoundation.framework/UIFoundation")
// etc - up to four names (to handle "Foo.framework/Contents/MacOS/Foo")
for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) {
FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i));
// Add the components backwards. For
// .../PrivateFrameworks/UIFoundation.framework/UIFoundation
// path_parts is
// [0] UIFoundation
// [1] UIFoundation.framework
// [2] PrivateFrameworks
//
// and if 'j' is 2, we want to append path_parts[1] and then
// path_parts[0], aka
// 'UIFoundation.framework/UIFoundation', to the module_search_paths_ptr
// path.
for (int k = j; k >= 0; --k) {
path_to_try.AppendPathComponent(path_parts[k]);
}
if (path_to_try.Exists()) {
ModuleSpec new_module_spec(module_spec);
new_module_spec.GetFileSpec() = path_to_try;
Error new_error(Platform::GetSharedModule(
new_module_spec, process, module_sp, NULL, old_module_sp_ptr,
did_create_ptr));
if (module_sp) {
module_sp->SetPlatformFileSpec(path_to_try);
return new_error;
}
}
}
}
}
const bool always_create = false;
error = ModuleList::GetSharedModule(
module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
did_create_ptr, always_create);
if (module_sp)
module_sp->SetPlatformFileSpec(platform_file);
return error;
}
uint32_t PlatformRemoteDarwinDevice::GetConnectedSDKIndex() {
if (IsConnected()) {
if (m_connected_module_sdk_idx == UINT32_MAX) {
std::string build;
if (GetRemoteOSBuildString(build)) {
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
for (uint32_t i = 0; i < num_sdk_infos; ++i) {
const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
if (strstr(sdk_dir_info.directory.GetFilename().AsCString(""),
build.c_str())) {
m_connected_module_sdk_idx = i;
}
}
}
}
} else {
m_connected_module_sdk_idx = UINT32_MAX;
}
return m_connected_module_sdk_idx;
}
uint32_t PlatformRemoteDarwinDevice::GetSDKIndexBySDKDirectoryInfo(
const SDKDirectoryInfo *sdk_info) {
if (sdk_info == NULL) {
return UINT32_MAX;
}
return sdk_info - &m_sdk_directory_infos[0];
}

View File

@ -0,0 +1,118 @@
//===-- PlatformRemoteDarwinDevice.h -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_PlatformRemoteDarwinDevice_h_
#define liblldb_PlatformRemoteDarwinDevice_h_
// C Includes
// C++ Includes
#include <string>
// Other libraries and framework includes
// Project includes
#include "PlatformDarwin.h"
#include "lldb/Utility/FileSpec.h"
#include "llvm/Support/FileSystem.h"
class PlatformRemoteDarwinDevice : public PlatformDarwin {
public:
PlatformRemoteDarwinDevice();
~PlatformRemoteDarwinDevice() override;
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
lldb_private::Error ResolveExecutable(
const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp,
const lldb_private::FileSpecList *module_search_paths_ptr) override;
void GetStatus(lldb_private::Stream &strm) override;
virtual lldb_private::Error
GetSymbolFile(const lldb_private::FileSpec &platform_file,
const lldb_private::UUID *uuid_ptr,
lldb_private::FileSpec &local_file);
lldb_private::Error
GetSharedModule(const lldb_private::ModuleSpec &module_spec,
lldb_private::Process *process, lldb::ModuleSP &module_sp,
const lldb_private::FileSpecList *module_search_paths_ptr,
lldb::ModuleSP *old_module_sp_ptr,
bool *did_create_ptr) override;
void
AddClangModuleCompilationOptions(lldb_private::Target *target,
std::vector<std::string> &options) override {
return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
target, options, PlatformDarwin::SDKType::iPhoneOS);
}
protected:
struct SDKDirectoryInfo {
SDKDirectoryInfo(const lldb_private::FileSpec &sdk_dir_spec);
lldb_private::FileSpec directory;
lldb_private::ConstString build;
uint32_t version_major;
uint32_t version_minor;
uint32_t version_update;
bool user_cached;
};
typedef std::vector<SDKDirectoryInfo> SDKDirectoryInfoCollection;
std::mutex m_sdk_dir_mutex;
SDKDirectoryInfoCollection m_sdk_directory_infos;
std::string m_device_support_directory;
std::string m_device_support_directory_for_os_version;
std::string m_build_update;
uint32_t m_last_module_sdk_idx;
uint32_t m_connected_module_sdk_idx;
bool UpdateSDKDirectoryInfosIfNeeded();
const char *GetDeviceSupportDirectory();
const char *GetDeviceSupportDirectoryForOSVersion();
const SDKDirectoryInfo *GetSDKDirectoryForLatestOSVersion();
const SDKDirectoryInfo *GetSDKDirectoryForCurrentOSVersion();
static lldb_private::FileSpec::EnumerateDirectoryResult
GetContainedFilesIntoVectorOfStringsCallback(
void *baton, llvm::sys::fs::file_type ft,
const lldb_private::FileSpec &file_spec);
uint32_t FindFileInAllSDKs(const char *platform_file_path,
lldb_private::FileSpecList &file_list);
bool GetFileInSDK(const char *platform_file_path, uint32_t sdk_idx,
lldb_private::FileSpec &local_file);
uint32_t FindFileInAllSDKs(const lldb_private::FileSpec &platform_file,
lldb_private::FileSpecList &file_list);
uint32_t GetConnectedSDKIndex();
// Get index of SDK in SDKDirectoryInfoCollection by its pointer and return
// UINT32_MAX if that SDK not found.
uint32_t GetSDKIndexBySDKDirectoryInfo(const SDKDirectoryInfo *sdk_info);
virtual void GetDeviceSupportDirectoryNames (std::vector<std::string> &dirnames) = 0;
virtual std::string GetPlatformName () = 0;
private:
DISALLOW_COPY_AND_ASSIGN(PlatformRemoteDarwinDevice);
};
#endif // liblldb_PlatformRemoteDarwinDevice_h_

View File

@ -30,17 +30,6 @@
using namespace lldb;
using namespace lldb_private;
PlatformRemoteiOS::SDKDirectoryInfo::SDKDirectoryInfo(
const lldb_private::FileSpec &sdk_dir)
: directory(sdk_dir), build(), version_major(0), version_minor(0),
version_update(0), user_cached(false) {
llvm::StringRef dirname_str = sdk_dir.GetFilename().GetStringRef();
llvm::StringRef build_str;
std::tie(version_major, version_minor, version_update, build_str) =
ParseVersionBuildDir(dirname_str);
build.SetString(build_str);
}
//------------------------------------------------------------------
// Static Variables
//------------------------------------------------------------------
@ -156,666 +145,21 @@ const char *PlatformRemoteiOS::GetDescriptionStatic() {
/// Default Constructor
//------------------------------------------------------------------
PlatformRemoteiOS::PlatformRemoteiOS()
: PlatformDarwin(false), // This is a remote platform
m_sdk_directory_infos(), m_device_support_directory(),
m_device_support_directory_for_os_version(), m_build_update(),
m_last_module_sdk_idx(UINT32_MAX),
m_connected_module_sdk_idx(UINT32_MAX) {}
//------------------------------------------------------------------
/// Destructor.
///
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
//------------------------------------------------------------------
PlatformRemoteiOS::~PlatformRemoteiOS() {}
void PlatformRemoteiOS::GetStatus(Stream &strm) {
Platform::GetStatus(strm);
const char *sdk_directory = GetDeviceSupportDirectoryForOSVersion();
if (sdk_directory)
strm.Printf(" SDK Path: \"%s\"\n", sdk_directory);
else
strm.PutCString(" SDK Path: error: unable to locate SDK\n");
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
for (uint32_t i = 0; i < num_sdk_infos; ++i) {
const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
strm.Printf(" SDK Roots: [%2u] \"%s\"\n", i,
sdk_dir_info.directory.GetPath().c_str());
}
}
Error PlatformRemoteiOS::ResolveExecutable(
const ModuleSpec &ms, lldb::ModuleSP &exe_module_sp,
const FileSpecList *module_search_paths_ptr) {
Error error;
// Nothing special to do here, just use the actual file and architecture
ModuleSpec resolved_module_spec(ms);
// Resolve any executable within a bundle on MacOSX
// TODO: verify that this handles shallow bundles, if not then implement one
// ourselves
Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
if (resolved_module_spec.GetFileSpec().Exists()) {
if (resolved_module_spec.GetArchitecture().IsValid() ||
resolved_module_spec.GetUUID().IsValid()) {
error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
NULL, NULL, NULL);
if (exe_module_sp && exe_module_sp->GetObjectFile())
return error;
exe_module_sp.reset();
}
// No valid architecture was specified or the exact ARM slice wasn't
// found so ask the platform for the architectures that we should be
// using (in the correct order) and see if we can find a match that way
StreamString arch_names;
for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
idx, resolved_module_spec.GetArchitecture());
++idx) {
error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
NULL, NULL, NULL);
// Did we find an executable using one of the
if (error.Success()) {
if (exe_module_sp && exe_module_sp->GetObjectFile())
break;
else
error.SetErrorToGenericError();
}
if (idx > 0)
arch_names.PutCString(", ");
arch_names.PutCString(
resolved_module_spec.GetArchitecture().GetArchitectureName());
}
if (error.Fail() || !exe_module_sp) {
if (resolved_module_spec.GetFileSpec().Readable()) {
error.SetErrorStringWithFormat(
"'%s' doesn't contain any '%s' platform architectures: %s",
resolved_module_spec.GetFileSpec().GetPath().c_str(),
GetPluginName().GetCString(), arch_names.GetData());
} else {
error.SetErrorStringWithFormat(
"'%s' is not readable",
resolved_module_spec.GetFileSpec().GetPath().c_str());
}
}
} else {
error.SetErrorStringWithFormat(
"'%s' does not exist",
resolved_module_spec.GetFileSpec().GetPath().c_str());
}
return error;
}
FileSpec::EnumerateDirectoryResult
PlatformRemoteiOS::GetContainedFilesIntoVectorOfStringsCallback(
void *baton, llvm::sys::fs::file_type ft, const FileSpec &file_spec) {
((PlatformRemoteiOS::SDKDirectoryInfoCollection *)baton)
->push_back(PlatformRemoteiOS::SDKDirectoryInfo(file_spec));
return FileSpec::eEnumerateDirectoryResultNext;
}
bool PlatformRemoteiOS::UpdateSDKDirectoryInfosIfNeeded() {
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
std::lock_guard<std::mutex> guard(m_sdk_dir_mutex);
if (m_sdk_directory_infos.empty()) {
// A --sysroot option was supplied - add it to our list of SDKs to check
if (m_sdk_sysroot) {
FileSpec sdk_sysroot_fspec(m_sdk_sysroot.GetCString(), true);
const SDKDirectoryInfo sdk_sysroot_directory_info(sdk_sysroot_fspec);
m_sdk_directory_infos.push_back(sdk_sysroot_directory_info);
if (log) {
log->Printf("PlatformRemoteiOS::UpdateSDKDirectoryInfosIfNeeded added "
"--sysroot SDK directory %s",
m_sdk_sysroot.GetCString());
}
return true;
}
const char *device_support_dir = GetDeviceSupportDirectory();
if (log) {
log->Printf("PlatformRemoteiOS::UpdateSDKDirectoryInfosIfNeeded Got "
"DeviceSupport directory %s",
device_support_dir);
}
if (device_support_dir) {
const bool find_directories = true;
const bool find_files = false;
const bool find_other = false;
SDKDirectoryInfoCollection builtin_sdk_directory_infos;
FileSpec::EnumerateDirectory(m_device_support_directory, find_directories,
find_files, find_other,
GetContainedFilesIntoVectorOfStringsCallback,
&builtin_sdk_directory_infos);
// Only add SDK directories that have symbols in them, some SDKs only
// contain
// developer disk images and no symbols, so they aren't useful to us.
FileSpec sdk_symbols_symlink_fspec;
for (const auto &sdk_directory_info : builtin_sdk_directory_infos) {
sdk_symbols_symlink_fspec = sdk_directory_info.directory;
sdk_symbols_symlink_fspec.AppendPathComponent("Symbols");
if (sdk_symbols_symlink_fspec.Exists()) {
m_sdk_directory_infos.push_back(sdk_directory_info);
if (log) {
log->Printf("PlatformRemoteiOS::UpdateSDKDirectoryInfosIfNeeded "
"added builtin SDK directory %s",
sdk_symbols_symlink_fspec.GetPath().c_str());
}
}
}
const uint32_t num_installed = m_sdk_directory_infos.size();
FileSpec local_sdk_cache("~/Library/Developer/Xcode/iOS DeviceSupport",
true);
if (local_sdk_cache.Exists()) {
if (log) {
log->Printf("PlatformRemoteiOS::UpdateSDKDirectoryInfosIfNeeded "
"searching %s for additional SDKs",
local_sdk_cache.GetPath().c_str());
}
char path[PATH_MAX];
if (local_sdk_cache.GetPath(path, sizeof(path))) {
FileSpec::EnumerateDirectory(
path, find_directories, find_files, find_other,
GetContainedFilesIntoVectorOfStringsCallback,
&m_sdk_directory_infos);
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
// First try for an exact match of major, minor and update
for (uint32_t i = num_installed; i < num_sdk_infos; ++i) {
m_sdk_directory_infos[i].user_cached = true;
if (log) {
log->Printf("PlatformRemoteiOS::UpdateSDKDirectoryInfosIfNeeded "
"user SDK directory %s",
m_sdk_directory_infos[i].directory.GetPath().c_str());
}
}
}
}
}
}
return !m_sdk_directory_infos.empty();
}
const PlatformRemoteiOS::SDKDirectoryInfo *
PlatformRemoteiOS::GetSDKDirectoryForCurrentOSVersion() {
uint32_t i;
if (UpdateSDKDirectoryInfosIfNeeded()) {
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
// Check to see if the user specified a build string. If they did, then
// be sure to match it.
std::vector<bool> check_sdk_info(num_sdk_infos, true);
ConstString build(m_sdk_build);
if (build) {
for (i = 0; i < num_sdk_infos; ++i)
check_sdk_info[i] = m_sdk_directory_infos[i].build == build;
}
// If we are connected we can find the version of the OS the platform
// us running on and select the right SDK
uint32_t major, minor, update;
if (GetOSVersion(major, minor, update)) {
if (UpdateSDKDirectoryInfosIfNeeded()) {
// First try for an exact match of major, minor and update
for (i = 0; i < num_sdk_infos; ++i) {
if (check_sdk_info[i]) {
if (m_sdk_directory_infos[i].version_major == major &&
m_sdk_directory_infos[i].version_minor == minor &&
m_sdk_directory_infos[i].version_update == update) {
return &m_sdk_directory_infos[i];
}
}
}
// First try for an exact match of major and minor
for (i = 0; i < num_sdk_infos; ++i) {
if (check_sdk_info[i]) {
if (m_sdk_directory_infos[i].version_major == major &&
m_sdk_directory_infos[i].version_minor == minor) {
return &m_sdk_directory_infos[i];
}
}
}
// Lastly try to match of major version only..
for (i = 0; i < num_sdk_infos; ++i) {
if (check_sdk_info[i]) {
if (m_sdk_directory_infos[i].version_major == major) {
return &m_sdk_directory_infos[i];
}
}
}
}
} else if (build) {
// No version, just a build number, search for the first one that matches
for (i = 0; i < num_sdk_infos; ++i)
if (check_sdk_info[i])
return &m_sdk_directory_infos[i];
}
}
return NULL;
}
const PlatformRemoteiOS::SDKDirectoryInfo *
PlatformRemoteiOS::GetSDKDirectoryForLatestOSVersion() {
const PlatformRemoteiOS::SDKDirectoryInfo *result = NULL;
if (UpdateSDKDirectoryInfosIfNeeded()) {
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
// First try for an exact match of major, minor and update
for (uint32_t i = 0; i < num_sdk_infos; ++i) {
const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
if (sdk_dir_info.version_major != UINT32_MAX) {
if (result == NULL ||
sdk_dir_info.version_major > result->version_major) {
result = &sdk_dir_info;
} else if (sdk_dir_info.version_major == result->version_major) {
if (sdk_dir_info.version_minor > result->version_minor) {
result = &sdk_dir_info;
} else if (sdk_dir_info.version_minor == result->version_minor) {
if (sdk_dir_info.version_update > result->version_update) {
result = &sdk_dir_info;
}
}
}
}
}
}
return result;
}
const char *PlatformRemoteiOS::GetDeviceSupportDirectory() {
if (m_device_support_directory.empty()) {
const char *device_support_dir = GetDeveloperDirectory();
if (device_support_dir) {
m_device_support_directory.assign(device_support_dir);
m_device_support_directory.append(
"/Platforms/iPhoneOS.platform/DeviceSupport");
} else {
// Assign a single NULL character so we know we tried to find the device
// support directory and we don't keep trying to find it over and over.
m_device_support_directory.assign(1, '\0');
}
}
// We should have put a single NULL character into m_device_support_directory
// or it should have a valid path if the code gets here
assert(m_device_support_directory.empty() == false);
if (m_device_support_directory[0])
return m_device_support_directory.c_str();
return NULL;
}
const char *PlatformRemoteiOS::GetDeviceSupportDirectoryForOSVersion() {
if (m_sdk_sysroot)
return m_sdk_sysroot.GetCString();
if (m_device_support_directory_for_os_version.empty()) {
const PlatformRemoteiOS::SDKDirectoryInfo *sdk_dir_info =
GetSDKDirectoryForCurrentOSVersion();
if (sdk_dir_info == NULL)
sdk_dir_info = GetSDKDirectoryForLatestOSVersion();
if (sdk_dir_info) {
char path[PATH_MAX];
if (sdk_dir_info->directory.GetPath(path, sizeof(path))) {
m_device_support_directory_for_os_version = path;
return m_device_support_directory_for_os_version.c_str();
}
} else {
// Assign a single NULL character so we know we tried to find the device
// support directory and we don't keep trying to find it over and over.
m_device_support_directory_for_os_version.assign(1, '\0');
}
}
// We should have put a single NULL character into
// m_device_support_directory_for_os_version
// or it should have a valid path if the code gets here
assert(m_device_support_directory_for_os_version.empty() == false);
if (m_device_support_directory_for_os_version[0])
return m_device_support_directory_for_os_version.c_str();
return NULL;
}
uint32_t PlatformRemoteiOS::FindFileInAllSDKs(const char *platform_file_path,
FileSpecList &file_list) {
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
if (platform_file_path && platform_file_path[0] &&
UpdateSDKDirectoryInfosIfNeeded()) {
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
lldb_private::FileSpec local_file;
// First try for an exact match of major, minor and update
for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) {
LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file_path,
m_sdk_directory_infos[sdk_idx].directory);
if (GetFileInSDK(platform_file_path, sdk_idx, local_file)) {
file_list.Append(local_file);
}
}
}
return file_list.GetSize();
}
bool PlatformRemoteiOS::GetFileInSDK(const char *platform_file_path,
uint32_t sdk_idx,
lldb_private::FileSpec &local_file) {
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
if (sdk_idx < m_sdk_directory_infos.size()) {
std::string sdkroot_path =
m_sdk_directory_infos[sdk_idx].directory.GetPath();
local_file.Clear();
if (!sdkroot_path.empty() && platform_file_path && platform_file_path[0]) {
// We may need to interpose "/Symbols/" or "/Symbols.Internal/" between
// the
// SDK root directory and the file path.
const char *paths_to_try[] = {"Symbols", "", "Symbols.Internal", nullptr};
for (size_t i = 0; paths_to_try[i] != nullptr; i++) {
local_file.SetFile(sdkroot_path, false);
if (paths_to_try[i][0] != '\0')
local_file.AppendPathComponent(paths_to_try[i]);
local_file.AppendPathComponent(platform_file_path);
local_file.ResolvePath();
if (local_file.Exists()) {
if (log)
log->Printf("Found a copy of %s in the SDK dir %s/%s",
platform_file_path, sdkroot_path.c_str(),
paths_to_try[i]);
return true;
}
local_file.Clear();
}
}
}
return false;
}
Error PlatformRemoteiOS::GetSymbolFile(const FileSpec &platform_file,
const UUID *uuid_ptr,
FileSpec &local_file) {
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
Error error;
char platform_file_path[PATH_MAX];
if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
char resolved_path[PATH_MAX];
const char *os_version_dir = GetDeviceSupportDirectoryForOSVersion();
if (os_version_dir) {
::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", os_version_dir,
platform_file_path);
local_file.SetFile(resolved_path, true);
if (local_file.Exists()) {
if (log) {
log->Printf("Found a copy of %s in the DeviceSupport dir %s",
platform_file_path, os_version_dir);
}
return error;
}
::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols.Internal/%s",
os_version_dir, platform_file_path);
local_file.SetFile(resolved_path, true);
if (local_file.Exists()) {
if (log) {
log->Printf(
"Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal",
platform_file_path, os_version_dir);
}
return error;
}
::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols/%s",
os_version_dir, platform_file_path);
local_file.SetFile(resolved_path, true);
if (local_file.Exists()) {
if (log) {
log->Printf("Found a copy of %s in the DeviceSupport dir %s/Symbols",
platform_file_path, os_version_dir);
}
return error;
}
}
local_file = platform_file;
if (local_file.Exists())
return error;
error.SetErrorStringWithFormat(
"unable to locate a platform file for '%s' in platform '%s'",
platform_file_path, GetPluginName().GetCString());
} else {
error.SetErrorString("invalid platform file argument");
}
return error;
}
Error PlatformRemoteiOS::GetSharedModule(
const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr,
bool *did_create_ptr) {
// For iOS, the SDK files are all cached locally on the host
// system. So first we ask for the file in the cached SDK,
// then we attempt to get a shared module for the right architecture
// with the right UUID.
const FileSpec &platform_file = module_spec.GetFileSpec();
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
Error error;
char platform_file_path[PATH_MAX];
if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
ModuleSpec platform_module_spec(module_spec);
UpdateSDKDirectoryInfosIfNeeded();
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
// If we are connected we migth be able to correctly deduce the SDK
// directory
// using the OS build.
const uint32_t connected_sdk_idx = GetConnectedSDKIndex();
if (connected_sdk_idx < num_sdk_infos) {
LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
m_sdk_directory_infos[connected_sdk_idx].directory);
if (GetFileInSDK(platform_file_path, connected_sdk_idx,
platform_module_spec.GetFileSpec())) {
module_sp.reset();
error = ResolveExecutable(platform_module_spec, module_sp, NULL);
if (module_sp) {
m_last_module_sdk_idx = connected_sdk_idx;
error.Clear();
return error;
}
}
}
// Try the last SDK index if it is set as most files from an SDK
// will tend to be valid in that same SDK.
if (m_last_module_sdk_idx < num_sdk_infos) {
LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
m_sdk_directory_infos[m_last_module_sdk_idx].directory);
if (GetFileInSDK(platform_file_path, m_last_module_sdk_idx,
platform_module_spec.GetFileSpec())) {
module_sp.reset();
error = ResolveExecutable(platform_module_spec, module_sp, NULL);
if (module_sp) {
error.Clear();
return error;
}
}
}
// First try for an exact match of major, minor and update:
// If a particalar SDK version was specified via --version or --build, look
// for a match on disk.
const SDKDirectoryInfo *current_sdk_info =
GetSDKDirectoryForCurrentOSVersion();
const uint32_t current_sdk_idx =
GetSDKIndexBySDKDirectoryInfo(current_sdk_info);
if (current_sdk_idx < num_sdk_infos &&
current_sdk_idx != m_last_module_sdk_idx) {
LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
m_sdk_directory_infos[current_sdk_idx].directory);
if (GetFileInSDK(platform_file_path, current_sdk_idx,
platform_module_spec.GetFileSpec())) {
module_sp.reset();
error = ResolveExecutable(platform_module_spec, module_sp, NULL);
if (module_sp) {
m_last_module_sdk_idx = current_sdk_idx;
error.Clear();
return error;
}
}
}
// Second try all SDKs that were found.
for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) {
if (m_last_module_sdk_idx == sdk_idx) {
// Skip the last module SDK index if we already searched
// it above
continue;
}
LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
m_sdk_directory_infos[sdk_idx].directory);
if (GetFileInSDK(platform_file_path, sdk_idx,
platform_module_spec.GetFileSpec())) {
// printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());
error = ResolveExecutable(platform_module_spec, module_sp, NULL);
if (module_sp) {
// Remember the index of the last SDK that we found a file
// in in case the wrong SDK was selected.
m_last_module_sdk_idx = sdk_idx;
error.Clear();
return error;
}
}
}
}
// Not the module we are looking for... Nothing to see here...
module_sp.reset();
// This may not be an SDK-related module. Try whether we can bring in the
// thing to our local cache.
error = GetSharedModuleWithLocalCache(module_spec, module_sp,
module_search_paths_ptr,
old_module_sp_ptr, did_create_ptr);
if (error.Success())
return error;
// See if the file is present in any of the module_search_paths_ptr
// directories.
if (!module_sp && module_search_paths_ptr && platform_file) {
// create a vector of all the file / directory names in platform_file
// e.g. this might be
// /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation
//
// We'll need to look in the module_search_paths_ptr directories for
// both "UIFoundation" and "UIFoundation.framework" -- most likely the
// latter will be the one we find there.
FileSpec platform_pull_apart(platform_file);
std::vector<std::string> path_parts;
ConstString unix_root_dir("/");
while (true) {
ConstString part = platform_pull_apart.GetLastPathComponent();
platform_pull_apart.RemoveLastPathComponent();
if (part.IsEmpty() || part == unix_root_dir)
break;
path_parts.push_back(part.AsCString());
}
const size_t path_parts_size = path_parts.size();
size_t num_module_search_paths = module_search_paths_ptr->GetSize();
for (size_t i = 0; i < num_module_search_paths; ++i) {
LLDB_LOGV(log, "searching for binary in search-path {0}",
module_search_paths_ptr->GetFileSpecAtIndex(i));
// Create a new FileSpec with this module_search_paths_ptr
// plus just the filename ("UIFoundation"), then the parent
// dir plus filename ("UIFoundation.framework/UIFoundation")
// etc - up to four names (to handle "Foo.framework/Contents/MacOS/Foo")
for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) {
FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i));
// Add the components backwards. For
// .../PrivateFrameworks/UIFoundation.framework/UIFoundation
// path_parts is
// [0] UIFoundation
// [1] UIFoundation.framework
// [2] PrivateFrameworks
//
// and if 'j' is 2, we want to append path_parts[1] and then
// path_parts[0], aka
// 'UIFoundation.framework/UIFoundation', to the module_search_paths_ptr
// path.
for (int k = j; k >= 0; --k) {
path_to_try.AppendPathComponent(path_parts[k]);
}
if (path_to_try.Exists()) {
ModuleSpec new_module_spec(module_spec);
new_module_spec.GetFileSpec() = path_to_try;
Error new_error(Platform::GetSharedModule(
new_module_spec, process, module_sp, NULL, old_module_sp_ptr,
did_create_ptr));
if (module_sp) {
module_sp->SetPlatformFileSpec(path_to_try);
return new_error;
}
}
}
}
}
const bool always_create = false;
error = ModuleList::GetSharedModule(
module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
did_create_ptr, always_create);
if (module_sp)
module_sp->SetPlatformFileSpec(platform_file);
return error;
}
: PlatformRemoteDarwinDevice() {}
bool PlatformRemoteiOS::GetSupportedArchitectureAtIndex(uint32_t idx,
ArchSpec &arch) {
return ARMGetSupportedArchitectureAtIndex(idx, arch);
}
uint32_t PlatformRemoteiOS::GetConnectedSDKIndex() {
if (IsConnected()) {
if (m_connected_module_sdk_idx == UINT32_MAX) {
std::string build;
if (GetRemoteOSBuildString(build)) {
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
for (uint32_t i = 0; i < num_sdk_infos; ++i) {
const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
if (strstr(sdk_dir_info.directory.GetFilename().AsCString(""),
build.c_str())) {
m_connected_module_sdk_idx = i;
}
}
}
}
} else {
m_connected_module_sdk_idx = UINT32_MAX;
}
return m_connected_module_sdk_idx;
void PlatformRemoteiOS::GetDeviceSupportDirectoryNames (std::vector<std::string> &dirnames)
{
dirnames.clear();
dirnames.push_back("iOS DeviceSupport");
}
uint32_t PlatformRemoteiOS::GetSDKIndexBySDKDirectoryInfo(
const SDKDirectoryInfo *sdk_info) {
if (sdk_info == NULL) {
return UINT32_MAX;
}
return sdk_info - &m_sdk_directory_infos[0];
std::string PlatformRemoteiOS::GetPlatformName ()
{
return "iPhoneOS.platform";
}

View File

@ -16,16 +16,16 @@
// Other libraries and framework includes
// Project includes
#include "PlatformDarwin.h"
#include "PlatformRemoteDarwinDevice.h"
#include "lldb/Utility/FileSpec.h"
#include "llvm/Support/FileSystem.h"
class PlatformRemoteiOS : public PlatformDarwin {
class PlatformRemoteiOS : public PlatformRemoteDarwinDevice {
public:
PlatformRemoteiOS();
~PlatformRemoteiOS() override;
~PlatformRemoteiOS() override = default;
//------------------------------------------------------------
// Class Functions
@ -41,6 +41,12 @@ public:
static const char *GetDescriptionStatic();
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
const char *GetDescription() override { return GetDescriptionStatic(); }
//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
@ -50,89 +56,18 @@ public:
uint32_t GetPluginVersion() override { return 1; }
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
lldb_private::Error ResolveExecutable(
const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp,
const lldb_private::FileSpecList *module_search_paths_ptr) override;
const char *GetDescription() override { return GetDescriptionStatic(); }
void GetStatus(lldb_private::Stream &strm) override;
virtual lldb_private::Error
GetSymbolFile(const lldb_private::FileSpec &platform_file,
const lldb_private::UUID *uuid_ptr,
lldb_private::FileSpec &local_file);
lldb_private::Error
GetSharedModule(const lldb_private::ModuleSpec &module_spec,
lldb_private::Process *process, lldb::ModuleSP &module_sp,
const lldb_private::FileSpecList *module_search_paths_ptr,
lldb::ModuleSP *old_module_sp_ptr,
bool *did_create_ptr) override;
bool GetSupportedArchitectureAtIndex(uint32_t idx,
lldb_private::ArchSpec &arch) override;
void
AddClangModuleCompilationOptions(lldb_private::Target *target,
std::vector<std::string> &options) override {
return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
target, options, PlatformDarwin::SDKType::iPhoneOS);
}
protected:
struct SDKDirectoryInfo {
SDKDirectoryInfo(const lldb_private::FileSpec &sdk_dir_spec);
lldb_private::FileSpec directory;
lldb_private::ConstString build;
uint32_t version_major;
uint32_t version_minor;
uint32_t version_update;
bool user_cached;
};
typedef std::vector<SDKDirectoryInfo> SDKDirectoryInfoCollection;
//------------------------------------------------------------
// lldb_private::PlatformRemoteDarwinDevice functions
//------------------------------------------------------------
std::mutex m_sdk_dir_mutex;
SDKDirectoryInfoCollection m_sdk_directory_infos;
std::string m_device_support_directory;
std::string m_device_support_directory_for_os_version;
std::string m_build_update;
uint32_t m_last_module_sdk_idx;
uint32_t m_connected_module_sdk_idx;
void GetDeviceSupportDirectoryNames (std::vector<std::string> &dirnames) override;
bool UpdateSDKDirectoryInfosIfNeeded();
const char *GetDeviceSupportDirectory();
const char *GetDeviceSupportDirectoryForOSVersion();
const SDKDirectoryInfo *GetSDKDirectoryForLatestOSVersion();
const SDKDirectoryInfo *GetSDKDirectoryForCurrentOSVersion();
static lldb_private::FileSpec::EnumerateDirectoryResult
GetContainedFilesIntoVectorOfStringsCallback(
void *baton, llvm::sys::fs::file_type ft,
const lldb_private::FileSpec &file_spec);
uint32_t FindFileInAllSDKs(const char *platform_file_path,
lldb_private::FileSpecList &file_list);
bool GetFileInSDK(const char *platform_file_path, uint32_t sdk_idx,
lldb_private::FileSpec &local_file);
uint32_t FindFileInAllSDKs(const lldb_private::FileSpec &platform_file,
lldb_private::FileSpecList &file_list);
uint32_t GetConnectedSDKIndex();
// Get index of SDK in SDKDirectoryInfoCollection by its pointer and return
// UINT32_MAX if that SDK not found.
uint32_t GetSDKIndexBySDKDirectoryInfo(const SDKDirectoryInfo *sdk_info);
std::string GetPlatformName () override;
private:
DISALLOW_COPY_AND_ASSIGN(PlatformRemoteiOS);

View File

@ -224,36 +224,83 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {
PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
// Get details on the signal raised.
if (siginfo_err.Success()) {
switch (info.psi_siginfo.si_code) {
case TRAP_BRKPT:
if (siginfo_err.Fail()) {
return;
}
switch (info.psi_siginfo.si_code) {
case TRAP_BRKPT:
for (const auto &thread_sp : m_threads) {
static_pointer_cast<NativeThreadNetBSD>(thread_sp)
->SetStoppedByBreakpoint();
FixupBreakpointPCAsNeeded(
*static_pointer_cast<NativeThreadNetBSD>(thread_sp));
}
SetState(StateType::eStateStopped, true);
break;
case TRAP_TRACE:
for (const auto &thread_sp : m_threads) {
static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedByTrace();
}
SetState(StateType::eStateStopped, true);
break;
case TRAP_EXEC: {
Error error = ReinitializeThreads();
if (error.Fail()) {
SetState(StateType::eStateInvalid);
return;
}
// Let our delegate know we have just exec'd.
NotifyDidExec();
for (const auto &thread_sp : m_threads) {
static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedByExec();
}
SetState(StateType::eStateStopped, true);
} break;
case TRAP_DBREG: {
// If a watchpoint was hit, report it
uint32_t wp_index;
Error error =
static_pointer_cast<NativeThreadNetBSD>(m_threads[info.psi_lwpid])
->GetRegisterContext()
->GetWatchpointHitIndex(wp_index,
(uintptr_t)info.psi_siginfo.si_addr);
if (error.Fail())
LLDB_LOG(log,
"received error while checking for watchpoint hits, pid = "
"{0}, LWP = {1}, error = {2}",
GetID(), info.psi_lwpid, error);
if (wp_index != LLDB_INVALID_INDEX32) {
for (const auto &thread_sp : m_threads) {
static_pointer_cast<NativeThreadNetBSD>(thread_sp)
->SetStoppedByWatchpoint(wp_index);
}
SetState(StateType::eStateStopped, true);
break;
}
// If a breakpoint was hit, report it
uint32_t bp_index;
error = static_pointer_cast<NativeThreadNetBSD>(m_threads[info.psi_lwpid])
->GetRegisterContext()
->GetHardwareBreakHitIndex(bp_index,
(uintptr_t)info.psi_siginfo.si_addr);
if (error.Fail())
LLDB_LOG(log,
"received error while checking for hardware "
"breakpoint hits, pid = {0}, LWP = {1}, error = {2}",
GetID(), info.psi_lwpid, error);
if (bp_index != LLDB_INVALID_INDEX32) {
for (const auto &thread_sp : m_threads) {
static_pointer_cast<NativeThreadNetBSD>(thread_sp)
->SetStoppedByBreakpoint();
FixupBreakpointPCAsNeeded(
*static_pointer_cast<NativeThreadNetBSD>(thread_sp));
}
SetState(StateType::eStateStopped, true);
break;
case TRAP_TRACE:
for (const auto &thread_sp : m_threads) {
static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedByTrace();
}
SetState(StateType::eStateStopped, true);
break;
case TRAP_EXEC: {
Error error = ReinitializeThreads();
if (error.Fail()) {
SetState(StateType::eStateInvalid);
return;
}
// Let our delegate know we have just exec'd.
NotifyDidExec();
SetState(StateType::eStateStopped, true);
} break;
}
} break;
}
}
@ -328,8 +375,8 @@ Error NativeProcessNetBSD::FixupBreakpointPCAsNeeded(
return error;
} else
LLDB_LOG(log, "breakpoint size: {0}", breakpoint_size);
// First try probing for a breakpoint at a software breakpoint location: PC -
// breakpoint size.
// First try probing for a breakpoint at a software breakpoint location: PC
// - breakpoint size.
const lldb::addr_t initial_pc_addr =
context_sp->GetPCfromBreakpointLocation();
lldb::addr_t breakpoint_addr = initial_pc_addr;
@ -439,7 +486,7 @@ Error NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) {
llvm_unreachable("Unexpected state");
default:
return Error("NativeProcessLinux::%s (): unexpected state %s specified "
return Error("NativeProcessNetBSD::%s (): unexpected state %s specified "
"for pid %" PRIu64 ", tid %" PRIu64,
__FUNCTION__, StateAsCString(action->state), GetID(),
thread_sp->GetID());
@ -540,8 +587,8 @@ Error NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
"descending memory map entries detected, unexpected");
prev_base_address = proc_entry_info.GetRange().GetRangeBase();
UNUSED_IF_ASSERT_DISABLED(prev_base_address);
// If the target address comes before this entry, indicate distance to next
// region.
// If the target address comes before this entry, indicate distance to
// next region.
if (load_addr < proc_entry_info.GetRange().GetRangeBase()) {
range_info.GetRange().SetRangeBase(load_addr);
range_info.GetRange().SetByteSize(
@ -561,9 +608,8 @@ Error NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
}
// If we made it here, we didn't find an entry that contained the given
// address. Return the
// load_addr as start and the amount of bytes betwwen load address and the end
// of the memory as
// size.
// load_addr as start and the amount of bytes betwwen load address and the
// end of the memory as size.
range_info.GetRange().SetRangeBase(load_addr);
range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
@ -722,8 +768,8 @@ Error NativeProcessNetBSD::LaunchInferior(MainLoop &mainloop,
LLDB_LOG(log, "waitpid for inferior failed with %s", error);
// Mark the inferior as invalid.
// FIXME this could really use a new state - eStateLaunchFailure. For now,
// using eStateInvalid.
// FIXME this could really use a new state - eStateLaunchFailure. For
// now, using eStateInvalid.
SetState(StateType::eStateInvalid);
return error;
@ -766,6 +812,11 @@ Error NativeProcessNetBSD::LaunchInferior(MainLoop &mainloop,
return error;
}
for (const auto &thread_sp : m_threads) {
static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal(
SIGSTOP);
}
/* Set process stopped */
SetState(StateType::eStateStopped);
@ -894,6 +945,11 @@ NativeThreadNetBSDSP NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
return -1;
}
for (const auto &thread_sp : m_threads) {
static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal(
SIGSTOP);
}
// Let our process instance know the thread has stopped.
SetState(StateType::eStateStopped);
@ -1007,7 +1063,6 @@ Error NativeProcessNetBSD::ReinitializeThreads() {
// Reinitialize from scratch threads and register them in process
while (info.pl_lwpid != 0) {
NativeThreadNetBSDSP thread_sp = AddThread(info.pl_lwpid);
thread_sp->SetStoppedByExec();
error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info));
if (error.Fail()) {
return error;

View File

@ -57,6 +57,22 @@ Error NativeRegisterContextNetBSD::WriteFPR() {
return DoWriteFPR(buf);
}
Error NativeRegisterContextNetBSD::ReadDBR() {
void *buf = GetDBRBuffer();
if (!buf)
return Error("DBR buffer is NULL");
return DoReadDBR(buf);
}
Error NativeRegisterContextNetBSD::WriteDBR() {
void *buf = GetDBRBuffer();
if (!buf)
return Error("DBR buffer is NULL");
return DoWriteDBR(buf);
}
Error NativeRegisterContextNetBSD::DoReadGPR(void *buf) {
return NativeProcessNetBSD::PtraceWrapper(PT_GETREGS, GetProcessPid(), buf,
m_thread.GetID());
@ -77,6 +93,16 @@ Error NativeRegisterContextNetBSD::DoWriteFPR(void *buf) {
m_thread.GetID());
}
Error NativeRegisterContextNetBSD::DoReadDBR(void *buf) {
return NativeProcessNetBSD::PtraceWrapper(PT_GETDBREGS, GetProcessPid(), buf,
m_thread.GetID());
}
Error NativeRegisterContextNetBSD::DoWriteDBR(void *buf) {
return NativeProcessNetBSD::PtraceWrapper(PT_SETDBREGS, GetProcessPid(), buf,
m_thread.GetID());
}
NativeProcessNetBSD &NativeRegisterContextNetBSD::GetProcess() {
auto process_sp =
std::static_pointer_cast<NativeProcessNetBSD>(m_thread.GetProcess());

View File

@ -41,6 +41,9 @@ protected:
virtual Error ReadFPR();
virtual Error WriteFPR();
virtual Error ReadDBR();
virtual Error WriteDBR();
virtual void *GetGPRBuffer() { return nullptr; }
virtual size_t GetGPRSize() {
return GetRegisterInfoInterface().GetGPRSize();
@ -49,12 +52,18 @@ protected:
virtual void *GetFPRBuffer() { return nullptr; }
virtual size_t GetFPRSize() { return 0; }
virtual void *GetDBRBuffer() { return nullptr; }
virtual size_t GetDBRSize() { return 0; }
virtual Error DoReadGPR(void *buf);
virtual Error DoWriteGPR(void *buf);
virtual Error DoReadFPR(void *buf);
virtual Error DoWriteFPR(void *buf);
virtual Error DoReadDBR(void *buf);
virtual Error DoWriteDBR(void *buf);
virtual NativeProcessNetBSD &GetProcess();
virtual ::pid_t GetProcessPid();
};

View File

@ -19,7 +19,15 @@
#include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h"
// clang-format off
#include <sys/types.h>
#include <sys/sysctl.h>
#include <x86/cpu.h>
#include <elf.h>
#include <err.h>
#include <stdint.h>
#include <stdlib.h>
// clang-format on
using namespace lldb_private;
using namespace lldb_private::process_netbsd;
@ -86,6 +94,57 @@ static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = {
#define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize())
const int fpu_present = []() -> int {
int mib[2];
int error;
size_t len;
int val;
len = sizeof(val);
mib[0] = CTL_MACHDEP;
mib[1] = CPU_FPU_PRESENT;
error = sysctl(mib, __arraycount(mib), &val, &len, NULL, 0);
if (error)
errx(EXIT_FAILURE, "sysctl");
return val;
}();
const int osfxsr = []() -> int {
int mib[2];
int error;
size_t len;
int val;
len = sizeof(val);
mib[0] = CTL_MACHDEP;
mib[1] = CPU_OSFXSR;
error = sysctl(mib, __arraycount(mib), &val, &len, NULL, 0);
if (error)
errx(EXIT_FAILURE, "sysctl");
return val;
}();
const int fpu_save = []() -> int {
int mib[2];
int error;
size_t len;
int val;
len = sizeof(val);
mib[0] = CTL_MACHDEP;
mib[1] = CPU_FPU_SAVE;
error = sysctl(mib, __arraycount(mib), &val, &len, NULL, 0);
if (error)
errx(EXIT_FAILURE, "sysctl");
return val;
}();
} // namespace
NativeRegisterContextNetBSD *
@ -114,7 +173,7 @@ NativeRegisterContextNetBSD_x86_64::NativeRegisterContextNetBSD_x86_64(
uint32_t concrete_frame_idx)
: NativeRegisterContextNetBSD(native_thread, concrete_frame_idx,
CreateRegisterInfoInterface(target_arch)),
m_gpr_x86_64() {}
m_gpr_x86_64(), m_fpr_x86_64(), m_dbr_x86_64() {}
// CONSIDER after local and llgs debugging are merged, register set support can
// be moved into a base x86-64 class with IsRegisterSetAvailable made virtual.
@ -143,8 +202,18 @@ NativeRegisterContextNetBSD_x86_64::GetRegisterSet(uint32_t set_index) const {
int NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum(
int reg_num) const {
if (reg_num < lldb_fctrl_x86_64)
if (reg_num <= k_last_gpr_x86_64)
return GPRegSet;
else if (reg_num <= k_last_fpr_x86_64)
return (fpu_present == 1 && osfxsr == 1 && fpu_save >= 1) ? FPRegSet : -1;
else if (reg_num <= k_last_avx_x86_64)
return -1; // AVX
else if (reg_num <= k_last_mpxr_x86_64)
return -1; // MPXR
else if (reg_num <= k_last_mpxc_x86_64)
return -1; // MPXC
else if (reg_num <= lldb_dr7_x86_64)
return DBRegSet; // DBR
else
return -1;
}
@ -157,6 +226,9 @@ int NativeRegisterContextNetBSD_x86_64::ReadRegisterSet(uint32_t set) {
case FPRegSet:
ReadFPR();
return 0;
case DBRegSet:
ReadDBR();
return 0;
default:
break;
}
@ -170,6 +242,9 @@ int NativeRegisterContextNetBSD_x86_64::WriteRegisterSet(uint32_t set) {
case FPRegSet:
WriteFPR();
return 0;
case DBRegSet:
WriteDBR();
return 0;
default:
break;
}
@ -285,6 +360,87 @@ Error NativeRegisterContextNetBSD_x86_64::ReadRegister(
case lldb_es_x86_64:
reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_ES];
break;
case lldb_fctrl_x86_64:
reg_value = (uint16_t)m_fpr_x86_64.fxstate.fx_cw;
break;
case lldb_fstat_x86_64:
reg_value = (uint16_t)m_fpr_x86_64.fxstate.fx_sw;
break;
case lldb_ftag_x86_64:
reg_value = (uint8_t)m_fpr_x86_64.fxstate.fx_tw;
break;
case lldb_fop_x86_64:
reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_opcode;
break;
case lldb_fiseg_x86_64:
reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_ip.fa_64;
break;
case lldb_fioff_x86_64:
reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_ip.fa_32.fa_off;
break;
case lldb_foseg_x86_64:
reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_dp.fa_64;
break;
case lldb_fooff_x86_64:
reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_dp.fa_32.fa_off;
break;
case lldb_mxcsr_x86_64:
reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_mxcsr;
break;
case lldb_mxcsrmask_x86_64:
reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_mxcsr_mask;
break;
case lldb_st0_x86_64:
case lldb_st1_x86_64:
case lldb_st2_x86_64:
case lldb_st3_x86_64:
case lldb_st4_x86_64:
case lldb_st5_x86_64:
case lldb_st6_x86_64:
case lldb_st7_x86_64:
reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_87_ac[reg - lldb_st0_x86_64],
reg_info->byte_size, endian::InlHostByteOrder());
break;
case lldb_mm0_x86_64:
case lldb_mm1_x86_64:
case lldb_mm2_x86_64:
case lldb_mm3_x86_64:
case lldb_mm4_x86_64:
case lldb_mm5_x86_64:
case lldb_mm6_x86_64:
case lldb_mm7_x86_64:
reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_mm0_x86_64],
reg_info->byte_size, endian::InlHostByteOrder());
break;
case lldb_xmm0_x86_64:
case lldb_xmm1_x86_64:
case lldb_xmm2_x86_64:
case lldb_xmm3_x86_64:
case lldb_xmm4_x86_64:
case lldb_xmm5_x86_64:
case lldb_xmm6_x86_64:
case lldb_xmm7_x86_64:
case lldb_xmm8_x86_64:
case lldb_xmm9_x86_64:
case lldb_xmm10_x86_64:
case lldb_xmm11_x86_64:
case lldb_xmm12_x86_64:
case lldb_xmm13_x86_64:
case lldb_xmm14_x86_64:
case lldb_xmm15_x86_64:
reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_xmm0_x86_64],
reg_info->byte_size, endian::InlHostByteOrder());
break;
case lldb_dr0_x86_64:
case lldb_dr1_x86_64:
case lldb_dr2_x86_64:
case lldb_dr3_x86_64:
case lldb_dr4_x86_64:
case lldb_dr5_x86_64:
case lldb_dr6_x86_64:
case lldb_dr7_x86_64:
reg_value = (uint64_t)m_dbr_x86_64.dr[reg - lldb_dr0_x86_64];
break;
}
return error;
@ -400,6 +556,87 @@ Error NativeRegisterContextNetBSD_x86_64::WriteRegister(
case lldb_es_x86_64:
m_gpr_x86_64.regs[_REG_ES] = reg_value.GetAsUInt64();
break;
case lldb_fctrl_x86_64:
m_fpr_x86_64.fxstate.fx_cw = reg_value.GetAsUInt16();
break;
case lldb_fstat_x86_64:
m_fpr_x86_64.fxstate.fx_sw = reg_value.GetAsUInt16();
break;
case lldb_ftag_x86_64:
m_fpr_x86_64.fxstate.fx_tw = reg_value.GetAsUInt8();
break;
case lldb_fop_x86_64:
m_fpr_x86_64.fxstate.fx_opcode = reg_value.GetAsUInt16();
break;
case lldb_fiseg_x86_64:
m_fpr_x86_64.fxstate.fx_ip.fa_64 = reg_value.GetAsUInt64();
break;
case lldb_fioff_x86_64:
m_fpr_x86_64.fxstate.fx_ip.fa_32.fa_off = reg_value.GetAsUInt32();
break;
case lldb_foseg_x86_64:
m_fpr_x86_64.fxstate.fx_dp.fa_64 = reg_value.GetAsUInt64();
break;
case lldb_fooff_x86_64:
m_fpr_x86_64.fxstate.fx_dp.fa_32.fa_off = reg_value.GetAsUInt32();
break;
case lldb_mxcsr_x86_64:
m_fpr_x86_64.fxstate.fx_mxcsr = reg_value.GetAsUInt32();
break;
case lldb_mxcsrmask_x86_64:
m_fpr_x86_64.fxstate.fx_mxcsr_mask = reg_value.GetAsUInt32();
break;
case lldb_st0_x86_64:
case lldb_st1_x86_64:
case lldb_st2_x86_64:
case lldb_st3_x86_64:
case lldb_st4_x86_64:
case lldb_st5_x86_64:
case lldb_st6_x86_64:
case lldb_st7_x86_64:
::memcpy(&m_fpr_x86_64.fxstate.fx_87_ac[reg - lldb_st0_x86_64],
reg_value.GetBytes(), reg_value.GetByteSize());
break;
case lldb_mm0_x86_64:
case lldb_mm1_x86_64:
case lldb_mm2_x86_64:
case lldb_mm3_x86_64:
case lldb_mm4_x86_64:
case lldb_mm5_x86_64:
case lldb_mm6_x86_64:
case lldb_mm7_x86_64:
::memcpy(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_mm0_x86_64],
reg_value.GetBytes(), reg_value.GetByteSize());
break;
case lldb_xmm0_x86_64:
case lldb_xmm1_x86_64:
case lldb_xmm2_x86_64:
case lldb_xmm3_x86_64:
case lldb_xmm4_x86_64:
case lldb_xmm5_x86_64:
case lldb_xmm6_x86_64:
case lldb_xmm7_x86_64:
case lldb_xmm8_x86_64:
case lldb_xmm9_x86_64:
case lldb_xmm10_x86_64:
case lldb_xmm11_x86_64:
case lldb_xmm12_x86_64:
case lldb_xmm13_x86_64:
case lldb_xmm14_x86_64:
case lldb_xmm15_x86_64:
::memcpy(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_xmm0_x86_64],
reg_value.GetBytes(), reg_value.GetByteSize());
break;
case lldb_dr0_x86_64:
case lldb_dr1_x86_64:
case lldb_dr2_x86_64:
case lldb_dr3_x86_64:
case lldb_dr4_x86_64:
case lldb_dr5_x86_64:
case lldb_dr6_x86_64:
case lldb_dr7_x86_64:
m_dbr_x86_64.dr[reg - lldb_dr0_x86_64] = reg_value.GetAsUInt64();
break;
}
if (WriteRegisterSet(set) != 0)
@ -480,4 +717,223 @@ Error NativeRegisterContextNetBSD_x86_64::WriteAllRegisterValues(
return error;
}
Error NativeRegisterContextNetBSD_x86_64::IsWatchpointHit(uint32_t wp_index,
bool &is_hit) {
if (wp_index >= NumSupportedHardwareWatchpoints())
return Error("Watchpoint index out of range");
RegisterValue reg_value;
const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(lldb_dr6_x86_64);
Error error = ReadRegister(reg_info, reg_value);
if (error.Fail()) {
is_hit = false;
return error;
}
uint64_t status_bits = reg_value.GetAsUInt64();
is_hit = status_bits & (1 << wp_index);
return error;
}
Error NativeRegisterContextNetBSD_x86_64::GetWatchpointHitIndex(
uint32_t &wp_index, lldb::addr_t trap_addr) {
uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) {
bool is_hit;
Error error = IsWatchpointHit(wp_index, is_hit);
if (error.Fail()) {
wp_index = LLDB_INVALID_INDEX32;
return error;
} else if (is_hit) {
return error;
}
}
wp_index = LLDB_INVALID_INDEX32;
return Error();
}
Error NativeRegisterContextNetBSD_x86_64::IsWatchpointVacant(uint32_t wp_index,
bool &is_vacant) {
if (wp_index >= NumSupportedHardwareWatchpoints())
return Error("Watchpoint index out of range");
RegisterValue reg_value;
const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(lldb_dr7_x86_64);
Error error = ReadRegister(reg_info, reg_value);
if (error.Fail()) {
is_vacant = false;
return error;
}
uint64_t control_bits = reg_value.GetAsUInt64();
is_vacant = !(control_bits & (1 << (2 * wp_index)));
return error;
}
Error NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpointWithIndex(
lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
if (wp_index >= NumSupportedHardwareWatchpoints())
return Error("Watchpoint index out of range");
// Read only watchpoints aren't supported on x86_64. Fall back to read/write
// waitchpoints instead.
// TODO: Add logic to detect when a write happens and ignore that watchpoint
// hit.
if (watch_flags == 0x2)
watch_flags = 0x3;
if (watch_flags != 0x1 && watch_flags != 0x3)
return Error("Invalid read/write bits for watchpoint");
if (size != 1 && size != 2 && size != 4 && size != 8)
return Error("Invalid size for watchpoint");
bool is_vacant;
Error error = IsWatchpointVacant(wp_index, is_vacant);
if (error.Fail())
return error;
if (!is_vacant)
return Error("Watchpoint index not vacant");
RegisterValue reg_value;
const RegisterInfo *const reg_info_dr7 =
GetRegisterInfoAtIndex(lldb_dr7_x86_64);
error = ReadRegister(reg_info_dr7, reg_value);
if (error.Fail())
return error;
// for watchpoints 0, 1, 2, or 3, respectively,
// set bits 1, 3, 5, or 7
uint64_t enable_bit = 1 << (2 * wp_index);
// set bits 16-17, 20-21, 24-25, or 28-29
// with 0b01 for write, and 0b11 for read/write
uint64_t rw_bits = watch_flags << (16 + 4 * wp_index);
// set bits 18-19, 22-23, 26-27, or 30-31
// with 0b00, 0b01, 0b10, or 0b11
// for 1, 2, 8 (if supported), or 4 bytes, respectively
uint64_t size_bits = (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index);
uint64_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
control_bits |= enable_bit | rw_bits | size_bits;
const RegisterInfo *const reg_info_drN =
GetRegisterInfoAtIndex(lldb_dr0_x86_64 + wp_index);
error = WriteRegister(reg_info_drN, RegisterValue(addr));
if (error.Fail())
return error;
error = WriteRegister(reg_info_dr7, RegisterValue(control_bits));
if (error.Fail())
return error;
error.Clear();
return error;
}
bool NativeRegisterContextNetBSD_x86_64::ClearHardwareWatchpoint(
uint32_t wp_index) {
if (wp_index >= NumSupportedHardwareWatchpoints())
return false;
RegisterValue reg_value;
// for watchpoints 0, 1, 2, or 3, respectively,
// clear bits 0, 1, 2, or 3 of the debug status register (DR6)
const RegisterInfo *const reg_info_dr6 =
GetRegisterInfoAtIndex(lldb_dr6_x86_64);
Error error = ReadRegister(reg_info_dr6, reg_value);
if (error.Fail())
return false;
uint64_t bit_mask = 1 << wp_index;
uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
error = WriteRegister(reg_info_dr6, RegisterValue(status_bits));
if (error.Fail())
return false;
// for watchpoints 0, 1, 2, or 3, respectively,
// clear bits {0-1,16-19}, {2-3,20-23}, {4-5,24-27}, or {6-7,28-31}
// of the debug control register (DR7)
const RegisterInfo *const reg_info_dr7 =
GetRegisterInfoAtIndex(lldb_dr7_x86_64);
error = ReadRegister(reg_info_dr7, reg_value);
if (error.Fail())
return false;
bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
return WriteRegister(reg_info_dr7, RegisterValue(control_bits)).Success();
}
Error NativeRegisterContextNetBSD_x86_64::ClearAllHardwareWatchpoints() {
RegisterValue reg_value;
// clear bits {0-4} of the debug status register (DR6)
const RegisterInfo *const reg_info_dr6 =
GetRegisterInfoAtIndex(lldb_dr6_x86_64);
Error error = ReadRegister(reg_info_dr6, reg_value);
if (error.Fail())
return error;
uint64_t bit_mask = 0xF;
uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
error = WriteRegister(reg_info_dr6, RegisterValue(status_bits));
if (error.Fail())
return error;
// clear bits {0-7,16-31} of the debug control register (DR7)
const RegisterInfo *const reg_info_dr7 =
GetRegisterInfoAtIndex(lldb_dr7_x86_64);
error = ReadRegister(reg_info_dr7, reg_value);
if (error.Fail())
return error;
bit_mask = 0xFF | (0xFFFF << 16);
uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
return WriteRegister(reg_info_dr7, RegisterValue(control_bits));
}
uint32_t NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpoint(
lldb::addr_t addr, size_t size, uint32_t watch_flags) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
for (uint32_t wp_index = 0; wp_index < num_hw_watchpoints; ++wp_index) {
bool is_vacant;
Error error = IsWatchpointVacant(wp_index, is_vacant);
if (is_vacant) {
error = SetHardwareWatchpointWithIndex(addr, size, watch_flags, wp_index);
if (error.Success())
return wp_index;
}
if (error.Fail() && log) {
log->Printf("NativeRegisterContextNetBSD_x86_64::%s Error: %s",
__FUNCTION__, error.AsCString());
}
}
return LLDB_INVALID_INDEX32;
}
lldb::addr_t
NativeRegisterContextNetBSD_x86_64::GetWatchpointAddress(uint32_t wp_index) {
if (wp_index >= NumSupportedHardwareWatchpoints())
return LLDB_INVALID_ADDRESS;
RegisterValue reg_value;
const RegisterInfo *const reg_info_drN =
GetRegisterInfoAtIndex(lldb_dr0_x86_64 + wp_index);
if (ReadRegister(reg_info_drN, reg_value).Fail())
return LLDB_INVALID_ADDRESS;
return reg_value.GetAsUInt64();
}
uint32_t NativeRegisterContextNetBSD_x86_64::NumSupportedHardwareWatchpoints() {
// Available debug address registers: dr0, dr1, dr2, dr3
return 4;
}
#endif // defined(__x86_64__)

View File

@ -46,17 +46,40 @@ public:
Error WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
Error IsWatchpointHit(uint32_t wp_index, bool &is_hit) override;
Error GetWatchpointHitIndex(uint32_t &wp_index,
lldb::addr_t trap_addr) override;
Error IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override;
bool ClearHardwareWatchpoint(uint32_t wp_index) override;
Error ClearAllHardwareWatchpoints() override;
Error SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size,
uint32_t watch_flags, uint32_t wp_index);
uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
uint32_t watch_flags) override;
lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override;
uint32_t NumSupportedHardwareWatchpoints() override;
protected:
void *GetGPRBuffer() override { return &m_gpr_x86_64; }
void *GetFPRBuffer() override { return &m_fpr_x86_64; }
void *GetDBRBuffer() override { return &m_dbr_x86_64; }
private:
// Private member types.
enum { GPRegSet, FPRegSet };
enum { GPRegSet, FPRegSet, DBRegSet };
// Private member variables.
struct reg m_gpr_x86_64;
struct fpreg m_fpr_x86_64;
struct dbreg m_dbr_x86_64;
int GetSetForNativeRegNum(int reg_num) const;

View File

@ -16,6 +16,9 @@
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/State.h"
#include "lldb/Utility/LLDBAssert.h"
#include <sstream>
using namespace lldb;
using namespace lldb_private;
@ -68,6 +71,23 @@ void NativeThreadNetBSD::SetStoppedByExec() {
m_stop_info.details.signal.signo = SIGTRAP;
}
void NativeThreadNetBSD::SetStoppedByWatchpoint(uint32_t wp_index) {
SetStopped();
lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid");
std::ostringstream ostr;
ostr << GetRegisterContext()->GetWatchpointAddress(wp_index) << " ";
ostr << wp_index;
ostr << " " << GetRegisterContext()->GetWatchpointHitAddress(wp_index);
m_stop_description = ostr.str();
m_stop_info.reason = StopReason::eStopReasonWatchpoint;
m_stop_info.details.signal.signo = SIGTRAP;
}
void NativeThreadNetBSD::SetStopped() {
const StateType new_state = StateType::eStateStopped;
m_state = new_state;
@ -142,18 +162,61 @@ NativeRegisterContextSP NativeThreadNetBSD::GetRegisterContext() {
Error NativeThreadNetBSD::SetWatchpoint(lldb::addr_t addr, size_t size,
uint32_t watch_flags, bool hardware) {
return Error("Unimplemented");
if (!hardware)
return Error("not implemented");
if (m_state == eStateLaunching)
return Error();
Error error = RemoveWatchpoint(addr);
if (error.Fail())
return error;
NativeRegisterContextSP reg_ctx = GetRegisterContext();
uint32_t wp_index = reg_ctx->SetHardwareWatchpoint(addr, size, watch_flags);
if (wp_index == LLDB_INVALID_INDEX32)
return Error("Setting hardware watchpoint failed.");
m_watchpoint_index_map.insert({addr, wp_index});
return Error();
}
Error NativeThreadNetBSD::RemoveWatchpoint(lldb::addr_t addr) {
return Error("Unimplemented");
auto wp = m_watchpoint_index_map.find(addr);
if (wp == m_watchpoint_index_map.end())
return Error();
uint32_t wp_index = wp->second;
m_watchpoint_index_map.erase(wp);
if (GetRegisterContext()->ClearHardwareWatchpoint(wp_index))
return Error();
return Error("Clearing hardware watchpoint failed.");
}
Error NativeThreadNetBSD::SetHardwareBreakpoint(lldb::addr_t addr,
size_t size) {
return Error("Unimplemented");
if (m_state == eStateLaunching)
return Error();
Error error = RemoveHardwareBreakpoint(addr);
if (error.Fail())
return error;
NativeRegisterContextSP reg_ctx = GetRegisterContext();
uint32_t bp_index = reg_ctx->SetHardwareBreakpoint(addr, size);
if (bp_index == LLDB_INVALID_INDEX32)
return Error("Setting hardware breakpoint failed.");
m_hw_break_index_map.insert({addr, bp_index});
return Error();
}
Error NativeThreadNetBSD::RemoveHardwareBreakpoint(lldb::addr_t addr) {
return Error("Unimplemented");
auto bp = m_hw_break_index_map.find(addr);
if (bp == m_hw_break_index_map.end())
return Error();
uint32_t bp_index = bp->second;
if (GetRegisterContext()->ClearHardwareBreakpoint(bp_index)) {
m_hw_break_index_map.erase(bp);
return Error();
}
return Error("Clearing hardware breakpoint failed.");
}

View File

@ -12,6 +12,9 @@
#include "lldb/Host/common/NativeThreadProtocol.h"
#include <map>
#include <string>
namespace lldb_private {
namespace process_netbsd {
@ -53,6 +56,7 @@ private:
void SetStoppedByBreakpoint();
void SetStoppedByTrace();
void SetStoppedByExec();
void SetStoppedByWatchpoint(uint32_t wp_index);
void SetStopped();
void SetRunning();
void SetStepping();
@ -64,6 +68,9 @@ private:
ThreadStopInfo m_stop_info;
NativeRegisterContextSP m_reg_context_sp;
std::string m_stop_description;
using WatchpointIndexMap = std::map<lldb::addr_t, uint32_t>;
WatchpointIndexMap m_watchpoint_index_map;
WatchpointIndexMap m_hw_break_index_map;
};
typedef std::shared_ptr<NativeThreadNetBSD> NativeThreadNetBSDSP;

View File

@ -55,9 +55,10 @@ RegisterContextPOSIX_mips64::RegisterContextPOSIX_mips64(
m_registers_count[i] = reg_set_ptr->num_registers;
}
assert(m_num_registers == m_registers_count[gpr_registers_count] +
m_registers_count[fpr_registers_count] +
m_registers_count[msa_registers_count]);
assert(m_num_registers ==
static_cast<uint32_t>(m_registers_count[gpr_registers_count] +
m_registers_count[fpr_registers_count] +
m_registers_count[msa_registers_count]));
// elf-core yet to support ReadFPR()
ProcessSP base = CalculateProcess();

View File

@ -148,7 +148,7 @@
DR_OFFSET(i), eEncodingUint, eFormatHex, \
{LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
LLDB_INVALID_REGNUM }, \
lldb_##reg##i##_x86_64 }, \
nullptr, nullptr, nullptr, 0 \
}

View File

@ -1310,12 +1310,20 @@ void GDBRemoteCommunication::DumpHistory(Stream &strm) { m_history.Dump(strm); }
GDBRemoteCommunication::ScopedTimeout::ScopedTimeout(
GDBRemoteCommunication &gdb_comm, std::chrono::seconds timeout)
: m_gdb_comm(gdb_comm) {
m_saved_timeout = m_gdb_comm.SetPacketTimeout(timeout);
: m_gdb_comm(gdb_comm), m_timeout_modified(false) {
auto curr_timeout = gdb_comm.GetPacketTimeout();
// Only update the timeout if the timeout is greater than the current
// timeout. If the current timeout is larger, then just use that.
if (curr_timeout < timeout) {
m_timeout_modified = true;
m_saved_timeout = m_gdb_comm.SetPacketTimeout(timeout);
}
}
GDBRemoteCommunication::ScopedTimeout::~ScopedTimeout() {
m_gdb_comm.SetPacketTimeout(m_saved_timeout);
// Only restore the timeout if we set it in the constructor.
if (m_timeout_modified)
m_gdb_comm.SetPacketTimeout(m_saved_timeout);
}
// This function is called via the Communications class read thread when bytes

View File

@ -89,6 +89,10 @@ public:
private:
GDBRemoteCommunication &m_gdb_comm;
std::chrono::seconds m_saved_timeout;
// Don't ever reduce the timeout for a packet, only increase it. If the
// requested timeout if less than the current timeout, we don't set it
// and won't need to restore it.
bool m_timeout_modified;
};
GDBRemoteCommunication(const char *comm_name, const char *listener_name);

View File

@ -4484,7 +4484,8 @@ ClangASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) {
const clang::ObjCInterfaceType *objc_interface_type =
objc_class_type->getInterfaceType();
if (objc_interface_type &&
GetCompleteType((lldb::opaque_compiler_type_t)objc_interface_type)) {
GetCompleteType(static_cast<lldb::opaque_compiler_type_t>(
const_cast<clang::ObjCInterfaceType *>(objc_interface_type)))) {
clang::ObjCInterfaceDecl *class_interface_decl =
objc_interface_type->getDecl();
if (class_interface_decl) {
@ -4592,7 +4593,8 @@ ClangASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
const clang::ObjCInterfaceType *objc_interface_type =
objc_class_type->getInterfaceType();
if (objc_interface_type &&
GetCompleteType((lldb::opaque_compiler_type_t)objc_interface_type)) {
GetCompleteType(static_cast<lldb::opaque_compiler_type_t>(
const_cast<clang::ObjCInterfaceType *>(objc_interface_type)))) {
clang::ObjCInterfaceDecl *class_interface_decl =
objc_interface_type->getDecl();
if (class_interface_decl) {
@ -5660,7 +5662,8 @@ uint32_t ClangASTContext::GetNumFields(lldb::opaque_compiler_type_t type) {
const clang::ObjCInterfaceType *objc_interface_type =
objc_class_type->getInterfaceType();
if (objc_interface_type &&
GetCompleteType((lldb::opaque_compiler_type_t)objc_interface_type)) {
GetCompleteType(static_cast<lldb::opaque_compiler_type_t>(
const_cast<clang::ObjCInterfaceType *>(objc_interface_type)))) {
clang::ObjCInterfaceDecl *class_interface_decl =
objc_interface_type->getDecl();
if (class_interface_decl) {
@ -5807,7 +5810,8 @@ CompilerType ClangASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type,
const clang::ObjCInterfaceType *objc_interface_type =
objc_class_type->getInterfaceType();
if (objc_interface_type &&
GetCompleteType((lldb::opaque_compiler_type_t)objc_interface_type)) {
GetCompleteType(static_cast<lldb::opaque_compiler_type_t>(
const_cast<clang::ObjCInterfaceType *>(objc_interface_type)))) {
clang::ObjCInterfaceDecl *class_interface_decl =
objc_interface_type->getDecl();
if (class_interface_decl) {

View File

@ -73,10 +73,6 @@ void StringLexer::PutBack(Size s) {
m_position -= s;
}
bool StringLexer::HasAny(Character c) {
return m_data.find(c, m_position) != std::string::npos;
}
std::string StringLexer::GetUnlexed() {
return std::string(m_data, m_position);
}

View File

@ -134,3 +134,22 @@ TEST(ArchSpecTest, TestSetTriple) {
AS = ArchSpec();
EXPECT_FALSE(AS.SetTriple(""));
}
TEST(ArchSpecTest, MergeFrom) {
ArchSpec A;
ArchSpec B("x86_64-pc-linux");
EXPECT_FALSE(A.IsValid());
ASSERT_TRUE(B.IsValid());
EXPECT_EQ(llvm::Triple::ArchType::x86_64, B.GetTriple().getArch());
EXPECT_EQ(llvm::Triple::VendorType::PC, B.GetTriple().getVendor());
EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS());
EXPECT_EQ(ArchSpec::eCore_x86_64_x86_64, B.GetCore());
A.MergeFrom(B);
ASSERT_TRUE(A.IsValid());
EXPECT_EQ(llvm::Triple::ArchType::x86_64, A.GetTriple().getArch());
EXPECT_EQ(llvm::Triple::VendorType::PC, A.GetTriple().getVendor());
EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS());
EXPECT_EQ(ArchSpec::eCore_x86_64_x86_64, A.GetCore());
}