blob: 42d95bc9ee621eac75f500497e801d95c642ac36 [file] [log] [blame]
Russ Coxd6f6e422015-01-19 14:34:58 -05001// 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@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@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
32package obj
33
34import (
35 "fmt"
36 "log"
37 "os"
38 "path/filepath"
39)
40
41func yy_isalpha(c int) bool {
42 return 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z'
43}
44
45var headers = []struct {
46 name string
47 val int
48}{
49 struct {
50 name string
51 val int
52 }{"android", Hlinux},
53 struct {
54 name string
55 val int
56 }{"darwin", Hdarwin},
57 struct {
58 name string
59 val int
60 }{"dragonfly", Hdragonfly},
61 struct {
62 name string
63 val int
64 }{"elf", Helf},
65 struct {
66 name string
67 val int
68 }{"freebsd", Hfreebsd},
69 struct {
70 name string
71 val int
72 }{"linux", Hlinux},
73 struct {
74 name string
75 val int
76 }{"nacl", Hnacl},
77 struct {
78 name string
79 val int
80 }{"netbsd", Hnetbsd},
81 struct {
82 name string
83 val int
84 }{"openbsd", Hopenbsd},
85 struct {
86 name string
87 val int
88 }{"plan9", Hplan9},
89 struct {
90 name string
91 val int
92 }{"solaris", Hsolaris},
93 struct {
94 name string
95 val int
96 }{"windows", Hwindows},
97 struct {
98 name string
99 val int
100 }{"windowsgui", Hwindows},
101}
102
103func headtype(name string) int {
104 var i int
105
106 for i = 0; i < len(headers); i++ {
107 if name == headers[i].name {
108 return headers[i].val
109 }
110 }
111 return -1
112}
113
114func Headstr(v int) string {
115 var buf string
116 var i int
117
118 for i = 0; i < len(headers); i++ {
119 if v == headers[i].val {
120 return headers[i].name
121 }
122 }
123 buf = fmt.Sprintf("%d", v)
124 return buf
125}
126
127func Linknew(arch *LinkArch) *Link {
128 var ctxt *Link
129 var p string
130 var buf string
131
132 ctxt = new(Link)
133 ctxt.Arch = arch
134 ctxt.Version = HistVersion
135 ctxt.Goroot = Getgoroot()
136 ctxt.Goroot_final = os.Getenv("GOROOT_FINAL")
137
138 buf, _ = os.Getwd()
139 if buf == "" {
140 buf = "/???"
141 }
142 buf = filepath.ToSlash(buf)
143
144 ctxt.Pathname = buf
145
146 ctxt.Headtype = headtype(Getgoos())
147 if ctxt.Headtype < 0 {
148 log.Fatalf("unknown goos %s", Getgoos())
149 }
150
151 // Record thread-local storage offset.
152 // TODO(rsc): Move tlsoffset back into the linker.
153 switch ctxt.Headtype {
154
155 default:
156 log.Fatalf("unknown thread-local storage offset for %s", Headstr(ctxt.Headtype))
157
158 case Hplan9,
159 Hwindows:
160 break
161
162 /*
163 * ELF uses TLS offset negative from FS.
164 * Translate 0(FS) and 8(FS) into -16(FS) and -8(FS).
165 * Known to low-level assembly in package runtime and runtime/cgo.
166 */
167 case Hlinux,
168 Hfreebsd,
169 Hnetbsd,
170 Hopenbsd,
171 Hdragonfly,
172 Hsolaris:
173 ctxt.Tlsoffset = -2 * ctxt.Arch.Ptrsize
174
175 case Hnacl:
176 switch ctxt.Arch.Thechar {
177 default:
178 log.Fatalf("unknown thread-local storage offset for nacl/%s", ctxt.Arch.Name)
179
180 case '6':
181 ctxt.Tlsoffset = 0
182
183 case '8':
184 ctxt.Tlsoffset = -8
185
186 case '5':
187 ctxt.Tlsoffset = 0
188 break
189 }
190
191 /*
192 * OS X system constants - offset from 0(GS) to our TLS.
193 * Explained in ../../runtime/cgo/gcc_darwin_*.c.
194 */
195 case Hdarwin:
196 switch ctxt.Arch.Thechar {
197
198 default:
199 log.Fatalf("unknown thread-local storage offset for darwin/%s", ctxt.Arch.Name)
200
201 case '6':
202 ctxt.Tlsoffset = 0x8a0
203
204 case '8':
205 ctxt.Tlsoffset = 0x468
206 break
207 }
208
209 break
210 }
211
212 // On arm, record goarm.
213 if ctxt.Arch.Thechar == '5' {
214
215 p = Getgoarm()
216 if p != "" {
217 ctxt.Goarm = int32(Atoi(p))
218 } else {
219
220 ctxt.Goarm = 6
221 }
222 }
223
224 return ctxt
225}
226
227func linknewsym(ctxt *Link, symb string, v int) *LSym {
228 var s *LSym
229
230 s = new(LSym)
231 *s = LSym{}
232
233 s.Dynid = -1
234 s.Plt = -1
235 s.Got = -1
236 s.Name = symb
237 s.Type_ = 0
238 s.Version = int16(v)
239 s.Value = 0
240 s.Sig = 0
241 s.Size = 0
242 ctxt.Nsymbol++
243
244 s.Allsym = ctxt.Allsym
245 ctxt.Allsym = s
246
247 return s
248}
249
250func _lookup(ctxt *Link, symb string, v int, creat int) *LSym {
251 var s *LSym
252 var h uint32
253
254 h = uint32(v)
255 for i := 0; i < len(symb); i++ {
256 c := int(symb[i])
257 h = h + h + h + uint32(c)
258 }
259 h &= 0xffffff
260 h %= LINKHASH
261 for s = ctxt.Hash[h]; s != nil; s = s.Hash {
262 if int(s.Version) == v && s.Name == symb {
263 return s
264 }
265 }
266 if !(creat != 0) {
267 return nil
268 }
269
270 s = linknewsym(ctxt, symb, v)
271 s.Extname = s.Name
272 s.Hash = ctxt.Hash[h]
273 ctxt.Hash[h] = s
274
275 return s
276}
277
278func Linklookup(ctxt *Link, name string, v int) *LSym {
279 return _lookup(ctxt, name, v, 1)
280}
281
282// read-only lookup
283func linkrlookup(ctxt *Link, name string, v int) *LSym {
284
285 return _lookup(ctxt, name, v, 0)
286}