98 lines · cpp
1//===-- ObjectFileMachOTest.cpp -------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Host/HostInfo.h"10#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"11#include "TestingSupport/SubsystemRAII.h"12#include "TestingSupport/TestUtilities.h"13#include "lldb/Core/Module.h"14#include "lldb/Host/FileSystem.h"15#include "lldb/lldb-defines.h"16#include "gtest/gtest.h"17 18#ifdef __APPLE__19#include <dlfcn.h>20#endif21 22using namespace lldb_private;23using namespace llvm;24 25namespace {26class ObjectFileMachOTest : public ::testing::Test {27 SubsystemRAII<FileSystem, HostInfo, ObjectFileMachO> subsystems;28};29} // namespace30 31#if defined(__APPLE__)32TEST_F(ObjectFileMachOTest, ModuleFromSharedCacheInfo) {33 SharedCacheImageInfo image_info =34 HostInfo::GetSharedCacheImageInfo("/usr/lib/libobjc.A.dylib");35 EXPECT_TRUE(image_info.uuid);36 EXPECT_TRUE(image_info.data_sp);37 38 ModuleSpec spec(FileSpec(), UUID(), image_info.data_sp);39 lldb::ModuleSP module = std::make_shared<Module>(spec);40 ObjectFile *OF = module->GetObjectFile();41 ASSERT_TRUE(llvm::isa<ObjectFileMachO>(OF));42 EXPECT_TRUE(43 OF->GetArchitecture().IsCompatibleMatch(HostInfo::GetArchitecture()));44 Symtab *symtab = OF->GetSymtab();45 ASSERT_NE(symtab, nullptr);46 void *libobjc = dlopen("/usr/lib/libobjc.A.dylib", RTLD_LAZY);47 ASSERT_NE(libobjc, nullptr);48 49 // This function checks that if we read something from the50 // ObjectFile we get through the shared cache in-mmeory51 // buffer, it matches what we get by reading directly the52 // memory of the symbol.53 auto check_symbol = [&](const char *sym_name) {54 std::vector<uint32_t> symbol_indices;55 symtab->FindAllSymbolsWithNameAndType(ConstString(sym_name),56 lldb::eSymbolTypeAny, symbol_indices);57 EXPECT_EQ(symbol_indices.size(), 1u);58 59 Symbol *sym = symtab->SymbolAtIndex(symbol_indices[0]);60 ASSERT_NE(sym, nullptr);61 Address base = sym->GetAddress();62 size_t size = sym->GetByteSize();63 ASSERT_NE(size, 0u);64 uint8_t buffer[size];65 EXPECT_EQ(OF->ReadSectionData(base.GetSection().get(), base.GetOffset(),66 buffer, size),67 size);68 69 void *sym_addr = dlsym(libobjc, sym_name);70 ASSERT_NE(sym_addr, nullptr);71 EXPECT_EQ(memcmp(buffer, sym_addr, size), 0);72 };73 74 // Read a symbol from the __TEXT segment...75 check_symbol("objc_msgSend");76 // ... and one from the __DATA segment77 check_symbol("OBJC_CLASS_$_NSObject");78}79 80TEST_F(ObjectFileMachOTest, IndirectSymbolsInTheSharedCache) {81 SharedCacheImageInfo image_info = HostInfo::GetSharedCacheImageInfo(82 "/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit");83 ModuleSpec spec(FileSpec(), UUID(), image_info.data_sp);84 lldb::ModuleSP module = std::make_shared<Module>(spec);85 86 ObjectFile *OF = module->GetObjectFile();87 ASSERT_TRUE(llvm::isa<ObjectFileMachO>(OF));88 EXPECT_TRUE(89 OF->GetArchitecture().IsCompatibleMatch(HostInfo::GetArchitecture()));90 91 // Check that we can parse the symbol table several times over without92 // crashing.93 Symtab symtab(OF);94 for (size_t i = 0; i < 10; i++)95 OF->ParseSymtab(symtab);96}97#endif98