...
Run Format

Text file src/cmd/ld/lib.c

     1	// Derived from Inferno utils/6l/obj.c and utils/6l/span.c
     2	// http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.c
     3	// http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c
     4	//
     5	//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     6	//	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     7	//	Portions Copyright © 1997-1999 Vita Nuova Limited
     8	//	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
     9	//	Portions Copyright © 2004,2006 Bruce Ellis
    10	//	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    11	//	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    12	//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    13	//
    14	// Permission is hereby granted, free of charge, to any person obtaining a copy
    15	// of this software and associated documentation files (the "Software"), to deal
    16	// in the Software without restriction, including without limitation the rights
    17	// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    18	// copies of the Software, and to permit persons to whom the Software is
    19	// furnished to do so, subject to the following conditions:
    20	//
    21	// The above copyright notice and this permission notice shall be included in
    22	// all copies or substantial portions of the Software.
    23	//
    24	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    25	// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    26	// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    27	// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    28	// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    29	// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    30	// THE SOFTWARE.
    31	
    32	#include	"l.h"
    33	#include	"lib.h"
    34	#include	"../ld/elf.h"
    35	#include	"../ld/dwarf.h"
    36	#include	"../../pkg/runtime/stack.h"
    37	#include	"../../pkg/runtime/funcdata.h"
    38	
    39	#include	<ar.h>
    40	#if !(defined(_WIN32) || defined(PLAN9))
    41	#include	<sys/stat.h>
    42	#endif
    43	
    44	enum
    45	{
    46		// Whether to assume that the external linker is "gold"
    47		// (http://sourceware.org/ml/binutils/2008-03/msg00162.html).
    48		AssumeGoldLinker = 0,
    49	};
    50	
    51	int iconv(Fmt*);
    52	
    53	char	symname[]	= SYMDEF;
    54	char	pkgname[]	= "__.PKGDEF";
    55	static int	cout = -1;
    56	
    57	extern int	version;
    58	
    59	// Set if we see an object compiled by the host compiler that is not
    60	// from a package that is known to support internal linking mode.
    61	static int	externalobj = 0;
    62	
    63	static	void	hostlinksetup(void);
    64	
    65	char*	goroot;
    66	char*	goarch;
    67	char*	goos;
    68	char*	theline;
    69	
    70	void
    71	Lflag(char *arg)
    72	{
    73		char **p;
    74	
    75		if(ctxt->nlibdir >= ctxt->maxlibdir) {
    76			if (ctxt->maxlibdir == 0)
    77				ctxt->maxlibdir = 8;
    78			else
    79				ctxt->maxlibdir *= 2;
    80			p = erealloc(ctxt->libdir, ctxt->maxlibdir * sizeof(*p));
    81			ctxt->libdir = p;
    82		}
    83		ctxt->libdir[ctxt->nlibdir++] = arg;
    84	}
    85	
    86	/*
    87	 * Unix doesn't like it when we write to a running (or, sometimes,
    88	 * recently run) binary, so remove the output file before writing it.
    89	 * On Windows 7, remove() can force a subsequent create() to fail.
    90	 * S_ISREG() does not exist on Plan 9.
    91	 */
    92	static void
    93	mayberemoveoutfile(void) 
    94	{
    95	#if !(defined(_WIN32) || defined(PLAN9))
    96		struct stat st;
    97		if(lstat(outfile, &st) == 0 && !S_ISREG(st.st_mode))
    98			return;
    99	#endif
   100		remove(outfile);
   101	}
   102	
   103	void
   104	libinit(void)
   105	{
   106		char *suffix, *suffixsep;
   107	
   108		funcalign = FuncAlign;
   109		fmtinstall('i', iconv);
   110		fmtinstall('Y', Yconv);
   111		fmtinstall('Z', Zconv);
   112		mywhatsys();	// get goroot, goarch, goos
   113	
   114		// add goroot to the end of the libdir list.
   115		suffix = "";
   116		suffixsep = "";
   117		if(flag_installsuffix != nil) {
   118			suffixsep = "_";
   119			suffix = flag_installsuffix;
   120		} else if(flag_race) {
   121			suffixsep = "_";
   122			suffix = "race";
   123		}
   124		Lflag(smprint("%s/pkg/%s_%s%s%s", goroot, goos, goarch, suffixsep, suffix));
   125	
   126		mayberemoveoutfile();
   127		cout = create(outfile, 1, 0775);
   128		if(cout < 0) {
   129			diag("cannot create %s: %r", outfile);
   130			errorexit();
   131		}
   132	
   133		if(INITENTRY == nil) {
   134			INITENTRY = mal(strlen(goarch)+strlen(goos)+20);
   135			if(!flag_shared) {
   136				sprint(INITENTRY, "_rt0_%s_%s", goarch, goos);
   137			} else {
   138				sprint(INITENTRY, "_rt0_%s_%s_lib", goarch, goos);
   139			}
   140		}
   141		linklookup(ctxt, INITENTRY, 0)->type = SXREF;
   142	}
   143	
   144	void
   145	errorexit(void)
   146	{
   147		if(nerrors) {
   148			if(cout >= 0)
   149				mayberemoveoutfile();
   150			exits("error");
   151		}
   152		exits(0);
   153	}
   154	
   155	void
   156	loadinternal(char *name)
   157	{
   158		char pname[1024];
   159		int i, found;
   160	
   161		found = 0;
   162		for(i=0; i<ctxt->nlibdir; i++) {
   163			snprint(pname, sizeof pname, "%s/%s.a", ctxt->libdir[i], name);
   164			if(debug['v'])
   165				Bprint(&bso, "searching for %s.a in %s\n", name, pname);
   166			if(access(pname, AEXIST) >= 0) {
   167				addlibpath(ctxt, "internal", "internal", pname, name);
   168				found = 1;
   169				break;
   170			}
   171		}
   172		if(!found)
   173			Bprint(&bso, "warning: unable to find %s.a\n", name);
   174	}
   175	
   176	void
   177	loadlib(void)
   178	{
   179		int i, w, x;
   180		LSym *s, *gmsym;
   181		char* cgostrsym;
   182	
   183		if(flag_shared) {
   184			s = linklookup(ctxt, "runtime.islibrary", 0);
   185			s->dupok = 1;
   186			adduint8(ctxt, s, 1);
   187		}
   188	
   189		loadinternal("runtime");
   190		if(thechar == '5')
   191			loadinternal("math");
   192		if(flag_race)
   193			loadinternal("runtime/race");
   194	
   195		for(i=0; i<ctxt->libraryp; i++) {
   196			if(debug['v'] > 1)
   197				Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), ctxt->library[i].file, ctxt->library[i].objref);
   198			iscgo |= strcmp(ctxt->library[i].pkg, "runtime/cgo") == 0;
   199			objfile(ctxt->library[i].file, ctxt->library[i].pkg);
   200		}
   201		
   202		if(linkmode == LinkExternal && !iscgo) {
   203			// This indicates a user requested -linkmode=external.
   204			// The startup code uses an import of runtime/cgo to decide
   205			// whether to initialize the TLS.  So give it one.  This could
   206			// be handled differently but it's an unusual case.
   207			loadinternal("runtime/cgo");
   208			if(i < ctxt->libraryp)
   209				objfile(ctxt->library[i].file, ctxt->library[i].pkg);
   210	
   211			// Pretend that we really imported the package.
   212			s = linklookup(ctxt, "go.importpath.runtime/cgo.", 0);
   213			s->type = SDATA;
   214			s->dupok = 1;
   215			s->reachable = 1;
   216	
   217			// Provided by the code that imports the package.
   218			// Since we are simulating the import, we have to provide this string.
   219			cgostrsym = "go.string.\"runtime/cgo\"";
   220			if(linkrlookup(ctxt, cgostrsym, 0) == nil)
   221				addstrdata(cgostrsym, "runtime/cgo");
   222		}
   223	
   224		if(linkmode == LinkAuto) {
   225			if(iscgo && externalobj)
   226				linkmode = LinkExternal;
   227			else
   228				linkmode = LinkInternal;
   229		}
   230	
   231		if(linkmode == LinkInternal) {
   232			// Drop all the cgo_import_static declarations.
   233			// Turns out we won't be needing them.
   234			for(s = ctxt->allsym; s != S; s = s->allsym)
   235				if(s->type == SHOSTOBJ) {
   236					// If a symbol was marked both
   237					// cgo_import_static and cgo_import_dynamic,
   238					// then we want to make it cgo_import_dynamic
   239					// now.
   240					if(s->extname != nil && s->dynimplib != nil && s->cgoexport == 0) {
   241						s->type = SDYNIMPORT;
   242					} else
   243						s->type = 0;
   244				}
   245		}
   246		
   247		gmsym = linklookup(ctxt, "runtime.tlsgm", 0);
   248		gmsym->type = STLSBSS;
   249		gmsym->size = 2*PtrSize;
   250		gmsym->hide = 1;
   251		gmsym->reachable = 1;
   252		ctxt->gmsym = gmsym;
   253	
   254		// Now that we know the link mode, trim the dynexp list.
   255		x = CgoExportDynamic;
   256		if(linkmode == LinkExternal)
   257			x = CgoExportStatic;
   258		w = 0;
   259		for(i=0; i<ndynexp; i++)
   260			if(dynexp[i]->cgoexport & x)
   261				dynexp[w++] = dynexp[i];
   262		ndynexp = w;
   263		
   264		// In internal link mode, read the host object files.
   265		if(linkmode == LinkInternal)
   266			hostobjs();
   267		else
   268			hostlinksetup();
   269	
   270		// We've loaded all the code now.
   271		// If there are no dynamic libraries needed, gcc disables dynamic linking.
   272		// Because of this, glibc's dynamic ELF loader occasionally (like in version 2.13)
   273		// assumes that a dynamic binary always refers to at least one dynamic library.
   274		// Rather than be a source of test cases for glibc, disable dynamic linking
   275		// the same way that gcc would.
   276		//
   277		// Exception: on OS X, programs such as Shark only work with dynamic
   278		// binaries, so leave it enabled on OS X (Mach-O) binaries.
   279		// Also leave it enabled on Solaris which doesn't support
   280		// statically linked binaries.
   281		if(!flag_shared && !havedynamic && HEADTYPE != Hdarwin && HEADTYPE != Hsolaris)
   282			debug['d'] = 1;
   283		
   284		importcycles();
   285	}
   286	
   287	/*
   288	 * look for the next file in an archive.
   289	 * adapted from libmach.
   290	 */
   291	static vlong
   292	nextar(Biobuf *bp, vlong off, struct ar_hdr *a)
   293	{
   294		int r;
   295		int32 arsize;
   296		char *buf;
   297	
   298		if (off&01)
   299			off++;
   300		Bseek(bp, off, 0);
   301		buf = Brdline(bp, '\n');
   302		r = Blinelen(bp);
   303		if(buf == nil) {
   304			if(r == 0)
   305				return 0;
   306			return -1;
   307		}
   308		if(r != SAR_HDR)
   309			return -1;
   310		memmove(a, buf, SAR_HDR);
   311		if(strncmp(a->fmag, ARFMAG, sizeof a->fmag))
   312			return -1;
   313		arsize = strtol(a->size, 0, 0);
   314		if (arsize&1)
   315			arsize++;
   316		return arsize + r;
   317	}
   318	
   319	void
   320	objfile(char *file, char *pkg)
   321	{
   322		vlong off, l;
   323		Biobuf *f;
   324		char magbuf[SARMAG];
   325		char pname[150];
   326		struct ar_hdr arhdr;
   327	
   328		pkg = smprint("%i", pkg);
   329	
   330		if(debug['v'] > 1)
   331			Bprint(&bso, "%5.2f ldobj: %s (%s)\n", cputime(), file, pkg);
   332		Bflush(&bso);
   333		f = Bopen(file, 0);
   334		if(f == nil) {
   335			diag("cannot open file: %s", file);
   336			errorexit();
   337		}
   338		l = Bread(f, magbuf, SARMAG);
   339		if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
   340			/* load it as a regular file */
   341			l = Bseek(f, 0L, 2);
   342			Bseek(f, 0L, 0);
   343			ldobj(f, pkg, l, file, file, FileObj);
   344			Bterm(f);
   345			free(pkg);
   346			return;
   347		}
   348		
   349		/* skip over optional __.GOSYMDEF and process __.PKGDEF */
   350		off = Boffset(f);
   351		l = nextar(f, off, &arhdr);
   352		if(l <= 0) {
   353			diag("%s: short read on archive file symbol header", file);
   354			goto out;
   355		}
   356		if(strncmp(arhdr.name, symname, strlen(symname)) == 0) {
   357			off += l;
   358			l = nextar(f, off, &arhdr);
   359			if(l <= 0) {
   360				diag("%s: short read on archive file symbol header", file);
   361				goto out;
   362			}
   363		}
   364	
   365		if(strncmp(arhdr.name, pkgname, strlen(pkgname))) {
   366			diag("%s: cannot find package header", file);
   367			goto out;
   368		}
   369		off += l;
   370	
   371		if(debug['u'])
   372			ldpkg(f, pkg, atolwhex(arhdr.size), file, Pkgdef);
   373	
   374		/*
   375		 * load all the object files from the archive now.
   376		 * this gives us sequential file access and keeps us
   377		 * from needing to come back later to pick up more
   378		 * objects.  it breaks the usual C archive model, but
   379		 * this is Go, not C.  the common case in Go is that
   380		 * we need to load all the objects, and then we throw away
   381		 * the individual symbols that are unused.
   382		 *
   383		 * loading every object will also make it possible to
   384		 * load foreign objects not referenced by __.GOSYMDEF.
   385		 */
   386		for(;;) {
   387			l = nextar(f, off, &arhdr);
   388			if(l == 0)
   389				break;
   390			if(l < 0) {
   391				diag("%s: malformed archive", file);
   392				goto out;
   393			}
   394			off += l;
   395	
   396			l = SARNAME;
   397			while(l > 0 && arhdr.name[l-1] == ' ')
   398				l--;
   399			snprint(pname, sizeof pname, "%s(%.*s)", file, utfnlen(arhdr.name, l), arhdr.name);
   400			l = atolwhex(arhdr.size);
   401			ldobj(f, pkg, l, pname, file, ArchiveObj);
   402		}
   403	
   404	out:
   405		Bterm(f);
   406		free(pkg);
   407	}
   408	
   409	static void
   410	dowrite(int fd, char *p, int n)
   411	{
   412		int m;
   413		
   414		while(n > 0) {
   415			m = write(fd, p, n);
   416			if(m <= 0) {
   417				ctxt->cursym = S;
   418				diag("write error: %r");
   419				errorexit();
   420			}
   421			n -= m;
   422			p += m;
   423		}
   424	}
   425	
   426	typedef struct Hostobj Hostobj;
   427	
   428	struct Hostobj
   429	{
   430		void (*ld)(Biobuf*, char*, int64, char*);
   431		char *pkg;
   432		char *pn;
   433		char *file;
   434		int64 off;
   435		int64 len;
   436	};
   437	
   438	Hostobj *hostobj;
   439	int nhostobj;
   440	int mhostobj;
   441	
   442	// These packages can use internal linking mode.
   443	// Others trigger external mode.
   444	const char *internalpkg[] = {
   445		"crypto/x509",
   446		"net",
   447		"os/user",
   448		"runtime/cgo",
   449		"runtime/race"
   450	};
   451	
   452	void
   453	ldhostobj(void (*ld)(Biobuf*, char*, int64, char*), Biobuf *f, char *pkg, int64 len, char *pn, char *file)
   454	{
   455		int i, isinternal;
   456		Hostobj *h;
   457	
   458		isinternal = 0;
   459		for(i=0; i<nelem(internalpkg); i++) {
   460			if(strcmp(pkg, internalpkg[i]) == 0) {
   461				isinternal = 1;
   462				break;
   463			}
   464		}
   465	
   466		// DragonFly declares errno with __thread, which results in a symbol
   467		// type of R_386_TLS_GD or R_X86_64_TLSGD. The Go linker does not
   468		// currently know how to handle TLS relocations, hence we have to
   469		// force external linking for any libraries that link in code that
   470		// uses errno. This can be removed if the Go linker ever supports
   471		// these relocation types.
   472		if(HEADTYPE == Hdragonfly)
   473		if(strcmp(pkg, "net") == 0 || strcmp(pkg, "os/user") == 0)
   474			isinternal = 0;
   475	
   476		if(!isinternal)
   477			externalobj = 1;
   478	
   479		if(nhostobj >= mhostobj) {
   480			if(mhostobj == 0)
   481				mhostobj = 16;
   482			else
   483				mhostobj *= 2;
   484			hostobj = erealloc(hostobj, mhostobj*sizeof hostobj[0]);
   485		}
   486		h = &hostobj[nhostobj++];
   487		h->ld = ld;
   488		h->pkg = estrdup(pkg);
   489		h->pn = estrdup(pn);
   490		h->file = estrdup(file);
   491		h->off = Boffset(f);
   492		h->len = len;
   493	}
   494	
   495	void
   496	hostobjs(void)
   497	{
   498		int i;
   499		Biobuf *f;
   500		Hostobj *h;
   501		
   502		for(i=0; i<nhostobj; i++) {
   503			h = &hostobj[i];
   504			f = Bopen(h->file, OREAD);
   505			if(f == nil) {
   506				ctxt->cursym = S;
   507				diag("cannot reopen %s: %r", h->pn);
   508				errorexit();
   509			}
   510			Bseek(f, h->off, 0);
   511			h->ld(f, h->pkg, h->len, h->pn);
   512			Bterm(f);
   513		}
   514	}
   515	
   516	// provided by lib9
   517	int runcmd(char**);
   518	char* mktempdir(void);
   519	void removeall(char*);
   520	
   521	static void
   522	rmtemp(void)
   523	{
   524		removeall(tmpdir);
   525	}
   526	
   527	static void
   528	hostlinksetup(void)
   529	{
   530		char *p;
   531	
   532		if(linkmode != LinkExternal)
   533			return;
   534	
   535		// create temporary directory and arrange cleanup
   536		if(tmpdir == nil) {
   537			tmpdir = mktempdir();
   538			atexit(rmtemp);
   539		}
   540	
   541		// change our output to temporary object file
   542		close(cout);
   543		p = smprint("%s/go.o", tmpdir);
   544		cout = create(p, 1, 0775);
   545		if(cout < 0) {
   546			diag("cannot create %s: %r", p);
   547			errorexit();
   548		}
   549		free(p);
   550	}
   551	
   552	void
   553	hostlink(void)
   554	{
   555		char *p, **argv;
   556		int c, i, w, n, argc, len;
   557		Hostobj *h;
   558		Biobuf *f;
   559		static char buf[64<<10];
   560	
   561		if(linkmode != LinkExternal || nerrors > 0)
   562			return;
   563	
   564		c = 0;
   565		p = extldflags;
   566		while(p != nil) {
   567			while(*p == ' ')
   568				p++;
   569			if(*p == '\0')
   570				break;
   571			c++;
   572			p = strchr(p + 1, ' ');
   573		}
   574	
   575		argv = malloc((14+nhostobj+nldflag+c)*sizeof argv[0]);
   576		argc = 0;
   577		if(extld == nil)
   578			extld = "gcc";
   579		argv[argc++] = extld;
   580		switch(thechar){
   581		case '8':
   582			argv[argc++] = "-m32";
   583			break;
   584		case '6':
   585			argv[argc++] = "-m64";
   586			break;
   587		case '5':
   588			argv[argc++] = "-marm";
   589			break;
   590		}
   591		if(!debug['s'] && !debug_s) {
   592			argv[argc++] = "-gdwarf-2"; 
   593		} else {
   594			argv[argc++] = "-s";
   595		}
   596		if(HEADTYPE == Hdarwin)
   597			argv[argc++] = "-Wl,-no_pie,-pagezero_size,4000000";
   598		if(HEADTYPE == Hopenbsd)
   599			argv[argc++] = "-Wl,-nopie";
   600		
   601		if(iself && AssumeGoldLinker)
   602			argv[argc++] = "-Wl,--rosegment";
   603	
   604		if(flag_shared) {
   605			argv[argc++] = "-Wl,-Bsymbolic";
   606			argv[argc++] = "-shared";
   607		}
   608		argv[argc++] = "-o";
   609		argv[argc++] = outfile;
   610		
   611		if(rpath)
   612			argv[argc++] = smprint("-Wl,-rpath,%s", rpath);
   613	
   614		// Force global symbols to be exported for dlopen, etc.
   615		if(iself)
   616			argv[argc++] = "-rdynamic";
   617	
   618		if(strstr(argv[0], "clang") != nil)
   619			argv[argc++] = "-Qunused-arguments";
   620	
   621		// already wrote main object file
   622		// copy host objects to temporary directory
   623		for(i=0; i<nhostobj; i++) {
   624			h = &hostobj[i];
   625			f = Bopen(h->file, OREAD);
   626			if(f == nil) {
   627				ctxt->cursym = S;
   628				diag("cannot reopen %s: %r", h->pn);
   629				errorexit();
   630			}
   631			Bseek(f, h->off, 0);
   632			p = smprint("%s/%06d.o", tmpdir, i);
   633			argv[argc++] = p;
   634			w = create(p, 1, 0775);
   635			if(w < 0) {
   636				ctxt->cursym = S;
   637				diag("cannot create %s: %r", p);
   638				errorexit();
   639			}
   640			len = h->len;
   641			while(len > 0 && (n = Bread(f, buf, sizeof buf)) > 0){
   642				if(n > len)
   643					n = len;
   644				dowrite(w, buf, n);
   645				len -= n;
   646			}
   647			if(close(w) < 0) {
   648				ctxt->cursym = S;
   649				diag("cannot write %s: %r", p);
   650				errorexit();
   651			}
   652			Bterm(f);
   653		}
   654		
   655		argv[argc++] = smprint("%s/go.o", tmpdir);
   656		for(i=0; i<nldflag; i++)
   657			argv[argc++] = ldflag[i];
   658	
   659		p = extldflags;
   660		while(p != nil) {
   661			while(*p == ' ')
   662				*p++ = '\0';
   663			if(*p == '\0')
   664				break;
   665			argv[argc++] = p;
   666	
   667			// clang, unlike GCC, passes -rdynamic to the linker
   668			// even when linking with -static, causing a linker
   669			// error when using GNU ld.  So take out -rdynamic if
   670			// we added it.  We do it in this order, rather than
   671			// only adding -rdynamic later, so that -extldflags
   672			// can override -rdynamic without using -static.
   673			if(iself && strncmp(p, "-static", 7) == 0 && (p[7]==' ' || p[7]=='\0')) {
   674				for(i=0; i<argc; i++) {
   675					if(strcmp(argv[i], "-rdynamic") == 0)
   676						argv[i] = "-static";
   677				}
   678			}
   679	
   680			p = strchr(p + 1, ' ');
   681		}
   682	
   683		argv[argc] = nil;
   684	
   685		quotefmtinstall();
   686		if(debug['v']) {
   687			Bprint(&bso, "host link:");
   688			for(i=0; i<argc; i++)
   689				Bprint(&bso, " %q", argv[i]);
   690			Bprint(&bso, "\n");
   691			Bflush(&bso);
   692		}
   693	
   694		if(runcmd(argv) < 0) {
   695			ctxt->cursym = S;
   696			diag("%s: running %s failed: %r", argv0, argv[0]);
   697			errorexit();
   698		}
   699	}
   700	
   701	void
   702	ldobj(Biobuf *f, char *pkg, int64 len, char *pn, char *file, int whence)
   703	{
   704		char *line;
   705		int n, c1, c2, c3, c4;
   706		uint32 magic;
   707		vlong import0, import1, eof;
   708		char *t;
   709	
   710		eof = Boffset(f) + len;
   711	
   712		pn = estrdup(pn);
   713	
   714		c1 = BGETC(f);
   715		c2 = BGETC(f);
   716		c3 = BGETC(f);
   717		c4 = BGETC(f);
   718		Bungetc(f);
   719		Bungetc(f);
   720		Bungetc(f);
   721		Bungetc(f);
   722	
   723		magic = c1<<24 | c2<<16 | c3<<8 | c4;
   724		if(magic == 0x7f454c46) {	// \x7F E L F
   725			ldhostobj(ldelf, f, pkg, len, pn, file);
   726			return;
   727		}
   728		if((magic&~1) == 0xfeedface || (magic&~0x01000000) == 0xcefaedfe) {
   729			ldhostobj(ldmacho, f, pkg, len, pn, file);
   730			return;
   731		}
   732		if(c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86) {
   733			ldhostobj(ldpe, f, pkg, len, pn, file);
   734			return;
   735		}
   736	
   737		/* check the header */
   738		line = Brdline(f, '\n');
   739		if(line == nil) {
   740			if(Blinelen(f) > 0) {
   741				diag("%s: not an object file", pn);
   742				return;
   743			}
   744			goto eof;
   745		}
   746		n = Blinelen(f) - 1;
   747		line[n] = '\0';
   748		if(strncmp(line, "go object ", 10) != 0) {
   749			if(strlen(pn) > 3 && strcmp(pn+strlen(pn)-3, ".go") == 0) {
   750				print("%cl: input %s is not .%c file (use %cg to compile .go files)\n", thechar, pn, thechar, thechar);
   751				errorexit();
   752			}
   753			if(strcmp(line, thestring) == 0) {
   754				// old header format: just $GOOS
   755				diag("%s: stale object file", pn);
   756				return;
   757			}
   758			diag("%s: not an object file", pn);
   759			free(pn);
   760			return;
   761		}
   762		
   763		// First, check that the basic goos, goarch, and version match.
   764		t = smprint("%s %s %s ", goos, getgoarch(), getgoversion());
   765		line[n] = ' ';
   766		if(strncmp(line+10, t, strlen(t)) != 0 && !debug['f']) {
   767			line[n] = '\0';
   768			diag("%s: object is [%s] expected [%s]", pn, line+10, t);
   769			free(t);
   770			free(pn);
   771			return;
   772		}
   773		
   774		// Second, check that longer lines match each other exactly,
   775		// so that the Go compiler and write additional information
   776		// that must be the same from run to run.
   777		line[n] = '\0';
   778		if(n-10 > strlen(t)) {
   779			if(theline == nil)
   780				theline = estrdup(line+10);
   781			else if(strcmp(theline, line+10) != 0) {
   782				line[n] = '\0';
   783				diag("%s: object is [%s] expected [%s]", pn, line+10, theline);
   784				free(t);
   785				free(pn);
   786				return;
   787			}
   788		}
   789		free(t);
   790		line[n] = '\n';
   791	
   792		/* skip over exports and other info -- ends with \n!\n */
   793		import0 = Boffset(f);
   794		c1 = '\n';	// the last line ended in \n
   795		c2 = BGETC(f);
   796		c3 = BGETC(f);
   797		while(c1 != '\n' || c2 != '!' || c3 != '\n') {
   798			c1 = c2;
   799			c2 = c3;
   800			c3 = BGETC(f);
   801			if(c3 == Beof)
   802				goto eof;
   803		}
   804		import1 = Boffset(f);
   805	
   806		Bseek(f, import0, 0);
   807		ldpkg(f, pkg, import1 - import0 - 2, pn, whence);	// -2 for !\n
   808		Bseek(f, import1, 0);
   809	
   810		ldobjfile(ctxt, f, pkg, eof - Boffset(f), pn);
   811		free(pn);
   812		return;
   813	
   814	eof:
   815		diag("truncated object file: %s", pn);
   816		free(pn);
   817	}
   818	
   819	void
   820	zerosig(char *sp)
   821	{
   822		LSym *s;
   823	
   824		s = linklookup(ctxt, sp, 0);
   825		s->sig = 0;
   826	}
   827	
   828	void
   829	mywhatsys(void)
   830	{
   831		goroot = getgoroot();
   832		goos = getgoos();
   833		goarch = getgoarch();
   834	
   835		if(strncmp(goarch, thestring, strlen(thestring)) != 0)
   836			sysfatal("cannot use %cc with GOARCH=%s", thechar, goarch);
   837	}
   838	
   839	int
   840	pathchar(void)
   841	{
   842		return '/';
   843	}
   844	
   845	static	uchar*	hunk;
   846	static	uint32	nhunk;
   847	#define	NHUNK	(10UL<<20)
   848	
   849	void*
   850	mal(uint32 n)
   851	{
   852		void *v;
   853	
   854		n = (n+7)&~7;
   855		if(n > NHUNK) {
   856			v = malloc(n);
   857			if(v == nil) {
   858				diag("out of memory");
   859				errorexit();
   860			}
   861			memset(v, 0, n);
   862			return v;
   863		}
   864		if(n > nhunk) {
   865			hunk = malloc(NHUNK);
   866			if(hunk == nil) {
   867				diag("out of memory");
   868				errorexit();
   869			}
   870			nhunk = NHUNK;
   871		}
   872	
   873		v = hunk;
   874		nhunk -= n;
   875		hunk += n;
   876	
   877		memset(v, 0, n);
   878		return v;
   879	}
   880	
   881	void
   882	unmal(void *v, uint32 n)
   883	{
   884		n = (n+7)&~7;
   885		if(hunk - n == v) {
   886			hunk -= n;
   887			nhunk += n;
   888		}
   889	}
   890	
   891	// Copied from ../gc/subr.c:/^pathtoprefix; must stay in sync.
   892	/*
   893	 * Convert raw string to the prefix that will be used in the symbol table.
   894	 * Invalid bytes turn into %xx.	 Right now the only bytes that need
   895	 * escaping are %, ., and ", but we escape all control characters too.
   896	 *
   897	 * If you edit this, edit ../gc/subr.c:/^pathtoprefix too.
   898	 * If you edit this, edit ../../pkg/debug/goobj/read.go:/importPathToPrefix too.
   899	 */
   900	static char*
   901	pathtoprefix(char *s)
   902	{
   903		static char hex[] = "0123456789abcdef";
   904		char *p, *r, *w, *l;
   905		int n;
   906	
   907		// find first character past the last slash, if any.
   908		l = s;
   909		for(r=s; *r; r++)
   910			if(*r == '/')
   911				l = r+1;
   912	
   913		// check for chars that need escaping
   914		n = 0;
   915		for(r=s; *r; r++)
   916			if(*r <= ' ' || (*r == '.' && r >= l) || *r == '%' || *r == '"' || *r >= 0x7f)
   917				n++;
   918	
   919		// quick exit
   920		if(n == 0)
   921			return s;
   922	
   923		// escape
   924		p = mal((r-s)+1+2*n);
   925		for(r=s, w=p; *r; r++) {
   926			if(*r <= ' ' || (*r == '.' && r >= l) || *r == '%' || *r == '"' || *r >= 0x7f) {
   927				*w++ = '%';
   928				*w++ = hex[(*r>>4)&0xF];
   929				*w++ = hex[*r&0xF];
   930			} else
   931				*w++ = *r;
   932		}
   933		*w = '\0';
   934		return p;
   935	}
   936	
   937	int
   938	iconv(Fmt *fp)
   939	{
   940		char *p;
   941	
   942		p = va_arg(fp->args, char*);
   943		if(p == nil) {
   944			fmtstrcpy(fp, "<nil>");
   945			return 0;
   946		}
   947		p = pathtoprefix(p);
   948		fmtstrcpy(fp, p);
   949		return 0;
   950	}
   951	
   952	Section*
   953	addsection(Segment *seg, char *name, int rwx)
   954	{
   955		Section **l;
   956		Section *sect;
   957		
   958		for(l=&seg->sect; *l; l=&(*l)->next)
   959			;
   960		sect = mal(sizeof *sect);
   961		sect->rwx = rwx;
   962		sect->name = name;
   963		sect->seg = seg;
   964		sect->align = PtrSize; // everything is at least pointer-aligned
   965		*l = sect;
   966		return sect;
   967	}
   968	
   969	uint16
   970	le16(uchar *b)
   971	{
   972		return b[0] | b[1]<<8;
   973	}
   974	
   975	uint32
   976	le32(uchar *b)
   977	{
   978		return b[0] | b[1]<<8 | b[2]<<16 | (uint32)b[3]<<24;
   979	}
   980	
   981	uint64
   982	le64(uchar *b)
   983	{
   984		return le32(b) | (uint64)le32(b+4)<<32;
   985	}
   986	
   987	uint16
   988	be16(uchar *b)
   989	{
   990		return b[0]<<8 | b[1];
   991	}
   992	
   993	uint32
   994	be32(uchar *b)
   995	{
   996		return (uint32)b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
   997	}
   998	
   999	uint64
  1000	be64(uchar *b)
  1001	{
  1002		return (uvlong)be32(b)<<32 | be32(b+4);
  1003	}
  1004	
  1005	Endian be = { be16, be32, be64 };
  1006	Endian le = { le16, le32, le64 };
  1007	
  1008	typedef struct Chain Chain;
  1009	struct Chain
  1010	{
  1011		LSym *sym;
  1012		Chain *up;
  1013		int limit;  // limit on entry to sym
  1014	};
  1015	
  1016	static int stkcheck(Chain*, int);
  1017	static void stkprint(Chain*, int);
  1018	static void stkbroke(Chain*, int);
  1019	static LSym *morestack;
  1020	static LSym *newstack;
  1021	
  1022	enum
  1023	{
  1024		HasLinkRegister = (thechar == '5'),
  1025	};
  1026	
  1027	// TODO: Record enough information in new object files to
  1028	// allow stack checks here.
  1029	
  1030	static int
  1031	callsize(void)
  1032	{
  1033		if(thechar == '5')
  1034			return 0;
  1035		return RegSize;
  1036	}
  1037	
  1038	void
  1039	dostkcheck(void)
  1040	{
  1041		Chain ch;
  1042		LSym *s;
  1043		
  1044		morestack = linklookup(ctxt, "runtime.morestack", 0);
  1045		newstack = linklookup(ctxt, "runtime.newstack", 0);
  1046	
  1047		// Every splitting function ensures that there are at least StackLimit
  1048		// bytes available below SP when the splitting prologue finishes.
  1049		// If the splitting function calls F, then F begins execution with
  1050		// at least StackLimit - callsize() bytes available.
  1051		// Check that every function behaves correctly with this amount
  1052		// of stack, following direct calls in order to piece together chains
  1053		// of non-splitting functions.
  1054		ch.up = nil;
  1055		ch.limit = StackLimit - callsize();
  1056	
  1057		// Check every function, but do the nosplit functions in a first pass,
  1058		// to make the printed failure chains as short as possible.
  1059		for(s = ctxt->textp; s != nil; s = s->next) {
  1060			// runtime.racesymbolizethunk is called from gcc-compiled C
  1061			// code running on the operating system thread stack.
  1062			// It uses more than the usual amount of stack but that's okay.
  1063			if(strcmp(s->name, "runtime.racesymbolizethunk") == 0)
  1064				continue;
  1065	
  1066			if(s->nosplit) {
  1067			ctxt->cursym = s;
  1068			ch.sym = s;
  1069			stkcheck(&ch, 0);
  1070		}
  1071		}
  1072		for(s = ctxt->textp; s != nil; s = s->next) {
  1073			if(!s->nosplit) {
  1074			ctxt->cursym = s;
  1075			ch.sym = s;
  1076			stkcheck(&ch, 0);
  1077		}
  1078	}
  1079	}
  1080	
  1081	static int
  1082	stkcheck(Chain *up, int depth)
  1083	{
  1084		Chain ch, ch1;
  1085		LSym *s;
  1086		int limit;
  1087		Reloc *r, *endr;
  1088		Pciter pcsp;
  1089		
  1090		limit = up->limit;
  1091		s = up->sym;
  1092		
  1093		// Don't duplicate work: only need to consider each
  1094		// function at top of safe zone once.
  1095		if(limit == StackLimit-callsize()) {
  1096			if(s->stkcheck)
  1097			return 0;
  1098			s->stkcheck = 1;
  1099		}
  1100		
  1101		if(depth > 100) {
  1102			diag("nosplit stack check too deep");
  1103			stkbroke(up, 0);
  1104			return -1;
  1105		}
  1106	
  1107		if(s->external || s->pcln == nil) {
  1108			// external function.
  1109			// should never be called directly.
  1110			// only diagnose the direct caller.
  1111			if(depth == 1 && s->type != SXREF)
  1112				diag("call to external function %s", s->name);
  1113			return -1;
  1114		}
  1115	
  1116		if(limit < 0) {
  1117			stkbroke(up, limit);
  1118			return -1;
  1119		}
  1120	
  1121		// morestack looks like it calls functions,
  1122		// but it switches the stack pointer first.
  1123		if(s == morestack)
  1124			return 0;
  1125	
  1126		ch.up = up;
  1127		
  1128		// Walk through sp adjustments in function, consuming relocs.
  1129		r = s->r;
  1130		endr = r + s->nr;
  1131		for(pciterinit(ctxt, &pcsp, &s->pcln->pcsp); !pcsp.done; pciternext(&pcsp)) {
  1132			// pcsp.value is in effect for [pcsp.pc, pcsp.nextpc).
  1133	
  1134			// Check stack size in effect for this span.
  1135			if(limit - pcsp.value < 0) {
  1136				stkbroke(up, limit - pcsp.value);
  1137				return -1;
  1138			}
  1139	
  1140			// Process calls in this span.
  1141			for(; r < endr && r->off < pcsp.nextpc; r++) {
  1142				switch(r->type) {
  1143				case R_CALL:
  1144				case R_CALLARM:
  1145					// Direct call.
  1146					ch.limit = limit - pcsp.value - callsize();
  1147					ch.sym = r->sym;
  1148					if(stkcheck(&ch, depth+1) < 0)
  1149						return -1;
  1150	
  1151					// If this is a call to morestack, we've just raised our limit back
  1152					// to StackLimit beyond the frame size.
  1153					if(strncmp(r->sym->name, "runtime.morestack", 17) == 0) {
  1154						limit = StackLimit + s->locals;
  1155						if(thechar == '5')
  1156							limit += 4; // saved LR
  1157					}
  1158					break;
  1159	
  1160				case R_CALLIND:
  1161					// Indirect call.  Assume it is a call to a splitting function,
  1162					// so we have to make sure it can call morestack.
  1163					// Arrange the data structures to report both calls, so that
  1164					// if there is an error, stkprint shows all the steps involved.
  1165					ch.limit = limit - pcsp.value - callsize();
  1166					ch.sym = nil;
  1167					ch1.limit = ch.limit - callsize(); // for morestack in called prologue
  1168					ch1.up = &ch;
  1169					ch1.sym = morestack;
  1170					if(stkcheck(&ch1, depth+2) < 0)
  1171						return -1;
  1172					break;
  1173				}
  1174			}
  1175			}
  1176			
  1177		return 0;
  1178	}
  1179	
  1180	static void
  1181	stkbroke(Chain *ch, int limit)
  1182	{
  1183		diag("nosplit stack overflow");
  1184		stkprint(ch, limit);
  1185	}
  1186	
  1187	static void
  1188	stkprint(Chain *ch, int limit)
  1189	{
  1190		char *name;
  1191	
  1192		if(ch->sym)
  1193			name = ch->sym->name;
  1194		else
  1195			name = "function pointer";
  1196	
  1197		if(ch->up == nil) {
  1198			// top of chain.  ch->sym != nil.
  1199			if(ch->sym->nosplit)
  1200				print("\t%d\tassumed on entry to %s\n", ch->limit, name);
  1201			else
  1202				print("\t%d\tguaranteed after split check in %s\n", ch->limit, name);
  1203		} else {
  1204			stkprint(ch->up, ch->limit + (!HasLinkRegister)*PtrSize);
  1205			if(!HasLinkRegister)
  1206				print("\t%d\ton entry to %s\n", ch->limit, name);
  1207		}
  1208		if(ch->limit != limit)
  1209			print("\t%d\tafter %s uses %d\n", limit, name, ch->limit - limit);
  1210	}
  1211	
  1212	int
  1213	Yconv(Fmt *fp)
  1214	{
  1215		LSym *s;
  1216		Fmt fmt;
  1217		int i;
  1218		char *str;
  1219	
  1220		s = va_arg(fp->args, LSym*);
  1221		if (s == S) {
  1222			fmtprint(fp, "<nil>");
  1223		} else {
  1224			fmtstrinit(&fmt);
  1225			fmtprint(&fmt, "%s @0x%08llx [%lld]", s->name, (vlong)s->value, (vlong)s->size);
  1226			for (i = 0; i < s->size; i++) {
  1227				if (!(i%8)) fmtprint(&fmt,  "\n\t0x%04x ", i);
  1228				fmtprint(&fmt, "%02x ", s->p[i]);
  1229			}
  1230			fmtprint(&fmt, "\n");
  1231			for (i = 0; i < s->nr; i++) {
  1232				fmtprint(&fmt, "\t0x%04x[%x] %d %s[%llx]\n",
  1233				      s->r[i].off,
  1234				      s->r[i].siz,
  1235				      s->r[i].type,
  1236				      s->r[i].sym->name,
  1237				      (vlong)s->r[i].add);
  1238			}
  1239			str = fmtstrflush(&fmt);
  1240			fmtstrcpy(fp, str);
  1241			free(str);
  1242		}
  1243	
  1244		return 0;
  1245	}
  1246	
  1247	vlong coutpos;
  1248	
  1249	void
  1250	cflush(void)
  1251	{
  1252		int n;
  1253	
  1254		if(cbpmax < cbp)
  1255			cbpmax = cbp;
  1256		n = cbpmax - buf.cbuf;
  1257		dowrite(cout, buf.cbuf, n);
  1258		coutpos += n;
  1259		cbp = buf.cbuf;
  1260		cbc = sizeof(buf.cbuf);
  1261		cbpmax = cbp;
  1262	}
  1263	
  1264	vlong
  1265	cpos(void)
  1266	{
  1267		return coutpos + cbp - buf.cbuf;
  1268	}
  1269	
  1270	void
  1271	cseek(vlong p)
  1272	{
  1273		vlong start;
  1274		int delta;
  1275	
  1276		if(cbpmax < cbp)
  1277			cbpmax = cbp;
  1278		start = coutpos;
  1279		if(start <= p && p <= start+(cbpmax - buf.cbuf)) {
  1280	//print("cseek %lld in [%lld,%lld] (%lld)\n", p, start, start+sizeof(buf.cbuf), cpos());
  1281			delta = p - (start + cbp - buf.cbuf);
  1282			cbp += delta;
  1283			cbc -= delta;
  1284	//print("now at %lld\n", cpos());
  1285			return;
  1286		}
  1287	
  1288		cflush();
  1289		seek(cout, p, 0);
  1290		coutpos = p;
  1291	}
  1292	
  1293	void
  1294	cwrite(void *buf, int n)
  1295	{
  1296		cflush();
  1297		if(n <= 0)
  1298			return;
  1299		dowrite(cout, buf, n);
  1300		coutpos += n;
  1301	}
  1302	
  1303	void
  1304	usage(void)
  1305	{
  1306		fprint(2, "usage: %cl [options] main.%c\n", thechar, thechar);
  1307		flagprint(2);
  1308		exits("usage");
  1309	}
  1310	
  1311	void
  1312	setheadtype(char *s)
  1313	{
  1314		int h;
  1315		
  1316		h = headtype(s);
  1317		if(h < 0) {
  1318			fprint(2, "unknown header type -H %s\n", s);
  1319			errorexit();
  1320		}
  1321		headstring = s;
  1322		HEADTYPE = headtype(s);
  1323	}
  1324	
  1325	void
  1326	setinterp(char *s)
  1327	{
  1328		debug['I'] = 1; // denote cmdline interpreter override
  1329		interpreter = s;
  1330	}
  1331	
  1332	void
  1333	doversion(void)
  1334	{
  1335		print("%cl version %s\n", thechar, getgoversion());
  1336		errorexit();
  1337	}
  1338	
  1339	void
  1340	genasmsym(void (*put)(LSym*, char*, int, vlong, vlong, int, LSym*))
  1341	{
  1342		Auto *a;
  1343		LSym *s;
  1344		int32 off;
  1345	
  1346		// These symbols won't show up in the first loop below because we
  1347		// skip STEXT symbols. Normal STEXT symbols are emitted by walking textp.
  1348		s = linklookup(ctxt, "text", 0);
  1349		if(s->type == STEXT)
  1350			put(s, s->name, 'T', s->value, s->size, s->version, 0);
  1351		s = linklookup(ctxt, "etext", 0);
  1352		if(s->type == STEXT)
  1353			put(s, s->name, 'T', s->value, s->size, s->version, 0);
  1354	
  1355		for(s=ctxt->allsym; s!=S; s=s->allsym) {
  1356			if(s->hide || (s->name[0] == '.' && s->version == 0 && strcmp(s->name, ".rathole") != 0))
  1357				continue;
  1358			switch(s->type&SMASK) {
  1359			case SCONST:
  1360			case SRODATA:
  1361			case SSYMTAB:
  1362			case SPCLNTAB:
  1363			case SDATA:
  1364			case SNOPTRDATA:
  1365			case SELFROSECT:
  1366			case SMACHOGOT:
  1367			case STYPE:
  1368			case SSTRING:
  1369			case SGOSTRING:
  1370			case SWINDOWS:
  1371				if(!s->reachable)
  1372					continue;
  1373				put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
  1374				continue;
  1375	
  1376			case SBSS:
  1377			case SNOPTRBSS:
  1378				if(!s->reachable)
  1379					continue;
  1380				if(s->np > 0)
  1381					diag("%s should not be bss (size=%d type=%d special=%d)", s->name, (int)s->np, s->type, s->special);
  1382				put(s, s->name, 'B', symaddr(s), s->size, s->version, s->gotype);
  1383				continue;
  1384	
  1385			case SFILE:
  1386				put(nil, s->name, 'f', s->value, 0, s->version, 0);
  1387				continue;
  1388			}
  1389		}
  1390	
  1391		for(s = ctxt->textp; s != nil; s = s->next) {
  1392			put(s, s->name, 'T', s->value, s->size, s->version, s->gotype);
  1393	
  1394			// NOTE(ality): acid can't produce a stack trace without .frame symbols
  1395			put(nil, ".frame", 'm', s->locals+PtrSize, 0, 0, 0);
  1396	
  1397			for(a=s->autom; a; a=a->link) {
  1398				// Emit a or p according to actual offset, even if label is wrong.
  1399				// This avoids negative offsets, which cannot be encoded.
  1400				if(a->type != A_AUTO && a->type != A_PARAM)
  1401					continue;
  1402				
  1403				// compute offset relative to FP
  1404				if(a->type == A_PARAM)
  1405					off = a->aoffset;
  1406				else
  1407					off = a->aoffset - PtrSize;
  1408				
  1409				// FP
  1410				if(off >= 0) {
  1411					put(nil, a->asym->name, 'p', off, 0, 0, a->gotype);
  1412					continue;
  1413				}
  1414				
  1415				// SP
  1416				if(off <= -PtrSize) {
  1417					put(nil, a->asym->name, 'a', -(off+PtrSize), 0, 0, a->gotype);
  1418					continue;
  1419				}
  1420				
  1421				// Otherwise, off is addressing the saved program counter.
  1422				// Something underhanded is going on. Say nothing.
  1423			}
  1424		}
  1425		if(debug['v'] || debug['n'])
  1426			Bprint(&bso, "%5.2f symsize = %ud\n", cputime(), symsize);
  1427		Bflush(&bso);
  1428	}
  1429	
  1430	vlong
  1431	symaddr(LSym *s)
  1432	{
  1433		if(!s->reachable)
  1434			diag("unreachable symbol in symaddr - %s", s->name);
  1435		return s->value;
  1436	}
  1437	
  1438	void
  1439	xdefine(char *p, int t, vlong v)
  1440	{
  1441		LSym *s;
  1442	
  1443		s = linklookup(ctxt, p, 0);
  1444		s->type = t;
  1445		s->value = v;
  1446		s->reachable = 1;
  1447		s->special = 1;
  1448	}
  1449	
  1450	vlong
  1451	datoff(vlong addr)
  1452	{
  1453		if(addr >= segdata.vaddr)
  1454			return addr - segdata.vaddr + segdata.fileoff;
  1455		if(addr >= segtext.vaddr)
  1456			return addr - segtext.vaddr + segtext.fileoff;
  1457		diag("datoff %#llx", addr);
  1458		return 0;
  1459	}
  1460	
  1461	vlong
  1462	entryvalue(void)
  1463	{
  1464		char *a;
  1465		LSym *s;
  1466	
  1467		a = INITENTRY;
  1468		if(*a >= '0' && *a <= '9')
  1469			return atolwhex(a);
  1470		s = linklookup(ctxt, a, 0);
  1471		if(s->type == 0)
  1472			return INITTEXT;
  1473		if(s->type != STEXT)
  1474			diag("entry not text: %s", s->name);
  1475		return s->value;
  1476	}
  1477	
  1478	static void
  1479	undefsym(LSym *s)
  1480	{
  1481		int i;
  1482		Reloc *r;
  1483	
  1484		ctxt->cursym = s;
  1485		for(i=0; i<s->nr; i++) {
  1486			r = &s->r[i];
  1487			if(r->sym == nil) // happens for some external ARM relocs
  1488				continue;
  1489			if(r->sym->type == Sxxx || r->sym->type == SXREF)
  1490				diag("undefined: %s", r->sym->name);
  1491			if(!r->sym->reachable)
  1492				diag("use of unreachable symbol: %s", r->sym->name);
  1493		}
  1494	}
  1495	
  1496	void
  1497	undef(void)
  1498	{
  1499		LSym *s;
  1500		
  1501		for(s = ctxt->textp; s != nil; s = s->next)
  1502			undefsym(s);
  1503		for(s = datap; s != nil; s = s->next)
  1504			undefsym(s);
  1505		if(nerrors > 0)
  1506			errorexit();
  1507	}
  1508	
  1509	void
  1510	callgraph(void)
  1511	{
  1512		LSym *s;
  1513		Reloc *r;
  1514		int i;
  1515	
  1516		if(!debug['c'])
  1517			return;
  1518	
  1519		for(s = ctxt->textp; s != nil; s = s->next) {
  1520			for(i=0; i<s->nr; i++) {
  1521				r = &s->r[i];
  1522				if(r->sym == nil)
  1523					continue;
  1524				if((r->type == R_CALL || r->type == R_CALLARM) && r->sym->type == STEXT)
  1525					Bprint(&bso, "%s calls %s\n", s->name, r->sym->name);
  1526			}
  1527		}
  1528	}
  1529	
  1530	void
  1531	diag(char *fmt, ...)
  1532	{
  1533		char buf[1024], *tn, *sep;
  1534		va_list arg;
  1535	
  1536		tn = "";
  1537		sep = "";
  1538		if(ctxt->cursym != S) {
  1539			tn = ctxt->cursym->name;
  1540			sep = ": ";
  1541		}
  1542		va_start(arg, fmt);
  1543		vseprint(buf, buf+sizeof(buf), fmt, arg);
  1544		va_end(arg);
  1545		print("%s%s%s\n", tn, sep, buf);
  1546	
  1547		nerrors++;
  1548		if(nerrors > 20) {
  1549			print("too many errors\n");
  1550			errorexit();
  1551		}
  1552	}

View as plain text