Skip to content

Commit 96d1218

Browse files
committed
Allow firmware binaries to be specified only by load address
Add support to Mach-O corefiles and to live gdb remote serial protocol connections for the corefile/remote stub to provide a list of load addresses of binaries that should be found & loaded by lldb, and nothing else. lldb will try to parse the binary out of memory, and if it can find a UUID, try to find a binary & its debug information based on the UUID, falling back to using the memory image if it must. A bit of code unification from three parts of lldb that were loading individual binaries already, so there is a shared method in DynamicLoader to handle all of the variations they were doing. Re-landing this with a uuid_is_null() implementation added to Utility/UuidCompatibility.h for non-Darwin systems. Differential Revision: https://reviews.llvm.org/D130813 rdar://94249937 rdar://94249384
1 parent 560efad commit 96d1218

File tree

15 files changed

+952
-208
lines changed

15 files changed

+952
-208
lines changed

lldb/docs/lldb-gdb-remote.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,12 @@ main-binary-uuid: is the UUID of a firmware type binary that the gdb stub knows
10731073
main-binary-address: is the load address of the firmware type binary
10741074
main-binary-slide: is the slide of the firmware type binary, if address isn't known
10751075

1076+
binary-addresses: A comma-separated list of binary load addresses base16.
1077+
lldb will parse the binaries in memory to get UUIDs, then
1078+
try to find the binaries & debug info by UUID. Intended for
1079+
use with a small number of firmware type binaries where the
1080+
search for binary/debug info may be expensive.
1081+
10761082
//----------------------------------------------------------------------
10771083
// "qShlibInfoAddr"
10781084
//

lldb/include/lldb/Target/DynamicLoader.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,52 @@ class DynamicLoader : public PluginInterface {
210210
lldb::addr_t base_addr,
211211
bool base_addr_is_offset);
212212

213+
/// Find/load a binary into lldb given a UUID and the address where it is
214+
/// loaded in memory, or a slide to be applied to the file address.
215+
/// May force an expensive search on the computer to find the binary by
216+
/// UUID, should not be used for a large number of binaries - intended for
217+
/// an environment where there may be one, or a few, binaries resident in
218+
/// memory.
219+
///
220+
/// Given a UUID, search for a binary and load it at the address provided,
221+
/// or with the slide applied, or at the file address unslid.
222+
///
223+
/// Given an address, try to read the binary out of memory, get the UUID,
224+
/// find the file if possible and load it unslid, or add the memory module.
225+
///
226+
/// \param[in] process
227+
/// The process to add this binary to.
228+
///
229+
/// \param[in] uuid
230+
/// UUID of the binary to be loaded. UUID may be empty, and if a
231+
/// load address is supplied, will read the binary from memory, get
232+
/// a UUID and try to find a local binary. There is a performance
233+
/// cost to doing this, it is not preferable.
234+
///
235+
/// \param[in] value
236+
/// Address where the binary should be loaded, or read out of memory.
237+
/// Or a slide value, to be applied to the file addresses of the binary.
238+
///
239+
/// \param[in] value_is_offset
240+
/// A flag indicating that \p value is an address, or an offset to
241+
/// be applied to the file addresses.
242+
///
243+
/// \param[in] force_symbol_search
244+
/// Allow the search to do a possibly expensive external search for
245+
/// the ObjectFile and/or SymbolFile.
246+
///
247+
/// \param[in] notify
248+
/// Whether ModulesDidLoad should be called when a binary has been added
249+
/// to the Target. The caller may prefer to batch up these when loading
250+
/// multiple binaries.
251+
///
252+
/// \return
253+
/// Returns a shared pointer for the Module that has been added.
254+
static lldb::ModuleSP
255+
LoadBinaryWithUUIDAndAddress(Process *process, UUID uuid, lldb::addr_t value,
256+
bool value_is_offset, bool force_symbol_search,
257+
bool notify);
258+
213259
/// Get information about the shared cache for a process, if possible.
214260
///
215261
/// On some systems (e.g. Darwin based systems), a set of libraries that are

lldb/source/Core/DynamicLoader.cpp

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,15 @@
1313
#include "lldb/Core/ModuleSpec.h"
1414
#include "lldb/Core/PluginManager.h"
1515
#include "lldb/Core/Section.h"
16+
#include "lldb/Symbol/LocateSymbolFile.h"
1617
#include "lldb/Symbol/ObjectFile.h"
1718
#include "lldb/Target/MemoryRegionInfo.h"
19+
#include "lldb/Target/Platform.h"
1820
#include "lldb/Target/Process.h"
1921
#include "lldb/Target/Target.h"
2022
#include "lldb/Utility/ConstString.h"
23+
#include "lldb/Utility/LLDBLog.h"
24+
#include "lldb/Utility/Log.h"
2125
#include "lldb/lldb-private-interfaces.h"
2226

2327
#include "llvm/ADT/StringRef.h"
@@ -171,6 +175,100 @@ ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file,
171175
return nullptr;
172176
}
173177

178+
static ModuleSP ReadUnnamedMemoryModule(Process *process, addr_t addr) {
179+
char namebuf[80];
180+
snprintf(namebuf, sizeof(namebuf), "memory-image-0x%" PRIx64, addr);
181+
return process->ReadModuleFromMemory(FileSpec(namebuf), addr);
182+
}
183+
184+
ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress(Process *process,
185+
UUID uuid, addr_t value,
186+
bool value_is_offset,
187+
bool force_symbol_search,
188+
bool notify) {
189+
ModuleSP memory_module_sp;
190+
ModuleSP module_sp;
191+
PlatformSP platform_sp = process->GetTarget().GetPlatform();
192+
Target &target = process->GetTarget();
193+
Status error;
194+
ModuleSpec module_spec;
195+
module_spec.GetUUID() = uuid;
196+
197+
if (!uuid.IsValid() && !value_is_offset) {
198+
memory_module_sp = ReadUnnamedMemoryModule(process, value);
199+
200+
if (memory_module_sp)
201+
uuid = memory_module_sp->GetUUID();
202+
}
203+
204+
if (uuid.IsValid()) {
205+
ModuleSpec module_spec;
206+
module_spec.GetUUID() = uuid;
207+
208+
if (!module_sp)
209+
module_sp = target.GetOrCreateModule(module_spec, false, &error);
210+
211+
// If we haven't found a binary, or we don't have a SymbolFile, see
212+
// if there is an external search tool that can find it.
213+
if (force_symbol_search &&
214+
(!module_sp || !module_sp->GetSymbolFileFileSpec())) {
215+
Symbols::DownloadObjectAndSymbolFile(module_spec, error, true);
216+
if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
217+
module_sp = std::make_shared<Module>(module_spec);
218+
}
219+
}
220+
}
221+
222+
// If we couldn't find the binary anywhere else, as a last resort,
223+
// read it out of memory.
224+
if (!module_sp.get() && value != LLDB_INVALID_ADDRESS && !value_is_offset) {
225+
if (!memory_module_sp)
226+
memory_module_sp = ReadUnnamedMemoryModule(process, value);
227+
if (memory_module_sp)
228+
module_sp = memory_module_sp;
229+
}
230+
231+
Log *log = GetLog(LLDBLog::DynamicLoader);
232+
if (module_sp.get()) {
233+
target.GetImages().AppendIfNeeded(module_sp, false);
234+
235+
bool changed = false;
236+
if (module_sp->GetObjectFile()) {
237+
if (value != LLDB_INVALID_ADDRESS) {
238+
LLDB_LOGF(log, "Loading binary UUID %s at %s 0x%" PRIx64,
239+
uuid.GetAsString().c_str(),
240+
value_is_offset ? "offset" : "address", value);
241+
module_sp->SetLoadAddress(target, value, value_is_offset, changed);
242+
} else {
243+
// No address/offset/slide, load the binary at file address,
244+
// offset 0.
245+
LLDB_LOGF(log, "Loading binary UUID %s at file address",
246+
uuid.GetAsString().c_str());
247+
module_sp->SetLoadAddress(target, 0, true /* value_is_slide */,
248+
changed);
249+
}
250+
} else {
251+
// In-memory image, load at its true address, offset 0.
252+
LLDB_LOGF(log, "Loading binary UUID %s from memory at address 0x%" PRIx64,
253+
uuid.GetAsString().c_str(), value);
254+
module_sp->SetLoadAddress(target, 0, true /* value_is_slide */, changed);
255+
}
256+
257+
if (notify) {
258+
ModuleList added_module;
259+
added_module.Append(module_sp, false);
260+
target.ModulesDidLoad(added_module);
261+
}
262+
} else {
263+
LLDB_LOGF(log, "Unable to find binary with UUID %s and load it at "
264+
"%s 0x%" PRIx64,
265+
uuid.GetAsString().c_str(),
266+
value_is_offset ? "offset" : "address", value);
267+
}
268+
269+
return module_sp;
270+
}
271+
174272
int64_t DynamicLoader::ReadUnsignedIntWithSizeInBytes(addr_t addr,
175273
int size_in_bytes) {
176274
Status error;

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

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5600,7 +5600,8 @@ bool ObjectFileMachO::GetCorefileMainBinaryInfo(addr_t &value,
56005600
}
56015601

56025602
if (m_data.CopyData(offset, sizeof(uuid_t), raw_uuid) != 0) {
5603-
uuid = UUID::fromOptionalData(raw_uuid, sizeof(uuid_t));
5603+
if (!uuid_is_null(raw_uuid))
5604+
uuid = UUID::fromOptionalData(raw_uuid, sizeof(uuid_t));
56045605
// convert the "main bin spec" type into our
56055606
// ObjectFile::BinaryType enum
56065607
switch (binspec_type) {
@@ -6901,7 +6902,8 @@ ObjectFileMachO::GetCorefileAllImageInfos() {
69016902

69026903
MachOCorefileImageEntry image_entry;
69036904
image_entry.filename = (const char *)m_data.GetCStr(&filepath_offset);
6904-
image_entry.uuid = UUID::fromData(uuid, sizeof(uuid_t));
6905+
if (!uuid_is_null(uuid))
6906+
image_entry.uuid = UUID::fromData(uuid, sizeof(uuid_t));
69056907
image_entry.load_address = load_address;
69066908
image_entry.currently_executing = currently_executing;
69076909

@@ -6932,9 +6934,11 @@ ObjectFileMachO::GetCorefileAllImageInfos() {
69326934

69336935
MachOCorefileImageEntry image_entry;
69346936
image_entry.filename = filename;
6935-
image_entry.uuid = UUID::fromData(uuid, sizeof(uuid_t));
6937+
if (!uuid_is_null(uuid))
6938+
image_entry.uuid = UUID::fromData(uuid, sizeof(uuid_t));
69366939
image_entry.load_address = load_address;
69376940
image_entry.slide = slide;
6941+
image_entry.currently_executing = true;
69386942
image_infos.all_image_infos.push_back(image_entry);
69396943
}
69406944
}
@@ -6951,42 +6955,41 @@ bool ObjectFileMachO::LoadCoreFileImages(lldb_private::Process &process) {
69516955

69526956
ModuleList added_modules;
69536957
for (const MachOCorefileImageEntry &image : image_infos.all_image_infos) {
6954-
ModuleSpec module_spec;
6955-
module_spec.GetUUID() = image.uuid;
6956-
if (image.filename.empty()) {
6957-
char namebuf[80];
6958-
if (image.load_address != LLDB_INVALID_ADDRESS)
6959-
snprintf(namebuf, sizeof(namebuf), "mem-image-0x%" PRIx64,
6960-
image.load_address);
6961-
else
6962-
snprintf(namebuf, sizeof(namebuf), "mem-image+0x%" PRIx64, image.slide);
6963-
module_spec.GetFileSpec() = FileSpec(namebuf);
6964-
} else {
6965-
module_spec.GetFileSpec() = FileSpec(image.filename.c_str());
6966-
}
6967-
if (image.currently_executing) {
6958+
ModuleSP module_sp;
6959+
6960+
if (!image.filename.empty()) {
69686961
Status error;
6969-
Symbols::DownloadObjectAndSymbolFile(module_spec, error, true);
6970-
if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
6971-
process.GetTarget().GetOrCreateModule(module_spec, false);
6962+
ModuleSpec module_spec;
6963+
module_spec.GetUUID() = image.uuid;
6964+
module_spec.GetFileSpec() = FileSpec(image.filename.c_str());
6965+
if (image.currently_executing) {
6966+
Symbols::DownloadObjectAndSymbolFile(module_spec, error, true);
6967+
if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
6968+
process.GetTarget().GetOrCreateModule(module_spec, false);
6969+
}
69726970
}
6973-
}
6974-
Status error;
6975-
ModuleSP module_sp =
6976-
process.GetTarget().GetOrCreateModule(module_spec, false, &error);
6977-
if (!module_sp.get() || !module_sp->GetObjectFile()) {
6971+
module_sp =
6972+
process.GetTarget().GetOrCreateModule(module_spec, false, &error);
6973+
process.GetTarget().GetImages().AppendIfNeeded(module_sp,
6974+
false /* notify */);
6975+
} else {
69786976
if (image.load_address != LLDB_INVALID_ADDRESS) {
6979-
module_sp = process.ReadModuleFromMemory(module_spec.GetFileSpec(),
6980-
image.load_address);
6977+
module_sp = DynamicLoader::LoadBinaryWithUUIDAndAddress(
6978+
&process, image.uuid, image.load_address,
6979+
false /* value_is_offset */, image.currently_executing,
6980+
false /* notify */);
6981+
} else if (image.slide != LLDB_INVALID_ADDRESS) {
6982+
module_sp = DynamicLoader::LoadBinaryWithUUIDAndAddress(
6983+
&process, image.uuid, image.slide, true /* value_is_offset */,
6984+
image.currently_executing, false /* notify */);
69816985
}
69826986
}
6987+
69836988
if (module_sp.get()) {
69846989
// Will call ModulesDidLoad with all modules once they've all
69856990
// been added to the Target with load addresses. Don't notify
69866991
// here, before the load address is set.
6987-
const bool notify = false;
6988-
process.GetTarget().GetImages().AppendIfNeeded(module_sp, notify);
6989-
added_modules.Append(module_sp, notify);
6992+
added_modules.Append(module_sp, false /* notify */);
69906993
if (image.segment_load_addresses.size() > 0) {
69916994
if (log) {
69926995
std::string uuidstr = image.uuid.GetAsString();

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,13 @@ bool GDBRemoteCommunicationClient::GetProcessStandaloneBinary(
10331033
return true;
10341034
}
10351035

1036+
std::vector<addr_t>
1037+
GDBRemoteCommunicationClient::GetProcessStandaloneBinaries() {
1038+
if (m_qProcessInfo_is_valid == eLazyBoolCalculate)
1039+
GetCurrentProcessInfo();
1040+
return m_binary_addresses;
1041+
}
1042+
10361043
bool GDBRemoteCommunicationClient::GetGDBServerVersion() {
10371044
if (m_qGDBServerVersion_is_valid == eLazyBoolCalculate) {
10381045
m_gdb_server_name.clear();
@@ -2192,6 +2199,14 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) {
21922199
m_process_standalone_value_is_offset = false;
21932200
++num_keys_decoded;
21942201
}
2202+
} else if (name.equals("binary-addresses")) {
2203+
addr_t addr;
2204+
while (!value.empty()) {
2205+
llvm::StringRef addr_str;
2206+
std::tie(addr_str, value) = value.split(',');
2207+
if (!addr_str.getAsInteger(16, addr))
2208+
m_binary_addresses.push_back(addr);
2209+
}
21952210
}
21962211
}
21972212
if (num_keys_decoded > 0)

lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase {
220220
bool GetProcessStandaloneBinary(UUID &uuid, lldb::addr_t &value,
221221
bool &value_is_offset);
222222

223+
std::vector<lldb::addr_t> GetProcessStandaloneBinaries();
224+
223225
void GetRemoteQSupported();
224226

225227
bool GetVContSupported(char flavor);
@@ -593,6 +595,7 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase {
593595
UUID m_process_standalone_uuid;
594596
lldb::addr_t m_process_standalone_value = LLDB_INVALID_ADDRESS;
595597
bool m_process_standalone_value_is_offset = false;
598+
std::vector<lldb::addr_t> m_binary_addresses;
596599
llvm::VersionTuple m_os_version;
597600
llvm::VersionTuple m_maccatalyst_version;
598601
std::string m_os_build;

0 commit comments

Comments
 (0)