Home | History | Annotate | Download | only in soslim
      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