Skip to content
This repository has been archived by the owner on Apr 2, 2020. It is now read-only.

Improve support for debugging Swift code built on a different machine. #503

Merged
merged 1 commit into from Apr 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/lldb/Symbol/SwiftASTContext.h
Expand Up @@ -865,6 +865,10 @@ class SwiftASTContext : public TypeSystem {
SwiftEnumDescriptor *GetCachedEnumInfo(void *type);

friend class CompilerType;

/// Apply a PathMappingList dictionary on all search paths in the
/// ClangImporterOptions.
void RemapClangImporterOptions(const PathMappingList &path_map);
};

class SwiftASTContextForExpressions : public SwiftASTContext {
Expand Down
3 changes: 3 additions & 0 deletions lldb.xcodeproj/project.pbxproj
Expand Up @@ -9387,6 +9387,7 @@
"-Wglobal-constructors",
"$(OTHER_CFLAGS)",
"-DLLDB_USE_BUILTIN_DEMANGLER",
"-DLIBXML2_DEFINED",
"-DDT_VARIANT_$(DT_VARIANT)",
);
"OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*]" = (
Expand Down Expand Up @@ -13629,6 +13630,7 @@
"-Wglobal-constructors",
"$(OTHER_CFLAGS)",
"-DLLDB_USE_BUILTIN_DEMANGLER",
"-DLIBXML2_DEFINED",
"-DDT_VARIANT_$(DT_VARIANT)",
);
"OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*]" = (
Expand Down Expand Up @@ -14230,6 +14232,7 @@
"-Wglobal-constructors",
"$(OTHER_CFLAGS)",
"-DLLDB_USE_BUILTIN_DEMANGLER",
"-DLIBXML2_DEFINED",
"-DDT_VARIANT_$(DT_VARIANT)",
);
"OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*]" = (
Expand Down
@@ -0,0 +1,13 @@
import CFoo
import Foundation

func use<T>(_ t: T) {}

@objc public class Foo : NSObject {
@objc public func f() {
let foo = CFoo(x: 23)
let bar = FromBridgingHeader(y: 42)
use(foo) // break here
use(bar)
}
}
@@ -0,0 +1 @@
struct CFoo { int x; };
@@ -0,0 +1 @@
struct FromBridgingHeader { int y; };
@@ -0,0 +1,3 @@
module CFoo {
header "CFoo.h"
}
@@ -0,0 +1,40 @@
LEVEL = ../../../../make
SRCDIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
SWIFT_OBJC_INTEROP := 1

include $(LEVEL)/Makefile.rules

BUILDDIR := $(realpath $(shell pwd))
BOTDIR := $(BUILDDIR)/buildbot
USERDIR := $(BUILDDIR)/user

a.out: main.m libFoo.dylib
$(CC) $(CFLAGS) $(MANDATORY_MODULE_BUILD_CFLAGS) -I$(shell pwd) -lFoo -L$(shell pwd) -o $@ $<
mv $(BOTDIR) $(USERDIR)

libFoo.dylib: Foo.swift
mkdir -p $(BOTDIR)
cp -r $(SRCDIR)/Foo $(BOTDIR)/
$(SWIFTC) -g -Onone $^ -emit-library \
-module-name $(shell basename $< .swift) -emit-module \
-Xlinker -install_name -Xlinker @executable_path/$@ \
-Xcc -I$(BOTDIR)/Foo $(SWIFTFLAGS) -emit-objc-header-path Foo.h \
-sdk "$(SWIFTSDKROOT)" -import-objc-header $(BOTDIR)/Foo/bridge.h
UUID=$$(dwarfdump --uuid "$@.dSYM" | awk '{ print $$2 }') ; \
echo "UUID = $$UUID" ; \
PLIST="$@.dSYM/Contents/Resources/$$UUID.plist" ; \
echo "Generating $$PLIST ..."; \
echo '<?xml version="1.0" encoding="UTF-8"?>'>$$PLIST; \
echo '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">'>>$$PLIST; \
echo '<plist version="1.0">'>>$$PLIST; \
echo '<dict>'>>$$PLIST; \
echo ' <key>DBGSourcePathRemapping</key>'>>$$PLIST; \
echo ' <dict>'>>$$PLIST; \
echo " <key>$(BOTDIR)</key>">>$$PLIST; \
echo " <string>$(USERDIR)</string>">>$$PLIST; \
echo ' </dict>'>>$$PLIST; \
echo '</dict>'>>$$PLIST; \
echo '</plist>'>>$$PLIST

clean::
rm -rf $(USERDIR) rm -rf *.swiftmodule *.swiftdoc *.dSYM *~ lib*.dylib a.out *.o
@@ -0,0 +1,101 @@
# TestSwiftRewriteClangPaths.py
#
# This source file is part of the Swift.org open source project
#
# Copyright (c) 2018 Apple Inc. and the Swift project authors
# Licensed under Apache License v2.0 with Runtime Library Exception
#
# See https://swift.org/LICENSE.txt for license information
# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
#
# ------------------------------------------------------------------------------

import lldb
from lldbsuite.test.lldbtest import *
import lldbsuite.test.decorators as decorators
import lldbsuite.test.lldbutil as lldbutil
import os
import unittest2
import shutil

class TestSwiftRewriteClangPaths(TestBase):

mydir = TestBase.compute_mydir(__file__)

def setUp(self):
TestBase.setUp(self)

@decorators.skipUnlessDarwin
@decorators.swiftTest
@decorators.add_test_categories(["swiftpr"])
def testWithRemap(self):
self.dotest(True)

@decorators.skipUnlessDarwin
@decorators.swiftTest
@decorators.add_test_categories(["swiftpr"])
def testWithoutRemap(self):
self.dotest(False)

def find_plist(self):
import glob
plist = self.getBuildArtifact("libFoo.dylib.dSYM/Contents/Resources/*.plist")
lst = glob.glob(plist)
self.assertTrue(len(lst) == 1)
return lst[0]

def dotest(self, remap):
self.build()
# To ensure the module is rebuilt remove the cache to avoid caching.
mod_cache = self.getBuildArtifact("my-clang-modules-cache")
if os.path.isdir(mod_cache):
shutil.rmtree(mod_cache)
self.runCmd('settings set symbols.clang-modules-cache-path "%s"'
% mod_cache)

botdir = os.path.realpath(self.getBuildArtifact("buildbot"))
userdir = os.path.realpath(self.getBuildArtifact("user"))
self.assertFalse(os.path.isdir(botdir))
self.assertTrue(os.path.isdir(userdir))
plist = self.find_plist()
self.assertTrue(os.path.isfile(plist))
if remap:
self.runCmd("settings set target.source-map %s %s" %
(botdir, userdir))
else:
# Also delete the remapping plist from the .dSYM to verify
# that this doesn't work by happy accident without it.
os.remove(plist)

exe_name = "a.out"
exe = self.getBuildArtifact(exe_name)

# Create the target
target = self.dbg.CreateTarget(exe)
self.assertTrue(target, VALID_TARGET)

# Set the breakpoints
foo_breakpoint = target.BreakpointCreateBySourceRegex(
'break here', lldb.SBFileSpec('Foo.swift'))

process = target.LaunchSimple(None, None, os.getcwd())

if remap:
comment = "returns correct value"
self.expect("p foo", comment, substrs=["x", "23"])
self.expect("p bar", comment, substrs=["y", "42"])
self.expect("fr var foo", comment, substrs=["x", "23"])
self.expect("fr var bar", comment, substrs=["y", "42"])
self.assertTrue(os.path.isdir(mod_cache), "module cache exists")
else:
threads = lldbutil.get_threads_stopped_at_breakpoint(
process, foo_breakpoint)
frame = threads[0].GetFrameAtIndex(0)
value = frame.EvaluateExpression("foo")
self.assertFalse(value.GetError().Success())

if __name__ == '__main__':
import atexit
lldb.SBDebugger.Initialize()
atexit.register(lldb.SBDebugger.Terminate)
unittest2.main()
@@ -0,0 +1,7 @@
@import Foundation;
#include "Foo.h"

int main(int argc, char **argv) {
[[[Foo alloc] init] f];
return 0;
}
31 changes: 31 additions & 0 deletions source/Symbol/SwiftASTContext.cpp
Expand Up @@ -1275,6 +1275,31 @@ static bool DeserializeCompilerFlags(SwiftASTContext &swift_ast, Module &module,
}
}

void SwiftASTContext::RemapClangImporterOptions(
const PathMappingList &path_map) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
auto &options = GetClangImporterOptions();
std::string remapped;
if (path_map.RemapPath(options.BridgingHeader, remapped)) {
if (log)
log->Printf("remapped %s -> %s", options.BridgingHeader.c_str(),
remapped.c_str());
options.BridgingHeader = remapped;
}
for (auto &arg_string : options.ExtraArgs) {
StringRef prefix;
StringRef arg = arg_string;
if (arg.consume_front("-I"))
prefix = "-I";
if (path_map.RemapPath(arg, remapped)) {
if (log)
log->Printf("remapped %s -> %s%s", arg.str().c_str(),
prefix.str().c_str(), remapped.c_str());
arg_string = prefix.str()+remapped;
}
}
}

lldb::TypeSystemSP SwiftASTContext::CreateInstance(lldb::LanguageType language,
Module &module) {
if (!SwiftASTContextSupportsLanguage(language))
Expand Down Expand Up @@ -1488,6 +1513,9 @@ lldb::TypeSystemSP SwiftASTContext::CreateInstance(lldb::LanguageType language,
}
}

// Apply source path remappings ofund in the module's dSYM.
swift_ast_sp->RemapClangImporterOptions(module.GetSourceMappingList());

if (!swift_ast_sp->GetClangImporter()) {
if (log) {
log->Printf("((Module*)%p) [%s]->GetSwiftASTContext() returning NULL "
Expand Down Expand Up @@ -1813,6 +1841,9 @@ lldb::TypeSystemSP SwiftASTContext::CreateInstance(lldb::LanguageType language,
swift_ast_sp->GetDiagnosticEngine());
}

// Apply source path remappings ofund in the target settings.
swift_ast_sp->RemapClangImporterOptions(target.GetSourcePathMap());

// This needs to happen once all the import paths are set, or otherwise no
// modules will be found.
if (!swift_ast_sp->GetClangImporter()) {
Expand Down