Skip to content

Commit 57cbd26

Browse files
committed
Flag for LoadBinaryWithUUIDAndAddress, to create memory image or not
DynamicLoader::LoadBinaryWithUUIDAndAddress can create a Module based on the binary image in memory, which in some cases contains symbol names and can be genuinely useful. If we don't have a filename, it creates a name in the form `memory-image-0x...` with the header address. In practice, this is most useful with Darwin userland corefiles where the binary was stored in the corefile in whole, and we can't find a binary with the matching UUID. Using the binary out of the corefile memory in this case works well. But in other cases, akin to firmware debugging, we merely end up with an oddly named binary image and no symbols. Add a flag to control whether we will create these memory images and add them to the Target or not; only set it to true when working with a userland Mach-O image with the "all image infos" LC_NOTE for a userland corefile. Differential Revision: https://reviews.llvm.org/D157167
1 parent 3e66a17 commit 57cbd26

File tree

7 files changed

+80
-54
lines changed

7 files changed

+80
-54
lines changed

lldb/include/lldb/Target/DynamicLoader.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -264,13 +264,18 @@ class DynamicLoader : public PluginInterface {
264264
/// load address for the binary or its segments in the Target if it passes
265265
/// true.
266266
///
267+
/// \param[in] allow_memory_image_last_resort
268+
/// If no better binary image can be found, allow reading the binary
269+
/// out of memory, if possible, and create the Module based on that.
270+
/// May be slow to read a binary out of memory, and for unusual
271+
/// environments, may be no symbols mapped in memory at all.
272+
///
267273
/// \return
268274
/// Returns a shared pointer for the Module that has been added.
269-
static lldb::ModuleSP
270-
LoadBinaryWithUUIDAndAddress(Process *process, llvm::StringRef name,
271-
UUID uuid, lldb::addr_t value,
272-
bool value_is_offset, bool force_symbol_search,
273-
bool notify, bool set_address_in_target);
275+
static lldb::ModuleSP LoadBinaryWithUUIDAndAddress(
276+
Process *process, llvm::StringRef name, UUID uuid, lldb::addr_t value,
277+
bool value_is_offset, bool force_symbol_search, bool notify,
278+
bool set_address_in_target, bool allow_memory_image_last_resort);
274279

275280
/// Get information about the shared cache for a process, if possible.
276281
///

lldb/source/Core/DynamicLoader.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ static ModuleSP ReadUnnamedMemoryModule(Process *process, addr_t addr,
188188
ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress(
189189
Process *process, llvm::StringRef name, UUID uuid, addr_t value,
190190
bool value_is_offset, bool force_symbol_search, bool notify,
191-
bool set_address_in_target) {
191+
bool set_address_in_target, bool allow_memory_image_last_resort) {
192192
ModuleSP memory_module_sp;
193193
ModuleSP module_sp;
194194
PlatformSP platform_sp = process->GetTarget().GetPlatform();
@@ -245,7 +245,8 @@ ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress(
245245

246246
// If we couldn't find the binary anywhere else, as a last resort,
247247
// read it out of memory.
248-
if (!module_sp.get() && value != LLDB_INVALID_ADDRESS && !value_is_offset) {
248+
if (allow_memory_image_last_resort && !module_sp.get() &&
249+
value != LLDB_INVALID_ADDRESS && !value_is_offset) {
249250
if (!memory_module_sp)
250251
memory_module_sp = ReadUnnamedMemoryModule(process, value, name);
251252
if (memory_module_sp)

lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6938,9 +6938,15 @@ bool ObjectFileMachO::LoadCoreFileImages(lldb_private::Process &process) {
69386938
if (image.uuid.IsValid() ||
69396939
(!value_is_offset && value != LLDB_INVALID_ADDRESS)) {
69406940
const bool set_load_address = image.segment_load_addresses.size() == 0;
6941+
const bool notify = false;
6942+
// Userland Darwin binaries will have segment load addresses via
6943+
// the `all image infos` LC_NOTE.
6944+
const bool allow_memory_image_last_resort =
6945+
image.segment_load_addresses.size();
69416946
module_sp = DynamicLoader::LoadBinaryWithUUIDAndAddress(
69426947
&process, image.filename, image.uuid, value, value_is_offset,
6943-
image.currently_executing, false /* notify */, set_load_address);
6948+
image.currently_executing, notify, set_load_address,
6949+
allow_memory_image_last_resort);
69446950
}
69456951

69466952
// We have a ModuleSP to load in the Target. Load it at the

lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,10 +1001,11 @@ void ProcessGDBRemote::LoadStubBinaries() {
10011001
const bool force_symbol_search = true;
10021002
const bool notify = true;
10031003
const bool set_address_in_target = true;
1004+
const bool allow_memory_image_last_resort = false;
10041005
DynamicLoader::LoadBinaryWithUUIDAndAddress(
10051006
this, "", standalone_uuid, standalone_value,
10061007
standalone_value_is_offset, force_symbol_search, notify,
1007-
set_address_in_target);
1008+
set_address_in_target, allow_memory_image_last_resort);
10081009
}
10091010
}
10101011

@@ -1033,10 +1034,12 @@ void ProcessGDBRemote::LoadStubBinaries() {
10331034

10341035
const bool force_symbol_search = true;
10351036
const bool set_address_in_target = true;
1037+
const bool allow_memory_image_last_resort = false;
10361038
// Second manually load this binary into the Target.
10371039
DynamicLoader::LoadBinaryWithUUIDAndAddress(
10381040
this, llvm::StringRef(), uuid, addr, value_is_slide,
1039-
force_symbol_search, notify, set_address_in_target);
1041+
force_symbol_search, notify, set_address_in_target,
1042+
allow_memory_image_last_resort);
10401043
}
10411044
}
10421045
}

lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,12 @@ void ProcessMachCore::LoadBinariesViaMetadata() {
259259
const bool force_symbol_search = true;
260260
const bool notify = true;
261261
const bool set_address_in_target = true;
262+
const bool allow_memory_image_last_resort = false;
262263
if (DynamicLoader::LoadBinaryWithUUIDAndAddress(
263264
this, llvm::StringRef(), objfile_binary_uuid,
264265
objfile_binary_value, objfile_binary_value_is_offset,
265-
force_symbol_search, notify, set_address_in_target)) {
266+
force_symbol_search, notify, set_address_in_target,
267+
allow_memory_image_last_resort)) {
266268
found_main_binary_definitively = true;
267269
m_dyld_plugin_name = DynamicLoaderStatic::GetPluginNameStatic();
268270
}
@@ -315,10 +317,11 @@ void ProcessMachCore::LoadBinariesViaMetadata() {
315317
const bool force_symbol_search = true;
316318
const bool notify = true;
317319
const bool set_address_in_target = true;
320+
const bool allow_memory_image_last_resort = false;
318321
if (DynamicLoader::LoadBinaryWithUUIDAndAddress(
319322
this, llvm::StringRef(), ident_uuid, ident_binary_addr,
320323
value_is_offset, force_symbol_search, notify,
321-
set_address_in_target)) {
324+
set_address_in_target, allow_memory_image_last_resort)) {
322325
found_main_binary_definitively = true;
323326
m_dyld_plugin_name = DynamicLoaderStatic::GetPluginNameStatic();
324327
}

lldb/test/API/macosx/lc-note/multiple-binary-corefile/TestMultipleBinaryCorefile.py

Lines changed: 49 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Test corefiles with "main bin spec"/"load binary" with only addrs work."""
1+
"""Test corefiles with "main bin spec"/"load binary" with only vmaddrs works."""
22

33

44
import os
@@ -35,41 +35,28 @@ def initial_setup(self):
3535
self.libtwo_exe,
3636
self.libtwo_slide,
3737
)
38+
if self.TraceOn():
39+
print("Creating corefile with command %s")
3840
call(cmd, shell=True)
3941

4042
def load_corefile_and_test(self):
4143
target = self.dbg.CreateTarget("")
4244
err = lldb.SBError()
4345
if self.TraceOn():
44-
self.runCmd("script print('loading corefile %s')" % self.corefile)
46+
print("loading corefile %s" % self.corefile)
4547
process = target.LoadCore(self.corefile)
4648
self.assertEqual(process.IsValid(), True)
4749
if self.TraceOn():
48-
self.runCmd("script print('image list after loading corefile:')")
50+
print("image list after loading corefile:")
4951
self.runCmd("image list")
5052

51-
self.assertEqual(target.GetNumModules(), 3)
53+
## We don't have libone.dylib in the global module cache or from
54+
## dsymForUUID, and lldb will not read the binary out of memory.
55+
self.assertEqual(target.GetNumModules(), 2)
5256
fspec = target.GetModuleAtIndex(0).GetFileSpec()
5357
self.assertEqual(fspec.GetFilename(), self.aout_exe_basename)
5458

55-
# libone.dylib was never loaded into lldb, see that we added a memory module.
5659
fspec = target.GetModuleAtIndex(1).GetFileSpec()
57-
self.assertIn("memory-image", fspec.GetFilename())
58-
59-
dwarfdump_uuid_regex = re.compile("UUID: ([-0-9a-fA-F]+) \(([^\(]+)\) .*")
60-
dwarfdump_cmd_output = subprocess.check_output(
61-
('/usr/bin/dwarfdump --uuid "%s"' % self.libone_exe), shell=True
62-
).decode("utf-8")
63-
libone_uuid = None
64-
for line in dwarfdump_cmd_output.splitlines():
65-
match = dwarfdump_uuid_regex.search(line)
66-
if match:
67-
libone_uuid = match.group(1)
68-
69-
memory_image_uuid = target.GetModuleAtIndex(1).GetUUIDString()
70-
self.assertEqual(libone_uuid, memory_image_uuid)
71-
72-
fspec = target.GetModuleAtIndex(2).GetFileSpec()
7360
self.assertEqual(fspec.GetFilename(), self.libtwo_exe_basename)
7461

7562
# Executables "always" have this base address
@@ -80,17 +67,9 @@ def load_corefile_and_test(self):
8067
)
8168
self.assertEqual(aout_load, 0x100000000 + self.aout_slide)
8269

83-
# Value from Makefile
84-
libone_load = (
85-
target.GetModuleAtIndex(1)
86-
.GetObjectFileHeaderAddress()
87-
.GetLoadAddress(target)
88-
)
89-
self.assertEqual(libone_load, self.libone_slide)
90-
9170
# Value from Makefile
9271
libtwo_load = (
93-
target.GetModuleAtIndex(2)
72+
target.GetModuleAtIndex(1)
9473
.GetObjectFileHeaderAddress()
9574
.GetLoadAddress(target)
9675
)
@@ -140,6 +119,15 @@ def test_corefile_binaries_dsymforuuid(self):
140119
self.assertNotEqual(
141120
libtwo_uuid, None, "Could not get uuid of built libtwo.dylib"
142121
)
122+
dwarfdump_cmd_output = subprocess.check_output(
123+
('/usr/bin/dwarfdump --uuid "%s"' % self.aout_exe), shell=True
124+
).decode("utf-8")
125+
aout_uuid = None
126+
for line in dwarfdump_cmd_output.splitlines():
127+
match = dwarfdump_uuid_regex.search(line)
128+
if match:
129+
aout_uuid = match.group(1)
130+
self.assertNotEqual(aout_uuid, None, "Could not get uuid of built a.out")
143131

144132
### Create our dsym-for-uuid shell script which returns aout_exe
145133
shell_cmds = [
@@ -149,27 +137,47 @@ def test_corefile_binaries_dsymforuuid(self):
149137
"do",
150138
" shift",
151139
"done",
152-
"ret=0",
153140
'echo "<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?>"',
154141
'echo "<!DOCTYPE plist PUBLIC \\"-//Apple//DTD PLIST 1.0//EN\\" \\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\\">"',
155142
'echo "<plist version=\\"1.0\\">"',
143+
'echo " <dict>"',
144+
'echo " <key>$1</key>"',
145+
'echo " <dict>"',
156146
"",
157-
'if [ "$1" != "%s" ]' % (libtwo_uuid),
147+
'if [ "$1" != "%s" -a "$1" != "%s" ]' % (libtwo_uuid, aout_uuid),
158148
"then",
159-
' echo "<key>DBGError</key><string>not found</string>"',
149+
' echo " <key>DBGError</key>"',
150+
' echo " <string>not found by $0</string>"',
151+
' echo " </dict>"',
152+
' echo " </dict>"',
160153
' echo "</plist>"',
161-
" exit 1",
154+
" exit 0",
162155
"fi",
156+
# UUID matches libtwo.dylib
157+
'if [ "$1" = "%s" ]' % (libtwo_uuid),
158+
"then",
163159
" uuid=%s" % libtwo_uuid,
164160
" bin=%s" % self.libtwo_exe,
165161
" dsym=%s.dSYM/Contents/Resources/DWARF/%s"
166162
% (self.libtwo_exe, os.path.basename(self.libtwo_exe)),
167-
'echo "<dict><key>$uuid</key><dict>"',
163+
"fi",
164+
# UUID matches a.out
165+
'if [ "$1" = "%s" ]' % (aout_uuid),
166+
"then",
167+
" uuid=%s" % aout_uuid,
168+
" bin=%s" % self.aout_exe,
169+
" dsym=%s.dSYM/Contents/Resources/DWARF/%s"
170+
% (self.aout_exe, os.path.basename(self.aout_exe)),
171+
"fi",
168172
"",
169-
'echo "<key>DBGDSYMPath</key><string>$dsym</string>"',
170-
'echo "<key>DBGSymbolRichExecutable</key><string>$bin</string>"',
171-
'echo "</dict></dict></plist>"',
172-
"exit $ret",
173+
'echo " <key>DBGDSYMPath</key>"',
174+
'echo " <string>$dsym</string>"',
175+
'echo " <key>DBGSymbolRichExecutable</key>"',
176+
'echo " <string>$bin</string>"',
177+
'echo " </dict>"',
178+
'echo " </dict>"',
179+
'echo "</plist>"',
180+
"exit 0",
173181
]
174182

175183
with open(dsym_for_uuid, "w") as writer:
@@ -183,7 +191,7 @@ def test_corefile_binaries_dsymforuuid(self):
183191
self.dbg.DeleteTarget(target)
184192

185193
if self.TraceOn():
186-
self.runCmd("script print('Global image list, before loading corefile:')")
194+
print("Global image list, before loading corefile:")
187195
self.runCmd("image list -g")
188196

189197
self.load_corefile_and_test()
@@ -206,7 +214,7 @@ def test_corefile_binaries_preloaded(self):
206214
self.dbg.DeleteTarget(target)
207215

208216
if self.TraceOn():
209-
self.runCmd("script print('Global image list, before loading corefile:')")
217+
print("Global image list, before loading corefile:")
210218
self.runCmd("image list -g")
211219

212220
self.load_corefile_and_test()

lldb/test/API/macosx/lc-note/multiple-binary-corefile/create-multibin-corefile.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include <vector>
1717

1818
// Given a list of binaries, and optional slides to be applied,
19-
// create a corefile whose memory is those binaries laid at at
19+
// create a corefile whose memory is those binaries laid down at
2020
// their slid addresses.
2121
//
2222
// Add a 'main bin spec' LC_NOTE for the first binary, and

0 commit comments

Comments
 (0)