1 #include "l.h" 2 3 #define Dbufslop 100 4 5 #define PADDR(a) ((a) & ~0xfffffffff0000000ull) 6 7 vlong 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 32 wputl(long w) 33 { 34 cput(w); 35 cput(w>>8); 36 } 37 38 void 39 wput(long w) 40 { 41 cput(w>>8); 42 cput(w); 43 } 44 45 void 46 lput(long l) 47 { 48 cput(l>>24); 49 cput(l>>16); 50 cput(l>>8); 51 cput(l); 52 } 53 54 void 55 llput(vlong v) 56 { 57 lput(v>>32); 58 lput(v); 59 } 60 61 void 62 lputl(long l) 63 { 64 cput(l); 65 cput(l>>8); 66 cput(l>>16); 67 cput(l>>24); 68 } 69 70 void 71 llputl(vlong v) 72 { 73 lputl(v); 74 lputl(v>>32); 75 } 76 77 void 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 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 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 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 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