每篇文章都说.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个字(小端):
000162e1
ffffffff
00029475
00000000
000162e1
和00029475
似乎是一些函数指针:
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
ffffffff
是什么?00000000
是什么?答案 0 :(得分:3)
对于问题#1,查看反汇编,您的ARM代码处于Thumb模式 - Thumb指令的地址是在设置最低有效位的情况下生成的,这样当从标准ARM模式调用时,它们会触发将处理器切换到Thumb模式。为了兼容性,我认为即使ARM处理器只支持Thumb,这通常也会完成。
对于数字2和3,来自readme on the Android linker:
DT_INIT_ARRAY
指向必须调用的函数地址数组, 按顺序,执行初始化。数组中的一些条目 可以是0或-1,应该被忽略。
注意:这通常存储在.init_array部分
中