|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #include <stdint.h> |
|
6 #include <elf.h> |
|
7 |
|
8 /* The Android NDK headers define those */ |
|
9 #undef Elf_Ehdr |
|
10 #undef Elf_Addr |
|
11 |
|
12 #if defined(__LP64__) |
|
13 #define Elf_Ehdr Elf64_Ehdr |
|
14 #define Elf_Addr Elf64_Addr |
|
15 #else |
|
16 #define Elf_Ehdr Elf32_Ehdr |
|
17 #define Elf_Addr Elf32_Addr |
|
18 #endif |
|
19 |
|
20 extern __attribute__((visibility("hidden"))) void original_init(int argc, char **argv, char **env); |
|
21 |
|
22 extern __attribute__((visibility("hidden"))) Elf32_Rel relhack[]; |
|
23 extern __attribute__((visibility("hidden"))) Elf_Ehdr elf_header; |
|
24 |
|
25 static inline __attribute__((always_inline)) |
|
26 void do_relocations(void) |
|
27 { |
|
28 Elf32_Rel *rel; |
|
29 Elf_Addr *ptr, *start; |
|
30 for (rel = relhack; rel->r_offset; rel++) { |
|
31 start = (Elf_Addr *)((intptr_t)&elf_header + rel->r_offset); |
|
32 for (ptr = start; ptr < &start[rel->r_info]; ptr++) |
|
33 *ptr += (intptr_t)&elf_header; |
|
34 } |
|
35 } |
|
36 |
|
37 __attribute__((section(".text._init_noinit"))) |
|
38 int init_noinit(int argc, char **argv, char **env) |
|
39 { |
|
40 do_relocations(); |
|
41 return 0; |
|
42 } |
|
43 |
|
44 __attribute__((section(".text._init"))) |
|
45 int init(int argc, char **argv, char **env) |
|
46 { |
|
47 do_relocations(); |
|
48 original_init(argc, argv, env); |
|
49 // Ensure there is no tail-call optimization, avoiding the use of the |
|
50 // B.W instruction in Thumb for the call above. |
|
51 return 0; |
|
52 } |