File indexing completed on 2025-05-11 08:24:16
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
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 #include <sys/cdefs.h>
0066 #ifndef lint
0067 __RCSID("$NetBSD: mdreloc.c,v 1.14 2020/06/16 21:01:30 joerg Exp $");
0068 #endif
0069
0070 #include <sys/types.h>
0071 #include <string.h>
0072 #include <errno.h>
0073 #include <inttypes.h>
0074 #include <sys/stat.h>
0075 #include <sys/endian.h>
0076
0077 #include <rtems/rtl/rtl.h>
0078 #include "rtl-elf.h"
0079 #include "rtl-error.h"
0080 #include <rtems/rtl/rtl-trace.h>
0081 #include <rtems/score/tls.h>
0082
0083 #include "rtl-unwind.h"
0084 #include "rtl-unwind-dw2.h"
0085
0086 struct tls_data {
0087 size_t td_tlsindex;
0088 Elf_Addr td_tlsoffs;
0089 };
0090
0091 rtems_rtl_elf_rel_status
0092 rtems_rtl_elf_reloc_rela (
0093 rtems_rtl_obj* obj,
0094 const Elf_Rela* rela,
0095 const rtems_rtl_obj_sect* sect,
0096 const char* symname,
0097 const Elf_Byte syminfo,
0098 const Elf_Word symvalue,
0099 const bool parsing
0100 );
0101
0102 #define __BITS(hi,lo) ((~((~(Elf_Addr)0)<<((hi)+1)))&((~(Elf_Addr)0)<<(lo)))
0103 #define WIDTHMASK(w) (0xffffffffffffffffUL >> (64 - (w)))
0104
0105 static inline bool
0106 checkoverflow(Elf_Addr addr, int bitwidth, Elf_Addr targetaddr,
0107 const char *bitscale, void *where, Elf64_Addr off)
0108 {
0109 const Elf_Addr mask = ~__BITS(bitwidth - 1, 0);
0110
0111 if (((addr & mask) != 0) && ((addr & mask) != mask)) {
0112 printf("kobj_reloc: Relocation 0x%" PRIxPTR " too far from %p"
0113 " (base+0x%jx) for %dbit%s\n",
0114 (uintptr_t)targetaddr, where, off, bitwidth, bitscale);
0115 return true;
0116 }
0117
0118 return false;
0119 }
0120
0121 static inline bool
0122 checkalign(Elf_Addr addr, int alignbyte, void *where, Elf64_Addr off)
0123 {
0124 if ((addr & (alignbyte - 1)) != 0) {
0125 printf("kobj_reloc: Relocation 0x%" PRIxPTR " unaligned at %p"
0126 " (base+0x%jx). must be aligned %d\n",
0127 (uintptr_t)addr, where, off, alignbyte);
0128 return true;
0129 }
0130 return false;
0131 }
0132
0133
0134
0135
0136
0137 #define ALLOW_UNTESTED_RELOCS 1
0138
0139 static void*
0140 set_veneer(void* trampoline, Elf_Addr target)
0141 {
0142
0143
0144
0145
0146
0147
0148
0149 uint64_t* tramp = (uint64_t*) trampoline;
0150 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
0151 *tramp++ = 0xd61f012058000049;
0152 #else
0153 *tramp++ = 0xd61f012058000049;
0154 #endif
0155 *tramp++ = (uint64_t) target;
0156 return tramp;
0157 }
0158
0159 static size_t
0160 get_veneer_size(int type)
0161 {
0162 (void) type;
0163 return 16;
0164 }
0165
0166 uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj)
0167 {
0168 (void) obj;
0169 return sizeof(uint64_t);
0170 }
0171
0172 size_t
0173 rtems_rtl_elf_relocate_tramp_max_size (void)
0174 {
0175 return 16;
0176 }
0177
0178 uint32_t
0179 rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj,
0180 const Elf_Shdr* shdr)
0181 {
0182 return 0;
0183 }
0184
0185 uint32_t
0186 rtems_rtl_elf_arch_parse_section (const rtems_rtl_obj* obj,
0187 int section,
0188 const char* name,
0189 const Elf_Shdr* shdr,
0190 const uint32_t flags)
0191 {
0192 (void) obj;
0193 (void) section;
0194 (void) name;
0195 (void) shdr;
0196 return flags;
0197 }
0198
0199 bool
0200 rtems_rtl_elf_arch_section_alloc (const rtems_rtl_obj* obj,
0201 rtems_rtl_obj_sect* sect)
0202 {
0203 (void) obj;
0204 (void) sect;
0205 return false;
0206 }
0207
0208 bool
0209 rtems_rtl_elf_arch_section_free (const rtems_rtl_obj* obj,
0210 rtems_rtl_obj_sect* sect)
0211 {
0212 (void) obj;
0213 (void) sect;
0214 return false;
0215 }
0216
0217 bool
0218 rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
0219 {
0220 return true;
0221 }
0222
0223 rtems_rtl_elf_rel_status
0224 rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
0225 const Elf_Rela* rela,
0226 const rtems_rtl_obj_sect* sect,
0227 const char* symname,
0228 const Elf_Byte syminfo,
0229 const Elf_Word symvalue,
0230 const bool parsing)
0231 {
0232 Elf64_Addr *where;
0233 Elf32_Addr *where32;
0234 Elf_Addr off = rela->r_offset;
0235 Elf_Addr target;
0236 Elf_Addr raddr;
0237 uint32_t *insn, immhi, immlo, shift;
0238
0239 where = (Elf_Addr *)(sect->base + rela->r_offset);
0240 where32 = (void *)where;
0241
0242 insn = (uint32_t *)where;
0243
0244
0245
0246
0247
0248
0249
0250
0251 switch (ELF_R_TYPE(rela->r_info)) {
0252 case R_TYPE(NONE):
0253 if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
0254 printf ("rtl: NONE %p in %s\n", where, rtems_rtl_obj_oname (obj));
0255 }
0256 break;
0257
0258 case R_TYPE(ABS64):
0259 case R_TYPE(GLOB_DAT):
0260 if (!parsing) {
0261 target = (Elf_Addr)symvalue + rela->r_addend;
0262
0263 if (*where != target)
0264 *where = target;
0265
0266 if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0267 printf ("rtl: reloc 64/GLOB_DAT in %s --> %p in %s\n",
0268 sect->name, (void *)(uintptr_t)*where,
0269 rtems_rtl_obj_oname (obj));
0270 }
0271 break;
0272
0273
0274
0275
0276
0277
0278
0279 case R_TYPE(RELATIVE):
0280 if (!parsing) {
0281 *where = (Elf_Addr)(uintptr_t)(sect->base + rela->r_addend);
0282 if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0283 printf ("rtl: reloc RELATIVE in %s --> %p in %s\n",
0284 sect->name, (void *)(uintptr_t)*where,
0285 rtems_rtl_obj_oname (obj));
0286 }
0287 break;
0288
0289 case R_TYPE(COPY):
0290
0291
0292
0293
0294
0295
0296 printf("rtl: reloc COPY (please report)\n");
0297 break;
0298
0299 case R_AARCH64_ADD_TPREL_HI12:
0300 case R_AARCH64_ADD_TPREL_LO12:
0301 case R_AARCH64_ADD_TPREL_LO12_NC:
0302 uint32_t of_check = 0;
0303 switch (ELF_R_TYPE(rela->r_info)) {
0304 case R_AARCH64_ADD_TPREL_LO12:
0305 of_check = 212;
0306
0307 case R_AARCH64_ADD_TPREL_LO12_NC:
0308 shift = 0;
0309 break;
0310 case R_AARCH64_ADD_TPREL_HI12:
0311 of_check = 224;
0312 shift = 12;
0313 break;
0314 default:
0315 printf("illegal rtype: %" PRIu64 "\n", ELF_R_TYPE(rela->r_info));
0316 break;
0317 }
0318
0319 if (!parsing) {
0320 target = (Elf_Addr)symvalue;
0321 target >>= shift;
0322 target &= WIDTHMASK(12);
0323 if (of_check && target >= of_check) {
0324 return rtems_rtl_elf_rel_failure;
0325 }
0326 *insn = htole32(
0327 (le32toh(*insn) & ~__BITS(21,10)) | (target << 10));
0328 }
0329 break;
0330
0331 case R_AARCH64_ADD_ABS_LO12_NC:
0332 case R_AARCH64_LDST8_ABS_LO12_NC:
0333 case R_AARCH_LDST16_ABS_LO12_NC:
0334 case R_AARCH_LDST32_ABS_LO12_NC:
0335 case R_AARCH_LDST64_ABS_LO12_NC:
0336 case R_AARCH64_LDST128_ABS_LO12_NC:
0337 switch (ELF_R_TYPE(rela->r_info)) {
0338 case R_AARCH64_ADD_ABS_LO12_NC:
0339 case R_AARCH64_LDST8_ABS_LO12_NC:
0340 shift = 0;
0341 break;
0342 case R_AARCH_LDST16_ABS_LO12_NC:
0343 shift = 1;
0344 break;
0345 case R_AARCH_LDST32_ABS_LO12_NC:
0346 shift = 2;
0347 break;
0348 case R_AARCH_LDST64_ABS_LO12_NC:
0349 shift = 3;
0350 break;
0351 case R_AARCH64_LDST128_ABS_LO12_NC:
0352 shift = 4;
0353 break;
0354 default:
0355 printf("illegal rtype: %" PRIu64 "\n", ELF_R_TYPE(rela->r_info));
0356 break;
0357 }
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367 if (!parsing) {
0368 target = (Elf_Addr)symvalue + rela->r_addend;
0369 if (checkalign(target, 1 << shift, where, off)) {
0370 printf ("rtl: reloc checkalign failed in %s --> %p in %s\n",
0371 sect->name, (void *)(uintptr_t)*where,
0372 rtems_rtl_obj_oname (obj));
0373 printf("ELF_R_TYPE is : %" PRIu64 "\n", ELF_R_TYPE(rela->r_info));
0374 break;
0375 }
0376 target &= WIDTHMASK(12);
0377 target >>= shift;
0378 *insn = htole32(
0379 (le32toh(*insn) & ~__BITS(21,10)) | (target << 10));
0380 }
0381 break;
0382
0383 case R_AARCH64_ADR_PREL_PG_HI21:
0384
0385
0386
0387
0388 if (!parsing) {
0389 target = (Elf_Addr)symvalue + rela->r_addend;
0390 target = target >> 12;
0391 raddr = target << 12;
0392 target -= (uintptr_t)where >> 12;
0393
0394 if (checkoverflow(target, 21, raddr, " x 4k", where, off)) {
0395 printf("]] %d\n", __LINE__);
0396 return rtems_rtl_elf_rel_failure;
0397 }
0398
0399 immlo = target & WIDTHMASK(2);
0400 immhi = (target >> 2) & WIDTHMASK(19);
0401 *insn = htole32((le32toh(*insn) &
0402 ~(__BITS(30,29) | __BITS(23,5))) |
0403 (immlo << 29) | (immhi << 5));
0404 }
0405 break;
0406
0407 case R_AARCH_JUMP26:
0408 case R_AARCH_CALL26:
0409
0410
0411
0412
0413
0414 if (parsing && sect->base == 0) {
0415 if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0416 printf ("rtl: JUMP26/PC26/CALL tramp cache\n");
0417 return rtems_rtl_elf_rel_tramp_cache;
0418 }
0419
0420 raddr = (Elf_Addr)symvalue + rela->r_addend;
0421 target = raddr - (uintptr_t)where;
0422
0423 if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0424 printf (
0425 "rtl: JUMP26/PC26/CALL: insn=%p where=%p target=%p raddr=%p parsing=%d\n",
0426 insn, (void*) where, (void*)(uintptr_t) target, (void*)(uintptr_t) raddr,
0427 parsing
0428 );
0429
0430 if (checkalign(target, 4, where, off)) {
0431 return rtems_rtl_elf_rel_failure;
0432 }
0433
0434 target = (intptr_t)target >> 2;
0435
0436 if (((Elf_Sword)target > 0x1FFFFFF) || ((Elf_Sword)target < -0x2000000)) {
0437 Elf_Word tramp_addr;
0438 size_t tramp_size = get_veneer_size(ELF_R_TYPE(rela->r_info));
0439
0440 if (parsing) {
0441 if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0442 printf ("rtl: JUMP26/PC26/CALL tramp add\n");
0443 return rtems_rtl_elf_rel_tramp_add;
0444 }
0445
0446 if (!rtems_rtl_obj_has_tramp_space (obj, tramp_size)) {
0447 rtems_rtl_set_error (EINVAL,
0448 "%s: CALL/JUMP26: overflow: no tramp memory",
0449 sect->name);
0450 return rtems_rtl_elf_rel_failure;
0451 }
0452
0453 tramp_addr = ((Elf_Addr)(uintptr_t) obj->tramp_brk) | (symvalue & 1);
0454 obj->tramp_brk = set_veneer(obj->tramp_brk, symvalue);
0455 target = tramp_addr + rela->r_addend - (uintptr_t)where;
0456 target = (uintptr_t)target >> 2;
0457 }
0458
0459 if (checkoverflow(target, 26, raddr, " word", where, off)) {
0460 return rtems_rtl_elf_rel_failure;
0461 }
0462
0463 if (!parsing) {
0464 target &= WIDTHMASK(26);
0465 *insn = htole32((le32toh(*insn) & ~__BITS(25,0)) | target);
0466 }
0467
0468 break;
0469
0470 case R_AARCH64_PREL32:
0471
0472
0473
0474
0475 if (!parsing) {
0476 raddr = (Elf_Addr)symvalue + rela->r_addend;
0477 target = raddr - (uintptr_t)where;
0478 if (checkoverflow(target, 32, raddr, "", where, off)) {
0479 printf("]] %d\n", __LINE__);
0480 return rtems_rtl_elf_rel_failure;
0481 }
0482 *where32 = target;
0483 }
0484 break;
0485
0486 case R_TYPE(TLSDESC):
0487 printf ("rtl: reloc TLSDESC in %s --> %p in %s\n",
0488 sect->name, (void *)(uintptr_t)*where,
0489 rtems_rtl_obj_oname (obj));
0490 break;
0491
0492 case R_TLS_TYPE(TLS_DTPREL):
0493 printf ("rtl: reloc TLS_DTPREL in %s --> %p in %s\n",
0494 sect->name, (void *)(uintptr_t)*where,
0495 rtems_rtl_obj_oname (obj));
0496 break;
0497 case R_TLS_TYPE(TLS_DTPMOD):
0498 printf ("rtl: reloc TLS_DTPMOD in %s --> %p in %s\n",
0499 sect->name, (void *)(uintptr_t)*where,
0500 rtems_rtl_obj_oname (obj));
0501 break;
0502
0503 case R_TLS_TYPE(TLS_TPREL):
0504 printf ("rtl: reloc TLS_TPREL in %s --> %p in %s\n",
0505 sect->name, (void *)(uintptr_t)*where,
0506 rtems_rtl_obj_oname (obj));
0507 break;
0508
0509 default:
0510 printf ("rtl: Unsupported relocation type (%" PRIu64
0511 ") in %s --> %p in %s\n",
0512 ELF_R_TYPE(rela->r_info), sect->name, (void *)where,
0513 rtems_rtl_obj_oname (obj));
0514 return rtems_rtl_elf_rel_failure;
0515 }
0516
0517 return rtems_rtl_elf_rel_no_error;
0518 }
0519
0520 rtems_rtl_elf_rel_status
0521 rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
0522 const Elf_Rela* rela,
0523 const rtems_rtl_obj_sect* sect,
0524 const char* symname,
0525 const Elf_Byte syminfo,
0526 const Elf_Word symvalue)
0527 {
0528 return rtems_rtl_elf_reloc_rela (obj,
0529 rela,
0530 sect,
0531 symname,
0532 syminfo,
0533 symvalue,
0534 true);
0535 }
0536
0537 rtems_rtl_elf_rel_status
0538 rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
0539 const Elf_Rela* rela,
0540 const rtems_rtl_obj_sect* sect,
0541 const char* symname,
0542 const Elf_Byte syminfo,
0543 const Elf_Word symvalue)
0544 {
0545 return rtems_rtl_elf_reloc_rela (obj,
0546 rela,
0547 sect,
0548 symname,
0549 syminfo,
0550 symvalue,
0551 false);
0552 }
0553
0554 rtems_rtl_elf_rel_status
0555 rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
0556 const Elf_Rel* rel,
0557 const rtems_rtl_obj_sect* sect,
0558 const char* symname,
0559 const Elf_Byte syminfo,
0560 const Elf_Word symvalue)
0561 {
0562 rtems_rtl_set_error (EINVAL, "rela type record not supported");
0563 return rtems_rtl_elf_rel_failure;
0564 }
0565
0566 rtems_rtl_elf_rel_status
0567 rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
0568 const Elf_Rel* rel,
0569 const rtems_rtl_obj_sect* sect,
0570 const char* symname,
0571 const Elf_Byte syminfo,
0572 const Elf_Word symvalue)
0573 {
0574 rtems_rtl_set_error (EINVAL, "rela type record not supported");
0575 return rtems_rtl_elf_rel_failure;
0576 }
0577
0578 bool
0579 rtems_rtl_elf_unwind_parse (const rtems_rtl_obj* obj,
0580 const char* name,
0581 uint32_t flags) {
0582 return rtems_rtl_elf_unwind_dw2_parse (obj, name, flags);
0583 }
0584
0585 bool
0586 rtems_rtl_elf_unwind_register (rtems_rtl_obj* obj) {
0587 return rtems_rtl_elf_unwind_dw2_register (obj);
0588 }
0589
0590 bool
0591 rtems_rtl_elf_unwind_deregister (rtems_rtl_obj* obj) {
0592 return rtems_rtl_elf_unwind_dw2_deregister (obj);
0593 }