Summary: On macOS 11, the libraries that have been integrated in the system shared cache are not present on the filesystem anymore. LLDB was using those files to get access to the symbols of those libraries. LLDB can get the images from the target process memory though. This has 2 consequences: - LLDB cannot load the images before the process starts, reporting an error if someone tries to break on a system symbol. - Loading the symbols by downloading the data from the inferior is super slow. It takes tens of seconds at the start of the debug session to populate the Module list. To fix this, we can use the library images LLDB has in its own mapping of the shared cache. Shared cache images are somewhat special as their LINKEDIT segment is moved to the end of the cache and thus the images are not contiguous in memory. All of this can hidden in ObjectFileMachO. This patch fixes a number of test failures on macOS 11 due to the first problem described above and adds some specific unittesting for the new SharedCache Host utilities. Reviewers: jasonmolenda, labath Subscribers: llvm-commits, lldb-commits Tags: #lldb, #llvm Differential Revision: https://reviews.llvm.org/D83023
80 lines
2.7 KiB
C++
80 lines
2.7 KiB
C++
//===-- ObjectFileMachOTest.cpp -------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "lldb/Host/HostInfo.h"
|
|
#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
|
|
#include "TestingSupport/SubsystemRAII.h"
|
|
#include "TestingSupport/TestUtilities.h"
|
|
#include "lldb/Core/Module.h"
|
|
#include "lldb/Host/FileSystem.h"
|
|
#include "lldb/lldb-defines.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
#ifdef __APPLE__
|
|
#include <dlfcn.h>
|
|
#endif
|
|
|
|
using namespace lldb_private;
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
class ObjectFileMachOTest : public ::testing::Test {
|
|
SubsystemRAII<FileSystem, HostInfo, ObjectFileMachO> subsystems;
|
|
};
|
|
} // namespace
|
|
|
|
#if defined(__APPLE__)
|
|
TEST_F(ObjectFileMachOTest, ModuleFromSharedCacheInfo) {
|
|
SharedCacheImageInfo image_info =
|
|
HostInfo::GetSharedCacheImageInfo("/usr/lib/libobjc.A.dylib");
|
|
EXPECT_TRUE(image_info.uuid);
|
|
EXPECT_TRUE(image_info.data_sp);
|
|
|
|
ModuleSpec spec(FileSpec(), UUID(), image_info.data_sp);
|
|
lldb::ModuleSP module = std::make_shared<Module>(spec);
|
|
ObjectFile *OF = module->GetObjectFile();
|
|
ASSERT_TRUE(llvm::isa<ObjectFileMachO>(OF));
|
|
EXPECT_TRUE(
|
|
OF->GetArchitecture().IsCompatibleMatch(HostInfo::GetArchitecture()));
|
|
Symtab *symtab = OF->GetSymtab();
|
|
ASSERT_NE(symtab, nullptr);
|
|
void *libobjc = dlopen("/usr/lib/libobjc.A.dylib", RTLD_LAZY);
|
|
ASSERT_NE(libobjc, nullptr);
|
|
|
|
// This function checks that if we read something from the
|
|
// ObjectFile we get through the shared cache in-mmeory
|
|
// buffer, it matches what we get by reading directly the
|
|
// memory of the symbol.
|
|
auto check_symbol = [&](const char *sym_name) {
|
|
std::vector<uint32_t> symbol_indices;
|
|
symtab->FindAllSymbolsWithNameAndType(ConstString(sym_name),
|
|
lldb::eSymbolTypeAny, symbol_indices);
|
|
EXPECT_EQ(symbol_indices.size(), 1u);
|
|
|
|
Symbol *sym = symtab->SymbolAtIndex(symbol_indices[0]);
|
|
ASSERT_NE(sym, nullptr);
|
|
Address base = sym->GetAddress();
|
|
size_t size = sym->GetByteSize();
|
|
ASSERT_NE(size, 0u);
|
|
uint8_t buffer[size];
|
|
EXPECT_EQ(OF->ReadSectionData(base.GetSection().get(), base.GetOffset(),
|
|
buffer, size),
|
|
size);
|
|
|
|
void *sym_addr = dlsym(libobjc, sym_name);
|
|
ASSERT_NE(sym_addr, nullptr);
|
|
EXPECT_EQ(memcmp(buffer, sym_addr, size), 0);
|
|
};
|
|
|
|
// Read a symbol from the __TEXT segment...
|
|
check_symbol("objc_msgSend");
|
|
// ... and one from the __DATA segment
|
|
check_symbol("OBJC_CLASS_$_NSObject");
|
|
}
|
|
#endif
|