Home | History | Annotate | Download | only in ld
      1 // Derived from Inferno utils/6l/obj.c and utils/6l/span.c
      2 // http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.c
      3 // http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c
      4 //
      5 //	Copyright  1994-1999 Lucent Technologies Inc.  All rights reserved.
      6 //	Portions Copyright  1995-1997 C H Forsyth (forsyth (a] terzarima.net)
      7 //	Portions Copyright  1997-1999 Vita Nuova Limited
      8 //	Portions Copyright  2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
      9 //	Portions Copyright  2004,2006 Bruce Ellis
     10 //	Portions Copyright  2005-2007 C H Forsyth (forsyth (a] terzarima.net)
     11 //	Revisions Copyright  2000-2007 Lucent Technologies Inc. and others
     12 //	Portions Copyright  2009 The Go Authors.  All rights reserved.
     13 //
     14 // Permission is hereby granted, free of charge, to any person obtaining a copy
     15 // of this software and associated documentation files (the "Software"), to deal
     16 // in the Software without restriction, including without limitation the rights
     17 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     18 // copies of the Software, and to permit persons to whom the Software is
     19 // furnished to do so, subject to the following conditions:
     20 //
     21 // The above copyright notice and this permission notice shall be included in
     22 // all copies or substantial portions of the Software.
     23 //
     24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     25 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     27 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     29 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     30 // THE SOFTWARE.
     31 
     32 package ld
     33 
     34 import (
     35 	"cmd/internal/obj"
     36 	"log"
     37 	"os"
     38 	"path/filepath"
     39 	"strconv"
     40 )
     41 
     42 func yy_isalpha(c int) bool {
     43 	return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
     44 }
     45 
     46 var headers = []struct {
     47 	name string
     48 	val  int
     49 }{
     50 	{"darwin", obj.Hdarwin},
     51 	{"dragonfly", obj.Hdragonfly},
     52 	{"elf", obj.Helf},
     53 	{"freebsd", obj.Hfreebsd},
     54 	{"linux", obj.Hlinux},
     55 	{"android", obj.Hlinux}, // must be after "linux" entry or else headstr(Hlinux) == "android"
     56 	{"nacl", obj.Hnacl},
     57 	{"netbsd", obj.Hnetbsd},
     58 	{"openbsd", obj.Hopenbsd},
     59 	{"plan9", obj.Hplan9},
     60 	{"solaris", obj.Hsolaris},
     61 	{"windows", obj.Hwindows},
     62 	{"windowsgui", obj.Hwindows},
     63 }
     64 
     65 func linknew(arch *LinkArch) *Link {
     66 	ctxt := new(Link)
     67 	ctxt.Hash = make(map[symVer]*LSym)
     68 	ctxt.Arch = arch
     69 	ctxt.Version = obj.HistVersion
     70 	ctxt.Goroot = obj.Getgoroot()
     71 
     72 	p := obj.Getgoarch()
     73 	if p != arch.Name {
     74 		log.Fatalf("invalid goarch %s (want %s)", p, arch.Name)
     75 	}
     76 
     77 	var buf string
     78 	buf, _ = os.Getwd()
     79 	if buf == "" {
     80 		buf = "/???"
     81 	}
     82 	buf = filepath.ToSlash(buf)
     83 
     84 	ctxt.Headtype = headtype(obj.Getgoos())
     85 	if ctxt.Headtype < 0 {
     86 		log.Fatalf("unknown goos %s", obj.Getgoos())
     87 	}
     88 
     89 	// Record thread-local storage offset.
     90 	// TODO(rsc): Move tlsoffset back into the linker.
     91 	switch ctxt.Headtype {
     92 	default:
     93 		log.Fatalf("unknown thread-local storage offset for %s", Headstr(ctxt.Headtype))
     94 
     95 	case obj.Hplan9, obj.Hwindows:
     96 		break
     97 
     98 		/*
     99 		 * ELF uses TLS offset negative from FS.
    100 		 * Translate 0(FS) and 8(FS) into -16(FS) and -8(FS).
    101 		 * Known to low-level assembly in package runtime and runtime/cgo.
    102 		 */
    103 	case obj.Hlinux,
    104 		obj.Hfreebsd,
    105 		obj.Hnetbsd,
    106 		obj.Hopenbsd,
    107 		obj.Hdragonfly,
    108 		obj.Hsolaris:
    109 		ctxt.Tlsoffset = -1 * ctxt.Arch.Ptrsize
    110 
    111 	case obj.Hnacl:
    112 		switch ctxt.Arch.Thechar {
    113 		default:
    114 			log.Fatalf("unknown thread-local storage offset for nacl/%s", ctxt.Arch.Name)
    115 
    116 		case '5':
    117 			ctxt.Tlsoffset = 0
    118 
    119 		case '6':
    120 			ctxt.Tlsoffset = 0
    121 
    122 		case '8':
    123 			ctxt.Tlsoffset = -8
    124 		}
    125 
    126 		/*
    127 		 * OS X system constants - offset from 0(GS) to our TLS.
    128 		 * Explained in ../../runtime/cgo/gcc_darwin_*.c.
    129 		 */
    130 	case obj.Hdarwin:
    131 		switch ctxt.Arch.Thechar {
    132 		default:
    133 			log.Fatalf("unknown thread-local storage offset for darwin/%s", ctxt.Arch.Name)
    134 
    135 		case '5':
    136 			ctxt.Tlsoffset = 0 // dummy value, not needed
    137 
    138 		case '6':
    139 			ctxt.Tlsoffset = 0x8a0
    140 
    141 		case '7':
    142 			ctxt.Tlsoffset = 0 // dummy value, not needed
    143 
    144 		case '8':
    145 			ctxt.Tlsoffset = 0x468
    146 		}
    147 	}
    148 
    149 	// On arm, record goarm.
    150 	if ctxt.Arch.Thechar == '5' {
    151 		p := obj.Getgoarm()
    152 		if p != "" {
    153 			ctxt.Goarm = int32(obj.Atoi(p))
    154 		} else {
    155 			ctxt.Goarm = 6
    156 		}
    157 	}
    158 
    159 	return ctxt
    160 }
    161 
    162 func linknewsym(ctxt *Link, symb string, v int) *LSym {
    163 	s := new(LSym)
    164 	*s = LSym{}
    165 
    166 	s.Dynid = -1
    167 	s.Plt = -1
    168 	s.Got = -1
    169 	s.Name = symb
    170 	s.Type = 0
    171 	s.Version = int16(v)
    172 	s.Value = 0
    173 	s.Size = 0
    174 	ctxt.Nsymbol++
    175 
    176 	s.Allsym = ctxt.Allsym
    177 	ctxt.Allsym = s
    178 
    179 	return s
    180 }
    181 
    182 type symVer struct {
    183 	sym string
    184 	ver int
    185 }
    186 
    187 func _lookup(ctxt *Link, symb string, v int, creat int) *LSym {
    188 	s := ctxt.Hash[symVer{symb, v}]
    189 	if s != nil {
    190 		return s
    191 	}
    192 	if creat == 0 {
    193 		return nil
    194 	}
    195 
    196 	s = linknewsym(ctxt, symb, v)
    197 	s.Extname = s.Name
    198 	ctxt.Hash[symVer{symb, v}] = s
    199 	return s
    200 }
    201 
    202 func Linklookup(ctxt *Link, name string, v int) *LSym {
    203 	return _lookup(ctxt, name, v, 1)
    204 }
    205 
    206 // read-only lookup
    207 func Linkrlookup(ctxt *Link, name string, v int) *LSym {
    208 	return _lookup(ctxt, name, v, 0)
    209 }
    210 
    211 func Headstr(v int) string {
    212 	for i := 0; i < len(headers); i++ {
    213 		if v == headers[i].val {
    214 			return headers[i].name
    215 		}
    216 	}
    217 	return strconv.Itoa(v)
    218 }
    219 
    220 func headtype(name string) int {
    221 	for i := 0; i < len(headers); i++ {
    222 		if name == headers[i].name {
    223 			return headers[i].val
    224 		}
    225 	}
    226 	return -1
    227 }
    228