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 void 32 wputl(ushort w) 33 { 34 cput(w); 35 cput(w>>8); 36 } 37 38 void 39 wput(ushort 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 strnput(char *s, int n) 72 { 73 for(; *s && n > 0; s++){ 74 cput(*s); 75 n--; 76 } 77 while(n > 0){ 78 cput(0); 79 n--; 80 } 81 } 82 83 void 84 asmb(void) 85 { 86 Prog *p; 87 long v, magic; 88 int a; 89 uchar *op1; 90 vlong vl; 91 92 if(debug['v']) 93 Bprint(&bso, "%5.2f asmb\n", cputime()); 94 Bflush(&bso); 95 96 seek(cout, HEADR, 0); 97 pc = INITTEXT; 98 curp = firstp; 99 for(p = firstp; p != P; p = p->link) { 100 if(p->as == ATEXT) 101 curtext = p; 102 if(p->pc != pc) { 103 if(!debug['a']) 104 print("%P\n", curp); 105 diag("phase error %llux sb %llux in %s", p->pc, pc, TNAME); 106 pc = p->pc; 107 } 108 curp = p; 109 asmins(p); 110 a = (andptr - and); 111 if(cbc < a) 112 cflush(); 113 if(debug['a']) { 114 Bprint(&bso, pcstr, pc); 115 for(op1 = and; op1 < andptr; op1++) 116 Bprint(&bso, "%.2ux", *op1 & 0xff); 117 Bprint(&bso, "\t%P\n", curp); 118 } 119 if(dlm) { 120 if(p->as == ATEXT) 121 reloca = nil; 122 else if(reloca != nil) 123 diag("reloc failure: %P", curp); 124 } 125 memmove(cbp, and, a); 126 cbp += a; 127 pc += a; 128 cbc -= a; 129 } 130 cflush(); 131 switch(HEADTYPE) { 132 default: 133 diag("unknown header type %ld", HEADTYPE); 134 case 2: 135 case 5: 136 seek(cout, HEADR+textsize, 0); 137 break; 138 } 139 140 if(debug['v']) 141 Bprint(&bso, "%5.2f datblk\n", cputime()); 142 Bflush(&bso); 143 144 if(dlm){ 145 char buf[8]; 146 147 write(cout, buf, INITDAT-textsize); 148 textsize = INITDAT; 149 } 150 151 for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) { 152 if(datsize-v > sizeof(buf)-Dbufslop) 153 datblk(v, sizeof(buf)-Dbufslop); 154 else 155 datblk(v, datsize-v); 156 } 157 158 symsize = 0; 159 spsize = 0; 160 lcsize = 0; 161 if(!debug['s']) { 162 if(debug['v']) 163 Bprint(&bso, "%5.2f sym\n", cputime()); 164 Bflush(&bso); 165 switch(HEADTYPE) { 166 default: 167 case 2: 168 case 5: 169 seek(cout, HEADR+textsize+datsize, 0); 170 break; 171 } 172 if(!debug['s']) 173 asmsym(); 174 if(debug['v']) 175 Bprint(&bso, "%5.2f sp\n", cputime()); 176 Bflush(&bso); 177 if(debug['v']) 178 Bprint(&bso, "%5.2f pc\n", cputime()); 179 Bflush(&bso); 180 if(!debug['s']) 181 asmlc(); 182 if(dlm) 183 asmdyn(); 184 cflush(); 185 } 186 else if(dlm){ 187 seek(cout, HEADR+textsize+datsize, 0); 188 asmdyn(); 189 cflush(); 190 } 191 if(debug['v']) 192 Bprint(&bso, "%5.2f headr\n", cputime()); 193 Bflush(&bso); 194 seek(cout, 0L, 0); 195 switch(HEADTYPE) { 196 default: 197 case 2: /* plan9 */ 198 magic = 4*26*26+7; 199 magic |= 0x00008000; /* fat header */ 200 if(dlm) 201 magic |= 0x80000000; /* dlm */ 202 lput(magic); /* magic */ 203 lput(textsize); /* sizes */ 204 lput(datsize); 205 lput(bsssize); 206 lput(symsize); /* nsyms */ 207 vl = entryvalue(); 208 lput(PADDR(vl)); /* va of entry */ 209 lput(spsize); /* sp offsets */ 210 lput(lcsize); /* line offsets */ 211 llput(vl); /* va of entry */ 212 break; 213 case 3: /* plan9 */ 214 magic = 4*26*26+7; 215 if(dlm) 216 magic |= 0x80000000; 217 lput(magic); /* magic */ 218 lput(textsize); /* sizes */ 219 lput(datsize); 220 lput(bsssize); 221 lput(symsize); /* nsyms */ 222 lput(entryvalue()); /* va of entry */ 223 lput(spsize); /* sp offsets */ 224 lput(lcsize); /* line offsets */ 225 break; 226 case 5: 227 strnput("\177ELF", 4); /* e_ident */ 228 cput(1); /* class = 32 bit */ 229 cput(1); /* data = LSB */ 230 cput(1); /* version = CURRENT */ 231 strnput("", 9); 232 wputl(2); /* type = EXEC */ 233 if(debug['8']) 234 wputl(3); /* machine = 386 */ 235 else 236 wputl(62); /* machine = AMD64 */ 237 lputl(1L); /* version = CURRENT */ 238 lputl(PADDR(entryvalue())); /* entry vaddr */ 239 lputl(52L); /* offset to first phdr */ 240 lputl(0L); /* offset to first shdr */ 241 lputl(0L); /* processor specific flags */ 242 wputl(52); /* Ehdr size */ 243 wputl(32); /* Phdr size */ 244 wputl(3); /* # of Phdrs */ 245 wputl(0); /* Shdr size */ 246 wputl(0); /* # of Shdrs */ 247 wputl(0); /* Shdr string size */ 248 249 lputl(1L); /* text - type = PT_LOAD */ 250 lputl(HEADR); /* file offset */ 251 lputl(INITTEXT); /* vaddr */ 252 lputl(PADDR(INITTEXT)); /* paddr */ 253 lputl(textsize); /* file size */ 254 lputl(textsize); /* memory size */ 255 lputl(0x05L); /* protections = RX */ 256 lputl(INITRND); /* alignment */ 257 258 lputl(1L); /* data - type = PT_LOAD */ 259 lputl(HEADR+textsize); /* file offset */ 260 lputl(INITDAT); /* vaddr */ 261 lputl(PADDR(INITDAT)); /* paddr */ 262 lputl(datsize); /* file size */ 263 lputl(datsize+bsssize); /* memory size */ 264 lputl(0x06L); /* protections = RW */ 265 lputl(INITRND); /* alignment */ 266 267 lputl(0L); /* symbols - type = PT_NULL */ 268 lputl(HEADR+textsize+datsize); /* file offset */ 269 lputl(0L); 270 lputl(0L); 271 lputl(symsize); /* symbol table size */ 272 lputl(lcsize); /* line number size */ 273 lputl(0x04L); /* protections = R */ 274 lputl(0x04L); /* alignment */ 275 break; 276 } 277 cflush(); 278 } 279 280 void 281 cflush(void) 282 { 283 int n; 284 285 n = sizeof(buf.cbuf) - cbc; 286 if(n) 287 write(cout, buf.cbuf, n); 288 cbp = buf.cbuf; 289 cbc = sizeof(buf.cbuf); 290 } 291 292 void 293 datblk(long s, long n) 294 { 295 Prog *p; 296 uchar *cast; 297 long l, fl, j; 298 vlong o; 299 int i, c; 300 301 memset(buf.dbuf, 0, n+Dbufslop); 302 for(p = datap; p != P; p = p->link) { 303 curp = p; 304 l = p->from.sym->value + p->from.offset - s; 305 c = p->from.scale; 306 i = 0; 307 if(l < 0) { 308 if(l+c <= 0) 309 continue; 310 while(l < 0) { 311 l++; 312 i++; 313 } 314 } 315 if(l >= n) 316 continue; 317 if(p->as != AINIT && p->as != ADYNT) { 318 for(j=l+(c-i)-1; j>=l; j--) 319 if(buf.dbuf[j]) { 320 print("%P\n", p); 321 diag("multiple initialization"); 322 break; 323 } 324 } 325 switch(p->to.type) { 326 case D_FCONST: 327 switch(c) { 328 default: 329 case 4: 330 fl = ieeedtof(&p->to.ieee); 331 cast = (uchar*)&fl; 332 if(debug['a'] && i == 0) { 333 Bprint(&bso, pcstr, l+s+INITDAT); 334 for(j=0; j<c; j++) 335 Bprint(&bso, "%.2ux", cast[fnuxi4[j]]); 336 Bprint(&bso, "\t%P\n", curp); 337 } 338 for(; i<c; i++) { 339 buf.dbuf[l] = cast[fnuxi4[i]]; 340 l++; 341 } 342 break; 343 case 8: 344 cast = (uchar*)&p->to.ieee; 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[fnuxi8[j]]); 349 Bprint(&bso, "\t%P\n", curp); 350 } 351 for(; i<c; i++) { 352 buf.dbuf[l] = cast[fnuxi8[i]]; 353 l++; 354 } 355 break; 356 } 357 break; 358 359 case D_SCONST: 360 if(debug['a'] && i == 0) { 361 Bprint(&bso, pcstr, l+s+INITDAT); 362 for(j=0; j<c; j++) 363 Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff); 364 Bprint(&bso, "\t%P\n", curp); 365 } 366 for(; i<c; i++) { 367 buf.dbuf[l] = p->to.scon[i]; 368 l++; 369 } 370 break; 371 default: 372 o = p->to.offset; 373 if(p->to.type == D_ADDR) { 374 if(p->to.index != D_STATIC && p->to.index != D_EXTERN) 375 diag("DADDR type%P", p); 376 if(p->to.sym) { 377 if(p->to.sym->type == SUNDEF) 378 ckoff(p->to.sym, o); 379 o += p->to.sym->value; 380 if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF) 381 o += INITDAT; 382 if(dlm) 383 dynreloc(p->to.sym, l+s+INITDAT, 1); 384 } 385 } 386 fl = o; 387 cast = (uchar*)&fl; 388 switch(c) { 389 default: 390 diag("bad nuxi %d %d\n%P", c, i, curp); 391 break; 392 case 1: 393 if(debug['a'] && i == 0) { 394 Bprint(&bso, pcstr, l+s+INITDAT); 395 for(j=0; j<c; j++) 396 Bprint(&bso, "%.2ux", cast[inuxi1[j]]); 397 Bprint(&bso, "\t%P\n", curp); 398 } 399 for(; i<c; i++) { 400 buf.dbuf[l] = cast[inuxi1[i]]; 401 l++; 402 } 403 break; 404 case 2: 405 if(debug['a'] && i == 0) { 406 Bprint(&bso, pcstr, l+s+INITDAT); 407 for(j=0; j<c; j++) 408 Bprint(&bso, "%.2ux", cast[inuxi2[j]]); 409 Bprint(&bso, "\t%P\n", curp); 410 } 411 for(; i<c; i++) { 412 buf.dbuf[l] = cast[inuxi2[i]]; 413 l++; 414 } 415 break; 416 case 4: 417 if(debug['a'] && i == 0) { 418 Bprint(&bso, pcstr, l+s+INITDAT); 419 for(j=0; j<c; j++) 420 Bprint(&bso, "%.2ux", cast[inuxi4[j]]); 421 Bprint(&bso, "\t%P\n", curp); 422 } 423 for(; i<c; i++) { 424 buf.dbuf[l] = cast[inuxi4[i]]; 425 l++; 426 } 427 break; 428 case 8: 429 cast = (uchar*)&o; 430 if(debug['a'] && i == 0) { 431 Bprint(&bso, pcstr, l+s+INITDAT); 432 for(j=0; j<c; j++) 433 Bprint(&bso, "%.2ux", cast[inuxi8[j]]); 434 Bprint(&bso, "\t%P\n", curp); 435 } 436 for(; i<c; i++) { 437 buf.dbuf[l] = cast[inuxi8[i]]; 438 l++; 439 } 440 break; 441 } 442 break; 443 } 444 } 445 write(cout, buf.dbuf, n); 446 } 447 448 vlong 449 rnd(vlong v, vlong r) 450 { 451 vlong c; 452 453 if(r <= 0) 454 return v; 455 v += r - 1; 456 c = v % r; 457 if(c < 0) 458 c += r; 459 v -= c; 460 return v; 461 } 462