Home | History | Annotate | Download | only in obj
      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 obj
     33 
     34 import (
     35 	"log"
     36 	"os"
     37 	"path/filepath"
     38 	"runtime"
     39 	"strconv"
     40 )
     41 
     42 var headers = []struct {
     43 	name string
     44 	val  int
     45 }{
     46 	{"darwin", Hdarwin},
     47 	{"dragonfly", Hdragonfly},
     48 	{"elf", Helf},
     49 	{"freebsd", Hfreebsd},
     50 	{"linux", Hlinux},
     51 	{"android", Hlinux}, // must be after "linux" entry or else headstr(Hlinux) == "android"
     52 	{"nacl", Hnacl},
     53 	{"netbsd", Hnetbsd},
     54 	{"openbsd", Hopenbsd},
     55 	{"plan9", Hplan9},
     56 	{"solaris", Hsolaris},
     57 	{"windows", Hwindows},
     58 	{"windowsgui", Hwindows},
     59 }
     60 
     61 func headtype(name string) int {
     62 	for i := 0; i < len(headers); i++ {
     63 		if name == headers[i].name {
     64 			return headers[i].val
     65 		}
     66 	}
     67 	return -1
     68 }
     69 
     70 func Headstr(v int) string {
     71 	for i := 0; i < len(headers); i++ {
     72 		if v == headers[i].val {
     73 			return headers[i].name
     74 		}
     75 	}
     76 	return strconv.Itoa(v)
     77 }
     78 
     79 func Linknew(arch *LinkArch) *Link {
     80 	ctxt := new(Link)
     81 	ctxt.Hash = make(map[SymVer]*LSym)
     82 	ctxt.Arch = arch
     83 	ctxt.Version = HistVersion
     84 	ctxt.Goroot = Getgoroot()
     85 	ctxt.Goroot_final = os.Getenv("GOROOT_FINAL")
     86 	if runtime.GOOS == "windows" {
     87 		// TODO(rsc): Remove ctxt.Windows and let callers use runtime.GOOS.
     88 		ctxt.Windows = 1
     89 	}
     90 
     91 	var buf string
     92 	buf, _ = os.Getwd()
     93 	if buf == "" {
     94 		buf = "/???"
     95 	}
     96 	buf = filepath.ToSlash(buf)
     97 	ctxt.Pathname = buf
     98 
     99 	ctxt.LineHist.GOROOT = ctxt.Goroot
    100 	ctxt.LineHist.GOROOT_FINAL = ctxt.Goroot_final
    101 	ctxt.LineHist.Dir = ctxt.Pathname
    102 
    103 	ctxt.Headtype = headtype(Getgoos())
    104 	if ctxt.Headtype < 0 {
    105 		log.Fatalf("unknown goos %s", Getgoos())
    106 	}
    107 
    108 	// Record thread-local storage offset.
    109 	// TODO(rsc): Move tlsoffset back into the linker.
    110 	switch ctxt.Headtype {
    111 	default:
    112 		log.Fatalf("unknown thread-local storage offset for %s", Headstr(ctxt.Headtype))
    113 
    114 	case Hplan9, Hwindows:
    115 		break
    116 
    117 		/*
    118 		 * ELF uses TLS offset negative from FS.
    119 		 * Translate 0(FS) and 8(FS) into -16(FS) and -8(FS).
    120 		 * Known to low-level assembly in package runtime and runtime/cgo.
    121 		 */
    122 	case Hlinux,
    123 		Hfreebsd,
    124 		Hnetbsd,
    125 		Hopenbsd,
    126 		Hdragonfly,
    127 		Hsolaris:
    128 		ctxt.Tlsoffset = -1 * ctxt.Arch.Ptrsize
    129 
    130 	case Hnacl:
    131 		switch ctxt.Arch.Thechar {
    132 		default:
    133 			log.Fatalf("unknown thread-local storage offset for nacl/%s", ctxt.Arch.Name)
    134 
    135 		case '5':
    136 			ctxt.Tlsoffset = 0
    137 
    138 		case '6':
    139 			ctxt.Tlsoffset = 0
    140 
    141 		case '8':
    142 			ctxt.Tlsoffset = -8
    143 		}
    144 
    145 		/*
    146 		 * OS X system constants - offset from 0(GS) to our TLS.
    147 		 * Explained in ../../runtime/cgo/gcc_darwin_*.c.
    148 		 */
    149 	case Hdarwin:
    150 		switch ctxt.Arch.Thechar {
    151 		default:
    152 			log.Fatalf("unknown thread-local storage offset for darwin/%s", ctxt.Arch.Name)
    153 
    154 		case '5':
    155 			ctxt.Tlsoffset = 0 // dummy value, not needed
    156 
    157 		case '6':
    158 			ctxt.Tlsoffset = 0x8a0
    159 
    160 		case '7':
    161 			ctxt.Tlsoffset = 0 // dummy value, not needed
    162 
    163 		case '8':
    164 			ctxt.Tlsoffset = 0x468
    165 		}
    166 	}
    167 
    168 	// On arm, record goarm.
    169 	if ctxt.Arch.Thechar == '5' {
    170 		p := Getgoarm()
    171 		if p != "" {
    172 			ctxt.Goarm = int32(Atoi(p))
    173 		} else {
    174 			ctxt.Goarm = 6
    175 		}
    176 	}
    177 
    178 	return ctxt
    179 }
    180 
    181 func _lookup(ctxt *Link, symb string, v int, create bool) *LSym {
    182 	s := ctxt.Hash[SymVer{symb, v}]
    183 	if s != nil || !create {
    184 		return s
    185 	}
    186 
    187 	s = &LSym{
    188 		Name:    symb,
    189 		Type:    0,
    190 		Version: int16(v),
    191 		Value:   0,
    192 		Size:    0,
    193 	}
    194 	ctxt.Hash[SymVer{symb, v}] = s
    195 
    196 	return s
    197 }
    198 
    199 func Linklookup(ctxt *Link, name string, v int) *LSym {
    200 	return _lookup(ctxt, name, v, true)
    201 }
    202 
    203 // read-only lookup
    204 func linkrlookup(ctxt *Link, name string, v int) *LSym {
    205 	return _lookup(ctxt, name, v, false)
    206 }
    207 
    208 func Linksymfmt(s *LSym) string {
    209 	if s == nil {
    210 		return "<nil>"
    211 	}
    212 	return s.Name
    213 }
    214