android linker 浅析

  Android 的加载/链接器linker 主要用于实现共享库的加载与链接。它支持应用程序对库函数的隐式和显式调用。对于隐式调用,应用程序的编译与静态库大致相同,只是在静态链接的时候通过--dynamic-linker /system/bin/linker 指定动态链接器,(该信息将被存放在ELF文件的.interp节中,内核执行目标映像文件前将通过该信息加载并运行相应的解释器程序linker.)并链接相应的共享库。与ld.so不同的是,Linker目前没有提供Lazy Binding机制,所有外部过程引用都在映像执行之前解析。对于显式调用,可以同过linker中提供的接口dlopendlsym,dlerrordlclose来动态加载和链接共享库。

Android中的共享库和可执行映像都默认采用ELF格式的文件,其基本格式如下:


       每个ELF文件的开始部分都包含一个ELF头,其中包含了整个文件的基本信息,包括目标代码的格式,体系结构,各程序头或节头的偏移和大小,组织结构和访问权限等信息。

       程序头表包含了加载到内存中的各种段的索引及属性信息,它将告诉加载器如何加载映像。每个段中有包含了一个或几个节区,每个节区应是唯一的。无论是可执行程序还是共享库都包含以下几个的节区:

1. GOT表和PLT表:

       不同映像间的函数和数据引用都是通过它们实现的。GOT(全局偏移表)给出了映像中所有被引用符号(函数或变量)的值。每个普通PLT表项相当于一个函数的桩函数(stub),支持懒绑定的情况下,当发生对外部函数的调用时,程序会通过PLT表将控制交给动态连接器,后者解析出函数的绝对地址,修改GOT中相应的值,之后的调用将不再需要连接器的绑定。由于linker是不支持懒绑定的,所以在进程初始化时,动态链接器首先解析出外部过程引用的绝对地址,一次性的修改所有相应的GOT表项。对共享对象来说,由于GOTPLT节以及代码段和数据段之间的相对位置是固定的,所有引用都是基于一个固定地址(GOT)的偏移量,所以实现了PIC代码,重定位时只需要修改可写段中的GOT表。而可执行程序在连接过程中则可能发生对不可写段的修改。如果只读段和可写段不是以固定的相对位置加载的,那么在重定位是还需要修改所有指向GOT的指针。   

                                       

2. dynamic节:

       与重定位有关的基本目录结构,例如:

Dynamic section at offset 0x61014 contains 20 entries:

  Tag        Type                         Name/Value

 0x00000001 (NEEDED)                     Shared library: [libc.so.6]

 0x0000000c (INIT)                             0xb8a8

 0x0000000d (FINI)                           0x555c4

 0x00000004 (HASH)                       0x8128

 0x00000005 (STRTAB)                       0xa004

 0x00000006 (SYMTAB)                     0x8aa4

 0x0000000a (STRSZ)                         2902 (bytes)

 0x0000000b (SYMENT)                     16 (bytes)

 0x00000015 (DEBUG)                                0x0

 0x00000003 (PLTGOT)                     0x710dc

 0x00000002 (PLTRELSZ)                     2464 (bytes)

 0x00000014 (PLTREL)                       REL

 0x00000017 (JMPREL)                       0xaf08

 0x00000011 (REL)                           0xae98

 0x00000012 (RELSZ)                        112 (bytes)

 0x00000013 (RELENT)                      8 (bytes)

3. dynsymdynstr节:

       与重定位有关的符号表和字符串表:

Symbol table '.dynsym' contains 69 entries:

   Num:    Value   Size  Type    Bind       Vis        Ndx   Name

     0:   00000000   0  NOTYPE  LOCAL   DEFAULT  UND

     ……

     6:  00002568    28  FUNC    GLOBAL  DEFAULT    7   __ashldi3

     7:  00000001    58  FUNC    GLOBAL  DEFAULT  UND  _ZNK7android7RefBase9decS

     8:  00000001    32  FUNC    GLOBAL  DEFAULT  UND  ioctl

     9:  00000001    18  FUNC    GLOBAL  DEFAULT  UND  _ZN7android7String8D1Ev

    10:  00000001    16  FUNC    GLOBAL  DEFAULT  UND  _ZNK7android8EventHub16ge

    11:  00000001    32  FUNC    GLOBAL  DEFAULT  UND  strerror

    12:  00003024     0  NOTYPE  GLOBAL  DEFAULT  ABS  __exidx_end

4. .rel.dyn.rel.plt节:

       .rel.dyn节的表项对应了出外部过程调用的符号以外的所有重定位对象,.rel.plt则对应所有外部过程调用的重定位信息。每个重定位项记录了符号的符号表索引,重定位的操作地址,重定位类型的信息(见3.3节)。重定位所在的节区往往与重定位类型有关,例如:

Relocation section '.rel.plt' at offset 0x2f08 contains 308 entries:

 Offset     Info      Type                  Sym.Value  Sym. Name

000710e8  00000116   R_ARM_JUMP_SLOT   0000b8d0   fileno

000710ec  00000216   R_ARM_JUMP_SLOT   0000b8dc   getpagesize

000710f0  00000316   R_ARM_JUMP_SLOT   0000b8e8   fputs

000710f4  00000416   R_ARM_JUMP_SLOT   0000b8f4   abort

000710f8  00000516   R_ARM_JUMP_SLOT   0000b900   __errno_location

 

Relocation section '.rel.dyn' at offset 0x2e98 contains 14 entries:

 Offset     Info      Type            Sym.Value  Sym. Name

000715b8  00001e15  R_ARM_GLOB_DAT    00071000   __fini_array_end

000715bc  00002f15  R_ARM_GLOB_DAT    00000000   __gmon_start__

000715c8  0000f515  R_ARM_GLOB_DAT    00071000   __fini_array_start

000715cc  00010015  R_ARM_GLOB_DAT    00071000   __init_array_end

000715d0  00012e15  R_ARM_GLOB_DAT    00071000   __init_array_start

00072a00  00002714  R_ARM_COPY         00072a00   __timezone

00072a04  00005514  R_ARM_COPY         00072a04   __daylight

 

       R_ARM_JUMP_SLOTR_ARM_GLOB_DAT属性的重定位地址一般位于GOT表,R_ARM_COPYR_ARM_ABS32属性的重定位一般位于.data节或.text节中。

Linker的加载与启动

       Linker是共享库的加载/链接器,也可以称为解释器(interpreter)

  • 2
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值