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