https://github.com/NixOS/patchelf

动机

增加项目的维护能力。

关注点

  1. 新增segment流程 ; 新增到文件末尾,增大program header的空间(可能会与section 发生堆叠),写入记录。
  2. dynamic 拓展空间、并移动流程;原始的dynamic都会被删除,被修改的section 会被追加到文件末尾,修改section header 记录, 修改.dynamic 内部数据

启动参数:

patchelf --add-needed libjjrt.so  home/pareto/Desktop/libil2cpp.so --output libil2cpp.so

代码分析

mainWrapped 函数中处理命令行参数选项 。

将需要添加的so依赖名称存入neededLibsToAdd

目标so 名称放入fileNames

调用patchElf2

patchElf2

  1. 获取dynamic 和 dynstr 段。
  2. 创建新的dynstr 和 新的dynamic,并写入新的数据。
  3. rewriteSection ,判断是动态库,rewriteSectionLibrary
  4. 写文件

rewriteSectionLibrary

startPage 新增Segment 的起始地址

  1. 增加program header table 的大小,可能会导致第一个section 和program header 的内存堆叠,需要移动前几块segments。
    1. 获取被占用的section ,后续将其写到文件尾部。
    2. 获取文件需要新增的空间 ,包含新增的dynstr 、 dynamic 和 section。
    3. 创建新的program header。
    4. normalizeNoteSegments() ,这个操作有点神奇,猜测为被占用section 新建program header ,并写入相应数据, 后续可以细看
    5. writeReplacedSections , 将原section 覆盖为’X’ , 依次将新曾的section 写入文件,并修改相应的section header entry , 如果sectionName == “.dynamic” , 同时修改dynamic Segment。
    6. rewriteHeaders , 修改program table 中PT_PHDR segment , 修改program header,需要dynamic段内部字段。

rdi ,改变相应的数据类型的端序。

template<ElfFileParams>
template<class I>
I ElfFile<ElfFileParamNames>::rdi(I i) const
{
  I r = 0;
  if (littleEndian) {
      for (unsigned int n = 0; n < sizeof(I); ++n) {
          r |= ((I) *(((unsigned char *) &i) + n)) << (n * 8);
      }
  } else {
      for (unsigned int n = 0; n < sizeof(I); ++n) {
          r |= ((I) *(((unsigned char *) &i) + n)) << ((sizeof(I) - n - 1) * 8);
      }
  }
  return r;
}
分类: llvm

pareto

未来什么方向不管,先做自己喜欢做的事情。

0 条评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注