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  }