@@ -140,6 +140,9 @@ using namespace lldb;
140140using namespace lldb_private ;
141141using namespace llvm ::MachO;
142142
143+ static constexpr llvm::StringLiteral g_loader_path = " @loader_path" ;
144+ static constexpr llvm::StringLiteral g_executable_path = " @executable_path" ;
145+
143146LLDB_PLUGIN_DEFINE (ObjectFileMachO)
144147
145148static void PrintRegisterValue(RegisterContext *reg_ctx, const char *name,
@@ -5145,123 +5148,121 @@ UUID ObjectFileMachO::GetUUID() {
51455148}
51465149
51475150uint32_t ObjectFileMachO::GetDependentModules (FileSpecList &files) {
5151+ ModuleSP module_sp = GetModule ();
5152+ if (!module_sp)
5153+ return 0 ;
5154+
51485155 uint32_t count = 0 ;
5149- ModuleSP module_sp (GetModule ());
5150- if (module_sp) {
5151- std::lock_guard<std::recursive_mutex> guard (module_sp->GetMutex ());
5152- llvm::MachO::load_command load_cmd;
5153- lldb::offset_t offset = MachHeaderSizeFromMagic (m_header.magic );
5154- std::vector<std::string> rpath_paths;
5155- std::vector<std::string> rpath_relative_paths;
5156- std::vector<std::string> at_exec_relative_paths;
5157- uint32_t i;
5158- for (i = 0 ; i < m_header.ncmds ; ++i) {
5159- const uint32_t cmd_offset = offset;
5160- if (m_data.GetU32 (&offset, &load_cmd, 2 ) == nullptr )
5161- break ;
5156+ std::lock_guard<std::recursive_mutex> guard (module_sp->GetMutex ());
5157+ llvm::MachO::load_command load_cmd;
5158+ lldb::offset_t offset = MachHeaderSizeFromMagic (m_header.magic );
5159+ std::vector<std::string> rpath_paths;
5160+ std::vector<std::string> rpath_relative_paths;
5161+ std::vector<std::string> at_exec_relative_paths;
5162+ uint32_t i;
5163+ for (i = 0 ; i < m_header.ncmds ; ++i) {
5164+ const uint32_t cmd_offset = offset;
5165+ if (m_data.GetU32 (&offset, &load_cmd, 2 ) == nullptr )
5166+ break ;
51625167
5163- switch (load_cmd.cmd ) {
5164- case LC_RPATH:
5165- case LC_LOAD_DYLIB:
5166- case LC_LOAD_WEAK_DYLIB:
5167- case LC_REEXPORT_DYLIB:
5168- case LC_LOAD_DYLINKER:
5169- case LC_LOADFVMLIB:
5170- case LC_LOAD_UPWARD_DYLIB: {
5171- uint32_t name_offset = cmd_offset + m_data.GetU32 (&offset);
5172- // For LC_LOAD_DYLIB there is an alternate encoding
5173- // which adds a uint32_t `flags` field for `DYLD_USE_*`
5174- // flags. This can be detected by a timestamp field with
5175- // the `DYLIB_USE_MARKER` constant value.
5176- bool is_delayed_init = false ;
5177- uint32_t use_command_marker = m_data.GetU32 (&offset);
5178- if (use_command_marker == 0x1a741800 /* DYLIB_USE_MARKER */ ) {
5179- offset += 4 ; /* uint32_t current_version */
5180- offset += 4 ; /* uint32_t compat_version */
5181- uint32_t flags = m_data.GetU32 (&offset);
5182- // If this LC_LOAD_DYLIB is marked delay-init,
5183- // don't report it as a dependent library -- it
5184- // may be loaded in the process at some point,
5185- // but will most likely not be load at launch.
5186- if (flags & 0x08 /* DYLIB_USE_DELAYED_INIT */ )
5187- is_delayed_init = true ;
5188- }
5189- const char *path = m_data.PeekCStr (name_offset);
5190- if (path && !is_delayed_init) {
5191- if (load_cmd.cmd == LC_RPATH)
5192- rpath_paths.push_back (path);
5193- else {
5194- if (path[0 ] == ' @' ) {
5195- if (strncmp (path, " @rpath" , strlen (" @rpath" )) == 0 )
5196- rpath_relative_paths.push_back (path + strlen (" @rpath" ));
5197- else if (strncmp (path, " @executable_path" ,
5198- strlen (" @executable_path" )) == 0 )
5199- at_exec_relative_paths.push_back (path +
5200- strlen (" @executable_path" ));
5201- } else {
5202- FileSpec file_spec (path);
5203- if (files.AppendIfUnique (file_spec))
5204- count++;
5205- }
5168+ switch (load_cmd.cmd ) {
5169+ case LC_RPATH:
5170+ case LC_LOAD_DYLIB:
5171+ case LC_LOAD_WEAK_DYLIB:
5172+ case LC_REEXPORT_DYLIB:
5173+ case LC_LOAD_DYLINKER:
5174+ case LC_LOADFVMLIB:
5175+ case LC_LOAD_UPWARD_DYLIB: {
5176+ uint32_t name_offset = cmd_offset + m_data.GetU32 (&offset);
5177+ // For LC_LOAD_DYLIB there is an alternate encoding
5178+ // which adds a uint32_t `flags` field for `DYLD_USE_*`
5179+ // flags. This can be detected by a timestamp field with
5180+ // the `DYLIB_USE_MARKER` constant value.
5181+ bool is_delayed_init = false ;
5182+ uint32_t use_command_marker = m_data.GetU32 (&offset);
5183+ if (use_command_marker == 0x1a741800 /* DYLIB_USE_MARKER */ ) {
5184+ offset += 4 ; /* uint32_t current_version */
5185+ offset += 4 ; /* uint32_t compat_version */
5186+ uint32_t flags = m_data.GetU32 (&offset);
5187+ // If this LC_LOAD_DYLIB is marked delay-init,
5188+ // don't report it as a dependent library -- it
5189+ // may be loaded in the process at some point,
5190+ // but will most likely not be load at launch.
5191+ if (flags & 0x08 /* DYLIB_USE_DELAYED_INIT */ )
5192+ is_delayed_init = true ;
5193+ }
5194+ const char *path = m_data.PeekCStr (name_offset);
5195+ if (path && !is_delayed_init) {
5196+ if (load_cmd.cmd == LC_RPATH)
5197+ rpath_paths.push_back (path);
5198+ else {
5199+ if (path[0 ] == ' @' ) {
5200+ if (strncmp (path, " @rpath" , strlen (" @rpath" )) == 0 )
5201+ rpath_relative_paths.push_back (path + strlen (" @rpath" ));
5202+ else if (strncmp (path, " @executable_path" ,
5203+ strlen (" @executable_path" )) == 0 )
5204+ at_exec_relative_paths.push_back (path +
5205+ strlen (" @executable_path" ));
5206+ } else {
5207+ FileSpec file_spec (path);
5208+ if (files.AppendIfUnique (file_spec))
5209+ count++;
52065210 }
52075211 }
5208- } break ;
5209-
5210- default :
5211- break ;
52125212 }
5213- offset = cmd_offset + load_cmd.cmdsize ;
5214- }
5213+ } break ;
52155214
5216- FileSpec this_file_spec (m_file);
5217- FileSystem::Instance ().Resolve (this_file_spec);
5218-
5219- if (!rpath_paths.empty ()) {
5220- // Fixup all LC_RPATH values to be absolute paths
5221- std::string loader_path (" @loader_path" );
5222- std::string executable_path (" @executable_path" );
5223- for (auto &rpath : rpath_paths) {
5224- if (llvm::StringRef (rpath).starts_with (loader_path)) {
5225- rpath.erase (0 , loader_path.size ());
5226- rpath.insert (0 , this_file_spec.GetDirectory ().GetCString ());
5227- } else if (llvm::StringRef (rpath).starts_with (executable_path)) {
5228- rpath.erase (0 , executable_path.size ());
5229- rpath.insert (0 , this_file_spec.GetDirectory ().GetCString ());
5230- }
5231- }
5215+ default :
5216+ break ;
5217+ }
5218+ offset = cmd_offset + load_cmd.cmdsize ;
5219+ }
52325220
5233- for (const auto &rpath_relative_path : rpath_relative_paths) {
5234- for (const auto &rpath : rpath_paths) {
5235- std::string path = rpath;
5236- path += rpath_relative_path;
5237- // It is OK to resolve this path because we must find a file on disk
5238- // for us to accept it anyway if it is rpath relative.
5239- FileSpec file_spec (path);
5240- FileSystem::Instance ().Resolve (file_spec);
5241- if (FileSystem::Instance ().Exists (file_spec) &&
5242- files.AppendIfUnique (file_spec)) {
5243- count++;
5244- break ;
5245- }
5246- }
5247- }
5221+ FileSpec this_file_spec (m_file);
5222+ FileSystem::Instance ().Resolve (this_file_spec);
5223+
5224+ if (!rpath_paths.empty ()) {
5225+ // Fixup all LC_RPATH values to be absolute paths.
5226+ const std::string this_directory =
5227+ this_file_spec.GetDirectory ().GetString ();
5228+ for (auto &rpath : rpath_paths) {
5229+ if (llvm::StringRef (rpath).starts_with (g_loader_path))
5230+ rpath = this_directory + rpath.substr (g_loader_path.size ());
5231+ else if (llvm::StringRef (rpath).starts_with (g_executable_path))
5232+ rpath = this_directory + rpath.substr (g_executable_path.size ());
52485233 }
52495234
5250- // We may have @executable_paths but no RPATHS. Figure those out here.
5251- // Only do this if this object file is the executable. We have no way to
5252- // get back to the actual executable otherwise, so we won't get the right
5253- // path.
5254- if (!at_exec_relative_paths.empty () && CalculateType () == eTypeExecutable) {
5255- FileSpec exec_dir = this_file_spec.CopyByRemovingLastPathComponent ();
5256- for (const auto &at_exec_relative_path : at_exec_relative_paths) {
5257- FileSpec file_spec =
5258- exec_dir.CopyByAppendingPathComponent (at_exec_relative_path);
5235+ for (const auto &rpath_relative_path : rpath_relative_paths) {
5236+ for (const auto &rpath : rpath_paths) {
5237+ std::string path = rpath;
5238+ path += rpath_relative_path;
5239+ // It is OK to resolve this path because we must find a file on disk
5240+ // for us to accept it anyway if it is rpath relative.
5241+ FileSpec file_spec (path);
5242+ FileSystem::Instance ().Resolve (file_spec);
52595243 if (FileSystem::Instance ().Exists (file_spec) &&
5260- files.AppendIfUnique (file_spec))
5244+ files.AppendIfUnique (file_spec)) {
52615245 count++;
5246+ break ;
5247+ }
52625248 }
52635249 }
52645250 }
5251+
5252+ // We may have @executable_paths but no RPATHS. Figure those out here.
5253+ // Only do this if this object file is the executable. We have no way to
5254+ // get back to the actual executable otherwise, so we won't get the right
5255+ // path.
5256+ if (!at_exec_relative_paths.empty () && CalculateType () == eTypeExecutable) {
5257+ FileSpec exec_dir = this_file_spec.CopyByRemovingLastPathComponent ();
5258+ for (const auto &at_exec_relative_path : at_exec_relative_paths) {
5259+ FileSpec file_spec =
5260+ exec_dir.CopyByAppendingPathComponent (at_exec_relative_path);
5261+ if (FileSystem::Instance ().Exists (file_spec) &&
5262+ files.AppendIfUnique (file_spec))
5263+ count++;
5264+ }
5265+ }
52655266 return count;
52665267}
52675268
0 commit comments