1 #include "l.h" 2 3 #define Dbufslop 100 4 5 #define PADDR(a) ((ulong)(a) & ~0x80000000) 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 wputl(62); /* machine = AMD64 */ 234 lputl(1L); /* version = CURRENT */ 235 lputl(PADDR(entryvalue())); /* entry vaddr */ 236 lputl(52L); /* offset to first phdr */ 237 lputl(0L); /* offset to first shdr */ 238 lputl(0L); /* processor specific flags */ 239 wputl(52); /* Ehdr size */ 240 wputl(32); /* Phdr size */ 241 wputl(3); /* # of Phdrs */ 242 wputl(0); /* Shdr size */ 243 wputl(0); /* # of Shdrs */ 244 wputl(0); /* Shdr string size */ 245 246 lputl(1L); /* text - type = PT_LOAD */ 247 lputl(HEADR); /* file offset */ 248 lputl(INITTEXT); /* vaddr */ 249 lputl(PADDR(INITTEXT)); /* paddr */ 250 lputl(textsize); /* file size */ 251 lputl(textsize); /* memory size */ 252 lputl(0x05L); /* protections = RX */ 253 lputl(INITRND); /* alignment */ 254 255 lputl(1L); /* data - type = PT_LOAD */ 256 lputl(HEADR+textsize); /* file offset */ 257 lputl(INITDAT); /* vaddr */ 258 lputl(PADDR(INITDAT)); /* paddr */ 259 lputl(datsize); /* file size */ 260 lputl(datsize+bsssize); /* memory size */ 261 lputl(0x06L); /* protections = RW */ 262 lputl(INITRND); /* alignment */ 263 264 lputl(0L); /* data - type = PT_NULL */ 265 lputl(HEADR+textsize+datsize); /* file offset */ 266 lputl(0L); 267 lputl(0L); 268 lputl(symsize); /* symbol table size */ 269 lputl(lcsize); /* line number size */ 270 lputl(0x04L); /* protections = R */ 271 lputl(0x04L); /* alignment */ 272 break; 273 } 274 cflush(); 275 } 276 277 void 278 cflush(void) 279 { 280 int n; 281 282 n = sizeof(buf.cbuf) - cbc; 283 if(n) 284 write(cout, buf.cbuf, n); 285 cbp = buf.cbuf; 286 cbc = sizeof(buf.cbuf); 287 } 288 289 void 290 datblk(long s, long n) 291 { 292 Prog *p; 293 uchar *cast; 294 long l, fl, j; 295 vlong o; 296 int i, c; 297 298 memset(buf.dbuf, 0, n+Dbufslop); 299 for(p = datap; p != P; p = p->link) { 300 curp = p; 301 l = p->from.sym->value + p->from.offset - s; 302 c = p->from.scale; 303 i = 0; 304 if(l < 0) { 305 if(l+c <= 0) 306 continue; 307 while(l < 0) { 308 l++; 309 i++; 310 } 311 } 312 if(l >= n) 313 continue; 314 if(p->as != AINIT && p->as != ADYNT) { 315 for(j=l+(c-i)-1; j>=l; j--) 316 if(buf.dbuf[j]) { 317 print("%P\n", p); 318 diag("multiple initialization"); 319 break; 320 } 321 } 322 switch(p->to.type) { 323 case D_FCONST: 324 switch(c) { 325 default: 326 case 4: 327 fl = ieeedtof(&p->to.ieee); 328 cast = (uchar*)&fl; 329 if(debug['a'] && i == 0) { 330 Bprint(&bso, pcstr, l+s+INITDAT); 331 for(j=0; j<c; j++) 332 Bprint(&bso, "%.2ux", cast[fnuxi4[j]]); 333 Bprint(&bso, "\t%P\n", curp); 334 } 335 for(; i<c; i++) { 336 buf.dbuf[l] = cast[fnuxi4[i]]; 337 l++; 338 } 339 break; 340 case 8: 341 cast = (uchar*)&p->to.ieee; 342 if(debug['a'] && i == 0) { 343 Bprint(&bso, pcstr, l+s+INITDAT); 344 for(j=0; j<c; j++) 345 Bprint(&bso, "%.2ux", cast[fnuxi8[j]]); 346 Bprint(&bso, "\t%P\n", curp); 347 } 348 for(; i<c; i++) { 349 buf.dbuf[l] = cast[fnuxi8[i]]; 350 l++; 351 } 352 break; 353 } 354 break; 355 356 case D_SCONST: 357 if(debug['a'] && i == 0) { 358 Bprint(&bso, pcstr, l+s+INITDAT); 359 for(j=0; j<c; j++) 360 Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff); 361 Bprint(&bso, "\t%P\n", curp); 362 } 363 for(; i<c; i++) { 364 buf.dbuf[l] = p->to.scon[i]; 365 l++; 366 } 367 break; 368 default: 369 o = p->to.offset; 370 if(p->to.type == D_ADDR) { 371 if(p->to.index != D_STATIC && p->to.index != D_EXTERN) 372 diag("DADDR type%P", p); 373 if(p->to.sym) { 374 if(p->to.sym->type == SUNDEF) 375 ckoff(p->to.sym, o); 376 o += p->to.sym->value; 377 if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF) 378 o += INITDAT; 379 if(dlm) 380 dynreloc(p->to.sym, l+s+INITDAT, 1); 381 } 382 } 383 fl = o; 384 cast = (uchar*)&fl; 385 switch(c) { 386 default: 387 diag("bad nuxi %d %d\n%P", c, i, curp); 388 break; 389 case 1: 390 if(debug['a'] && i == 0) { 391 Bprint(&bso, pcstr, l+s+INITDAT); 392 for(j=0; j<c; j++) 393 Bprint(&bso, "%.2ux", cast[inuxi1[j]]); 394 Bprint(&bso, "\t%P\n", curp); 395 } 396 for(; i<c; i++) { 397 buf.dbuf[l] = cast[inuxi1[i]]; 398 l++; 399 } 400 break; 401 case 2: 402 if(debug['a'] && i == 0) { 403 Bprint(&bso, pcstr, l+s+INITDAT); 404 for(j=0; j<c; j++) 405 Bprint(&bso, "%.2ux", cast[inuxi2[j]]); 406 Bprint(&bso, "\t%P\n", curp); 407 } 408 for(; i<c; i++) { 409 buf.dbuf[l] = cast[inuxi2[i]]; 410 l++; 411 } 412 break; 413 case 4: 414 if(debug['a'] && i == 0) { 415 Bprint(&bso, pcstr, l+s+INITDAT); 416 for(j=0; j<c; j++) 417 Bprint(&bso, "%.2ux", cast[inuxi4[j]]); 418 Bprint(&bso, "\t%P\n", curp); 419 } 420 for(; i<c; i++) { 421 buf.dbuf[l] = cast[inuxi4[i]]; 422 l++; 423 } 424 break; 425 case 8: 426 cast = (uchar*)&o; 427 if(debug['a'] && i == 0) { 428 Bprint(&bso, pcstr, l+s+INITDAT); 429 for(j=0; j<c; j++) 430 Bprint(&bso, "%.2ux", cast[inuxi8[j]]); 431 Bprint(&bso, "\t%P\n", curp); 432 } 433 for(; i<c; i++) { 434 buf.dbuf[l] = cast[inuxi8[i]]; 435 l++; 436 } 437 break; 438 } 439 break; 440 } 441 } 442 write(cout, buf.dbuf, n); 443 } 444 445 vlong 446 rnd(vlong v, vlong r) 447 { 448 vlong c; 449 450 if(r <= 0) 451 return v; 452 v += r - 1; 453 c = v % r; 454 if(c < 0) 455 c += r; 456 v -= c; 457 return v; 458 } 459