blob: f9e257842794e514c8cdf90dbb068279db6b0f87 [file] [log] [blame]
Rob Pike0cafb9e2008-06-04 14:37:38 -07001// Inferno utils/6l/obj.c
2// http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.c
3//
4// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
5// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
6// Portions Copyright © 1997-1999 Vita Nuova Limited
7// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
8// Portions Copyright © 2004,2006 Bruce Ellis
9// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
10// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
11// Portions Copyright © 2009 The Go Authors. All rights reserved.
12//
13// Permission is hereby granted, free of charge, to any person obtaining a copy
14// of this software and associated documentation files (the "Software"), to deal
15// in the Software without restriction, including without limitation the rights
16// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17// copies of the Software, and to permit persons to whom the Software is
18// furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included in
21// all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29// THE SOFTWARE.
30
Russ Cox085be172010-10-13 15:51:21 -040031// Reading object files.
32
Rob Pike0cafb9e2008-06-04 14:37:38 -070033#define EXTERN
34#include "l.h"
Russ Coxc2874972009-10-07 00:11:59 -070035#include "../ld/lib.h"
Russ Cox0e25c1d2009-08-21 13:08:11 -070036#include "../ld/elf.h"
Russ Cox21570252009-09-30 17:33:39 -070037#include "../ld/macho.h"
Luuk van Dijkca9098e2010-08-18 16:53:22 +020038#include "../ld/dwarf.h"
Wei Guangjing3aec5512011-01-20 09:21:10 -050039#include "../ld/pe.h"
Rob Pike0cafb9e2008-06-04 14:37:38 -070040#include <ar.h>
41
Rob Pike0cafb9e2008-06-04 14:37:38 -070042char *noname = "<none>";
Rob Pike0cafb9e2008-06-04 14:37:38 -070043char thechar = '6';
Ken Thompsone2c3ec32008-06-05 16:56:23 -070044char* thestring = "amd64";
45char* paramspace = "FP";
Rob Pike0cafb9e2008-06-04 14:37:38 -070046
47/*
48 * -H2 -T4136 -R4096 is plan9 64-bit format
49 * -H3 -T4128 -R4096 is plan9 32-bit format
50 * -H5 -T0x80110000 -R4096 is ELF32
51 * -H6 -Tx -Rx is apple MH-exec
Rob Pike073486c2008-06-15 17:22:57 -070052 * -H7 -Tx -Rx is linux elf-exec
Devon H. O'Dell0489a262009-11-17 08:20:58 -080053 * -H9 -Tx -Rx is FreeBSD elf-exec
Rob Pike0cafb9e2008-06-04 14:37:38 -070054 *
55 * options used: 189BLQSWabcjlnpsvz
56 */
57
Rob Pike0cafb9e2008-06-04 14:37:38 -070058void
Russ Cox48974f52009-04-30 13:32:39 -070059usage(void)
60{
Ian Lance Taylor9040da92011-02-01 12:49:56 -080061 fprint(2, "usage: 6l [-options] [-E entry] [-H head] [-I interpreter] [-L dir] [-T text] [-R rnd] [-r path] [-o out] main.6\n");
Russ Cox48974f52009-04-30 13:32:39 -070062 exits("usage");
63}
64
65void
Rob Pike0cafb9e2008-06-04 14:37:38 -070066main(int argc, char *argv[])
67{
Russ Cox085be172010-10-13 15:51:21 -040068 int c;
Rob Pike0cafb9e2008-06-04 14:37:38 -070069
70 Binit(&bso, 1, OWRITE);
71 cout = -1;
72 listinit();
73 memset(debug, 0, sizeof(debug));
74 nerrors = 0;
75 outfile = "6.out";
76 HEADTYPE = -1;
77 INITTEXT = -1;
78 INITDAT = -1;
79 INITRND = -1;
80 INITENTRY = 0;
Ken Thompsone2c3ec32008-06-05 16:56:23 -070081
Rob Pike0cafb9e2008-06-04 14:37:38 -070082 ARGBEGIN {
83 default:
84 c = ARGC();
Kai Backman2f1a3212010-02-03 22:31:38 -080085 if(c == 'l')
86 usage();
87 if(c >= 0 && c < sizeof(debug))
Rob Pike0cafb9e2008-06-04 14:37:38 -070088 debug[c]++;
89 break;
90 case 'o': /* output to (next arg) */
Russ Cox48974f52009-04-30 13:32:39 -070091 outfile = EARGF(usage());
Rob Pike0cafb9e2008-06-04 14:37:38 -070092 break;
93 case 'E':
Russ Cox48974f52009-04-30 13:32:39 -070094 INITENTRY = EARGF(usage());
Rob Pike0cafb9e2008-06-04 14:37:38 -070095 break;
96 case 'H':
Russ Cox48974f52009-04-30 13:32:39 -070097 HEADTYPE = atolwhex(EARGF(usage()));
98 break;
Ian Lance Taylor9040da92011-02-01 12:49:56 -080099 case 'I':
100 interpreter = EARGF(usage());
101 break;
Russ Cox48974f52009-04-30 13:32:39 -0700102 case 'L':
Russ Coxc2874972009-10-07 00:11:59 -0700103 Lflag(EARGF(usage()));
Rob Pike0cafb9e2008-06-04 14:37:38 -0700104 break;
105 case 'T':
Russ Cox48974f52009-04-30 13:32:39 -0700106 INITTEXT = atolwhex(EARGF(usage()));
Rob Pike0cafb9e2008-06-04 14:37:38 -0700107 break;
108 case 'D':
Russ Cox48974f52009-04-30 13:32:39 -0700109 INITDAT = atolwhex(EARGF(usage()));
Rob Pike0cafb9e2008-06-04 14:37:38 -0700110 break;
111 case 'R':
Russ Cox48974f52009-04-30 13:32:39 -0700112 INITRND = atolwhex(EARGF(usage()));
Rob Pike0cafb9e2008-06-04 14:37:38 -0700113 break;
Ian Lance Taylore6443f62010-02-26 14:03:52 -0800114 case 'r':
115 rpath = EARGF(usage());
116 break;
Andrew Gerrandb4fb00b2010-02-08 09:46:53 -0800117 case 'V':
118 print("%cl version %s\n", thechar, getgoversion());
119 errorexit();
Rob Pike0cafb9e2008-06-04 14:37:38 -0700120 } ARGEND
Russ Cox3b1a0352010-01-25 17:53:43 -0800121
122 if(argc != 1)
Russ Cox07393f82009-06-02 22:33:21 -0700123 usage();
Ken Thompsone2c3ec32008-06-05 16:56:23 -0700124
Russ Coxc2874972009-10-07 00:11:59 -0700125 libinit();
Russ Cox489494c2010-06-30 23:31:27 -0700126 if(rpath == nil)
127 rpath = smprint("%s/pkg/%s_%s", goroot, goos, goarch);
Rob Pikee6bc5bf2009-10-05 21:31:50 -0700128
Rob Pike0cafb9e2008-06-04 14:37:38 -0700129 if(HEADTYPE == -1) {
Ken Thompsone2c3ec32008-06-05 16:56:23 -0700130 HEADTYPE = 2;
131 if(strcmp(goos, "linux") == 0)
132 HEADTYPE = 7;
133 else
134 if(strcmp(goos, "darwin") == 0)
135 HEADTYPE = 6;
136 else
Devon H. O'Dell60b1a172009-11-18 16:51:59 -0800137 if(strcmp(goos, "freebsd") == 0)
Devon H. O'Dell0489a262009-11-17 08:20:58 -0800138 HEADTYPE = 9;
Devon H. O'Dell60b1a172009-11-18 16:51:59 -0800139 else
Wei Guangjing3aec5512011-01-20 09:21:10 -0500140 if(strcmp(goos, "windows") == 0)
141 HEADTYPE = 10;
142 else
Ken Thompsone2c3ec32008-06-05 16:56:23 -0700143 print("goos is not known: %s\n", goos);
Rob Pike0cafb9e2008-06-04 14:37:38 -0700144 }
Ken Thompsone2c3ec32008-06-05 16:56:23 -0700145
Rob Pike0cafb9e2008-06-04 14:37:38 -0700146 switch(HEADTYPE) {
147 default:
148 diag("unknown -H option");
149 errorexit();
150 case 2: /* plan 9 */
151 HEADR = 32L+8L;
152 if(INITTEXT == -1)
153 INITTEXT = 4096+HEADR;
154 if(INITDAT == -1)
155 INITDAT = 0;
156 if(INITRND == -1)
157 INITRND = 4096;
158 break;
159 case 3: /* plan 9 */
160 HEADR = 32L;
161 if(INITTEXT == -1)
162 INITTEXT = 4096+32;
163 if(INITDAT == -1)
164 INITDAT = 0;
165 if(INITRND == -1)
166 INITRND = 4096;
167 break;
168 case 5: /* elf32 executable */
169 HEADR = rnd(52L+3*32L, 16);
170 if(INITTEXT == -1)
171 INITTEXT = 0x80110000L;
172 if(INITDAT == -1)
173 INITDAT = 0;
174 if(INITRND == -1)
175 INITRND = 4096;
176 break;
177 case 6: /* apple MACH */
Russ Coxe473f422010-08-04 17:50:22 -0700178 /*
179 * OS X system constant - offset from 0(GS) to our TLS.
180 * Explained in ../../libcgo/darwin_amd64.c.
181 */
182 tlsoffset = 0x8a0;
Russ Cox21570252009-09-30 17:33:39 -0700183 machoinit();
184 HEADR = MACHORESERVE;
Russ Cox133a1582009-10-03 10:37:12 -0700185 if(INITRND == -1)
186 INITRND = 4096;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700187 if(INITTEXT == -1)
188 INITTEXT = 4096+HEADR;
189 if(INITDAT == -1)
190 INITDAT = 0;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700191 break;
Ken Thompsone2c3ec32008-06-05 16:56:23 -0700192 case 7: /* elf64 executable */
Devon H. O'Dell0489a262009-11-17 08:20:58 -0800193 case 9: /* freebsd */
Russ Coxe473f422010-08-04 17:50:22 -0700194 /*
195 * ELF uses TLS offset negative from FS.
196 * Translate 0(FS) and 8(FS) into -16(FS) and -8(FS).
197 * Also known to ../../pkg/runtime/linux/amd64/sys.s
198 * and ../../libcgo/linux_amd64.s.
199 */
200 tlsoffset = -16;
Russ Cox0e25c1d2009-08-21 13:08:11 -0700201 elfinit();
202 HEADR = ELFRESERVE;
Ken Thompsone2c3ec32008-06-05 16:56:23 -0700203 if(INITTEXT == -1)
Russ Coxc3ca0562008-09-08 15:22:55 -0700204 INITTEXT = (1<<22)+HEADR;
Ken Thompsone2c3ec32008-06-05 16:56:23 -0700205 if(INITDAT == -1)
206 INITDAT = 0;
207 if(INITRND == -1)
208 INITRND = 4096;
209 break;
Wei Guangjing3aec5512011-01-20 09:21:10 -0500210 case 10: /* PE executable */
211 peinit();
212 HEADR = PEFILEHEADR;
213 if(INITTEXT == -1)
214 INITTEXT = PEBASE+PESECTHEADR;
215 if(INITDAT == -1)
216 INITDAT = 0;
217 if(INITRND == -1)
218 INITRND = PESECTALIGN;
219 break;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700220 }
221 if(INITDAT != 0 && INITRND != 0)
Russ Coxd9c989f2010-10-13 16:20:22 -0400222 print("warning: -D0x%llux is ignored because of -R0x%ux\n",
Rob Pike0cafb9e2008-06-04 14:37:38 -0700223 INITDAT, INITRND);
224 if(debug['v'])
Russ Coxd9c989f2010-10-13 16:20:22 -0400225 Bprint(&bso, "HEADER = -H%d -T0x%llux -D0x%llux -R0x%ux\n",
Rob Pike0cafb9e2008-06-04 14:37:38 -0700226 HEADTYPE, INITTEXT, INITDAT, INITRND);
227 Bflush(&bso);
Russ Cox085be172010-10-13 15:51:21 -0400228 instinit();
Rob Pike0cafb9e2008-06-04 14:37:38 -0700229
230 zprg.link = P;
231 zprg.pcond = P;
232 zprg.back = 2;
233 zprg.as = AGOK;
234 zprg.from.type = D_NONE;
235 zprg.from.index = D_NONE;
236 zprg.from.scale = 1;
237 zprg.to = zprg.from;
238 zprg.mode = 64;
239
240 pcstr = "%.6llux ";
241 nuxiinit();
242 histgen = 0;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700243 pc = 0;
244 dtype = 4;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700245 version = 0;
246 cbp = buf.cbuf;
247 cbc = sizeof(buf.cbuf);
Rob Pike0cafb9e2008-06-04 14:37:38 -0700248
Russ Cox00f4c6a2010-02-03 16:30:45 -0800249 addlibpath("command line", "command line", argv[0], "main");
Kai Backman2f1a3212010-02-03 22:31:38 -0800250 loadlib();
Russ Coxc3fa54c2009-01-21 14:50:27 -0800251 deadcode();
Rob Pike0cafb9e2008-06-04 14:37:38 -0700252 patch();
253 follow();
Russ Cox0e25c1d2009-08-21 13:08:11 -0700254 doelf();
Russ Cox133a1582009-10-03 10:37:12 -0700255 if(HEADTYPE == 6)
256 domacho();
Rob Pike0cafb9e2008-06-04 14:37:38 -0700257 dostkoff();
258 paramspace = "SP"; /* (FP) now (SP) on output */
259 if(debug['p'])
260 if(debug['1'])
261 doprof1();
262 else
263 doprof2();
264 span();
Wei Guangjing3aec5512011-01-20 09:21:10 -0500265 if(HEADTYPE == 10)
266 dope();
Russ Cox33405ec2010-12-15 17:20:26 -0500267 addexport();
Russ Cox8132f1d2010-12-08 13:53:07 -0500268 textaddress();
Russ Cox19fd5c72010-10-19 18:07:19 -0400269 pclntab();
270 symtab();
Russ Cox01df0882010-10-19 13:08:17 -0400271 dodata();
272 address();
Russ Coxbe2c2122010-10-14 23:48:40 -0400273 reloc();
Rob Pike0cafb9e2008-06-04 14:37:38 -0700274 asmb();
275 undef();
276 if(debug['v']) {
277 Bprint(&bso, "%5.2f cpu time\n", cputime());
Russ Coxd9c989f2010-10-13 16:20:22 -0400278 Bprint(&bso, "%d symbols\n", nsymbol);
Rob Pike0cafb9e2008-06-04 14:37:38 -0700279 Bprint(&bso, "%d sizeof adr\n", sizeof(Adr));
280 Bprint(&bso, "%d sizeof prog\n", sizeof(Prog));
281 }
282 Bflush(&bso);
283
284 errorexit();
285}
286
Russ Cox085be172010-10-13 15:51:21 -0400287static Sym*
Russ Cox916f8962010-07-21 13:44:49 -0700288zsym(char *pn, Biobuf *f, Sym *h[])
289{
290 int o;
291
292 o = Bgetc(f);
293 if(o < 0 || o >= NSYM || h[o] == nil)
294 mangle(pn);
295 return h[o];
296}
297
Russ Cox085be172010-10-13 15:51:21 -0400298static void
Russ Coxe6929772010-07-16 16:16:17 -0700299zaddr(char *pn, Biobuf *f, Adr *a, Sym *h[])
Russ Coxa570eaa2008-10-20 17:33:51 -0700300{
Russ Cox916f8962010-07-21 13:44:49 -0700301 int t;
Russ Cox9aad9fe2008-08-03 17:25:15 -0700302 int32 l;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700303 Sym *s;
304 Auto *u;
305
Russ Coxa570eaa2008-10-20 17:33:51 -0700306 t = Bgetc(f);
Ken Thompson9c753542009-11-04 18:17:57 -0800307 a->index = D_NONE;
308 a->scale = 0;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700309 if(t & T_INDEX) {
Russ Coxa570eaa2008-10-20 17:33:51 -0700310 a->index = Bgetc(f);
311 a->scale = Bgetc(f);
Rob Pike0cafb9e2008-06-04 14:37:38 -0700312 }
313 a->offset = 0;
314 if(t & T_OFFSET) {
Russ Coxa570eaa2008-10-20 17:33:51 -0700315 a->offset = Bget4(f);
Rob Pike0cafb9e2008-06-04 14:37:38 -0700316 if(t & T_64) {
Russ Coxa570eaa2008-10-20 17:33:51 -0700317 a->offset &= 0xFFFFFFFFULL;
318 a->offset |= (vlong)Bget4(f) << 32;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700319 }
320 }
321 a->sym = S;
Russ Cox916f8962010-07-21 13:44:49 -0700322 if(t & T_SYM)
323 a->sym = zsym(pn, f, h);
Rob Pike0cafb9e2008-06-04 14:37:38 -0700324 a->type = D_NONE;
325 if(t & T_FCONST) {
Russ Coxa570eaa2008-10-20 17:33:51 -0700326 a->ieee.l = Bget4(f);
327 a->ieee.h = Bget4(f);
Rob Pike0cafb9e2008-06-04 14:37:38 -0700328 a->type = D_FCONST;
329 } else
330 if(t & T_SCONST) {
Russ Coxa570eaa2008-10-20 17:33:51 -0700331 Bread(f, a->scon, NSNAME);
Rob Pike0cafb9e2008-06-04 14:37:38 -0700332 a->type = D_SCONST;
333 }
Russ Coxa570eaa2008-10-20 17:33:51 -0700334 if(t & T_TYPE)
335 a->type = Bgetc(f);
Russ Cox9a442212010-07-26 17:34:02 -0700336 if(a->type < 0 || a->type >= D_SIZE)
337 mangle(pn);
Ken Thompson9c753542009-11-04 18:17:57 -0800338 adrgotype = S;
Russ Cox43f29e62009-08-12 18:16:24 -0700339 if(t & T_GOTYPE)
Russ Cox916f8962010-07-21 13:44:49 -0700340 adrgotype = zsym(pn, f, h);
Rob Pike0cafb9e2008-06-04 14:37:38 -0700341 s = a->sym;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700342 t = a->type;
Russ Coxe473f422010-08-04 17:50:22 -0700343 if(t == D_INDIR+D_GS)
344 a->offset += tlsoffset;
Russ Cox311c0b42009-08-13 14:41:42 -0700345 if(t != D_AUTO && t != D_PARAM) {
Russ Cox9a442212010-07-26 17:34:02 -0700346 if(s && adrgotype)
Ken Thompson9c753542009-11-04 18:17:57 -0800347 s->gotype = adrgotype;
Russ Coxa570eaa2008-10-20 17:33:51 -0700348 return;
Russ Cox311c0b42009-08-13 14:41:42 -0700349 }
Rob Pike0cafb9e2008-06-04 14:37:38 -0700350 l = a->offset;
351 for(u=curauto; u; u=u->link) {
352 if(u->asym == s)
353 if(u->type == t) {
354 if(u->aoffset > l)
355 u->aoffset = l;
Ken Thompson9c753542009-11-04 18:17:57 -0800356 if(adrgotype)
357 u->gotype = adrgotype;
Russ Coxa570eaa2008-10-20 17:33:51 -0700358 return;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700359 }
360 }
361
362 u = mal(sizeof(*u));
363 u->link = curauto;
364 curauto = u;
365 u->asym = s;
366 u->aoffset = l;
367 u->type = t;
Ken Thompson9c753542009-11-04 18:17:57 -0800368 u->gotype = adrgotype;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700369}
370
371void
Rob Pike0cafb9e2008-06-04 14:37:38 -0700372nopout(Prog *p)
373{
374 p->as = ANOP;
375 p->from.type = D_NONE;
376 p->to.type = D_NONE;
377}
378
Rob Pike0cafb9e2008-06-04 14:37:38 -0700379void
Russ Cox758f2bc2010-01-22 17:06:20 -0800380ldobj1(Biobuf *f, char *pkg, int64 len, char *pn)
Rob Pike0cafb9e2008-06-04 14:37:38 -0700381{
382 vlong ipc;
Russ Coxbe2c2122010-10-14 23:48:40 -0400383 Prog *p;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700384 int v, o, r, skip, mode;
385 Sym *h[NSYM], *s, *di;
Russ Cox9aad9fe2008-08-03 17:25:15 -0700386 uint32 sig;
Russ Cox758f2bc2010-01-22 17:06:20 -0800387 char *name, *x;
Russ Coxc2874972009-10-07 00:11:59 -0700388 int ntext;
Russ Coxa570eaa2008-10-20 17:33:51 -0700389 vlong eof;
Russ Coxc5f21c02008-11-13 13:42:26 -0800390 char src[1024];
Russ Cox085be172010-10-13 15:51:21 -0400391 Prog *lastp;
Russ Coxa570eaa2008-10-20 17:33:51 -0700392
Russ Cox085be172010-10-13 15:51:21 -0400393 lastp = nil;
Rob Piked5f4d942008-07-09 16:40:11 -0700394 ntext = 0;
Russ Coxc2874972009-10-07 00:11:59 -0700395 eof = Boffset(f) + len;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700396 di = S;
Russ Coxc2874972009-10-07 00:11:59 -0700397 src[0] = 0;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700398
399newloop:
400 memset(h, 0, sizeof(h));
401 version++;
402 histfrogp = 0;
403 ipc = pc;
404 skip = 0;
405 mode = 64;
406
407loop:
Russ Coxa570eaa2008-10-20 17:33:51 -0700408 if(f->state == Bracteof || Boffset(f) >= eof)
Rob Pike0cafb9e2008-06-04 14:37:38 -0700409 goto eof;
Russ Coxa570eaa2008-10-20 17:33:51 -0700410 o = Bgetc(f);
411 if(o == Beof)
412 goto eof;
413 o |= Bgetc(f) << 8;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700414 if(o <= AXXX || o >= ALAST) {
415 if(o < 0)
416 goto eof;
Russ Coxa570eaa2008-10-20 17:33:51 -0700417 diag("%s:#%lld: opcode out of range: %#ux", pn, Boffset(f), o);
Rob Pike0cafb9e2008-06-04 14:37:38 -0700418 print(" probably not a .6 file\n");
419 errorexit();
420 }
421
422 if(o == ANAME || o == ASIGNAME) {
423 sig = 0;
Russ Coxa570eaa2008-10-20 17:33:51 -0700424 if(o == ASIGNAME)
425 sig = Bget4(f);
426 v = Bgetc(f); /* type */
427 o = Bgetc(f); /* sym */
Rob Pike0cafb9e2008-06-04 14:37:38 -0700428 r = 0;
429 if(v == D_STATIC)
430 r = version;
Russ Coxa570eaa2008-10-20 17:33:51 -0700431 name = Brdline(f, '\0');
432 if(name == nil) {
433 if(Blinelen(f) > 0) {
434 fprint(2, "%s: name too long\n", pn);
435 errorexit();
436 }
437 goto eof;
438 }
Russ Cox758f2bc2010-01-22 17:06:20 -0800439 x = expandpkg(name, pkg);
440 s = lookup(x, r);
441 if(x != name)
442 free(x);
443 name = nil;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700444
445 if(debug['S'] && r == 0)
446 sig = 1729;
447 if(sig != 0){
448 if(s->sig != 0 && s->sig != sig)
Ken Thompsonddba96a2008-06-18 22:07:09 -0700449 diag("incompatible type signatures"
Russ Coxd9c989f2010-10-13 16:20:22 -0400450 "%ux(%s) and %ux(%s) for %s",
Russ Coxc2874972009-10-07 00:11:59 -0700451 s->sig, s->file, sig, pn, s->name);
Rob Pike0cafb9e2008-06-04 14:37:38 -0700452 s->sig = sig;
Russ Coxc2874972009-10-07 00:11:59 -0700453 s->file = pn;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700454 }
455
456 if(debug['W'])
457 print(" ANAME %s\n", s->name);
Russ Cox916f8962010-07-21 13:44:49 -0700458 if(o < 0 || o >= nelem(h))
459 mangle(pn);
Rob Pike0cafb9e2008-06-04 14:37:38 -0700460 h[o] = s;
Russ Coxfc8dca92009-02-05 13:58:43 -0800461 if((v == D_EXTERN || v == D_STATIC) && s->type == 0)
Rob Pike0cafb9e2008-06-04 14:37:38 -0700462 s->type = SXREF;
463 if(v == D_FILE) {
464 if(s->type != SFILE) {
465 histgen++;
466 s->type = SFILE;
467 s->value = histgen;
468 }
469 if(histfrogp < MAXHIST) {
470 histfrog[histfrogp] = s;
471 histfrogp++;
472 } else
473 collapsefrog(s);
Russ Coxd64a2bd2010-09-14 11:16:57 -0400474 dwarfaddfrag(s->value, s->name);
Rob Pike0cafb9e2008-06-04 14:37:38 -0700475 }
476 goto loop;
477 }
478
479 p = mal(sizeof(*p));
480 p->as = o;
Russ Coxa570eaa2008-10-20 17:33:51 -0700481 p->line = Bget4(f);
Rob Pike0cafb9e2008-06-04 14:37:38 -0700482 p->back = 2;
483 p->mode = mode;
Ken Thompson9c753542009-11-04 18:17:57 -0800484 p->ft = 0;
485 p->tt = 0;
Russ Coxe6929772010-07-16 16:16:17 -0700486 zaddr(pn, f, &p->from, h);
Ken Thompson9c753542009-11-04 18:17:57 -0800487 fromgotype = adrgotype;
Russ Coxe6929772010-07-16 16:16:17 -0700488 zaddr(pn, f, &p->to, h);
Russ Cox9a442212010-07-26 17:34:02 -0700489
490 switch(p->as) {
491 case ATEXT:
492 case ADATA:
493 case AGLOBL:
494 if(p->from.sym == S)
495 mangle(pn);
496 break;
497 }
Rob Pike0cafb9e2008-06-04 14:37:38 -0700498
499 if(debug['W'])
500 print("%P\n", p);
501
502 switch(p->as) {
503 case AHISTORY:
504 if(p->to.offset == -1) {
Russ Coxc5f21c02008-11-13 13:42:26 -0800505 addlib(src, pn);
Rob Pike0cafb9e2008-06-04 14:37:38 -0700506 histfrogp = 0;
507 goto loop;
508 }
Russ Coxc5f21c02008-11-13 13:42:26 -0800509 if(src[0] == '\0')
510 copyhistfrog(src, sizeof src);
Rob Pike0cafb9e2008-06-04 14:37:38 -0700511 addhist(p->line, D_FILE); /* 'z' */
512 if(p->to.offset)
513 addhist(p->to.offset, D_FILE1); /* 'Z' */
514 histfrogp = 0;
515 goto loop;
516
517 case AEND:
518 histtoauto();
Russ Cox085be172010-10-13 15:51:21 -0400519 if(cursym != nil && cursym->text)
520 cursym->autom = curauto;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700521 curauto = 0;
Russ Cox085be172010-10-13 15:51:21 -0400522 cursym = nil;
Russ Coxa570eaa2008-10-20 17:33:51 -0700523 if(Boffset(f) == eof)
524 return;
525 goto newloop;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700526
527 case AGLOBL:
528 s = p->from.sym;
529 if(s->type == 0 || s->type == SXREF) {
530 s->type = SBSS;
Russ Cox698fb4f2010-09-12 00:17:44 -0400531 s->size = 0;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700532 }
Russ Cox698fb4f2010-09-12 00:17:44 -0400533 if(s->type != SBSS && !s->dupok) {
Rob Pike0cafb9e2008-06-04 14:37:38 -0700534 diag("%s: redefinition: %s in %s",
535 pn, s->name, TNAME);
536 s->type = SBSS;
Russ Cox698fb4f2010-09-12 00:17:44 -0400537 s->size = 0;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700538 }
Russ Cox698fb4f2010-09-12 00:17:44 -0400539 if(p->to.offset > s->size)
540 s->size = p->to.offset;
Russ Cox19831212008-11-05 11:27:50 -0800541 if(p->from.scale & DUPOK)
542 s->dupok = 1;
Russ Cox698fb4f2010-09-12 00:17:44 -0400543 if(p->from.scale & RODATA)
544 s->type = SRODATA;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700545 goto loop;
546
Rob Pike0cafb9e2008-06-04 14:37:38 -0700547 case ADATA:
Russ Cox19831212008-11-05 11:27:50 -0800548 // Assume that AGLOBL comes after ADATA.
549 // If we've seen an AGLOBL that said this sym was DUPOK,
550 // ignore any more ADATA we see, which must be
551 // redefinitions.
Russ Coxc3fa54c2009-01-21 14:50:27 -0800552 s = p->from.sym;
Russ Coxbe2c2122010-10-14 23:48:40 -0400553 if(s->dupok) {
Ken Thompson9c753542009-11-04 18:17:57 -0800554// if(debug['v'])
555// Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn);
Russ Cox19831212008-11-05 11:27:50 -0800556 goto loop;
Russ Cox8f144512009-01-20 13:21:22 -0800557 }
Russ Coxbe2c2122010-10-14 23:48:40 -0400558 if(s->file == nil)
559 s->file = pn;
560 else if(s->file != pn) {
561 diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn);
562 errorexit();
Russ Coxc3fa54c2009-01-21 14:50:27 -0800563 }
Russ Coxbe2c2122010-10-14 23:48:40 -0400564 savedata(s, p);
565 unmal(p, sizeof *p);
Rob Pike0cafb9e2008-06-04 14:37:38 -0700566 goto loop;
567
568 case AGOK:
569 diag("%s: GOK opcode in %s", pn, TNAME);
570 pc++;
571 goto loop;
572
573 case ATEXT:
Rob Piked5f4d942008-07-09 16:40:11 -0700574 s = p->from.sym;
Russ Cox085be172010-10-13 15:51:21 -0400575 if(s->text != nil) {
576 diag("%s: %s: redefinition", pn, s->name);
577 return;
578 }
Russ Coxfc8dca92009-02-05 13:58:43 -0800579 if(ntext++ == 0 && s->type != 0 && s->type != SXREF) {
Rob Piked5f4d942008-07-09 16:40:11 -0700580 /* redefinition, so file has probably been seen before */
581 if(debug['v'])
Russ Cox8f144512009-01-20 13:21:22 -0800582 Bprint(&bso, "skipping: %s: redefinition: %s", pn, s->name);
Rob Piked5f4d942008-07-09 16:40:11 -0700583 return;
584 }
Russ Cox085be172010-10-13 15:51:21 -0400585 if(cursym != nil && cursym->text) {
Rob Pike0cafb9e2008-06-04 14:37:38 -0700586 histtoauto();
Russ Cox085be172010-10-13 15:51:21 -0400587 cursym->autom = curauto;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700588 curauto = 0;
589 }
590 skip = 0;
Russ Cox085be172010-10-13 15:51:21 -0400591 if(etextp)
592 etextp->next = s;
593 else
594 textp = s;
595 etextp = s;
596 s->text = p;
597 cursym = s;
Russ Coxfc8dca92009-02-05 13:58:43 -0800598 if(s->type != 0 && s->type != SXREF) {
Rob Pike0cafb9e2008-06-04 14:37:38 -0700599 if(p->from.scale & DUPOK) {
600 skip = 1;
601 goto casdef;
602 }
603 diag("%s: redefinition: %s\n%P", pn, s->name, p);
604 }
Ken Thompson9c753542009-11-04 18:17:57 -0800605 if(fromgotype) {
606 if(s->gotype && s->gotype != fromgotype)
Russ Cox311c0b42009-08-13 14:41:42 -0700607 diag("%s: type mismatch for %s", pn, s->name);
Ken Thompson9c753542009-11-04 18:17:57 -0800608 s->gotype = fromgotype;
Russ Cox311c0b42009-08-13 14:41:42 -0700609 }
Russ Cox085be172010-10-13 15:51:21 -0400610 s->type = STEXT;
611 s->value = pc;
612 lastp = p;
613 p->pc = pc++;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700614 goto loop;
615
616 case AMODE:
617 if(p->from.type == D_CONST || p->from.type == D_INDIR+D_NONE){
618 switch((int)p->from.offset){
619 case 16: case 32: case 64:
620 mode = p->from.offset;
621 break;
622 }
623 }
624 goto loop;
625
626 case AFMOVF:
627 case AFADDF:
628 case AFSUBF:
629 case AFSUBRF:
630 case AFMULF:
631 case AFDIVF:
632 case AFDIVRF:
633 case AFCOMF:
634 case AFCOMFP:
635 case AMOVSS:
636 case AADDSS:
637 case ASUBSS:
638 case AMULSS:
639 case ADIVSS:
640 case ACOMISS:
641 case AUCOMISS:
642 if(skip)
643 goto casdef;
644 if(p->from.type == D_FCONST) {
645 /* size sb 9 max */
Russ Coxd9c989f2010-10-13 16:20:22 -0400646 sprint(literal, "$%ux", ieeedtof(&p->from.ieee));
Rob Pike0cafb9e2008-06-04 14:37:38 -0700647 s = lookup(literal, 0);
648 if(s->type == 0) {
Russ Coxbe2c2122010-10-14 23:48:40 -0400649 s->type = SDATA;
650 adduint32(s, ieeedtof(&p->from.ieee));
Russ Cox8132f1d2010-12-08 13:53:07 -0500651 s->reachable = 0;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700652 }
653 p->from.type = D_EXTERN;
654 p->from.sym = s;
655 p->from.offset = 0;
656 }
657 goto casdef;
658
659 case AFMOVD:
660 case AFADDD:
661 case AFSUBD:
662 case AFSUBRD:
663 case AFMULD:
664 case AFDIVD:
665 case AFDIVRD:
666 case AFCOMD:
667 case AFCOMDP:
668 case AMOVSD:
669 case AADDSD:
670 case ASUBSD:
671 case AMULSD:
672 case ADIVSD:
673 case ACOMISD:
674 case AUCOMISD:
675 if(skip)
676 goto casdef;
677 if(p->from.type == D_FCONST) {
678 /* size sb 18 max */
Russ Coxd9c989f2010-10-13 16:20:22 -0400679 sprint(literal, "$%ux.%ux",
Rob Pike0cafb9e2008-06-04 14:37:38 -0700680 p->from.ieee.l, p->from.ieee.h);
681 s = lookup(literal, 0);
682 if(s->type == 0) {
Russ Coxbe2c2122010-10-14 23:48:40 -0400683 s->type = SDATA;
684 adduint32(s, p->from.ieee.l);
685 adduint32(s, p->from.ieee.h);
Russ Cox8132f1d2010-12-08 13:53:07 -0500686 s->reachable = 0;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700687 }
688 p->from.type = D_EXTERN;
689 p->from.sym = s;
690 p->from.offset = 0;
691 }
692 goto casdef;
693
694 casdef:
695 default:
696 if(skip)
697 nopout(p);
Russ Cox085be172010-10-13 15:51:21 -0400698 p->pc = pc;
699 pc++;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700700
701 if(p->to.type == D_BRANCH)
702 p->to.offset += ipc;
Russ Cox085be172010-10-13 15:51:21 -0400703 if(lastp == nil) {
704 if(p->as != ANOP)
705 diag("unexpected instruction: %P", p);
706 goto loop;
707 }
Rob Pike0cafb9e2008-06-04 14:37:38 -0700708 lastp->link = p;
709 lastp = p;
Rob Pike0cafb9e2008-06-04 14:37:38 -0700710 goto loop;
711 }
712 goto loop;
713
714eof:
715 diag("truncated object file: %s", pn);
716}
717
Rob Pike0cafb9e2008-06-04 14:37:38 -0700718Prog*
719prg(void)
720{
721 Prog *p;
722
723 p = mal(sizeof(*p));
724
725 *p = zprg;
726 return p;
727}
728
729Prog*
730copyp(Prog *q)
731{
732 Prog *p;
733
734 p = prg();
735 *p = *q;
736 return p;
737}
738
739Prog*
740appendp(Prog *q)
741{
742 Prog *p;
743
744 p = prg();
745 p->link = q->link;
746 q->link = p;
747 p->line = q->line;
748 p->mode = q->mode;
749 return p;
750}