gpt4 book ai didi

android - 什么是 ELF 二进制文件中的 .init_array 部分?

转载 作者:塔克拉玛干 更新时间:2023-11-02 22:58:16 27 4
gpt4 key购买 nike

每篇文章都说 .init_array 部分是一个函数数组,但根据我的经验,它不是。

这是我为 Android 编译的 libc.so 的 .init_array:

$ prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi-objdump -s -j .init_array out/target/product/e910/obj/SHARED_LIBRARIES/libc_intermediates/LINKED/libc.so 

out/target/product/e910/obj/SHARED_LIBRARIES/libc_intermediates/LINKED/libc.so: file format elf32-littlearm

Contents of section .init_array:
42000 e1620100 ffffffff 75940200 00000000 .b......u.......

它包含 4 个单词(little endian):

000162e1
ffffffff
00029475
00000000

000162e100029475 似乎是一些函数指针:

000162e0 <__libc_preinit>:
* as soon as the shared library is loaded.
*/
void __attribute__((constructor)) __libc_preinit(void);

void __libc_preinit(void)
{
162e0: b510 push {r4, lr}
* Note that:
* - we clear the slot so no other initializer sees its value.
* - __libc_init_common() will change the TLS area so the old one
* won't be accessible anyway.
*/
void** tls_area = (void**)__get_tls();
162e2: 4805 ldr r0, [pc, #20] (162f8 <__libc_preinit+0x18>)
unsigned* elfdata = tls_area[TLS_SLOT_BIONIC_PREINIT];

tls_area[TLS_SLOT_BIONIC_PREINIT] = NULL;
162e4: 2200 movs r2, #0
* Note that:
* - we clear the slot so no other initializer sees its value.
* - __libc_init_common() will change the TLS area so the old one
* won't be accessible anyway.
*/
void** tls_area = (void**)__get_tls();
162e6: 6803 ldr r3, [r0, #0]
unsigned* elfdata = tls_area[TLS_SLOT_BIONIC_PREINIT];
162e8: 68d8 ldr r0, [r3, #12]

tls_area[TLS_SLOT_BIONIC_PREINIT] = NULL;
162ea: 60da str r2, [r3, #12]

__libc_init_common(elfdata);
162ec: f010 fed6 bl 2709c <__libc_init_common>

/* Setup malloc routines accordingly to the environment.
* Requires system properties
*/
extern void malloc_debug_init(void);
malloc_debug_init();
162f0: f7ff fd0e bl 15d10 <malloc_debug_init>
}
162f4: bd10 pop {r4, pc}
162f6: 46c0 nop (mov r8, r8)
162f8: ffff0ff0 .word 0xffff0ff0

00029475是:

00029474 <__guard_setup>:

/* Initialize the canary with a random value from /dev/urandom.
* If that fails, use the "terminator canary". */
static void __attribute__ ((constructor))
__guard_setup(void)
{
29474: b570 push {r4, r5, r6, lr}
int fd;

fd = open("/dev/urandom", O_RDONLY);
29476: 4810 ldr r0, [pc, #64] (294b8 <__guard_setup+0x44>)
29478: 2100 movs r1, #0
2947a: 4478 add r0, pc
2947c: f7ef f89a bl 185b4 <open>
if (fd != -1) {
ssize_t len = read(fd, &__stack_chk_guard,
29480: 4d0e ldr r5, [pc, #56] (294bc <__guard_setup+0x48>)
29482: 447d add r5, pc
static void __attribute__ ((constructor))
__guard_setup(void)
{
int fd;

fd = open("/dev/urandom", O_RDONLY);
29484: 1c06 adds r6, r0, #0
if (fd != -1) {
29486: 1c43 adds r3, r0, #1
29488: d00a beq.n 294a0 <__guard_setup+0x2c>
ssize_t len = read(fd, &__stack_chk_guard,
2948a: 4b0d ldr r3, [pc, #52] (294c0 <__guard_setup+0x4c>)
2948c: 2204 movs r2, #4
2948e: 58e9 ldr r1, [r5, r3]
29490: f7e3 e8fe blx c690 <read>
29494: 1c04 adds r4, r0, #0
sizeof(__stack_chk_guard));
close(fd);
29496: 1c30 adds r0, r6, #0
29498: f7e3 e96a blx c770 <close>
if (len == sizeof(__stack_chk_guard))
2949c: 2c04 cmp r4, #4
2949e: d009 beq.n 294b4 <__guard_setup+0x40>
return;
}

/* If that failed, switch to 'terminator canary' */
((unsigned char *)&__stack_chk_guard)[0] = 0;
294a0: 4c07 ldr r4, [pc, #28] (294c0 <__guard_setup+0x4c>)
((unsigned char *)&__stack_chk_guard)[1] = 0;
((unsigned char *)&__stack_chk_guard)[2] = '\n';
((unsigned char *)&__stack_chk_guard)[3] = 255;
294a2: 2101 movs r1, #1
if (len == sizeof(__stack_chk_guard))
return;
}

/* If that failed, switch to 'terminator canary' */
((unsigned char *)&__stack_chk_guard)[0] = 0;
294a4: 2600 movs r6, #0
294a6: 5928 ldr r0, [r5, r4]
((unsigned char *)&__stack_chk_guard)[1] = 0;
((unsigned char *)&__stack_chk_guard)[2] = '\n';
((unsigned char *)&__stack_chk_guard)[3] = 255;
294a8: 424a negs r2, r1
}

/* If that failed, switch to 'terminator canary' */
((unsigned char *)&__stack_chk_guard)[0] = 0;
((unsigned char *)&__stack_chk_guard)[1] = 0;
((unsigned char *)&__stack_chk_guard)[2] = '\n';
294aa: 250a movs r5, #10
if (len == sizeof(__stack_chk_guard))
return;
}

/* If that failed, switch to 'terminator canary' */
((unsigned char *)&__stack_chk_guard)[0] = 0;
294ac: 7006 strb r6, [r0, #0]
((unsigned char *)&__stack_chk_guard)[1] = 0;
294ae: 7046 strb r6, [r0, #1]
((unsigned char *)&__stack_chk_guard)[2] = '\n';
294b0: 7085 strb r5, [r0, #2]
((unsigned char *)&__stack_chk_guard)[3] = 255;
294b2: 70c2 strb r2, [r0, #3]
}
294b4: bd70 pop {r4, r5, r6, pc}
294b6: 46c0 nop (mov r8, r8)
294b8: 0001451d .word 0x0001451d
294bc: 0001a09e .word 0x0001a09e
294c0: ffffff1c .word 0xffffff1c

有3个问题:

  1. 为什么有 1 个字节的偏移量?在 arm 架构中,所有指令都对齐到 2 字节边界,但它们不是。
  2. 那个数组中的 ffffffff 是什么?
  3. 那个数组中的 00000000 是什么?

最佳答案

对于问题 #1,查看反汇编代码,您的 ARM 代码处于 Thumb 模式 - Thumb 指令的地址生成时设置了最低有效位,以便在从标准 ARM 模式调用时触发将处理器切换到 Thumb 模式。为了兼容性,我认为即使 ARM 处理器是 Thumb-only,这通常也是如此。

对于数字 2 和 3,来自 readme on the Android linker :

DT_INIT_ARRAY

Points to an array of function addresses that must be called, in-order, to perform initialization. Some of the entries in the array can be 0 or -1, and should be ignored.

Note: this is generally stored in a .init_array section

关于android - 什么是 ELF 二进制文件中的 .init_array 部分?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10468531/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com