github.com/d4l3k/go@v0.0.0-20151015000803-65fc379daeda/src/cmd/compile/internal/gc/obj.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 package gc 6 7 import ( 8 "cmd/internal/obj" 9 "fmt" 10 "strconv" 11 ) 12 13 /* 14 * architecture-independent object file output 15 */ 16 const ( 17 ArhdrSize = 60 18 ) 19 20 func formathdr(arhdr []byte, name string, size int64) { 21 copy(arhdr[:], fmt.Sprintf("%-16s%-12d%-6d%-6d%-8o%-10d`\n", name, 0, 0, 0, 0644, size)) 22 } 23 24 func dumpobj() { 25 var err error 26 bout, err = obj.Bopenw(outfile) 27 if err != nil { 28 Flusherrors() 29 fmt.Printf("can't create %s: %v\n", outfile, err) 30 errorexit() 31 } 32 33 startobj := int64(0) 34 var arhdr [ArhdrSize]byte 35 if writearchive != 0 { 36 obj.Bwritestring(bout, "!<arch>\n") 37 arhdr = [ArhdrSize]byte{} 38 bout.Write(arhdr[:]) 39 startobj = obj.Boffset(bout) 40 } 41 42 fmt.Fprintf(bout, "go object %s %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion(), obj.Expstring()) 43 dumpexport() 44 45 if writearchive != 0 { 46 bout.Flush() 47 size := obj.Boffset(bout) - startobj 48 if size&1 != 0 { 49 obj.Bputc(bout, 0) 50 } 51 obj.Bseek(bout, startobj-ArhdrSize, 0) 52 formathdr(arhdr[:], "__.PKGDEF", size) 53 bout.Write(arhdr[:]) 54 bout.Flush() 55 56 obj.Bseek(bout, startobj+size+(size&1), 0) 57 arhdr = [ArhdrSize]byte{} 58 bout.Write(arhdr[:]) 59 startobj = obj.Boffset(bout) 60 fmt.Fprintf(bout, "go object %s %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion(), obj.Expstring()) 61 } 62 63 if pragcgobuf != "" { 64 if writearchive != 0 { 65 // write empty export section; must be before cgo section 66 fmt.Fprintf(bout, "\n$$\n\n$$\n\n") 67 } 68 69 fmt.Fprintf(bout, "\n$$ // cgo\n") 70 fmt.Fprintf(bout, "%s\n$$\n\n", pragcgobuf) 71 } 72 73 fmt.Fprintf(bout, "\n!\n") 74 75 externs := len(externdcl) 76 77 dumpglobls() 78 dumptypestructs() 79 80 // Dump extra globals. 81 tmp := externdcl 82 83 if externdcl != nil { 84 externdcl = externdcl[externs:] 85 } 86 dumpglobls() 87 externdcl = tmp 88 89 dumpdata() 90 obj.Writeobjdirect(Ctxt, bout) 91 92 if writearchive != 0 { 93 bout.Flush() 94 size := obj.Boffset(bout) - startobj 95 if size&1 != 0 { 96 obj.Bputc(bout, 0) 97 } 98 obj.Bseek(bout, startobj-ArhdrSize, 0) 99 formathdr(arhdr[:], "_go_.o", size) 100 bout.Write(arhdr[:]) 101 } 102 103 obj.Bterm(bout) 104 } 105 106 func dumpglobls() { 107 // add globals 108 for _, n := range externdcl { 109 if n.Op != ONAME { 110 continue 111 } 112 113 if n.Type == nil { 114 Fatalf("external %v nil type\n", n) 115 } 116 if n.Class == PFUNC { 117 continue 118 } 119 if n.Sym.Pkg != localpkg { 120 continue 121 } 122 dowidth(n.Type) 123 ggloblnod(n) 124 } 125 126 for _, n := range funcsyms { 127 dsymptr(n.Sym, 0, n.Sym.Def.Func.Shortname.Sym, 0) 128 ggloblsym(n.Sym, int32(Widthptr), obj.DUPOK|obj.RODATA) 129 } 130 131 // Do not reprocess funcsyms on next dumpglobls call. 132 funcsyms = nil 133 } 134 135 func Bputname(b *obj.Biobuf, s *obj.LSym) { 136 obj.Bwritestring(b, s.Name) 137 obj.Bputc(b, 0) 138 } 139 140 func Linksym(s *Sym) *obj.LSym { 141 if s == nil { 142 return nil 143 } 144 if s.Lsym != nil { 145 return s.Lsym 146 } 147 var name string 148 if isblanksym(s) { 149 name = "_" 150 } else if s.Linkname != "" { 151 name = s.Linkname 152 } else { 153 name = s.Pkg.Prefix + "." + s.Name 154 } 155 156 ls := obj.Linklookup(Ctxt, name, 0) 157 s.Lsym = ls 158 return ls 159 } 160 161 func duintxx(s *Sym, off int, v uint64, wid int) int { 162 // Update symbol data directly instead of generating a 163 // DATA instruction that liblink will have to interpret later. 164 // This reduces compilation time and memory usage. 165 off = int(Rnd(int64(off), int64(wid))) 166 167 return int(obj.Setuintxx(Ctxt, Linksym(s), int64(off), v, int64(wid))) 168 } 169 170 func duint8(s *Sym, off int, v uint8) int { 171 return duintxx(s, off, uint64(v), 1) 172 } 173 174 func duint16(s *Sym, off int, v uint16) int { 175 return duintxx(s, off, uint64(v), 2) 176 } 177 178 func duint32(s *Sym, off int, v uint32) int { 179 return duintxx(s, off, uint64(v), 4) 180 } 181 182 func duintptr(s *Sym, off int, v uint64) int { 183 return duintxx(s, off, v, Widthptr) 184 } 185 186 var stringsym_gen int 187 188 func stringsym(s string) (hdr, data *Sym) { 189 var symname string 190 var pkg *Pkg 191 if len(s) > 100 { 192 // huge strings are made static to avoid long names 193 stringsym_gen++ 194 symname = fmt.Sprintf(".gostring.%d", stringsym_gen) 195 196 pkg = localpkg 197 } else { 198 // small strings get named by their contents, 199 // so that multiple modules using the same string 200 // can share it. 201 symname = strconv.Quote(s) 202 pkg = gostringpkg 203 } 204 205 symhdr := Pkglookup("hdr."+symname, pkg) 206 symdata := Pkglookup(symname, pkg) 207 208 // SymUniq flag indicates that data is generated already 209 if symhdr.Flags&SymUniq != 0 { 210 return symhdr, symdata 211 } 212 symhdr.Flags |= SymUniq 213 symhdr.Def = newname(symhdr) 214 215 // string header 216 off := 0 217 off = dsymptr(symhdr, off, symdata, 0) 218 off = duintxx(symhdr, off, uint64(len(s)), Widthint) 219 ggloblsym(symhdr, int32(off), obj.DUPOK|obj.RODATA|obj.LOCAL) 220 221 // string data 222 if symdata.Flags&SymUniq != 0 { 223 return symhdr, symdata 224 } 225 symdata.Flags |= SymUniq 226 symdata.Def = newname(symdata) 227 228 off = 0 229 var m int 230 for n := 0; n < len(s); n += m { 231 m = 8 232 if m > len(s)-n { 233 m = len(s) - n 234 } 235 off = dsname(symdata, off, s[n:n+m]) 236 } 237 238 off = duint8(symdata, off, 0) // terminating NUL for runtime 239 off = (off + Widthptr - 1) &^ (Widthptr - 1) // round to pointer alignment 240 ggloblsym(symdata, int32(off), obj.DUPOK|obj.RODATA|obj.LOCAL) 241 242 return symhdr, symdata 243 } 244 245 var slicebytes_gen int 246 247 func slicebytes(nam *Node, s string, len int) { 248 var m int 249 250 slicebytes_gen++ 251 symname := fmt.Sprintf(".gobytes.%d", slicebytes_gen) 252 sym := Pkglookup(symname, localpkg) 253 sym.Def = newname(sym) 254 255 off := 0 256 for n := 0; n < len; n += m { 257 m = 8 258 if m > len-n { 259 m = len - n 260 } 261 off = dsname(sym, off, s[n:n+m]) 262 } 263 264 ggloblsym(sym, int32(off), obj.NOPTR|obj.LOCAL) 265 266 if nam.Op != ONAME { 267 Fatalf("slicebytes %v", nam) 268 } 269 off = int(nam.Xoffset) 270 off = dsymptr(nam.Sym, off, sym, 0) 271 off = duintxx(nam.Sym, off, uint64(len), Widthint) 272 duintxx(nam.Sym, off, uint64(len), Widthint) 273 } 274 275 func Datastring(s string, a *obj.Addr) { 276 _, symdata := stringsym(s) 277 a.Type = obj.TYPE_MEM 278 a.Name = obj.NAME_EXTERN 279 a.Sym = Linksym(symdata) 280 a.Node = symdata.Def 281 a.Offset = 0 282 a.Etype = Simtype[TINT] 283 } 284 285 func datagostring(sval string, a *obj.Addr) { 286 symhdr, _ := stringsym(sval) 287 a.Type = obj.TYPE_MEM 288 a.Name = obj.NAME_EXTERN 289 a.Sym = Linksym(symhdr) 290 a.Node = symhdr.Def 291 a.Offset = 0 292 a.Etype = TSTRING 293 } 294 295 func dgostringptr(s *Sym, off int, str string) int { 296 if str == "" { 297 return duintptr(s, off, 0) 298 } 299 return dgostrlitptr(s, off, &str) 300 } 301 302 func dgostrlitptr(s *Sym, off int, lit *string) int { 303 if lit == nil { 304 return duintptr(s, off, 0) 305 } 306 off = int(Rnd(int64(off), int64(Widthptr))) 307 p := Thearch.Gins(obj.ADATA, nil, nil) 308 p.From.Type = obj.TYPE_MEM 309 p.From.Name = obj.NAME_EXTERN 310 p.From.Sym = Linksym(s) 311 p.From.Offset = int64(off) 312 p.From3 = new(obj.Addr) 313 p.From3.Type = obj.TYPE_CONST 314 p.From3.Offset = int64(Widthptr) 315 datagostring(*lit, &p.To) 316 p.To.Type = obj.TYPE_ADDR 317 p.To.Etype = Simtype[TINT] 318 off += Widthptr 319 320 return off 321 } 322 323 func dsname(s *Sym, off int, t string) int { 324 p := Thearch.Gins(obj.ADATA, nil, nil) 325 p.From.Type = obj.TYPE_MEM 326 p.From.Name = obj.NAME_EXTERN 327 p.From.Offset = int64(off) 328 p.From.Sym = Linksym(s) 329 p.From3 = new(obj.Addr) 330 p.From3.Type = obj.TYPE_CONST 331 p.From3.Offset = int64(len(t)) 332 333 p.To.Type = obj.TYPE_SCONST 334 p.To.Val = t 335 return off + len(t) 336 } 337 338 func dsymptr(s *Sym, off int, x *Sym, xoff int) int { 339 off = int(Rnd(int64(off), int64(Widthptr))) 340 341 p := Thearch.Gins(obj.ADATA, nil, nil) 342 p.From.Type = obj.TYPE_MEM 343 p.From.Name = obj.NAME_EXTERN 344 p.From.Sym = Linksym(s) 345 p.From.Offset = int64(off) 346 p.From3 = new(obj.Addr) 347 p.From3.Type = obj.TYPE_CONST 348 p.From3.Offset = int64(Widthptr) 349 p.To.Type = obj.TYPE_ADDR 350 p.To.Name = obj.NAME_EXTERN 351 p.To.Sym = Linksym(x) 352 p.To.Offset = int64(xoff) 353 off += Widthptr 354 355 return off 356 } 357 358 func gdata(nam *Node, nr *Node, wid int) { 359 if nr.Op == OLITERAL { 360 switch nr.Val().Ctype() { 361 case CTCPLX: 362 gdatacomplex(nam, nr.Val().U.(*Mpcplx)) 363 return 364 365 case CTSTR: 366 gdatastring(nam, nr.Val().U.(string)) 367 return 368 } 369 } 370 371 p := Thearch.Gins(obj.ADATA, nam, nr) 372 p.From3 = new(obj.Addr) 373 p.From3.Type = obj.TYPE_CONST 374 p.From3.Offset = int64(wid) 375 } 376 377 func gdatacomplex(nam *Node, cval *Mpcplx) { 378 w := cplxsubtype(int(nam.Type.Etype)) 379 w = int(Types[w].Width) 380 381 p := Thearch.Gins(obj.ADATA, nam, nil) 382 p.From3 = new(obj.Addr) 383 p.From3.Type = obj.TYPE_CONST 384 p.From3.Offset = int64(w) 385 p.To.Type = obj.TYPE_FCONST 386 p.To.Val = mpgetflt(&cval.Real) 387 388 p = Thearch.Gins(obj.ADATA, nam, nil) 389 p.From3 = new(obj.Addr) 390 p.From3.Type = obj.TYPE_CONST 391 p.From3.Offset = int64(w) 392 p.From.Offset += int64(w) 393 p.To.Type = obj.TYPE_FCONST 394 p.To.Val = mpgetflt(&cval.Imag) 395 } 396 397 func gdatastring(nam *Node, sval string) { 398 var nod1 Node 399 400 p := Thearch.Gins(obj.ADATA, nam, nil) 401 Datastring(sval, &p.To) 402 p.From3 = new(obj.Addr) 403 p.From3.Type = obj.TYPE_CONST 404 p.From3.Offset = Types[Tptr].Width 405 p.To.Type = obj.TYPE_ADDR 406 407 //print("%v\n", p); 408 409 Nodconst(&nod1, Types[TINT], int64(len(sval))) 410 411 p = Thearch.Gins(obj.ADATA, nam, &nod1) 412 p.From3 = new(obj.Addr) 413 p.From3.Type = obj.TYPE_CONST 414 p.From3.Offset = int64(Widthint) 415 p.From.Offset += int64(Widthptr) 416 }