github.com/yanyiwu/go@v0.0.0-20150106053140-03d6637dbb7f/src/cmd/gc/obj.c (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 #include <u.h> 6 #include <libc.h> 7 #include "go.h" 8 #include "../ld/textflag.h" 9 10 /* 11 * architecture-independent object file output 12 */ 13 14 static void dumpglobls(void); 15 16 enum 17 { 18 ArhdrSize = 60 19 }; 20 21 static void 22 formathdr(char *arhdr, char *name, vlong size) 23 { 24 snprint(arhdr, ArhdrSize, "%-16s%-12d%-6d%-6d%-8o%-10lld`", 25 name, 0, 0, 0, 0644, size); 26 arhdr[ArhdrSize-1] = '\n'; // overwrite \0 written by snprint 27 } 28 29 void 30 dumpobj(void) 31 { 32 NodeList *externs, *tmp; 33 char arhdr[ArhdrSize]; 34 vlong startobj, size; 35 Sym *zero; 36 37 bout = Bopen(outfile, OWRITE); 38 if(bout == nil) { 39 flusherrors(); 40 print("can't create %s: %r\n", outfile); 41 errorexit(); 42 } 43 44 startobj = 0; 45 if(writearchive) { 46 Bwrite(bout, "!<arch>\n", 8); 47 memset(arhdr, 0, sizeof arhdr); 48 Bwrite(bout, arhdr, sizeof arhdr); 49 startobj = Boffset(bout); 50 } 51 Bprint(bout, "go object %s %s %s %s\n", getgoos(), getgoarch(), getgoversion(), expstring()); 52 dumpexport(); 53 54 if(writearchive) { 55 Bflush(bout); 56 size = Boffset(bout) - startobj; 57 if(size&1) 58 Bputc(bout, 0); 59 Bseek(bout, startobj - ArhdrSize, 0); 60 formathdr(arhdr, "__.PKGDEF", size); 61 Bwrite(bout, arhdr, ArhdrSize); 62 Bflush(bout); 63 64 Bseek(bout, startobj + size + (size&1), 0); 65 memset(arhdr, 0, ArhdrSize); 66 Bwrite(bout, arhdr, ArhdrSize); 67 startobj = Boffset(bout); 68 Bprint(bout, "go object %s %s %s %s\n", getgoos(), getgoarch(), getgoversion(), expstring()); 69 } 70 71 if(pragcgobuf.to > pragcgobuf.start) { 72 if(writearchive) { 73 // write empty export section; must be before cgo section 74 Bprint(bout, "\n$$\n\n$$\n\n"); 75 } 76 Bprint(bout, "\n$$ // cgo\n"); 77 Bprint(bout, "%s\n$$\n\n", fmtstrflush(&pragcgobuf)); 78 } 79 80 81 Bprint(bout, "\n!\n"); 82 83 externs = nil; 84 if(externdcl != nil) 85 externs = externdcl->end; 86 87 dumpglobls(); 88 dumptypestructs(); 89 90 // Dump extra globals. 91 tmp = externdcl; 92 if(externs != nil) 93 externdcl = externs->next; 94 dumpglobls(); 95 externdcl = tmp; 96 97 zero = pkglookup("zerovalue", runtimepkg); 98 ggloblsym(zero, zerosize, DUPOK|RODATA); 99 100 dumpdata(); 101 writeobj(ctxt, bout); 102 103 if(writearchive) { 104 Bflush(bout); 105 size = Boffset(bout) - startobj; 106 if(size&1) 107 Bputc(bout, 0); 108 Bseek(bout, startobj - ArhdrSize, 0); 109 snprint(namebuf, sizeof namebuf, "_go_.%c", thechar); 110 formathdr(arhdr, namebuf, size); 111 Bwrite(bout, arhdr, ArhdrSize); 112 } 113 Bterm(bout); 114 } 115 116 static void 117 dumpglobls(void) 118 { 119 Node *n; 120 NodeList *l; 121 122 // add globals 123 for(l=externdcl; l; l=l->next) { 124 n = l->n; 125 if(n->op != ONAME) 126 continue; 127 128 if(n->type == T) 129 fatal("external %N nil type\n", n); 130 if(n->class == PFUNC) 131 continue; 132 if(n->sym->pkg != localpkg) 133 continue; 134 dowidth(n->type); 135 136 ggloblnod(n); 137 } 138 139 for(l=funcsyms; l; l=l->next) { 140 n = l->n; 141 dsymptr(n->sym, 0, n->sym->def->shortname->sym, 0); 142 ggloblsym(n->sym, widthptr, DUPOK|RODATA); 143 } 144 145 // Do not reprocess funcsyms on next dumpglobls call. 146 funcsyms = nil; 147 } 148 149 void 150 Bputname(Biobuf *b, LSym *s) 151 { 152 Bwrite(b, s->name, strlen(s->name)+1); 153 } 154 155 LSym* 156 linksym(Sym *s) 157 { 158 char *p; 159 160 if(s == nil) 161 return nil; 162 if(s->lsym != nil) 163 return s->lsym; 164 if(isblanksym(s)) 165 s->lsym = linklookup(ctxt, "_", 0); 166 else if(s->linkname != nil) 167 s->lsym = linklookup(ctxt, s->linkname, 0); 168 else { 169 p = smprint("%s.%s", s->pkg->prefix, s->name); 170 s->lsym = linklookup(ctxt, p, 0); 171 free(p); 172 } 173 return s->lsym; 174 } 175 176 int 177 duintxx(Sym *s, int off, uint64 v, int wid) 178 { 179 // Update symbol data directly instead of generating a 180 // DATA instruction that liblink will have to interpret later. 181 // This reduces compilation time and memory usage. 182 off = rnd(off, wid); 183 return setuintxx(ctxt, linksym(s), off, v, wid); 184 } 185 186 int 187 duint8(Sym *s, int off, uint8 v) 188 { 189 return duintxx(s, off, v, 1); 190 } 191 192 int 193 duint16(Sym *s, int off, uint16 v) 194 { 195 return duintxx(s, off, v, 2); 196 } 197 198 int 199 duint32(Sym *s, int off, uint32 v) 200 { 201 return duintxx(s, off, v, 4); 202 } 203 204 int 205 duint64(Sym *s, int off, uint64 v) 206 { 207 return duintxx(s, off, v, 8); 208 } 209 210 int 211 duintptr(Sym *s, int off, uint64 v) 212 { 213 return duintxx(s, off, v, widthptr); 214 } 215 216 Sym* 217 stringsym(char *s, int len) 218 { 219 static int gen; 220 Sym *sym; 221 int off, n, m; 222 struct { 223 Strlit lit; 224 char buf[110]; 225 } tmp; 226 Pkg *pkg; 227 228 if(len > 100) { 229 // huge strings are made static to avoid long names 230 snprint(namebuf, sizeof(namebuf), ".gostring.%d", ++gen); 231 pkg = localpkg; 232 } else { 233 // small strings get named by their contents, 234 // so that multiple modules using the same string 235 // can share it. 236 tmp.lit.len = len; 237 memmove(tmp.lit.s, s, len); 238 tmp.lit.s[len] = '\0'; 239 snprint(namebuf, sizeof(namebuf), "\"%Z\"", &tmp.lit); 240 pkg = gostringpkg; 241 } 242 sym = pkglookup(namebuf, pkg); 243 244 // SymUniq flag indicates that data is generated already 245 if(sym->flags & SymUniq) 246 return sym; 247 sym->flags |= SymUniq; 248 sym->def = newname(sym); 249 250 off = 0; 251 252 // string header 253 off = dsymptr(sym, off, sym, widthptr+widthint); 254 off = duintxx(sym, off, len, widthint); 255 256 // string data 257 for(n=0; n<len; n+=m) { 258 m = 8; 259 if(m > len-n) 260 m = len-n; 261 off = dsname(sym, off, s+n, m); 262 } 263 off = duint8(sym, off, 0); // terminating NUL for runtime 264 off = (off+widthptr-1)&~(widthptr-1); // round to pointer alignment 265 ggloblsym(sym, off, DUPOK|RODATA); 266 267 return sym; 268 } 269 270 void 271 slicebytes(Node *nam, char *s, int len) 272 { 273 int off, n, m; 274 static int gen; 275 Sym *sym; 276 277 snprint(namebuf, sizeof(namebuf), ".gobytes.%d", ++gen); 278 sym = pkglookup(namebuf, localpkg); 279 sym->def = newname(sym); 280 281 off = 0; 282 for(n=0; n<len; n+=m) { 283 m = 8; 284 if(m > len-n) 285 m = len-n; 286 off = dsname(sym, off, s+n, m); 287 } 288 ggloblsym(sym, off, NOPTR); 289 290 if(nam->op != ONAME) 291 fatal("slicebytes %N", nam); 292 off = nam->xoffset; 293 off = dsymptr(nam->sym, off, sym, 0); 294 off = duintxx(nam->sym, off, len, widthint); 295 duintxx(nam->sym, off, len, widthint); 296 }