github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/runtime/os_linux.go (about) 1 //go:build linux && !baremetal && !nintendoswitch && !wasip1 && !wasm_unknown 2 3 package runtime 4 5 // This file is for systems that are _actually_ Linux (not systems that pretend 6 // to be Linux, like baremetal systems). 7 8 import "unsafe" 9 10 const GOOS = "linux" 11 12 const ( 13 // See https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/mman-common.h 14 flag_PROT_READ = 0x1 15 flag_PROT_WRITE = 0x2 16 flag_MAP_PRIVATE = 0x2 17 flag_MAP_ANONYMOUS = 0x20 18 ) 19 20 // Source: https://github.com/torvalds/linux/blob/master/include/uapi/linux/time.h 21 const ( 22 clock_REALTIME = 0 23 clock_MONOTONIC_RAW = 4 24 ) 25 26 // For the definition of the various header structs, see: 27 // https://refspecs.linuxfoundation.org/elf/elf.pdf 28 // Also useful: 29 // https://en.wikipedia.org/wiki/Executable_and_Linkable_Format 30 type elfHeader struct { 31 ident_magic uint32 32 ident_class uint8 33 ident_data uint8 34 ident_version uint8 35 ident_osabi uint8 36 ident_abiversion uint8 37 _ [7]byte // reserved 38 filetype uint16 39 machine uint16 40 version uint32 41 entry uintptr 42 phoff uintptr 43 shoff uintptr 44 flags uint32 45 ehsize uint16 46 phentsize uint16 47 phnum uint16 48 shentsize uint16 49 shnum uint16 50 shstrndx uint16 51 } 52 53 type elfProgramHeader64 struct { 54 _type uint32 55 flags uint32 56 offset uintptr 57 vaddr uintptr 58 paddr uintptr 59 filesz uintptr 60 memsz uintptr 61 align uintptr 62 } 63 64 type elfProgramHeader32 struct { 65 _type uint32 66 offset uintptr 67 vaddr uintptr 68 paddr uintptr 69 filesz uintptr 70 memsz uintptr 71 flags uint32 72 align uintptr 73 } 74 75 // ELF header of the currently running process. 76 // 77 //go:extern __ehdr_start 78 var ehdr_start elfHeader 79 80 // findGlobals finds globals in the .data/.bss sections. 81 // It parses the ELF program header to find writable segments. 82 func findGlobals(found func(start, end uintptr)) { 83 // Relevant constants from the ELF specification. 84 // See: https://refspecs.linuxfoundation.org/elf/elf.pdf 85 const ( 86 PT_LOAD = 1 87 PF_W = 0x2 // program flag: write access 88 ) 89 90 headerPtr := unsafe.Pointer(uintptr(unsafe.Pointer(&ehdr_start)) + ehdr_start.phoff) 91 for i := 0; i < int(ehdr_start.phnum); i++ { 92 // Look for a writable segment and scan its contents. 93 // There is a little bit of duplication here, which is unfortunate. But 94 // the alternative would be to put elfProgramHeader in separate files 95 // which is IMHO a lot uglier. If only the ELF spec was consistent 96 // between 32-bit and 64-bit... 97 if TargetBits == 64 { 98 header := (*elfProgramHeader64)(headerPtr) 99 if header._type == PT_LOAD && header.flags&PF_W != 0 { 100 start := header.vaddr 101 end := start + header.memsz 102 found(start, end) 103 } 104 } else { 105 header := (*elfProgramHeader32)(headerPtr) 106 if header._type == PT_LOAD && header.flags&PF_W != 0 { 107 start := header.vaddr 108 end := start + header.memsz 109 found(start, end) 110 } 111 } 112 headerPtr = unsafe.Add(headerPtr, ehdr_start.phentsize) 113 } 114 } 115 116 //export getpagesize 117 func libc_getpagesize() int 118 119 //go:linkname syscall_Getpagesize syscall.Getpagesize 120 func syscall_Getpagesize() int { 121 return libc_getpagesize() 122 } 123 124 func hardwareRand() (n uint64, ok bool) { 125 read := libc_getrandom(unsafe.Pointer(&n), 8, 0) 126 if read != 8 { 127 return 0, false 128 } 129 return n, true 130 } 131 132 // ssize_t getrandom(void buf[.buflen], size_t buflen, unsigned int flags); 133 // 134 //export getrandom 135 func libc_getrandom(buf unsafe.Pointer, buflen uintptr, flags uint32) uint32