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  }