Skip to content

Commit 457eb05

Browse files
committed
[lldb/PlatformMacOSX] Re-implement GetDeveloperDirectory
GetDeveloperDirectory returns a const char* which is NULL when we cannot find the developer directory. This crashes in PlatformDarwinKernel::CollectKextAndKernelDirectories because we're unconditionally assigning it to a std::string. Coincidentally I just refactored a bunch of code in PlatformMacOSX so instead of a ad-hoc fix I've reimplemented the method based on GetXcodeContentsDirectory. The change is mostly NFC. Obviously it fixes the crash, but it also removes support for finding the Xcode directory through he legacy $XCODE_SELECT_PREFIX_DIR/usr/share/xcode-select/xcode_dir_path. Differential revision: https://reviews.llvm.org/D76938
1 parent 34d7751 commit 457eb05

8 files changed

+33
-105
lines changed

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

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,10 @@ void PlatformAppleSimulator::GetStatus(Stream &strm) {
7777
// simulator
7878
PlatformAppleSimulator::LoadCoreSimulator();
7979

80+
std::string developer_dir = GetXcodeDeveloperDirectory().GetPath();
8081
CoreSimulatorSupport::DeviceSet devices =
8182
CoreSimulatorSupport::DeviceSet::GetAvailableDevices(
82-
GetDeveloperDirectory());
83+
developer_dir.c_str());
8384
const size_t num_devices = devices.GetNumDevices();
8485
if (num_devices) {
8586
strm.Printf("Available devices:\n");
@@ -123,9 +124,10 @@ Status PlatformAppleSimulator::ConnectRemote(Args &args) {
123124
const char *arg_cstr = args.GetArgumentAtIndex(0);
124125
if (arg_cstr) {
125126
std::string arg_str(arg_cstr);
127+
std::string developer_dir = GetXcodeDeveloperDirectory().GetPath();
126128
CoreSimulatorSupport::DeviceSet devices =
127129
CoreSimulatorSupport::DeviceSet::GetAvailableDevices(
128-
GetDeveloperDirectory());
130+
developer_dir.c_str());
129131
devices.ForEach(
130132
[this, &arg_str](const CoreSimulatorSupport::Device &device) -> bool {
131133
if (arg_str == device.GetUDID() || arg_str == device.GetName()) {
@@ -212,12 +214,12 @@ FileSpec PlatformAppleSimulator::GetCoreSimulatorPath() {
212214
#if defined(__APPLE__)
213215
std::lock_guard<std::mutex> guard(m_core_sim_path_mutex);
214216
if (!m_core_simulator_framework_path.hasValue()) {
215-
const char *developer_dir = GetDeveloperDirectory();
216-
if (developer_dir) {
217+
if (FileSpec fspec = GetXcodeDeveloperDirectory()) {
218+
std::string developer_dir = fspec.GetPath();
217219
StreamString cs_path;
218220
cs_path.Printf(
219221
"%s/Library/PrivateFrameworks/CoreSimulator.framework/CoreSimulator",
220-
developer_dir);
222+
developer_dir.c_str());
221223
m_core_simulator_framework_path = FileSpec(cs_path.GetData());
222224
FileSystem::Instance().Resolve(*m_core_simulator_framework_path);
223225
}
@@ -245,8 +247,9 @@ CoreSimulatorSupport::Device PlatformAppleSimulator::GetSimulatorDevice() {
245247
if (!m_device.hasValue()) {
246248
const CoreSimulatorSupport::DeviceType::ProductFamilyID dev_id =
247249
CoreSimulatorSupport::DeviceType::ProductFamilyID::iPhone;
250+
std::string developer_dir = GetXcodeDeveloperDirectory().GetPath();
248251
m_device = CoreSimulatorSupport::DeviceSet::GetAvailableDevices(
249-
GetDeveloperDirectory())
252+
developer_dir.c_str())
250253
.GetFanciest(dev_id);
251254
}
252255

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -255,14 +255,14 @@ EnumerateDirectoryCallback(void *baton, llvm::sys::fs::file_type ft,
255255
const char *PlatformAppleTVSimulator::GetSDKDirectoryAsCString() {
256256
std::lock_guard<std::mutex> guard(m_sdk_dir_mutex);
257257
if (m_sdk_directory.empty()) {
258-
const char *developer_dir = GetDeveloperDirectory();
259-
if (developer_dir) {
258+
if (FileSpec fspec = GetXcodeDeveloperDirectory()) {
259+
std::string developer_dir = fspec.GetPath();
260260
char sdks_directory[PATH_MAX];
261261
char sdk_dirname[PATH_MAX];
262262
sdk_dirname[0] = '\0';
263263
snprintf(sdks_directory, sizeof(sdks_directory),
264264
"%s/Platforms/AppleTVSimulator.platform/Developer/SDKs",
265-
developer_dir);
265+
developer_dir.c_str());
266266
FileSpec simulator_sdk_spec;
267267
bool find_directories = true;
268268
bool find_files = false;

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -255,14 +255,14 @@ EnumerateDirectoryCallback(void *baton, llvm::sys::fs::file_type ft,
255255
const char *PlatformAppleWatchSimulator::GetSDKDirectoryAsCString() {
256256
std::lock_guard<std::mutex> guard(m_sdk_dir_mutex);
257257
if (m_sdk_directory.empty()) {
258-
const char *developer_dir = GetDeveloperDirectory();
259-
if (developer_dir) {
258+
if (FileSpec fspec = GetXcodeDeveloperDirectory()) {
259+
std::string developer_dir = fspec.GetPath();
260260
char sdks_directory[PATH_MAX];
261261
char sdk_dirname[PATH_MAX];
262262
sdk_dirname[0] = '\0';
263263
snprintf(sdks_directory, sizeof(sdks_directory),
264264
"%s/Platforms/AppleWatchSimulator.platform/Developer/SDKs",
265-
developer_dir);
265+
developer_dir.c_str());
266266
FileSpec simulator_sdk_spec;
267267
bool find_directories = true;
268268
bool find_files = false;

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

Lines changed: 11 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,7 @@ using namespace lldb;
4848
using namespace lldb_private;
4949

5050
/// Default Constructor
51-
PlatformDarwin::PlatformDarwin(bool is_host)
52-
: PlatformPOSIX(is_host), // This is the local host platform
53-
m_developer_directory() {}
51+
PlatformDarwin::PlatformDarwin(bool is_host) : PlatformPOSIX(is_host) {}
5452

5553
/// Destructor.
5654
///
@@ -1135,88 +1133,17 @@ static FileSpec GetXcodeSelectPath() {
11351133
return g_xcode_select_filespec;
11361134
}
11371135

1138-
// Return a directory path like /Applications/Xcode.app/Contents/Developer
1139-
const char *PlatformDarwin::GetDeveloperDirectory() {
1140-
std::lock_guard<std::mutex> guard(m_mutex);
1141-
if (m_developer_directory.empty()) {
1142-
bool developer_dir_path_valid = false;
1143-
char developer_dir_path[PATH_MAX];
1144-
1145-
// Get the lldb framework's file path, and if it exists, truncate some
1146-
// components to only the developer directory path.
1147-
FileSpec temp_file_spec = HostInfo::GetShlibDir();
1148-
if (temp_file_spec) {
1149-
if (temp_file_spec.GetPath(developer_dir_path,
1150-
sizeof(developer_dir_path))) {
1151-
// e.g.
1152-
// /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework
1153-
char *shared_frameworks =
1154-
strstr(developer_dir_path, "/SharedFrameworks/LLDB.framework");
1155-
if (shared_frameworks) {
1156-
shared_frameworks[0] = '\0'; // truncate developer_dir_path at this point
1157-
strncat (developer_dir_path, "/Developer", sizeof (developer_dir_path) - 1); // add /Developer on
1158-
developer_dir_path_valid = true;
1159-
} else {
1160-
// e.g.
1161-
// /Applications/Xcode.app/Contents/Developer/Toolchains/iOS11.2.xctoolchain/System/Library/PrivateFrameworks/LLDB.framework
1162-
char *developer_toolchains =
1163-
strstr(developer_dir_path, "/Contents/Developer/Toolchains/");
1164-
if (developer_toolchains) {
1165-
developer_toolchains += sizeof ("/Contents/Developer") - 1;
1166-
developer_toolchains[0] = '\0'; // truncate developer_dir_path at this point
1167-
developer_dir_path_valid = true;
1168-
}
1169-
}
1170-
}
1171-
}
1172-
1173-
if (!developer_dir_path_valid) {
1174-
std::string xcode_dir_path;
1175-
const char *xcode_select_prefix_dir = getenv("XCODE_SELECT_PREFIX_DIR");
1176-
if (xcode_select_prefix_dir)
1177-
xcode_dir_path.append(xcode_select_prefix_dir);
1178-
xcode_dir_path.append("/usr/share/xcode-select/xcode_dir_path");
1179-
temp_file_spec.SetFile(xcode_dir_path, FileSpec::Style::native);
1180-
auto dir_buffer =
1181-
FileSystem::Instance().CreateDataBuffer(temp_file_spec.GetPath());
1182-
if (dir_buffer && dir_buffer->GetByteSize() > 0) {
1183-
llvm::StringRef path_ref(dir_buffer->GetChars());
1184-
// Trim tailing newlines and make sure there is enough room for a null
1185-
// terminator.
1186-
path_ref =
1187-
path_ref.rtrim("\r\n").take_front(sizeof(developer_dir_path) - 1);
1188-
::memcpy(developer_dir_path, path_ref.data(), path_ref.size());
1189-
developer_dir_path[path_ref.size()] = '\0';
1190-
developer_dir_path_valid = true;
1191-
}
1192-
}
1193-
1194-
if (!developer_dir_path_valid) {
1195-
FileSpec devel_dir = GetXcodeSelectPath();
1196-
if (FileSystem::Instance().IsDirectory(devel_dir)) {
1197-
devel_dir.GetPath(&developer_dir_path[0], sizeof(developer_dir_path));
1198-
developer_dir_path_valid = true;
1199-
}
1200-
}
1201-
1202-
if (developer_dir_path_valid) {
1203-
temp_file_spec.SetFile(developer_dir_path, FileSpec::Style::native);
1204-
if (FileSystem::Instance().Exists(temp_file_spec)) {
1205-
m_developer_directory.assign(developer_dir_path);
1206-
return m_developer_directory.c_str();
1207-
}
1136+
lldb_private::FileSpec PlatformDarwin::GetXcodeDeveloperDirectory() {
1137+
static lldb_private::FileSpec g_developer_directory;
1138+
static llvm::once_flag g_once_flag;
1139+
llvm::call_once(g_once_flag, []() {
1140+
if (FileSpec fspec = GetXcodeContentsDirectory()) {
1141+
fspec.AppendPathComponent("Developer");
1142+
if (FileSystem::Instance().Exists(fspec))
1143+
g_developer_directory = fspec;
12081144
}
1209-
// Assign a single NULL character so we know we tried to find the device
1210-
// support directory and we don't keep trying to find it over and over.
1211-
m_developer_directory.assign(1, '\0');
1212-
}
1213-
1214-
// We should have put a single NULL character into m_developer_directory or
1215-
// it should have a valid path if the code gets here
1216-
assert(m_developer_directory.empty() == false);
1217-
if (m_developer_directory[0])
1218-
return m_developer_directory.c_str();
1219-
return nullptr;
1145+
});
1146+
return g_developer_directory;
12201147
}
12211148

12221149
BreakpointSP PlatformDarwin::SetThreadCreationBreakpoint(Target &target) {

lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ class PlatformDarwin : public PlatformPOSIX {
104104
static llvm::StringRef GetSDKNameForType(SDKType type);
105105
static lldb_private::FileSpec GetXcodeSDK(SDKType type);
106106
static lldb_private::FileSpec GetXcodeContentsDirectory();
107+
static lldb_private::FileSpec GetXcodeDeveloperDirectory();
107108

108109
/// Return the toolchain directroy the current LLDB instance is located in.
109110
static lldb_private::FileSpec GetCurrentToolchainDirectory();
@@ -176,7 +177,6 @@ class PlatformDarwin : public PlatformPOSIX {
176177
std::vector<std::string> &options,
177178
SDKType sdk_type);
178179

179-
const char *GetDeveloperDirectory();
180180

181181
lldb_private::Status FindBundleBinaryInExecSearchPaths(
182182
const lldb_private::ModuleSpec &module_spec,
@@ -188,7 +188,6 @@ class PlatformDarwin : public PlatformPOSIX {
188188
llvm::StringRef component);
189189
static std::string FindXcodeContentsDirectoryInPath(llvm::StringRef path);
190190

191-
std::string m_developer_directory;
192191

193192
private:
194193
DISALLOW_COPY_AND_ASSIGN(PlatformDarwin);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ void PlatformDarwinKernel::CollectKextAndKernelDirectories() {
327327

328328
// DeveloperDirectory is something like
329329
// "/Applications/Xcode.app/Contents/Developer"
330-
std::string developer_dir = GetDeveloperDirectory();
330+
std::string developer_dir = GetXcodeDeveloperDirectory().GetPath();
331331
if (developer_dir.empty())
332332
developer_dir = "/Applications/Xcode.app/Contents/Developer";
333333

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,9 +342,8 @@ PlatformRemoteDarwinDevice::GetSDKDirectoryForLatestOSVersion() {
342342
const char *PlatformRemoteDarwinDevice::GetDeviceSupportDirectory() {
343343
std::string platform_dir = "/Platforms/" + GetPlatformName() + "/DeviceSupport";
344344
if (m_device_support_directory.empty()) {
345-
const char *device_support_dir = GetDeveloperDirectory();
346-
if (device_support_dir) {
347-
m_device_support_directory.assign(device_support_dir);
345+
if (FileSpec fspec = GetXcodeDeveloperDirectory()) {
346+
m_device_support_directory = fspec.GetPath();
348347
m_device_support_directory.append(platform_dir.c_str());
349348
} else {
350349
// Assign a single NULL character so we know we tried to find the device

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -260,14 +260,14 @@ EnumerateDirectoryCallback(void *baton, llvm::sys::fs::file_type ft,
260260
const char *PlatformiOSSimulator::GetSDKDirectoryAsCString() {
261261
std::lock_guard<std::mutex> guard(m_sdk_dir_mutex);
262262
if (m_sdk_directory.empty()) {
263-
const char *developer_dir = GetDeveloperDirectory();
264-
if (developer_dir) {
263+
if (FileSpec fspec = GetXcodeDeveloperDirectory()) {
264+
std::string developer_dir = fspec.GetPath();
265265
char sdks_directory[PATH_MAX];
266266
char sdk_dirname[PATH_MAX];
267267
sdk_dirname[0] = '\0';
268268
snprintf(sdks_directory, sizeof(sdks_directory),
269269
"%s/Platforms/iPhoneSimulator.platform/Developer/SDKs",
270-
developer_dir);
270+
developer_dir.c_str());
271271
FileSpec simulator_sdk_spec;
272272
bool find_directories = true;
273273
bool find_files = false;

0 commit comments

Comments
 (0)