383 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			383 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 lldb_private::ConstString
 | |
|     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 lldb_private::ConstString
 | |
|     GetPluginName();
 | |
| 
 | |
|     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::CPU_ARCH_ABI64)
 | |
|                     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::ModuleWP m_dyld_module_wp;
 | |
|     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_
 |