Skip to content

Commit a0d6c6d

Browse files
Merge pull request #5701 from adrian-prantl/cherry-pick-1013
Cherry pick 1013
2 parents 7fdd7b0 + 6acf21d commit a0d6c6d

File tree

9 files changed

+154
-44
lines changed

9 files changed

+154
-44
lines changed

lldb/include/lldb/Host/HostInfoBase.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,9 @@ class HostInfoBase {
116116
#endif
117117

118118
/// Return the directory containing a specific Xcode SDK.
119-
static llvm::StringRef GetXcodeSDKPath(XcodeSDK sdk) { return {}; }
119+
static llvm::Expected<llvm::StringRef> GetXcodeSDKPath(XcodeSDK sdk) {
120+
return "";
121+
}
120122

121123
/// Return information about module \p image_name if it is loaded in
122124
/// the current process's address space.

lldb/include/lldb/Host/macosx/HostInfoMacOSX.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class HostInfoMacOSX : public HostInfoPosix {
5252
#endif
5353

5454
/// Query xcrun to find an Xcode SDK directory.
55-
static llvm::StringRef GetXcodeSDKPath(XcodeSDK sdk);
55+
static llvm::Expected<llvm::StringRef> GetXcodeSDKPath(XcodeSDK sdk);
5656

5757
/// Shared cache utilities
5858
static SharedCacheImageInfo

lldb/source/Core/Module.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1713,7 +1713,15 @@ Module::RemapSourceFile(llvm::StringRef path) const {
17131713
void Module::RegisterXcodeSDK(llvm::StringRef sdk_name,
17141714
llvm::StringRef sysroot) {
17151715
XcodeSDK sdk(sdk_name.str());
1716-
llvm::StringRef sdk_path(HostInfo::GetXcodeSDKPath(sdk));
1716+
auto sdk_path_or_err = HostInfo::GetXcodeSDKPath(sdk);
1717+
1718+
if (!sdk_path_or_err) {
1719+
Debugger::ReportError("Error while searching for Xcode SDK: " +
1720+
toString(sdk_path_or_err.takeError()));
1721+
return;
1722+
}
1723+
1724+
auto sdk_path = *sdk_path_or_err;
17171725
if (sdk_path.empty())
17181726
return;
17191727
// If the SDK changed for a previously registered source path, update it.

lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm

Lines changed: 86 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,14 @@ static void ParseOSVersion(llvm::VersionTuple &version, NSString *Key) {
337337
}
338338
}
339339

340-
FileSpec fspec(HostInfo::GetXcodeSDKPath(XcodeSDK::GetAnyMacOS()));
340+
auto sdk_path_or_err = HostInfo::GetXcodeSDKPath(XcodeSDK::GetAnyMacOS());
341+
if (!sdk_path_or_err) {
342+
Log *log = GetLog(LLDBLog::Host);
343+
LLDB_LOGF(log, "Error while searching for Xcode SDK: %s",
344+
toString(sdk_path_or_err.takeError()).c_str());
345+
return;
346+
}
347+
FileSpec fspec(*sdk_path_or_err);
341348
if (fspec) {
342349
if (FileSystem::Instance().Exists(fspec)) {
343350
std::string xcode_contents_dir =
@@ -365,12 +372,18 @@ static void ParseOSVersion(llvm::VersionTuple &version, NSString *Key) {
365372
return g_developer_directory;
366373
}
367374

368-
static std::string GetXcodeSDK(XcodeSDK sdk) {
375+
llvm::Expected<std::string> GetXcodeSDK(XcodeSDK sdk) {
369376
XcodeSDK::Info info = sdk.Parse();
370377
std::string sdk_name = XcodeSDK::GetCanonicalName(info);
378+
if (sdk_name.empty())
379+
return llvm::createStringError(llvm::inconvertibleErrorCode(),
380+
"Unrecognized SDK type: " + sdk.GetString());
381+
382+
Log *log = GetLog(LLDBLog::Host);
371383

372384
auto xcrun = [](const std::string &sdk,
373-
llvm::StringRef developer_dir = "") -> std::string {
385+
llvm::StringRef developer_dir =
386+
"") -> llvm::Expected<std::string> {
374387
Args args;
375388
if (!developer_dir.empty()) {
376389
args.AppendArgument("/usr/bin/env");
@@ -391,13 +404,29 @@ static void ParseOSVersion(llvm::VersionTuple &version, NSString *Key) {
391404
int status = 0;
392405
int signo = 0;
393406
std::string output_str;
394-
lldb_private::Status error =
395-
Host::RunShellCommand(args, FileSpec(), &status, &signo, &output_str,
396-
std::chrono::seconds(15));
397-
398-
// Check that xcrun return something useful.
399-
if (status != 0 || output_str.empty())
400-
return {};
407+
// The first time after Xcode was updated or freshly installed,
408+
// xcrun can take surprisingly long to build up its database.
409+
auto timeout = std::chrono::seconds(60);
410+
bool run_in_shell = false;
411+
lldb_private::Status error = Host::RunShellCommand(
412+
args, FileSpec(), &status, &signo, &output_str, timeout, run_in_shell);
413+
414+
// Check that xcrun returned something useful.
415+
if (error.Fail()) {
416+
// Catastrophic error.
417+
LLDB_LOG(log, "xcrun failed to execute: %s", error.AsCString());
418+
return error.ToError();
419+
}
420+
if (status != 0) {
421+
// xcrun didn't find a matching SDK. Not an error, we'll try
422+
// different spellings.
423+
LLDB_LOG(log, "xcrun returned exit code %d", status);
424+
return "";
425+
}
426+
if (output_str.empty()) {
427+
LLDB_LOG(log, "xcrun returned no results");
428+
return "";
429+
}
401430

402431
// Convert to a StringRef so we can manipulate the string without modifying
403432
// the underlying data.
@@ -414,7 +443,8 @@ static void ParseOSVersion(llvm::VersionTuple &version, NSString *Key) {
414443
return output.str();
415444
};
416445

417-
auto find_sdk = [&xcrun](const std::string &sdk_name) -> std::string {
446+
auto find_sdk =
447+
[&xcrun](const std::string &sdk_name) -> llvm::Expected<std::string> {
418448
// Invoke xcrun with the developer dir specified in the environment.
419449
std::string developer_dir = GetEnvDeveloperDir();
420450
if (!developer_dir.empty()) {
@@ -430,8 +460,10 @@ static void ParseOSVersion(llvm::VersionTuple &version, NSString *Key) {
430460
llvm::StringRef shlib_developer_dir =
431461
llvm::sys::path::parent_path(contents_dir);
432462
if (!shlib_developer_dir.empty()) {
433-
std::string sdk = xcrun(sdk_name, std::move(shlib_developer_dir));
434-
if (!sdk.empty())
463+
auto sdk = xcrun(sdk_name, std::move(shlib_developer_dir));
464+
if (!sdk)
465+
return sdk.takeError();
466+
if (!sdk->empty())
435467
return sdk;
436468
}
437469
}
@@ -441,52 +473,79 @@ static void ParseOSVersion(llvm::VersionTuple &version, NSString *Key) {
441473
return xcrun(sdk_name);
442474
};
443475

444-
std::string path = find_sdk(sdk_name);
476+
auto path_or_err = find_sdk(sdk_name);
477+
if (!path_or_err)
478+
return path_or_err.takeError();
479+
std::string path = *path_or_err;
445480
while (path.empty()) {
446481
// Try an alternate spelling of the name ("macosx10.9internal").
447482
if (info.type == XcodeSDK::Type::MacOSX && !info.version.empty() &&
448483
info.internal) {
449484
llvm::StringRef fixed(sdk_name);
450485
if (fixed.consume_back(".internal"))
451486
sdk_name = fixed.str() + "internal";
452-
path = find_sdk(sdk_name);
487+
path_or_err = find_sdk(sdk_name);
488+
if (!path_or_err)
489+
return path_or_err.takeError();
490+
path = *path_or_err;
453491
if (!path.empty())
454492
break;
455493
}
456-
Log *log = GetLog(LLDBLog::Host);
457494
LLDB_LOGF(log, "Couldn't find SDK %s on host", sdk_name.c_str());
458495

459496
// Try without the version.
460497
if (!info.version.empty()) {
461498
info.version = {};
462499
sdk_name = XcodeSDK::GetCanonicalName(info);
463-
path = find_sdk(sdk_name);
500+
path_or_err = find_sdk(sdk_name);
501+
if (!path_or_err)
502+
return path_or_err.takeError();
503+
path = *path_or_err;
464504
if (!path.empty())
465505
break;
466506
}
467507

468508
LLDB_LOGF(log, "Couldn't find any matching SDK on host");
469-
return {};
509+
return "";
470510
}
471511

472512
// Whatever is left in output should be a valid path.
473-
if (!FileSystem::Instance().Exists(path))
474-
return {};
513+
if (!FileSystem::Instance().Exists(path)) {
514+
LLDB_LOGF(log, "SDK returned by xcrun doesn't exist");
515+
return llvm::createStringError(llvm::inconvertibleErrorCode(),
516+
"SDK returned by xcrun doesn't exist");
517+
}
475518
return path;
476519
}
477520

478-
llvm::StringRef HostInfoMacOSX::GetXcodeSDKPath(XcodeSDK sdk) {
479-
static llvm::StringMap<std::string> g_sdk_path;
521+
llvm::Expected<llvm::StringRef> HostInfoMacOSX::GetXcodeSDKPath(XcodeSDK sdk) {
522+
struct ErrorOrPath {
523+
std::string str;
524+
bool is_error;
525+
};
526+
static llvm::StringMap<ErrorOrPath> g_sdk_path;
480527
static std::mutex g_sdk_path_mutex;
481528

482529
std::lock_guard<std::mutex> guard(g_sdk_path_mutex);
483530
LLDB_SCOPED_TIMER();
484531

485-
auto it = g_sdk_path.find(sdk.GetString());
486-
if (it != g_sdk_path.end())
487-
return it->second;
488-
auto it_new = g_sdk_path.insert({sdk.GetString(), GetXcodeSDK(sdk)});
489-
return it_new.first->second;
532+
auto key = sdk.GetString();
533+
auto it = g_sdk_path.find(key);
534+
if (it != g_sdk_path.end()) {
535+
if (it->second.is_error)
536+
return llvm::createStringError(llvm::inconvertibleErrorCode(),
537+
it->second.str);
538+
else
539+
return it->second.str;
540+
}
541+
auto path_or_err = GetXcodeSDK(sdk);
542+
if (!path_or_err) {
543+
std::string error = toString(path_or_err.takeError());
544+
g_sdk_path.insert({key, {error, true}});
545+
return llvm::createStringError(llvm::inconvertibleErrorCode(), error);
546+
}
547+
auto it_new = g_sdk_path.insert({key, {*path_or_err, false}});
548+
return it_new.first->second.str;
490549
}
491550

492551
namespace {

lldb/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <dlfcn.h>
1313
#endif
1414

15+
#include "lldb/Core/Debugger.h"
1516
#include "lldb/Core/Module.h"
1617
#include "lldb/Core/PluginManager.h"
1718
#include "lldb/Host/HostInfo.h"
@@ -278,9 +279,19 @@ std::vector<ArchSpec> PlatformAppleSimulator::GetSupportedArchitectures(
278279
static llvm::StringRef GetXcodeSDKDir(std::string preferred,
279280
std::string secondary) {
280281
llvm::StringRef sdk;
281-
sdk = HostInfo::GetXcodeSDKPath(XcodeSDK(std::move(preferred)));
282+
auto get_sdk = [&](std::string sdk) -> llvm::StringRef {
283+
auto sdk_path_or_err = HostInfo::GetXcodeSDKPath(XcodeSDK(std::move(sdk)));
284+
if (!sdk_path_or_err) {
285+
Debugger::ReportError("Error while searching for Xcode SDK: " +
286+
toString(sdk_path_or_err.takeError()));
287+
return {};
288+
}
289+
return *sdk_path_or_err;
290+
};
291+
292+
sdk = get_sdk(preferred);
282293
if (sdk.empty())
283-
sdk = HostInfo::GetXcodeSDKPath(XcodeSDK(std::move(secondary)));
294+
sdk = get_sdk(secondary);
284295
return sdk;
285296
}
286297

lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "PlatformRemoteAppleWatch.h"
1818
#endif
1919
#include "lldb/Breakpoint/BreakpointLocation.h"
20+
#include "lldb/Core/Debugger.h"
2021
#include "lldb/Core/Module.h"
2122
#include "lldb/Core/ModuleList.h"
2223
#include "lldb/Core/ModuleSpec.h"
@@ -123,8 +124,14 @@ ConstString PlatformMacOSX::GetSDKDirectory(lldb_private::Target &target) {
123124
}
124125

125126
// Use the default SDK as a fallback.
126-
FileSpec fspec(
127-
HostInfo::GetXcodeSDKPath(lldb_private::XcodeSDK::GetAnyMacOS()));
127+
auto sdk_path_or_err = HostInfo::GetXcodeSDKPath(XcodeSDK::GetAnyMacOS());
128+
if (!sdk_path_or_err) {
129+
Debugger::ReportError("Error while searching for Xcode SDK: " +
130+
toString(sdk_path_or_err.takeError()));
131+
return {};
132+
}
133+
134+
FileSpec fspec(*sdk_path_or_err);
128135
if (fspec) {
129136
if (FileSystem::Instance().Exists(fspec))
130137
return ConstString(fspec.GetPath());

lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,6 +1354,22 @@ static llvm::Optional<StringRef> GetDSYMBundle(Module &module) {
13541354
return dsym;
13551355
}
13561356

1357+
static std::string GetSDKPath(std::string m_description, XcodeSDK sdk) {
1358+
auto sdk_path_or_err = HostInfo::GetXcodeSDKPath(sdk);
1359+
if (!sdk_path_or_err) {
1360+
Debugger::ReportError("Error while searching for Xcode SDK: " +
1361+
toString(sdk_path_or_err.takeError()));
1362+
HEALTH_LOG_PRINTF("Error while searching for Xcode SDK %s.",
1363+
sdk.GetString().str().c_str());
1364+
return {};
1365+
}
1366+
1367+
std::string sdk_path = sdk_path_or_err->str();
1368+
LOG_PRINTF(GetLog(LLDBLog::Types), "Host SDK path for sdk %s is %s.",
1369+
sdk.GetString().str().c_str(), sdk_path.c_str());
1370+
return sdk_path;
1371+
}
1372+
13571373
/// Force parsing of the CUs to extract the SDK info.
13581374
static std::string GetSDKPathFromDebugInfo(std::string m_description,
13591375
Module &module) {
@@ -1376,11 +1392,7 @@ static std::string GetSDKPathFromDebugInfo(std::string m_description,
13761392
"'%s'. Mixed use of SDKs indicates use of different "
13771393
"toolchains, which is not supported.",
13781394
module.GetFileSpec().GetFilename().GetCString());
1379-
1380-
std::string sdk_path = HostInfo::GetXcodeSDKPath(sdk).str();
1381-
LOG_PRINTF(GetLog(LLDBLog::Types), "Host SDK path for sdk %s is %s.",
1382-
sdk.GetString().str().c_str(), sdk_path.c_str());
1383-
return sdk_path;
1395+
return GetSDKPath(m_description, sdk);
13841396
}
13851397

13861398
/// Detect whether a Swift module was "imported" by DWARFImporter.
@@ -2464,15 +2476,15 @@ void SwiftASTContext::InitializeSearchPathOptions(
24642476
XcodeSDK::Info info;
24652477
info.type = XcodeSDK::GetSDKTypeForTriple(triple);
24662478
XcodeSDK sdk(info);
2467-
sdk_path = HostInfo::GetXcodeSDKPath(sdk).str();
2479+
sdk_path = GetSDKPath(m_description, sdk);
24682480
}
24692481
if (sdk_path.empty()) {
24702482
// This fallback is questionable. Perhaps it should be removed.
24712483
XcodeSDK::Info info;
24722484
info.type = XcodeSDK::GetSDKTypeForTriple(
24732485
HostInfo::GetArchitecture().GetTriple());
24742486
XcodeSDK sdk(info);
2475-
sdk_path = std::string(HostInfo::GetXcodeSDKPath(sdk));
2487+
sdk_path = GetSDKPath(m_description, sdk);
24762488
}
24772489
if (!sdk_path.empty()) {
24782490
// Note that calling setSDKPath() also recomputes all paths that

lldb/unittests/Host/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ add_lldb_unittest(HostTests
3939
${FILES}
4040
LINK_LIBS
4141
lldbHost
42+
lldbCore
4243
lldbUtilityHelpers
4344
lldbHostHelpers
4445
LLVMTestingSupport

lldb/unittests/Host/HostInfoTest.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,21 @@ TEST_F(HostInfoTest, GetHostname) {
5656

5757
#if defined(__APPLE__)
5858
TEST_F(HostInfoTest, GetXcodeSDK) {
59-
EXPECT_FALSE(HostInfo::GetXcodeSDKPath(XcodeSDK("MacOSX.sdk")).empty());
59+
auto get_sdk = [](std::string sdk, bool error = false) -> llvm::StringRef {
60+
auto sdk_path_or_err = HostInfo::GetXcodeSDKPath(XcodeSDK(std::move(sdk)));
61+
if (!error) {
62+
EXPECT_TRUE((bool)sdk_path_or_err);
63+
return *sdk_path_or_err;
64+
}
65+
EXPECT_FALSE((bool)sdk_path_or_err);
66+
llvm::consumeError(sdk_path_or_err.takeError());
67+
return {};
68+
};
69+
EXPECT_FALSE(get_sdk("MacOSX.sdk").empty());
6070
// These are expected to fall back to an available version.
61-
EXPECT_FALSE(HostInfo::GetXcodeSDKPath(XcodeSDK("MacOSX9999.sdk")).empty());
71+
EXPECT_FALSE(get_sdk("MacOSX9999.sdk").empty());
6272
// This is expected to fail.
63-
EXPECT_TRUE(HostInfo::GetXcodeSDKPath(XcodeSDK("CeciNestPasUnOS.sdk")).empty());
73+
EXPECT_TRUE(get_sdk("CeciNestPasUnOS.sdk", true).empty());
6474
}
6575
#endif
6676

0 commit comments

Comments
 (0)