Fix in loading mach files from memory when using DynamicLoaderMacOSXDYLD. Removed the uuid mismatch warning that could be spit out and any time during debugging and removed the test case that was looking for that. Currently the "add-dsym" or "target symbols add" command will report an error when the UUID's don't match. Be more careful when checking and resolving section + offset addresses to make sure none of the base addresses are invalid. llvm-svn: 174222
385 lines
11 KiB
C++
385 lines
11 KiB
C++
//===-- 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
|
|
// C++ Includes
|
|
#include <map>
|
|
#include <vector>
|
|
#include <string>
|
|
|
|
// Other libraries and framework includes
|
|
#include "llvm/Support/MachO.h"
|
|
|
|
#include "lldb/Target/DynamicLoader.h"
|
|
#include "lldb/Host/FileSpec.h"
|
|
#include "lldb/Core/UUID.h"
|
|
#include "lldb/Host/Mutex.h"
|
|
#include "lldb/Target/Process.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, bool force);
|
|
|
|
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 ();
|
|
|
|
virtual bool
|
|
ProcessDidExec ();
|
|
|
|
virtual lldb::ThreadPlanSP
|
|
GetStepThroughTrampolinePlan (lldb_private::Thread &thread,
|
|
bool stop_others);
|
|
|
|
virtual size_t
|
|
FindEquivalentSymbols (lldb_private::Symbol *original_symbol,
|
|
lldb_private::ModuleList &module_list,
|
|
lldb_private::SymbolContextList &equivalent_symbols);
|
|
|
|
virtual lldb_private::Error
|
|
CanLoadImage ();
|
|
|
|
//------------------------------------------------------------------
|
|
// PluginInterface protocol
|
|
//------------------------------------------------------------------
|
|
virtual const char *
|
|
GetPluginName();
|
|
|
|
virtual const char *
|
|
GetShortPluginName();
|
|
|
|
virtual uint32_t
|
|
GetPluginVersion();
|
|
|
|
virtual bool
|
|
AlwaysRelyOnEHUnwindInfo (lldb_private::SymbolContext &sym_ctx);
|
|
|
|
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);
|
|
|
|
static bool
|
|
NotifyBreakpointHit (void *baton,
|
|
lldb_private::StoppointCallbackContext *context,
|
|
lldb::user_id_t break_id,
|
|
lldb::user_id_t break_loc_id);
|
|
|
|
uint32_t
|
|
AddrByteSize();
|
|
|
|
static lldb::ByteOrder
|
|
GetByteOrderFromMagic (uint32_t magic);
|
|
|
|
bool
|
|
ReadMachHeader (lldb::addr_t addr,
|
|
llvm::MachO::mach_header *header,
|
|
lldb_private::DataExtractor *load_command_data);
|
|
class Segment
|
|
{
|
|
public:
|
|
|
|
Segment() :
|
|
name(),
|
|
vmaddr(LLDB_INVALID_ADDRESS),
|
|
vmsize(0),
|
|
fileoff(0),
|
|
filesize(0),
|
|
maxprot(0),
|
|
initprot(0),
|
|
nsects(0),
|
|
flags(0)
|
|
{
|
|
}
|
|
|
|
lldb_private::ConstString name;
|
|
lldb::addr_t vmaddr;
|
|
lldb::addr_t vmsize;
|
|
lldb::addr_t fileoff;
|
|
lldb::addr_t filesize;
|
|
uint32_t maxprot;
|
|
uint32_t initprot;
|
|
uint32_t nsects;
|
|
uint32_t flags;
|
|
|
|
bool
|
|
operator==(const Segment& rhs) const
|
|
{
|
|
return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize;
|
|
}
|
|
|
|
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
|
|
llvm::MachO::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)
|
|
uint32_t load_stop_id; // The process stop ID that the sections for this image were loadeded
|
|
|
|
DYLDImageInfo() :
|
|
address(LLDB_INVALID_ADDRESS),
|
|
slide(0),
|
|
mod_date(0),
|
|
file_spec(),
|
|
uuid(),
|
|
header(),
|
|
segments(),
|
|
load_stop_id(0)
|
|
{
|
|
}
|
|
|
|
void
|
|
Clear(bool load_cmd_data_only)
|
|
{
|
|
if (!load_cmd_data_only)
|
|
{
|
|
address = LLDB_INVALID_ADDRESS;
|
|
slide = 0;
|
|
mod_date = 0;
|
|
file_spec.Clear();
|
|
::memset (&header, 0, sizeof(header));
|
|
}
|
|
uuid.Clear();
|
|
segments.clear();
|
|
load_stop_id = 0;
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
uint32_t
|
|
GetAddressByteSize ()
|
|
{
|
|
if (header.cputype)
|
|
{
|
|
if (header.cputype & llvm::MachO::CPUArchABI64)
|
|
return 8;
|
|
else
|
|
return 4;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
lldb::ByteOrder
|
|
GetByteOrder();
|
|
|
|
lldb_private::ArchSpec
|
|
GetArchitecture () const
|
|
{
|
|
return lldb_private::ArchSpec (lldb_private::eArchTypeMachO, header.cputype, header.cpusubtype);
|
|
}
|
|
|
|
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,
|
|
DYLDImageInfo& dylib_info,
|
|
lldb_private::FileSpec *lc_id_dylinker);
|
|
|
|
bool
|
|
UpdateImageLoadAddress(lldb_private::Module *module,
|
|
DYLDImageInfo& info);
|
|
|
|
bool
|
|
UnloadImageLoadAddress (lldb_private::Module *module,
|
|
DYLDImageInfo& info);
|
|
|
|
lldb::ModuleSP
|
|
FindTargetModuleForDYLDImageInfo (DYLDImageInfo &image_info,
|
|
bool can_create,
|
|
bool *did_create_ptr);
|
|
|
|
DYLDImageInfo *
|
|
GetImageInfo (lldb_private::Module *module);
|
|
|
|
bool
|
|
NeedToLocateDYLD () const;
|
|
|
|
bool
|
|
SetNotificationBreakpoint ();
|
|
|
|
// There is a little tricky bit where you might initially attach while dyld is updating
|
|
// the all_image_infos, and you can't read the infos, so you have to continue and pick it
|
|
// up when you hit the update breakpoint. At that point, you need to run this initialize
|
|
// function, but when you do it that way you DON'T need to do the extra work you would at
|
|
// the breakpoint.
|
|
// So this function will only do actual work if the image infos haven't been read yet.
|
|
// If it does do any work, then it will return true, and false otherwise. That way you can
|
|
// call it in the breakpoint action, and if it returns true you're done.
|
|
bool
|
|
InitializeFromAllImageInfos ();
|
|
|
|
bool
|
|
ReadAllImageInfosStructure ();
|
|
|
|
bool
|
|
AddModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count);
|
|
|
|
bool
|
|
AddModulesUsingImageInfos (DYLDImageInfo::collection &image_infos);
|
|
|
|
bool
|
|
RemoveModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count);
|
|
|
|
void
|
|
UpdateImageInfosHeaderAndLoadCommands(DYLDImageInfo::collection &image_infos,
|
|
uint32_t infos_count,
|
|
bool update_executable);
|
|
|
|
bool
|
|
ReadImageInfos (lldb::addr_t image_infos_addr,
|
|
uint32_t image_infos_count,
|
|
DYLDImageInfo::collection &image_infos);
|
|
|
|
|
|
DYLDImageInfo m_dyld; // Info about the current dyld being used
|
|
lldb::addr_t m_dyld_all_image_infos_addr;
|
|
DYLDAllImageInfos m_dyld_all_image_infos;
|
|
uint32_t m_dyld_all_image_infos_stop_id;
|
|
lldb::user_id_t m_break_id;
|
|
DYLDImageInfo::collection m_dyld_image_infos; // Current shared libraries information
|
|
uint32_t m_dyld_image_infos_stop_id; // The process stop ID that "m_dyld_image_infos" is valid for
|
|
mutable lldb_private::Mutex m_mutex;
|
|
lldb_private::Process::Notifications m_notification_callbacks;
|
|
bool m_process_image_addr_is_all_images_infos;
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXDYLD);
|
|
};
|
|
|
|
#endif // liblldb_DynamicLoaderMacOSXDYLD_h_
|