0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 #include <elf.h>
0036 #include <errno.h>
0037 #include <fcntl.h>
0038 #include <stdarg.h>
0039 #include <stdbool.h>
0040 #include <stdio.h>
0041 #include <stdlib.h>
0042 #include <string.h>
0043 #include <sys/mman.h>
0044 #include <sys/stat.h>
0045 #include <sys/types.h>
0046 #include <unistd.h>
0047
0048 #define swab16(x) \
0049 ((((x) & 0x00ff) << 8) | \
0050 (((x) & 0xff00) >> 8))
0051
0052 #define swab32(x) \
0053 ((((x) & 0x000000ff) << 24) | \
0054 (((x) & 0x0000ff00) << 8) | \
0055 (((x) & 0x00ff0000) >> 8) | \
0056 (((x) & 0xff000000) >> 24))
0057
0058 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
0059 #define HOST_ORDER ELFDATA2LSB
0060 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
0061 #define HOST_ORDER ELFDATA2MSB
0062 #endif
0063
0064
0065
0066
0067 #ifndef EF_ARM_EABI_VER5
0068 #define EF_ARM_EABI_VER5 0x05000000
0069 #endif
0070
0071 #ifndef EF_ARM_ABI_FLOAT_SOFT
0072 #define EF_ARM_ABI_FLOAT_SOFT 0x200
0073 #endif
0074
0075 #ifndef EF_ARM_ABI_FLOAT_HARD
0076 #define EF_ARM_ABI_FLOAT_HARD 0x400
0077 #endif
0078
0079 static int failed;
0080 static const char *argv0;
0081 static const char *outfile;
0082
0083 static void fail(const char *fmt, ...)
0084 {
0085 va_list ap;
0086
0087 failed = 1;
0088 fprintf(stderr, "%s: ", argv0);
0089 va_start(ap, fmt);
0090 vfprintf(stderr, fmt, ap);
0091 va_end(ap);
0092 exit(EXIT_FAILURE);
0093 }
0094
0095 static void cleanup(void)
0096 {
0097 if (failed && outfile != NULL)
0098 unlink(outfile);
0099 }
0100
0101 static Elf32_Word read_elf_word(Elf32_Word word, bool swap)
0102 {
0103 return swap ? swab32(word) : word;
0104 }
0105
0106 static Elf32_Half read_elf_half(Elf32_Half half, bool swap)
0107 {
0108 return swap ? swab16(half) : half;
0109 }
0110
0111 static void write_elf_word(Elf32_Word val, Elf32_Word *dst, bool swap)
0112 {
0113 *dst = swap ? swab32(val) : val;
0114 }
0115
0116 int main(int argc, char **argv)
0117 {
0118 const Elf32_Ehdr *inhdr;
0119 bool clear_soft_float;
0120 const char *infile;
0121 Elf32_Word e_flags;
0122 const void *inbuf;
0123 struct stat stat;
0124 void *outbuf;
0125 bool swap;
0126 int outfd;
0127 int infd;
0128
0129 atexit(cleanup);
0130 argv0 = argv[0];
0131
0132 if (argc != 3)
0133 fail("Usage: %s [infile] [outfile]\n", argv[0]);
0134
0135 infile = argv[1];
0136 outfile = argv[2];
0137
0138 infd = open(infile, O_RDONLY);
0139 if (infd < 0)
0140 fail("Cannot open %s: %s\n", infile, strerror(errno));
0141
0142 if (fstat(infd, &stat) != 0)
0143 fail("Failed stat for %s: %s\n", infile, strerror(errno));
0144
0145 inbuf = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, infd, 0);
0146 if (inbuf == MAP_FAILED)
0147 fail("Failed to map %s: %s\n", infile, strerror(errno));
0148
0149 close(infd);
0150
0151 inhdr = inbuf;
0152
0153 if (memcmp(&inhdr->e_ident, ELFMAG, SELFMAG) != 0)
0154 fail("Not an ELF file\n");
0155
0156 if (inhdr->e_ident[EI_CLASS] != ELFCLASS32)
0157 fail("Unsupported ELF class\n");
0158
0159 swap = inhdr->e_ident[EI_DATA] != HOST_ORDER;
0160
0161 if (read_elf_half(inhdr->e_type, swap) != ET_DYN)
0162 fail("Not a shared object\n");
0163
0164 if (read_elf_half(inhdr->e_machine, swap) != EM_ARM)
0165 fail("Unsupported architecture %#x\n", inhdr->e_machine);
0166
0167 e_flags = read_elf_word(inhdr->e_flags, swap);
0168
0169 if (EF_ARM_EABI_VERSION(e_flags) != EF_ARM_EABI_VER5) {
0170 fail("Unsupported EABI version %#x\n",
0171 EF_ARM_EABI_VERSION(e_flags));
0172 }
0173
0174 if (e_flags & EF_ARM_ABI_FLOAT_HARD)
0175 fail("Unexpected hard-float flag set in e_flags\n");
0176
0177 clear_soft_float = !!(e_flags & EF_ARM_ABI_FLOAT_SOFT);
0178
0179 outfd = open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
0180 if (outfd < 0)
0181 fail("Cannot open %s: %s\n", outfile, strerror(errno));
0182
0183 if (ftruncate(outfd, stat.st_size) != 0)
0184 fail("Cannot truncate %s: %s\n", outfile, strerror(errno));
0185
0186 outbuf = mmap(NULL, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED,
0187 outfd, 0);
0188 if (outbuf == MAP_FAILED)
0189 fail("Failed to map %s: %s\n", outfile, strerror(errno));
0190
0191 close(outfd);
0192
0193 memcpy(outbuf, inbuf, stat.st_size);
0194
0195 if (clear_soft_float) {
0196 Elf32_Ehdr *outhdr;
0197
0198 outhdr = outbuf;
0199 e_flags &= ~EF_ARM_ABI_FLOAT_SOFT;
0200 write_elf_word(e_flags, &outhdr->e_flags, swap);
0201 }
0202
0203 if (msync(outbuf, stat.st_size, MS_SYNC) != 0)
0204 fail("Failed to sync %s: %s\n", outfile, strerror(errno));
0205
0206 return EXIT_SUCCESS;
0207 }