github.com/yukk001/go1.10.8@v0.0.0-20190813125351-6df2d3982e20/src/cmd/link/internal/ld/go.go (about) 1 // Copyright 2009 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 // go-specific code shared across loaders (5l, 6l, 8l). 6 7 package ld 8 9 import ( 10 "bytes" 11 "cmd/internal/bio" 12 "cmd/internal/objabi" 13 "cmd/link/internal/sym" 14 "fmt" 15 "io" 16 "os" 17 "strings" 18 ) 19 20 // go-specific code shared across loaders (5l, 6l, 8l). 21 22 // replace all "". with pkg. 23 func expandpkg(t0 string, pkg string) string { 24 return strings.Replace(t0, `"".`, pkg+".", -1) 25 } 26 27 // TODO: 28 // generate debugging section in binary. 29 // once the dust settles, try to move some code to 30 // libmach, so that other linkers and ar can share. 31 32 func ldpkg(ctxt *Link, f *bio.Reader, pkg string, length int64, filename string, whence int) { 33 if *flagG { 34 return 35 } 36 37 if int64(int(length)) != length { 38 fmt.Fprintf(os.Stderr, "%s: too much pkg data in %s\n", os.Args[0], filename) 39 if *flagU { 40 errorexit() 41 } 42 return 43 } 44 45 // In a __.PKGDEF, we only care about the package name. 46 // Don't read all the export data. 47 if length > 1000 && whence == Pkgdef { 48 length = 1000 49 } 50 51 bdata := make([]byte, length) 52 if _, err := io.ReadFull(f, bdata); err != nil { 53 fmt.Fprintf(os.Stderr, "%s: short pkg read %s\n", os.Args[0], filename) 54 if *flagU { 55 errorexit() 56 } 57 return 58 } 59 data := string(bdata) 60 61 // process header lines 62 isSafe := false 63 isMain := false 64 for data != "" { 65 var line string 66 if i := strings.Index(data, "\n"); i >= 0 { 67 line, data = data[:i], data[i+1:] 68 } else { 69 line, data = data, "" 70 } 71 if line == "safe" { 72 isSafe = true 73 } 74 if line == "main" { 75 isMain = true 76 } 77 if line == "" { 78 break 79 } 80 } 81 82 if whence == Pkgdef || whence == FileObj { 83 if pkg == "main" && !isMain { 84 Exitf("%s: not package main", filename) 85 } 86 if *flagU && whence != ArchiveObj && !isSafe { 87 Exitf("load of unsafe package %s", filename) 88 } 89 } 90 91 // __.PKGDEF has no cgo section - those are in the C compiler-generated object files. 92 if whence == Pkgdef { 93 return 94 } 95 96 // look for cgo section 97 p0 := strings.Index(data, "\n$$ // cgo") 98 var p1 int 99 if p0 >= 0 { 100 p0 += p1 101 i := strings.IndexByte(data[p0+1:], '\n') 102 if i < 0 { 103 fmt.Fprintf(os.Stderr, "%s: found $$ // cgo but no newline in %s\n", os.Args[0], filename) 104 if *flagU { 105 errorexit() 106 } 107 return 108 } 109 p0 += 1 + i 110 111 p1 = strings.Index(data[p0:], "\n$$") 112 if p1 < 0 { 113 p1 = strings.Index(data[p0:], "\n!\n") 114 } 115 if p1 < 0 { 116 fmt.Fprintf(os.Stderr, "%s: cannot find end of // cgo section in %s\n", os.Args[0], filename) 117 if *flagU { 118 errorexit() 119 } 120 return 121 } 122 p1 += p0 123 124 loadcgo(ctxt, filename, pkg, data[p0:p1]) 125 } 126 } 127 128 func loadcgo(ctxt *Link, file string, pkg string, p string) { 129 var next string 130 var q string 131 var lib string 132 var s *sym.Symbol 133 134 p0 := "" 135 for ; p != ""; p = next { 136 if i := strings.Index(p, "\n"); i >= 0 { 137 p, next = p[:i], p[i+1:] 138 } else { 139 next = "" 140 } 141 142 p0 = p // save for error message 143 f := tokenize(p) 144 if len(f) == 0 { 145 continue 146 } 147 148 if f[0] == "cgo_import_dynamic" { 149 if len(f) < 2 || len(f) > 4 { 150 goto err 151 } 152 153 local := f[1] 154 remote := local 155 if len(f) > 2 { 156 remote = f[2] 157 } 158 lib = "" 159 if len(f) > 3 { 160 lib = f[3] 161 } 162 163 if *FlagD { 164 fmt.Fprintf(os.Stderr, "%s: %s: cannot use dynamic imports with -d flag\n", os.Args[0], file) 165 nerrors++ 166 return 167 } 168 169 if local == "_" && remote == "_" { 170 // allow #pragma dynimport _ _ "foo.so" 171 // to force a link of foo.so. 172 havedynamic = 1 173 174 if ctxt.HeadType == objabi.Hdarwin { 175 machoadddynlib(lib, ctxt.LinkMode) 176 } else { 177 dynlib = append(dynlib, lib) 178 } 179 continue 180 } 181 182 local = expandpkg(local, pkg) 183 q = "" 184 if i := strings.Index(remote, "#"); i >= 0 { 185 remote, q = remote[:i], remote[i+1:] 186 } 187 s = ctxt.Syms.Lookup(local, 0) 188 if s.Type == 0 || s.Type == sym.SXREF || s.Type == sym.SHOSTOBJ { 189 s.Dynimplib = lib 190 s.Extname = remote 191 s.Dynimpvers = q 192 if s.Type != sym.SHOSTOBJ { 193 s.Type = sym.SDYNIMPORT 194 } 195 havedynamic = 1 196 } 197 198 continue 199 } 200 201 if f[0] == "cgo_import_static" { 202 if len(f) != 2 { 203 goto err 204 } 205 local := f[1] 206 s = ctxt.Syms.Lookup(local, 0) 207 s.Type = sym.SHOSTOBJ 208 s.Size = 0 209 continue 210 } 211 212 if f[0] == "cgo_export_static" || f[0] == "cgo_export_dynamic" { 213 if len(f) < 2 || len(f) > 3 { 214 goto err 215 } 216 local := f[1] 217 var remote string 218 if len(f) > 2 { 219 remote = f[2] 220 } else { 221 remote = local 222 } 223 local = expandpkg(local, pkg) 224 s = ctxt.Syms.Lookup(local, 0) 225 226 switch ctxt.BuildMode { 227 case BuildModeCShared, BuildModeCArchive, BuildModePlugin: 228 if s == ctxt.Syms.Lookup("main", 0) { 229 continue 230 } 231 } 232 233 // export overrides import, for openbsd/cgo. 234 // see issue 4878. 235 if s.Dynimplib != "" { 236 s.Dynimplib = "" 237 s.Extname = "" 238 s.Dynimpvers = "" 239 s.Type = 0 240 } 241 242 if !s.Attr.CgoExport() { 243 s.Extname = remote 244 dynexp = append(dynexp, s) 245 } else if s.Extname != remote { 246 fmt.Fprintf(os.Stderr, "%s: conflicting cgo_export directives: %s as %s and %s\n", os.Args[0], s.Name, s.Extname, remote) 247 nerrors++ 248 return 249 } 250 251 if f[0] == "cgo_export_static" { 252 s.Attr |= sym.AttrCgoExportStatic 253 } else { 254 s.Attr |= sym.AttrCgoExportDynamic 255 } 256 continue 257 } 258 259 if f[0] == "cgo_dynamic_linker" { 260 if len(f) != 2 { 261 goto err 262 } 263 264 if *flagInterpreter == "" { 265 if interpreter != "" && interpreter != f[1] { 266 fmt.Fprintf(os.Stderr, "%s: conflict dynlinker: %s and %s\n", os.Args[0], interpreter, f[1]) 267 nerrors++ 268 return 269 } 270 271 interpreter = f[1] 272 } 273 274 continue 275 } 276 277 if f[0] == "cgo_ldflag" { 278 if len(f) != 2 { 279 goto err 280 } 281 ldflag = append(ldflag, f[1]) 282 continue 283 } 284 } 285 286 return 287 288 err: 289 fmt.Fprintf(os.Stderr, "%s: %s: invalid dynimport line: %s\n", os.Args[0], file, p0) 290 nerrors++ 291 } 292 293 var seenlib = make(map[string]bool) 294 295 func adddynlib(ctxt *Link, lib string) { 296 if seenlib[lib] || ctxt.LinkMode == LinkExternal { 297 return 298 } 299 seenlib[lib] = true 300 301 if ctxt.IsELF { 302 s := ctxt.Syms.Lookup(".dynstr", 0) 303 if s.Size == 0 { 304 Addstring(s, "") 305 } 306 Elfwritedynent(ctxt, ctxt.Syms.Lookup(".dynamic", 0), DT_NEEDED, uint64(Addstring(s, lib))) 307 } else { 308 Errorf(nil, "adddynlib: unsupported binary format") 309 } 310 } 311 312 func Adddynsym(ctxt *Link, s *sym.Symbol) { 313 if s.Dynid >= 0 || ctxt.LinkMode == LinkExternal { 314 return 315 } 316 317 if ctxt.IsELF { 318 elfadddynsym(ctxt, s) 319 } else if ctxt.HeadType == objabi.Hdarwin { 320 Errorf(s, "adddynsym: missed symbol (Extname=%s)", s.Extname) 321 } else if ctxt.HeadType == objabi.Hwindows { 322 // already taken care of 323 } else { 324 Errorf(s, "adddynsym: unsupported binary format") 325 } 326 } 327 328 func fieldtrack(ctxt *Link) { 329 // record field tracking references 330 var buf bytes.Buffer 331 for _, s := range ctxt.Syms.Allsym { 332 if strings.HasPrefix(s.Name, "go.track.") { 333 s.Attr |= sym.AttrSpecial // do not lay out in data segment 334 s.Attr |= sym.AttrNotInSymbolTable 335 if s.Attr.Reachable() { 336 buf.WriteString(s.Name[9:]) 337 for p := s.Reachparent; p != nil; p = p.Reachparent { 338 buf.WriteString("\t") 339 buf.WriteString(p.Name) 340 } 341 buf.WriteString("\n") 342 } 343 344 s.Type = sym.SCONST 345 s.Value = 0 346 } 347 } 348 349 if *flagFieldTrack == "" { 350 return 351 } 352 s := ctxt.Syms.ROLookup(*flagFieldTrack, 0) 353 if s == nil || !s.Attr.Reachable() { 354 return 355 } 356 s.Type = sym.SDATA 357 addstrdata(ctxt, *flagFieldTrack, buf.String()) 358 } 359 360 func (ctxt *Link) addexport() { 361 if ctxt.HeadType == objabi.Hdarwin { 362 return 363 } 364 365 for _, exp := range dynexp { 366 Adddynsym(ctxt, exp) 367 } 368 for _, lib := range dynlib { 369 adddynlib(ctxt, lib) 370 } 371 } 372 373 type Pkg struct { 374 mark bool 375 checked bool 376 path string 377 impby []*Pkg 378 } 379 380 var pkgall []*Pkg 381 382 func (p *Pkg) cycle() *Pkg { 383 if p.checked { 384 return nil 385 } 386 387 if p.mark { 388 nerrors++ 389 fmt.Printf("import cycle:\n") 390 fmt.Printf("\t%s\n", p.path) 391 return p 392 } 393 394 p.mark = true 395 for _, q := range p.impby { 396 if bad := q.cycle(); bad != nil { 397 p.mark = false 398 p.checked = true 399 fmt.Printf("\timports %s\n", p.path) 400 if bad == p { 401 return nil 402 } 403 return bad 404 } 405 } 406 407 p.checked = true 408 p.mark = false 409 return nil 410 } 411 412 func importcycles() { 413 for _, p := range pkgall { 414 p.cycle() 415 } 416 }