github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/runtime/dynamic_arm64.go (about)

     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  }