github.com/zach-klippenstein/go@v0.0.0-20150108044943-fcfbeb3adf58/src/cmd/ld/ldmacho.c (about)

     1  /*
     2  Derived from Plan 9 from User Space's src/libmach/elf.h, elf.c
     3  http://code.swtch.com/plan9port/src/tip/src/libmach/
     4  
     5  	Copyright © 2004 Russ Cox.
     6  	Portions Copyright © 2008-2010 Google Inc.
     7  	Portions Copyright © 2010 The Go Authors.
     8  
     9  Permission is hereby granted, free of charge, to any person obtaining a copy
    10  of this software and associated documentation files (the "Software"), to deal
    11  in the Software without restriction, including without limitation the rights
    12  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    13  copies of the Software, and to permit persons to whom the Software is
    14  furnished to do so, subject to the following conditions:
    15  
    16  The above copyright notice and this permission notice shall be included in
    17  all copies or substantial portions of the Software.
    18  
    19  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    20  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    21  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    22  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    23  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    24  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    25  THE SOFTWARE.
    26  */
    27  
    28  #include	"l.h"
    29  #include	"lib.h"
    30  
    31  enum {
    32  	MACHO_FAKE_GOTPCREL = 100,	// from macho.h
    33  	
    34  	N_EXT = 0x01,
    35  	N_TYPE = 0x1e,
    36  	N_STAB = 0xe0,
    37  };
    38  
    39  typedef struct MachoObj MachoObj;
    40  typedef struct MachoCmd MachoCmd;
    41  typedef struct MachoSeg MachoSeg;
    42  typedef struct MachoSect MachoSect;
    43  typedef struct MachoRel MachoRel;
    44  typedef struct MachoSymtab MachoSymtab;
    45  typedef struct MachoSym MachoSym;
    46  typedef struct MachoDysymtab MachoDysymtab;
    47  
    48  enum
    49  {
    50  	MachoCpuVax = 1,
    51  	MachoCpu68000 = 6,
    52  	MachoCpu386 = 7,
    53  	MachoCpuAmd64 = 0x1000007,
    54  	MachoCpuMips = 8,
    55  	MachoCpu98000 = 10,
    56  	MachoCpuHppa = 11,
    57  	MachoCpuArm = 12,
    58  	MachoCpu88000 = 13,
    59  	MachoCpuSparc = 14,
    60  	MachoCpu860 = 15,
    61  	MachoCpuAlpha = 16,
    62  	MachoCpuPower = 18,
    63  
    64  	MachoCmdSegment = 1,
    65  	MachoCmdSymtab = 2,
    66  	MachoCmdSymseg = 3,
    67  	MachoCmdThread = 4,
    68  	MachoCmdDysymtab = 11,
    69  	MachoCmdSegment64 = 25,
    70  
    71  	MachoFileObject = 1,
    72  	MachoFileExecutable = 2,
    73  	MachoFileFvmlib = 3,
    74  	MachoFileCore = 4,
    75  	MachoFilePreload = 5,
    76  };
    77  
    78  struct MachoSeg
    79  {
    80  	char name[16+1];
    81  	uint64 vmaddr;
    82  	uint64 vmsize;
    83  	uint32 fileoff;
    84  	uint32 filesz;
    85  	uint32 maxprot;
    86  	uint32 initprot;
    87  	uint32 nsect;
    88  	uint32 flags;
    89  	MachoSect *sect;
    90  };
    91  
    92  struct MachoSect
    93  {
    94  	char	name[16+1];
    95  	char	segname[16+1];
    96  	uint64 addr;
    97  	uint64 size;
    98  	uint32 off;
    99  	uint32 align;
   100  	uint32 reloff;
   101  	uint32 nreloc;
   102  	uint32 flags;
   103  	uint32 res1;
   104  	uint32 res2;
   105  	LSym *sym;
   106  	
   107  	MachoRel *rel;
   108  };
   109  
   110  struct MachoRel
   111  {
   112  	uint32 addr;
   113  	uint32 symnum;
   114  	uint8 pcrel;
   115  	uint8 length;
   116  	uint8 extrn;
   117  	uint8 type;
   118  	uint8 scattered;
   119  	uint32 value;
   120  };
   121  
   122  struct MachoSymtab
   123  {
   124  	uint32 symoff;
   125  	uint32 nsym;
   126  	uint32 stroff;
   127  	uint32 strsize;
   128  	
   129  	char *str;
   130  	MachoSym *sym;
   131  };
   132  
   133  struct MachoSym
   134  {
   135  	char *name;
   136  	uint8 type;
   137  	uint8 sectnum;
   138  	uint16 desc;
   139  	char kind;
   140  	uint64 value;
   141  	LSym *sym;
   142  };
   143  
   144  struct MachoDysymtab
   145  {
   146  	uint32 ilocalsym;
   147  	uint32 nlocalsym;
   148  	uint32 iextdefsym;
   149  	uint32 nextdefsym;
   150  	uint32 iundefsym;
   151  	uint32 nundefsym;
   152  	uint32 tocoff;
   153  	uint32 ntoc;
   154  	uint32 modtaboff;
   155  	uint32 nmodtab;
   156  	uint32 extrefsymoff;
   157  	uint32 nextrefsyms;
   158  	uint32 indirectsymoff;
   159  	uint32 nindirectsyms;
   160  	uint32 extreloff;
   161  	uint32 nextrel;
   162  	uint32 locreloff;
   163  	uint32 nlocrel;
   164  	uint32 *indir;
   165  };
   166  
   167  struct MachoCmd
   168  {
   169  	int type;
   170  	uint32 off;
   171  	uint32 size;
   172  	MachoSeg seg;
   173  	MachoSymtab sym;
   174  	MachoDysymtab dsym;
   175  };
   176  
   177  struct MachoObj
   178  {
   179  	Biobuf	*f;
   180  	int64	base;	// off in f where Mach-O begins
   181  	int64	len;		// length of Mach-O
   182  	int is64;
   183  	char	*name;
   184  
   185  	Endian	*e;
   186  	uint cputype;
   187  	uint subcputype;
   188  	uint32 filetype;
   189  	uint32 flags;
   190  	MachoCmd *cmd;
   191  	uint ncmd;
   192  };
   193  
   194  static int
   195  unpackcmd(uchar *p, MachoObj *m, MachoCmd *c, uint type, uint sz)
   196  {
   197  	uint32 (*e4)(uchar*);
   198  	uint64 (*e8)(uchar*);
   199  	MachoSect *s;
   200  	int i;
   201  
   202  	e4 = m->e->e32;
   203  	e8 = m->e->e64;
   204  
   205  	c->type = type;
   206  	c->size = sz;
   207  	switch(type){
   208  	default:
   209  		return -1;
   210  	case MachoCmdSegment:
   211  		if(sz < 56)
   212  			return -1;
   213  		strecpy(c->seg.name, c->seg.name+sizeof c->seg.name, (char*)p+8);
   214  		c->seg.vmaddr = e4(p+24);
   215  		c->seg.vmsize = e4(p+28);
   216  		c->seg.fileoff = e4(p+32);
   217  		c->seg.filesz = e4(p+36);
   218  		c->seg.maxprot = e4(p+40);
   219  		c->seg.initprot = e4(p+44);
   220  		c->seg.nsect = e4(p+48);
   221  		c->seg.flags = e4(p+52);
   222  		c->seg.sect = mal(c->seg.nsect * sizeof c->seg.sect[0]);
   223  		if(sz < 56+c->seg.nsect*68)
   224  			return -1;
   225  		p += 56;
   226  		for(i=0; i<c->seg.nsect; i++) {
   227  			s = &c->seg.sect[i];
   228  			strecpy(s->name, s->name+sizeof s->name, (char*)p+0);
   229  			strecpy(s->segname, s->segname+sizeof s->segname, (char*)p+16);
   230  			s->addr = e4(p+32);
   231  			s->size = e4(p+36);
   232  			s->off = e4(p+40);
   233  			s->align = e4(p+44);
   234  			s->reloff = e4(p+48);
   235  			s->nreloc = e4(p+52);
   236  			s->flags = e4(p+56);
   237  			s->res1 = e4(p+60);
   238  			s->res2 = e4(p+64);
   239  			p += 68;
   240  		}
   241  		break;
   242  	case MachoCmdSegment64:
   243  		if(sz < 72)
   244  			return -1;
   245  		strecpy(c->seg.name, c->seg.name+sizeof c->seg.name, (char*)p+8);
   246  		c->seg.vmaddr = e8(p+24);
   247  		c->seg.vmsize = e8(p+32);
   248  		c->seg.fileoff = e8(p+40);
   249  		c->seg.filesz = e8(p+48);
   250  		c->seg.maxprot = e4(p+56);
   251  		c->seg.initprot = e4(p+60);
   252  		c->seg.nsect = e4(p+64);
   253  		c->seg.flags = e4(p+68);
   254  		c->seg.sect = mal(c->seg.nsect * sizeof c->seg.sect[0]);
   255  		if(sz < 72+c->seg.nsect*80)
   256  			return -1;
   257  		p += 72;
   258  		for(i=0; i<c->seg.nsect; i++) {
   259  			s = &c->seg.sect[i];
   260  			strecpy(s->name, s->name+sizeof s->name, (char*)p+0);
   261  			strecpy(s->segname, s->segname+sizeof s->segname, (char*)p+16);
   262  			s->addr = e8(p+32);
   263  			s->size = e8(p+40);
   264  			s->off = e4(p+48);
   265  			s->align = e4(p+52);
   266  			s->reloff = e4(p+56);
   267  			s->nreloc = e4(p+60);
   268  			s->flags = e4(p+64);
   269  			s->res1 = e4(p+68);
   270  			s->res2 = e4(p+72);
   271  			// p+76 is reserved
   272  			p += 80;
   273  		}
   274  		break;
   275  	case MachoCmdSymtab:
   276  		if(sz < 24)
   277  			return -1;
   278  		c->sym.symoff = e4(p+8);
   279  		c->sym.nsym = e4(p+12);
   280  		c->sym.stroff = e4(p+16);
   281  		c->sym.strsize = e4(p+20);
   282  		break;
   283  	case MachoCmdDysymtab:
   284  		if(sz < 80)
   285  			return -1;
   286  		c->dsym.ilocalsym = e4(p+8);
   287  		c->dsym.nlocalsym = e4(p+12);
   288  		c->dsym.iextdefsym = e4(p+16);
   289  		c->dsym.nextdefsym = e4(p+20);
   290  		c->dsym.iundefsym = e4(p+24);
   291  		c->dsym.nundefsym = e4(p+28);
   292  		c->dsym.tocoff = e4(p+32);
   293  		c->dsym.ntoc = e4(p+36);
   294  		c->dsym.modtaboff = e4(p+40);
   295  		c->dsym.nmodtab = e4(p+44);
   296  		c->dsym.extrefsymoff = e4(p+48);
   297  		c->dsym.nextrefsyms = e4(p+52);
   298  		c->dsym.indirectsymoff = e4(p+56);
   299  		c->dsym.nindirectsyms = e4(p+60);
   300  		c->dsym.extreloff = e4(p+64);
   301  		c->dsym.nextrel = e4(p+68);
   302  		c->dsym.locreloff = e4(p+72);
   303  		c->dsym.nlocrel = e4(p+76);
   304  		break;
   305  	}
   306  	return 0;
   307  }
   308  
   309  static int
   310  macholoadrel(MachoObj *m, MachoSect *sect)
   311  {
   312  	MachoRel *rel, *r;
   313  	uchar *buf, *p;
   314  	int i, n;
   315  	uint32 v;
   316  	
   317  	if(sect->rel != nil || sect->nreloc == 0)
   318  		return 0;
   319  	rel = mal(sect->nreloc * sizeof r[0]);
   320  	n = sect->nreloc * 8;
   321  	buf = mal(n);
   322  	if(Bseek(m->f, m->base + sect->reloff, 0) < 0 || Bread(m->f, buf, n) != n)
   323  		return -1;
   324  	for(i=0; i<sect->nreloc; i++) {
   325  		r = &rel[i];
   326  		p = buf+i*8;
   327  		r->addr = m->e->e32(p);
   328  		
   329  		// TODO(rsc): Wrong interpretation for big-endian bitfields?
   330  		if(r->addr & 0x80000000) {
   331  			// scatterbrained relocation
   332  			r->scattered = 1;
   333  			v = r->addr >> 24;
   334  			r->addr &= 0xFFFFFF;
   335  			r->type = v & 0xF;
   336  			v >>= 4;
   337  			r->length = 1<<(v&3);
   338  			v >>= 2;
   339  			r->pcrel = v & 1;
   340  			r->value = m->e->e32(p+4);
   341  		} else {
   342  			v = m->e->e32(p+4);
   343  			r->symnum = v & 0xFFFFFF;
   344  			v >>= 24;
   345  			r->pcrel = v&1;
   346  			v >>= 1;
   347  			r->length = 1<<(v&3);
   348  			v >>= 2;
   349  			r->extrn = v&1;
   350  			v >>= 1;
   351  			r->type = v;
   352  		}
   353  	}
   354  	sect->rel = rel;
   355  	return 0;
   356  }
   357  
   358  static int
   359  macholoaddsym(MachoObj *m, MachoDysymtab *d)
   360  {
   361  	uchar *p;
   362  	int i, n;
   363  	
   364  	n = d->nindirectsyms;
   365  	
   366  	p = mal(n*4);
   367  	if(Bseek(m->f, m->base + d->indirectsymoff, 0) < 0 || Bread(m->f, p, n*4) != n*4)
   368  		return -1;
   369  	
   370  	d->indir = (uint32*)p;
   371  	for(i=0; i<n; i++)
   372  		d->indir[i] = m->e->e32(p+4*i);
   373  	return 0;
   374  }
   375  
   376  static int 
   377  macholoadsym(MachoObj *m, MachoSymtab *symtab)
   378  {
   379  	char *strbuf;
   380  	uchar *symbuf, *p;
   381  	int i, n, symsize;
   382  	MachoSym *sym, *s;
   383  	uint32 v;
   384  
   385  	if(symtab->sym != nil)
   386  		return 0;
   387  
   388  	strbuf = mal(symtab->strsize);
   389  	if(Bseek(m->f, m->base + symtab->stroff, 0) < 0 || Bread(m->f, strbuf, symtab->strsize) != symtab->strsize)
   390  		return -1;
   391  	
   392  	symsize = 12;
   393  	if(m->is64)
   394  		symsize = 16;
   395  	n = symtab->nsym * symsize;
   396  	symbuf = mal(n);
   397  	if(Bseek(m->f, m->base + symtab->symoff, 0) < 0 || Bread(m->f, symbuf, n) != n)
   398  		return -1;
   399  	sym = mal(symtab->nsym * sizeof sym[0]);
   400  	p = symbuf;
   401  	for(i=0; i<symtab->nsym; i++) {
   402  		s = &sym[i];
   403  		v = m->e->e32(p);
   404  		if(v >= symtab->strsize)
   405  			return -1;
   406  		s->name = strbuf + v;
   407  		s->type = p[4];
   408  		s->sectnum = p[5];
   409  		s->desc = m->e->e16(p+6);
   410  		if(m->is64)
   411  			s->value = m->e->e64(p+8);
   412  		else
   413  			s->value = m->e->e32(p+8);
   414  		p += symsize;
   415  	}
   416  	symtab->str = strbuf;
   417  	symtab->sym = sym;
   418  	return 0;
   419  }
   420  
   421  void
   422  ldmacho(Biobuf *f, char *pkg, int64 len, char *pn)
   423  {
   424  	int i, j, is64;
   425  	uint64 secaddr;
   426  	uchar hdr[7*4], *cmdp;
   427  	uchar tmp[4];
   428  	uchar *dat;
   429  	ulong ncmd, cmdsz, ty, sz, off;
   430  	MachoObj *m;
   431  	Endian *e;
   432  	int64 base;
   433  	MachoSect *sect;
   434  	MachoRel *rel;
   435  	LSym *s, *s1, *outer;
   436  	MachoCmd *c;
   437  	MachoSymtab *symtab;
   438  	MachoDysymtab *dsymtab;
   439  	MachoSym *sym;
   440  	Reloc *r, *rp;
   441  	char *name;
   442  
   443  	ctxt->version++;
   444  	base = Boffset(f);
   445  	if(Bread(f, hdr, sizeof hdr) != sizeof hdr)
   446  		goto bad;
   447  
   448  	if((be.e32(hdr)&~1) == 0xFEEDFACE){
   449  		e = &be;
   450  	}else if((le.e32(hdr)&~1) == 0xFEEDFACE){
   451  		e = &le;
   452  	}else{
   453  		werrstr("bad magic - not mach-o file");
   454  		goto bad;
   455  	}
   456  
   457  	is64 = e->e32(hdr) == 0xFEEDFACF;
   458  	ncmd = e->e32(hdr+4*4);
   459  	cmdsz = e->e32(hdr+5*4);
   460  	if(ncmd > 0x10000 || cmdsz >= 0x01000000){
   461  		werrstr("implausible mach-o header ncmd=%lud cmdsz=%lud", ncmd, cmdsz);
   462  		goto bad;
   463  	}
   464  	if(is64)
   465  		Bread(f, tmp, 4);	// skip reserved word in header
   466  
   467  	m = mal(sizeof(*m)+ncmd*sizeof(MachoCmd)+cmdsz);
   468  	m->f = f;
   469  	m->e = e;
   470  	m->cputype = e->e32(hdr+1*4);
   471  	m->subcputype = e->e32(hdr+2*4);
   472  	m->filetype = e->e32(hdr+3*4);
   473  	m->ncmd = ncmd;
   474  	m->flags = e->e32(hdr+6*4);
   475  	m->is64 = is64;
   476  	m->base = base;
   477  	m->len = len;
   478  	m->name = pn;
   479  	
   480  	switch(thechar) {
   481  	default:
   482  		diag("%s: mach-o %s unimplemented", pn, thestring);
   483  		return;
   484  	case '6':
   485  		if(e != &le || m->cputype != MachoCpuAmd64) {
   486  			diag("%s: mach-o object but not amd64", pn);
   487  			return;
   488  		}
   489  		break;
   490  	case '8':
   491  		if(e != &le || m->cputype != MachoCpu386) {
   492  			diag("%s: mach-o object but not 386", pn);
   493  			return;
   494  		}
   495  		break;
   496  	}
   497  
   498  	m->cmd = (MachoCmd*)(m+1);
   499  	off = sizeof hdr;
   500  	cmdp = (uchar*)(m->cmd+ncmd);
   501  	if(Bread(f, cmdp, cmdsz) != cmdsz){
   502  		werrstr("reading cmds: %r");
   503  		goto bad;
   504  	}
   505  
   506  	// read and parse load commands
   507  	c = nil;
   508  	symtab = nil;
   509  	dsymtab = nil;
   510  	USED(dsymtab);
   511  	for(i=0; i<ncmd; i++){
   512  		ty = e->e32(cmdp);
   513  		sz = e->e32(cmdp+4);
   514  		m->cmd[i].off = off;
   515  		unpackcmd(cmdp, m, &m->cmd[i], ty, sz);
   516  		cmdp += sz;
   517  		off += sz;
   518  		if(ty == MachoCmdSymtab) {
   519  			if(symtab != nil) {
   520  				werrstr("multiple symbol tables");
   521  				goto bad;
   522  			}
   523  			symtab = &m->cmd[i].sym;
   524  			macholoadsym(m, symtab);
   525  		}
   526  		if(ty == MachoCmdDysymtab) {
   527  			dsymtab = &m->cmd[i].dsym;
   528  			macholoaddsym(m, dsymtab);
   529  		}
   530  		if((is64 && ty == MachoCmdSegment64) || (!is64 && ty == MachoCmdSegment)) {
   531  			if(c != nil) {
   532  				werrstr("multiple load commands");
   533  				goto bad;
   534  			}
   535  			c = &m->cmd[i];
   536  		}
   537  	}
   538  
   539  	// load text and data segments into memory.
   540  	// they are not as small as the load commands, but we'll need
   541  	// the memory anyway for the symbol images, so we might
   542  	// as well use one large chunk.
   543  	if(c == nil) {
   544  		werrstr("no load command");
   545  		goto bad;
   546  	}
   547  	if(symtab == nil) {
   548  		// our work is done here - no symbols means nothing can refer to this file
   549  		return;
   550  	}
   551  
   552  	if(c->seg.fileoff+c->seg.filesz >= len) {
   553  		werrstr("load segment out of range");
   554  		goto bad;
   555  	}
   556  
   557  	dat = mal(c->seg.filesz);
   558  	if(Bseek(f, m->base + c->seg.fileoff, 0) < 0 || Bread(f, dat, c->seg.filesz) != c->seg.filesz) {
   559  		werrstr("cannot load object data: %r");
   560  		goto bad;
   561  	}
   562  	
   563  	for(i=0; i<c->seg.nsect; i++) {
   564  		sect = &c->seg.sect[i];
   565  		if(strcmp(sect->segname, "__TEXT") != 0 && strcmp(sect->segname, "__DATA") != 0)
   566  			continue;
   567  		if(strcmp(sect->name, "__eh_frame") == 0)
   568  			continue;
   569  		name = smprint("%s(%s/%s)", pkg, sect->segname, sect->name);
   570  		s = linklookup(ctxt, name, ctxt->version);
   571  		if(s->type != 0) {
   572  			werrstr("duplicate %s/%s", sect->segname, sect->name);
   573  			goto bad;
   574  		}
   575  		free(name);
   576  
   577  		s->np = sect->size;
   578  		s->size = s->np;
   579  		if((sect->flags & 0xff) == 1) // S_ZEROFILL
   580  			s->p = mal(s->size);
   581  		else {
   582  			s->p = dat + sect->addr - c->seg.vmaddr;
   583  		}
   584  		
   585  		if(strcmp(sect->segname, "__TEXT") == 0) {
   586  			if(strcmp(sect->name, "__text") == 0)
   587  				s->type = STEXT;
   588  			else
   589  				s->type = SRODATA;
   590  		} else {
   591  			if (strcmp(sect->name, "__bss") == 0) {
   592  				s->type = SNOPTRBSS;
   593  				s->np = 0;
   594  			} else
   595  				s->type = SNOPTRDATA;
   596  		}
   597  		sect->sym = s;
   598  	}
   599  	
   600  	// enter sub-symbols into symbol table.
   601  	// have to guess sizes from next symbol.
   602  	for(i=0; i<symtab->nsym; i++) {
   603  		int v;
   604  		sym = &symtab->sym[i];
   605  		if(sym->type&N_STAB)
   606  			continue;
   607  		// TODO: check sym->type against outer->type.
   608  		name = sym->name;
   609  		if(name[0] == '_' && name[1] != '\0')
   610  			name++;
   611  		v = 0;
   612  		if(!(sym->type&N_EXT))
   613  			v = ctxt->version;
   614  		s = linklookup(ctxt, name, v);
   615  		if(!(sym->type&N_EXT))
   616  			s->dupok = 1;
   617  		sym->sym = s;
   618  		if(sym->sectnum == 0)	// undefined
   619  			continue;
   620  		if(sym->sectnum > c->seg.nsect) {
   621  			werrstr("reference to invalid section %d", sym->sectnum);
   622  			goto bad;
   623  		}
   624  		sect = &c->seg.sect[sym->sectnum-1];
   625  		outer = sect->sym;
   626  		if(outer == nil) {
   627  			werrstr("reference to invalid section %s/%s", sect->segname, sect->name);
   628  			continue;
   629  		}
   630  		if(s->outer != S) {
   631  			if(s->dupok)
   632  				continue;
   633  			diag("%s: duplicate symbol reference: %s in both %s and %s", pn, s->name, s->outer->name, sect->sym->name);
   634  			errorexit();
   635  		}
   636  		s->type = outer->type | SSUB;
   637  		s->sub = outer->sub;
   638  		outer->sub = s;
   639  		s->outer = outer;
   640  		s->value = sym->value - sect->addr;
   641  		if(!(s->cgoexport & CgoExportDynamic))
   642  			s->dynimplib = nil;	// satisfy dynimport
   643  		if(outer->type == STEXT) {
   644  			if(s->external && !s->dupok)
   645  				diag("%s: duplicate definition of %s", pn, s->name);
   646  			s->external = 1;
   647  		}
   648  		sym->sym = s;
   649  	}
   650  
   651  	// Sort outer lists by address, adding to textp.
   652  	// This keeps textp in increasing address order.
   653  	for(i=0; i<c->seg.nsect; i++) {
   654  		sect = &c->seg.sect[i];
   655  		if((s = sect->sym) == S)
   656  			continue;
   657  		if(s->sub) {
   658  			s->sub = listsort(s->sub, valuecmp, offsetof(LSym, sub));
   659  			
   660  			// assign sizes, now that we know symbols in sorted order.
   661  			for(s1 = s->sub; s1 != S; s1 = s1->sub) {
   662  				if(s1->sub)
   663  					s1->size = s1->sub->value - s1->value;
   664  				else
   665  					s1->size = s->value + s->size - s1->value;
   666  			}
   667  		}
   668  		if(s->type == STEXT) {
   669  			if(s->onlist)
   670  				sysfatal("symbol %s listed multiple times", s->name);
   671  			s->onlist = 1;
   672  			if(ctxt->etextp)
   673  				ctxt->etextp->next = s;
   674  			else
   675  				ctxt->textp = s;
   676  			ctxt->etextp = s;
   677  			for(s1 = s->sub; s1 != S; s1 = s1->sub) {
   678  				if(s1->onlist)
   679  					sysfatal("symbol %s listed multiple times", s1->name);
   680  				s1->onlist = 1;
   681  				ctxt->etextp->next = s1;
   682  				ctxt->etextp = s1;
   683  			}
   684  		}
   685  	}
   686  
   687  	// load relocations
   688  	for(i=0; i<c->seg.nsect; i++) {
   689  		sect = &c->seg.sect[i];
   690  		if((s = sect->sym) == S)
   691  			continue;
   692  		macholoadrel(m, sect);
   693  		if(sect->rel == nil)
   694  			continue;
   695  		r = mal(sect->nreloc*sizeof r[0]);
   696  		rp = r;
   697  		rel = sect->rel;
   698  		for(j=0; j<sect->nreloc; j++, rel++) {
   699  			if(rel->scattered) {
   700  				int k;
   701  				MachoSect *ks;
   702  
   703  				if(thechar != '8') {
   704  					// mach-o only uses scattered relocation on 32-bit platforms
   705  					diag("unexpected scattered relocation");
   706  					continue;
   707  				}
   708  
   709  				// on 386, rewrite scattered 4/1 relocation and some
   710  				// scattered 2/1 relocation into the pseudo-pc-relative
   711  				// reference that it is.
   712  				// assume that the second in the pair is in this section
   713  				// and use that as the pc-relative base.
   714  				if(j+1 >= sect->nreloc) {
   715  					werrstr("unsupported scattered relocation %d", (int)rel->type);
   716  					goto bad;
   717  				}
   718  				if(!(rel+1)->scattered || (rel+1)->type != 1 ||
   719  				   (rel->type != 4 && rel->type != 2) ||
   720  				   (rel+1)->value < sect->addr || (rel+1)->value >= sect->addr+sect->size) {
   721  					werrstr("unsupported scattered relocation %d/%d", (int)rel->type, (int)(rel+1)->type);
   722  					goto bad;
   723  				}
   724  
   725  				rp->siz = rel->length;
   726  				rp->off = rel->addr;
   727  				
   728  				// NOTE(rsc): I haven't worked out why (really when)
   729  				// we should ignore the addend on a
   730  				// scattered relocation, but it seems that the
   731  				// common case is we ignore it.
   732  				// It's likely that this is not strictly correct
   733  				// and that the math should look something
   734  				// like the non-scattered case below.
   735  				rp->add = 0;
   736  				
   737  				// want to make it pc-relative aka relative to rp->off+4
   738  				// but the scatter asks for relative to off = (rel+1)->value - sect->addr.
   739  				// adjust rp->add accordingly.
   740  				rp->type = R_PCREL;
   741  				rp->add += (rp->off+4) - ((rel+1)->value - sect->addr);
   742  				
   743  				// now consider the desired symbol.
   744  				// find the section where it lives.
   745  				for(k=0; k<c->seg.nsect; k++) {
   746  					ks = &c->seg.sect[k];
   747  					if(ks->addr <= rel->value && rel->value < ks->addr+ks->size)
   748  						goto foundk;
   749  				}
   750  				werrstr("unsupported scattered relocation: invalid address %#ux", rel->addr);
   751  				goto bad;
   752  			foundk:
   753  				if(ks->sym != S) {
   754  					rp->sym = ks->sym;
   755  					rp->add += rel->value - ks->addr;
   756  				} else if(strcmp(ks->segname, "__IMPORT") == 0 && strcmp(ks->name, "__pointers") == 0) {
   757  					// handle reference to __IMPORT/__pointers.
   758  					// how much worse can this get?
   759  					// why are we supporting 386 on the mac anyway?
   760  					rp->type = 512 + MACHO_FAKE_GOTPCREL;
   761  					// figure out which pointer this is a reference to.
   762  					k = ks->res1 + (rel->value - ks->addr) / 4;
   763  					// load indirect table for __pointers
   764  					// fetch symbol number
   765  					if(dsymtab == nil || k < 0 || k >= dsymtab->nindirectsyms || dsymtab->indir == nil) {
   766  						werrstr("invalid scattered relocation: indirect symbol reference out of range");
   767  						goto bad;
   768  					}
   769  					k = dsymtab->indir[k];
   770  					if(k < 0 || k >= symtab->nsym) {
   771  						werrstr("invalid scattered relocation: symbol reference out of range");
   772  						goto bad;
   773  					}
   774  					rp->sym = symtab->sym[k].sym;
   775  				} else {
   776  					werrstr("unsupported scattered relocation: reference to %s/%s", ks->segname, ks->name);
   777  					goto bad;
   778  				}
   779  				rp++;
   780  				// skip #1 of 2 rel; continue skips #2 of 2.
   781  				rel++;
   782  				j++;
   783  				continue;
   784  			}
   785  
   786  			rp->siz = rel->length;
   787  			rp->type = 512 + (rel->type<<1) + rel->pcrel;
   788  			rp->off = rel->addr;
   789  
   790  			// Handle X86_64_RELOC_SIGNED referencing a section (rel->extrn == 0).
   791  			if (thechar == '6' && rel->extrn == 0 && rel->type == 1) {
   792  				// Calculate the addend as the offset into the section.
   793  				//
   794  				// The rip-relative offset stored in the object file is encoded
   795  				// as follows:
   796  				//    
   797  				//    movsd	0x00000360(%rip),%xmm0
   798  				//
   799  				// To get the absolute address of the value this rip-relative address is pointing
   800  				// to, we must add the address of the next instruction to it. This is done by
   801  				// taking the address of the relocation and adding 4 to it (since the rip-relative
   802  				// offset can at most be 32 bits long).  To calculate the offset into the section the
   803  				// relocation is referencing, we subtract the vaddr of the start of the referenced
   804  				// section found in the original object file.
   805  				//
   806  				// [For future reference, see Darwin's /usr/include/mach-o/x86_64/reloc.h]
   807  				secaddr = c->seg.sect[rel->symnum-1].addr;
   808  				rp->add = (int32)e->e32(s->p+rp->off) + rp->off + 4 - secaddr;
   809  			} else
   810  				rp->add = (int32)e->e32(s->p+rp->off);
   811  
   812  			// For i386 Mach-O PC-relative, the addend is written such that
   813  			// it *is* the PC being subtracted.  Use that to make
   814  			// it match our version of PC-relative.
   815  			if(rel->pcrel && thechar == '8')
   816  				rp->add += rp->off+rp->siz;
   817  			if(!rel->extrn) {
   818  				if(rel->symnum < 1 || rel->symnum > c->seg.nsect) {
   819  					werrstr("invalid relocation: section reference out of range %d vs %d", rel->symnum, c->seg.nsect);
   820  					goto bad;
   821  				}
   822  				rp->sym = c->seg.sect[rel->symnum-1].sym;
   823  				if(rp->sym == nil) {
   824  					werrstr("invalid relocation: %s", c->seg.sect[rel->symnum-1].name);
   825  					goto bad;
   826  				}
   827  				// References to symbols in other sections
   828  				// include that information in the addend.
   829  				// We only care about the delta from the 
   830  				// section base.
   831  				if(thechar == '8')
   832  					rp->add -= c->seg.sect[rel->symnum-1].addr;
   833  			} else {
   834  				if(rel->symnum >= symtab->nsym) {
   835  					werrstr("invalid relocation: symbol reference out of range");
   836  					goto bad;
   837  				}
   838  				rp->sym = symtab->sym[rel->symnum].sym;
   839  			}
   840  			rp++;
   841  		}			
   842  		qsort(r, rp - r, sizeof r[0], rbyoff);
   843  		s->r = r;
   844  		s->nr = rp - r;
   845  	}
   846  	return;
   847  
   848  bad:
   849  	diag("%s: malformed mach-o file: %r", pn);
   850  }