Exemple #1
0
static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec,
                                              FileSpec &dsym_fspec) {
  Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
  const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
  if (exec_fspec) {
    char path[PATH_MAX];
    if (exec_fspec->GetPath(path, sizeof(path))) {
      // Make sure the module isn't already just a dSYM file...
      if (strcasestr(path, ".dSYM/Contents/Resources/DWARF") == NULL) {
        if (log) {
          if (module_spec.GetUUIDPtr() && module_spec.GetUUIDPtr()->IsValid()) {
            log->Printf(
                "Searching for dSYM bundle next to executable %s, UUID %s",
                path, module_spec.GetUUIDPtr()->GetAsString().c_str());
          } else {
            log->Printf("Searching for dSYM bundle next to executable %s",
                        path);
          }
        }
        ::strncat(path, ".dSYM/Contents/Resources/DWARF/",
                  sizeof(path) - strlen(path) - 1);
        ::strncat(path, exec_fspec->GetFilename().AsCString(),
                  sizeof(path) - strlen(path) - 1);

        dsym_fspec.SetFile(path, false);

        ModuleSpecList module_specs;
        ModuleSpec matched_module_spec;
        if (dsym_fspec.Exists() &&
            FileAtPathContainsArchAndUUID(dsym_fspec,
                                          module_spec.GetArchitecturePtr(),
                                          module_spec.GetUUIDPtr())) {
          if (log) {
            log->Printf("dSYM with matching UUID & arch found at %s", path);
          }
          return true;
        } else {
          FileSpec parent_dirs = exec_fspec;

          // Remove the binary name from the FileSpec
          parent_dirs.RemoveLastPathComponent();

          // Add a ".dSYM" name to each directory component of the path,
          // stripping off components.  e.g. we may have a binary like
          // /S/L/F/Foundation.framework/Versions/A/Foundation
          // and
          // /S/L/F/Foundation.framework.dSYM
          //
          // so we'll need to start with /S/L/F/Foundation.framework/Versions/A,
          // add the .dSYM part to the "A", and if that doesn't exist, strip off
          // the "A" and try it again with "Versions", etc., until we find a
          // dSYM bundle or we've stripped off enough path components that
          // there's no need to continue.

          for (int i = 0; i < 4; i++) {
            // Does this part of the path have a "." character - could it be a
            // bundle's top level directory?
            const char *fn = parent_dirs.GetFilename().AsCString();
            if (fn == nullptr)
              break;
            if (::strchr(fn, '.') != nullptr) {
              dsym_fspec = parent_dirs;
              dsym_fspec.RemoveLastPathComponent();

              // If the current directory name is "Foundation.framework", see if
              // "Foundation.framework.dSYM/Contents/Resources/DWARF/Foundation"
              // exists & has the right uuid.
              std::string dsym_fn = fn;
              dsym_fn += ".dSYM";
              dsym_fspec.AppendPathComponent(dsym_fn.c_str());
              dsym_fspec.AppendPathComponent("Contents");
              dsym_fspec.AppendPathComponent("Resources");
              dsym_fspec.AppendPathComponent("DWARF");
              dsym_fspec.AppendPathComponent(
                  exec_fspec->GetFilename().AsCString());
              if (dsym_fspec.Exists() &&
                  FileAtPathContainsArchAndUUID(
                      dsym_fspec, module_spec.GetArchitecturePtr(),
                      module_spec.GetUUIDPtr())) {
                if (log) {
                  log->Printf("dSYM with matching UUID & arch found at %s",
                              dsym_fspec.GetPath().c_str());
                }
                return true;
              }
            }
            parent_dirs.RemoveLastPathComponent();
          }
        }
      }
    }
  }
  dsym_fspec.Clear();
  return false;
}