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 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 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 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