The Go Programming Language

Text file src/libmach/obj.c

     1	// Inferno libmach/obj.c
     2	// http://code.google.com/p/inferno-os/source/browse/utils/libmach/obj.c
     3	//
     4	// 	Copyright © 1994-1999 Lucent Technologies Inc.
     5	// 	Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
     6	// 	Portions Copyright © 1997-1999 Vita Nuova Limited.
     7	// 	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
     8	// 	Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
     9	//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    10	//
    11	// Permission is hereby granted, free of charge, to any person obtaining a copy
    12	// of this software and associated documentation files (the "Software"), to deal
    13	// in the Software without restriction, including without limitation the rights
    14	// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    15	// copies of the Software, and to permit persons to whom the Software is
    16	// furnished to do so, subject to the following conditions:
    17	//
    18	// The above copyright notice and this permission notice shall be included in
    19	// all copies or substantial portions of the Software.
    20	//
    21	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    22	// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    23	// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    24	// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    25	// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    26	// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    27	// THE SOFTWARE.
    28	
    29	/*
    30	 * obj.c
    31	 * routines universal to all object files
    32	 */
    33	#include <u.h>
    34	#include <libc.h>
    35	#include <bio.h>
    36	#include <ar.h>
    37	#include <mach.h>
    38	#include "obj.h"
    39	
    40	#define islocal(t)	((t)=='a' || (t)=='p')
    41	
    42	enum
    43	{
    44		NNAMES	= 50,
    45		MAXIS	= 8,		/* max length to determine if a file is a .? file */
    46		MAXOFF	= 0x7fffffff,	/* larger than any possible local offset */
    47		NHASH	= 1024,		/* must be power of two */
    48		HASHMUL	= 79L,
    49	};
    50	
    51	int	_is2(char*),		/* in [$OS].c */
    52		_is5(char*),
    53		_is6(char*),
    54		_is7(char*),
    55		_is8(char*),
    56		_is9(char*),
    57		_isk(char*),
    58		_isq(char*),
    59		_isv(char*),
    60		_isu(char*),
    61		_read2(Biobuf*, Prog*),
    62		_read5(Biobuf*, Prog*),
    63		_read6(Biobuf*, Prog*),
    64		_read7(Biobuf*, Prog*),
    65		_read8(Biobuf*, Prog*),
    66		_read9(Biobuf*, Prog*),
    67		_readk(Biobuf*, Prog*),
    68		_readq(Biobuf*, Prog*),
    69		_readv(Biobuf*, Prog*),
    70		_readu(Biobuf*, Prog*);
    71	
    72	typedef struct Obj	Obj;
    73	typedef struct Symtab	Symtab;
    74	
    75	struct	Obj		/* functions to handle each intermediate (.$O) file */
    76	{
    77		char	*name;				/* name of each $O file */
    78		int	(*is)(char*);			/* test for each type of $O file */
    79		int	(*read)(Biobuf*, Prog*);	/* read for each type of $O file*/
    80	};
    81	
    82	static Obj	obj[] =
    83	{			/* functions to identify and parse each type of obj */
    84		[Obj68020]   = { "68020 .2",	_is2, _read2 },
    85		[ObjAmd64]   = { "amd64 .6",	_is6 , _read6 },
    86		[ObjArm]     = { "arm .5",	_is5, _read5 },
    87		[ObjAlpha]   = { "alpha .7",	_is7, _read7 },
    88		[Obj386]     = { "386 .8",	_is8, _read8 },
    89		[ObjSparc]   = { "sparc .k",	_isk, _readk },
    90		[ObjPower]   = { "power .q",	_isq, _readq },
    91		[ObjMips]    = { "mips .v",	_isv, _readv },
    92		[ObjSparc64] = { "sparc64 .u",  _isu, _readu },
    93		[ObjPower64] = { "power64 .9",	_is9, _read9 },
    94		[Maxobjtype] = { 0, 0, 0 }
    95	};
    96	
    97	struct	Symtab
    98	{
    99		struct	Sym 	s;
   100		struct	Symtab	*next;
   101	};
   102	
   103	static	Symtab *hash[NHASH];
   104	static	Sym	*names[NNAMES];	/* working set of active names */
   105	
   106	static	int	processprog(Prog*,int);	/* decode each symbol reference */
   107	static	void	objreset(void);
   108	static	void	objlookup(int, char *, int, uint);
   109	static	void 	objupdate(int, int);
   110	
   111	static	int	sequence;
   112	
   113	int
   114	objtype(Biobuf *bp, char **name)
   115	{
   116		int i;
   117		char buf[MAXIS];
   118		int c;
   119		char *p;
   120	
   121		/*
   122		 * Look for import block.
   123		 */
   124		p = Brdline(bp, '\n');
   125		if(p == nil)
   126			return -1;
   127		if(Blinelen(bp) < 10 || strncmp(p, "go object ", 10) != 0)
   128			return -1;
   129		Bseek(bp, -1, 1);
   130	
   131		/*
   132		 * Found one.  Skip until "\n!\n"
   133		 */
   134		for(;;) {
   135			if((c = Bgetc(bp)) == Beof)
   136				return -1;
   137			if(c != '\n')
   138				continue;
   139			c = Bgetc(bp);
   140			if(c != '!'){
   141				Bungetc(bp);
   142				continue;
   143			}
   144			c = Bgetc(bp);
   145			if(c != '\n'){
   146				Bungetc(bp);
   147				continue;
   148			}
   149			break;
   150		}
   151	
   152		if(Bread(bp, buf, MAXIS) < MAXIS)
   153			return -1;
   154		Bseek(bp, -MAXIS, 1);
   155		for (i = 0; i < Maxobjtype; i++) {
   156			if (obj[i].is && (*obj[i].is)(buf)) {
   157				if (name)
   158					*name = obj[i].name;
   159				return i;
   160			}
   161		}
   162	
   163		return -1;
   164	}
   165	
   166	int
   167	isar(Biobuf *bp)
   168	{
   169		int n;
   170		char magbuf[SARMAG];
   171	
   172		n = Bread(bp, magbuf, SARMAG);
   173		if(n == SARMAG && strncmp(magbuf, ARMAG, SARMAG) == 0)
   174			return 1;
   175		return 0;
   176	}
   177	
   178	/*
   179	 * determine what kind of object file this is and process it.
   180	 * return whether or not this was a recognized intermediate file.
   181	 */
   182	int
   183	readobj(Biobuf *bp, int objtype)
   184	{
   185		Prog p;
   186	
   187		if (objtype < 0 || objtype >= Maxobjtype || obj[objtype].is == 0)
   188			return 1;
   189		objreset();
   190		while ((*obj[objtype].read)(bp, &p))
   191			if (!processprog(&p, 1))
   192				return 0;
   193		return 1;
   194	}
   195	
   196	int
   197	readar(Biobuf *bp, int objtype, vlong end, int doautos)
   198	{
   199		Prog p;
   200	
   201		if (objtype < 0 || objtype >= Maxobjtype || obj[objtype].is == 0)
   202			return 1;
   203		objreset();
   204		while ((*obj[objtype].read)(bp, &p) && Boffset(bp) < end)
   205			if (!processprog(&p, doautos))
   206				return 0;
   207		return 1;
   208	}
   209	
   210	/*
   211	 *	decode a symbol reference or definition
   212	 */
   213	static	int
   214	processprog(Prog *p, int doautos)
   215	{
   216		if(p->kind == aNone)
   217			return 1;
   218		if((schar)p->sym < 0 || p->sym >= NNAMES)
   219			return 0;
   220		switch(p->kind)
   221		{
   222		case aName:
   223			if (!doautos)
   224			if(p->type != 'U' && p->type != 'b')
   225				break;
   226			objlookup(p->sym, p->id, p->type, p->sig);
   227			break;
   228		case aText:
   229			objupdate(p->sym, 'T');
   230			break;
   231		case aData:
   232			objupdate(p->sym, 'D');
   233			break;
   234		default:
   235			break;
   236		}
   237		return 1;
   238	}
   239	
   240	/*
   241	 * find the entry for s in the symbol array.
   242	 * make a new entry if it is not already there.
   243	 */
   244	static void
   245	objlookup(int id, char *name, int type, uint sig)
   246	{
   247		int32 h;
   248		char *cp;
   249		Sym *s;
   250		Symtab *sp;
   251	
   252		s = names[id];
   253		if(s && strcmp(s->name, name) == 0) {
   254			s->type = type;
   255			s->sig = sig;
   256			return;
   257		}
   258	
   259		h = *name;
   260		for(cp = name+1; *cp; h += *cp++)
   261			h *= HASHMUL;
   262		h &= NHASH-1;
   263		if (type == 'U' || type == 'b' || islocal(type)) {
   264			for(sp = hash[h]; sp; sp = sp->next)
   265				if(strcmp(sp->s.name, name) == 0) {
   266					switch(sp->s.type) {
   267					case 'T':
   268					case 'D':
   269					case 'U':
   270						if (type == 'U') {
   271							names[id] = &sp->s;
   272							return;
   273						}
   274						break;
   275					case 't':
   276					case 'd':
   277					case 'b':
   278						if (type == 'b') {
   279							names[id] = &sp->s;
   280							return;
   281						}
   282						break;
   283					case 'a':
   284					case 'p':
   285						if (islocal(type)) {
   286							names[id] = &sp->s;
   287							return;
   288						}
   289						break;
   290					default:
   291						break;
   292					}
   293				}
   294		}
   295		sp = malloc(sizeof(Symtab));
   296		sp->s.name = name;
   297		sp->s.type = type;
   298		sp->s.sig = sig;
   299		sp->s.value = islocal(type) ? MAXOFF : 0;
   300		sp->s.sequence = sequence++;
   301		names[id] = &sp->s;
   302		sp->next = hash[h];
   303		hash[h] = sp;
   304		return;
   305	}
   306	/*
   307	 *	traverse the symbol lists
   308	 */
   309	void
   310	objtraverse(void (*fn)(Sym*, void*), void *pointer)
   311	{
   312		int i;
   313		Symtab *s;
   314	
   315		for(i = 0; i < NHASH; i++)
   316			for(s = hash[i]; s; s = s->next)
   317				(*fn)(&s->s, pointer);
   318	}
   319	
   320	/*
   321	 * update the offset information for a 'a' or 'p' symbol in an intermediate file
   322	 */
   323	void
   324	_offset(int id, vlong off)
   325	{
   326		Sym *s;
   327	
   328		s = names[id];
   329		if (s && s->name[0] && islocal(s->type) && s->value > off)
   330			s->value = off;
   331	}
   332	
   333	/*
   334	 * update the type of a global text or data symbol
   335	 */
   336	static void
   337	objupdate(int id, int type)
   338	{
   339		Sym *s;
   340	
   341		s = names[id];
   342		if (s && s->name[0])
   343			if (s->type == 'U')
   344				s->type = type;
   345			else if (s->type == 'b')
   346				s->type = tolower(type);
   347	}
   348	
   349	/*
   350	 * look for the next file in an archive
   351	 */
   352	int
   353	nextar(Biobuf *bp, int offset, char *buf)
   354	{
   355		struct ar_hdr a;
   356		int i, r;
   357		int32 arsize;
   358	
   359		if (offset&01)
   360			offset++;
   361		Bseek(bp, offset, 0);
   362		r = Bread(bp, &a, SAR_HDR);
   363		if(r != SAR_HDR)
   364			return 0;
   365		if(strncmp(a.fmag, ARFMAG, sizeof(a.fmag)))
   366			return -1;
   367		for(i=0; i<sizeof(a.name) && i<SARNAME && a.name[i] != ' '; i++)
   368			buf[i] = a.name[i];
   369		buf[i] = 0;
   370		arsize = strtol(a.size, 0, 0);
   371		if (arsize&1)
   372			arsize++;
   373		return arsize + SAR_HDR;
   374	}
   375	
   376	static void
   377	objreset(void)
   378	{
   379		int i;
   380		Symtab *s, *n;
   381	
   382		for(i = 0; i < NHASH; i++) {
   383			for(s = hash[i]; s; s = n) {
   384				n = s->next;
   385				free(s->s.name);
   386				free(s);
   387			}
   388			hash[i] = 0;
   389		}
   390		memset(names, 0, sizeof names);
   391	}

release.r60.3. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.