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