blob: 2600ac73b30a5d995a1fb2b599a7dd8e6bb606fa [file] [log] [blame]
The Android Open Source Project88b60792009-03-03 19:28:42 -08001#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
Hristo Bojinov96be7202010-08-02 10:26:17 -070014#define RETOUCH_SUFFIX_SIZE 12
The Android Open Source Project88b60792009-03-03 19:28:42 -080015typedef struct {
16 uint32_t mmap_addr;
17 char tag[4]; /* 'P', 'R', 'E', ' ' */
Kenny Rootafb36e72010-06-26 22:39:38 -070018} __attribute__((packed)) prelink_info_t;
The Android Open Source Project88b60792009-03-03 19:28:42 -080019
20static inline void set_prelink(long *prelink_addr,
21 int elf_little,
22 prelink_info_t *info)
23{
Kenny Rootafb36e72010-06-26 22:39:38 -070024 FAILIF(sizeof(prelink_info_t) != 8, "Unexpected sizeof(prelink_info_t) == %zd!\n", sizeof(prelink_info_t));
The Android Open Source Project88b60792009-03-03 19:28:42 -080025 if (prelink_addr) {
26 if (!(elf_little ^ is_host_little())) {
27 /* Same endianness */
28 *prelink_addr = info->mmap_addr;
29 }
30 else {
31 /* Different endianness */
Hristo Bojinov96be7202010-08-02 10:26:17 -070032 *prelink_addr = switch_endianness(info->mmap_addr);
The Android Open Source Project88b60792009-03-03 19:28:42 -080033 }
34 }
35}
36
37int check_prelinked(const char *fname, int elf_little, long *prelink_addr)
38{
Kenny Rootafb36e72010-06-26 22:39:38 -070039 FAILIF(sizeof(prelink_info_t) != 8, "Unexpected sizeof(prelink_info_t) == %zd!\n", sizeof(prelink_info_t));
The Android Open Source Project88b60792009-03-03 19:28:42 -080040 int fd = open(fname, O_RDONLY);
41 FAILIF(fd < 0, "open(%s, O_RDONLY): %s (%d)!\n",
42 fname, strerror(errno), errno);
43 off_t end = lseek(fd, 0, SEEK_END);
Kenny Rootafb36e72010-06-26 22:39:38 -070044#ifndef DEBUG
45 (void)end;
46#endif
The Android Open Source Project88b60792009-03-03 19:28:42 -080047
48 int nr = sizeof(prelink_info_t);
49
50 off_t sz = lseek(fd, -nr, SEEK_CUR);
51 ASSERT((long)(end - sz) == (long)nr);
52 FAILIF(sz == (off_t)-1,
53 "lseek(%d, 0, SEEK_END): %s (%d)!\n",
54 fd, strerror(errno), errno);
55
56 prelink_info_t info;
Kenny Rootafb36e72010-06-26 22:39:38 -070057 ssize_t num_read = read(fd, &info, nr);
The Android Open Source Project88b60792009-03-03 19:28:42 -080058 FAILIF(num_read < 0,
59 "read(%d, &info, sizeof(prelink_info_t)): %s (%d)!\n",
60 fd, strerror(errno), errno);
Kenny Rootafb36e72010-06-26 22:39:38 -070061 FAILIF((size_t)num_read != sizeof(info),
62 "read(%d, &info, sizeof(prelink_info_t)): did not read %zd bytes as "
63 "expected (read %zd)!\n",
64 fd, sizeof(info), (size_t)num_read);
The Android Open Source Project88b60792009-03-03 19:28:42 -080065
66 int prelinked = 0;
67 if (!strncmp(info.tag, "PRE ", 4)) {
68 set_prelink(prelink_addr, elf_little, &info);
69 prelinked = 1;
70 }
Hristo Bojinov96be7202010-08-02 10:26:17 -070071 FAILIF(close(fd) < 0,
72 "close(%d): %s (%d)!\n", fd, strerror(errno), errno);
The Android Open Source Project88b60792009-03-03 19:28:42 -080073 return prelinked;
74}
75
Hristo Bojinov96be7202010-08-02 10:26:17 -070076int check_retouched(const char *fname, int elf_little,
77 unsigned int *retouch_byte_cnt, char *retouch_buf) {
78 FAILIF(sizeof(prelink_info_t) != 8,
79 "Unexpected sizeof(prelink_info_t) == %d!\n",
80 sizeof(prelink_info_t));
81 int fd = open(fname, O_RDONLY);
82 FAILIF(fd < 0, "open(%s, O_RDONLY): %s (%d)!\n",
83 fname, strerror(errno), errno);
84 off_t end = lseek(fd, 0, SEEK_END);
85 int nr = sizeof(prelink_info_t);
86 off_t sz = lseek(fd, -nr-RETOUCH_SUFFIX_SIZE, SEEK_CUR);
87 ASSERT((long)(end - sz) == (long)(nr+RETOUCH_SUFFIX_SIZE));
88 FAILIF(sz == (off_t)-1,
89 "lseek(%d, 0, SEEK_END): %s (%d)!\n",
90 fd, strerror(errno), errno);
91
92 char retouch_meta[RETOUCH_SUFFIX_SIZE];
93 int num_read = read(fd, &retouch_meta, RETOUCH_SUFFIX_SIZE);
94 FAILIF(num_read < 0,
95 "read(%d, &info, sizeof(prelink_info_t)): %s (%d)!\n",
96 fd, strerror(errno), errno);
97 FAILIF(num_read != RETOUCH_SUFFIX_SIZE,
98 "read(%d, &info, sizeof(prelink_info_t)): did not read %d bytes as "
99 "expected (read %d)!\n",
100 fd, RETOUCH_SUFFIX_SIZE, num_read);
101
102 int retouched = 0;
103 if (!strncmp(retouch_meta, "RETOUCH ", 8)) {
104 unsigned int retouch_byte_cnt_meta;
105 if (!(elf_little ^ is_host_little()))
106 retouch_byte_cnt_meta = *(unsigned int *)(retouch_meta+8);
107 else
108 retouch_byte_cnt_meta =
109 switch_endianness(*(unsigned int *)(retouch_meta+8));
110 FAILIF(*retouch_byte_cnt < retouch_byte_cnt_meta,
111 "Retouch buffer too small at %d bytes (%d needed).",
112 *retouch_byte_cnt, retouch_byte_cnt_meta);
113 *retouch_byte_cnt = retouch_byte_cnt_meta;
114 off_t sz = lseek(fd,
115 -((long)*retouch_byte_cnt)-RETOUCH_SUFFIX_SIZE-nr,
116 SEEK_END);
117 ASSERT((long)(end - sz) ==
118 (long)(*retouch_byte_cnt+RETOUCH_SUFFIX_SIZE+nr));
119 FAILIF(sz == (off_t)-1,
120 "lseek(%d, 0, SEEK_END): %s (%d)!\n",
121 fd, strerror(errno), errno);
122 num_read = read(fd, retouch_buf, *retouch_byte_cnt);
123 FAILIF(num_read < 0,
124 "read(%d, &info, sizeof(prelink_info_t)): %s (%d)!\n",
125 fd, strerror(errno), errno);
126 FAILIF(num_read != *retouch_byte_cnt,
127 "read(%d, retouch_buf, %u): did not read %d bytes as "
128 "expected (read %d)!\n",
129 fd, *retouch_byte_cnt, *retouch_byte_cnt, num_read);
130
131 retouched = 1;
132 }
133 FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno);
134 return retouched;
135}
136
137void retouch_dump(const char *fname, int elf_little,
138 unsigned int retouch_byte_cnt, char *retouch_buf) {
139 int fd = open(fname, O_WRONLY);
140 FAILIF(fd < 0,
141 "open(%s, O_WRONLY): %s (%d)\n",
142 fname, strerror(errno), errno);
143 off_t sz = lseek(fd, 0, SEEK_END);
144 FAILIF(sz == (off_t)-1,
145 "lseek(%d, 0, SEEK_END): %s (%d)!\n",
146 fd, strerror(errno), errno);
147
148 // The retouch blob ends with "RETOUCH XXXX", where XXXX is the 4-byte
149 // size of the retouch blob, in target endianness.
150 strncpy(retouch_buf+retouch_byte_cnt, "RETOUCH ", 8);
151 if (elf_little ^ is_host_little()) {
152 *(unsigned int *)(retouch_buf+retouch_byte_cnt+8) =
153 switch_endianness(retouch_byte_cnt);
154 } else {
155 *(unsigned int *)(retouch_buf+retouch_byte_cnt+8) =
156 retouch_byte_cnt;
157 }
158
159 int num_written = write(fd, retouch_buf, retouch_byte_cnt+12);
160 FAILIF(num_written < 0,
161 "write(%d, &info, sizeof(info)): %s (%d)\n",
162 fd, strerror(errno), errno);
163 FAILIF((retouch_byte_cnt+12) != num_written,
164 "Could not write %d bytes as expected (wrote %d bytes instead)!\n",
165 retouch_byte_cnt, num_written);
166 FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno);
167}
168
The Android Open Source Project88b60792009-03-03 19:28:42 -0800169void setup_prelink_info(const char *fname, int elf_little, long base)
170{
Kenny Rootafb36e72010-06-26 22:39:38 -0700171 FAILIF(sizeof(prelink_info_t) != 8, "Unexpected sizeof(prelink_info_t) == %zd!\n", sizeof(prelink_info_t));
The Android Open Source Project88b60792009-03-03 19:28:42 -0800172 int fd = open(fname, O_WRONLY);
173 FAILIF(fd < 0,
174 "open(%s, O_WRONLY): %s (%d)\n" ,
175 fname, strerror(errno), errno);
176 prelink_info_t info;
177 off_t sz = lseek(fd, 0, SEEK_END);
178 FAILIF(sz == (off_t)-1,
179 "lseek(%d, 0, SEEK_END): %s (%d)!\n",
180 fd, strerror(errno), errno);
181
182 if (!(elf_little ^ is_host_little())) {
183 /* Same endianness */
184 INFO("Host and ELF file [%s] have same endianness.\n", fname);
185 info.mmap_addr = base;
186 }
187 else {
188 /* Different endianness */
189 INFO("Host and ELF file [%s] have different endianness.\n", fname);
Hristo Bojinov96be7202010-08-02 10:26:17 -0700190 info.mmap_addr = switch_endianness(base);
The Android Open Source Project88b60792009-03-03 19:28:42 -0800191 }
192 strncpy(info.tag, "PRE ", 4);
193
Kenny Rootafb36e72010-06-26 22:39:38 -0700194 ssize_t num_written = write(fd, &info, sizeof(info));
The Android Open Source Project88b60792009-03-03 19:28:42 -0800195 FAILIF(num_written < 0,
196 "write(%d, &info, sizeof(info)): %s (%d)\n",
197 fd, strerror(errno), errno);
Kenny Rootafb36e72010-06-26 22:39:38 -0700198 FAILIF(sizeof(info) != (size_t)num_written,
199 "Could not write %zd bytes (wrote only %zd bytes) as expected!\n",
200 sizeof(info), (size_t)num_written);
The Android Open Source Project88b60792009-03-03 19:28:42 -0800201 FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno);
202}
203
204#endif /*SUPPORT_ANDROID_PRELINK_TAGS*/