github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/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  	Sym *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  	Sym *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  	Sym *s, *outer;
   436  	MachoCmd *c;
   437  	MachoSymtab *symtab;
   438  	MachoDysymtab *dsymtab;
   439  	MachoSym *sym;
   440  	Reloc *r, *rp;
   441  	char *name;
   442  
   443  	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  	for(i=0; i<ncmd; i++){
   511  		ty = e->e32(cmdp);
   512  		sz = e->e32(cmdp+4);
   513  		m->cmd[i].off = off;
   514  		unpackcmd(cmdp, m, &m->cmd[i], ty, sz);
   515  		cmdp += sz;
   516  		off += sz;
   517  		if(ty == MachoCmdSymtab) {
   518  			if(symtab != nil) {
   519  				werrstr("multiple symbol tables");
   520  				goto bad;
   521  			}
   522  			symtab = &m->cmd[i].sym;
   523  			macholoadsym(m, symtab);
   524  		}
   525  		if(ty == MachoCmdDysymtab) {
   526  			dsymtab = &m->cmd[i].dsym;
   527  			macholoaddsym(m, dsymtab);
   528  		}
   529  		if((is64 && ty == MachoCmdSegment64) || (!is64 && ty == MachoCmdSegment)) {
   530  			if(c != nil) {
   531  				werrstr("multiple load commands");
   532  				goto bad;
   533  			}
   534  			c = &m->cmd[i];
   535  		}
   536  	}
   537  
   538  	// load text and data segments into memory.
   539  	// they are not as small as the load commands, but we'll need
   540  	// the memory anyway for the symbol images, so we might
   541  	// as well use one large chunk.
   542  	if(c == nil) {
   543  		werrstr("no load command");
   544  		goto bad;
   545  	}
   546  	if(symtab == nil) {
   547  		// our work is done here - no symbols means nothing can refer to this file
   548  		return;
   549  	}
   550  
   551  	if(c->seg.fileoff+c->seg.filesz >= len) {
   552  		werrstr("load segment out of range");
   553  		goto bad;
   554  	}
   555  
   556  	dat = mal(c->seg.filesz);
   557  	if(Bseek(f, m->base + c->seg.fileoff, 0) < 0 || Bread(f, dat, c->seg.filesz) != c->seg.filesz) {
   558  		werrstr("cannot load object data: %r");
   559  		goto bad;
   560  	}
   561  	
   562  	for(i=0; i<c->seg.nsect; i++) {
   563  		sect = &c->seg.sect[i];
   564  		if(strcmp(sect->segname, "__TEXT") != 0 && strcmp(sect->segname, "__DATA") != 0)
   565  			continue;
   566  		if(strcmp(sect->name, "__eh_frame") == 0)
   567  			continue;
   568  		name = smprint("%s(%s/%s)", pkg, sect->segname, sect->name);
   569  		s = lookup(name, version);
   570  		if(s->type != 0) {
   571  			werrstr("duplicate %s/%s", sect->segname, sect->name);
   572  			goto bad;
   573  		}
   574  		free(name);
   575  
   576  		s->np = sect->size;
   577  		s->size = s->np;
   578  		if((sect->flags & 0xff) == 1) // S_ZEROFILL
   579  			s->p = mal(s->size);
   580  		else {
   581  			s->p = dat + sect->addr - c->seg.vmaddr;
   582  		}
   583  		
   584  		if(strcmp(sect->segname, "__TEXT") == 0) {
   585  			if(strcmp(sect->name, "__text") == 0)
   586  				s->type = STEXT;
   587  			else
   588  				s->type = SRODATA;
   589  		} else {
   590  			if (strcmp(sect->name, "__bss") == 0) {
   591  				s->type = SBSS;
   592  				s->np = 0;
   593  			} else
   594  				s->type = SDATA;
   595  		}
   596  		sect->sym = s;
   597  	}
   598  	
   599  	// enter sub-symbols into symbol table.
   600  	// have to guess sizes from next symbol.
   601  	for(i=0; i<symtab->nsym; i++) {
   602  		int v;
   603  		sym = &symtab->sym[i];
   604  		if(sym->type&N_STAB)
   605  			continue;
   606  		// TODO: check sym->type against outer->type.
   607  		name = sym->name;
   608  		if(name[0] == '_' && name[1] != '\0')
   609  			name++;
   610  		v = 0;
   611  		if(!(sym->type&N_EXT))
   612  			v = version;
   613  		s = lookup(name, v);
   614  		sym->sym = s;
   615  		if(sym->sectnum == 0)	// undefined
   616  			continue;
   617  		if(sym->sectnum > c->seg.nsect) {
   618  			werrstr("reference to invalid section %d", sym->sectnum);
   619  			goto bad;
   620  		}
   621  		sect = &c->seg.sect[sym->sectnum-1];
   622  		outer = sect->sym;
   623  		if(outer == nil) {
   624  			werrstr("reference to invalid section %s/%s", sect->segname, sect->name);
   625  			continue;
   626  		}
   627  		if(s->outer != S) {
   628  			if(s->dupok)
   629  				continue;
   630  			diag("%s: duplicate symbol reference: %s in both %s and %s", pn, s->name, s->outer->name, sect->sym->name);
   631  			errorexit();
   632  		}
   633  		s->type = outer->type | SSUB;
   634  		s->sub = outer->sub;
   635  		outer->sub = s;
   636  		s->outer = outer;
   637  		s->value = sym->value - sect->addr;
   638  		if(i+1 < symtab->nsym)
   639  			s->size = (sym+1)->value - sym->value;
   640  		else
   641  			s->size = sect->addr + sect->size - sym->value;
   642  		if(!(s->cgoexport & CgoExportDynamic))
   643  			s->dynimplib = nil;	// satisfy dynimport
   644  		if(outer->type == STEXT) {
   645  			Prog *p;
   646  
   647  			if(s->text != P)
   648  				diag("%s sym#%d: duplicate definition of %s", pn, i, s->name);
   649  			// build a TEXT instruction with a unique pc
   650  			// just to make the rest of the linker happy.
   651  			// TODO: this is too 6l-specific ?
   652  			p = prg();
   653  			p->as = ATEXT;
   654  			p->from.type = D_EXTERN;
   655  			p->from.sym = s;
   656  			p->textflag = 7;
   657  			p->to.type = D_CONST;
   658  			p->link = nil;
   659  			p->pc = pc++;
   660  			s->text = p;
   661  		}
   662  		sym->sym = s;
   663  	}
   664  
   665  	// Sort outer lists by address, adding to textp.
   666  	// This keeps textp in increasing address order.
   667  	for(i=0; i<c->seg.nsect; i++) {
   668  		sect = &c->seg.sect[i];
   669  		if((s = sect->sym) == S)
   670  			continue;
   671  		if(s->sub)
   672  			s->sub = listsort(s->sub, valuecmp, offsetof(Sym, sub));
   673  		if(s->type == STEXT) {
   674  			if(etextp)
   675  				etextp->next = s;
   676  			else
   677  				textp = s;
   678  			etextp = s;
   679  			for(s = s->sub; s != S; s = s->sub) {
   680  				etextp->next = s;
   681  				etextp = s;
   682  			}
   683  		}
   684  	}
   685  
   686  	// load relocations
   687  	for(i=0; i<c->seg.nsect; i++) {
   688  		sect = &c->seg.sect[i];
   689  		if((s = sect->sym) == S)
   690  			continue;
   691  		macholoadrel(m, sect);
   692  		if(sect->rel == nil)
   693  			continue;
   694  		r = mal(sect->nreloc*sizeof r[0]);
   695  		rp = r;
   696  		rel = sect->rel;
   697  		for(j=0; j<sect->nreloc; j++, rel++) {
   698  			if(rel->scattered) {
   699  				int k;
   700  				MachoSect *ks;
   701  
   702  				if(thechar != '8') {
   703  					// mach-o only uses scattered relocation on 32-bit platforms
   704  					diag("unexpected scattered relocation");
   705  					continue;
   706  				}
   707  
   708  				// on 386, rewrite scattered 4/1 relocation and some
   709  				// scattered 2/1 relocation into the pseudo-pc-relative
   710  				// reference that it is.
   711  				// assume that the second in the pair is in this section
   712  				// and use that as the pc-relative base.
   713  				if(j+1 >= sect->nreloc) {
   714  					werrstr("unsupported scattered relocation %d", (int)rel->type);
   715  					goto bad;
   716  				}
   717  				if(!(rel+1)->scattered || (rel+1)->type != 1 ||
   718  				   (rel->type != 4 && rel->type != 2) ||
   719  				   (rel+1)->value < sect->addr || (rel+1)->value >= sect->addr+sect->size) {
   720  					werrstr("unsupported scattered relocation %d/%d", (int)rel->type, (int)(rel+1)->type);
   721  					goto bad;
   722  				}
   723  
   724  				rp->siz = rel->length;
   725  				rp->off = rel->addr;
   726  				
   727  				// NOTE(rsc): I haven't worked out why (really when)
   728  				// we should ignore the addend on a
   729  				// scattered relocation, but it seems that the
   730  				// common case is we ignore it.
   731  				// It's likely that this is not strictly correct
   732  				// and that the math should look something
   733  				// like the non-scattered case below.
   734  				rp->add = 0;
   735  				
   736  				// want to make it pc-relative aka relative to rp->off+4
   737  				// but the scatter asks for relative to off = (rel+1)->value - sect->addr.
   738  				// adjust rp->add accordingly.
   739  				rp->type = D_PCREL;
   740  				rp->add += (rp->off+4) - ((rel+1)->value - sect->addr);
   741  				
   742  				// now consider the desired symbol.
   743  				// find the section where it lives.
   744  				for(k=0; k<c->seg.nsect; k++) {
   745  					ks = &c->seg.sect[k];
   746  					if(ks->addr <= rel->value && rel->value < ks->addr+ks->size)
   747  						goto foundk;
   748  				}
   749  				werrstr("unsupported scattered relocation: invalid address %#ux", rel->addr);
   750  				goto bad;
   751  			foundk:
   752  				if(ks->sym != S) {
   753  					rp->sym = ks->sym;
   754  					rp->add += rel->value - ks->addr;
   755  				} else if(strcmp(ks->segname, "__IMPORT") == 0 && strcmp(ks->name, "__pointers") == 0) {
   756  					// handle reference to __IMPORT/__pointers.
   757  					// how much worse can this get?
   758  					// why are we supporting 386 on the mac anyway?
   759  					rp->type = 512 + MACHO_FAKE_GOTPCREL;
   760  					// figure out which pointer this is a reference to.
   761  					k = ks->res1 + (rel->value - ks->addr) / 4;
   762  					// load indirect table for __pointers
   763  					// fetch symbol number
   764  					if(dsymtab == nil || k < 0 || k >= dsymtab->nindirectsyms || dsymtab->indir == nil) {
   765  						werrstr("invalid scattered relocation: indirect symbol reference out of range");
   766  						goto bad;
   767  					}
   768  					k = dsymtab->indir[k];
   769  					if(k < 0 || k >= symtab->nsym) {
   770  						werrstr("invalid scattered relocation: symbol reference out of range");
   771  						goto bad;
   772  					}
   773  					rp->sym = symtab->sym[k].sym;
   774  				} else {
   775  					werrstr("unsupported scattered relocation: reference to %s/%s", ks->segname, ks->name);
   776  					goto bad;
   777  				}
   778  				rp++;
   779  				// skip #1 of 2 rel; continue skips #2 of 2.
   780  				rel++;
   781  				j++;
   782  				continue;
   783  			}
   784  
   785  			rp->siz = rel->length;
   786  			rp->type = 512 + (rel->type<<1) + rel->pcrel;
   787  			rp->off = rel->addr;
   788  
   789  			// Handle X86_64_RELOC_SIGNED referencing a section (rel->extrn == 0).
   790  			if (thechar == '6' && rel->extrn == 0 && rel->type == 1) {
   791  				// Calculate the addend as the offset into the section.
   792  				//
   793  				// The rip-relative offset stored in the object file is encoded
   794  				// as follows:
   795  				//    
   796  				//    movsd	0x00000360(%rip),%xmm0
   797  				//
   798  				// To get the absolute address of the value this rip-relative address is pointing
   799  				// to, we must add the address of the next instruction to it. This is done by
   800  				// taking the address of the relocation and adding 4 to it (since the rip-relative
   801  				// offset can at most be 32 bits long).  To calculate the offset into the section the
   802  				// relocation is referencing, we subtract the vaddr of the start of the referenced
   803  				// section found in the original object file.
   804  				//
   805  				// [For future reference, see Darwin's /usr/include/mach-o/x86_64/reloc.h]
   806  				secaddr = c->seg.sect[rel->symnum-1].addr;
   807  				rp->add = (int32)e->e32(s->p+rp->off) + rp->off + 4 - secaddr;
   808  			} else
   809  				rp->add = (int32)e->e32(s->p+rp->off);
   810  
   811  			// For i386 Mach-O PC-relative, the addend is written such that
   812  			// it *is* the PC being subtracted.  Use that to make
   813  			// it match our version of PC-relative.
   814  			if(rel->pcrel && thechar == '8')
   815  				rp->add += rp->off+rp->siz;
   816  			if(!rel->extrn) {
   817  				if(rel->symnum < 1 || rel->symnum > c->seg.nsect) {
   818  					werrstr("invalid relocation: section reference out of range %d vs %d", rel->symnum, c->seg.nsect);
   819  					goto bad;
   820  				}
   821  				rp->sym = c->seg.sect[rel->symnum-1].sym;
   822  				if(rp->sym == nil) {
   823  					werrstr("invalid relocation: %s", c->seg.sect[rel->symnum-1].name);
   824  					goto bad;
   825  				}
   826  				// References to symbols in other sections
   827  				// include that information in the addend.
   828  				// We only care about the delta from the 
   829  				// section base.
   830  				if(thechar == '8')
   831  					rp->add -= c->seg.sect[rel->symnum-1].addr;
   832  			} else {
   833  				if(rel->symnum >= symtab->nsym) {
   834  					werrstr("invalid relocation: symbol reference out of range");
   835  					goto bad;
   836  				}
   837  				rp->sym = symtab->sym[rel->symnum].sym;
   838  			}
   839  			rp++;
   840  		}			
   841  		qsort(r, rp - r, sizeof r[0], rbyoff);
   842  		s->r = r;
   843  		s->nr = rp - r;
   844  	}
   845  	return;
   846  
   847  bad:
   848  	diag("%s: malformed mach-o file: %r", pn);
   849  }