Skip to content

Commit 58b9fb1

Browse files
eukarpovgithub-actions
authored andcommitted
Fix relocations in dynamic linking (#9)
The patch implements the required changes to support runtime relocations in MinGW. For 26-bit relocations, the linker generates a jump stub, as a single opcode is not sufficient for relocation. Co-authored-by: Evgeny Karpov <[email protected]>
1 parent 3156503 commit 58b9fb1

File tree

1 file changed

+16
-11
lines changed

1 file changed

+16
-11
lines changed

mingw-w64-crt/crt/pseudo-reloc.c

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -503,23 +503,28 @@ do_pseudo_reloc (void * start, void * end, void * base)
503503
break;
504504
#ifdef __aarch64__
505505
case 12:
506-
reldata = reldata & 0xfff;
507-
opcode &= 0xffc003ff;
508-
opcode |= reldata << 10;
506+
/* Replace add Xn, Xn, :lo12:label with ldr Xn, [Xn, :lo12:__imp__func].
507+
That loads the address of _func into Xn. */
508+
opcode = 0xf9400000 | (opcode & 0x3ff); // ldr
509+
reldata = ((ptrdiff_t) base + r->sym) & ((1 << 12) - 1);
510+
reldata >>= 3;
511+
opcode |= reldata << 10;
509512
__write_memory ((void *) reloc_target, &opcode, 4);
510513
break;
511514
case 21:
515+
/* Replace adrp Xn, label with adrp Xn, __imp__func. */
512516
opcode &= 0x9f00001f;
513-
reldata >>= 12;
514-
opcode |= (reldata & 0x3) << 29;
515-
opcode |= (reldata & 0x1ffffc) << 3;
516-
__write_memory ((void *) reloc_target, &opcode, 4);
517-
break;
518-
case 26:
519-
opcode &= 0xfc000000;
520-
opcode |= (reldata >> 2) & 0x3ffffff;
517+
reldata = (((ptrdiff_t) base + r->sym) >> 12)
518+
- (((ptrdiff_t) base + r->target) >> 12);
519+
reldata &= (1 << 21) - 1;
520+
opcode |= (reldata & 3) << 29;
521+
reldata >>= 2;
522+
opcode |= reldata << 5;
521523
__write_memory ((void *) reloc_target, &opcode, 4);
522524
break;
525+
/* A note regarding 26 bits relocation.
526+
A single opcode is not sufficient for 26 bits relocation in dynamic linking.
527+
The linker generates a jump stub instead. */
523528
#endif
524529
case 32:
525530
__write_memory ((void *) reloc_target, &reldata, 4);

0 commit comments

Comments
 (0)