2011-08-22 22:30:57 +00:00
|
|
|
//===-- DynamicLoaderDarwinKernel.cpp -----------------------------*- C++ -*-===//
|
2011-07-08 00:48:09 +00:00
|
|
|
//
|
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
|
//
|
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
|
//
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
|
|
#include "lldb/Breakpoint/StoppointCallbackContext.h"
|
|
|
|
|
#include "lldb/Core/DataBuffer.h"
|
|
|
|
|
#include "lldb/Core/DataBufferHeap.h"
|
2011-07-20 03:41:06 +00:00
|
|
|
#include "lldb/Core/Debugger.h"
|
2011-07-08 00:48:09 +00:00
|
|
|
#include "lldb/Core/Log.h"
|
|
|
|
|
#include "lldb/Core/Module.h"
|
<rdar://problem/11757916>
Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes:
- Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file".
- modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly
- Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was.
- modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile()
Cleaned up header includes a bit as well.
llvm-svn: 162860
2012-08-29 21:13:06 +00:00
|
|
|
#include "lldb/Core/ModuleSpec.h"
|
2011-07-08 00:48:09 +00:00
|
|
|
#include "lldb/Core/PluginManager.h"
|
<rdar://problem/11757916>
Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes:
- Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file".
- modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly
- Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was.
- modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile()
Cleaned up header includes a bit as well.
llvm-svn: 162860
2012-08-29 21:13:06 +00:00
|
|
|
#include "lldb/Core/Section.h"
|
2011-07-08 00:48:09 +00:00
|
|
|
#include "lldb/Core/State.h"
|
|
|
|
|
#include "lldb/Symbol/ObjectFile.h"
|
|
|
|
|
#include "lldb/Target/ObjCLanguageRuntime.h"
|
|
|
|
|
#include "lldb/Target/RegisterContext.h"
|
|
|
|
|
#include "lldb/Target/Target.h"
|
|
|
|
|
#include "lldb/Target/Thread.h"
|
|
|
|
|
#include "lldb/Target/ThreadPlanRunToAddress.h"
|
|
|
|
|
#include "lldb/Target/StackFrame.h"
|
|
|
|
|
|
2011-08-22 22:30:57 +00:00
|
|
|
#include "DynamicLoaderDarwinKernel.h"
|
2011-07-08 00:48:09 +00:00
|
|
|
|
|
|
|
|
//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
|
|
|
|
|
#ifdef ENABLE_DEBUG_PRINTF
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
|
|
|
|
|
#else
|
|
|
|
|
#define DEBUG_PRINTF(fmt, ...)
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
using namespace lldb;
|
|
|
|
|
using namespace lldb_private;
|
|
|
|
|
|
|
|
|
|
/// FIXME - The ObjC Runtime trampoline handler doesn't really belong here.
|
|
|
|
|
/// I am putting it here so I can invoke it in the Trampoline code here, but
|
|
|
|
|
/// it should be moved to the ObjC Runtime support when it is set up.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
// Create an instance of this class. This function is filled into
|
|
|
|
|
// the plugin info class that gets handed out by the plugin factory and
|
|
|
|
|
// allows the lldb to instantiate an instance of this class.
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
DynamicLoader *
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::CreateInstance (Process* process, bool force)
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
|
|
|
|
bool create = force;
|
|
|
|
|
if (!create)
|
|
|
|
|
{
|
2011-08-11 02:48:45 +00:00
|
|
|
Module* exe_module = process->GetTarget().GetExecutableModulePointer();
|
2011-07-08 04:11:42 +00:00
|
|
|
if (exe_module)
|
|
|
|
|
{
|
|
|
|
|
ObjectFile *object_file = exe_module->GetObjectFile();
|
|
|
|
|
if (object_file)
|
|
|
|
|
{
|
2012-02-10 20:22:35 +00:00
|
|
|
create = (object_file->GetStrata() == ObjectFile::eStrataKernel);
|
2011-07-08 04:11:42 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (create)
|
|
|
|
|
{
|
|
|
|
|
const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
|
2012-05-08 01:45:38 +00:00
|
|
|
switch (triple_ref.getOS())
|
|
|
|
|
{
|
|
|
|
|
case llvm::Triple::Darwin:
|
|
|
|
|
case llvm::Triple::MacOSX:
|
|
|
|
|
case llvm::Triple::IOS:
|
|
|
|
|
create = triple_ref.getVendor() == llvm::Triple::Apple;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
create = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2011-07-08 04:11:42 +00:00
|
|
|
}
|
2011-07-08 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (create)
|
2011-09-20 23:01:51 +00:00
|
|
|
{
|
|
|
|
|
process->SetCanJIT(false);
|
2011-08-22 22:30:57 +00:00
|
|
|
return new DynamicLoaderDarwinKernel (process);
|
2011-09-20 23:01:51 +00:00
|
|
|
}
|
2011-07-08 00:48:09 +00:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
// Constructor
|
|
|
|
|
//----------------------------------------------------------------------
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::DynamicLoaderDarwinKernel (Process* process) :
|
2011-07-08 00:48:09 +00:00
|
|
|
DynamicLoader(process),
|
|
|
|
|
m_kernel(),
|
2011-07-12 17:06:17 +00:00
|
|
|
m_kext_summary_header_ptr_addr (),
|
2011-07-08 03:21:57 +00:00
|
|
|
m_kext_summary_header_addr (),
|
2011-07-08 00:48:09 +00:00
|
|
|
m_kext_summary_header (),
|
|
|
|
|
m_kext_summaries(),
|
2011-10-31 22:50:49 +00:00
|
|
|
m_mutex(Mutex::eMutexTypeRecursive),
|
|
|
|
|
m_break_id (LLDB_INVALID_BREAK_ID)
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
// Destructor
|
|
|
|
|
//----------------------------------------------------------------------
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::~DynamicLoaderDarwinKernel()
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
|
|
|
|
Clear(true);
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-09 17:15:55 +00:00
|
|
|
void
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::UpdateIfNeeded()
|
2011-07-09 17:15:55 +00:00
|
|
|
{
|
|
|
|
|
LoadKernelModuleIfNeeded();
|
|
|
|
|
SetNotificationBreakpointIfNeeded ();
|
|
|
|
|
}
|
2011-07-08 00:48:09 +00:00
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
/// Called after attaching a process.
|
|
|
|
|
///
|
|
|
|
|
/// Allow DynamicLoader plug-ins to execute some code after
|
|
|
|
|
/// attaching to a process.
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
void
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::DidAttach ()
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
|
|
|
|
PrivateInitialize(m_process);
|
2011-07-09 17:15:55 +00:00
|
|
|
UpdateIfNeeded();
|
2011-07-08 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
/// Called after attaching a process.
|
|
|
|
|
///
|
|
|
|
|
/// Allow DynamicLoader plug-ins to execute some code after
|
|
|
|
|
/// attaching to a process.
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
void
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::DidLaunch ()
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
|
|
|
|
PrivateInitialize(m_process);
|
2011-07-09 17:15:55 +00:00
|
|
|
UpdateIfNeeded();
|
2011-07-08 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
// Clear out the state of this class.
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
void
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::Clear (bool clear_process)
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
|
|
|
|
Mutex::Locker locker(m_mutex);
|
|
|
|
|
|
|
|
|
|
if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id))
|
|
|
|
|
m_process->ClearBreakpointSiteByID(m_break_id);
|
|
|
|
|
|
|
|
|
|
if (clear_process)
|
|
|
|
|
m_process = NULL;
|
|
|
|
|
m_kernel.Clear(false);
|
2011-07-12 17:06:17 +00:00
|
|
|
m_kext_summary_header_ptr_addr.Clear();
|
2011-07-08 03:21:57 +00:00
|
|
|
m_kext_summary_header_addr.Clear();
|
2011-07-08 00:48:09 +00:00
|
|
|
m_kext_summaries.clear();
|
|
|
|
|
m_break_id = LLDB_INVALID_BREAK_ID;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-03-21 04:25:00 +00:00
|
|
|
bool
|
|
|
|
|
DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::LoadImageAtFileAddress (Process *process)
|
|
|
|
|
{
|
|
|
|
|
if (IsLoaded())
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (module_sp)
|
|
|
|
|
{
|
|
|
|
|
bool changed = false;
|
|
|
|
|
if (module_sp->SetLoadAddress (process->GetTarget(), 0, changed))
|
|
|
|
|
load_process_stop_id = process->GetStopID();
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-08 00:48:09 +00:00
|
|
|
bool
|
2012-02-13 23:10:39 +00:00
|
|
|
DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::LoadImageUsingMemoryModule (Process *process)
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2012-02-13 23:10:39 +00:00
|
|
|
if (IsLoaded())
|
|
|
|
|
return true;
|
2011-07-08 00:48:09 +00:00
|
|
|
|
2012-02-13 23:10:39 +00:00
|
|
|
bool uuid_is_valid = uuid.IsValid();
|
2011-07-08 00:48:09 +00:00
|
|
|
|
2012-02-13 23:10:39 +00:00
|
|
|
Target &target = process->GetTarget();
|
|
|
|
|
ModuleSP memory_module_sp;
|
|
|
|
|
// Use the memory module as the module if we have one...
|
|
|
|
|
if (address != LLDB_INVALID_ADDRESS)
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2012-02-13 23:10:39 +00:00
|
|
|
FileSpec file_spec;
|
|
|
|
|
if (module_sp)
|
|
|
|
|
file_spec = module_sp->GetFileSpec();
|
|
|
|
|
else
|
|
|
|
|
file_spec.SetFile (name, false);
|
|
|
|
|
|
|
|
|
|
memory_module_sp = process->ReadModuleFromMemory (file_spec, address, false, false);
|
|
|
|
|
if (memory_module_sp && !uuid_is_valid)
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2012-02-13 23:10:39 +00:00
|
|
|
uuid = memory_module_sp->GetUUID();
|
|
|
|
|
uuid_is_valid = uuid.IsValid();
|
2011-07-08 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-13 23:10:39 +00:00
|
|
|
if (!module_sp)
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2012-02-13 23:10:39 +00:00
|
|
|
if (uuid_is_valid)
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2012-02-13 23:10:39 +00:00
|
|
|
ModuleList &target_images = target.GetImages();
|
|
|
|
|
module_sp = target_images.FindModule(uuid);
|
|
|
|
|
|
|
|
|
|
if (!module_sp)
|
2012-02-26 05:51:37 +00:00
|
|
|
{
|
2012-03-21 04:25:00 +00:00
|
|
|
ModuleSpec module_spec;
|
2012-02-26 05:51:37 +00:00
|
|
|
module_spec.GetUUID() = uuid;
|
|
|
|
|
module_sp = target.GetSharedModule (module_spec);
|
|
|
|
|
}
|
2011-07-08 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
}
|
2012-02-13 23:10:39 +00:00
|
|
|
|
2011-07-08 00:48:09 +00:00
|
|
|
|
2012-02-13 23:10:39 +00:00
|
|
|
if (memory_module_sp)
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2012-02-13 23:10:39 +00:00
|
|
|
// Someone already supplied a file, make sure it is the right one.
|
|
|
|
|
if (module_sp)
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2012-02-13 23:10:39 +00:00
|
|
|
if (module_sp->GetUUID() == memory_module_sp->GetUUID())
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2012-02-13 23:10:39 +00:00
|
|
|
ObjectFile *ondisk_object_file = module_sp->GetObjectFile();
|
|
|
|
|
ObjectFile *memory_object_file = memory_module_sp->GetObjectFile();
|
|
|
|
|
if (memory_object_file && ondisk_object_file)
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2012-02-13 23:10:39 +00:00
|
|
|
SectionList *ondisk_section_list = ondisk_object_file->GetSectionList ();
|
|
|
|
|
SectionList *memory_section_list = memory_object_file->GetSectionList ();
|
|
|
|
|
if (memory_section_list && ondisk_section_list)
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2012-02-14 00:14:24 +00:00
|
|
|
const uint32_t num_ondisk_sections = ondisk_section_list->GetSize();
|
2012-02-13 23:10:39 +00:00
|
|
|
// There may be CTF sections in the memory image so we can't
|
|
|
|
|
// always just compare the number of sections (which are actually
|
|
|
|
|
// segments in mach-o parlance)
|
|
|
|
|
uint32_t sect_idx = 0;
|
2012-02-14 00:14:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
// We now iterate through all sections in the file module
|
|
|
|
|
// and look to see if the memory module has a load address
|
|
|
|
|
// for that section.
|
|
|
|
|
uint32_t num_sections_loaded = 0;
|
|
|
|
|
for (sect_idx=0; sect_idx<num_ondisk_sections; ++sect_idx)
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2012-07-07 01:24:12 +00:00
|
|
|
SectionSP ondisk_section_sp(ondisk_section_list->GetSectionAtIndex(sect_idx));
|
|
|
|
|
if (ondisk_section_sp)
|
2011-07-19 03:57:15 +00:00
|
|
|
{
|
2012-07-07 01:24:12 +00:00
|
|
|
const Section *memory_section = memory_section_list->FindSectionByName(ondisk_section_sp->GetName()).get();
|
2012-02-14 00:14:24 +00:00
|
|
|
if (memory_section)
|
|
|
|
|
{
|
2012-07-07 01:24:12 +00:00
|
|
|
target.GetSectionLoadList().SetSectionLoadAddress (ondisk_section_sp, memory_section->GetFileAddress());
|
2012-02-14 00:14:24 +00:00
|
|
|
++num_sections_loaded;
|
|
|
|
|
}
|
2011-07-19 03:57:15 +00:00
|
|
|
}
|
|
|
|
|
}
|
2012-02-14 00:14:24 +00:00
|
|
|
if (num_sections_loaded > 0)
|
|
|
|
|
load_process_stop_id = process->GetStopID();
|
|
|
|
|
else
|
|
|
|
|
module_sp.reset(); // No sections were loaded
|
2011-07-08 00:48:09 +00:00
|
|
|
}
|
2012-02-13 23:10:39 +00:00
|
|
|
else
|
|
|
|
|
module_sp.reset(); // One or both section lists
|
2011-07-08 00:48:09 +00:00
|
|
|
}
|
2012-02-13 23:10:39 +00:00
|
|
|
else
|
|
|
|
|
module_sp.reset(); // One or both object files missing
|
2011-07-08 00:48:09 +00:00
|
|
|
}
|
2012-02-13 23:10:39 +00:00
|
|
|
else
|
|
|
|
|
module_sp.reset(); // UUID mismatch
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Use the memory module as the module if we didn't like the file
|
|
|
|
|
// module we either found or were supplied with
|
|
|
|
|
if (!module_sp)
|
|
|
|
|
{
|
|
|
|
|
module_sp = memory_module_sp;
|
|
|
|
|
// Load the memory image in the target as all adresses are already correct
|
|
|
|
|
bool changed = false;
|
|
|
|
|
target.GetImages().Append (memory_module_sp);
|
|
|
|
|
if (module_sp->SetLoadAddress (target, 0, changed))
|
|
|
|
|
load_process_stop_id = process->GetStopID();
|
2011-07-08 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
}
|
2012-02-13 23:10:39 +00:00
|
|
|
bool is_loaded = IsLoaded();
|
|
|
|
|
|
|
|
|
|
if (so_address.IsValid())
|
|
|
|
|
{
|
|
|
|
|
if (is_loaded)
|
|
|
|
|
so_address.SetLoadAddress (address, &target);
|
|
|
|
|
else
|
|
|
|
|
target.GetImages().ResolveFileAddress (address, so_address);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
return is_loaded;
|
2011-07-08 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
|
<rdar://problem/11757916>
Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes:
- Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file".
- modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly
- Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was.
- modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile()
Cleaned up header includes a bit as well.
llvm-svn: 162860
2012-08-29 21:13:06 +00:00
|
|
|
uint32_t
|
|
|
|
|
DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::GetAddressByteSize ()
|
|
|
|
|
{
|
|
|
|
|
if (module_sp)
|
|
|
|
|
return module_sp->GetArchitecture().GetAddressByteSize();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lldb::ByteOrder
|
|
|
|
|
DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::GetByteOrder()
|
|
|
|
|
{
|
|
|
|
|
if (module_sp)
|
|
|
|
|
return module_sp->GetArchitecture().GetByteOrder();
|
|
|
|
|
return lldb::endian::InlHostByteOrder();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lldb_private::ArchSpec
|
|
|
|
|
DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::GetArchitecture () const
|
|
|
|
|
{
|
|
|
|
|
if (module_sp)
|
|
|
|
|
return module_sp->GetArchitecture();
|
|
|
|
|
return lldb_private::ArchSpec ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-07-08 00:48:09 +00:00
|
|
|
//----------------------------------------------------------------------
|
2012-02-13 23:10:39 +00:00
|
|
|
// Load the kernel module and initialize the "m_kernel" member. Return
|
|
|
|
|
// true _only_ if the kernel is loaded the first time through (subsequent
|
|
|
|
|
// calls to this function should return false after the kernel has been
|
|
|
|
|
// already loaded).
|
2011-07-08 00:48:09 +00:00
|
|
|
//----------------------------------------------------------------------
|
2012-02-13 23:10:39 +00:00
|
|
|
void
|
|
|
|
|
DynamicLoaderDarwinKernel::LoadKernelModuleIfNeeded()
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2012-02-13 23:10:39 +00:00
|
|
|
if (!m_kext_summary_header_ptr_addr.IsValid())
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2012-02-13 23:10:39 +00:00
|
|
|
m_kernel.Clear(false);
|
|
|
|
|
m_kernel.module_sp = m_process->GetTarget().GetExecutableModule();
|
2012-09-29 04:02:01 +00:00
|
|
|
|
|
|
|
|
ConstString kernel_name("mach_kernel");
|
|
|
|
|
if (m_kernel.module_sp.get()
|
|
|
|
|
&& m_kernel.module_sp->GetObjectFile()
|
|
|
|
|
&& !m_kernel.module_sp->GetObjectFile()->GetFileSpec().GetFilename().IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
kernel_name = m_kernel.module_sp->GetObjectFile()->GetFileSpec().GetFilename();
|
|
|
|
|
}
|
|
|
|
|
strlcpy (m_kernel.name, kernel_name.AsCString(), sizeof(m_kernel.name));
|
|
|
|
|
|
2012-02-13 23:10:39 +00:00
|
|
|
if (m_kernel.address == LLDB_INVALID_ADDRESS)
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2012-02-13 23:10:39 +00:00
|
|
|
m_kernel.address = m_process->GetImageInfoAddress ();
|
|
|
|
|
if (m_kernel.address == LLDB_INVALID_ADDRESS && m_kernel.module_sp)
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2012-02-13 23:10:39 +00:00
|
|
|
// We didn't get a hint from the process, so we will
|
|
|
|
|
// try the kernel at the address that it exists at in
|
|
|
|
|
// the file if we have one
|
|
|
|
|
ObjectFile *kernel_object_file = m_kernel.module_sp->GetObjectFile();
|
|
|
|
|
if (kernel_object_file)
|
2012-09-29 04:02:01 +00:00
|
|
|
{
|
|
|
|
|
addr_t load_address = kernel_object_file->GetHeaderAddress().GetLoadAddress(&m_process->GetTarget());
|
|
|
|
|
addr_t file_address = kernel_object_file->GetHeaderAddress().GetFileAddress();
|
|
|
|
|
if (load_address != LLDB_INVALID_ADDRESS && load_address != 0)
|
|
|
|
|
{
|
|
|
|
|
m_kernel.address = load_address;
|
|
|
|
|
if (load_address != file_address)
|
|
|
|
|
{
|
|
|
|
|
// Don't accidentally relocate the kernel to the File address --
|
|
|
|
|
// the Load address has already been set to its actual in-memory address.
|
|
|
|
|
// Mark it as IsLoaded.
|
|
|
|
|
m_kernel.load_process_stop_id = m_process->GetStopID();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_kernel.address = file_address;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-07-08 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
}
|
2012-02-13 23:10:39 +00:00
|
|
|
|
|
|
|
|
if (m_kernel.address != LLDB_INVALID_ADDRESS)
|
2012-03-21 04:25:00 +00:00
|
|
|
{
|
|
|
|
|
if (!m_kernel.LoadImageUsingMemoryModule (m_process))
|
|
|
|
|
{
|
|
|
|
|
m_kernel.LoadImageAtFileAddress (m_process);
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-02-13 23:10:39 +00:00
|
|
|
|
|
|
|
|
if (m_kernel.IsLoaded())
|
|
|
|
|
{
|
|
|
|
|
static ConstString kext_summary_symbol ("gLoadedKextSummaries");
|
|
|
|
|
const Symbol *symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (kext_summary_symbol, eSymbolTypeData);
|
|
|
|
|
if (symbol)
|
|
|
|
|
{
|
2012-03-07 21:03:09 +00:00
|
|
|
m_kext_summary_header_ptr_addr = symbol->GetAddress();
|
2012-02-13 23:10:39 +00:00
|
|
|
// Update all image infos
|
|
|
|
|
ReadAllKextSummaries ();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_kernel.Clear(false);
|
|
|
|
|
}
|
2011-07-08 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
// Static callback function that gets called when our DYLD notification
|
|
|
|
|
// breakpoint gets hit. We update all of our image infos and then
|
|
|
|
|
// let our super class DynamicLoader class decide if we should stop
|
|
|
|
|
// or not (based on global preference).
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
bool
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::BreakpointHitCallback (void *baton,
|
2011-07-09 17:15:55 +00:00
|
|
|
StoppointCallbackContext *context,
|
|
|
|
|
user_id_t break_id,
|
|
|
|
|
user_id_t break_loc_id)
|
2011-07-08 03:21:57 +00:00
|
|
|
{
|
2011-08-22 22:30:57 +00:00
|
|
|
return static_cast<DynamicLoaderDarwinKernel*>(baton)->BreakpointHit (context, break_id, break_loc_id);
|
2011-07-08 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
|
2011-07-09 17:15:55 +00:00
|
|
|
bool
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::BreakpointHit (StoppointCallbackContext *context,
|
2011-07-09 17:15:55 +00:00
|
|
|
user_id_t break_id,
|
|
|
|
|
user_id_t break_loc_id)
|
|
|
|
|
{
|
2011-07-12 17:06:17 +00:00
|
|
|
LogSP log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
|
|
|
|
|
if (log)
|
2011-08-22 22:30:57 +00:00
|
|
|
log->Printf ("DynamicLoaderDarwinKernel::BreakpointHit (...)\n");
|
2011-07-12 17:06:17 +00:00
|
|
|
|
2011-07-09 17:15:55 +00:00
|
|
|
ReadAllKextSummaries ();
|
2011-07-12 17:06:17 +00:00
|
|
|
|
|
|
|
|
if (log)
|
|
|
|
|
PutToLog(log.get());
|
|
|
|
|
|
2011-07-09 17:15:55 +00:00
|
|
|
return GetStopWhenImagesChange();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-07-08 00:48:09 +00:00
|
|
|
bool
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::ReadKextSummaryHeader ()
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
|
|
|
|
Mutex::Locker locker(m_mutex);
|
|
|
|
|
|
|
|
|
|
// the all image infos is already valid for this process stop ID
|
|
|
|
|
|
|
|
|
|
m_kext_summaries.clear();
|
2011-07-12 17:06:17 +00:00
|
|
|
if (m_kext_summary_header_ptr_addr.IsValid())
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
|
|
|
|
const uint32_t addr_size = m_kernel.GetAddressByteSize ();
|
|
|
|
|
const ByteOrder byte_order = m_kernel.GetByteOrder();
|
|
|
|
|
Error error;
|
|
|
|
|
// Read enough bytes for a "OSKextLoadedKextSummaryHeader" structure
|
|
|
|
|
// which is currenty 4 uint32_t and a pointer.
|
|
|
|
|
uint8_t buf[24];
|
|
|
|
|
DataExtractor data (buf, sizeof(buf), byte_order, addr_size);
|
|
|
|
|
const size_t count = 4 * sizeof(uint32_t) + addr_size;
|
2011-07-08 03:21:57 +00:00
|
|
|
const bool prefer_file_cache = false;
|
2011-07-12 17:06:17 +00:00
|
|
|
if (m_process->GetTarget().ReadPointerFromMemory (m_kext_summary_header_ptr_addr,
|
|
|
|
|
prefer_file_cache,
|
|
|
|
|
error,
|
|
|
|
|
m_kext_summary_header_addr))
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2011-07-12 17:06:17 +00:00
|
|
|
// We got a valid address for our kext summary header and make sure it isn't NULL
|
|
|
|
|
if (m_kext_summary_header_addr.IsValid() &&
|
|
|
|
|
m_kext_summary_header_addr.GetFileAddress() != 0)
|
|
|
|
|
{
|
|
|
|
|
const size_t bytes_read = m_process->GetTarget().ReadMemory (m_kext_summary_header_addr, prefer_file_cache, buf, count, error);
|
|
|
|
|
if (bytes_read == count)
|
|
|
|
|
{
|
|
|
|
|
uint32_t offset = 0;
|
2011-07-19 03:57:15 +00:00
|
|
|
m_kext_summary_header.version = data.GetU32(&offset);
|
|
|
|
|
if (m_kext_summary_header.version >= 2)
|
|
|
|
|
{
|
|
|
|
|
m_kext_summary_header.entry_size = data.GetU32(&offset);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Versions less than 2 didn't have an entry size, it was hard coded
|
|
|
|
|
m_kext_summary_header.entry_size = KERNEL_MODULE_ENTRY_SIZE_VERSION_1;
|
|
|
|
|
}
|
|
|
|
|
m_kext_summary_header.entry_count = data.GetU32(&offset);
|
2011-07-12 17:06:17 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-07-08 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
}
|
2011-07-12 17:06:17 +00:00
|
|
|
m_kext_summary_header_addr.Clear();
|
2011-07-08 00:48:09 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::ParseKextSummaries (const Address &kext_summary_addr,
|
2011-07-08 03:21:57 +00:00
|
|
|
uint32_t count)
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
|
|
|
|
OSKextLoadedKextSummary::collection kext_summaries;
|
2011-07-09 17:15:55 +00:00
|
|
|
LogSP log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
|
2011-07-08 00:48:09 +00:00
|
|
|
if (log)
|
2011-09-20 21:44:10 +00:00
|
|
|
log->Printf ("Adding %d modules.\n", count);
|
2011-07-08 00:48:09 +00:00
|
|
|
|
|
|
|
|
Mutex::Locker locker(m_mutex);
|
|
|
|
|
|
|
|
|
|
if (!ReadKextSummaries (kext_summary_addr, count, kext_summaries))
|
|
|
|
|
return false;
|
|
|
|
|
|
2011-07-20 03:41:06 +00:00
|
|
|
Stream *s = &m_process->GetTarget().GetDebugger().GetOutputStream();
|
2011-07-08 00:48:09 +00:00
|
|
|
for (uint32_t i = 0; i < count; i++)
|
|
|
|
|
{
|
2011-07-20 03:41:06 +00:00
|
|
|
if (s)
|
|
|
|
|
{
|
|
|
|
|
const uint8_t *u = (const uint8_t *)kext_summaries[i].uuid.GetBytes();
|
|
|
|
|
if (u)
|
|
|
|
|
{
|
2011-09-24 02:47:39 +00:00
|
|
|
s->Printf("Loading kext: %2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X 0x%16.16llx \"%s\"...",
|
2011-07-20 03:41:06 +00:00
|
|
|
u[ 0], u[ 1], u[ 2], u[ 3], u[ 4], u[ 5], u[ 6], u[ 7],
|
|
|
|
|
u[ 8], u[ 9], u[10], u[11], u[12], u[13], u[14], u[15],
|
|
|
|
|
kext_summaries[i].address, kext_summaries[i].name);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2011-09-24 02:47:39 +00:00
|
|
|
s->Printf("0x%16.16llx \"%s\"...", kext_summaries[i].address, kext_summaries[i].name);
|
2011-07-20 03:41:06 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-21 04:25:00 +00:00
|
|
|
if (!kext_summaries[i].LoadImageUsingMemoryModule (m_process))
|
|
|
|
|
kext_summaries[i].LoadImageAtFileAddress (m_process);
|
2012-02-13 23:10:39 +00:00
|
|
|
|
2011-07-21 01:12:01 +00:00
|
|
|
if (s)
|
|
|
|
|
{
|
|
|
|
|
if (kext_summaries[i].module_sp)
|
2012-02-13 23:10:39 +00:00
|
|
|
{
|
|
|
|
|
if (kext_summaries[i].module_sp->GetFileSpec().GetDirectory())
|
|
|
|
|
s->Printf("\n found kext: %s/%s\n",
|
|
|
|
|
kext_summaries[i].module_sp->GetFileSpec().GetDirectory().AsCString(),
|
|
|
|
|
kext_summaries[i].module_sp->GetFileSpec().GetFilename().AsCString());
|
|
|
|
|
else
|
|
|
|
|
s->Printf("\n found kext: %s\n",
|
|
|
|
|
kext_summaries[i].module_sp->GetFileSpec().GetFilename().AsCString());
|
|
|
|
|
}
|
2011-09-24 02:47:39 +00:00
|
|
|
else
|
|
|
|
|
s->Printf (" failed to locate/load.\n");
|
2011-07-21 01:12:01 +00:00
|
|
|
}
|
|
|
|
|
|
2011-07-19 03:57:15 +00:00
|
|
|
if (log)
|
|
|
|
|
kext_summaries[i].PutToLog (log.get());
|
2011-07-08 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
bool return_value = AddModulesUsingImageInfos (kext_summaries);
|
|
|
|
|
return return_value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Adds the modules in image_infos to m_kext_summaries.
|
|
|
|
|
// NB don't call this passing in m_kext_summaries.
|
|
|
|
|
|
|
|
|
|
bool
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::AddModulesUsingImageInfos (OSKextLoadedKextSummary::collection &image_infos)
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
|
|
|
|
// Now add these images to the main list.
|
|
|
|
|
ModuleList loaded_module_list;
|
|
|
|
|
|
|
|
|
|
for (uint32_t idx = 0; idx < image_infos.size(); ++idx)
|
|
|
|
|
{
|
2012-02-13 23:10:39 +00:00
|
|
|
OSKextLoadedKextSummary &image_info = image_infos[idx];
|
|
|
|
|
m_kext_summaries.push_back(image_info);
|
2011-07-08 00:48:09 +00:00
|
|
|
|
2012-02-13 23:10:39 +00:00
|
|
|
if (image_info.module_sp && m_process->GetStopID() == image_info.load_process_stop_id)
|
|
|
|
|
loaded_module_list.AppendIfNeeded (image_infos[idx].module_sp);
|
2011-07-08 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (loaded_module_list.GetSize() > 0)
|
|
|
|
|
{
|
|
|
|
|
m_process->GetTarget().ModulesDidLoad (loaded_module_list);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::ReadKextSummaries (const Address &kext_summary_addr,
|
2011-07-08 00:48:09 +00:00
|
|
|
uint32_t image_infos_count,
|
|
|
|
|
OSKextLoadedKextSummary::collection &image_infos)
|
|
|
|
|
{
|
|
|
|
|
const ByteOrder endian = m_kernel.GetByteOrder();
|
|
|
|
|
const uint32_t addr_size = m_kernel.GetAddressByteSize();
|
|
|
|
|
|
|
|
|
|
image_infos.resize(image_infos_count);
|
|
|
|
|
const size_t count = image_infos.size() * m_kext_summary_header.entry_size;
|
|
|
|
|
DataBufferHeap data(count, 0);
|
|
|
|
|
Error error;
|
2011-07-21 01:12:01 +00:00
|
|
|
|
|
|
|
|
Stream *s = &m_process->GetTarget().GetDebugger().GetOutputStream();
|
|
|
|
|
|
|
|
|
|
if (s)
|
|
|
|
|
s->Printf ("Reading %u kext summaries...\n", image_infos_count);
|
2011-07-08 03:21:57 +00:00
|
|
|
const bool prefer_file_cache = false;
|
|
|
|
|
const size_t bytes_read = m_process->GetTarget().ReadMemory (kext_summary_addr,
|
|
|
|
|
prefer_file_cache,
|
|
|
|
|
data.GetBytes(),
|
|
|
|
|
data.GetByteSize(),
|
|
|
|
|
error);
|
2011-07-08 00:48:09 +00:00
|
|
|
if (bytes_read == count)
|
|
|
|
|
{
|
2011-07-19 03:57:15 +00:00
|
|
|
|
2011-07-08 00:48:09 +00:00
|
|
|
DataExtractor extractor (data.GetBytes(), data.GetByteSize(), endian, addr_size);
|
|
|
|
|
uint32_t i=0;
|
2011-07-19 03:57:15 +00:00
|
|
|
for (uint32_t kext_summary_offset = 0;
|
|
|
|
|
i < image_infos.size() && extractor.ValidOffsetForDataOfSize(kext_summary_offset, m_kext_summary_header.entry_size);
|
|
|
|
|
++i, kext_summary_offset += m_kext_summary_header.entry_size)
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2011-07-19 03:57:15 +00:00
|
|
|
uint32_t offset = kext_summary_offset;
|
2011-07-08 00:48:09 +00:00
|
|
|
const void *name_data = extractor.GetData(&offset, KERNEL_MODULE_MAX_NAME);
|
|
|
|
|
if (name_data == NULL)
|
|
|
|
|
break;
|
|
|
|
|
memcpy (image_infos[i].name, name_data, KERNEL_MODULE_MAX_NAME);
|
|
|
|
|
image_infos[i].uuid.SetBytes(extractor.GetData (&offset, 16));
|
|
|
|
|
image_infos[i].address = extractor.GetU64(&offset);
|
2011-07-08 03:21:57 +00:00
|
|
|
if (!image_infos[i].so_address.SetLoadAddress (image_infos[i].address, &m_process->GetTarget()))
|
|
|
|
|
m_process->GetTarget().GetImages().ResolveFileAddress (image_infos[i].address, image_infos[i].so_address);
|
2011-07-08 00:48:09 +00:00
|
|
|
image_infos[i].size = extractor.GetU64(&offset);
|
|
|
|
|
image_infos[i].version = extractor.GetU64(&offset);
|
|
|
|
|
image_infos[i].load_tag = extractor.GetU32(&offset);
|
|
|
|
|
image_infos[i].flags = extractor.GetU32(&offset);
|
2011-07-19 03:57:15 +00:00
|
|
|
if ((offset - kext_summary_offset) < m_kext_summary_header.entry_size)
|
|
|
|
|
{
|
|
|
|
|
image_infos[i].reference_list = extractor.GetU64(&offset);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
image_infos[i].reference_list = 0;
|
|
|
|
|
}
|
2012-02-14 00:14:24 +00:00
|
|
|
// printf ("[%3u] %*.*s: address=0x%16.16llx, size=0x%16.16llx, version=0x%16.16llx, load_tag=0x%8.8x, flags=0x%8.8x\n",
|
|
|
|
|
// i,
|
|
|
|
|
// KERNEL_MODULE_MAX_NAME, KERNEL_MODULE_MAX_NAME, (char *)name_data,
|
|
|
|
|
// image_infos[i].address,
|
|
|
|
|
// image_infos[i].size,
|
|
|
|
|
// image_infos[i].version,
|
|
|
|
|
// image_infos[i].load_tag,
|
|
|
|
|
// image_infos[i].flags);
|
2011-07-08 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
if (i < image_infos.size())
|
|
|
|
|
image_infos.resize(i);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
image_infos.clear();
|
|
|
|
|
}
|
|
|
|
|
return image_infos.size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::ReadAllKextSummaries ()
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2011-07-09 17:15:55 +00:00
|
|
|
LogSP log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
|
2011-07-08 00:48:09 +00:00
|
|
|
|
|
|
|
|
Mutex::Locker locker(m_mutex);
|
2011-07-09 17:15:55 +00:00
|
|
|
|
2011-07-08 00:48:09 +00:00
|
|
|
if (ReadKextSummaryHeader ())
|
|
|
|
|
{
|
2011-07-09 17:15:55 +00:00
|
|
|
if (m_kext_summary_header.entry_count > 0 && m_kext_summary_header_addr.IsValid())
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2011-07-08 03:21:57 +00:00
|
|
|
Address summary_addr (m_kext_summary_header_addr);
|
2011-07-19 03:57:15 +00:00
|
|
|
summary_addr.Slide(m_kext_summary_header.GetSize());
|
2011-07-08 03:21:57 +00:00
|
|
|
if (!ParseKextSummaries (summary_addr, m_kext_summary_header.entry_count))
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
|
|
|
|
m_kext_summaries.clear();
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
// Dump an image info structure to the file handle provided.
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
void
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::PutToLog (Log *log) const
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
|
|
|
|
if (log == NULL)
|
|
|
|
|
return;
|
2011-07-20 03:41:06 +00:00
|
|
|
const uint8_t *u = (uint8_t *)uuid.GetBytes();
|
2011-07-08 00:48:09 +00:00
|
|
|
|
|
|
|
|
if (address == LLDB_INVALID_ADDRESS)
|
|
|
|
|
{
|
|
|
|
|
if (u)
|
|
|
|
|
{
|
2011-07-19 03:57:15 +00:00
|
|
|
log->Printf("\tuuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X name=\"%s\" (UNLOADED)",
|
2011-07-08 00:48:09 +00:00
|
|
|
u[ 0], u[ 1], u[ 2], u[ 3],
|
|
|
|
|
u[ 4], u[ 5], u[ 6], u[ 7],
|
|
|
|
|
u[ 8], u[ 9], u[10], u[11],
|
|
|
|
|
u[12], u[13], u[14], u[15],
|
|
|
|
|
name);
|
|
|
|
|
}
|
|
|
|
|
else
|
2011-07-19 03:57:15 +00:00
|
|
|
log->Printf("\tname=\"%s\" (UNLOADED)", name);
|
2011-07-08 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (u)
|
|
|
|
|
{
|
2011-07-19 03:57:15 +00:00
|
|
|
log->Printf("\taddr=0x%16.16llx size=0x%16.16llx version=0x%16.16llx load-tag=0x%8.8x flags=0x%8.8x ref-list=0x%16.16llx uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X name=\"%s\"",
|
|
|
|
|
address, size, version, load_tag, flags, reference_list,
|
|
|
|
|
u[ 0], u[ 1], u[ 2], u[ 3], u[ 4], u[ 5], u[ 6], u[ 7],
|
|
|
|
|
u[ 8], u[ 9], u[10], u[11], u[12], u[13], u[14], u[15],
|
2011-07-08 00:48:09 +00:00
|
|
|
name);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2011-07-19 03:57:15 +00:00
|
|
|
log->Printf("\t[0x%16.16llx - 0x%16.16llx) version=0x%16.16llx load-tag=0x%8.8x flags=0x%8.8x ref-list=0x%16.16llx name=\"%s\"",
|
|
|
|
|
address, address+size, version, load_tag, flags, reference_list,
|
|
|
|
|
name);
|
2011-07-08 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
// Dump the _dyld_all_image_infos members and all current image infos
|
|
|
|
|
// that we have parsed to the file handle provided.
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
void
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::PutToLog(Log *log) const
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
|
|
|
|
if (log == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
Mutex::Locker locker(m_mutex);
|
2011-07-19 03:57:15 +00:00
|
|
|
log->Printf("gLoadedKextSummaries = 0x%16.16llx { version=%u, entry_size=%u, entry_count=%u }",
|
2011-07-08 03:21:57 +00:00
|
|
|
m_kext_summary_header_addr.GetFileAddress(),
|
2011-07-08 00:48:09 +00:00
|
|
|
m_kext_summary_header.version,
|
|
|
|
|
m_kext_summary_header.entry_size,
|
2011-07-19 03:57:15 +00:00
|
|
|
m_kext_summary_header.entry_count);
|
2011-07-08 00:48:09 +00:00
|
|
|
|
|
|
|
|
size_t i;
|
|
|
|
|
const size_t count = m_kext_summaries.size();
|
|
|
|
|
if (count > 0)
|
|
|
|
|
{
|
|
|
|
|
log->PutCString("Loaded:");
|
|
|
|
|
for (i = 0; i<count; i++)
|
|
|
|
|
m_kext_summaries[i].PutToLog(log);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::PrivateInitialize(Process *process)
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2011-08-22 22:30:57 +00:00
|
|
|
DEBUG_PRINTF("DynamicLoaderDarwinKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
|
2011-07-08 00:48:09 +00:00
|
|
|
Clear(true);
|
|
|
|
|
m_process = process;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-09 17:15:55 +00:00
|
|
|
void
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::SetNotificationBreakpointIfNeeded ()
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2012-02-13 23:10:39 +00:00
|
|
|
if (m_break_id == LLDB_INVALID_BREAK_ID && m_kernel.module_sp)
|
2011-07-09 17:15:55 +00:00
|
|
|
{
|
2011-08-22 22:30:57 +00:00
|
|
|
DEBUG_PRINTF("DynamicLoaderDarwinKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
|
2011-07-09 17:15:55 +00:00
|
|
|
|
2011-07-12 17:06:17 +00:00
|
|
|
|
2012-05-22 00:12:20 +00:00
|
|
|
const bool internal_bp = true;
|
2011-07-12 17:06:17 +00:00
|
|
|
const LazyBool skip_prologue = eLazyBoolNo;
|
2011-09-21 01:17:13 +00:00
|
|
|
FileSpecList module_spec_list;
|
|
|
|
|
module_spec_list.Append (m_kernel.module_sp->GetFileSpec());
|
|
|
|
|
Breakpoint *bp = m_process->GetTarget().CreateBreakpoint (&module_spec_list,
|
2011-09-23 00:54:11 +00:00
|
|
|
NULL,
|
2011-07-09 17:15:55 +00:00
|
|
|
"OSKextLoadedKextSummariesUpdated",
|
|
|
|
|
eFunctionNameTypeFull,
|
2012-05-22 00:12:20 +00:00
|
|
|
skip_prologue,
|
|
|
|
|
internal_bp).get();
|
2011-07-09 17:15:55 +00:00
|
|
|
|
2011-08-22 22:30:57 +00:00
|
|
|
bp->SetCallback (DynamicLoaderDarwinKernel::BreakpointHitCallback, this, true);
|
2011-07-09 17:15:55 +00:00
|
|
|
m_break_id = bp->GetID();
|
|
|
|
|
}
|
2011-07-08 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
// Member function that gets called when the process state changes.
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
void
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::PrivateProcessStateChanged (Process *process, StateType state)
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2011-08-22 22:30:57 +00:00
|
|
|
DEBUG_PRINTF("DynamicLoaderDarwinKernel::%s(%s)\n", __FUNCTION__, StateAsCString(state));
|
2011-07-08 00:48:09 +00:00
|
|
|
switch (state)
|
|
|
|
|
{
|
|
|
|
|
case eStateConnected:
|
|
|
|
|
case eStateAttaching:
|
|
|
|
|
case eStateLaunching:
|
|
|
|
|
case eStateInvalid:
|
|
|
|
|
case eStateUnloaded:
|
|
|
|
|
case eStateExited:
|
|
|
|
|
case eStateDetached:
|
|
|
|
|
Clear(false);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eStateStopped:
|
2011-07-09 17:15:55 +00:00
|
|
|
UpdateIfNeeded();
|
2011-07-08 00:48:09 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case eStateRunning:
|
|
|
|
|
case eStateStepping:
|
|
|
|
|
case eStateCrashed:
|
|
|
|
|
case eStateSuspended:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ThreadPlanSP
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
|
|
|
|
ThreadPlanSP thread_plan_sp;
|
2011-07-09 17:15:55 +00:00
|
|
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
|
|
|
|
|
if (log)
|
|
|
|
|
log->Printf ("Could not find symbol for step through.");
|
2011-07-08 00:48:09 +00:00
|
|
|
return thread_plan_sp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Error
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::CanLoadImage ()
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
|
|
|
|
Error error;
|
|
|
|
|
error.SetErrorString("always unsafe to load or unload shared libraries in the darwin kernel");
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::Initialize()
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
|
|
|
|
PluginManager::RegisterPlugin (GetPluginNameStatic(),
|
|
|
|
|
GetPluginDescriptionStatic(),
|
|
|
|
|
CreateInstance);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::Terminate()
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
|
|
|
|
PluginManager::UnregisterPlugin (CreateInstance);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const char *
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::GetPluginNameStatic()
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
|
|
|
|
return "dynamic-loader.macosx-kernel";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::GetPluginDescriptionStatic()
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
|
|
|
|
return "Dynamic loader plug-in that watches for shared library loads/unloads in the MacOSX kernel.";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
// PluginInterface protocol
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
const char *
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::GetPluginName()
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
2011-08-22 22:30:57 +00:00
|
|
|
return "DynamicLoaderDarwinKernel";
|
2011-07-08 00:48:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::GetShortPluginName()
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
|
|
|
|
return GetPluginNameStatic();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t
|
2011-08-22 22:30:57 +00:00
|
|
|
DynamicLoaderDarwinKernel::GetPluginVersion()
|
2011-07-08 00:48:09 +00:00
|
|
|
{
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
<rdar://problem/11757916>
Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes:
- Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file".
- modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly
- Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was.
- modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile()
Cleaned up header includes a bit as well.
llvm-svn: 162860
2012-08-29 21:13:06 +00:00
|
|
|
lldb::ByteOrder
|
|
|
|
|
DynamicLoaderDarwinKernel::GetByteOrderFromMagic (uint32_t magic)
|
|
|
|
|
{
|
|
|
|
|
switch (magic)
|
|
|
|
|
{
|
|
|
|
|
case llvm::MachO::HeaderMagic32:
|
|
|
|
|
case llvm::MachO::HeaderMagic64:
|
|
|
|
|
return lldb::endian::InlHostByteOrder();
|
|
|
|
|
|
|
|
|
|
case llvm::MachO::HeaderMagic32Swapped:
|
|
|
|
|
case llvm::MachO::HeaderMagic64Swapped:
|
|
|
|
|
if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderBig)
|
|
|
|
|
return lldb::eByteOrderLittle;
|
|
|
|
|
else
|
|
|
|
|
return lldb::eByteOrderBig;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return lldb::eByteOrderInvalid;
|
|
|
|
|
}
|
|
|
|
|
|