Vendor import of lldb trunk r300890:
https://llvm.org/svn/llvm-project/lldb/trunk@300890
This commit is contained in:
parent
74a628f776
commit
d44a35e87e
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 */,
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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"'])
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
LEVEL = ../../make
|
||||
|
||||
C_SOURCES := main.c
|
||||
CFLAGS_EXTRAS += -std=c99
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
|
@ -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")
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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.")
|
|
@ -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
|
||||
|
|
|
@ -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."""
|
||||
|
|
|
@ -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."""
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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() {}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
}
|
|
@ -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_
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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__)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 \
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue