dynamic_arm64.mx raw
1 package runtime
2
3 import (
4 "unsafe"
5 )
6
7 const debugLoader = false
8
9 const (
10 rAARCH64_RELATIVE = 1027
11 dtNULL = 0 /* Terminating entry. */
12 dtRELA = 7 /* Address of ElfNN_Rela relocations. */
13 dtRELASZ = 8 /* Total size of ElfNN_Rela relocations. */
14 )
15
16 /* ELF64 relocations that need an addend field. */
17 type rela64 struct {
18 Off uint64 /* Location to be relocated. */
19 Info uint64 /* Relocation type and symbol index. */
20 Addend int64 /* Addend. */
21 }
22
23 // ELF64 Dynamic structure. The ".dynamic" section contains an array of them.
24 type dyn64 struct {
25 Tag int64 /* Entry type. */
26 Val uint64 /* Integer/address value */
27 }
28
29 //export __dynamic_loader
30 func dynamicLoader(base uintptr, dyn *dyn64) {
31 var rela *rela64
32 relasz := uint64(0)
33
34 if debugLoader {
35 println("ASLR Base: ", base)
36 }
37
38 for dyn.Tag != dtNULL {
39 switch dyn.Tag {
40 case dtRELA:
41 rela = (*rela64)(unsafe.Pointer(base + uintptr(dyn.Val)))
42 case dtRELASZ:
43 relasz = uint64(dyn.Val) / uint64(unsafe.Sizeof(rela64{}))
44 }
45
46 ptr := unsafe.Pointer(dyn)
47 ptr = unsafe.Add(ptr, unsafe.Sizeof(dyn64{}))
48 dyn = (*dyn64)(ptr)
49 }
50
51 if rela == nil {
52 runtimePanic("bad reloc")
53 }
54
55 if debugLoader {
56 println("Sections to load: ", relasz)
57 }
58
59 for relasz > 0 && rela != nil {
60 switch rela.Info {
61 case rAARCH64_RELATIVE:
62 if debugLoader {
63 println("relocating ", uintptr(rela.Addend), " to ", base+uintptr(rela.Addend))
64 }
65 ptr := (*uint64)(unsafe.Pointer(base + uintptr(rela.Off)))
66 *ptr = uint64(base + uintptr(rela.Addend))
67 default:
68 if debugLoader {
69 println("unknown section to load:", rela.Info)
70 }
71 }
72
73 rptr := unsafe.Pointer(rela)
74 rptr = unsafe.Add(rptr, unsafe.Sizeof(rela64{}))
75 rela = (*rela64)(rptr)
76 relasz--
77 }
78 }
79