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 #include <elf.h>
0028 #include <endian.h>
0029 #include <errno.h>
0030 #include <fcntl.h>
0031 #include <stdbool.h>
0032 #include <stdio.h>
0033 #include <stdlib.h>
0034 #include <string.h>
0035 #include <sys/mman.h>
0036 #include <sys/types.h>
0037 #include <sys/stat.h>
0038 #include <unistd.h>
0039
0040 #include <generated/autoconf.h>
0041
0042 #define HYP_SECTION_PREFIX ".hyp"
0043 #define HYP_RELOC_SECTION ".hyp.reloc"
0044 #define HYP_SECTION_SYMBOL_PREFIX "__hyp_section_"
0045
0046
0047
0048
0049
0050 #ifndef R_AARCH64_ABS64
0051 #define R_AARCH64_ABS64 257
0052 #endif
0053 #ifndef R_AARCH64_PREL64
0054 #define R_AARCH64_PREL64 260
0055 #endif
0056 #ifndef R_AARCH64_PREL32
0057 #define R_AARCH64_PREL32 261
0058 #endif
0059 #ifndef R_AARCH64_PREL16
0060 #define R_AARCH64_PREL16 262
0061 #endif
0062 #ifndef R_AARCH64_PLT32
0063 #define R_AARCH64_PLT32 314
0064 #endif
0065 #ifndef R_AARCH64_LD_PREL_LO19
0066 #define R_AARCH64_LD_PREL_LO19 273
0067 #endif
0068 #ifndef R_AARCH64_ADR_PREL_LO21
0069 #define R_AARCH64_ADR_PREL_LO21 274
0070 #endif
0071 #ifndef R_AARCH64_ADR_PREL_PG_HI21
0072 #define R_AARCH64_ADR_PREL_PG_HI21 275
0073 #endif
0074 #ifndef R_AARCH64_ADR_PREL_PG_HI21_NC
0075 #define R_AARCH64_ADR_PREL_PG_HI21_NC 276
0076 #endif
0077 #ifndef R_AARCH64_ADD_ABS_LO12_NC
0078 #define R_AARCH64_ADD_ABS_LO12_NC 277
0079 #endif
0080 #ifndef R_AARCH64_LDST8_ABS_LO12_NC
0081 #define R_AARCH64_LDST8_ABS_LO12_NC 278
0082 #endif
0083 #ifndef R_AARCH64_TSTBR14
0084 #define R_AARCH64_TSTBR14 279
0085 #endif
0086 #ifndef R_AARCH64_CONDBR19
0087 #define R_AARCH64_CONDBR19 280
0088 #endif
0089 #ifndef R_AARCH64_JUMP26
0090 #define R_AARCH64_JUMP26 282
0091 #endif
0092 #ifndef R_AARCH64_CALL26
0093 #define R_AARCH64_CALL26 283
0094 #endif
0095 #ifndef R_AARCH64_LDST16_ABS_LO12_NC
0096 #define R_AARCH64_LDST16_ABS_LO12_NC 284
0097 #endif
0098 #ifndef R_AARCH64_LDST32_ABS_LO12_NC
0099 #define R_AARCH64_LDST32_ABS_LO12_NC 285
0100 #endif
0101 #ifndef R_AARCH64_LDST64_ABS_LO12_NC
0102 #define R_AARCH64_LDST64_ABS_LO12_NC 286
0103 #endif
0104 #ifndef R_AARCH64_MOVW_PREL_G0
0105 #define R_AARCH64_MOVW_PREL_G0 287
0106 #endif
0107 #ifndef R_AARCH64_MOVW_PREL_G0_NC
0108 #define R_AARCH64_MOVW_PREL_G0_NC 288
0109 #endif
0110 #ifndef R_AARCH64_MOVW_PREL_G1
0111 #define R_AARCH64_MOVW_PREL_G1 289
0112 #endif
0113 #ifndef R_AARCH64_MOVW_PREL_G1_NC
0114 #define R_AARCH64_MOVW_PREL_G1_NC 290
0115 #endif
0116 #ifndef R_AARCH64_MOVW_PREL_G2
0117 #define R_AARCH64_MOVW_PREL_G2 291
0118 #endif
0119 #ifndef R_AARCH64_MOVW_PREL_G2_NC
0120 #define R_AARCH64_MOVW_PREL_G2_NC 292
0121 #endif
0122 #ifndef R_AARCH64_MOVW_PREL_G3
0123 #define R_AARCH64_MOVW_PREL_G3 293
0124 #endif
0125 #ifndef R_AARCH64_LDST128_ABS_LO12_NC
0126 #define R_AARCH64_LDST128_ABS_LO12_NC 299
0127 #endif
0128
0129
0130 static struct {
0131 const char *path;
0132 char *begin;
0133 size_t size;
0134 Elf64_Ehdr *ehdr;
0135 Elf64_Shdr *sh_table;
0136 const char *sh_string;
0137 } elf;
0138
0139 #if defined(CONFIG_CPU_LITTLE_ENDIAN)
0140
0141 #define elf16toh(x) le16toh(x)
0142 #define elf32toh(x) le32toh(x)
0143 #define elf64toh(x) le64toh(x)
0144
0145 #define ELFENDIAN ELFDATA2LSB
0146
0147 #elif defined(CONFIG_CPU_BIG_ENDIAN)
0148
0149 #define elf16toh(x) be16toh(x)
0150 #define elf32toh(x) be32toh(x)
0151 #define elf64toh(x) be64toh(x)
0152
0153 #define ELFENDIAN ELFDATA2MSB
0154
0155 #else
0156
0157 #error PDP-endian sadly unsupported...
0158
0159 #endif
0160
0161 #define fatal_error(fmt, ...) \
0162 ({ \
0163 fprintf(stderr, "error: %s: " fmt "\n", \
0164 elf.path, ## __VA_ARGS__); \
0165 exit(EXIT_FAILURE); \
0166 __builtin_unreachable(); \
0167 })
0168
0169 #define fatal_perror(msg) \
0170 ({ \
0171 fprintf(stderr, "error: %s: " msg ": %s\n", \
0172 elf.path, strerror(errno)); \
0173 exit(EXIT_FAILURE); \
0174 __builtin_unreachable(); \
0175 })
0176
0177 #define assert_op(lhs, rhs, fmt, op) \
0178 ({ \
0179 typeof(lhs) _lhs = (lhs); \
0180 typeof(rhs) _rhs = (rhs); \
0181 \
0182 if (!(_lhs op _rhs)) { \
0183 fatal_error("assertion " #lhs " " #op " " #rhs \
0184 " failed (lhs=" fmt ", rhs=" fmt \
0185 ", line=%d)", _lhs, _rhs, __LINE__); \
0186 } \
0187 })
0188
0189 #define assert_eq(lhs, rhs, fmt) assert_op(lhs, rhs, fmt, ==)
0190 #define assert_ne(lhs, rhs, fmt) assert_op(lhs, rhs, fmt, !=)
0191 #define assert_lt(lhs, rhs, fmt) assert_op(lhs, rhs, fmt, <)
0192 #define assert_ge(lhs, rhs, fmt) assert_op(lhs, rhs, fmt, >=)
0193
0194
0195
0196
0197
0198 #define elf_ptr(type, off) ((type *)(elf.begin + (off)))
0199
0200
0201 #define for_each_section(var) \
0202 for (var = elf.sh_table; var < elf.sh_table + elf16toh(elf.ehdr->e_shnum); ++var)
0203
0204
0205 #define for_each_rela(shdr, var) \
0206 for (var = elf_ptr(Elf64_Rela, elf64toh(shdr->sh_offset)); \
0207 var < elf_ptr(Elf64_Rela, elf64toh(shdr->sh_offset) + elf64toh(shdr->sh_size)); var++)
0208
0209
0210 static inline bool starts_with(const char *str, const char *prefix)
0211 {
0212 return memcmp(str, prefix, strlen(prefix)) == 0;
0213 }
0214
0215
0216 static inline const char *section_name(Elf64_Shdr *shdr)
0217 {
0218 return elf.sh_string + elf32toh(shdr->sh_name);
0219 }
0220
0221
0222 static inline const char *section_begin(Elf64_Shdr *shdr)
0223 {
0224 return elf_ptr(char, elf64toh(shdr->sh_offset));
0225 }
0226
0227
0228 static inline Elf64_Shdr *section_by_off(Elf64_Off off)
0229 {
0230 assert_ne(off, 0UL, "%lu");
0231 return elf_ptr(Elf64_Shdr, off);
0232 }
0233
0234
0235 static inline Elf64_Shdr *section_by_idx(uint16_t idx)
0236 {
0237 assert_ne(idx, SHN_UNDEF, "%u");
0238 return &elf.sh_table[idx];
0239 }
0240
0241
0242
0243
0244
0245 static void init_elf(const char *path)
0246 {
0247 int fd, ret;
0248 struct stat stat;
0249
0250
0251 elf.path = path;
0252
0253
0254 fd = open(path, O_RDONLY);
0255 if (fd < 0)
0256 fatal_perror("Could not open ELF file");
0257
0258
0259 ret = fstat(fd, &stat);
0260 if (ret < 0) {
0261 close(fd);
0262 fatal_perror("Could not get status of ELF file");
0263 }
0264
0265
0266 elf.begin = mmap(0, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
0267 if (elf.begin == MAP_FAILED) {
0268 close(fd);
0269 fatal_perror("Could not mmap ELF file");
0270 }
0271
0272
0273 close(fd);
0274
0275
0276 assert_ge(stat.st_size, sizeof(*elf.ehdr), "%lu");
0277 elf.ehdr = elf_ptr(Elf64_Ehdr, 0);
0278
0279
0280 assert_eq(elf.ehdr->e_ident[EI_MAG0], ELFMAG0, "0x%x");
0281 assert_eq(elf.ehdr->e_ident[EI_MAG1], ELFMAG1, "0x%x");
0282 assert_eq(elf.ehdr->e_ident[EI_MAG2], ELFMAG2, "0x%x");
0283 assert_eq(elf.ehdr->e_ident[EI_MAG3], ELFMAG3, "0x%x");
0284
0285
0286 assert_eq(elf.ehdr->e_ident[EI_CLASS], ELFCLASS64, "%u");
0287 assert_eq(elf.ehdr->e_ident[EI_DATA], ELFENDIAN, "%u");
0288 assert_eq(elf16toh(elf.ehdr->e_type), ET_REL, "%u");
0289 assert_eq(elf16toh(elf.ehdr->e_machine), EM_AARCH64, "%u");
0290
0291
0292 elf.sh_table = section_by_off(elf64toh(elf.ehdr->e_shoff));
0293 elf.sh_string = section_begin(section_by_idx(elf16toh(elf.ehdr->e_shstrndx)));
0294 }
0295
0296
0297 static void emit_prologue(void)
0298 {
0299 printf(".data\n"
0300 ".pushsection " HYP_RELOC_SECTION ", \"a\"\n");
0301 }
0302
0303
0304 static void emit_section_prologue(const char *sh_orig_name)
0305 {
0306
0307 printf(".global %s%s\n", HYP_SECTION_SYMBOL_PREFIX, sh_orig_name);
0308 }
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326 static void emit_rela_abs64(Elf64_Rela *rela, const char *sh_orig_name)
0327 {
0328
0329 static size_t reloc_offset;
0330
0331
0332 printf(".word 0\n");
0333
0334
0335
0336
0337
0338
0339
0340 printf(".reloc %lu, R_AARCH64_PREL32, %s%s + 0x%lx\n",
0341 reloc_offset, HYP_SECTION_SYMBOL_PREFIX, sh_orig_name,
0342 elf64toh(rela->r_offset));
0343
0344 reloc_offset += 4;
0345 }
0346
0347
0348 static void emit_epilogue(void)
0349 {
0350 printf(".popsection\n");
0351 }
0352
0353
0354
0355
0356
0357
0358
0359
0360 static void emit_rela_section(Elf64_Shdr *sh_rela)
0361 {
0362 Elf64_Shdr *sh_orig = &elf.sh_table[elf32toh(sh_rela->sh_info)];
0363 const char *sh_orig_name = section_name(sh_orig);
0364 Elf64_Rela *rela;
0365
0366
0367 if (!starts_with(sh_orig_name, HYP_SECTION_PREFIX))
0368 return;
0369
0370 emit_section_prologue(sh_orig_name);
0371
0372 for_each_rela(sh_rela, rela) {
0373 uint32_t type = (uint32_t)elf64toh(rela->r_info);
0374
0375
0376 assert_lt(elf64toh(rela->r_offset), elf64toh(sh_orig->sh_size), "0x%lx");
0377
0378 switch (type) {
0379
0380
0381
0382
0383 case R_AARCH64_ABS64:
0384 emit_rela_abs64(rela, sh_orig_name);
0385 break;
0386
0387 case R_AARCH64_PREL64:
0388 case R_AARCH64_PREL32:
0389 case R_AARCH64_PREL16:
0390 case R_AARCH64_PLT32:
0391 break;
0392
0393 case R_AARCH64_LD_PREL_LO19:
0394 case R_AARCH64_ADR_PREL_LO21:
0395 case R_AARCH64_ADR_PREL_PG_HI21:
0396 case R_AARCH64_ADR_PREL_PG_HI21_NC:
0397 case R_AARCH64_ADD_ABS_LO12_NC:
0398 case R_AARCH64_LDST8_ABS_LO12_NC:
0399 case R_AARCH64_LDST16_ABS_LO12_NC:
0400 case R_AARCH64_LDST32_ABS_LO12_NC:
0401 case R_AARCH64_LDST64_ABS_LO12_NC:
0402 case R_AARCH64_LDST128_ABS_LO12_NC:
0403 break;
0404
0405 case R_AARCH64_TSTBR14:
0406 case R_AARCH64_CONDBR19:
0407 case R_AARCH64_JUMP26:
0408 case R_AARCH64_CALL26:
0409 break;
0410
0411 case R_AARCH64_MOVW_PREL_G0:
0412 case R_AARCH64_MOVW_PREL_G0_NC:
0413 case R_AARCH64_MOVW_PREL_G1:
0414 case R_AARCH64_MOVW_PREL_G1_NC:
0415 case R_AARCH64_MOVW_PREL_G2:
0416 case R_AARCH64_MOVW_PREL_G2_NC:
0417 case R_AARCH64_MOVW_PREL_G3:
0418 break;
0419 default:
0420 fatal_error("Unexpected RELA type %u", type);
0421 }
0422 }
0423 }
0424
0425
0426 static void emit_all_relocs(void)
0427 {
0428 Elf64_Shdr *shdr;
0429
0430 for_each_section(shdr) {
0431 switch (elf32toh(shdr->sh_type)) {
0432 case SHT_REL:
0433 fatal_error("Unexpected SHT_REL section \"%s\"",
0434 section_name(shdr));
0435 case SHT_RELA:
0436 emit_rela_section(shdr);
0437 break;
0438 }
0439 }
0440 }
0441
0442 int main(int argc, const char **argv)
0443 {
0444 if (argc != 2) {
0445 fprintf(stderr, "Usage: %s <elf_input>\n", argv[0]);
0446 return EXIT_FAILURE;
0447 }
0448
0449 init_elf(argv[1]);
0450
0451 emit_prologue();
0452 emit_all_relocs();
0453 emit_epilogue();
0454
0455 return EXIT_SUCCESS;
0456 }