Skip to content

Commit 551823b

Browse files
authored
Merge pull request #7982 from jimingham/executable-first-prev
Ensure that the executable module is ModuleList[0] (llvm#78360)
2 parents b659e9e + 5eed9b9 commit 551823b

File tree

5 files changed

+88
-1
lines changed

5 files changed

+88
-1
lines changed

lldb/source/Core/ModuleList.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,29 @@ ModuleList::~ModuleList() = default;
330330
void ModuleList::AppendImpl(const ModuleSP &module_sp, bool use_notifier) {
331331
if (module_sp) {
332332
std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
333-
m_modules.push_back(module_sp);
333+
// We are required to keep the first element of the Module List as the
334+
// executable module. So check here and if the first module is NOT an
335+
// but the new one is, we insert this module at the beginning, rather than
336+
// at the end.
337+
// We don't need to do any of this if the list is empty:
338+
if (m_modules.empty()) {
339+
m_modules.push_back(module_sp);
340+
} else {
341+
// Since producing the ObjectFile may take some work, first check the 0th
342+
// element, and only if that's NOT an executable look at the incoming
343+
// ObjectFile. That way in the normal case we only look at the element
344+
// 0 ObjectFile.
345+
const bool elem_zero_is_executable
346+
= m_modules[0]->GetObjectFile()->GetType()
347+
== ObjectFile::Type::eTypeExecutable;
348+
lldb_private::ObjectFile *obj = module_sp->GetObjectFile();
349+
if (!elem_zero_is_executable && obj
350+
&& obj->GetType() == ObjectFile::Type::eTypeExecutable) {
351+
m_modules.insert(m_modules.begin(), module_sp);
352+
} else {
353+
m_modules.push_back(module_sp);
354+
}
355+
}
334356
if (use_notifier && m_notifier)
335357
m_notifier->NotifyModuleAdded(*this, module_sp);
336358
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
CXX_SOURCES := main.cpp
2+
DYLIB_CXX_SOURCES := b.cpp
3+
DYLIB_NAME := bar
4+
include Makefile.rules
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# This test checks that we make the executable the first
2+
# element in the image list.
3+
4+
import lldb
5+
from lldbsuite.test.decorators import *
6+
from lldbsuite.test.lldbtest import *
7+
from lldbsuite.test import lldbutil
8+
9+
10+
class TestExecutableIsFirst(TestBase):
11+
NO_DEBUG_INFO_TESTCASE = True
12+
13+
# ELF does not have a hard distinction between shared libraries and
14+
# (position-independent) executables
15+
@skipIf(oslist=no_match(lldbplatformutil.getDarwinOSTriples()+["windows"]))
16+
def test_executable_is_first_before_run(self):
17+
self.build()
18+
19+
ctx = self.platformContext
20+
lib_name = ctx.shlib_prefix + "bar." + ctx.shlib_extension
21+
22+
exe = self.getBuildArtifact("a.out")
23+
lib = self.getBuildArtifact(lib_name)
24+
25+
target = self.dbg.CreateTarget(None)
26+
module = target.AddModule(lib, None, None)
27+
self.assertTrue(module.IsValid(), "Added the module for the library")
28+
29+
module = target.AddModule(exe, None, None)
30+
self.assertTrue(module.IsValid(), "Added the executable module")
31+
32+
# This is the executable module so it should be the first in the list:
33+
first_module = target.GetModuleAtIndex(0)
34+
print("This is the first test, this one succeeds")
35+
self.assertEqual(module, first_module, "This executable is the first module")
36+
37+
# The executable property is an SBFileSpec to the executable. Make sure
38+
# that is also right:
39+
executable_module = target.executable
40+
self.assertEqual(
41+
first_module.file, executable_module, "Python property is also our module"
42+
)
43+
44+
def test_executable_is_first_during_run(self):
45+
self.build()
46+
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
47+
self, "break after function call", lldb.SBFileSpec("main.cpp"),
48+
extra_images=["bar"]
49+
)
50+
51+
first_module = target.GetModuleAtIndex(0)
52+
self.assertTrue(first_module.IsValid(), "We have at least one module")
53+
executable_module = target.executable
54+
self.assertEqual(first_module.file, executable_module, "They are the same")
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
int LLDB_DYLIB_EXPORT b_function() { return 500; }
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
extern int b_function();
2+
3+
int main(int argc, char* argv[]) {
4+
int ret_value = b_function();
5+
return ret_value; // break after function call
6+
}

0 commit comments

Comments
 (0)