Coverage Report

Created: 2022-01-18 06:27

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- DynamicLoaderMacOSXDYLD.cpp ---------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "DynamicLoaderMacOSXDYLD.h"
10
#include "DynamicLoaderDarwin.h"
11
#include "DynamicLoaderMacOS.h"
12
#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
13
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
14
#include "lldb/Breakpoint/StoppointCallbackContext.h"
15
#include "lldb/Core/Debugger.h"
16
#include "lldb/Core/Module.h"
17
#include "lldb/Core/ModuleSpec.h"
18
#include "lldb/Core/PluginManager.h"
19
#include "lldb/Core/Section.h"
20
#include "lldb/Symbol/Function.h"
21
#include "lldb/Symbol/ObjectFile.h"
22
#include "lldb/Target/ABI.h"
23
#include "lldb/Target/RegisterContext.h"
24
#include "lldb/Target/StackFrame.h"
25
#include "lldb/Target/Target.h"
26
#include "lldb/Target/Thread.h"
27
#include "lldb/Target/ThreadPlanRunToAddress.h"
28
#include "lldb/Utility/DataBuffer.h"
29
#include "lldb/Utility/DataBufferHeap.h"
30
#include "lldb/Utility/Log.h"
31
#include "lldb/Utility/State.h"
32
33
//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
34
#ifdef ENABLE_DEBUG_PRINTF
35
#include <cstdio>
36
#define DEBUG_PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__)
37
#else
38
#define DEBUG_PRINTF(fmt, ...)
39
#endif
40
41
#ifndef __APPLE__
42
#include "Utility/UuidCompatibility.h"
43
#else
44
#include <uuid/uuid.h>
45
#endif
46
47
using namespace lldb;
48
using namespace lldb_private;
49
50
LLDB_PLUGIN_DEFINE(DynamicLoaderMacOSXDYLD)
51
52
// Create an instance of this class. This function is filled into the plugin
53
// info class that gets handed out by the plugin factory and allows the lldb to
54
// instantiate an instance of this class.
55
DynamicLoader *DynamicLoaderMacOSXDYLD::CreateInstance(Process *process,
56
2.66k
                                                       bool force) {
57
2.66k
  bool create = force;
58
2.66k
  if (!create) {
59
2.66k
    create = true;
60
2.66k
    Module *exe_module = process->GetTarget().GetExecutableModulePointer();
61
2.66k
    if (exe_module) {
62
2.60k
      ObjectFile *object_file = exe_module->GetObjectFile();
63
2.60k
      if (object_file) {
64
2.60k
        create = (object_file->GetStrata() == ObjectFile::eStrataUser);
65
2.60k
      }
66
2.60k
    }
67
68
2.66k
    if (create) {
69
2.66k
      const llvm::Triple &triple_ref =
70
2.66k
          process->GetTarget().GetArchitecture().GetTriple();
71
2.66k
      switch (triple_ref.getOS()) {
72
0
      case llvm::Triple::Darwin:
73
2.59k
      case llvm::Triple::MacOSX:
74
2.59k
      case llvm::Triple::IOS:
75
2.59k
      case llvm::Triple::TvOS:
76
2.60k
      case llvm::Triple::WatchOS:
77
      // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS:
78
2.60k
        create = triple_ref.getVendor() == llvm::Triple::Apple;
79
2.60k
        break;
80
62
      default:
81
62
        create = false;
82
62
        break;
83
2.66k
      }
84
2.66k
    }
85
2.66k
  }
86
87
2.66k
  if (UseDYLDSPI(process)) {
88
2.59k
    create = false;
89
2.59k
  }
90
91
2.66k
  if (create)
92
9
    return new DynamicLoaderMacOSXDYLD(process);
93
2.65k
  return nullptr;
94
2.66k
}
95
96
// Constructor
97
DynamicLoaderMacOSXDYLD::DynamicLoaderMacOSXDYLD(Process *process)
98
    : DynamicLoaderDarwin(process),
99
      m_dyld_all_image_infos_addr(LLDB_INVALID_ADDRESS),
100
      m_dyld_all_image_infos(), m_dyld_all_image_infos_stop_id(UINT32_MAX),
101
      m_break_id(LLDB_INVALID_BREAK_ID), m_mutex(),
102
9
      m_process_image_addr_is_all_images_infos(false) {}
103
104
// Destructor
105
9
DynamicLoaderMacOSXDYLD::~DynamicLoaderMacOSXDYLD() {
106
9
  if (LLDB_BREAK_ID_IS_VALID(m_break_id))
107
0
    m_process->GetTarget().RemoveBreakpointByID(m_break_id);
108
9
}
109
110
0
bool DynamicLoaderMacOSXDYLD::ProcessDidExec() {
111
0
  std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
112
0
  bool did_exec = false;
113
0
  if (m_process) {
114
    // If we are stopped after an exec, we will have only one thread...
115
0
    if (m_process->GetThreadList().GetSize() == 1) {
116
      // We know if a process has exec'ed if our "m_dyld_all_image_infos_addr"
117
      // value differs from the Process' image info address. When a process
118
      // execs itself it might cause a change if ASLR is enabled.
119
0
      const addr_t shlib_addr = m_process->GetImageInfoAddress();
120
0
      if (m_process_image_addr_is_all_images_infos &&
121
0
          shlib_addr != m_dyld_all_image_infos_addr) {
122
        // The image info address from the process is the
123
        // 'dyld_all_image_infos' address and it has changed.
124
0
        did_exec = true;
125
0
      } else if (!m_process_image_addr_is_all_images_infos &&
126
0
                 shlib_addr == m_dyld.address) {
127
        // The image info address from the process is the mach_header address
128
        // for dyld and it has changed.
129
0
        did_exec = true;
130
0
      } else {
131
        // ASLR might be disabled and dyld could have ended up in the same
132
        // location. We should try and detect if we are stopped at
133
        // '_dyld_start'
134
0
        ThreadSP thread_sp(m_process->GetThreadList().GetThreadAtIndex(0));
135
0
        if (thread_sp) {
136
0
          lldb::StackFrameSP frame_sp(thread_sp->GetStackFrameAtIndex(0));
137
0
          if (frame_sp) {
138
0
            const Symbol *symbol =
139
0
                frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol;
140
0
            if (symbol) {
141
0
              if (symbol->GetName() == "_dyld_start")
142
0
                did_exec = true;
143
0
            }
144
0
          }
145
0
        }
146
0
      }
147
148
0
      if (did_exec) {
149
0
        m_libpthread_module_wp.reset();
150
0
        m_pthread_getspecific_addr.Clear();
151
0
      }
152
0
    }
153
0
  }
154
0
  return did_exec;
155
0
}
156
157
// Clear out the state of this class.
158
0
void DynamicLoaderMacOSXDYLD::DoClear() {
159
0
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
160
161
0
  if (LLDB_BREAK_ID_IS_VALID(m_break_id))
162
0
    m_process->GetTarget().RemoveBreakpointByID(m_break_id);
163
164
0
  m_dyld_all_image_infos_addr = LLDB_INVALID_ADDRESS;
165
0
  m_dyld_all_image_infos.Clear();
166
0
  m_break_id = LLDB_INVALID_BREAK_ID;
167
0
}
168
169
// Check if we have found DYLD yet
170
0
bool DynamicLoaderMacOSXDYLD::DidSetNotificationBreakpoint() {
171
0
  return LLDB_BREAK_ID_IS_VALID(m_break_id);
172
0
}
173
174
0
void DynamicLoaderMacOSXDYLD::ClearNotificationBreakpoint() {
175
0
  if (LLDB_BREAK_ID_IS_VALID(m_break_id)) {
176
0
    m_process->GetTarget().RemoveBreakpointByID(m_break_id);
177
0
  }
178
0
}
179
180
// Try and figure out where dyld is by first asking the Process if it knows
181
// (which currently calls down in the lldb::Process to get the DYLD info
182
// (available on SnowLeopard only). If that fails, then check in the default
183
// addresses.
184
9
void DynamicLoaderMacOSXDYLD::DoInitialImageFetch() {
185
9
  if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS) {
186
    // Check the image info addr as it might point to the mach header for dyld,
187
    // or it might point to the dyld_all_image_infos struct
188
9
    const addr_t shlib_addr = m_process->GetImageInfoAddress();
189
9
    if (shlib_addr != LLDB_INVALID_ADDRESS) {
190
0
      ByteOrder byte_order =
191
0
          m_process->GetTarget().GetArchitecture().GetByteOrder();
192
0
      uint8_t buf[4];
193
0
      DataExtractor data(buf, sizeof(buf), byte_order, 4);
194
0
      Status error;
195
0
      if (m_process->ReadMemory(shlib_addr, buf, 4, error) == 4) {
196
0
        lldb::offset_t offset = 0;
197
0
        uint32_t magic = data.GetU32(&offset);
198
0
        switch (magic) {
199
0
        case llvm::MachO::MH_MAGIC:
200
0
        case llvm::MachO::MH_MAGIC_64:
201
0
        case llvm::MachO::MH_CIGAM:
202
0
        case llvm::MachO::MH_CIGAM_64:
203
0
          m_process_image_addr_is_all_images_infos = false;
204
0
          ReadDYLDInfoFromMemoryAndSetNotificationCallback(shlib_addr);
205
0
          return;
206
207
0
        default:
208
0
          break;
209
0
        }
210
0
      }
211
      // Maybe it points to the all image infos?
212
0
      m_dyld_all_image_infos_addr = shlib_addr;
213
0
      m_process_image_addr_is_all_images_infos = true;
214
0
    }
215
9
  }
216
217
9
  if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) {
218
0
    if (ReadAllImageInfosStructure()) {
219
0
      if (m_dyld_all_image_infos.dyldImageLoadAddress != LLDB_INVALID_ADDRESS)
220
0
        ReadDYLDInfoFromMemoryAndSetNotificationCallback(
221
0
            m_dyld_all_image_infos.dyldImageLoadAddress);
222
0
      else
223
0
        ReadDYLDInfoFromMemoryAndSetNotificationCallback(
224
0
            m_dyld_all_image_infos_addr & 0xfffffffffff00000ull);
225
0
      return;
226
0
    }
227
0
  }
228
229
  // Check some default values
230
9
  Module *executable = m_process->GetTarget().GetExecutableModulePointer();
231
232
9
  if (executable) {
233
8
    const ArchSpec &exe_arch = executable->GetArchitecture();
234
8
    if (exe_arch.GetAddressByteSize() == 8) {
235
8
      ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x7fff5fc00000ull);
236
8
    } else 
if (0
exe_arch.GetMachine() == llvm::Triple::arm0
||
237
0
               exe_arch.GetMachine() == llvm::Triple::thumb ||
238
0
               exe_arch.GetMachine() == llvm::Triple::aarch64 ||
239
0
               exe_arch.GetMachine() == llvm::Triple::aarch64_32) {
240
0
      ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x2fe00000);
241
0
    } else {
242
0
      ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x8fe00000);
243
0
    }
244
8
  }
245
9
}
246
247
// Assume that dyld is in memory at ADDR and try to parse it's load commands
248
bool DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(
249
8
    lldb::addr_t addr) {
250
8
  std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
251
8
  DataExtractor data; // Load command data
252
8
  static ConstString g_dyld_all_image_infos("dyld_all_image_infos");
253
8
  static ConstString g_new_dyld_all_image_infos("dyld4::dyld_all_image_infos");
254
8
  if (ReadMachHeader(addr, &m_dyld.header, &data)) {
255
0
    if (m_dyld.header.filetype == llvm::MachO::MH_DYLINKER) {
256
0
      m_dyld.address = addr;
257
0
      ModuleSP dyld_module_sp;
258
0
      if (ParseLoadCommands(data, m_dyld, &m_dyld.file_spec)) {
259
0
        if (m_dyld.file_spec) {
260
0
          UpdateDYLDImageInfoFromNewImageInfo(m_dyld);
261
0
        }
262
0
      }
263
0
      dyld_module_sp = GetDYLDModule();
264
265
0
      Target &target = m_process->GetTarget();
266
267
0
      if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS &&
268
0
          dyld_module_sp.get()) {
269
0
        const Symbol *symbol = dyld_module_sp->FindFirstSymbolWithNameAndType(
270
0
            g_dyld_all_image_infos, eSymbolTypeData);
271
0
        if (!symbol) {
272
0
          symbol = dyld_module_sp->FindFirstSymbolWithNameAndType(
273
0
              g_new_dyld_all_image_infos, eSymbolTypeData);
274
0
        }
275
0
        if (symbol)
276
0
          m_dyld_all_image_infos_addr = symbol->GetLoadAddress(&target);
277
0
      }
278
279
      // Update all image infos
280
0
      InitializeFromAllImageInfos();
281
282
      // If we didn't have an executable before, but now we do, then the dyld
283
      // module shared pointer might be unique and we may need to add it again
284
      // (since Target::SetExecutableModule() will clear the images). So append
285
      // the dyld module back to the list if it is
286
      /// unique!
287
0
      if (dyld_module_sp) {
288
0
        target.GetImages().AppendIfNeeded(dyld_module_sp);
289
290
        // At this point we should have read in dyld's module, and so we should
291
        // set breakpoints in it:
292
0
        ModuleList modules;
293
0
        modules.Append(dyld_module_sp);
294
0
        target.ModulesDidLoad(modules);
295
0
        SetDYLDModule(dyld_module_sp);
296
0
      }
297
298
0
      return true;
299
0
    }
300
0
  }
301
8
  return false;
302
8
}
303
304
0
bool DynamicLoaderMacOSXDYLD::NeedToDoInitialImageFetch() {
305
0
  return m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS;
306
0
}
307
308
// Static callback function that gets called when our DYLD notification
309
// breakpoint gets hit. We update all of our image infos and then let our super
310
// class DynamicLoader class decide if we should stop or not (based on global
311
// preference).
312
bool DynamicLoaderMacOSXDYLD::NotifyBreakpointHit(
313
    void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id,
314
0
    lldb::user_id_t break_loc_id) {
315
  // Let the event know that the images have changed
316
  // DYLD passes three arguments to the notification breakpoint.
317
  // Arg1: enum dyld_image_mode mode - 0 = adding, 1 = removing Arg2: uint32_t
318
  // infoCount        - Number of shared libraries added Arg3: dyld_image_info
319
  // info[]    - Array of structs of the form:
320
  //                                     const struct mach_header
321
  //                                     *imageLoadAddress
322
  //                                     const char               *imageFilePath
323
  //                                     uintptr_t imageFileModDate (a time_t)
324
325
0
  DynamicLoaderMacOSXDYLD *dyld_instance = (DynamicLoaderMacOSXDYLD *)baton;
326
327
  // First step is to see if we've already initialized the all image infos.  If
328
  // we haven't then this function will do so and return true.  In the course
329
  // of initializing the all_image_infos it will read the complete current
330
  // state, so we don't need to figure out what has changed from the data
331
  // passed in to us.
332
333
0
  ExecutionContext exe_ctx(context->exe_ctx_ref);
334
0
  Process *process = exe_ctx.GetProcessPtr();
335
336
  // This is a sanity check just in case this dyld_instance is an old dyld
337
  // plugin's breakpoint still lying around.
338
0
  if (process != dyld_instance->m_process)
339
0
    return false;
340
341
0
  if (dyld_instance->InitializeFromAllImageInfos())
342
0
    return dyld_instance->GetStopWhenImagesChange();
343
344
0
  const lldb::ABISP &abi = process->GetABI();
345
0
  if (abi) {
346
    // Build up the value array to store the three arguments given above, then
347
    // get the values from the ABI:
348
349
0
    TypeSystemClang *clang_ast_context =
350
0
        ScratchTypeSystemClang::GetForTarget(process->GetTarget());
351
0
    if (!clang_ast_context)
352
0
      return false;
353
354
0
    ValueList argument_values;
355
0
    Value input_value;
356
357
0
    CompilerType clang_void_ptr_type =
358
0
        clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
359
0
    CompilerType clang_uint32_type =
360
0
        clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(
361
0
            lldb::eEncodingUint, 32);
362
0
    input_value.SetValueType(Value::ValueType::Scalar);
363
0
    input_value.SetCompilerType(clang_uint32_type);
364
    //        input_value.SetContext (Value::eContextTypeClangType,
365
    //        clang_uint32_type);
366
0
    argument_values.PushValue(input_value);
367
0
    argument_values.PushValue(input_value);
368
0
    input_value.SetCompilerType(clang_void_ptr_type);
369
    //        input_value.SetContext (Value::eContextTypeClangType,
370
    //        clang_void_ptr_type);
371
0
    argument_values.PushValue(input_value);
372
373
0
    if (abi->GetArgumentValues(exe_ctx.GetThreadRef(), argument_values)) {
374
0
      uint32_t dyld_mode =
375
0
          argument_values.GetValueAtIndex(0)->GetScalar().UInt(-1);
376
0
      if (dyld_mode != static_cast<uint32_t>(-1)) {
377
        // Okay the mode was right, now get the number of elements, and the
378
        // array of new elements...
379
0
        uint32_t image_infos_count =
380
0
            argument_values.GetValueAtIndex(1)->GetScalar().UInt(-1);
381
0
        if (image_infos_count != static_cast<uint32_t>(-1)) {
382
          // Got the number added, now go through the array of added elements,
383
          // putting out the mach header address, and adding the image. Note,
384
          // I'm not putting in logging here, since the AddModules &
385
          // RemoveModules functions do all the logging internally.
386
387
0
          lldb::addr_t image_infos_addr =
388
0
              argument_values.GetValueAtIndex(2)->GetScalar().ULongLong();
389
0
          if (dyld_mode == 0) {
390
            // This is add:
391
0
            dyld_instance->AddModulesUsingImageInfosAddress(image_infos_addr,
392
0
                                                            image_infos_count);
393
0
          } else {
394
            // This is remove:
395
0
            dyld_instance->RemoveModulesUsingImageInfosAddress(
396
0
                image_infos_addr, image_infos_count);
397
0
          }
398
0
        }
399
0
      }
400
0
    }
401
0
  } else {
402
0
    process->GetTarget().GetDebugger().GetAsyncErrorStream()->Printf(
403
0
        "No ABI plugin located for triple %s -- shared libraries will not be "
404
0
        "registered!\n",
405
0
        process->GetTarget().GetArchitecture().GetTriple().getTriple().c_str());
406
0
  }
407
408
  // Return true to stop the target, false to just let the target run
409
0
  return dyld_instance->GetStopWhenImagesChange();
410
0
}
411
412
0
bool DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure() {
413
0
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
414
415
  // the all image infos is already valid for this process stop ID
416
0
  if (m_process->GetStopID() == m_dyld_all_image_infos_stop_id)
417
0
    return true;
418
419
0
  m_dyld_all_image_infos.Clear();
420
0
  if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) {
421
0
    ByteOrder byte_order =
422
0
        m_process->GetTarget().GetArchitecture().GetByteOrder();
423
0
    uint32_t addr_size =
424
0
        m_process->GetTarget().GetArchitecture().GetAddressByteSize();
425
426
0
    uint8_t buf[256];
427
0
    DataExtractor data(buf, sizeof(buf), byte_order, addr_size);
428
0
    lldb::offset_t offset = 0;
429
430
0
    const size_t count_v2 = sizeof(uint32_t) + // version
431
0
                            sizeof(uint32_t) + // infoArrayCount
432
0
                            addr_size +        // infoArray
433
0
                            addr_size +        // notification
434
0
                            addr_size + // processDetachedFromSharedRegion +
435
                                        // libSystemInitialized + pad
436
0
                            addr_size;  // dyldImageLoadAddress
437
0
    const size_t count_v11 = count_v2 + addr_size +  // jitInfo
438
0
                             addr_size +             // dyldVersion
439
0
                             addr_size +             // errorMessage
440
0
                             addr_size +             // terminationFlags
441
0
                             addr_size +             // coreSymbolicationShmPage
442
0
                             addr_size +             // systemOrderFlag
443
0
                             addr_size +             // uuidArrayCount
444
0
                             addr_size +             // uuidArray
445
0
                             addr_size +             // dyldAllImageInfosAddress
446
0
                             addr_size +             // initialImageCount
447
0
                             addr_size +             // errorKind
448
0
                             addr_size +             // errorClientOfDylibPath
449
0
                             addr_size +             // errorTargetDylibPath
450
0
                             addr_size;              // errorSymbol
451
0
    const size_t count_v13 = count_v11 + addr_size + // sharedCacheSlide
452
0
                             sizeof(uuid_t);         // sharedCacheUUID
453
0
    UNUSED_IF_ASSERT_DISABLED(count_v13);
454
0
    assert(sizeof(buf) >= count_v13);
455
456
0
    Status error;
457
0
    if (m_process->ReadMemory(m_dyld_all_image_infos_addr, buf, 4, error) ==
458
0
        4) {
459
0
      m_dyld_all_image_infos.version = data.GetU32(&offset);
460
      // If anything in the high byte is set, we probably got the byte order
461
      // incorrect (the process might not have it set correctly yet due to
462
      // attaching to a program without a specified file).
463
0
      if (m_dyld_all_image_infos.version & 0xff000000) {
464
        // We have guessed the wrong byte order. Swap it and try reading the
465
        // version again.
466
0
        if (byte_order == eByteOrderLittle)
467
0
          byte_order = eByteOrderBig;
468
0
        else
469
0
          byte_order = eByteOrderLittle;
470
471
0
        data.SetByteOrder(byte_order);
472
0
        offset = 0;
473
0
        m_dyld_all_image_infos.version = data.GetU32(&offset);
474
0
      }
475
0
    } else {
476
0
      return false;
477
0
    }
478
479
0
    const size_t count =
480
0
        (m_dyld_all_image_infos.version >= 11) ? count_v11 : count_v2;
481
482
0
    const size_t bytes_read =
483
0
        m_process->ReadMemory(m_dyld_all_image_infos_addr, buf, count, error);
484
0
    if (bytes_read == count) {
485
0
      offset = 0;
486
0
      m_dyld_all_image_infos.version = data.GetU32(&offset);
487
0
      m_dyld_all_image_infos.dylib_info_count = data.GetU32(&offset);
488
0
      m_dyld_all_image_infos.dylib_info_addr = data.GetAddress(&offset);
489
0
      m_dyld_all_image_infos.notification = data.GetAddress(&offset);
490
0
      m_dyld_all_image_infos.processDetachedFromSharedRegion =
491
0
          data.GetU8(&offset);
492
0
      m_dyld_all_image_infos.libSystemInitialized = data.GetU8(&offset);
493
      // Adjust for padding.
494
0
      offset += addr_size - 2;
495
0
      m_dyld_all_image_infos.dyldImageLoadAddress = data.GetAddress(&offset);
496
0
      if (m_dyld_all_image_infos.version >= 11) {
497
0
        offset += addr_size * 8;
498
0
        uint64_t dyld_all_image_infos_addr = data.GetAddress(&offset);
499
500
        // When we started, we were given the actual address of the
501
        // all_image_infos struct (probably via TASK_DYLD_INFO) in memory -
502
        // this address is stored in m_dyld_all_image_infos_addr and is the
503
        // most accurate address we have.
504
505
        // We read the dyld_all_image_infos struct from memory; it contains its
506
        // own address. If the address in the struct does not match the actual
507
        // address, the dyld we're looking at has been loaded at a different
508
        // location (slid) from where it intended to load.  The addresses in
509
        // the dyld_all_image_infos struct are the original, non-slid
510
        // addresses, and need to be adjusted.  Most importantly the address of
511
        // dyld and the notification address need to be adjusted.
512
513
0
        if (dyld_all_image_infos_addr != m_dyld_all_image_infos_addr) {
514
0
          uint64_t image_infos_offset =
515
0
              dyld_all_image_infos_addr -
516
0
              m_dyld_all_image_infos.dyldImageLoadAddress;
517
0
          uint64_t notification_offset =
518
0
              m_dyld_all_image_infos.notification -
519
0
              m_dyld_all_image_infos.dyldImageLoadAddress;
520
0
          m_dyld_all_image_infos.dyldImageLoadAddress =
521
0
              m_dyld_all_image_infos_addr - image_infos_offset;
522
0
          m_dyld_all_image_infos.notification =
523
0
              m_dyld_all_image_infos.dyldImageLoadAddress + notification_offset;
524
0
        }
525
0
      }
526
0
      m_dyld_all_image_infos_stop_id = m_process->GetStopID();
527
0
      return true;
528
0
    }
529
0
  }
530
0
  return false;
531
0
}
532
533
bool DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfosAddress(
534
0
    lldb::addr_t image_infos_addr, uint32_t image_infos_count) {
535
0
  ImageInfo::collection image_infos;
536
0
  Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
537
0
  LLDB_LOGF(log, "Adding %d modules.\n", image_infos_count);
538
539
0
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
540
0
  std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
541
0
  if (m_process->GetStopID() == m_dyld_image_infos_stop_id)
542
0
    return true;
543
544
0
  StructuredData::ObjectSP image_infos_json_sp =
545
0
      m_process->GetLoadedDynamicLibrariesInfos(image_infos_addr,
546
0
                                                image_infos_count);
547
0
  if (image_infos_json_sp.get() && image_infos_json_sp->GetAsDictionary() &&
548
0
      image_infos_json_sp->GetAsDictionary()->HasKey("images") &&
549
0
      image_infos_json_sp->GetAsDictionary()
550
0
          ->GetValueForKey("images")
551
0
          ->GetAsArray() &&
552
0
      image_infos_json_sp->GetAsDictionary()
553
0
              ->GetValueForKey("images")
554
0
              ->GetAsArray()
555
0
              ->GetSize() == image_infos_count) {
556
0
    bool return_value = false;
557
0
    if (JSONImageInformationIntoImageInfo(image_infos_json_sp, image_infos)) {
558
0
      UpdateSpecialBinariesFromNewImageInfos(image_infos);
559
0
      return_value = AddModulesUsingImageInfos(image_infos);
560
0
    }
561
0
    m_dyld_image_infos_stop_id = m_process->GetStopID();
562
0
    return return_value;
563
0
  }
564
565
0
  if (!ReadImageInfos(image_infos_addr, image_infos_count, image_infos))
566
0
    return false;
567
568
0
  UpdateImageInfosHeaderAndLoadCommands(image_infos, image_infos_count, false);
569
0
  bool return_value = AddModulesUsingImageInfos(image_infos);
570
0
  m_dyld_image_infos_stop_id = m_process->GetStopID();
571
0
  return return_value;
572
0
}
573
574
bool DynamicLoaderMacOSXDYLD::RemoveModulesUsingImageInfosAddress(
575
0
    lldb::addr_t image_infos_addr, uint32_t image_infos_count) {
576
0
  ImageInfo::collection image_infos;
577
0
  Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
578
579
0
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
580
0
  std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
581
0
  if (m_process->GetStopID() == m_dyld_image_infos_stop_id)
582
0
    return true;
583
584
  // First read in the image_infos for the removed modules, and their headers &
585
  // load commands.
586
0
  if (!ReadImageInfos(image_infos_addr, image_infos_count, image_infos)) {
587
0
    if (log)
588
0
      log->PutCString("Failed reading image infos array.");
589
0
    return false;
590
0
  }
591
592
0
  LLDB_LOGF(log, "Removing %d modules.", image_infos_count);
593
594
0
  ModuleList unloaded_module_list;
595
0
  for (uint32_t idx = 0; idx < image_infos.size(); ++idx) {
596
0
    if (log) {
597
0
      LLDB_LOGF(log, "Removing module at address=0x%16.16" PRIx64 ".",
598
0
                image_infos[idx].address);
599
0
      image_infos[idx].PutToLog(log);
600
0
    }
601
602
    // Remove this image_infos from the m_all_image_infos.  We do the
603
    // comparison by address rather than by file spec because we can have many
604
    // modules with the same "file spec" in the case that they are modules
605
    // loaded from memory.
606
    //
607
    // Also copy over the uuid from the old entry to the removed entry so we
608
    // can use it to lookup the module in the module list.
609
610
0
    ImageInfo::collection::iterator pos, end = m_dyld_image_infos.end();
611
0
    for (pos = m_dyld_image_infos.begin(); pos != end; pos++) {
612
0
      if (image_infos[idx].address == (*pos).address) {
613
0
        image_infos[idx].uuid = (*pos).uuid;
614
615
        // Add the module from this image_info to the "unloaded_module_list".
616
        // We'll remove them all at one go later on.
617
618
0
        ModuleSP unload_image_module_sp(
619
0
            FindTargetModuleForImageInfo(image_infos[idx], false, nullptr));
620
0
        if (unload_image_module_sp.get()) {
621
          // When we unload, be sure to use the image info from the old list,
622
          // since that has sections correctly filled in.
623
0
          UnloadModuleSections(unload_image_module_sp.get(), *pos);
624
0
          unloaded_module_list.AppendIfNeeded(unload_image_module_sp);
625
0
        } else {
626
0
          if (log) {
627
0
            LLDB_LOGF(log, "Could not find module for unloading info entry:");
628
0
            image_infos[idx].PutToLog(log);
629
0
          }
630
0
        }
631
632
        // Then remove it from the m_dyld_image_infos:
633
634
0
        m_dyld_image_infos.erase(pos);
635
0
        break;
636
0
      }
637
0
    }
638
639
0
    if (pos == end) {
640
0
      if (log) {
641
0
        LLDB_LOGF(log, "Could not find image_info entry for unloading image:");
642
0
        image_infos[idx].PutToLog(log);
643
0
      }
644
0
    }
645
0
  }
646
0
  if (unloaded_module_list.GetSize() > 0) {
647
0
    if (log) {
648
0
      log->PutCString("Unloaded:");
649
0
      unloaded_module_list.LogUUIDAndPaths(
650
0
          log, "DynamicLoaderMacOSXDYLD::ModulesDidUnload");
651
0
    }
652
0
    m_process->GetTarget().GetImages().Remove(unloaded_module_list);
653
0
  }
654
0
  m_dyld_image_infos_stop_id = m_process->GetStopID();
655
0
  return true;
656
0
}
657
658
bool DynamicLoaderMacOSXDYLD::ReadImageInfos(
659
    lldb::addr_t image_infos_addr, uint32_t image_infos_count,
660
0
    ImageInfo::collection &image_infos) {
661
0
  std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
662
0
  const ByteOrder endian = GetByteOrderFromMagic(m_dyld.header.magic);
663
0
  const uint32_t addr_size = m_dyld.GetAddressByteSize();
664
665
0
  image_infos.resize(image_infos_count);
666
0
  const size_t count = image_infos.size() * 3 * addr_size;
667
0
  DataBufferHeap info_data(count, 0);
668
0
  Status error;
669
0
  const size_t bytes_read = m_process->ReadMemory(
670
0
      image_infos_addr, info_data.GetBytes(), info_data.GetByteSize(), error);
671
0
  if (bytes_read == count) {
672
0
    lldb::offset_t info_data_offset = 0;
673
0
    DataExtractor info_data_ref(info_data.GetBytes(), info_data.GetByteSize(),
674
0
                                endian, addr_size);
675
0
    for (size_t i = 0;
676
0
         i < image_infos.size() && info_data_ref.ValidOffset(info_data_offset);
677
0
         i++) {
678
0
      image_infos[i].address = info_data_ref.GetAddress(&info_data_offset);
679
0
      lldb::addr_t path_addr = info_data_ref.GetAddress(&info_data_offset);
680
0
      image_infos[i].mod_date = info_data_ref.GetAddress(&info_data_offset);
681
682
0
      char raw_path[PATH_MAX];
683
0
      m_process->ReadCStringFromMemory(path_addr, raw_path, sizeof(raw_path),
684
0
                                       error);
685
      // don't resolve the path
686
0
      if (error.Success()) {
687
0
        image_infos[i].file_spec.SetFile(raw_path, FileSpec::Style::native);
688
0
      }
689
0
    }
690
0
    return true;
691
0
  } else {
692
0
    return false;
693
0
  }
694
0
}
695
696
// If we have found where the "_dyld_all_image_infos" lives in memory, read the
697
// current info from it, and then update all image load addresses (or lack
698
// thereof).  Only do this if this is the first time we're reading the dyld
699
// infos.  Return true if we actually read anything, and false otherwise.
700
0
bool DynamicLoaderMacOSXDYLD::InitializeFromAllImageInfos() {
701
0
  Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
702
703
0
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
704
0
  std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
705
0
  if (m_process->GetStopID() == m_dyld_image_infos_stop_id ||
706
0
      m_dyld_image_infos.size() != 0)
707
0
    return false;
708
709
0
  if (ReadAllImageInfosStructure()) {
710
    // Nothing to load or unload?
711
0
    if (m_dyld_all_image_infos.dylib_info_count == 0)
712
0
      return true;
713
714
0
    if (m_dyld_all_image_infos.dylib_info_addr == 0) {
715
      // DYLD is updating the images now.  So we should say we have no images,
716
      // and then we'll
717
      // figure it out when we hit the added breakpoint.
718
0
      return false;
719
0
    } else {
720
0
      if (!AddModulesUsingImageInfosAddress(
721
0
              m_dyld_all_image_infos.dylib_info_addr,
722
0
              m_dyld_all_image_infos.dylib_info_count)) {
723
0
        DEBUG_PRINTF("%s", "unable to read all data for all_dylib_infos.");
724
0
        m_dyld_image_infos.clear();
725
0
      }
726
0
    }
727
728
    // Now we have one more bit of business.  If there is a library left in the
729
    // images for our target that doesn't have a load address, then it must be
730
    // something that we were expecting to load (for instance we read a load
731
    // command for it) but it didn't in fact load - probably because
732
    // DYLD_*_PATH pointed to an equivalent version.  We don't want it to stay
733
    // in the target's module list or it will confuse us, so unload it here.
734
0
    Target &target = m_process->GetTarget();
735
0
    ModuleList not_loaded_modules;
736
0
    for (ModuleSP module_sp : target.GetImages().Modules()) {
737
0
      if (!module_sp->IsLoadedInTarget(&target)) {
738
0
        if (log) {
739
0
          StreamString s;
740
0
          module_sp->GetDescription(s.AsRawOstream());
741
0
          LLDB_LOGF(log, "Unloading pre-run module: %s.", s.GetData());
742
0
        }
743
0
        not_loaded_modules.Append(module_sp);
744
0
      }
745
0
    }
746
747
0
    if (not_loaded_modules.GetSize() != 0) {
748
0
      target.GetImages().Remove(not_loaded_modules);
749
0
    }
750
751
0
    return true;
752
0
  } else
753
0
    return false;
754
0
}
755
756
// Read a mach_header at ADDR into HEADER, and also fill in the load command
757
// data into LOAD_COMMAND_DATA if it is non-NULL.
758
//
759
// Returns true if we succeed, false if we fail for any reason.
760
bool DynamicLoaderMacOSXDYLD::ReadMachHeader(lldb::addr_t addr,
761
                                             llvm::MachO::mach_header *header,
762
8
                                             DataExtractor *load_command_data) {
763
8
  DataBufferHeap header_bytes(sizeof(llvm::MachO::mach_header), 0);
764
8
  Status error;
765
8
  size_t bytes_read = m_process->ReadMemory(addr, header_bytes.GetBytes(),
766
8
                                            header_bytes.GetByteSize(), error);
767
8
  if (bytes_read == sizeof(llvm::MachO::mach_header)) {
768
8
    lldb::offset_t offset = 0;
769
8
    ::memset(header, 0, sizeof(llvm::MachO::mach_header));
770
771
    // Get the magic byte unswapped so we can figure out what we are dealing
772
    // with
773
8
    DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(),
774
8
                       endian::InlHostByteOrder(), 4);
775
8
    header->magic = data.GetU32(&offset);
776
8
    lldb::addr_t load_cmd_addr = addr;
777
8
    data.SetByteOrder(
778
8
        DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(header->magic));
779
8
    switch (header->magic) {
780
0
    case llvm::MachO::MH_MAGIC:
781
0
    case llvm::MachO::MH_CIGAM:
782
0
      data.SetAddressByteSize(4);
783
0
      load_cmd_addr += sizeof(llvm::MachO::mach_header);
784
0
      break;
785
786
0
    case llvm::MachO::MH_MAGIC_64:
787
0
    case llvm::MachO::MH_CIGAM_64:
788
0
      data.SetAddressByteSize(8);
789
0
      load_cmd_addr += sizeof(llvm::MachO::mach_header_64);
790
0
      break;
791
792
8
    default:
793
8
      return false;
794
8
    }
795
796
    // Read the rest of dyld's mach header
797
0
    if (data.GetU32(&offset, &header->cputype,
798
0
                    (sizeof(llvm::MachO::mach_header) / sizeof(uint32_t)) -
799
0
                        1)) {
800
0
      if (load_command_data == nullptr)
801
0
        return true; // We were able to read the mach_header and weren't asked
802
                     // to read the load command bytes
803
804
0
      DataBufferSP load_cmd_data_sp(new DataBufferHeap(header->sizeofcmds, 0));
805
806
0
      size_t load_cmd_bytes_read =
807
0
          m_process->ReadMemory(load_cmd_addr, load_cmd_data_sp->GetBytes(),
808
0
                                load_cmd_data_sp->GetByteSize(), error);
809
810
0
      if (load_cmd_bytes_read == header->sizeofcmds) {
811
        // Set the load command data and also set the correct endian swap
812
        // settings and the correct address size
813
0
        load_command_data->SetData(load_cmd_data_sp, 0, header->sizeofcmds);
814
0
        load_command_data->SetByteOrder(data.GetByteOrder());
815
0
        load_command_data->SetAddressByteSize(data.GetAddressByteSize());
816
0
        return true; // We successfully read the mach_header and the load
817
                     // command data
818
0
      }
819
820
0
      return false; // We weren't able to read the load command data
821
0
    }
822
0
  }
823
0
  return false; // We failed the read the mach_header
824
8
}
825
826
// Parse the load commands for an image
827
uint32_t DynamicLoaderMacOSXDYLD::ParseLoadCommands(const DataExtractor &data,
828
                                                    ImageInfo &dylib_info,
829
0
                                                    FileSpec *lc_id_dylinker) {
830
0
  lldb::offset_t offset = 0;
831
0
  uint32_t cmd_idx;
832
0
  Segment segment;
833
0
  dylib_info.Clear(true);
834
835
0
  for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++) {
836
    // Clear out any load command specific data from DYLIB_INFO since we are
837
    // about to read it.
838
839
0
    if (data.ValidOffsetForDataOfSize(offset,
840
0
                                      sizeof(llvm::MachO::load_command))) {
841
0
      llvm::MachO::load_command load_cmd;
842
0
      lldb::offset_t load_cmd_offset = offset;
843
0
      load_cmd.cmd = data.GetU32(&offset);
844
0
      load_cmd.cmdsize = data.GetU32(&offset);
845
0
      switch (load_cmd.cmd) {
846
0
      case llvm::MachO::LC_SEGMENT: {
847
0
        segment.name.SetTrimmedCStringWithLength(
848
0
            (const char *)data.GetData(&offset, 16), 16);
849
        // We are putting 4 uint32_t values 4 uint64_t values so we have to use
850
        // multiple 32 bit gets below.
851
0
        segment.vmaddr = data.GetU32(&offset);
852
0
        segment.vmsize = data.GetU32(&offset);
853
0
        segment.fileoff = data.GetU32(&offset);
854
0
        segment.filesize = data.GetU32(&offset);
855
        // Extract maxprot, initprot, nsects and flags all at once
856
0
        data.GetU32(&offset, &segment.maxprot, 4);
857
0
        dylib_info.segments.push_back(segment);
858
0
      } break;
859
860
0
      case llvm::MachO::LC_SEGMENT_64: {
861
0
        segment.name.SetTrimmedCStringWithLength(
862
0
            (const char *)data.GetData(&offset, 16), 16);
863
        // Extract vmaddr, vmsize, fileoff, and filesize all at once
864
0
        data.GetU64(&offset, &segment.vmaddr, 4);
865
        // Extract maxprot, initprot, nsects and flags all at once
866
0
        data.GetU32(&offset, &segment.maxprot, 4);
867
0
        dylib_info.segments.push_back(segment);
868
0
      } break;
869
870
0
      case llvm::MachO::LC_ID_DYLINKER:
871
0
        if (lc_id_dylinker) {
872
0
          const lldb::offset_t name_offset =
873
0
              load_cmd_offset + data.GetU32(&offset);
874
0
          const char *path = data.PeekCStr(name_offset);
875
0
          lc_id_dylinker->SetFile(path, FileSpec::Style::native);
876
0
          FileSystem::Instance().Resolve(*lc_id_dylinker);
877
0
        }
878
0
        break;
879
880
0
      case llvm::MachO::LC_UUID:
881
0
        dylib_info.uuid = UUID::fromOptionalData(data.GetData(&offset, 16), 16);
882
0
        break;
883
884
0
      default:
885
0
        break;
886
0
      }
887
      // Set offset to be the beginning of the next load command.
888
0
      offset = load_cmd_offset + load_cmd.cmdsize;
889
0
    }
890
0
  }
891
892
  // All sections listed in the dyld image info structure will all either be
893
  // fixed up already, or they will all be off by a single slide amount that is
894
  // determined by finding the first segment that is at file offset zero which
895
  // also has bytes (a file size that is greater than zero) in the object file.
896
897
  // Determine the slide amount (if any)
898
0
  const size_t num_sections = dylib_info.segments.size();
899
0
  for (size_t i = 0; i < num_sections; ++i) {
900
    // Iterate through the object file sections to find the first section that
901
    // starts of file offset zero and that has bytes in the file...
902
0
    if ((dylib_info.segments[i].fileoff == 0 &&
903
0
         dylib_info.segments[i].filesize > 0) ||
904
0
        (dylib_info.segments[i].name == "__TEXT")) {
905
0
      dylib_info.slide = dylib_info.address - dylib_info.segments[i].vmaddr;
906
      // We have found the slide amount, so we can exit this for loop.
907
0
      break;
908
0
    }
909
0
  }
910
0
  return cmd_idx;
911
0
}
912
913
// Read the mach_header and load commands for each image that the
914
// _dyld_all_image_infos structure points to and cache the results.
915
916
void DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands(
917
    ImageInfo::collection &image_infos, uint32_t infos_count,
918
0
    bool update_executable) {
919
0
  uint32_t exe_idx = UINT32_MAX;
920
  // Read any UUID values that we can get
921
0
  for (uint32_t i = 0; i < infos_count; i++) {
922
0
    if (!image_infos[i].UUIDValid()) {
923
0
      DataExtractor data; // Load command data
924
0
      if (!ReadMachHeader(image_infos[i].address, &image_infos[i].header,
925
0
                          &data))
926
0
        continue;
927
928
0
      ParseLoadCommands(data, image_infos[i], nullptr);
929
930
0
      if (image_infos[i].header.filetype == llvm::MachO::MH_EXECUTE)
931
0
        exe_idx = i;
932
0
    }
933
0
  }
934
935
0
  Target &target = m_process->GetTarget();
936
937
0
  if (exe_idx < image_infos.size()) {
938
0
    const bool can_create = true;
939
0
    ModuleSP exe_module_sp(FindTargetModuleForImageInfo(image_infos[exe_idx],
940
0
                                                        can_create, nullptr));
941
942
0
    if (exe_module_sp) {
943
0
      UpdateImageLoadAddress(exe_module_sp.get(), image_infos[exe_idx]);
944
945
0
      if (exe_module_sp.get() != target.GetExecutableModulePointer()) {
946
        // Don't load dependent images since we are in dyld where we will know
947
        // and find out about all images that are loaded. Also when setting the
948
        // executable module, it will clear the targets module list, and if we
949
        // have an in memory dyld module, it will get removed from the list so
950
        // we will need to add it back after setting the executable module, so
951
        // we first try and see if we already have a weak pointer to the dyld
952
        // module, make it into a shared pointer, then add the executable, then
953
        // re-add it back to make sure it is always in the list.
954
0
        ModuleSP dyld_module_sp(GetDYLDModule());
955
956
0
        m_process->GetTarget().SetExecutableModule(exe_module_sp,
957
0
                                                   eLoadDependentsNo);
958
959
0
        if (dyld_module_sp) {
960
0
          if (target.GetImages().AppendIfNeeded(dyld_module_sp)) {
961
0
            std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
962
963
            // Also add it to the section list.
964
0
            UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld);
965
0
          }
966
0
        }
967
0
      }
968
0
    }
969
0
  }
970
0
}
971
972
// Dump the _dyld_all_image_infos members and all current image infos that we
973
// have parsed to the file handle provided.
974
0
void DynamicLoaderMacOSXDYLD::PutToLog(Log *log) const {
975
0
  if (log == nullptr)
976
0
    return;
977
978
0
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
979
0
  std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
980
0
  LLDB_LOGF(log,
981
0
            "dyld_all_image_infos = { version=%d, count=%d, addr=0x%8.8" PRIx64
982
0
            ", notify=0x%8.8" PRIx64 " }",
983
0
            m_dyld_all_image_infos.version,
984
0
            m_dyld_all_image_infos.dylib_info_count,
985
0
            (uint64_t)m_dyld_all_image_infos.dylib_info_addr,
986
0
            (uint64_t)m_dyld_all_image_infos.notification);
987
0
  size_t i;
988
0
  const size_t count = m_dyld_image_infos.size();
989
0
  if (count > 0) {
990
0
    log->PutCString("Loaded:");
991
0
    for (i = 0; i < count; i++)
992
0
      m_dyld_image_infos[i].PutToLog(log);
993
0
  }
994
0
}
995
996
9
bool DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint() {
997
9
  DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n",
998
9
               __FUNCTION__, StateAsCString(m_process->GetState()));
999
9
  if (m_break_id == LLDB_INVALID_BREAK_ID) {
1000
9
    if (m_dyld_all_image_infos.notification != LLDB_INVALID_ADDRESS) {
1001
0
      Address so_addr;
1002
      // Set the notification breakpoint and install a breakpoint callback
1003
      // function that will get called each time the breakpoint gets hit. We
1004
      // will use this to track when shared libraries get loaded/unloaded.
1005
0
      bool resolved = m_process->GetTarget().ResolveLoadAddress(
1006
0
          m_dyld_all_image_infos.notification, so_addr);
1007
0
      if (!resolved) {
1008
0
        ModuleSP dyld_module_sp = GetDYLDModule();
1009
0
        if (dyld_module_sp) {
1010
0
          std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
1011
1012
0
          UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld);
1013
0
          resolved = m_process->GetTarget().ResolveLoadAddress(
1014
0
              m_dyld_all_image_infos.notification, so_addr);
1015
0
        }
1016
0
      }
1017
1018
0
      if (resolved) {
1019
0
        Breakpoint *dyld_break =
1020
0
            m_process->GetTarget().CreateBreakpoint(so_addr, true, false).get();
1021
0
        dyld_break->SetCallback(DynamicLoaderMacOSXDYLD::NotifyBreakpointHit,
1022
0
                                this, true);
1023
0
        dyld_break->SetBreakpointKind("shared-library-event");
1024
0
        m_break_id = dyld_break->GetID();
1025
0
      }
1026
0
    }
1027
9
  }
1028
9
  return m_break_id != LLDB_INVALID_BREAK_ID;
1029
9
}
1030
1031
0
Status DynamicLoaderMacOSXDYLD::CanLoadImage() {
1032
0
  Status error;
1033
  // In order for us to tell if we can load a shared library we verify that the
1034
  // dylib_info_addr isn't zero (which means no shared libraries have been set
1035
  // yet, or dyld is currently mucking with the shared library list).
1036
0
  if (ReadAllImageInfosStructure()) {
1037
    // TODO: also check the _dyld_global_lock_held variable in
1038
    // libSystem.B.dylib?
1039
    // TODO: check the malloc lock?
1040
    // TODO: check the objective C lock?
1041
0
    if (m_dyld_all_image_infos.dylib_info_addr != 0)
1042
0
      return error; // Success
1043
0
  }
1044
1045
0
  error.SetErrorString("unsafe to load or unload shared libraries");
1046
0
  return error;
1047
0
}
1048
1049
bool DynamicLoaderMacOSXDYLD::GetSharedCacheInformation(
1050
    lldb::addr_t &base_address, UUID &uuid, LazyBool &using_shared_cache,
1051
0
    LazyBool &private_shared_cache) {
1052
0
  base_address = LLDB_INVALID_ADDRESS;
1053
0
  uuid.Clear();
1054
0
  using_shared_cache = eLazyBoolCalculate;
1055
0
  private_shared_cache = eLazyBoolCalculate;
1056
1057
0
  if (m_process) {
1058
0
    addr_t all_image_infos = m_process->GetImageInfoAddress();
1059
1060
    // The address returned by GetImageInfoAddress may be the address of dyld
1061
    // (don't want) or it may be the address of the dyld_all_image_infos
1062
    // structure (want). The first four bytes will be either the version field
1063
    // (all_image_infos) or a Mach-O file magic constant. Version 13 and higher
1064
    // of dyld_all_image_infos is required to get the sharedCacheUUID field.
1065
1066
0
    Status err;
1067
0
    uint32_t version_or_magic =
1068
0
        m_process->ReadUnsignedIntegerFromMemory(all_image_infos, 4, -1, err);
1069
0
    if (version_or_magic != static_cast<uint32_t>(-1) &&
1070
0
        version_or_magic != llvm::MachO::MH_MAGIC &&
1071
0
        version_or_magic != llvm::MachO::MH_CIGAM &&
1072
0
        version_or_magic != llvm::MachO::MH_MAGIC_64 &&
1073
0
        version_or_magic != llvm::MachO::MH_CIGAM_64 &&
1074
0
        version_or_magic >= 13) {
1075
0
      addr_t sharedCacheUUID_address = LLDB_INVALID_ADDRESS;
1076
0
      int wordsize = m_process->GetAddressByteSize();
1077
0
      if (wordsize == 8) {
1078
0
        sharedCacheUUID_address =
1079
0
            all_image_infos + 160; // sharedCacheUUID <mach-o/dyld_images.h>
1080
0
      }
1081
0
      if (wordsize == 4) {
1082
0
        sharedCacheUUID_address =
1083
0
            all_image_infos + 84; // sharedCacheUUID <mach-o/dyld_images.h>
1084
0
      }
1085
0
      if (sharedCacheUUID_address != LLDB_INVALID_ADDRESS) {
1086
0
        uuid_t shared_cache_uuid;
1087
0
        if (m_process->ReadMemory(sharedCacheUUID_address, shared_cache_uuid,
1088
0
                                  sizeof(uuid_t), err) == sizeof(uuid_t)) {
1089
0
          uuid = UUID::fromOptionalData(shared_cache_uuid, 16);
1090
0
          if (uuid.IsValid()) {
1091
0
            using_shared_cache = eLazyBoolYes;
1092
0
          }
1093
0
        }
1094
1095
0
        if (version_or_magic >= 15) {
1096
          // The sharedCacheBaseAddress field is the next one in the
1097
          // dyld_all_image_infos struct.
1098
0
          addr_t sharedCacheBaseAddr_address = sharedCacheUUID_address + 16;
1099
0
          Status error;
1100
0
          base_address = m_process->ReadUnsignedIntegerFromMemory(
1101
0
              sharedCacheBaseAddr_address, wordsize, LLDB_INVALID_ADDRESS,
1102
0
              error);
1103
0
          if (error.Fail())
1104
0
            base_address = LLDB_INVALID_ADDRESS;
1105
0
        }
1106
1107
0
        return true;
1108
0
      }
1109
1110
      //
1111
      // add
1112
      // NB: sharedCacheBaseAddress is the next field in dyld_all_image_infos
1113
      // after
1114
      // sharedCacheUUID -- that is, 16 bytes after it, if we wanted to fetch
1115
      // it.
1116
0
    }
1117
0
  }
1118
0
  return false;
1119
0
}
1120
1121
0
bool DynamicLoaderMacOSXDYLD::IsFullyInitialized() {
1122
0
  if (ReadAllImageInfosStructure())
1123
0
    return m_dyld_all_image_infos.libSystemInitialized;
1124
0
  return false;
1125
0
}
1126
1127
3.44k
void DynamicLoaderMacOSXDYLD::Initialize() {
1128
3.44k
  PluginManager::RegisterPlugin(GetPluginNameStatic(),
1129
3.44k
                                GetPluginDescriptionStatic(), CreateInstance);
1130
3.44k
  DynamicLoaderMacOS::Initialize();
1131
3.44k
}
1132
1133
3.43k
void DynamicLoaderMacOSXDYLD::Terminate() {
1134
3.43k
  DynamicLoaderMacOS::Terminate();
1135
3.43k
  PluginManager::UnregisterPlugin(CreateInstance);
1136
3.43k
}
1137
1138
3.44k
llvm::StringRef DynamicLoaderMacOSXDYLD::GetPluginDescriptionStatic() {
1139
3.44k
  return "Dynamic loader plug-in that watches for shared library loads/unloads "
1140
3.44k
         "in MacOSX user processes.";
1141
3.44k
}
1142
1143
0
uint32_t DynamicLoaderMacOSXDYLD::AddrByteSize() {
1144
0
  std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
1145
1146
0
  switch (m_dyld.header.magic) {
1147
0
  case llvm::MachO::MH_MAGIC:
1148
0
  case llvm::MachO::MH_CIGAM:
1149
0
    return 4;
1150
1151
0
  case llvm::MachO::MH_MAGIC_64:
1152
0
  case llvm::MachO::MH_CIGAM_64:
1153
0
    return 8;
1154
1155
0
  default:
1156
0
    break;
1157
0
  }
1158
0
  return 0;
1159
0
}
1160
1161
8
lldb::ByteOrder DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(uint32_t magic) {
1162
8
  switch (magic) {
1163
0
  case llvm::MachO::MH_MAGIC:
1164
0
  case llvm::MachO::MH_MAGIC_64:
1165
0
    return endian::InlHostByteOrder();
1166
1167
0
  case llvm::MachO::MH_CIGAM:
1168
0
  case llvm::MachO::MH_CIGAM_64:
1169
0
    if (endian::InlHostByteOrder() == lldb::eByteOrderBig)
1170
0
      return lldb::eByteOrderLittle;
1171
0
    else
1172
0
      return lldb::eByteOrderBig;
1173
1174
8
  default:
1175
8
    break;
1176
8
  }
1177
8
  return lldb::eByteOrderInvalid;
1178
8
}