dyld启动加载过程,笔记

启动过程调用堆栈是这个样子:

  * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 5.1
  * frame #0: 0x0000000104c0acd4 Xman_New`___lldb_unnamed_symbol191473$$Xman_New
    frame #1: 0x0000000237695ffc libobjc.A.dylib`call_load_methods +
    frame #2: 0x0000000237697e54 libobjc.A.dylib`load_images + 180
    frame #3: 0x000000010544e390 dyld`dyld::notifySingle(dyld_image_states, ImageLoader const*, ImageLoader::InitializerTimingList*) + 444
    frame #4: 0x0000000105460380 dyld`ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 440
    frame #5: 0x000000010545f3dc dyld`ImageLoader::processInitializers(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 136
    frame #6: 0x000000010545f498 dyld`ImageLoader::runInitializers(ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&) + 84
    frame #7: 0x000000010544e6d8 dyld`dyld::initializeMainExecutable() + 220
    frame #8: 0x00000001054532a0 dyld`dyld::_main(macho_header const*, unsigned long, int, char const**, char const**, char const**, unsigned long*) + 4304
    frame #9: 0x000000010544d044 dyld`_dyld_start + 68

这里有点注意就是网上很多资料写的不具体的一点是函数notifySingle中调用load_images函数,并执行完成+load函数和其他初始化函数。

    (还有在ImageLoaderMachO::doInitialization中的doImageInit和doModInitFunctions,完成初始化函数调用和dyld`dyld::notifySingle中完成的初始化函数调用之间是什么关系,还没有捋顺。)

在调用 load_images -> load_images_nolock -> prepare_load_methods -> schedule_class_load -> add_class_to_loadable_list 的时候会将未加载的类添加到 loadable_classes 数组中

其中prepare_load_methods中调用

objc_class *__fastcall prepare_load_methods(const mach_header_64 *a1)
{
  const mach_header_64 *v1; // x19
  __int64 v2; // x0
  __int64 v3; // x20
  unsigned __int64 v4; // x21
  objc_class *v5; // x0
  objc_class *result; // x0
  objc_class *v7; // x19
  unsigned __int64 v8; // x21
  __int64 v9; // x20
  __int64 v10; // x0
  unsigned __int64 v11; // [xsp+8h] [xbp-28h]

  v1 = a1;
  v2 = _getObjc2NonlazyClassList(a1, &v11);     // 得到Nolazy列表+load数量
  if ( v11 )
  {
    v3 = v2;
    v4 = 0LL;
    do
    {
      v5 = remapClass(*(objc_class **)(v3 + 8 * v4));// 0x10a006160是列表
      schedule_class_load((__int64)v5);
      ++v4;
    }
    while ( v4 < v11 );
  }
  result = (objc_class *)_getObjc2NonlazyCategoryList(v1, &v11);
  if ( v11 )
  {
    v7 = result;
    v8 = 0LL;
    do
    {
      v9 = *((_QWORD *)v7 + v8);
      result = remapClass(*(objc_class **)(v9 + 8));
      if ( result )
      {
        if ( *((_BYTE *)result + 32) & 2 )
        {
          v10 = _objc_fatal("Swift class extensions and categories on Swift classes are not allowed to have +load methods");
          unmap_image(v10);
        }
        realizeClassWithoutSwift(result);
        result = (objc_class *)add_category_to_loadable_list(v9);
      }
      ++v8;
    }
    while ( v8 < v11 );
  }
  return result;
}

  v2 = _getObjc2NonlazyClassList(a1, &v11);     // 得到Nolazy列表+load数量

  _getObjc2NonlazyClassList就读取是在MachO文件中的DATA,__objc_nlclslist中的内容,v11要初始化类的+load函数数量;v2是__objc_nlclslist实际内存地址。

  在调用_getObjc2NonlazyClassList之后,调用v5 = remapClass(*(objc_class **)(v3 + 8 * v4));函数,其中v3=v2,这里就是从__objc_nlclslist中读取函数指针

     在remapClass之后调用schedule_class_load就是将上面的v5添加到列表当中,汇编里就是一个内存地址。

__int64 __fastcall schedule_class_load(__int64 result)
{
  objc_class *v1; // x19
  unsigned int *v2; // x9
  unsigned int *v3; // x8
  unsigned int v4; // off

  if ( result )
  {
    v1 = (objc_class *)result;
    if ( !(*(_BYTE *)((*(_QWORD *)(result + 0x20) & 0x7FFFFFFFFFF8LL) + 2) & 0x80) )// x+0x20是类bits变量,这一步应该是判断是否为元类
                                                // cls->data()->flags & RW_LOADED
    {
      schedule_class_load(*(_QWORD *)(result + 8));// +8是supperclass 
                                                // schedule_class_load(cls->superclass);
      result = add_class_to_loadable_list(v1);
      v3 = (unsigned int *)(*((_QWORD *)v1 + 4) & 0x7FFFFFFFFFF8LL);
      do
      {
        v4 = __ldaxr(v2);
        v2 = (unsigned int *)((unsigned int)v2 | 0x800000);
      }
      while ( __stlxr((unsigned int)v2, v3) );
    }
  }
  return result;
}

//传入参数实际是类内存地址。result + 0x20是oc类结构中的 class_rw_t *bits。

(*(_BYTE *)((*(_QWORD *)(result + 0x20) & 0x7FFFFFFFFFF8LL) + 2) & 0x80) 这一句意思cls->data()->flags & RW_LOADED进行判断。判断是否为元类且是否为RW_LOADED

在add_class_to_loadable_list(v1);将方法添加到+load函数列表当中即loadable_classes当中。loadable_classes是全局变量,吐槽下,全局变量怎么不作为入口参数传入那!

在回到prepare_load_methods函数中下一步就是对_getObjc2NonlazyCategoryList,这部分初始化函数进行加载了。这部分是对MachO中的DATA,__objc_nlcatlist进行加载,具体没仔细看,这里不讨论。

然后返回到load_images中下一步开始执行call_load_methods();这里就开始执行列表中的所有+load函数了。

初始化函数ImageLoaderMachO::doModInitFunctions

__int64 __fastcall ImageLoaderMachO::doModInitFunctions(__int64 result, __int64 a2)
{
  __int64 v2; // x22
  unsigned __int64 v3; // x23
  __int64 (__fastcall *v4)(_QWORD, _QWORD, _QWORD, _QWORD, _QWORD); // x24
  __int64 v5; // x25
  void *v6; // x26
  __int64 v7; // x30
  _QWORD *v8; // x19
  __int64 v9; // x8
  __int64 v10; // x20
  int v11; // w9
  _DWORD *v12; // x10
  __int64 v13; // x21
  unsigned __int64 v14; // x27
  unsigned __int64 v15; // x8
  unsigned __int64 v16; // x10
  unsigned __int64 v17; // x9
  __int64 v18; // x0
  __int64 v19; // x8
  __int64 v20; // x8
  __int64 v21; // x8
  __int64 v22; // x0
  __int64 v23; // x2
  _QWORD *v24; // x19
  __int64 v25; // x8
  unsigned int v26; // w21
  __int64 v27; // x20
  unsigned int v28; // w22
  signed __int64 v29; // x23
  unsigned __int64 v30; // x25
  unsigned __int64 v31; // x26
  unsigned __int64 v32; // x8
  unsigned __int64 v33; // x9
  __int64 v34; // x10
  unsigned __int8 v35; // cf
  unsigned __int64 v36; // x10
  __int64 v37; // x8
  __int128 v38; // q0
  __int64 v39; // ST20_8
  __int64 v40; // x0
  __int64 v41; // x1
  __int128 v42; // [xsp+28h] [xbp-158h]
  __int64 v43; // [xsp+38h] [xbp-148h]
  void *v44; // [xsp+40h] [xbp-140h]
  __int64 v45; // [xsp+48h] [xbp-138h]
  __int64 (__fastcall *v46)(_QWORD, _QWORD, _QWORD, _QWORD, _QWORD); // [xsp+50h] [xbp-130h]
  unsigned __int64 v47; // [xsp+58h] [xbp-128h]
  __int64 v48; // [xsp+60h] [xbp-120h]
  __int64 v49; // [xsp+68h] [xbp-118h]
  __int64 v50; // [xsp+70h] [xbp-110h]
  _QWORD *v51; // [xsp+78h] [xbp-108h]
  __int64 *v52; // [xsp+80h] [xbp-100h]
  __int64 v53; // [xsp+88h] [xbp-F8h]
  __int64 (__fastcall *v54)(_QWORD, _QWORD, _QWORD, _QWORD, _QWORD); // [xsp+90h] [xbp-F0h]
  __int64 v55; // [xsp+98h] [xbp-E8h]
  unsigned int v56; // [xsp+A0h] [xbp-E0h]
  int v57; // [xsp+A4h] [xbp-DCh]
  _DWORD *v58; // [xsp+A8h] [xbp-D8h]
  unsigned __int64 v59; // [xsp+B0h] [xbp-D0h]
  int v60; // [xsp+B8h] [xbp-C8h]
  __int64 v61; // [xsp+C0h] [xbp-C0h]
  __int64 v62; // [xsp+C8h] [xbp-B8h]
  __int64 (__fastcall *v63)(_QWORD, _QWORD, _QWORD, _QWORD, _QWORD); // [xsp+D0h] [xbp-B0h]
  __int128 v64; // [xsp+D8h] [xbp-A8h]
  __int128 v65; // [xsp+E8h] [xbp-98h]
  __int128 v66; // [xsp+F8h] [xbp-88h]
  __int128 v67; // [xsp+108h] [xbp-78h]
  __int128 v68; // [xsp+118h] [xbp-68h]
  __int64 vars0; // [xsp+180h] [xbp+0h]

  if ( *(_BYTE *)(result + 117) & 0x80 )
  {
    v8 = (_QWORD *)result;
    v9 = *(_QWORD *)(result + 80);              // 0
    v56 = *(_DWORD *)(v9 + 16);                 // 0x19
    if ( v56 )
    {
      v10 = a2;
      v11 = 0;
      v12 = (_DWORD *)(v9 + 32);
      v13 = a2 + 224;
      while ( 1 )
      {
        v57 = v11;
        v58 = v12;
        if ( *v12 == 25 )                       // 0x25是LC_SEGMENT_64的宏
        {
          v14 = (unsigned __int64)(v58 + 0x12);
          v59 = (unsigned __int64)&v58[0x14 * v58[16] + 0x12];
          if ( v59 > (unsigned __int64)(v58 + 0x12) )
            break;
        }
LABEL_23:
        v12 = (_DWORD *)((char *)v58 + (unsigned int)v58[1]);// //第一步对LC_SEGMENT_64(_TEXT)对应的 Section段扫描查找_mod_init_func
                                                // //第二步对LC_SEGMENT_64(_DATA)对应的 Section段扫描查找_mod_init_func
        v11 = v57 + 1;
        if ( v57 + 1 >= v56 )
          return result;
      }
      while ( 1 )
      {
        if ( *(_BYTE *)(v14 + 0x40) == 9 )      // 9是mod_init_func的Flags的宏
        {
          v15 = *(_QWORD *)(v14 + 0x20);        // 得到 偏移地址
          v16 = *((_QWORD *)v58 + 3);           // LC_SEGMENT_64(_DATA)地址
          if ( v15 < v16 )
            goto LABEL_27;                      // 容错判断
          v17 = *(_QWORD *)(v14 + 0x28);        // 得到 size
          if ( __CFADD__(v17, v15) || v17 + v15 > *((_QWORD *)v58 + 4) + v16 )
            goto LABEL_27;                      // 容错判断
          v3 = v17 >> 3;
          if ( v17 >> 3 )
            break;
        }
LABEL_22:
        v14 += 0x50LL;                          // 初始 为0x00000001098f8068 "__text"即dylb+0x68是Section段0x50是这段间距
                                                // 
        if ( v14 >= v59 )                       // v59是LC_SEGMENT_64(_DATA)开头,所这段是循环判断LC_SEGMENT_64(_TEXT)段内容
          goto LABEL_23;
      }
      v2 = 0LL;                                 // 到这里得到_mod_init_func_section地址偏移
      v5 = v8[12] + v15;                        // v8[12]是dylib头地址+v15是偏移地址,v5就是_mod_init_func_section实际地址
      while ( 1 )
      {
        v4 = *(__int64 (__fastcall **)(_QWORD, _QWORD, _QWORD, _QWORD, _QWORD))(v5 + 8 * v2);// ImageLoader::containsAddress参数是InitFunc_0的地址。应该连续加载初始化函数
        if ( !((*(__int64 (__fastcall **)(_QWORD *, _QWORD))(*v8 + 64LL))(v8, *(_QWORD *)(v5 + 8 * v2)) & 1) )
          break;
        if ( !*((_BYTE *)off_5BAC0 + 25) )
        {
          v18 = (*(__int64 (__fastcall **)(_QWORD *))(*v8 + 48LL))(v8);
          if ( !v18 || (unsigned int)sub_3E310(v18, "/usr/lib/libSystem.B.dylib") )
            goto LABEL_26;
        }
        if ( *(_BYTE *)(v10 + 0x14D) )
        {
          v19 = v8[1];
          v54 = v4;
          v55 = v19;
          sub_1B40("dyld: calling initializer function %p in %s\n");
        }
        v6 = off_5B738;
        v20 = v8[10];
        v60 = 520552448;
        v61 = v20;
        v62 = 0LL;
        v63 = v4;
        v67 = 0u;
        v68 = 0u;
        v65 = 0u;
        v66 = 0u;
        v64 = 0u;
        dyld3::ScopedTimer::startTimer__(&v60);
        dyld3::ScopedTimer::endTimer__(&v60);
        result = v4(                            // InitFunc_0
                   *(unsigned int *)(v10 + 188),// 1
                   *(_QWORD *)(v10 + 192),      // "/var/containers/Bundle/Application/9F94AAB3-F845-4F47-9A99-97C236323030/Xman_New.app/Xman_New"
                   *(_QWORD *)(v10 + 200),      // "TMPDIR=/private/var/mobile/Containers/Data/Application/1A2AE213-8E07-4C10-B998-1DDB33E31826/tmp/"
                   *(_QWORD *)(v10 + 208),      // "executable_path=/var/containers/Bundle/Application/9F94AAB3-F845-4F47-9A99-97C236323030/Xman_New.app/Xman_New"
                   v13);                        // app的mach文件
        if ( !v6 )
        {
          if ( off_5B738 )
            *((_BYTE *)off_5BAC0 + 25) = 1;
        }
        if ( ++v2 >= v3 )
          goto LABEL_22;
      }
      v21 = v8[1];
      v54 = v4;
      v55 = v21;
      sub_18A8("initializer function %p not in mapped image for %s\n");
LABEL_26:
      v54 = (__int64 (__fastcall *)(_QWORD, _QWORD, _QWORD, _QWORD, _QWORD))v8[1];
      sub_18A8("initializer in image (%s) that does not link with libSystem.dylib\n");
LABEL_27:
      v54 = (__int64 (__fastcall *)(_QWORD, _QWORD, _QWORD, _QWORD, _QWORD))v8[1];
      v22 = sub_18A8("__mod_init_funcs section has malformed address range for %s\n");
      result = sub_1BEC(v22);
      v44 = v6;
      v45 = v5;
      v46 = v4;
      v47 = v3;
      v48 = v2;
      v49 = v13;
      v50 = v10;
      v51 = v8;
      v52 = &vars0;
      v53 = v7;
      if ( *(_BYTE *)(result + 117) & 0x20 )
      {
        v24 = (_QWORD *)result;
        v25 = *(_QWORD *)(result + 80);
        v26 = *(_DWORD *)(v25 + 16);
        if ( v26 )
        {
          v27 = v23;
          v28 = 0;
          v29 = v25 + 32;
          do
          {
            if ( *(_DWORD *)v29 == 25 )
            {
              v30 = v29 + 72;
              v31 = v29 + 72 + 80LL * *(unsigned int *)(v29 + 64);
              if ( v31 > v29 + 72 )
              {
                do
                {
                  if ( *(_BYTE *)(v30 + 64) == 15 )
                  {
                    v32 = *(_QWORD *)(v30 + 32);
                    v33 = *(_QWORD *)(v29 + 24);
                    if ( v32 < v33
                      || (v34 = *(_QWORD *)(v30 + 40), v35 = __CFADD__(v34, v32), v36 = v34 + v32, v35)
                      || v36 > *(_QWORD *)(v29 + 32) + v33 )
                    {
                      v39 = v24[1];
                      v40 = sub_18A8("DOF section has malformed address range for %s\n");
                      return ImageLoaderMachO::doInitialization(v40, v41);
                    }
                    *(_QWORD *)&v42 = v24[12] + v32;
                    *((_QWORD *)&v42 + 1) = (*(__int64 (__fastcall **)(_QWORD *))(*v24 + 104LL))(v24);
                    result = sub_12048(v24);
                    v43 = result;
                    v37 = *(_QWORD *)(v27 + 8);
                    if ( v37 == *(_QWORD *)(v27 + 16) )
                    {
                      result = sub_1A114(v27, &v42);
                    }
                    else
                    {
                      v38 = v42;
                      *(_QWORD *)(v37 + 16) = v43;
                      *(_OWORD *)v37 = v38;
                      *(_QWORD *)(v27 + 8) += 24LL;
                    }
                  }
                  v30 += 80LL;
                }
                while ( v30 < v31 );
              }
            }
            v29 += *(unsigned int *)(v29 + 4);
            ++v28;
          }
          while ( v28 < v26 );
        }
      }
    }
  }
  return result;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值