|
21 | 21 | #include "lldb/Symbol/LocateSymbolFile.h"
|
22 | 22 | #include "lldb/Symbol/ObjectFile.h"
|
23 | 23 | #include "lldb/Target/MemoryRegionInfo.h"
|
| 24 | +#include "lldb/Target/SectionLoadList.h" |
24 | 25 | #include "lldb/Target/Target.h"
|
25 | 26 | #include "lldb/Target/Thread.h"
|
26 | 27 | #include "lldb/Utility/DataBuffer.h"
|
|
36 | 37 |
|
37 | 38 | #include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"
|
38 | 39 | #include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h"
|
| 40 | +#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h" |
39 | 41 | #include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
|
40 | 42 |
|
41 | 43 | #include <memory>
|
@@ -188,6 +190,59 @@ bool ProcessMachCore::GetDynamicLoaderAddress(lldb::addr_t addr) {
|
188 | 190 | return false;
|
189 | 191 | }
|
190 | 192 |
|
| 193 | +// We have a hint about a binary -- a UUID, possibly a load address. |
| 194 | +// Try to load a file with that UUID into lldb, and if we have a load |
| 195 | +// address, set it correctly. Else assume that the binary was loaded |
| 196 | +// with no slide. |
| 197 | +static bool load_standalone_binary(UUID uuid, addr_t addr, Target &target) { |
| 198 | + if (uuid.IsValid()) { |
| 199 | + ModuleSpec module_spec; |
| 200 | + module_spec.GetUUID() = uuid; |
| 201 | + |
| 202 | + // Look up UUID in global module cache before attempting |
| 203 | + // dsymForUUID-like action. |
| 204 | + ModuleSP module_sp; |
| 205 | + Status error = ModuleList::GetSharedModule(module_spec, module_sp, nullptr, |
| 206 | + nullptr, nullptr); |
| 207 | + |
| 208 | + if (!module_sp.get()) { |
| 209 | + // Force a a dsymForUUID lookup, if that tool is available. |
| 210 | + if (!module_spec.GetSymbolFileSpec()) |
| 211 | + Symbols::DownloadObjectAndSymbolFile(module_spec, true); |
| 212 | + |
| 213 | + if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { |
| 214 | + module_sp = std::make_shared<Module>(module_spec); |
| 215 | + } |
| 216 | + } |
| 217 | + |
| 218 | + if (module_sp.get() && module_sp->GetObjectFile()) { |
| 219 | + target.SetArchitecture(module_sp->GetObjectFile()->GetArchitecture()); |
| 220 | + target.GetImages().AppendIfNeeded(module_sp, false); |
| 221 | + |
| 222 | + Address base_addr = module_sp->GetObjectFile()->GetBaseAddress(); |
| 223 | + addr_t slide = 0; |
| 224 | + if (addr != LLDB_INVALID_ADDRESS && base_addr.IsValid()) { |
| 225 | + addr_t file_load_addr = base_addr.GetFileAddress(); |
| 226 | + slide = addr - file_load_addr; |
| 227 | + } |
| 228 | + bool changed = false; |
| 229 | + module_sp->SetLoadAddress(target, slide, true, changed); |
| 230 | + |
| 231 | + ModuleList added_module; |
| 232 | + added_module.Append(module_sp, false); |
| 233 | + target.ModulesDidLoad(added_module); |
| 234 | + |
| 235 | + // Flush info in the process (stack frames, etc). |
| 236 | + ProcessSP process_sp(target.GetProcessSP()); |
| 237 | + if (process_sp) |
| 238 | + process_sp->Flush(); |
| 239 | + |
| 240 | + return true; |
| 241 | + } |
| 242 | + } |
| 243 | + return false; |
| 244 | +} |
| 245 | + |
191 | 246 | // Process Control
|
192 | 247 | Status ProcessMachCore::DoLoadCore() {
|
193 | 248 | Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER |
|
@@ -285,124 +340,76 @@ Status ProcessMachCore::DoLoadCore() {
|
285 | 340 | ObjectFile::BinaryType type;
|
286 | 341 | if (core_objfile->GetCorefileMainBinaryInfo(objfile_binary_addr,
|
287 | 342 | objfile_binary_uuid, type)) {
|
| 343 | + if (log) { |
| 344 | + log->Printf( |
| 345 | + "ProcessMachCore::DoLoadCore: using binary hint from 'main bin spec' " |
| 346 | + "LC_NOTE with UUID %s address 0x%" PRIx64 " and type %d", |
| 347 | + objfile_binary_uuid.GetAsString().c_str(), objfile_binary_addr, type); |
| 348 | + } |
288 | 349 | if (objfile_binary_addr != LLDB_INVALID_ADDRESS) {
|
289 |
| - if (type == ObjectFile::eBinaryTypeUser) |
| 350 | + if (type == ObjectFile::eBinaryTypeUser) { |
290 | 351 | m_dyld_addr = objfile_binary_addr;
|
291 |
| - else |
| 352 | + m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic(); |
| 353 | + found_main_binary_definitively = true; |
| 354 | + } |
| 355 | + if (type == ObjectFile::eBinaryTypeKernel) { |
292 | 356 | m_mach_kernel_addr = objfile_binary_addr;
|
293 |
| - found_main_binary_definitively = true; |
294 |
| - LLDB_LOGF(log, |
295 |
| - "ProcessMachCore::DoLoadCore: using kernel address 0x%" PRIx64 |
296 |
| - " from LC_NOTE 'main bin spec' load command.", |
297 |
| - m_mach_kernel_addr); |
| 357 | + m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic(); |
| 358 | + found_main_binary_definitively = true; |
| 359 | + } |
| 360 | + } |
| 361 | + if (!found_main_binary_definitively) { |
| 362 | + // ObjectFile::eBinaryTypeStandalone, undeclared types |
| 363 | + if (load_standalone_binary(objfile_binary_uuid, objfile_binary_addr, |
| 364 | + GetTarget())) { |
| 365 | + found_main_binary_definitively = true; |
| 366 | + m_dyld_plugin_name = DynamicLoaderStatic::GetPluginNameStatic(); |
| 367 | + } |
298 | 368 | }
|
299 | 369 | }
|
300 | 370 |
|
301 | 371 | // This checks for the presence of an LC_IDENT string in a core file;
|
302 | 372 | // LC_IDENT is very obsolete and should not be used in new code, but if the
|
303 | 373 | // load command is present, let's use the contents.
|
304 |
| - std::string corefile_identifier = core_objfile->GetIdentifierString(); |
305 |
| - if (!found_main_binary_definitively && |
306 |
| - corefile_identifier.find("Darwin Kernel") != std::string::npos) { |
307 |
| - UUID uuid; |
308 |
| - addr_t addr = LLDB_INVALID_ADDRESS; |
| 374 | + UUID ident_uuid; |
| 375 | + addr_t ident_binary_addr = LLDB_INVALID_ADDRESS; |
| 376 | + if (!found_main_binary_definitively) { |
| 377 | + std::string corefile_identifier = core_objfile->GetIdentifierString(); |
| 378 | + |
| 379 | + // Search for UUID= and stext= strings in the identifier str. |
309 | 380 | if (corefile_identifier.find("UUID=") != std::string::npos) {
|
310 | 381 | size_t p = corefile_identifier.find("UUID=") + strlen("UUID=");
|
311 | 382 | std::string uuid_str = corefile_identifier.substr(p, 36);
|
312 |
| - uuid.SetFromStringRef(uuid_str); |
| 383 | + ident_uuid.SetFromStringRef(uuid_str); |
| 384 | + if (log) |
| 385 | + log->Printf("Got a UUID from LC_IDENT/kern ver str LC_NOTE: %s", |
| 386 | + ident_uuid.GetAsString().c_str()); |
313 | 387 | }
|
314 | 388 | if (corefile_identifier.find("stext=") != std::string::npos) {
|
315 | 389 | size_t p = corefile_identifier.find("stext=") + strlen("stext=");
|
316 | 390 | if (corefile_identifier[p] == '0' && corefile_identifier[p + 1] == 'x') {
|
317 |
| - errno = 0; |
318 |
| - addr = ::strtoul(corefile_identifier.c_str() + p, nullptr, 16); |
319 |
| - if (errno != 0 || addr == 0) |
320 |
| - addr = LLDB_INVALID_ADDRESS; |
| 391 | + ident_binary_addr = |
| 392 | + ::strtoul(corefile_identifier.c_str() + p, nullptr, 16); |
| 393 | + if (log) |
| 394 | + log->Printf("Got a load address from LC_IDENT/kern ver str " |
| 395 | + "LC_NOTE: 0x%" PRIx64, |
| 396 | + ident_binary_addr); |
321 | 397 | }
|
322 | 398 | }
|
323 |
| - if (uuid.IsValid() && addr != LLDB_INVALID_ADDRESS) { |
324 |
| - m_mach_kernel_addr = addr; |
325 |
| - found_main_binary_definitively = true; |
326 |
| - LLDB_LOGF( |
327 |
| - log, |
328 |
| - "ProcessMachCore::DoLoadCore: Using the kernel address 0x%" PRIx64 |
329 |
| - " from LC_IDENT/LC_NOTE 'kern ver str' string: '%s'", |
330 |
| - addr, corefile_identifier.c_str()); |
331 |
| - } |
332 |
| - } |
333 | 399 |
|
334 |
| - // In the case where we have an LC_NOTE specifying a standalone |
335 |
| - // binary with only a UUID (and no load address) (iBoot, EFI, etc), |
336 |
| - // then let's try to force a load of the binary and set its |
337 |
| - // load address to 0-offset. |
338 |
| - // |
339 |
| - // The two forms this can come in is either a |
340 |
| - // 'kern ver str' LC_NOTE with "EFI UUID=...." |
341 |
| - // 'main bin spec' LC_NOTE with UUID and no load address. |
342 |
| - |
343 |
| - if (found_main_binary_definitively == false && |
344 |
| - (corefile_identifier.find("EFI ") != std::string::npos || |
345 |
| - (objfile_binary_uuid.IsValid() && |
346 |
| - objfile_binary_addr == LLDB_INVALID_ADDRESS))) { |
347 |
| - UUID uuid; |
348 |
| - if (objfile_binary_uuid.IsValid()) { |
349 |
| - uuid = objfile_binary_uuid; |
350 |
| - LLDB_LOGF(log, |
351 |
| - "ProcessMachCore::DoLoadCore: Using the main bin spec " |
352 |
| - "LC_NOTE with UUID %s and no load address", |
353 |
| - uuid.GetAsString().c_str()); |
354 |
| - } else { |
355 |
| - if (corefile_identifier.find("UUID=") != std::string::npos) { |
356 |
| - size_t p = corefile_identifier.find("UUID=") + strlen("UUID="); |
357 |
| - std::string uuid_str = corefile_identifier.substr(p, 36); |
358 |
| - uuid.SetFromStringRef(uuid_str); |
359 |
| - if (uuid.IsValid()) { |
360 |
| - LLDB_LOGF(log, |
361 |
| - "ProcessMachCore::DoLoadCore: Using the EFI " |
362 |
| - "from LC_IDENT/LC_NOTE 'kern ver str' string: '%s'", |
363 |
| - corefile_identifier.c_str()); |
364 |
| - } |
365 |
| - } |
366 |
| - } |
367 |
| - |
368 |
| - if (uuid.IsValid()) { |
369 |
| - ModuleSpec module_spec; |
370 |
| - module_spec.GetUUID() = uuid; |
371 |
| - module_spec.GetArchitecture() = GetTarget().GetArchitecture(); |
372 |
| - |
373 |
| - // Lookup UUID locally, before attempting dsymForUUID-like action |
374 |
| - FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); |
375 |
| - module_spec.GetSymbolFileSpec() = |
376 |
| - Symbols::LocateExecutableSymbolFile(module_spec, search_paths); |
377 |
| - if (module_spec.GetSymbolFileSpec()) { |
378 |
| - ModuleSpec executable_module_spec = |
379 |
| - Symbols::LocateExecutableObjectFile(module_spec); |
380 |
| - if (FileSystem::Instance().Exists( |
381 |
| - executable_module_spec.GetFileSpec())) { |
382 |
| - module_spec.GetFileSpec() = executable_module_spec.GetFileSpec(); |
383 |
| - } |
384 |
| - } |
385 |
| - |
386 |
| - // Force a a dsymForUUID lookup, if that tool is available. |
387 |
| - if (!module_spec.GetSymbolFileSpec()) |
388 |
| - Symbols::DownloadObjectAndSymbolFile(module_spec, true); |
389 |
| - |
390 |
| - // If we found a binary, load it at offset 0 and set our |
391 |
| - // dyld_plugin to be the static plugin. |
392 |
| - if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { |
393 |
| - ModuleSP module_sp(new Module(module_spec)); |
394 |
| - if (module_sp.get() && module_sp->GetObjectFile()) { |
395 |
| - GetTarget().GetImages().AppendIfNeeded(module_sp, true); |
396 |
| - GetTarget().SetExecutableModule(module_sp, eLoadDependentsNo); |
397 |
| - found_main_binary_definitively = true; |
398 |
| - bool changed = true; |
399 |
| - module_sp->SetLoadAddress(GetTarget(), 0, true, changed); |
400 |
| - ModuleList added_module; |
401 |
| - added_module.Append(module_sp, false); |
402 |
| - GetTarget().ModulesDidLoad(added_module); |
403 |
| - m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic(); |
404 |
| - found_main_binary_definitively = true; |
405 |
| - } |
| 400 | + // Search for a "Darwin Kernel" str indicating kernel; else treat as |
| 401 | + // standalone |
| 402 | + if (corefile_identifier.find("Darwin Kernel") != std::string::npos && |
| 403 | + ident_uuid.IsValid() && ident_binary_addr != LLDB_INVALID_ADDRESS) { |
| 404 | + if (log) |
| 405 | + log->Printf("ProcessMachCore::DoLoadCore: Found kernel binary via " |
| 406 | + "LC_IDENT/kern ver str LC_NOTE"); |
| 407 | + m_mach_kernel_addr = ident_binary_addr; |
| 408 | + found_main_binary_definitively = true; |
| 409 | + } else if (ident_uuid.IsValid()) { |
| 410 | + if (load_standalone_binary(ident_uuid, ident_binary_addr, GetTarget())) { |
| 411 | + found_main_binary_definitively = true; |
| 412 | + m_dyld_plugin_name = DynamicLoaderStatic::GetPluginNameStatic(); |
406 | 413 | }
|
407 | 414 | }
|
408 | 415 | }
|
|
0 commit comments