blob: e5efa2eb2da8ac42ccc51d66fc4d004f541d5b39 [file] [log] [blame]
Colin Cross7bb052a2015-02-03 12:59:37 -08001// 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
32#include <u.h>
33#include <libc.h>
34#include <bio.h>
35#include <link.h>
36
37void
38mangle(char *file)
39{
40 sysfatal("%s: mangled input file", file);
41}
42
43void
44symgrow(Link *ctxt, LSym *s, vlong lsiz)
45{
46 int32 siz;
47
48 USED(ctxt);
49
50 siz = (int32)lsiz;
51 if((vlong)siz != lsiz)
52 sysfatal("symgrow size %lld too long", lsiz);
53
54 if(s->np >= siz)
55 return;
56
57 if(s->np > s->maxp) {
58 ctxt->cursym = s;
59 sysfatal("corrupt symbol data: np=%lld > maxp=%lld", (vlong)s->np, (vlong)s->maxp);
60 }
61
62 if(s->maxp < siz) {
63 if(s->maxp == 0)
64 s->maxp = 8;
65 while(s->maxp < siz)
66 s->maxp <<= 1;
67 s->p = erealloc(s->p, s->maxp);
68 memset(s->p+s->np, 0, s->maxp-s->np);
69 }
70 s->np = siz;
71}
72
73void
74savedata(Link *ctxt, LSym *s, Prog *p, char *pn)
75{
76 int32 off, siz, i, fl;
77 float32 flt;
78 uchar *cast;
79 vlong o;
80 Reloc *r;
81
82 off = p->from.offset;
83 siz = ctxt->arch->datasize(p);
84 if(off < 0 || siz < 0 || off >= 1<<30 || siz >= 100)
85 mangle(pn);
86 if(ctxt->enforce_data_order && off < s->np)
87 ctxt->diag("data out of order (already have %d)\n%P", p);
88 symgrow(ctxt, s, off+siz);
89
90 if(p->to.type == ctxt->arch->D_FCONST) {
91 switch(siz) {
92 default:
93 case 4:
94 flt = p->to.u.dval;
95 cast = (uchar*)&flt;
96 for(i=0; i<4; i++)
97 s->p[off+i] = cast[fnuxi4[i]];
98 break;
99 case 8:
100 cast = (uchar*)&p->to.u.dval;
101 for(i=0; i<8; i++)
102 s->p[off+i] = cast[fnuxi8[i]];
103 break;
104 }
105 } else if(p->to.type == ctxt->arch->D_SCONST) {
106 for(i=0; i<siz; i++)
107 s->p[off+i] = p->to.u.sval[i];
108 } else if(p->to.type == ctxt->arch->D_CONST) {
109 if(p->to.sym)
110 goto addr;
111 o = p->to.offset;
112 fl = o;
113 cast = (uchar*)&fl;
114 switch(siz) {
115 default:
116 ctxt->diag("bad nuxi %d\n%P", siz, p);
117 break;
118 case 1:
119 s->p[off] = cast[inuxi1[0]];
120 break;
121 case 2:
122 for(i=0; i<2; i++)
123 s->p[off+i] = cast[inuxi2[i]];
124 break;
125 case 4:
126 for(i=0; i<4; i++)
127 s->p[off+i] = cast[inuxi4[i]];
128 break;
129 case 8:
130 cast = (uchar*)&o;
131 for(i=0; i<8; i++)
132 s->p[off+i] = cast[inuxi8[i]];
133 break;
134 }
135 } else if(p->to.type == ctxt->arch->D_ADDR) {
136 addr:
137 r = addrel(s);
138 r->off = off;
139 r->siz = siz;
140 r->sym = p->to.sym;
141 r->type = R_ADDR;
142 r->add = p->to.offset;
143 } else {
144 ctxt->diag("bad data: %P", p);
145 }
146}
147
148Reloc*
149addrel(LSym *s)
150{
151 if(s->nr >= s->maxr) {
152 if(s->maxr == 0)
153 s->maxr = 4;
154 else
155 s->maxr <<= 1;
156 s->r = erealloc(s->r, s->maxr*sizeof s->r[0]);
157 memset(s->r+s->nr, 0, (s->maxr-s->nr)*sizeof s->r[0]);
158 }
159 return &s->r[s->nr++];
160}
161
162vlong
163setuintxx(Link *ctxt, LSym *s, vlong off, uint64 v, vlong wid)
164{
165 int32 i, fl;
166 vlong o;
167 uchar *cast;
168
169 if(s->type == 0)
170 s->type = SDATA;
171 s->reachable = 1;
172 if(s->size < off+wid) {
173 s->size = off+wid;
174 symgrow(ctxt, s, s->size);
175 }
176 fl = v;
177 cast = (uchar*)&fl;
178 switch(wid) {
179 case 1:
180 s->p[off] = cast[inuxi1[0]];
181 break;
182 case 2:
183 for(i=0; i<2; i++)
184 s->p[off+i] = cast[inuxi2[i]];
185 break;
186 case 4:
187 for(i=0; i<4; i++)
188 s->p[off+i] = cast[inuxi4[i]];
189 break;
190 case 8:
191 o = v;
192 cast = (uchar*)&o;
193 for(i=0; i<8; i++)
194 s->p[off+i] = cast[inuxi8[i]];
195 break;
196 }
197 return off+wid;
198}
199
200vlong
201adduintxx(Link *ctxt, LSym *s, uint64 v, int wid)
202{
203 vlong off;
204
205 off = s->size;
206 setuintxx(ctxt, s, off, v, wid);
207 return off;
208}
209
210vlong
211adduint8(Link *ctxt, LSym *s, uint8 v)
212{
213 return adduintxx(ctxt, s, v, 1);
214}
215
216vlong
217adduint16(Link *ctxt, LSym *s, uint16 v)
218{
219 return adduintxx(ctxt, s, v, 2);
220}
221
222vlong
223adduint32(Link *ctxt, LSym *s, uint32 v)
224{
225 return adduintxx(ctxt, s, v, 4);
226}
227
228vlong
229adduint64(Link *ctxt, LSym *s, uint64 v)
230{
231 return adduintxx(ctxt, s, v, 8);
232}
233
234vlong
235setuint8(Link *ctxt, LSym *s, vlong r, uint8 v)
236{
237 return setuintxx(ctxt, s, r, v, 1);
238}
239
240vlong
241setuint16(Link *ctxt, LSym *s, vlong r, uint16 v)
242{
243 return setuintxx(ctxt, s, r, v, 2);
244}
245
246vlong
247setuint32(Link *ctxt, LSym *s, vlong r, uint32 v)
248{
249 return setuintxx(ctxt, s, r, v, 4);
250}
251
252vlong
253setuint64(Link *ctxt, LSym *s, vlong r, uint64 v)
254{
255 return setuintxx(ctxt, s, r, v, 8);
256}
257
258vlong
259addaddrplus(Link *ctxt, LSym *s, LSym *t, vlong add)
260{
261 vlong i;
262 Reloc *r;
263
264 if(s->type == 0)
265 s->type = SDATA;
266 s->reachable = 1;
267 i = s->size;
268 s->size += ctxt->arch->ptrsize;
269 symgrow(ctxt, s, s->size);
270 r = addrel(s);
271 r->sym = t;
272 r->off = i;
273 r->siz = ctxt->arch->ptrsize;
274 r->type = R_ADDR;
275 r->add = add;
276 return i + r->siz;
277}
278
279vlong
280addpcrelplus(Link *ctxt, LSym *s, LSym *t, vlong add)
281{
282 vlong i;
283 Reloc *r;
284
285 if(s->type == 0)
286 s->type = SDATA;
287 s->reachable = 1;
288 i = s->size;
289 s->size += 4;
290 symgrow(ctxt, s, s->size);
291 r = addrel(s);
292 r->sym = t;
293 r->off = i;
294 r->add = add;
295 r->type = R_PCREL;
296 r->siz = 4;
297 return i + r->siz;
298}
299
300vlong
301addaddr(Link *ctxt, LSym *s, LSym *t)
302{
303 return addaddrplus(ctxt, s, t, 0);
304}
305
306vlong
307setaddrplus(Link *ctxt, LSym *s, vlong off, LSym *t, vlong add)
308{
309 Reloc *r;
310
311 if(s->type == 0)
312 s->type = SDATA;
313 s->reachable = 1;
314 if(off+ctxt->arch->ptrsize > s->size) {
315 s->size = off + ctxt->arch->ptrsize;
316 symgrow(ctxt, s, s->size);
317 }
318 r = addrel(s);
319 r->sym = t;
320 r->off = off;
321 r->siz = ctxt->arch->ptrsize;
322 r->type = R_ADDR;
323 r->add = add;
324 return off + r->siz;
325}
326
327vlong
328setaddr(Link *ctxt, LSym *s, vlong off, LSym *t)
329{
330 return setaddrplus(ctxt, s, off, t, 0);
331}
332
333vlong
334addsize(Link *ctxt, LSym *s, LSym *t)
335{
336 vlong i;
337 Reloc *r;
338
339 if(s->type == 0)
340 s->type = SDATA;
341 s->reachable = 1;
342 i = s->size;
343 s->size += ctxt->arch->ptrsize;
344 symgrow(ctxt, s, s->size);
345 r = addrel(s);
346 r->sym = t;
347 r->off = i;
348 r->siz = ctxt->arch->ptrsize;
349 r->type = R_SIZE;
350 return i + r->siz;
351}
352
353vlong
354addaddrplus4(Link *ctxt, LSym *s, LSym *t, vlong add)
355{
356 vlong i;
357 Reloc *r;
358
359 if(s->type == 0)
360 s->type = SDATA;
361 s->reachable = 1;
362 i = s->size;
363 s->size += 4;
364 symgrow(ctxt, s, s->size);
365 r = addrel(s);
366 r->sym = t;
367 r->off = i;
368 r->siz = 4;
369 r->type = R_ADDR;
370 r->add = add;
371 return i + r->siz;
372}