================
@@ -649,30 +653,228 @@ static bool ResolveAndVerifyCandidateSupportDir(FileSpec
&path) {
dyld_shared_cache_dylib_text_info;
}
-extern "C" int dyld_shared_cache_iterate_text(
+// All available on at least macOS 12
+extern "C" {
+int dyld_shared_cache_iterate_text(
const uuid_t cacheUuid,
void (^callback)(const dyld_shared_cache_dylib_text_info *info));
-extern "C" uint8_t *_dyld_get_shared_cache_range(size_t *length);
-extern "C" bool _dyld_get_shared_cache_uuid(uuid_t uuid);
+uint8_t *_dyld_get_shared_cache_range(size_t *length);
+bool _dyld_get_shared_cache_uuid(uuid_t uuid);
+bool dyld_image_for_each_segment_info(void *image,
+ void (^)(const char *segmentName,
+ uint64_t vmAddr, uint64_t
vmSize,
+ int perm));
+const char *dyld_shared_cache_file_path(void);
+bool dyld_shared_cache_for_file(const char *filePath,
+ void (^block)(void *cache));
+void dyld_shared_cache_copy_uuid(void *cache, uuid_t *uuid);
+uint64_t dyld_shared_cache_get_base_address(void *cache);
+void dyld_shared_cache_for_each_image(void *cache, void (^block)(void *image));
+bool dyld_image_copy_uuid(void *cache, uuid_t *uuid);
+const char *dyld_image_get_installname(void *image);
+const char *dyld_image_get_file_path(void *image);
+}
namespace {
class SharedCacheInfo {
public:
- const UUID &GetUUID() const { return m_uuid; }
- const llvm::StringMap<SharedCacheImageInfo> &GetImages() const {
- return m_images;
+ llvm::StringMap<SharedCacheImageInfo> &GetImages() {
+ return m_caches[m_host_uuid];
}
SharedCacheInfo();
private:
bool CreateSharedCacheInfoWithInstrospectionSPIs();
+ void CreateSharedCacheInfoLLDBsVirtualMemory();
+ bool CreateHostSharedCacheImageList();
+
+ // Given the UUID and filepath to a shared cache on the local debug host
+ // system, open it and add all of the binary images to m_caches.
+ bool CreateSharedCacheImageList(UUID uuid, std::string filepath);
- llvm::StringMap<SharedCacheImageInfo> m_images;
- UUID m_uuid;
+ std::map<UUID, llvm::StringMap<SharedCacheImageInfo>> m_caches;
+ UUID m_host_uuid;
+
+ // macOS 26.4 and newer
+ void (*m_dyld_image_retain_4HWTrace)(void *image);
+ void (*m_dyld_image_release_4HWTrace)(void *image);
+ dispatch_data_t (*m_dyld_image_segment_data_4HWTrace)(
+ void *image, const char *segmentName);
};
+
+} // namespace
+
+SharedCacheInfo::SharedCacheInfo() {
+ // macOS 26.4 and newer
+ m_dyld_image_retain_4HWTrace =
+ (void (*)(void *))dlsym(RTLD_DEFAULT, "dyld_image_retain_4HWTrace");
+ m_dyld_image_release_4HWTrace =
+ (void (*)(void *))dlsym(RTLD_DEFAULT, "dyld_image_release_4HWTrace");
+ m_dyld_image_segment_data_4HWTrace =
+ (dispatch_data_t(*)(void *image, const char *segmentName))dlsym(
+ RTLD_DEFAULT, "dyld_image_segment_data_4HWTrace");
+
+ uuid_t dsc_uuid;
+ _dyld_get_shared_cache_uuid(dsc_uuid);
+ m_host_uuid = UUID(dsc_uuid);
+
+ if (ModuleList::GetGlobalModuleListProperties()
+ .GetSharedCacheSegmentLoads() &&
+ CreateHostSharedCacheImageList())
+ return;
+
+ if (CreateSharedCacheInfoWithInstrospectionSPIs())
+ return;
+
+ CreateSharedCacheInfoLLDBsVirtualMemory();
}
+struct segment {
+ std::string name;
+ uint64_t vmaddr;
+ size_t vmsize;
+
+ // Mapped into lldb's own address space via libdispatch:
+ const void *data;
+ size_t size;
+};
+
+static DataExtractorSP map_shared_cache_binary_segments(void *image) {
+ // dyld_image_segment_data_4HWTrace can't be called on
+ // multiple threads simultaneously.
+ static std::mutex g_mutex;
+ std::lock_guard<std::mutex> guard(g_mutex);
+
+ static dispatch_data_t (*g_dyld_image_segment_data_4HWTrace)(
+ void *image, const char *segmentName);
+ static std::once_flag g_once_flag;
+ std::call_once(g_once_flag, [&]() {
+ g_dyld_image_segment_data_4HWTrace =
+ (dispatch_data_t(*)(void *, const char *))dlsym(
+ RTLD_DEFAULT, "dyld_image_segment_data_4HWTrace");
+ });
+ if (!g_dyld_image_segment_data_4HWTrace)
+ return {};
+
+ __block std::vector<segment> segments;
+ __block void *image_copy = image;
+ dyld_image_for_each_segment_info(
+ image,
+ ^(const char *segmentName, uint64_t vmAddr, uint64_t vmSize, int perm) {
+ segment seg;
+ seg.name = segmentName;
+ seg.vmaddr = vmAddr;
+ seg.vmsize = vmSize;
+
+ dispatch_data_t data_from_libdyld =
+ g_dyld_image_segment_data_4HWTrace(image_copy, segmentName);
+ (void)dispatch_data_create_map(data_from_libdyld, &seg.data,
&seg.size);
+
+ segments.push_back(seg);
+ });
+
+ if (!segments.size())
+ return {};
+
+ Log *log = GetLog(LLDBLog::Modules);
+ for (segment seg : segments) {
+ if (log && log->GetVerbose())
+ LLDB_LOGF(
+ log,
+ "image %p %s vmaddr 0x%llx vmsize 0x%zx mapped to lldb vm addr %p",
+ image, seg.name.c_str(), seg.vmaddr, seg.vmsize, seg.data);
+ }
+
+ // Calculate the virtual address range in lldb's
+ // address space (lowest memory address to highest) so
+ // we can contain the entire range in an unowned data buffer.
+ uint64_t min_lldb_vm_addr = UINT64_MAX;
+ uint64_t max_lldb_vm_addr = 0;
+ // Calculate the minimum shared cache address seen; we want the first
+ // segment, __TEXT, at "vm offset" 0 in our DataExtractor.
+ // A __DATA segment which is at the __TEXT vm addr + 0x1000 needs to be
+ // listed as offset 0x1000.
+ uint64_t min_file_vm_addr = UINT64_MAX;
+ for (segment seg : segments) {
+ min_lldb_vm_addr = std::min(min_lldb_vm_addr, (uint64_t)seg.data);
+ max_lldb_vm_addr =
+ std::max(max_lldb_vm_addr, (uint64_t)seg.data + seg.vmsize);
+ min_file_vm_addr = std::min(min_file_vm_addr, (uint64_t)seg.vmaddr);
+ }
+ DataBufferSP data_sp = std::make_shared<DataBufferUnowned>(
+ (uint8_t *)min_lldb_vm_addr, max_lldb_vm_addr - min_lldb_vm_addr);
+ VirtualDataExtractor::LookupTable remap_table;
+ for (segment seg : segments)
+ remap_table.Append(VirtualDataExtractor::LookupTable::Entry(
+ (uint64_t)seg.vmaddr - min_file_vm_addr, (uint64_t)seg.vmsize,
+ (uint64_t)seg.data - (uint64_t)min_lldb_vm_addr));
+
+ return std::make_shared<VirtualDataExtractor>(data_sp, remap_table);
+}
+
+// Scan the binaries in the specified shared cache filepath
+// if the UUID matches, using the macOS 26.4 libdyld SPI,
+// create a new entry in m_caches.
+bool SharedCacheInfo::CreateSharedCacheImageList(UUID uuid,
+ std::string filepath) {
+ if (!m_dyld_image_retain_4HWTrace || !m_dyld_image_release_4HWTrace ||
+ !m_dyld_image_segment_data_4HWTrace)
+ return false;
+
+ __block bool return_failed = false;
+ dyld_shared_cache_for_file(filepath.c_str(), ^(void *cache) {
+ uuid_t sc_uuid;
+ dyld_shared_cache_copy_uuid(cache, &sc_uuid);
+ UUID this_cache(sc_uuid, sizeof(uuid_t));
+ if (this_cache != uuid) {
+ return_failed = true;
+ return;
+ }
+
+ dyld_shared_cache_for_each_image(cache, ^(void *image) {
+ uuid_t uuid_tmp;
+ if (!dyld_image_copy_uuid(image, &uuid_tmp))
+ return;
+ UUID image_uuid(uuid_tmp, sizeof(uuid_t));
+
+ Log *log = GetLog(LLDBLog::Modules);
+ if (log && log->GetVerbose())
+ LLDB_LOGF(log, "sc file %s image %p",
dyld_image_get_installname(image),
+ image);
+
+ m_dyld_image_retain_4HWTrace(image);
+ m_caches[m_host_uuid][dyld_image_get_installname(image)] =
+ SharedCacheImageInfo(image_uuid, map_shared_cache_binary_segments,
+ image);
+ });
+ });
+ if (return_failed)
+ return false;
+
+ return true;
+}
+
+// Get the filename and uuid of lldb's own shared cache, scan
+// the files in it using the macOS 26.4 and newer libdyld SPI.
+bool SharedCacheInfo::CreateHostSharedCacheImageList() {
+ std::string host_shared_cache_file = dyld_shared_cache_file_path();
+ __block UUID host_sc_uuid;
+ dyld_shared_cache_for_file(host_shared_cache_file.c_str(), ^(void *cache) {
+ uuid_t sc_uuid;
+ dyld_shared_cache_copy_uuid(cache, &sc_uuid);
+ host_sc_uuid = UUID{sc_uuid, sizeof(uuid_t)};
----------------
JDevlieghere wrote:
```suggestion
host_sc_uuid = UUID(sc_uuid, sizeof(uuid_t));
```
https://github.com/llvm/llvm-project/pull/179881
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits