blob: 724a8b6bd6df2566f6cd6660d045474f9ea904be [file] [log] [blame]
//===-- DynamicLoaderMacOSXDYLD.h -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_DynamicLoaderMacOSXDYLD_h_
#define liblldb_DynamicLoaderMacOSXDYLD_h_
// C Includes
#include <mach-o/loader.h>
// C++ Includes
#include <map>
#include <vector>
#include <string>
// Other libraries and framework includes
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Core/FileSpec.h"
#include "lldb/Core/UUID.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Target/Process.h"
#include "ObjCTrampolineHandler.h"
class DynamicLoaderMacOSXDYLD : public lldb_private::DynamicLoader
{
public:
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
static void
Initialize();
static void
Terminate();
static const char *
GetPluginNameStatic();
static const char *
GetPluginDescriptionStatic();
static lldb_private::DynamicLoader *
CreateInstance (lldb_private::Process *process);
DynamicLoaderMacOSXDYLD (lldb_private::Process *process);
virtual
~DynamicLoaderMacOSXDYLD ();
//------------------------------------------------------------------
/// Called after attaching a process.
///
/// Allow DynamicLoader plug-ins to execute some code after
/// attaching to a process.
//------------------------------------------------------------------
virtual void
DidAttach ();
virtual void
DidLaunch ();
//------------------------------------------------------------------
// Process::Notifications callback functions
//------------------------------------------------------------------
static void
Initialize (void *baton,
lldb_private::Process *process);
static void
ProcessStateChanged (void *baton,
lldb_private::Process *process,
lldb::StateType state);
virtual lldb::ThreadPlanSP
GetStepThroughTrampolinePlan (lldb_private::Thread &thread,
bool stop_others);
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
virtual const char *
GetPluginName();
virtual const char *
GetShortPluginName();
virtual uint32_t
GetPluginVersion();
virtual void
GetPluginCommandHelp (const char *command, lldb_private::Stream *strm);
virtual lldb_private::Error
ExecutePluginCommand (lldb_private::Args &command, lldb_private::Stream *strm);
virtual lldb_private::Log *
EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
protected:
void
PrivateInitialize (lldb_private::Process *process);
void
PrivateProcessStateChanged (lldb_private::Process *process,
lldb::StateType state);
bool
LocateDYLD ();
bool
DidSetNotificationBreakpoint () const;
void
Clear (bool clear_process);
void
PutToLog (lldb_private::Log *log) const;
bool
ReadDYLDInfoFromMemoryAndSetNotificationCallback (lldb::addr_t addr);
uint32_t
UpdateAllImageInfos ();
static bool
NotifyBreakpointHit (void *baton,
lldb_private::StoppointCallbackContext *context,
lldb::user_id_t break_id,
lldb::user_id_t break_loc_id);
void
UpdateAllImageInfosHeaderAndLoadCommands ();
bool
UpdateCommPageLoadAddress (lldb_private::Module *module);
uint32_t
AddrByteSize()
{
switch (m_dyld.header.magic)
{
case MH_MAGIC:
case MH_CIGAM:
return 4;
case MH_MAGIC_64:
case MH_CIGAM_64:
return 8;
default:
break;
}
return 0;
}
static lldb::ByteOrder
GetByteOrderFromMagic (uint32_t magic)
{
switch (magic)
{
case MH_MAGIC:
case MH_MAGIC_64:
return lldb::eByteOrderHost;
case MH_CIGAM:
case MH_CIGAM_64:
if (lldb::eByteOrderHost == lldb::eByteOrderBig)
return lldb::eByteOrderLittle;
else
return lldb::eByteOrderBig;
default:
break;
}
return lldb::eByteOrderInvalid;
}
bool
ReadMachHeader (lldb::addr_t addr,
struct mach_header *header,
lldb_private::DataExtractor *load_command_data);
class Segment
{
public:
Segment() :
name(),
addr(LLDB_INVALID_ADDRESS),
size(0)
{
}
lldb_private::ConstString name;
lldb::addr_t addr;
lldb::addr_t size;
bool
operator==(const Segment& rhs) const
{
return name == rhs.name && addr == rhs.addr && size == rhs.size;
}
void
PutToLog (lldb_private::Log *log,
lldb::addr_t slide) const;
};
struct DYLDImageInfo
{
lldb::addr_t address; // Address of mach header for this dylib
lldb::addr_t slide; // The amount to slide all segments by if there is a global slide.
lldb::addr_t mod_date; // Modification date for this dylib
lldb_private::FileSpec file_spec; // Resolved path for this dylib
lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros
struct mach_header header; // The mach header for this image
std::vector<Segment> segments; // All segment vmaddr and vmsize pairs for this executable (from memory of inferior)
DYLDImageInfo() :
address(LLDB_INVALID_ADDRESS),
slide(0),
mod_date(0),
file_spec(),
uuid(),
header(),
segments()
{
}
void
Clear(bool load_cmd_data_only)
{
if (!load_cmd_data_only)
{
address = LLDB_INVALID_ADDRESS;
slide = 0;
mod_date = 0;
file_spec.Clear();
::bzero (&header, sizeof(header));
}
uuid.Clear();
segments.clear();
}
bool
operator == (const DYLDImageInfo& rhs) const
{
return address == rhs.address
&& slide == rhs.slide
&& mod_date == rhs.mod_date
&& file_spec == rhs.file_spec
&& uuid == rhs.uuid
&& memcmp(&header, &rhs.header, sizeof(header)) == 0
&& segments == rhs.segments;
}
bool
UUIDValid() const
{
return uuid.IsValid();
}
const Segment *
FindSegment (const lldb_private::ConstString &name) const;
void
PutToLog (lldb_private::Log *log) const;
typedef std::vector<DYLDImageInfo> collection;
typedef collection::iterator iterator;
typedef collection::const_iterator const_iterator;
};
struct DYLDAllImageInfos
{
uint32_t version;
uint32_t dylib_info_count; // Version >= 1
lldb::addr_t dylib_info_addr; // Version >= 1
lldb::addr_t notification; // Version >= 1
bool processDetachedFromSharedRegion; // Version >= 1
bool libSystemInitialized; // Version >= 2
lldb::addr_t dyldImageLoadAddress; // Version >= 2
DYLDAllImageInfos() :
version (0),
dylib_info_count (0),
dylib_info_addr (LLDB_INVALID_ADDRESS),
notification (LLDB_INVALID_ADDRESS),
processDetachedFromSharedRegion (false),
libSystemInitialized (false),
dyldImageLoadAddress (LLDB_INVALID_ADDRESS)
{
}
void
Clear()
{
version = 0;
dylib_info_count = 0;
dylib_info_addr = LLDB_INVALID_ADDRESS;
notification = LLDB_INVALID_ADDRESS;
processDetachedFromSharedRegion = false;
libSystemInitialized = false;
dyldImageLoadAddress = LLDB_INVALID_ADDRESS;
}
bool
IsValid() const
{
return version >= 1 || version <= 6;
}
};
void
RegisterNotificationCallbacks();
void
UnregisterNotificationCallbacks();
uint32_t
ParseLoadCommands (const lldb_private::DataExtractor& data,
struct DYLDImageInfo& dylib_info,
lldb_private::FileSpec *lc_id_dylinker);
bool
UpdateImageLoadAddress(lldb_private::Module *module,
struct DYLDImageInfo& info);
bool
UnloadImageLoadAddress (lldb_private::Module *module,
struct DYLDImageInfo& info);
bool
NeedToLocateDYLD () const;
bool
SetNotificationBreakpoint ();
bool
ReadAllImageInfosStructure ();
DYLDImageInfo m_dyld; // Info about the curent dyld being used
lldb::addr_t m_dyld_all_image_infos_addr;
DYLDAllImageInfos m_dyld_all_image_infos;
lldb::user_id_t m_break_id;
DYLDImageInfo::collection m_dyld_image_infos; // Current shared libraries information
mutable lldb_private::Mutex m_mutex;
lldb_private::Process::Notifications m_notification_callbacks;
std::auto_ptr<lldb_private::ObjCTrampolineHandler> m_objc_trampoline_handler_ap;
private:
DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXDYLD);
};
#endif // liblldb_DynamicLoaderMacOSXDYLD_h_