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