1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ld 6 7 import ( 8 "bytes" 9 "encoding/binary" 10 "log" 11 "os" 12 "runtime" 13 "runtime/pprof" 14 "strings" 15 "time" 16 ) 17 18 func cstring(x []byte) string { 19 i := bytes.IndexByte(x, '\x00') 20 if i >= 0 { 21 x = x[:i] 22 } 23 return string(x) 24 } 25 26 func tokenize(s string) []string { 27 var f []string 28 for { 29 s = strings.TrimLeft(s, " \t\r\n") 30 if s == "" { 31 break 32 } 33 quote := false 34 i := 0 35 for ; i < len(s); i++ { 36 if s[i] == '\'' { 37 if quote && i+1 < len(s) && s[i+1] == '\'' { 38 i++ 39 continue 40 } 41 quote = !quote 42 } 43 if !quote && (s[i] == ' ' || s[i] == '\t' || s[i] == '\r' || s[i] == '\n') { 44 break 45 } 46 } 47 next := s[:i] 48 s = s[i:] 49 if strings.Contains(next, "'") { 50 var buf []byte 51 quote := false 52 for i := 0; i < len(next); i++ { 53 if next[i] == '\'' { 54 if quote && i+1 < len(next) && next[i+1] == '\'' { 55 i++ 56 buf = append(buf, '\'') 57 } 58 quote = !quote 59 continue 60 } 61 buf = append(buf, next[i]) 62 } 63 next = string(buf) 64 } 65 f = append(f, next) 66 } 67 return f 68 } 69 70 func cutStringAtNUL(s string) string { 71 if i := strings.Index(s, "\x00"); i >= 0 { 72 s = s[:i] 73 } 74 return s 75 } 76 77 func Access(name string, mode int) int { 78 if mode != 0 { 79 panic("bad access") 80 } 81 _, err := os.Stat(name) 82 if err != nil { 83 return -1 84 } 85 return 0 86 } 87 88 // strings.Compare, introduced in Go 1.5. 89 func stringsCompare(a, b string) int { 90 if a == b { 91 return 0 92 } 93 if a < b { 94 return -1 95 } 96 return +1 97 } 98 99 var atExitFuncs []func() 100 101 func AtExit(f func()) { 102 atExitFuncs = append(atExitFuncs, f) 103 } 104 105 func Exit(code int) { 106 for i := len(atExitFuncs) - 1; i >= 0; i-- { 107 f := atExitFuncs[i] 108 atExitFuncs = atExitFuncs[:i] 109 f() 110 } 111 os.Exit(code) 112 } 113 114 var ( 115 cpuprofile string 116 memprofile string 117 memprofilerate int64 118 ) 119 120 func startProfile() { 121 if cpuprofile != "" { 122 f, err := os.Create(cpuprofile) 123 if err != nil { 124 log.Fatalf("%v", err) 125 } 126 if err := pprof.StartCPUProfile(f); err != nil { 127 log.Fatalf("%v", err) 128 } 129 AtExit(pprof.StopCPUProfile) 130 } 131 if memprofile != "" { 132 if memprofilerate != 0 { 133 runtime.MemProfileRate = int(memprofilerate) 134 } 135 f, err := os.Create(memprofile) 136 if err != nil { 137 log.Fatalf("%v", err) 138 } 139 AtExit(func() { 140 runtime.GC() // profile all outstanding allocations 141 if err := pprof.WriteHeapProfile(f); err != nil { 142 log.Fatalf("%v", err) 143 } 144 }) 145 } 146 } 147 148 func artrim(x []byte) string { 149 i := 0 150 j := len(x) 151 for i < len(x) && x[i] == ' ' { 152 i++ 153 } 154 for j > i && x[j-1] == ' ' { 155 j-- 156 } 157 return string(x[i:j]) 158 } 159 160 func stringtouint32(x []uint32, s string) { 161 for i := 0; len(s) > 0; i++ { 162 var buf [4]byte 163 s = s[copy(buf[:], s):] 164 x[i] = binary.LittleEndian.Uint32(buf[:]) 165 } 166 } 167 168 var start = time.Now() 169 170 func elapsed() float64 { 171 return time.Since(start).Seconds() 172 } 173