Home | History | Annotate | Download | only in ld
      1 package ld
      2 
      3 import (
      4 	"bytes"
      5 	"cmd/internal/obj"
      6 	"encoding/binary"
      7 	"fmt"
      8 	"log"
      9 	"sort"
     10 	"strings"
     11 )
     12 
     13 /*
     14 Derived from Plan 9 from User Space's src/libmach/elf.h, elf.c
     15 http://code.swtch.com/plan9port/src/tip/src/libmach/
     16 
     17 	Copyright  2004 Russ Cox.
     18 	Portions Copyright  2008-2010 Google Inc.
     19 	Portions Copyright  2010 The Go Authors.
     20 
     21 Permission is hereby granted, free of charge, to any person obtaining a copy
     22 of this software and associated documentation files (the "Software"), to deal
     23 in the Software without restriction, including without limitation the rights
     24 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     25 copies of the Software, and to permit persons to whom the Software is
     26 furnished to do so, subject to the following conditions:
     27 
     28 The above copyright notice and this permission notice shall be included in
     29 all copies or substantial portions of the Software.
     30 
     31 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     32 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     33 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     34 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     35 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     36 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     37 THE SOFTWARE.
     38 */
     39 const (
     40 	ElfClassNone = 0
     41 	ElfClass32   = 1
     42 	ElfClass64   = 2
     43 )
     44 
     45 const (
     46 	ElfDataNone = 0
     47 	ElfDataLsb  = 1
     48 	ElfDataMsb  = 2
     49 )
     50 
     51 const (
     52 	ElfTypeNone         = 0
     53 	ElfTypeRelocatable  = 1
     54 	ElfTypeExecutable   = 2
     55 	ElfTypeSharedObject = 3
     56 	ElfTypeCore         = 4
     57 )
     58 
     59 const (
     60 	ElfMachNone        = 0
     61 	ElfMach32100       = 1
     62 	ElfMachSparc       = 2
     63 	ElfMach386         = 3
     64 	ElfMach68000       = 4
     65 	ElfMach88000       = 5
     66 	ElfMach486         = 6
     67 	ElfMach860         = 7
     68 	ElfMachMips        = 8
     69 	ElfMachS370        = 9
     70 	ElfMachMipsLe      = 10
     71 	ElfMachParisc      = 15
     72 	ElfMachVpp500      = 17
     73 	ElfMachSparc32Plus = 18
     74 	ElfMach960         = 19
     75 	ElfMachPower       = 20
     76 	ElfMachPower64     = 21
     77 	ElfMachS390        = 22
     78 	ElfMachV800        = 36
     79 	ElfMachFr20        = 37
     80 	ElfMachRh32        = 38
     81 	ElfMachRce         = 39
     82 	ElfMachArm         = 40
     83 	ElfMachAlpha       = 41
     84 	ElfMachSH          = 42
     85 	ElfMachSparc9      = 43
     86 	ElfMachAmd64       = 62
     87 	ElfMachArm64       = 183
     88 )
     89 
     90 const (
     91 	ElfAbiNone     = 0
     92 	ElfAbiSystemV  = 0
     93 	ElfAbiHPUX     = 1
     94 	ElfAbiNetBSD   = 2
     95 	ElfAbiLinux    = 3
     96 	ElfAbiSolaris  = 6
     97 	ElfAbiAix      = 7
     98 	ElfAbiIrix     = 8
     99 	ElfAbiFreeBSD  = 9
    100 	ElfAbiTru64    = 10
    101 	ElfAbiModesto  = 11
    102 	ElfAbiOpenBSD  = 12
    103 	ElfAbiARM      = 97
    104 	ElfAbiEmbedded = 255
    105 )
    106 
    107 const (
    108 	ElfSectNone      = 0
    109 	ElfSectProgbits  = 1
    110 	ElfSectSymtab    = 2
    111 	ElfSectStrtab    = 3
    112 	ElfSectRela      = 4
    113 	ElfSectHash      = 5
    114 	ElfSectDynamic   = 6
    115 	ElfSectNote      = 7
    116 	ElfSectNobits    = 8
    117 	ElfSectRel       = 9
    118 	ElfSectShlib     = 10
    119 	ElfSectDynsym    = 11
    120 	ElfSectFlagWrite = 0x1
    121 	ElfSectFlagAlloc = 0x2
    122 	ElfSectFlagExec  = 0x4
    123 )
    124 
    125 const (
    126 	ElfSymBindLocal  = 0
    127 	ElfSymBindGlobal = 1
    128 	ElfSymBindWeak   = 2
    129 )
    130 
    131 const (
    132 	ElfSymTypeNone    = 0
    133 	ElfSymTypeObject  = 1
    134 	ElfSymTypeFunc    = 2
    135 	ElfSymTypeSection = 3
    136 	ElfSymTypeFile    = 4
    137 )
    138 
    139 const (
    140 	ElfSymShnNone   = 0
    141 	ElfSymShnAbs    = 0xFFF1
    142 	ElfSymShnCommon = 0xFFF2
    143 )
    144 
    145 const (
    146 	ElfProgNone      = 0
    147 	ElfProgLoad      = 1
    148 	ElfProgDynamic   = 2
    149 	ElfProgInterp    = 3
    150 	ElfProgNote      = 4
    151 	ElfProgShlib     = 5
    152 	ElfProgPhdr      = 6
    153 	ElfProgFlagExec  = 0x1
    154 	ElfProgFlagWrite = 0x2
    155 	ElfProgFlagRead  = 0x4
    156 )
    157 
    158 const (
    159 	ElfNotePrStatus     = 1
    160 	ElfNotePrFpreg      = 2
    161 	ElfNotePrPsinfo     = 3
    162 	ElfNotePrTaskstruct = 4
    163 	ElfNotePrAuxv       = 6
    164 	ElfNotePrXfpreg     = 0x46e62b7f
    165 )
    166 
    167 type ElfHdrBytes struct {
    168 	Ident     [16]uint8
    169 	Type      [2]uint8
    170 	Machine   [2]uint8
    171 	Version   [4]uint8
    172 	Entry     [4]uint8
    173 	Phoff     [4]uint8
    174 	Shoff     [4]uint8
    175 	Flags     [4]uint8
    176 	Ehsize    [2]uint8
    177 	Phentsize [2]uint8
    178 	Phnum     [2]uint8
    179 	Shentsize [2]uint8
    180 	Shnum     [2]uint8
    181 	Shstrndx  [2]uint8
    182 }
    183 
    184 type ElfSectBytes struct {
    185 	Name    [4]uint8
    186 	Type    [4]uint8
    187 	Flags   [4]uint8
    188 	Addr    [4]uint8
    189 	Off     [4]uint8
    190 	Size    [4]uint8
    191 	Link    [4]uint8
    192 	Info    [4]uint8
    193 	Align   [4]uint8
    194 	Entsize [4]uint8
    195 }
    196 
    197 type ElfProgBytes struct {
    198 }
    199 
    200 type ElfSymBytes struct {
    201 	Name  [4]uint8
    202 	Value [4]uint8
    203 	Size  [4]uint8
    204 	Info  uint8
    205 	Other uint8
    206 	Shndx [2]uint8
    207 }
    208 
    209 type ElfHdrBytes64 struct {
    210 	Ident     [16]uint8
    211 	Type      [2]uint8
    212 	Machine   [2]uint8
    213 	Version   [4]uint8
    214 	Entry     [8]uint8
    215 	Phoff     [8]uint8
    216 	Shoff     [8]uint8
    217 	Flags     [4]uint8
    218 	Ehsize    [2]uint8
    219 	Phentsize [2]uint8
    220 	Phnum     [2]uint8
    221 	Shentsize [2]uint8
    222 	Shnum     [2]uint8
    223 	Shstrndx  [2]uint8
    224 }
    225 
    226 type ElfSectBytes64 struct {
    227 	Name    [4]uint8
    228 	Type    [4]uint8
    229 	Flags   [8]uint8
    230 	Addr    [8]uint8
    231 	Off     [8]uint8
    232 	Size    [8]uint8
    233 	Link    [4]uint8
    234 	Info    [4]uint8
    235 	Align   [8]uint8
    236 	Entsize [8]uint8
    237 }
    238 
    239 type ElfProgBytes64 struct {
    240 }
    241 
    242 type ElfSymBytes64 struct {
    243 	Name  [4]uint8
    244 	Info  uint8
    245 	Other uint8
    246 	Shndx [2]uint8
    247 	Value [8]uint8
    248 	Size  [8]uint8
    249 }
    250 
    251 type ElfSect struct {
    252 	name    string
    253 	nameoff uint32
    254 	type_   uint32
    255 	flags   uint64
    256 	addr    uint64
    257 	off     uint64
    258 	size    uint64
    259 	link    uint32
    260 	info    uint32
    261 	align   uint64
    262 	entsize uint64
    263 	base    []byte
    264 	sym     *LSym
    265 }
    266 
    267 type ElfObj struct {
    268 	f         *obj.Biobuf
    269 	base      int64 // offset in f where ELF begins
    270 	length    int64 // length of ELF
    271 	is64      int
    272 	name      string
    273 	e         binary.ByteOrder
    274 	sect      []ElfSect
    275 	nsect     uint
    276 	shstrtab  string
    277 	nsymtab   int
    278 	symtab    *ElfSect
    279 	symstr    *ElfSect
    280 	type_     uint32
    281 	machine   uint32
    282 	version   uint32
    283 	entry     uint64
    284 	phoff     uint64
    285 	shoff     uint64
    286 	flags     uint32
    287 	ehsize    uint32
    288 	phentsize uint32
    289 	phnum     uint32
    290 	shentsize uint32
    291 	shnum     uint32
    292 	shstrndx  uint32
    293 }
    294 
    295 type ElfSym struct {
    296 	name  string
    297 	value uint64
    298 	size  uint64
    299 	bind  uint8
    300 	type_ uint8
    301 	other uint8
    302 	shndx uint16
    303 	sym   *LSym
    304 }
    305 
    306 var ElfMagic = [4]uint8{0x7F, 'E', 'L', 'F'}
    307 
    308 func valuecmp(a *LSym, b *LSym) int {
    309 	if a.Value < b.Value {
    310 		return -1
    311 	}
    312 	if a.Value > b.Value {
    313 		return +1
    314 	}
    315 	return 0
    316 }
    317 
    318 func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) {
    319 	if Debug['v'] != 0 {
    320 		fmt.Fprintf(&Bso, "%5.2f ldelf %s\n", obj.Cputime(), pn)
    321 	}
    322 
    323 	Ctxt.Version++
    324 	base := int32(obj.Boffset(f))
    325 
    326 	var add uint64
    327 	var e binary.ByteOrder
    328 	var elfobj *ElfObj
    329 	var err error
    330 	var flag int
    331 	var hdr *ElfHdrBytes
    332 	var hdrbuf [64]uint8
    333 	var info uint64
    334 	var is64 int
    335 	var j int
    336 	var n int
    337 	var name string
    338 	var p []byte
    339 	var r []Reloc
    340 	var rela int
    341 	var rp *Reloc
    342 	var rsect *ElfSect
    343 	var s *LSym
    344 	var sect *ElfSect
    345 	var sym ElfSym
    346 	var symbols []*LSym
    347 	if obj.Bread(f, hdrbuf[:]) != len(hdrbuf) {
    348 		goto bad
    349 	}
    350 	hdr = new(ElfHdrBytes)
    351 	binary.Read(bytes.NewReader(hdrbuf[:]), binary.BigEndian, hdr) // only byte arrays; byte order doesn't matter
    352 	if string(hdr.Ident[:4]) != "\x7FELF" {
    353 		goto bad
    354 	}
    355 	switch hdr.Ident[5] {
    356 	case ElfDataLsb:
    357 		e = binary.LittleEndian
    358 
    359 	case ElfDataMsb:
    360 		e = binary.BigEndian
    361 
    362 	default:
    363 		goto bad
    364 	}
    365 
    366 	// read header
    367 	elfobj = new(ElfObj)
    368 
    369 	elfobj.e = e
    370 	elfobj.f = f
    371 	elfobj.base = int64(base)
    372 	elfobj.length = length
    373 	elfobj.name = pn
    374 
    375 	is64 = 0
    376 	if hdr.Ident[4] == ElfClass64 {
    377 		is64 = 1
    378 		hdr := new(ElfHdrBytes64)
    379 		binary.Read(bytes.NewReader(hdrbuf[:]), binary.BigEndian, hdr) // only byte arrays; byte order doesn't matter
    380 		elfobj.type_ = uint32(e.Uint16(hdr.Type[:]))
    381 		elfobj.machine = uint32(e.Uint16(hdr.Machine[:]))
    382 		elfobj.version = e.Uint32(hdr.Version[:])
    383 		elfobj.phoff = e.Uint64(hdr.Phoff[:])
    384 		elfobj.shoff = e.Uint64(hdr.Shoff[:])
    385 		elfobj.flags = e.Uint32(hdr.Flags[:])
    386 		elfobj.ehsize = uint32(e.Uint16(hdr.Ehsize[:]))
    387 		elfobj.phentsize = uint32(e.Uint16(hdr.Phentsize[:]))
    388 		elfobj.phnum = uint32(e.Uint16(hdr.Phnum[:]))
    389 		elfobj.shentsize = uint32(e.Uint16(hdr.Shentsize[:]))
    390 		elfobj.shnum = uint32(e.Uint16(hdr.Shnum[:]))
    391 		elfobj.shstrndx = uint32(e.Uint16(hdr.Shstrndx[:]))
    392 	} else {
    393 		elfobj.type_ = uint32(e.Uint16(hdr.Type[:]))
    394 		elfobj.machine = uint32(e.Uint16(hdr.Machine[:]))
    395 		elfobj.version = e.Uint32(hdr.Version[:])
    396 		elfobj.entry = uint64(e.Uint32(hdr.Entry[:]))
    397 		elfobj.phoff = uint64(e.Uint32(hdr.Phoff[:]))
    398 		elfobj.shoff = uint64(e.Uint32(hdr.Shoff[:]))
    399 		elfobj.flags = e.Uint32(hdr.Flags[:])
    400 		elfobj.ehsize = uint32(e.Uint16(hdr.Ehsize[:]))
    401 		elfobj.phentsize = uint32(e.Uint16(hdr.Phentsize[:]))
    402 		elfobj.phnum = uint32(e.Uint16(hdr.Phnum[:]))
    403 		elfobj.shentsize = uint32(e.Uint16(hdr.Shentsize[:]))
    404 		elfobj.shnum = uint32(e.Uint16(hdr.Shnum[:]))
    405 		elfobj.shstrndx = uint32(e.Uint16(hdr.Shstrndx[:]))
    406 	}
    407 
    408 	elfobj.is64 = is64
    409 
    410 	if uint32(hdr.Ident[6]) != elfobj.version {
    411 		goto bad
    412 	}
    413 
    414 	if e.Uint16(hdr.Type[:]) != ElfTypeRelocatable {
    415 		Diag("%s: elf but not elf relocatable object", pn)
    416 		return
    417 	}
    418 
    419 	switch Thearch.Thechar {
    420 	default:
    421 		Diag("%s: elf %s unimplemented", pn, Thestring)
    422 		return
    423 
    424 	case '5':
    425 		if e != binary.LittleEndian || elfobj.machine != ElfMachArm || hdr.Ident[4] != ElfClass32 {
    426 			Diag("%s: elf object but not arm", pn)
    427 			return
    428 		}
    429 
    430 	case '6':
    431 		if e != binary.LittleEndian || elfobj.machine != ElfMachAmd64 || hdr.Ident[4] != ElfClass64 {
    432 			Diag("%s: elf object but not amd64", pn)
    433 			return
    434 		}
    435 
    436 	case '7':
    437 		if e != binary.LittleEndian || elfobj.machine != ElfMachArm64 || hdr.Ident[4] != ElfClass64 {
    438 			Diag("%s: elf object but not arm64", pn)
    439 			return
    440 		}
    441 
    442 	case '8':
    443 		if e != binary.LittleEndian || elfobj.machine != ElfMach386 || hdr.Ident[4] != ElfClass32 {
    444 			Diag("%s: elf object but not 386", pn)
    445 			return
    446 		}
    447 
    448 	case '9':
    449 		if elfobj.machine != ElfMachPower64 || hdr.Ident[4] != ElfClass64 {
    450 			Diag("%s: elf object but not ppc64", pn)
    451 			return
    452 		}
    453 	}
    454 
    455 	// load section list into memory.
    456 	elfobj.sect = make([]ElfSect, elfobj.shnum)
    457 
    458 	elfobj.nsect = uint(elfobj.shnum)
    459 	for i := 0; uint(i) < elfobj.nsect; i++ {
    460 		if obj.Bseek(f, int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0) < 0 {
    461 			goto bad
    462 		}
    463 		sect = &elfobj.sect[i]
    464 		if is64 != 0 {
    465 			var b ElfSectBytes64
    466 
    467 			if err = binary.Read(f, e, &b); err != nil {
    468 				goto bad
    469 			}
    470 
    471 			sect.nameoff = uint32(e.Uint32(b.Name[:]))
    472 			sect.type_ = e.Uint32(b.Type[:])
    473 			sect.flags = e.Uint64(b.Flags[:])
    474 			sect.addr = e.Uint64(b.Addr[:])
    475 			sect.off = e.Uint64(b.Off[:])
    476 			sect.size = e.Uint64(b.Size[:])
    477 			sect.link = e.Uint32(b.Link[:])
    478 			sect.info = e.Uint32(b.Info[:])
    479 			sect.align = e.Uint64(b.Align[:])
    480 			sect.entsize = e.Uint64(b.Entsize[:])
    481 		} else {
    482 			var b ElfSectBytes
    483 
    484 			if err = binary.Read(f, e, &b); err != nil {
    485 				goto bad
    486 			}
    487 
    488 			sect.nameoff = uint32(e.Uint32(b.Name[:]))
    489 			sect.type_ = e.Uint32(b.Type[:])
    490 			sect.flags = uint64(e.Uint32(b.Flags[:]))
    491 			sect.addr = uint64(e.Uint32(b.Addr[:]))
    492 			sect.off = uint64(e.Uint32(b.Off[:]))
    493 			sect.size = uint64(e.Uint32(b.Size[:]))
    494 			sect.link = e.Uint32(b.Link[:])
    495 			sect.info = e.Uint32(b.Info[:])
    496 			sect.align = uint64(e.Uint32(b.Align[:]))
    497 			sect.entsize = uint64(e.Uint32(b.Entsize[:]))
    498 		}
    499 	}
    500 
    501 	// read section string table and translate names
    502 	if elfobj.shstrndx >= uint32(elfobj.nsect) {
    503 		err = fmt.Errorf("shstrndx out of range %d >= %d", elfobj.shstrndx, elfobj.nsect)
    504 		goto bad
    505 	}
    506 
    507 	sect = &elfobj.sect[elfobj.shstrndx]
    508 	if err = elfmap(elfobj, sect); err != nil {
    509 		goto bad
    510 	}
    511 	for i := 0; uint(i) < elfobj.nsect; i++ {
    512 		if elfobj.sect[i].nameoff != 0 {
    513 			elfobj.sect[i].name = cstring(sect.base[elfobj.sect[i].nameoff:])
    514 		}
    515 	}
    516 
    517 	// load string table for symbols into memory.
    518 	elfobj.symtab = section(elfobj, ".symtab")
    519 
    520 	if elfobj.symtab == nil {
    521 		// our work is done here - no symbols means nothing can refer to this file
    522 		return
    523 	}
    524 
    525 	if elfobj.symtab.link <= 0 || elfobj.symtab.link >= uint32(elfobj.nsect) {
    526 		Diag("%s: elf object has symbol table with invalid string table link", pn)
    527 		return
    528 	}
    529 
    530 	elfobj.symstr = &elfobj.sect[elfobj.symtab.link]
    531 	if is64 != 0 {
    532 		elfobj.nsymtab = int(elfobj.symtab.size / ELF64SYMSIZE)
    533 	} else {
    534 		elfobj.nsymtab = int(elfobj.symtab.size / ELF32SYMSIZE)
    535 	}
    536 
    537 	if err = elfmap(elfobj, elfobj.symtab); err != nil {
    538 		goto bad
    539 	}
    540 	if err = elfmap(elfobj, elfobj.symstr); err != nil {
    541 		goto bad
    542 	}
    543 
    544 	// load text and data segments into memory.
    545 	// they are not as small as the section lists, but we'll need
    546 	// the memory anyway for the symbol images, so we might
    547 	// as well use one large chunk.
    548 
    549 	// create symbols for elfmapped sections
    550 	for i := 0; uint(i) < elfobj.nsect; i++ {
    551 		sect = &elfobj.sect[i]
    552 		if (sect.type_ != ElfSectProgbits && sect.type_ != ElfSectNobits) || sect.flags&ElfSectFlagAlloc == 0 {
    553 			continue
    554 		}
    555 		if sect.type_ != ElfSectNobits {
    556 			if err = elfmap(elfobj, sect); err != nil {
    557 				goto bad
    558 			}
    559 		}
    560 
    561 		name = fmt.Sprintf("%s(%s)", pkg, sect.name)
    562 		s = Linklookup(Ctxt, name, Ctxt.Version)
    563 
    564 		switch int(sect.flags) & (ElfSectFlagAlloc | ElfSectFlagWrite | ElfSectFlagExec) {
    565 		default:
    566 			err = fmt.Errorf("unexpected flags for ELF section %s", sect.name)
    567 			goto bad
    568 
    569 		case ElfSectFlagAlloc:
    570 			s.Type = obj.SRODATA
    571 
    572 		case ElfSectFlagAlloc + ElfSectFlagWrite:
    573 			if sect.type_ == ElfSectNobits {
    574 				s.Type = obj.SNOPTRBSS
    575 			} else {
    576 				s.Type = obj.SNOPTRDATA
    577 			}
    578 
    579 		case ElfSectFlagAlloc + ElfSectFlagExec:
    580 			s.Type = obj.STEXT
    581 		}
    582 
    583 		if sect.name == ".got" || sect.name == ".toc" {
    584 			s.Type = obj.SELFGOT
    585 		}
    586 		if sect.type_ == ElfSectProgbits {
    587 			s.P = sect.base
    588 			s.P = s.P[:sect.size]
    589 		}
    590 
    591 		s.Size = int64(sect.size)
    592 		s.Align = int32(sect.align)
    593 		sect.sym = s
    594 	}
    595 
    596 	// enter sub-symbols into symbol table.
    597 	// symbol 0 is the null symbol.
    598 	symbols = make([]*LSym, elfobj.nsymtab)
    599 
    600 	for i := 1; i < elfobj.nsymtab; i++ {
    601 		if err = readelfsym(elfobj, i, &sym, 1); err != nil {
    602 			goto bad
    603 		}
    604 		symbols[i] = sym.sym
    605 		if sym.type_ != ElfSymTypeFunc && sym.type_ != ElfSymTypeObject && sym.type_ != ElfSymTypeNone {
    606 			continue
    607 		}
    608 		if sym.shndx == ElfSymShnCommon {
    609 			s = sym.sym
    610 			if uint64(s.Size) < sym.size {
    611 				s.Size = int64(sym.size)
    612 			}
    613 			if s.Type == 0 || s.Type == obj.SXREF {
    614 				s.Type = obj.SNOPTRBSS
    615 			}
    616 			continue
    617 		}
    618 
    619 		if uint(sym.shndx) >= elfobj.nsect || sym.shndx == 0 {
    620 			continue
    621 		}
    622 
    623 		// even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols
    624 		if sym.sym == nil {
    625 			continue
    626 		}
    627 		sect = &elfobj.sect[sym.shndx:][0]
    628 		if sect.sym == nil {
    629 			if strings.HasPrefix(sym.name, ".Linfo_string") { // clang does this
    630 				continue
    631 			}
    632 			Diag("%s: sym#%d: ignoring %s in section %d (type %d)", pn, i, sym.name, sym.shndx, sym.type_)
    633 			continue
    634 		}
    635 
    636 		s = sym.sym
    637 		if s.Outer != nil {
    638 			if s.Dupok != 0 {
    639 				continue
    640 			}
    641 			Exitf("%s: duplicate symbol reference: %s in both %s and %s", pn, s.Name, s.Outer.Name, sect.sym.Name)
    642 		}
    643 
    644 		s.Sub = sect.sym.Sub
    645 		sect.sym.Sub = s
    646 		s.Type = sect.sym.Type | s.Type&^obj.SMASK | obj.SSUB
    647 		if s.Cgoexport&CgoExportDynamic == 0 {
    648 			s.Dynimplib = "" // satisfy dynimport
    649 		}
    650 		s.Value = int64(sym.value)
    651 		s.Size = int64(sym.size)
    652 		s.Outer = sect.sym
    653 		if sect.sym.Type == obj.STEXT {
    654 			if s.External != 0 && s.Dupok == 0 {
    655 				Diag("%s: duplicate definition of %s", pn, s.Name)
    656 			}
    657 			s.External = 1
    658 		}
    659 
    660 		if elfobj.machine == ElfMachPower64 {
    661 			flag = int(sym.other) >> 5
    662 			if 2 <= flag && flag <= 6 {
    663 				s.Localentry = 1 << uint(flag-2)
    664 			} else if flag == 7 {
    665 				Diag("%s: invalid sym.other 0x%x for %s", pn, sym.other, s.Name)
    666 			}
    667 		}
    668 	}
    669 
    670 	// Sort outer lists by address, adding to textp.
    671 	// This keeps textp in increasing address order.
    672 	for i := 0; uint(i) < elfobj.nsect; i++ {
    673 		s = elfobj.sect[i].sym
    674 		if s == nil {
    675 			continue
    676 		}
    677 		if s.Sub != nil {
    678 			s.Sub = listsort(s.Sub, valuecmp, listsubp)
    679 		}
    680 		if s.Type == obj.STEXT {
    681 			if s.Onlist != 0 {
    682 				log.Fatalf("symbol %s listed multiple times", s.Name)
    683 			}
    684 			s.Onlist = 1
    685 			if Ctxt.Etextp != nil {
    686 				Ctxt.Etextp.Next = s
    687 			} else {
    688 				Ctxt.Textp = s
    689 			}
    690 			Ctxt.Etextp = s
    691 			for s = s.Sub; s != nil; s = s.Sub {
    692 				if s.Onlist != 0 {
    693 					log.Fatalf("symbol %s listed multiple times", s.Name)
    694 				}
    695 				s.Onlist = 1
    696 				Ctxt.Etextp.Next = s
    697 				Ctxt.Etextp = s
    698 			}
    699 		}
    700 	}
    701 
    702 	// load relocations
    703 	for i := 0; uint(i) < elfobj.nsect; i++ {
    704 		rsect = &elfobj.sect[i]
    705 		if rsect.type_ != ElfSectRela && rsect.type_ != ElfSectRel {
    706 			continue
    707 		}
    708 		if rsect.info >= uint32(elfobj.nsect) || elfobj.sect[rsect.info].base == nil {
    709 			continue
    710 		}
    711 		sect = &elfobj.sect[rsect.info]
    712 		if err = elfmap(elfobj, rsect); err != nil {
    713 			goto bad
    714 		}
    715 		rela = 0
    716 		if rsect.type_ == ElfSectRela {
    717 			rela = 1
    718 		}
    719 		n = int(rsect.size / uint64(4+4*is64) / uint64(2+rela))
    720 		r = make([]Reloc, n)
    721 		p = rsect.base
    722 		for j = 0; j < n; j++ {
    723 			add = 0
    724 			rp = &r[j]
    725 			if is64 != 0 {
    726 				// 64-bit rel/rela
    727 				rp.Off = int32(e.Uint64(p))
    728 
    729 				p = p[8:]
    730 				info = e.Uint64(p)
    731 				p = p[8:]
    732 				if rela != 0 {
    733 					add = e.Uint64(p)
    734 					p = p[8:]
    735 				}
    736 			} else {
    737 				// 32-bit rel/rela
    738 				rp.Off = int32(e.Uint32(p))
    739 
    740 				p = p[4:]
    741 				info = uint64(e.Uint32(p))
    742 				info = info>>8<<32 | info&0xff // convert to 64-bit info
    743 				p = p[4:]
    744 				if rela != 0 {
    745 					add = uint64(e.Uint32(p))
    746 					p = p[4:]
    747 				}
    748 			}
    749 
    750 			if info&0xffffffff == 0 { // skip R_*_NONE relocation
    751 				j--
    752 				n--
    753 				continue
    754 			}
    755 
    756 			if info>>32 == 0 { // absolute relocation, don't bother reading the null symbol
    757 				rp.Sym = nil
    758 			} else {
    759 				if err = readelfsym(elfobj, int(info>>32), &sym, 0); err != nil {
    760 					goto bad
    761 				}
    762 				sym.sym = symbols[info>>32]
    763 				if sym.sym == nil {
    764 					err = fmt.Errorf("%s#%d: reloc of invalid sym #%d %s shndx=%d type=%d", sect.sym.Name, j, int(info>>32), sym.name, sym.shndx, sym.type_)
    765 					goto bad
    766 				}
    767 
    768 				rp.Sym = sym.sym
    769 			}
    770 
    771 			rp.Type = int32(reltype(pn, int(uint32(info)), &rp.Siz))
    772 			if rela != 0 {
    773 				rp.Add = int64(add)
    774 			} else {
    775 				// load addend from image
    776 				if rp.Siz == 4 {
    777 					rp.Add = int64(e.Uint32(sect.base[rp.Off:]))
    778 				} else if rp.Siz == 8 {
    779 					rp.Add = int64(e.Uint64(sect.base[rp.Off:]))
    780 				} else {
    781 					Diag("invalid rela size %d", rp.Siz)
    782 				}
    783 			}
    784 
    785 			if rp.Siz == 2 {
    786 				rp.Add = int64(int16(rp.Add))
    787 			}
    788 			if rp.Siz == 4 {
    789 				rp.Add = int64(int32(rp.Add))
    790 			}
    791 		}
    792 
    793 		//print("rel %s %d %d %s %#llx\n", sect->sym->name, rp->type, rp->siz, rp->sym->name, rp->add);
    794 		sort.Sort(rbyoff(r[:n]))
    795 		// just in case
    796 
    797 		s = sect.sym
    798 		s.R = r
    799 		s.R = s.R[:n]
    800 	}
    801 
    802 	return
    803 
    804 bad:
    805 	Diag("%s: malformed elf file: %v", pn, err)
    806 }
    807 
    808 func section(elfobj *ElfObj, name string) *ElfSect {
    809 	for i := 0; uint(i) < elfobj.nsect; i++ {
    810 		if elfobj.sect[i].name != "" && name != "" && elfobj.sect[i].name == name {
    811 			return &elfobj.sect[i]
    812 		}
    813 	}
    814 	return nil
    815 }
    816 
    817 func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) {
    818 	if sect.base != nil {
    819 		return nil
    820 	}
    821 
    822 	if sect.off+sect.size > uint64(elfobj.length) {
    823 		err = fmt.Errorf("elf section past end of file")
    824 		return err
    825 	}
    826 
    827 	sect.base = make([]byte, sect.size)
    828 	err = fmt.Errorf("short read")
    829 	if obj.Bseek(elfobj.f, int64(uint64(elfobj.base)+sect.off), 0) < 0 || obj.Bread(elfobj.f, sect.base) != len(sect.base) {
    830 		return err
    831 	}
    832 
    833 	return nil
    834 }
    835 
    836 func readelfsym(elfobj *ElfObj, i int, sym *ElfSym, needSym int) (err error) {
    837 	if i >= elfobj.nsymtab || i < 0 {
    838 		err = fmt.Errorf("invalid elf symbol index")
    839 		return err
    840 	}
    841 
    842 	if i == 0 {
    843 		Diag("readym: read null symbol!")
    844 	}
    845 
    846 	if elfobj.is64 != 0 {
    847 		b := new(ElfSymBytes64)
    848 		binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF64SYMSIZE:(i+1)*ELF64SYMSIZE]), elfobj.e, b)
    849 		sym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
    850 		sym.value = elfobj.e.Uint64(b.Value[:])
    851 		sym.size = elfobj.e.Uint64(b.Size[:])
    852 		sym.shndx = elfobj.e.Uint16(b.Shndx[:])
    853 		sym.bind = b.Info >> 4
    854 		sym.type_ = b.Info & 0xf
    855 		sym.other = b.Other
    856 	} else {
    857 		b := new(ElfSymBytes)
    858 		binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF32SYMSIZE:(i+1)*ELF32SYMSIZE]), elfobj.e, b)
    859 		sym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
    860 		sym.value = uint64(elfobj.e.Uint32(b.Value[:]))
    861 		sym.size = uint64(elfobj.e.Uint32(b.Size[:]))
    862 		sym.shndx = elfobj.e.Uint16(b.Shndx[:])
    863 		sym.bind = b.Info >> 4
    864 		sym.type_ = b.Info & 0xf
    865 		sym.other = b.Other
    866 	}
    867 
    868 	var s *LSym
    869 	if sym.name == "_GLOBAL_OFFSET_TABLE_" {
    870 		sym.name = ".got"
    871 	}
    872 	if sym.name == ".TOC." {
    873 		// Magic symbol on ppc64.  Will be set to this object
    874 		// file's .got+0x8000.
    875 		sym.bind = ElfSymBindLocal
    876 	}
    877 
    878 	switch sym.type_ {
    879 	case ElfSymTypeSection:
    880 		s = elfobj.sect[sym.shndx].sym
    881 
    882 	case ElfSymTypeObject, ElfSymTypeFunc, ElfSymTypeNone:
    883 		switch sym.bind {
    884 		case ElfSymBindGlobal:
    885 			if needSym != 0 {
    886 				s = Linklookup(Ctxt, sym.name, 0)
    887 
    888 				// for global scoped hidden symbols we should insert it into
    889 				// symbol hash table, but mark them as hidden.
    890 				// __i686.get_pc_thunk.bx is allowed to be duplicated, to
    891 				// workaround that we set dupok.
    892 				// TODO(minux): correctly handle __i686.get_pc_thunk.bx without
    893 				// set dupok generally. See http://codereview.appspot.com/5823055/
    894 				// comment #5 for details.
    895 				if s != nil && sym.other == 2 {
    896 					s.Type |= obj.SHIDDEN
    897 					s.Dupok = 1
    898 				}
    899 			}
    900 
    901 		case ElfSymBindLocal:
    902 			if Thearch.Thechar == '5' && (strings.HasPrefix(sym.name, "$a") || strings.HasPrefix(sym.name, "$d")) {
    903 				// binutils for arm generate these mapping
    904 				// symbols, ignore these
    905 				break
    906 			}
    907 
    908 			if sym.name == ".TOC." {
    909 				// We need to be able to look this up,
    910 				// so put it in the hash table.
    911 				if needSym != 0 {
    912 					s = Linklookup(Ctxt, sym.name, Ctxt.Version)
    913 					s.Type |= obj.SHIDDEN
    914 				}
    915 
    916 				break
    917 			}
    918 
    919 			if needSym != 0 {
    920 				// local names and hidden visiblity global names are unique
    921 				// and should only reference by its index, not name, so we
    922 				// don't bother to add them into hash table
    923 				s = linknewsym(Ctxt, sym.name, Ctxt.Version)
    924 
    925 				s.Type |= obj.SHIDDEN
    926 			}
    927 
    928 		case ElfSymBindWeak:
    929 			if needSym != 0 {
    930 				s = linknewsym(Ctxt, sym.name, 0)
    931 				if sym.other == 2 {
    932 					s.Type |= obj.SHIDDEN
    933 				}
    934 			}
    935 
    936 		default:
    937 			err = fmt.Errorf("%s: invalid symbol binding %d", sym.name, sym.bind)
    938 			return err
    939 		}
    940 	}
    941 
    942 	if s != nil && s.Type == 0 && sym.type_ != ElfSymTypeSection {
    943 		s.Type = obj.SXREF
    944 	}
    945 	sym.sym = s
    946 
    947 	return nil
    948 }
    949 
    950 type rbyoff []Reloc
    951 
    952 func (x rbyoff) Len() int {
    953 	return len(x)
    954 }
    955 
    956 func (x rbyoff) Swap(i, j int) {
    957 	x[i], x[j] = x[j], x[i]
    958 }
    959 
    960 func (x rbyoff) Less(i, j int) bool {
    961 	a := &x[i]
    962 	b := &x[j]
    963 	if a.Off < b.Off {
    964 		return true
    965 	}
    966 	if a.Off > b.Off {
    967 		return false
    968 	}
    969 	return false
    970 }
    971 
    972 func reltype(pn string, elftype int, siz *uint8) int {
    973 	switch uint32(Thearch.Thechar) | uint32(elftype)<<24 {
    974 	default:
    975 		Diag("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype)
    976 		fallthrough
    977 
    978 	case '9' | R_PPC64_TOC16<<24,
    979 		'9' | R_PPC64_TOC16_LO<<24,
    980 		'9' | R_PPC64_TOC16_HI<<24,
    981 		'9' | R_PPC64_TOC16_HA<<24,
    982 		'9' | R_PPC64_TOC16_DS<<24,
    983 		'9' | R_PPC64_TOC16_LO_DS<<24,
    984 		'9' | R_PPC64_REL16_LO<<24,
    985 		'9' | R_PPC64_REL16_HI<<24,
    986 		'9' | R_PPC64_REL16_HA<<24:
    987 		*siz = 2
    988 
    989 	case '5' | R_ARM_ABS32<<24,
    990 		'5' | R_ARM_GOT32<<24,
    991 		'5' | R_ARM_PLT32<<24,
    992 		'5' | R_ARM_GOTOFF<<24,
    993 		'5' | R_ARM_GOTPC<<24,
    994 		'5' | R_ARM_THM_PC22<<24,
    995 		'5' | R_ARM_REL32<<24,
    996 		'5' | R_ARM_CALL<<24,
    997 		'5' | R_ARM_V4BX<<24,
    998 		'5' | R_ARM_GOT_PREL<<24,
    999 		'5' | R_ARM_PC24<<24,
   1000 		'5' | R_ARM_JUMP24<<24,
   1001 		'6' | R_X86_64_PC32<<24,
   1002 		'6' | R_X86_64_PLT32<<24,
   1003 		'6' | R_X86_64_GOTPCREL<<24,
   1004 		'8' | R_386_32<<24,
   1005 		'8' | R_386_PC32<<24,
   1006 		'8' | R_386_GOT32<<24,
   1007 		'8' | R_386_PLT32<<24,
   1008 		'8' | R_386_GOTOFF<<24,
   1009 		'8' | R_386_GOTPC<<24,
   1010 		'9' | R_PPC64_REL24<<24:
   1011 		*siz = 4
   1012 
   1013 	case '6' | R_X86_64_64<<24,
   1014 		'9' | R_PPC64_ADDR64<<24:
   1015 		*siz = 8
   1016 	}
   1017 
   1018 	return 256 + elftype
   1019 }
   1020