Files
llvm-project/lldb/unittests/Core/ModuleListTest.cpp
Michael Buch f74c2668cc [lldb][Module][NFC] Remove unused always_create parameter to GetSharedModule (#176325)
No caller sets this to `true`. Initially added for and set by
`SymbolFileDWARFDebugMap` (see
`616f490777a4f35269a23abee851680134050065`). This was then removed
shortly after in:
```
commit 762f7135e2
Author: Greg Clayton <gclayton@apple.com>
Date:   Sun Sep 18 18:59:15 2011 +0000

    Don't put modules for .o files into the global shared module list. We
    used to do this because we needed to find the shared pointer for a .o
    file when the .o file's module was needed in a SymbolContext since the
    module in a symbol context was a shared pointer. Now that we are using
    intrusive pointers we don't have this limitation anymore since any
    instrusive shared pointer can be made from a pointer to an object
    all on its own.
```

At this point it's more of a foot-gun, because forcing it to true has
potentially significant performance implications (e.g.,
a5eaa05dce)
2026-01-19 10:57:52 +00:00

176 lines
6.0 KiB
C++

//===-- ModuleListTest.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/Core/ModuleList.h"
#include "TestingSupport/SubsystemRAII.h"
#include "TestingSupport/TestUtilities.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/UUID.h"
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
#include "gtest/gtest.h"
using namespace lldb;
using namespace lldb_private;
// Test that when we already have a module in the shared_module_list with a
// specific UUID, the next call to GetSharedModule with a module_spec with the
// same UUID should return the existing module instead of creating a new one.
TEST(ModuleListTest, GetSharedModuleReusesExistingModuleWithSameUUID) {
SubsystemRAII<FileSystem, ObjectFileELF> subsystems;
auto ExpectedFile = TestFile::fromYaml(R"(
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
AddressAlign: 0x0000000000000010
...
)");
ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());
// First, let's verify that calling GetSharedModule twice with the same
// module_spec returns the same module pointer
ModuleSP first_module;
bool first_did_create = false;
Status error_first = ModuleList::GetSharedModule(
ExpectedFile->moduleSpec(), first_module, nullptr, &first_did_create);
// Second call with the same spec
ModuleSP second_module;
bool second_did_create = false;
Status error_second = ModuleList::GetSharedModule(
ExpectedFile->moduleSpec(), second_module, nullptr, &second_did_create);
if (error_first.Success() && error_second.Success()) {
// If both succeeded, verify they're the same module
EXPECT_EQ(first_module.get(), second_module.get())
<< "GetSharedModule should return the same module for the same spec";
EXPECT_TRUE(first_did_create) << "First call should create the module";
EXPECT_FALSE(second_did_create)
<< "Second call should reuse the existing module";
}
}
// Test that UUID-based lookup finds existing modules
TEST(ModuleListTest, FindSharedModuleByUUID) {
SubsystemRAII<FileSystem, ObjectFileELF> subsystems;
auto ExpectedFile = TestFile::fromYaml(R"(
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
AddressAlign: 0x0000000000000010
...
)");
ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());
// Create and add a module to the shared module list using the moduleSpec()
ModuleSP created_module;
bool did_create = false;
Status error = ModuleList::GetSharedModule(
ExpectedFile->moduleSpec(), created_module, nullptr, &did_create);
if (error.Success() && created_module) {
// Get the UUID of the created module
UUID module_uuid = created_module->GetUUID();
if (module_uuid.IsValid()) {
// Now try to find the module by UUID
ModuleSP found_module = ModuleList::FindSharedModule(module_uuid);
ASSERT_NE(found_module.get(), nullptr)
<< "FindSharedModule should find the module by UUID";
EXPECT_EQ(found_module.get(), created_module.get())
<< "FindSharedModule should return the same module instance";
EXPECT_EQ(found_module->GetUUID(), module_uuid)
<< "Found module should have the same UUID";
}
}
}
// Test that GetSharedModule with UUID finds existing module even with different
// path
TEST(ModuleListTest, GetSharedModuleByUUIDIgnoresPath) {
SubsystemRAII<FileSystem, ObjectFileELF> subsystems;
auto ExpectedFile = TestFile::fromYaml(R"(
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_DYN
Machine: EM_X86_64
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
AddressAlign: 0x0000000000000010
...
)");
ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());
// Create and add a module to the shared module list
ModuleSP first_module;
bool first_did_create = false;
Status first_error = ModuleList::GetSharedModule(
ExpectedFile->moduleSpec(), first_module, nullptr, &first_did_create);
if (first_error.Success() && first_module) {
UUID module_uuid = first_module->GetUUID();
if (module_uuid.IsValid()) {
// Now try to get a module with the same UUID but different path
ModuleSpec second_spec;
second_spec.GetFileSpec() = FileSpec("/different/path/to/module.so");
second_spec.GetArchitecture() = ArchSpec("x86_64-pc-linux");
second_spec.GetUUID() = module_uuid;
ModuleSP second_module;
bool second_did_create = false;
Status second_error = ModuleList::GetSharedModule(
second_spec, second_module, nullptr, &second_did_create);
if (second_error.Success() && second_module) {
// If we got a module back, check if it's the same one
bool is_same_module = (second_module.get() == first_module.get());
// Document the behavior: ideally UUID should take precedence
// and return the existing module
EXPECT_TRUE(is_same_module)
<< "GetSharedModule with matching UUID should return existing "
"module, "
<< "even with different path (per PR #160199)";
if (is_same_module) {
EXPECT_FALSE(second_did_create)
<< "Should not create a new module when UUID matches";
}
}
}
}
}