blob: 81d5de3046864859460aa211367048e05a489a7d [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
14typedef struct {
15 uint32_t mmap_addr;
16 char tag[4]; /* 'P', 'R', 'E', ' ' */
Kenny Rootafb36e72010-06-26 22:39:38 -070017} __attribute__((packed)) prelink_info_t;
The Android Open Source Project88b60792009-03-03 19:28:42 -080018
19static inline void set_prelink(long *prelink_addr,
20 int elf_little,
21 prelink_info_t *info)
22{
Kenny Rootafb36e72010-06-26 22:39:38 -070023 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 -080024 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
36int check_prelinked(const char *fname, int elf_little, long *prelink_addr)
37{
Kenny Rootafb36e72010-06-26 22:39:38 -070038 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 -080039 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);
Kenny Rootafb36e72010-06-26 22:39:38 -070043#ifndef DEBUG
44 (void)end;
45#endif
The Android Open Source Project88b60792009-03-03 19:28:42 -080046
47 int nr = sizeof(prelink_info_t);
48
49 off_t sz = lseek(fd, -nr, SEEK_CUR);
50 ASSERT((long)(end - sz) == (long)nr);
51 FAILIF(sz == (off_t)-1,
52 "lseek(%d, 0, SEEK_END): %s (%d)!\n",
53 fd, strerror(errno), errno);
54
55 prelink_info_t info;
Kenny Rootafb36e72010-06-26 22:39:38 -070056 ssize_t num_read = read(fd, &info, nr);
The Android Open Source Project88b60792009-03-03 19:28:42 -080057 FAILIF(num_read < 0,
58 "read(%d, &info, sizeof(prelink_info_t)): %s (%d)!\n",
59 fd, strerror(errno), errno);
Kenny Rootafb36e72010-06-26 22:39:38 -070060 FAILIF((size_t)num_read != sizeof(info),
61 "read(%d, &info, sizeof(prelink_info_t)): did not read %zd bytes as "
62 "expected (read %zd)!\n",
63 fd, sizeof(info), (size_t)num_read);
The Android Open Source Project88b60792009-03-03 19:28:42 -080064
65 int prelinked = 0;
66 if (!strncmp(info.tag, "PRE ", 4)) {
67 set_prelink(prelink_addr, elf_little, &info);
68 prelinked = 1;
69 }
70 FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno);
71 return prelinked;
72}
73
74void setup_prelink_info(const char *fname, int elf_little, long base)
75{
Kenny Rootafb36e72010-06-26 22:39:38 -070076 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 -080077 int fd = open(fname, O_WRONLY);
78 FAILIF(fd < 0,
79 "open(%s, O_WRONLY): %s (%d)\n" ,
80 fname, strerror(errno), errno);
81 prelink_info_t info;
82 off_t sz = lseek(fd, 0, SEEK_END);
83 FAILIF(sz == (off_t)-1,
84 "lseek(%d, 0, SEEK_END): %s (%d)!\n",
85 fd, strerror(errno), errno);
86
87 if (!(elf_little ^ is_host_little())) {
88 /* Same endianness */
89 INFO("Host and ELF file [%s] have same endianness.\n", fname);
90 info.mmap_addr = base;
91 }
92 else {
93 /* Different endianness */
94 INFO("Host and ELF file [%s] have different endianness.\n", fname);
95 info.mmap_addr = switch_endianness(base);
96 }
97 strncpy(info.tag, "PRE ", 4);
98
Kenny Rootafb36e72010-06-26 22:39:38 -070099 ssize_t num_written = write(fd, &info, sizeof(info));
The Android Open Source Project88b60792009-03-03 19:28:42 -0800100 FAILIF(num_written < 0,
101 "write(%d, &info, sizeof(info)): %s (%d)\n",
102 fd, strerror(errno), errno);
Kenny Rootafb36e72010-06-26 22:39:38 -0700103 FAILIF(sizeof(info) != (size_t)num_written,
104 "Could not write %zd bytes (wrote only %zd bytes) as expected!\n",
105 sizeof(info), (size_t)num_written);
The Android Open Source Project88b60792009-03-03 19:28:42 -0800106 FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno);
107}
108
109#endif /*SUPPORT_ANDROID_PRELINK_TAGS*/