1 #include "l.h"
2
3 #define Dbufslop 100
4
5 #define PADDR(a) ((a) & ~0xfffffffff0000000ull)
6
7 vlong
entryvalue(void)8 entryvalue(void)
9 {
10 char *a;
11 Sym *s;
12
13 a = INITENTRY;
14 if(*a >= '0' && *a <= '9')
15 return atolwhex(a);
16 s = lookup(a, 0);
17 if(s->type == 0)
18 return INITTEXT;
19 switch(s->type) {
20 case STEXT:
21 break;
22 case SDATA:
23 if(dlm)
24 return s->value+INITDAT;
25 default:
26 diag("entry not text: %s", s->name);
27 }
28 return s->value;
29 }
30
31 /* these need to take long arguments to be compatible with elf.c */
32 void
wputl(long w)33 wputl(long w)
34 {
35 cput(w);
36 cput(w>>8);
37 }
38
39 void
wput(long w)40 wput(long w)
41 {
42 cput(w>>8);
43 cput(w);
44 }
45
46 void
lput(long l)47 lput(long l)
48 {
49 cput(l>>24);
50 cput(l>>16);
51 cput(l>>8);
52 cput(l);
53 }
54
55 void
llput(vlong v)56 llput(vlong v)
57 {
58 lput(v>>32);
59 lput(v);
60 }
61
62 void
lputl(long l)63 lputl(long l)
64 {
65 cput(l);
66 cput(l>>8);
67 cput(l>>16);
68 cput(l>>24);
69 }
70
71 void
llputl(vlong v)72 llputl(vlong v)
73 {
74 lputl(v);
75 lputl(v>>32);
76 }
77
78 void
strnput(char * s,int n)79 strnput(char *s, int n)
80 {
81 for(; *s && n > 0; s++){
82 cput(*s);
83 n--;
84 }
85 while(n > 0){
86 cput(0);
87 n--;
88 }
89 }
90
91 void
asmb(void)92 asmb(void)
93 {
94 Prog *p;
95 long v, magic;
96 int a;
97 uchar *op1;
98 vlong vl;
99
100 if(debug['v'])
101 Bprint(&bso, "%5.2f asmb\n", cputime());
102 Bflush(&bso);
103
104 seek(cout, HEADR, 0);
105 pc = INITTEXT;
106 curp = firstp;
107 for(p = firstp; p != P; p = p->link) {
108 if(p->as == ATEXT)
109 curtext = p;
110 if(p->pc != pc) {
111 if(!debug['a'])
112 print("%P\n", curp);
113 diag("phase error %llux sb %llux in %s", p->pc, pc, TNAME);
114 pc = p->pc;
115 }
116 curp = p;
117 asmins(p);
118 a = (andptr - and);
119 if(cbc < a)
120 cflush();
121 if(debug['a']) {
122 Bprint(&bso, pcstr, pc);
123 for(op1 = and; op1 < andptr; op1++)
124 Bprint(&bso, "%.2ux", *op1 & 0xff);
125 Bprint(&bso, "\t%P\n", curp);
126 }
127 if(dlm) {
128 if(p->as == ATEXT)
129 reloca = nil;
130 else if(reloca != nil)
131 diag("reloc failure: %P", curp);
132 }
133 memmove(cbp, and, a);
134 cbp += a;
135 pc += a;
136 cbc -= a;
137 }
138 cflush();
139 switch(HEADTYPE) {
140 default:
141 diag("unknown header type %ld", HEADTYPE);
142 case 2:
143 case 5:
144 case 6:
145 seek(cout, HEADR+textsize, 0);
146 break;
147 }
148
149 if(debug['v'])
150 Bprint(&bso, "%5.2f datblk\n", cputime());
151 Bflush(&bso);
152
153 if(dlm){
154 char buf[8];
155
156 write(cout, buf, INITDAT-textsize);
157 textsize = INITDAT;
158 }
159
160 for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) {
161 if(datsize-v > sizeof(buf)-Dbufslop)
162 datblk(v, sizeof(buf)-Dbufslop);
163 else
164 datblk(v, datsize-v);
165 }
166
167 symsize = 0;
168 spsize = 0;
169 lcsize = 0;
170 if(!debug['s']) {
171 if(debug['v'])
172 Bprint(&bso, "%5.2f sym\n", cputime());
173 Bflush(&bso);
174 switch(HEADTYPE) {
175 default:
176 case 2:
177 case 5:
178 case 6:
179 seek(cout, HEADR+textsize+datsize, 0);
180 break;
181 }
182 if(!debug['s'])
183 asmsym();
184 if(debug['v'])
185 Bprint(&bso, "%5.2f sp\n", cputime());
186 Bflush(&bso);
187 if(debug['v'])
188 Bprint(&bso, "%5.2f pc\n", cputime());
189 Bflush(&bso);
190 if(!debug['s'])
191 asmlc();
192 if(dlm)
193 asmdyn();
194 cflush();
195 }
196 else if(dlm){
197 seek(cout, HEADR+textsize+datsize, 0);
198 asmdyn();
199 cflush();
200 }
201 if(debug['v'])
202 Bprint(&bso, "%5.2f headr\n", cputime());
203 Bflush(&bso);
204 seek(cout, 0L, 0);
205 switch(HEADTYPE) {
206 default:
207 case 2: /* plan9 */
208 magic = 4*26*26+7;
209 magic |= 0x00008000; /* fat header */
210 if(dlm)
211 magic |= 0x80000000; /* dlm */
212 lput(magic); /* magic */
213 lput(textsize); /* sizes */
214 lput(datsize);
215 lput(bsssize);
216 lput(symsize); /* nsyms */
217 vl = entryvalue();
218 lput(PADDR(vl)); /* va of entry */
219 lput(spsize); /* sp offsets */
220 lput(lcsize); /* line offsets */
221 llput(vl); /* va of entry */
222 break;
223 case 5:
224 elf32(debug['8']? I386: AMD64, ELFDATA2LSB, 0, nil);
225 break;
226 case 6:
227 elf64(AMD64, ELFDATA2LSB, 0, nil);
228 break;
229 }
230 cflush();
231 }
232
233 void
cflush(void)234 cflush(void)
235 {
236 int n;
237
238 n = sizeof(buf.cbuf) - cbc;
239 if(n)
240 write(cout, buf.cbuf, n);
241 cbp = buf.cbuf;
242 cbc = sizeof(buf.cbuf);
243 }
244
245 void
datblk(long s,long n)246 datblk(long s, long n)
247 {
248 Prog *p;
249 uchar *cast;
250 long l, fl, j;
251 vlong o;
252 int i, c;
253
254 memset(buf.dbuf, 0, n+Dbufslop);
255 for(p = datap; p != P; p = p->link) {
256 curp = p;
257 l = p->from.sym->value + p->from.offset - s;
258 c = p->from.scale;
259 i = 0;
260 if(l < 0) {
261 if(l+c <= 0)
262 continue;
263 while(l < 0) {
264 l++;
265 i++;
266 }
267 }
268 if(l >= n)
269 continue;
270 if(p->as != AINIT && p->as != ADYNT) {
271 for(j=l+(c-i)-1; j>=l; j--)
272 if(buf.dbuf[j]) {
273 print("%P\n", p);
274 diag("multiple initialization");
275 break;
276 }
277 }
278 switch(p->to.type) {
279 case D_FCONST:
280 switch(c) {
281 default:
282 case 4:
283 fl = ieeedtof(&p->to.ieee);
284 cast = (uchar*)&fl;
285 if(debug['a'] && i == 0) {
286 Bprint(&bso, pcstr, l+s+INITDAT);
287 for(j=0; j<c; j++)
288 Bprint(&bso, "%.2ux", cast[fnuxi4[j]]);
289 Bprint(&bso, "\t%P\n", curp);
290 }
291 for(; i<c; i++) {
292 buf.dbuf[l] = cast[fnuxi4[i]];
293 l++;
294 }
295 break;
296 case 8:
297 cast = (uchar*)&p->to.ieee;
298 if(debug['a'] && i == 0) {
299 Bprint(&bso, pcstr, l+s+INITDAT);
300 for(j=0; j<c; j++)
301 Bprint(&bso, "%.2ux", cast[fnuxi8[j]]);
302 Bprint(&bso, "\t%P\n", curp);
303 }
304 for(; i<c; i++) {
305 buf.dbuf[l] = cast[fnuxi8[i]];
306 l++;
307 }
308 break;
309 }
310 break;
311
312 case D_SCONST:
313 if(debug['a'] && i == 0) {
314 Bprint(&bso, pcstr, l+s+INITDAT);
315 for(j=0; j<c; j++)
316 Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff);
317 Bprint(&bso, "\t%P\n", curp);
318 }
319 for(; i<c; i++) {
320 buf.dbuf[l] = p->to.scon[i];
321 l++;
322 }
323 break;
324 default:
325 o = p->to.offset;
326 if(p->to.type == D_ADDR) {
327 if(p->to.index != D_STATIC && p->to.index != D_EXTERN)
328 diag("DADDR type%P", p);
329 if(p->to.sym) {
330 if(p->to.sym->type == SUNDEF)
331 ckoff(p->to.sym, o);
332 o += p->to.sym->value;
333 if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF)
334 o += INITDAT;
335 if(dlm)
336 dynreloc(p->to.sym, l+s+INITDAT, 1);
337 }
338 }
339 fl = o;
340 cast = (uchar*)&fl;
341 switch(c) {
342 default:
343 diag("bad nuxi %d %d\n%P", c, i, curp);
344 break;
345 case 1:
346 if(debug['a'] && i == 0) {
347 Bprint(&bso, pcstr, l+s+INITDAT);
348 for(j=0; j<c; j++)
349 Bprint(&bso, "%.2ux", cast[inuxi1[j]]);
350 Bprint(&bso, "\t%P\n", curp);
351 }
352 for(; i<c; i++) {
353 buf.dbuf[l] = cast[inuxi1[i]];
354 l++;
355 }
356 break;
357 case 2:
358 if(debug['a'] && i == 0) {
359 Bprint(&bso, pcstr, l+s+INITDAT);
360 for(j=0; j<c; j++)
361 Bprint(&bso, "%.2ux", cast[inuxi2[j]]);
362 Bprint(&bso, "\t%P\n", curp);
363 }
364 for(; i<c; i++) {
365 buf.dbuf[l] = cast[inuxi2[i]];
366 l++;
367 }
368 break;
369 case 4:
370 if(debug['a'] && i == 0) {
371 Bprint(&bso, pcstr, l+s+INITDAT);
372 for(j=0; j<c; j++)
373 Bprint(&bso, "%.2ux", cast[inuxi4[j]]);
374 Bprint(&bso, "\t%P\n", curp);
375 }
376 for(; i<c; i++) {
377 buf.dbuf[l] = cast[inuxi4[i]];
378 l++;
379 }
380 break;
381 case 8:
382 cast = (uchar*)&o;
383 if(debug['a'] && i == 0) {
384 Bprint(&bso, pcstr, l+s+INITDAT);
385 for(j=0; j<c; j++)
386 Bprint(&bso, "%.2ux", cast[inuxi8[j]]);
387 Bprint(&bso, "\t%P\n", curp);
388 }
389 for(; i<c; i++) {
390 buf.dbuf[l] = cast[inuxi8[i]];
391 l++;
392 }
393 break;
394 }
395 break;
396 }
397 }
398 write(cout, buf.dbuf, n);
399 }
400
401 vlong
rnd(vlong v,vlong r)402 rnd(vlong v, vlong r)
403 {
404 vlong c;
405
406 if(r <= 0)
407 return v;
408 v += r - 1;
409 c = v % r;
410 if(c < 0)
411 c += r;
412 v -= c;
413 return v;
414 }
415