1 #ifdef SUPPORT_ANDROID_PRELINK_TAGS
2
3 #include <sys/types.h>
4 #include <fcntl.h>
5 #include <sys/types.h>
6 #include <unistd.h>
7 #include <string.h>
8 #include <errno.h>
9
10 #include <prelink_info.h>
11 #include <debug.h>
12 #include <common.h>
13
14 typedef struct {
15 uint32_t mmap_addr;
16 char tag[4]; /* 'P', 'R', 'E', ' ' */
17 } prelink_info_t __attribute__((packed));
18
set_prelink(long * prelink_addr,int elf_little,prelink_info_t * info)19 static inline void set_prelink(long *prelink_addr,
20 int elf_little,
21 prelink_info_t *info)
22 {
23 FAILIF(sizeof(prelink_info_t) != 8, "Unexpected sizeof(prelink_info_t) == %d!\n", sizeof(prelink_info_t));
24 if (prelink_addr) {
25 if (!(elf_little ^ is_host_little())) {
26 /* Same endianness */
27 *prelink_addr = info->mmap_addr;
28 }
29 else {
30 /* Different endianness */
31 *prelink_addr = switch_endianness(info->mmap_addr);
32 }
33 }
34 }
35
check_prelinked(const char * fname,int elf_little,long * prelink_addr)36 int check_prelinked(const char *fname, int elf_little, long *prelink_addr)
37 {
38 FAILIF(sizeof(prelink_info_t) != 8, "Unexpected sizeof(prelink_info_t) == %d!\n", sizeof(prelink_info_t));
39 int fd = open(fname, O_RDONLY);
40 FAILIF(fd < 0, "open(%s, O_RDONLY): %s (%d)!\n",
41 fname, strerror(errno), errno);
42 off_t end = lseek(fd, 0, SEEK_END);
43
44 int nr = sizeof(prelink_info_t);
45
46 off_t sz = lseek(fd, -nr, SEEK_CUR);
47 ASSERT((long)(end - sz) == (long)nr);
48 FAILIF(sz == (off_t)-1,
49 "lseek(%d, 0, SEEK_END): %s (%d)!\n",
50 fd, strerror(errno), errno);
51
52 prelink_info_t info;
53 int num_read = read(fd, &info, nr);
54 FAILIF(num_read < 0,
55 "read(%d, &info, sizeof(prelink_info_t)): %s (%d)!\n",
56 fd, strerror(errno), errno);
57 FAILIF(num_read != sizeof(info),
58 "read(%d, &info, sizeof(prelink_info_t)): did not read %d bytes as "
59 "expected (read %d)!\n",
60 fd, sizeof(info), num_read);
61
62 int prelinked = 0;
63 if (!strncmp(info.tag, "PRE ", 4)) {
64 set_prelink(prelink_addr, elf_little, &info);
65 prelinked = 1;
66 }
67 FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno);
68 return prelinked;
69 }
70
setup_prelink_info(const char * fname,int elf_little,long base)71 void setup_prelink_info(const char *fname, int elf_little, long base)
72 {
73 FAILIF(sizeof(prelink_info_t) != 8, "Unexpected sizeof(prelink_info_t) == %d!\n", sizeof(prelink_info_t));
74 int fd = open(fname, O_WRONLY);
75 FAILIF(fd < 0,
76 "open(%s, O_WRONLY): %s (%d)\n" ,
77 fname, strerror(errno), errno);
78 prelink_info_t info;
79 off_t sz = lseek(fd, 0, SEEK_END);
80 FAILIF(sz == (off_t)-1,
81 "lseek(%d, 0, SEEK_END): %s (%d)!\n",
82 fd, strerror(errno), errno);
83
84 if (!(elf_little ^ is_host_little())) {
85 /* Same endianness */
86 INFO("Host and ELF file [%s] have same endianness.\n", fname);
87 info.mmap_addr = base;
88 }
89 else {
90 /* Different endianness */
91 INFO("Host and ELF file [%s] have different endianness.\n", fname);
92 info.mmap_addr = switch_endianness(base);
93 }
94 strncpy(info.tag, "PRE ", 4);
95
96 int num_written = write(fd, &info, sizeof(info));
97 FAILIF(num_written < 0,
98 "write(%d, &info, sizeof(info)): %s (%d)\n",
99 fd, strerror(errno), errno);
100 FAILIF(sizeof(info) != num_written,
101 "Could not write %d bytes (wrote only %d bytes) as expected!\n",
102 sizeof(info), num_written);
103 FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno);
104 }
105
106 #endif /*SUPPORT_ANDROID_PRELINK_TAGS*/
107