179 lines · cpp
1//===-- ModuleListTest.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/Core/ModuleList.h"10#include "TestingSupport/SubsystemRAII.h"11#include "TestingSupport/TestUtilities.h"12#include "lldb/Core/Module.h"13#include "lldb/Core/ModuleSpec.h"14#include "lldb/Host/FileSystem.h"15#include "lldb/Utility/ArchSpec.h"16#include "lldb/Utility/UUID.h"17 18#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"19 20#include "gtest/gtest.h"21 22using namespace lldb;23using namespace lldb_private;24 25// Test that when we already have a module in the shared_module_list with a26// specific UUID, the next call to GetSharedModule with a module_spec with the27// same UUID should return the existing module instead of creating a new one.28TEST(ModuleListTest, GetSharedModuleReusesExistingModuleWithSameUUID) {29 SubsystemRAII<FileSystem, ObjectFileELF> subsystems;30 31 auto ExpectedFile = TestFile::fromYaml(R"(32--- !ELF33FileHeader:34 Class: ELFCLASS6435 Data: ELFDATA2LSB36 Type: ET_DYN37 Machine: EM_X86_6438Sections:39 - Name: .text40 Type: SHT_PROGBITS41 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]42 AddressAlign: 0x000000000000001043...44)");45 ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());46 47 // First, let's verify that calling GetSharedModule twice with the same48 // module_spec returns the same module pointer49 50 ModuleSP first_module;51 bool first_did_create = false;52 Status error_first =53 ModuleList::GetSharedModule(ExpectedFile->moduleSpec(), first_module,54 nullptr, &first_did_create, false);55 56 // Second call with the same spec57 ModuleSP second_module;58 bool second_did_create = false;59 Status error_second =60 ModuleList::GetSharedModule(ExpectedFile->moduleSpec(), second_module,61 nullptr, &second_did_create, false);62 63 if (error_first.Success() && error_second.Success()) {64 // If both succeeded, verify they're the same module65 EXPECT_EQ(first_module.get(), second_module.get())66 << "GetSharedModule should return the same module for the same spec";67 EXPECT_TRUE(first_did_create) << "First call should create the module";68 EXPECT_FALSE(second_did_create)69 << "Second call should reuse the existing module";70 }71}72 73// Test that UUID-based lookup finds existing modules74TEST(ModuleListTest, FindSharedModuleByUUID) {75 SubsystemRAII<FileSystem, ObjectFileELF> subsystems;76 77 auto ExpectedFile = TestFile::fromYaml(R"(78--- !ELF79FileHeader:80 Class: ELFCLASS6481 Data: ELFDATA2LSB82 Type: ET_DYN83 Machine: EM_X86_6484Sections:85 - Name: .text86 Type: SHT_PROGBITS87 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]88 AddressAlign: 0x000000000000001089...90)");91 ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());92 93 // Create and add a module to the shared module list using the moduleSpec()94 ModuleSP created_module;95 bool did_create = false;96 Status error = ModuleList::GetSharedModule(97 ExpectedFile->moduleSpec(), created_module, nullptr, &did_create, false);98 99 if (error.Success() && created_module) {100 // Get the UUID of the created module101 UUID module_uuid = created_module->GetUUID();102 103 if (module_uuid.IsValid()) {104 // Now try to find the module by UUID105 ModuleSP found_module = ModuleList::FindSharedModule(module_uuid);106 107 ASSERT_NE(found_module.get(), nullptr)108 << "FindSharedModule should find the module by UUID";109 EXPECT_EQ(found_module.get(), created_module.get())110 << "FindSharedModule should return the same module instance";111 EXPECT_EQ(found_module->GetUUID(), module_uuid)112 << "Found module should have the same UUID";113 }114 }115}116 117// Test that GetSharedModule with UUID finds existing module even with different118// path119TEST(ModuleListTest, GetSharedModuleByUUIDIgnoresPath) {120 SubsystemRAII<FileSystem, ObjectFileELF> subsystems;121 122 auto ExpectedFile = TestFile::fromYaml(R"(123--- !ELF124FileHeader:125 Class: ELFCLASS64126 Data: ELFDATA2LSB127 Type: ET_DYN128 Machine: EM_X86_64129Sections:130 - Name: .text131 Type: SHT_PROGBITS132 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]133 AddressAlign: 0x0000000000000010134...135)");136 ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());137 138 // Create and add a module to the shared module list139 ModuleSP first_module;140 bool first_did_create = false;141 Status first_error =142 ModuleList::GetSharedModule(ExpectedFile->moduleSpec(), first_module,143 nullptr, &first_did_create, false);144 145 if (first_error.Success() && first_module) {146 UUID module_uuid = first_module->GetUUID();147 148 if (module_uuid.IsValid()) {149 // Now try to get a module with the same UUID but different path150 ModuleSpec second_spec;151 second_spec.GetFileSpec() = FileSpec("/different/path/to/module.so");152 second_spec.GetArchitecture() = ArchSpec("x86_64-pc-linux");153 second_spec.GetUUID() = module_uuid;154 155 ModuleSP second_module;156 bool second_did_create = false;157 Status second_error = ModuleList::GetSharedModule(158 second_spec, second_module, nullptr, &second_did_create, false);159 160 if (second_error.Success() && second_module) {161 // If we got a module back, check if it's the same one162 bool is_same_module = (second_module.get() == first_module.get());163 164 // Document the behavior: ideally UUID should take precedence165 // and return the existing module166 EXPECT_TRUE(is_same_module)167 << "GetSharedModule with matching UUID should return existing "168 "module, "169 << "even with different path (per PR #160199)";170 171 if (is_same_module) {172 EXPECT_FALSE(second_did_create)173 << "Should not create a new module when UUID matches";174 }175 }176 }177 }178}179