chromium/tools/mac/dsc_extractor.cc

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Tool dsc_extract is used to dump the contents of a macOS dyld shared cache.
// It is recommended to only use this on the version of macOS with the matching
// shared cache macOS version because the format of the cache can change
// between macOS versions.

#include <dlfcn.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

using ExtractDylibsProgressT = int (*)(const char* shared_cache_file_path,
                                       const char* extraction_root_path,
                                       void (^progress)(unsigned current,
                                                        unsigned total));

int main(int argc, const char* argv[]) {
  if (argc != 3) {
    fprintf(stderr,
            "usage: dsc_extract <path-to-cache-file> <path-to-device-dir>\n");
    return EXIT_FAILURE;
  }

  void* handle = dlopen("/usr/lib/dsc_extractor.bundle", RTLD_LAZY);
  if (handle == nullptr) {
    fprintf(stderr, "dsc_extractor.bundle could not be loaded\n");
    return EXIT_FAILURE;
  }

  auto* extract = reinterpret_cast<ExtractDylibsProgressT>(
      dlsym(handle, "dyld_shared_cache_extract_dylibs_progress"));
  if (extract == nullptr) {
    fprintf(stderr,
            "dsc_extractor.bundle did not have "
            "dyld_shared_cache_extract_dylibs_progress symbol\n");
    return EXIT_FAILURE;
  }

  int result = (*extract)(argv[1], argv[2], ^(unsigned c, unsigned total) {
    fprintf(stdout, "%d/%d\n", c, total);
  });
  fprintf(stderr, "dyld_shared_cache_extract_dylibs_progress() => %d\n",
          result);
  return EXIT_SUCCESS;
}