Home | History | Annotate | Download | only in MacOSX-DYLD
      1 //===-- DynamicLoaderMacOSXDYLD.h -------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #ifndef liblldb_DynamicLoaderMacOSXDYLD_h_
     11 #define liblldb_DynamicLoaderMacOSXDYLD_h_
     12 
     13 // C Includes
     14 // C++ Includes
     15 #include <map>
     16 #include <vector>
     17 #include <string>
     18 
     19 // Other libraries and framework includes
     20 #include "llvm/Support/MachO.h"
     21 
     22 #include "lldb/Target/DynamicLoader.h"
     23 #include "lldb/Host/FileSpec.h"
     24 #include "lldb/Core/UUID.h"
     25 #include "lldb/Host/Mutex.h"
     26 #include "lldb/Target/Process.h"
     27 
     28 class DynamicLoaderMacOSXDYLD : public lldb_private::DynamicLoader
     29 {
     30 public:
     31     //------------------------------------------------------------------
     32     // Static Functions
     33     //------------------------------------------------------------------
     34     static void
     35     Initialize();
     36 
     37     static void
     38     Terminate();
     39 
     40     static lldb_private::ConstString
     41     GetPluginNameStatic();
     42 
     43     static const char *
     44     GetPluginDescriptionStatic();
     45 
     46     static lldb_private::DynamicLoader *
     47     CreateInstance (lldb_private::Process *process, bool force);
     48 
     49     DynamicLoaderMacOSXDYLD (lldb_private::Process *process);
     50 
     51     virtual
     52     ~DynamicLoaderMacOSXDYLD ();
     53     //------------------------------------------------------------------
     54     /// Called after attaching a process.
     55     ///
     56     /// Allow DynamicLoader plug-ins to execute some code after
     57     /// attaching to a process.
     58     //------------------------------------------------------------------
     59     virtual void
     60     DidAttach ();
     61 
     62     virtual void
     63     DidLaunch ();
     64 
     65     virtual bool
     66     ProcessDidExec ();
     67 
     68     virtual lldb::ThreadPlanSP
     69     GetStepThroughTrampolinePlan (lldb_private::Thread &thread,
     70                                   bool stop_others);
     71 
     72     virtual size_t
     73     FindEquivalentSymbols (lldb_private::Symbol *original_symbol,
     74                            lldb_private::ModuleList &module_list,
     75                            lldb_private::SymbolContextList &equivalent_symbols);
     76 
     77     virtual lldb_private::Error
     78     CanLoadImage ();
     79 
     80     //------------------------------------------------------------------
     81     // PluginInterface protocol
     82     //------------------------------------------------------------------
     83     virtual lldb_private::ConstString
     84     GetPluginName();
     85 
     86     virtual uint32_t
     87     GetPluginVersion();
     88 
     89     virtual bool
     90     AlwaysRelyOnEHUnwindInfo (lldb_private::SymbolContext &sym_ctx);
     91 
     92 protected:
     93     void
     94     PrivateInitialize (lldb_private::Process *process);
     95 
     96     void
     97     PrivateProcessStateChanged (lldb_private::Process *process,
     98                                 lldb::StateType state);
     99     bool
    100     LocateDYLD ();
    101 
    102     bool
    103     DidSetNotificationBreakpoint () const;
    104 
    105     void
    106     Clear (bool clear_process);
    107 
    108     void
    109     PutToLog (lldb_private::Log *log) const;
    110 
    111     bool
    112     ReadDYLDInfoFromMemoryAndSetNotificationCallback (lldb::addr_t addr);
    113 
    114     static bool
    115     NotifyBreakpointHit (void *baton,
    116                          lldb_private::StoppointCallbackContext *context,
    117                          lldb::user_id_t break_id,
    118                          lldb::user_id_t break_loc_id);
    119 
    120     uint32_t
    121     AddrByteSize();
    122 
    123     static lldb::ByteOrder
    124     GetByteOrderFromMagic (uint32_t magic);
    125 
    126     bool
    127     ReadMachHeader (lldb::addr_t addr,
    128                     llvm::MachO::mach_header *header,
    129                     lldb_private::DataExtractor *load_command_data);
    130     class Segment
    131     {
    132     public:
    133 
    134         Segment() :
    135             name(),
    136             vmaddr(LLDB_INVALID_ADDRESS),
    137             vmsize(0),
    138             fileoff(0),
    139             filesize(0),
    140             maxprot(0),
    141             initprot(0),
    142             nsects(0),
    143             flags(0)
    144         {
    145         }
    146 
    147         lldb_private::ConstString name;
    148         lldb::addr_t vmaddr;
    149         lldb::addr_t vmsize;
    150         lldb::addr_t fileoff;
    151         lldb::addr_t filesize;
    152         uint32_t maxprot;
    153         uint32_t initprot;
    154         uint32_t nsects;
    155         uint32_t flags;
    156 
    157         bool
    158         operator==(const Segment& rhs) const
    159         {
    160             return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize;
    161         }
    162 
    163         void
    164         PutToLog (lldb_private::Log *log,
    165                   lldb::addr_t slide) const;
    166 
    167     };
    168 
    169     struct DYLDImageInfo
    170     {
    171         lldb::addr_t address;               // Address of mach header for this dylib
    172         lldb::addr_t slide;                 // The amount to slide all segments by if there is a global slide.
    173         lldb::addr_t mod_date;              // Modification date for this dylib
    174         lldb_private::FileSpec file_spec;   // Resolved path for this dylib
    175         lldb_private::UUID uuid;            // UUID for this dylib if it has one, else all zeros
    176         llvm::MachO::mach_header header;    // The mach header for this image
    177         std::vector<Segment> segments;      // All segment vmaddr and vmsize pairs for this executable (from memory of inferior)
    178         uint32_t load_stop_id;              // The process stop ID that the sections for this image were loadeded
    179 
    180         DYLDImageInfo() :
    181             address(LLDB_INVALID_ADDRESS),
    182             slide(0),
    183             mod_date(0),
    184             file_spec(),
    185             uuid(),
    186             header(),
    187             segments(),
    188             load_stop_id(0)
    189         {
    190         }
    191 
    192         void
    193         Clear(bool load_cmd_data_only)
    194         {
    195             if (!load_cmd_data_only)
    196             {
    197                 address = LLDB_INVALID_ADDRESS;
    198                 slide = 0;
    199                 mod_date = 0;
    200                 file_spec.Clear();
    201                 ::memset (&header, 0, sizeof(header));
    202             }
    203             uuid.Clear();
    204             segments.clear();
    205             load_stop_id = 0;
    206         }
    207 
    208         bool
    209         operator == (const DYLDImageInfo& rhs) const
    210         {
    211             return  address == rhs.address
    212                 && slide == rhs.slide
    213                 && mod_date == rhs.mod_date
    214                 && file_spec == rhs.file_spec
    215                 && uuid == rhs.uuid
    216                 && memcmp(&header, &rhs.header, sizeof(header)) == 0
    217                 && segments == rhs.segments;
    218         }
    219 
    220         bool
    221         UUIDValid() const
    222         {
    223             return uuid.IsValid();
    224         }
    225 
    226         uint32_t
    227         GetAddressByteSize ()
    228         {
    229             if (header.cputype)
    230             {
    231                 if (header.cputype & llvm::MachO::CPUArchABI64)
    232                     return 8;
    233                 else
    234                     return 4;
    235             }
    236             return 0;
    237         }
    238 
    239         lldb::ByteOrder
    240         GetByteOrder();
    241 
    242         lldb_private::ArchSpec
    243         GetArchitecture () const
    244         {
    245             return lldb_private::ArchSpec (lldb_private::eArchTypeMachO, header.cputype, header.cpusubtype);
    246         }
    247 
    248         const Segment *
    249         FindSegment (const lldb_private::ConstString &name) const;
    250 
    251         void
    252         PutToLog (lldb_private::Log *log) const;
    253 
    254         typedef std::vector<DYLDImageInfo> collection;
    255         typedef collection::iterator iterator;
    256         typedef collection::const_iterator const_iterator;
    257     };
    258 
    259     struct DYLDAllImageInfos
    260     {
    261         uint32_t version;
    262         uint32_t dylib_info_count;              // Version >= 1
    263         lldb::addr_t dylib_info_addr;           // Version >= 1
    264         lldb::addr_t notification;              // Version >= 1
    265         bool processDetachedFromSharedRegion;   // Version >= 1
    266         bool libSystemInitialized;              // Version >= 2
    267         lldb::addr_t dyldImageLoadAddress;      // Version >= 2
    268 
    269         DYLDAllImageInfos() :
    270             version (0),
    271             dylib_info_count (0),
    272             dylib_info_addr (LLDB_INVALID_ADDRESS),
    273             notification (LLDB_INVALID_ADDRESS),
    274             processDetachedFromSharedRegion (false),
    275             libSystemInitialized (false),
    276             dyldImageLoadAddress (LLDB_INVALID_ADDRESS)
    277         {
    278         }
    279 
    280         void
    281         Clear()
    282         {
    283             version = 0;
    284             dylib_info_count = 0;
    285             dylib_info_addr = LLDB_INVALID_ADDRESS;
    286             notification = LLDB_INVALID_ADDRESS;
    287             processDetachedFromSharedRegion = false;
    288             libSystemInitialized = false;
    289             dyldImageLoadAddress = LLDB_INVALID_ADDRESS;
    290         }
    291 
    292         bool
    293         IsValid() const
    294         {
    295             return version >= 1 || version <= 6;
    296         }
    297     };
    298 
    299     void
    300     RegisterNotificationCallbacks();
    301 
    302     void
    303     UnregisterNotificationCallbacks();
    304 
    305     uint32_t
    306     ParseLoadCommands (const lldb_private::DataExtractor& data,
    307                        DYLDImageInfo& dylib_info,
    308                        lldb_private::FileSpec *lc_id_dylinker);
    309 
    310     bool
    311     UpdateImageLoadAddress(lldb_private::Module *module,
    312                            DYLDImageInfo& info);
    313 
    314     bool
    315     UnloadImageLoadAddress (lldb_private::Module *module,
    316                             DYLDImageInfo& info);
    317 
    318     lldb::ModuleSP
    319     FindTargetModuleForDYLDImageInfo (DYLDImageInfo &image_info,
    320                                       bool can_create,
    321                                       bool *did_create_ptr);
    322 
    323     DYLDImageInfo *
    324     GetImageInfo (lldb_private::Module *module);
    325 
    326     bool
    327     NeedToLocateDYLD () const;
    328 
    329     bool
    330     SetNotificationBreakpoint ();
    331 
    332     // There is a little tricky bit where you might initially attach while dyld is updating
    333     // the all_image_infos, and you can't read the infos, so you have to continue and pick it
    334     // up when you hit the update breakpoint.  At that point, you need to run this initialize
    335     // function, but when you do it that way you DON'T need to do the extra work you would at
    336     // the breakpoint.
    337     // So this function will only do actual work if the image infos haven't been read yet.
    338     // If it does do any work, then it will return true, and false otherwise.  That way you can
    339     // call it in the breakpoint action, and if it returns true you're done.
    340     bool
    341     InitializeFromAllImageInfos ();
    342 
    343     bool
    344     ReadAllImageInfosStructure ();
    345 
    346     bool
    347     AddModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count);
    348 
    349     bool
    350     AddModulesUsingImageInfos (DYLDImageInfo::collection &image_infos);
    351 
    352     bool
    353     RemoveModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count);
    354 
    355     void
    356     UpdateImageInfosHeaderAndLoadCommands(DYLDImageInfo::collection &image_infos,
    357                                           uint32_t infos_count,
    358                                           bool update_executable);
    359 
    360     bool
    361     ReadImageInfos (lldb::addr_t image_infos_addr,
    362                     uint32_t image_infos_count,
    363                     DYLDImageInfo::collection &image_infos);
    364 
    365 
    366     DYLDImageInfo m_dyld;               // Info about the current dyld being used
    367     lldb::addr_t m_dyld_all_image_infos_addr;
    368     DYLDAllImageInfos m_dyld_all_image_infos;
    369     uint32_t m_dyld_all_image_infos_stop_id;
    370     lldb::user_id_t m_break_id;
    371     DYLDImageInfo::collection m_dyld_image_infos;   // Current shared libraries information
    372     uint32_t m_dyld_image_infos_stop_id;    // The process stop ID that "m_dyld_image_infos" is valid for
    373     mutable lldb_private::Mutex m_mutex;
    374     lldb_private::Process::Notifications m_notification_callbacks;
    375     bool m_process_image_addr_is_all_images_infos;
    376 
    377 private:
    378     DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXDYLD);
    379 };
    380 
    381 #endif  // liblldb_DynamicLoaderMacOSXDYLD_h_
    382