xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- PlatformRemoteDarwinDevice.cpp ------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "PlatformRemoteDarwinDevice.h"
10061da546Spatrick 
11061da546Spatrick #include "lldb/Breakpoint/BreakpointLocation.h"
12061da546Spatrick #include "lldb/Core/Module.h"
13061da546Spatrick #include "lldb/Core/ModuleList.h"
14061da546Spatrick #include "lldb/Core/ModuleSpec.h"
15061da546Spatrick #include "lldb/Core/PluginManager.h"
16061da546Spatrick #include "lldb/Host/FileSystem.h"
17061da546Spatrick #include "lldb/Host/Host.h"
18dda28197Spatrick #include "lldb/Host/HostInfo.h"
19061da546Spatrick #include "lldb/Target/Process.h"
20061da546Spatrick #include "lldb/Target/Target.h"
21061da546Spatrick #include "lldb/Utility/FileSpec.h"
22*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
23061da546Spatrick #include "lldb/Utility/Log.h"
24061da546Spatrick #include "lldb/Utility/Status.h"
25061da546Spatrick #include "lldb/Utility/StreamString.h"
26*f6aab3d8Srobert #include <optional>
27061da546Spatrick 
28061da546Spatrick using namespace lldb;
29061da546Spatrick using namespace lldb_private;
30061da546Spatrick 
SDKDirectoryInfo(const lldb_private::FileSpec & sdk_dir)31061da546Spatrick PlatformRemoteDarwinDevice::SDKDirectoryInfo::SDKDirectoryInfo(
32061da546Spatrick     const lldb_private::FileSpec &sdk_dir)
33061da546Spatrick     : directory(sdk_dir), build(), user_cached(false) {
34061da546Spatrick   llvm::StringRef dirname_str = sdk_dir.GetFilename().GetStringRef();
35061da546Spatrick   llvm::StringRef build_str;
36061da546Spatrick   std::tie(version, build_str) = ParseVersionBuildDir(dirname_str);
37061da546Spatrick   build.SetString(build_str);
38061da546Spatrick }
39061da546Spatrick 
40061da546Spatrick /// Default Constructor
PlatformRemoteDarwinDevice()41061da546Spatrick PlatformRemoteDarwinDevice::PlatformRemoteDarwinDevice()
42*f6aab3d8Srobert     : PlatformDarwinDevice(false) {} // This is a remote platform
43061da546Spatrick 
44061da546Spatrick /// Destructor.
45061da546Spatrick ///
46061da546Spatrick /// The destructor is virtual since this class is designed to be
47061da546Spatrick /// inherited from by the plug-in instance.
48be691f3bSpatrick PlatformRemoteDarwinDevice::~PlatformRemoteDarwinDevice() = default;
49061da546Spatrick 
GetStatus(Stream & strm)50061da546Spatrick void PlatformRemoteDarwinDevice::GetStatus(Stream &strm) {
51061da546Spatrick   Platform::GetStatus(strm);
52061da546Spatrick   const char *sdk_directory = GetDeviceSupportDirectoryForOSVersion();
53061da546Spatrick   if (sdk_directory)
54061da546Spatrick     strm.Printf("  SDK Path: \"%s\"\n", sdk_directory);
55061da546Spatrick   else
56061da546Spatrick     strm.PutCString("  SDK Path: error: unable to locate SDK\n");
57061da546Spatrick 
58061da546Spatrick   const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
59061da546Spatrick   for (uint32_t i = 0; i < num_sdk_infos; ++i) {
60061da546Spatrick     const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
61061da546Spatrick     strm.Printf(" SDK Roots: [%2u] \"%s\"\n", i,
62061da546Spatrick                 sdk_dir_info.directory.GetPath().c_str());
63061da546Spatrick   }
64061da546Spatrick }
65061da546Spatrick 
ResolveExecutable(const ModuleSpec & ms,lldb::ModuleSP & exe_module_sp,const FileSpecList * module_search_paths_ptr)66061da546Spatrick Status PlatformRemoteDarwinDevice::ResolveExecutable(
67061da546Spatrick     const ModuleSpec &ms, lldb::ModuleSP &exe_module_sp,
68061da546Spatrick     const FileSpecList *module_search_paths_ptr) {
69061da546Spatrick   Status error;
70061da546Spatrick   // Nothing special to do here, just use the actual file and architecture
71061da546Spatrick 
72061da546Spatrick   ModuleSpec resolved_module_spec(ms);
73061da546Spatrick 
74061da546Spatrick   // Resolve any executable within a bundle on MacOSX
75061da546Spatrick   // TODO: verify that this handles shallow bundles, if not then implement one
76061da546Spatrick   // ourselves
77061da546Spatrick   Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
78061da546Spatrick 
79061da546Spatrick   if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) {
80061da546Spatrick     if (resolved_module_spec.GetArchitecture().IsValid() ||
81061da546Spatrick         resolved_module_spec.GetUUID().IsValid()) {
82061da546Spatrick       error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
83061da546Spatrick                                           nullptr, nullptr, nullptr);
84061da546Spatrick 
85061da546Spatrick       if (exe_module_sp && exe_module_sp->GetObjectFile())
86061da546Spatrick         return error;
87061da546Spatrick       exe_module_sp.reset();
88061da546Spatrick     }
89061da546Spatrick     // No valid architecture was specified or the exact ARM slice wasn't found
90061da546Spatrick     // so ask the platform for the architectures that we should be using (in
91061da546Spatrick     // the correct order) and see if we can find a match that way
92061da546Spatrick     StreamString arch_names;
93*f6aab3d8Srobert     llvm::ListSeparator LS;
94*f6aab3d8Srobert     ArchSpec process_host_arch;
95*f6aab3d8Srobert     for (const ArchSpec &arch : GetSupportedArchitectures(process_host_arch)) {
96*f6aab3d8Srobert       resolved_module_spec.GetArchitecture() = arch;
97061da546Spatrick       error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
98061da546Spatrick                                           nullptr, nullptr, nullptr);
99061da546Spatrick       // Did we find an executable using one of the
100061da546Spatrick       if (error.Success()) {
101061da546Spatrick         if (exe_module_sp && exe_module_sp->GetObjectFile())
102061da546Spatrick           break;
103061da546Spatrick         else
104061da546Spatrick           error.SetErrorToGenericError();
105061da546Spatrick       }
106061da546Spatrick 
107*f6aab3d8Srobert       arch_names << LS << arch.GetArchitectureName();
108061da546Spatrick     }
109061da546Spatrick 
110061da546Spatrick     if (error.Fail() || !exe_module_sp) {
111061da546Spatrick       if (FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec())) {
112*f6aab3d8Srobert         error.SetErrorStringWithFormatv(
113*f6aab3d8Srobert             "'{0}' doesn't contain any '{1}' platform architectures: {2}",
114*f6aab3d8Srobert             resolved_module_spec.GetFileSpec(), GetPluginName(),
115*f6aab3d8Srobert             arch_names.GetData());
116061da546Spatrick       } else {
117061da546Spatrick         error.SetErrorStringWithFormat(
118061da546Spatrick             "'%s' is not readable",
119061da546Spatrick             resolved_module_spec.GetFileSpec().GetPath().c_str());
120061da546Spatrick       }
121061da546Spatrick     }
122061da546Spatrick   } else {
123061da546Spatrick     error.SetErrorStringWithFormat(
124061da546Spatrick         "'%s' does not exist",
125061da546Spatrick         resolved_module_spec.GetFileSpec().GetPath().c_str());
126061da546Spatrick   }
127061da546Spatrick 
128061da546Spatrick   return error;
129061da546Spatrick }
130061da546Spatrick 
GetFileInSDK(const char * platform_file_path,uint32_t sdk_idx,lldb_private::FileSpec & local_file)131061da546Spatrick bool PlatformRemoteDarwinDevice::GetFileInSDK(const char *platform_file_path,
132061da546Spatrick                                      uint32_t sdk_idx,
133061da546Spatrick                                      lldb_private::FileSpec &local_file) {
134*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Host);
135061da546Spatrick   if (sdk_idx < m_sdk_directory_infos.size()) {
136061da546Spatrick     std::string sdkroot_path =
137061da546Spatrick         m_sdk_directory_infos[sdk_idx].directory.GetPath();
138061da546Spatrick     local_file.Clear();
139061da546Spatrick 
140061da546Spatrick     if (!sdkroot_path.empty() && platform_file_path && platform_file_path[0]) {
141061da546Spatrick       // We may need to interpose "/Symbols/" or "/Symbols.Internal/" between
142061da546Spatrick       // the
143061da546Spatrick       // SDK root directory and the file path.
144061da546Spatrick 
145061da546Spatrick       const char *paths_to_try[] = {"Symbols", "", "Symbols.Internal", nullptr};
146061da546Spatrick       for (size_t i = 0; paths_to_try[i] != nullptr; i++) {
147061da546Spatrick         local_file.SetFile(sdkroot_path, FileSpec::Style::native);
148061da546Spatrick         if (paths_to_try[i][0] != '\0')
149061da546Spatrick           local_file.AppendPathComponent(paths_to_try[i]);
150061da546Spatrick         local_file.AppendPathComponent(platform_file_path);
151061da546Spatrick         FileSystem::Instance().Resolve(local_file);
152061da546Spatrick         if (FileSystem::Instance().Exists(local_file)) {
153061da546Spatrick           LLDB_LOGF(log, "Found a copy of %s in the SDK dir %s/%s",
154061da546Spatrick                     platform_file_path, sdkroot_path.c_str(), paths_to_try[i]);
155061da546Spatrick           return true;
156061da546Spatrick         }
157061da546Spatrick         local_file.Clear();
158061da546Spatrick       }
159061da546Spatrick     }
160061da546Spatrick   }
161061da546Spatrick   return false;
162061da546Spatrick }
163061da546Spatrick 
GetSymbolFile(const FileSpec & platform_file,const UUID * uuid_ptr,FileSpec & local_file)164061da546Spatrick Status PlatformRemoteDarwinDevice::GetSymbolFile(const FileSpec &platform_file,
165061da546Spatrick                                                  const UUID *uuid_ptr,
166061da546Spatrick                                                  FileSpec &local_file) {
167*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Host);
168061da546Spatrick   Status error;
169061da546Spatrick   char platform_file_path[PATH_MAX];
170061da546Spatrick   if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
171061da546Spatrick     const char *os_version_dir = GetDeviceSupportDirectoryForOSVersion();
172061da546Spatrick     if (os_version_dir) {
173061da546Spatrick       std::string resolved_path =
174061da546Spatrick           (llvm::Twine(os_version_dir) + "/" + platform_file_path).str();
175061da546Spatrick 
176061da546Spatrick       local_file.SetFile(resolved_path, FileSpec::Style::native);
177061da546Spatrick       FileSystem::Instance().Resolve(local_file);
178061da546Spatrick       if (FileSystem::Instance().Exists(local_file)) {
179061da546Spatrick         if (log) {
180061da546Spatrick           LLDB_LOGF(log, "Found a copy of %s in the DeviceSupport dir %s",
181061da546Spatrick                     platform_file_path, os_version_dir);
182061da546Spatrick         }
183061da546Spatrick         return error;
184061da546Spatrick       }
185061da546Spatrick 
186061da546Spatrick       resolved_path = (llvm::Twine(os_version_dir) + "/Symbols.Internal/" +
187061da546Spatrick                        platform_file_path)
188061da546Spatrick                           .str();
189061da546Spatrick 
190061da546Spatrick       local_file.SetFile(resolved_path, FileSpec::Style::native);
191061da546Spatrick       FileSystem::Instance().Resolve(local_file);
192061da546Spatrick       if (FileSystem::Instance().Exists(local_file)) {
193061da546Spatrick         LLDB_LOGF(
194061da546Spatrick             log,
195061da546Spatrick             "Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal",
196061da546Spatrick             platform_file_path, os_version_dir);
197061da546Spatrick         return error;
198061da546Spatrick       }
199061da546Spatrick       resolved_path =
200061da546Spatrick           (llvm::Twine(os_version_dir) + "/Symbols/" + platform_file_path)
201061da546Spatrick               .str();
202061da546Spatrick 
203061da546Spatrick       local_file.SetFile(resolved_path, FileSpec::Style::native);
204061da546Spatrick       FileSystem::Instance().Resolve(local_file);
205061da546Spatrick       if (FileSystem::Instance().Exists(local_file)) {
206061da546Spatrick         LLDB_LOGF(log, "Found a copy of %s in the DeviceSupport dir %s/Symbols",
207061da546Spatrick                   platform_file_path, os_version_dir);
208061da546Spatrick         return error;
209061da546Spatrick       }
210061da546Spatrick     }
211061da546Spatrick     local_file = platform_file;
212061da546Spatrick     if (FileSystem::Instance().Exists(local_file))
213061da546Spatrick       return error;
214061da546Spatrick 
215*f6aab3d8Srobert     error.SetErrorStringWithFormatv(
216*f6aab3d8Srobert         "unable to locate a platform file for '{0}' in platform '{1}'",
217*f6aab3d8Srobert         platform_file_path, GetPluginName());
218061da546Spatrick   } else {
219061da546Spatrick     error.SetErrorString("invalid platform file argument");
220061da546Spatrick   }
221061da546Spatrick   return error;
222061da546Spatrick }
223061da546Spatrick 
GetSharedModule(const ModuleSpec & module_spec,Process * process,ModuleSP & module_sp,const FileSpecList * module_search_paths_ptr,llvm::SmallVectorImpl<ModuleSP> * old_modules,bool * did_create_ptr)224061da546Spatrick Status PlatformRemoteDarwinDevice::GetSharedModule(
225061da546Spatrick     const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
226dda28197Spatrick     const FileSpecList *module_search_paths_ptr,
227dda28197Spatrick     llvm::SmallVectorImpl<ModuleSP> *old_modules, bool *did_create_ptr) {
228061da546Spatrick   // For iOS, the SDK files are all cached locally on the host system. So first
229061da546Spatrick   // we ask for the file in the cached SDK, then we attempt to get a shared
230061da546Spatrick   // module for the right architecture with the right UUID.
231061da546Spatrick   const FileSpec &platform_file = module_spec.GetFileSpec();
232*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Host);
233061da546Spatrick 
234061da546Spatrick   Status error;
235061da546Spatrick   char platform_file_path[PATH_MAX];
236061da546Spatrick 
237061da546Spatrick   if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
238061da546Spatrick     ModuleSpec platform_module_spec(module_spec);
239061da546Spatrick 
240061da546Spatrick     UpdateSDKDirectoryInfosIfNeeded();
241061da546Spatrick 
242061da546Spatrick     const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
243061da546Spatrick 
244061da546Spatrick     // If we are connected we migth be able to correctly deduce the SDK
245061da546Spatrick     // directory using the OS build.
246061da546Spatrick     const uint32_t connected_sdk_idx = GetConnectedSDKIndex();
247061da546Spatrick     if (connected_sdk_idx < num_sdk_infos) {
248061da546Spatrick       LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
249061da546Spatrick                 m_sdk_directory_infos[connected_sdk_idx].directory);
250061da546Spatrick       if (GetFileInSDK(platform_file_path, connected_sdk_idx,
251061da546Spatrick                        platform_module_spec.GetFileSpec())) {
252061da546Spatrick         module_sp.reset();
253061da546Spatrick         error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
254061da546Spatrick         if (module_sp) {
255061da546Spatrick           m_last_module_sdk_idx = connected_sdk_idx;
256061da546Spatrick           error.Clear();
257061da546Spatrick           return error;
258061da546Spatrick         }
259061da546Spatrick       }
260061da546Spatrick     }
261061da546Spatrick 
262061da546Spatrick     // Try the last SDK index if it is set as most files from an SDK will tend
263061da546Spatrick     // to be valid in that same SDK.
264061da546Spatrick     if (m_last_module_sdk_idx < num_sdk_infos) {
265061da546Spatrick       LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
266061da546Spatrick                 m_sdk_directory_infos[m_last_module_sdk_idx].directory);
267061da546Spatrick       if (GetFileInSDK(platform_file_path, m_last_module_sdk_idx,
268061da546Spatrick                        platform_module_spec.GetFileSpec())) {
269061da546Spatrick         module_sp.reset();
270061da546Spatrick         error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
271061da546Spatrick         if (module_sp) {
272061da546Spatrick           error.Clear();
273061da546Spatrick           return error;
274061da546Spatrick         }
275061da546Spatrick       }
276061da546Spatrick     }
277061da546Spatrick 
278061da546Spatrick     // First try for an exact match of major, minor and update: If a particalar
279061da546Spatrick     // SDK version was specified via --version or --build, look for a match on
280061da546Spatrick     // disk.
281061da546Spatrick     const SDKDirectoryInfo *current_sdk_info =
282061da546Spatrick         GetSDKDirectoryForCurrentOSVersion();
283061da546Spatrick     const uint32_t current_sdk_idx =
284061da546Spatrick         GetSDKIndexBySDKDirectoryInfo(current_sdk_info);
285061da546Spatrick     if (current_sdk_idx < num_sdk_infos &&
286061da546Spatrick         current_sdk_idx != m_last_module_sdk_idx) {
287061da546Spatrick       LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
288061da546Spatrick                 m_sdk_directory_infos[current_sdk_idx].directory);
289061da546Spatrick       if (GetFileInSDK(platform_file_path, current_sdk_idx,
290061da546Spatrick                        platform_module_spec.GetFileSpec())) {
291061da546Spatrick         module_sp.reset();
292061da546Spatrick         error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
293061da546Spatrick         if (module_sp) {
294061da546Spatrick           m_last_module_sdk_idx = current_sdk_idx;
295061da546Spatrick           error.Clear();
296061da546Spatrick           return error;
297061da546Spatrick         }
298061da546Spatrick       }
299061da546Spatrick     }
300061da546Spatrick 
301061da546Spatrick     // Second try all SDKs that were found.
302061da546Spatrick     for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) {
303061da546Spatrick       if (m_last_module_sdk_idx == sdk_idx) {
304061da546Spatrick         // Skip the last module SDK index if we already searched it above
305061da546Spatrick         continue;
306061da546Spatrick       }
307061da546Spatrick       LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
308061da546Spatrick                 m_sdk_directory_infos[sdk_idx].directory);
309061da546Spatrick       if (GetFileInSDK(platform_file_path, sdk_idx,
310061da546Spatrick                        platform_module_spec.GetFileSpec())) {
311061da546Spatrick         // printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());
312061da546Spatrick 
313061da546Spatrick         error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
314061da546Spatrick         if (module_sp) {
315061da546Spatrick           // Remember the index of the last SDK that we found a file in in case
316061da546Spatrick           // the wrong SDK was selected.
317061da546Spatrick           m_last_module_sdk_idx = sdk_idx;
318061da546Spatrick           error.Clear();
319061da546Spatrick           return error;
320061da546Spatrick         }
321061da546Spatrick       }
322061da546Spatrick     }
323061da546Spatrick   }
324061da546Spatrick   // Not the module we are looking for... Nothing to see here...
325061da546Spatrick   module_sp.reset();
326061da546Spatrick 
327061da546Spatrick   // This may not be an SDK-related module.  Try whether we can bring in the
328061da546Spatrick   // thing to our local cache.
329061da546Spatrick   error = GetSharedModuleWithLocalCache(module_spec, module_sp,
330dda28197Spatrick                                         module_search_paths_ptr, old_modules,
331dda28197Spatrick                                         did_create_ptr);
332061da546Spatrick   if (error.Success())
333061da546Spatrick     return error;
334061da546Spatrick 
335061da546Spatrick   // See if the file is present in any of the module_search_paths_ptr
336061da546Spatrick   // directories.
337061da546Spatrick   if (!module_sp)
338dda28197Spatrick     error = PlatformDarwin::FindBundleBinaryInExecSearchPaths(
339dda28197Spatrick         module_spec, process, module_sp, module_search_paths_ptr, old_modules,
340dda28197Spatrick         did_create_ptr);
341061da546Spatrick 
342061da546Spatrick   if (error.Success())
343061da546Spatrick     return error;
344061da546Spatrick 
345061da546Spatrick   const bool always_create = false;
346dda28197Spatrick   error = ModuleList::GetSharedModule(module_spec, module_sp,
347dda28197Spatrick                                       module_search_paths_ptr, old_modules,
348061da546Spatrick                                       did_create_ptr, always_create);
349061da546Spatrick 
350061da546Spatrick   if (module_sp)
351061da546Spatrick     module_sp->SetPlatformFileSpec(platform_file);
352061da546Spatrick 
353061da546Spatrick   return error;
354061da546Spatrick }
355061da546Spatrick 
GetConnectedSDKIndex()356061da546Spatrick uint32_t PlatformRemoteDarwinDevice::GetConnectedSDKIndex() {
357061da546Spatrick   if (IsConnected()) {
358061da546Spatrick     if (m_connected_module_sdk_idx == UINT32_MAX) {
359*f6aab3d8Srobert       if (std::optional<std::string> build = GetRemoteOSBuildString()) {
360061da546Spatrick         const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
361061da546Spatrick         for (uint32_t i = 0; i < num_sdk_infos; ++i) {
362061da546Spatrick           const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
363061da546Spatrick           if (strstr(sdk_dir_info.directory.GetFilename().AsCString(""),
364*f6aab3d8Srobert                      build->c_str())) {
365061da546Spatrick             m_connected_module_sdk_idx = i;
366061da546Spatrick           }
367061da546Spatrick         }
368061da546Spatrick       }
369061da546Spatrick     }
370061da546Spatrick   } else {
371061da546Spatrick     m_connected_module_sdk_idx = UINT32_MAX;
372061da546Spatrick   }
373061da546Spatrick   return m_connected_module_sdk_idx;
374061da546Spatrick }
375061da546Spatrick 
GetSDKIndexBySDKDirectoryInfo(const SDKDirectoryInfo * sdk_info)376061da546Spatrick uint32_t PlatformRemoteDarwinDevice::GetSDKIndexBySDKDirectoryInfo(
377061da546Spatrick     const SDKDirectoryInfo *sdk_info) {
378061da546Spatrick   if (sdk_info == nullptr) {
379061da546Spatrick     return UINT32_MAX;
380061da546Spatrick   }
381061da546Spatrick 
382061da546Spatrick   return sdk_info - &m_sdk_directory_infos[0];
383061da546Spatrick }
384