Skip to content

Commit 23f3e51

Browse files
authored
Merge pull request #8242 from jimingham/old-sim-for-stable
Cherry-pick the workaround for using older dyld_sim's on newer dyld's
2 parents 3f5ee9c + 6c6589b commit 23f3e51

File tree

6 files changed

+93
-1
lines changed

6 files changed

+93
-1
lines changed

lldb/source/Core/ModuleList.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,29 @@ ModuleList::~ModuleList() = default;
333333
void ModuleList::AppendImpl(const ModuleSP &module_sp, bool use_notifier) {
334334
if (module_sp) {
335335
std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
336-
m_modules.push_back(module_sp);
336+
// We are required to keep the first element of the Module List as the
337+
// executable module. So check here and if the first module is NOT an
338+
// but the new one is, we insert this module at the beginning, rather than
339+
// at the end.
340+
// We don't need to do any of this if the list is empty:
341+
if (m_modules.empty()) {
342+
m_modules.push_back(module_sp);
343+
} else {
344+
// Since producing the ObjectFile may take some work, first check the 0th
345+
// element, and only if that's NOT an executable look at the incoming
346+
// ObjectFile. That way in the normal case we only look at the element
347+
// 0 ObjectFile.
348+
const bool elem_zero_is_executable
349+
= m_modules[0]->GetObjectFile()->GetType()
350+
== ObjectFile::Type::eTypeExecutable;
351+
lldb_private::ObjectFile *obj = module_sp->GetObjectFile();
352+
if (!elem_zero_is_executable && obj
353+
&& obj->GetType() == ObjectFile::Type::eTypeExecutable) {
354+
m_modules.insert(m_modules.begin(), module_sp);
355+
} else {
356+
m_modules.push_back(module_sp);
357+
}
358+
}
337359
if (use_notifier && m_notifier)
338360
m_notifier->NotifyModuleAdded(*this, module_sp);
339361
}
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: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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+
def test_executable_is_first_before_run(self):
14+
self.build()
15+
16+
ctx = self.platformContext
17+
lib_name = ctx.shlib_prefix + "bar." + ctx.shlib_extension
18+
19+
exe = self.getBuildArtifact("a.out")
20+
lib = self.getBuildArtifact(lib_name)
21+
22+
target = self.dbg.CreateTarget(None)
23+
module = target.AddModule(lib, None, None)
24+
self.assertTrue(module.IsValid(), "Added the module for the library")
25+
26+
module = target.AddModule(exe, None, None)
27+
self.assertTrue(module.IsValid(), "Added the executable module")
28+
29+
# This is the executable module so it should be the first in the list:
30+
first_module = target.GetModuleAtIndex(0)
31+
print("This is the first test, this one succeeds")
32+
self.assertEqual(module, first_module, "This executable is the first module")
33+
34+
# The executable property is an SBFileSpec to the executable. Make sure
35+
# that is also right:
36+
executable_module = target.executable
37+
self.assertEqual(
38+
first_module.file, executable_module, "Python property is also our module"
39+
)
40+
41+
def test_executable_is_first_during_run(self):
42+
self.build()
43+
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
44+
self, "break after function call", lldb.SBFileSpec("main.cpp"),
45+
extra_images=["bar"]
46+
)
47+
48+
first_module = target.GetModuleAtIndex(0)
49+
self.assertTrue(first_module.IsValid(), "We have at least one module")
50+
executable_module = target.executable
51+
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+
}

lldb/tools/debugserver/source/MacOSX/MachProcess.mm

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <algorithm>
3434
#include <chrono>
3535
#include <map>
36+
#include <unordered_set>
3637

3738
#include <TargetConditionals.h>
3839
#import <Foundation/Foundation.h>
@@ -1065,9 +1066,16 @@ static bool mach_header_validity_test(uint32_t magic, uint32_t cputype) {
10651066
dyld_process_info info =
10661067
m_dyld_process_info_create(m_task.TaskPort(), 0, &kern_ret);
10671068
if (info) {
1069+
// There's a bug in the interaction between dyld and older dyld_sim's
1070+
// (e.g. from the iOS 15 simulator) that causes dyld to report the same
1071+
// binary twice. We use this set to eliminate the duplicates.
1072+
__block std::unordered_set<uint64_t> seen_header_addrs;
10681073
m_dyld_process_info_for_each_image(
10691074
info,
10701075
^(uint64_t mach_header_addr, const uuid_t uuid, const char *path) {
1076+
auto res_pair = seen_header_addrs.insert(mach_header_addr);
1077+
if (!res_pair.second)
1078+
return;
10711079
struct binary_image_information image;
10721080
image.filename = path;
10731081
uuid_copy(image.macho_info.uuid, uuid);

0 commit comments

Comments
 (0)