Changeset 589
- Timestamp:
- 07/27/10 01:20:32 (14 years ago)
- Files:
-
- branches/dmd-1.x/src/backend/cod2.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/cod3.c (modified) (3 diffs)
- branches/dmd-1.x/src/backend/elfobj.c (modified) (3 diffs)
- trunk/src/backend/cod2.c (modified) (1 diff)
- trunk/src/backend/cod3.c (modified) (3 diffs)
- trunk/src/backend/elfobj.c (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/dmd-1.x/src/backend/cod2.c
r581 r589 3851 3851 case FLdata: 3852 3852 case FLudata: 3853 3853 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 3854 3854 case FLgot: 3855 3855 case FLgotoff: 3856 3856 #endif 3857 3857 case FLcsdata: 3858 3858 L4: 3859 3859 cs.IEVsym2 = e->EV.sp.Vsym; 3860 3860 cs.IEVoffset2 = e->EV.sp.Voffset; 3861 3861 L3: 3862 3862 if (reg == STACK) 3863 3863 { stackchanged = 1; 3864 3864 cs.Iop = 0x68; /* PUSH immed16 */ 3865 3865 c = genadjesp(NULL,REGSIZE); 3866 3866 } 3867 3867 else 3868 3868 { cs.Iop = 0xB8 + (reg & 7); // MOV reg,immed16 3869 3869 if (reg & 8) 3870 3870 cs.Irex |= REX_B; 3871 if (I64 && config.flags3 & CFG3pic) 3872 { // LEA reg,immed32[RIP] 3873 cs.Irex |= REX_W; 3874 cs.Iop = 0x8D; 3875 cs.Irm = modregrm(0,reg & 7,5); 3876 cs.IFL1 = fl; 3877 cs.IEVsym1 = cs.IEVsym2; 3878 cs.IEVoffset1 = cs.IEVoffset2; 3879 } 3871 3880 c = NULL; 3872 3881 } 3873 3882 cs.Iflags = CFoff; /* want offset only */ 3874 3883 cs.IFL2 = fl; 3875 3884 c = gen(c,&cs); 3876 3885 break; 3877 3886 3878 3887 #if 0 && TARGET_LINUX 3879 3888 case FLgot: 3880 3889 case FLgotoff: 3881 3890 { 3882 3891 gotref = 1; 3883 3892 symbol *s = e->EV.sp.Vsym; 3884 3893 // When using 8B (MOV), indicating that rm is used 3885 3894 // rm operands are always placed in IEV1 not IEV2 3886 3895 cs.IEVsym1 = s; 3887 3896 cs.IEVoffset1 = e->EV.sp.Voffset; 3888 3897 cs.Irm = modregrm(2,reg,BX); // reg,disp32[EBX] 3889 3898 cs.IFL1 = fl; 3890 3899 cs.Iop = (fl == FLgotoff) branches/dmd-1.x/src/backend/cod3.c
r583 r589 3308 3308 case 5: rm = modregrm(3,0,DI); goto L6; 3309 3309 case 7: rm = modregrm(3,0,BX); goto L6; 3310 3310 L6: c->Irm = rm + reg; 3311 3311 c->Iop = 0x8B; 3312 3312 break; 3313 3313 } 3314 3314 } 3315 3315 } 3316 3316 3317 3317 /* replace LEA reg,0[BP] with MOV reg,BP */ 3318 3318 else if (mod == modregrm(1,0,0) && rm == local_BPRM && 3319 3319 c->IFL1 == FLconst && c->IEVpointer1 == 0) 3320 3320 { c->Iop = 0x8B; /* MOV reg,BP */ 3321 3321 c->Irm = modregrm(3,0,BP) + reg; 3322 3322 } 3323 3323 } 3324 3324 3325 3325 // Replace [R13] with 0[R13] 3326 3326 if (c->Irex & REX_B && (c->Irm & modregrm(3,0,5)) == modregrm(0,0,5)) 3327 3327 { 3328 printf("test1\n");3329 3328 c->Irm |= modregrm(1,0,0); 3330 3329 c->IFL1 = FLconst; 3331 3330 c->IEVpointer1 = 0; 3332 3331 } 3333 3332 } 3334 3333 else 3335 3334 { 3336 3335 switch (op) 3337 3336 { 3338 3337 default: 3339 3338 if ((op & 0xF0) != 0x70) 3340 3339 break; 3341 3340 case JMP: 3342 3341 switch (c->IFL2) 3343 3342 { case FLcode: 3344 3343 if (c->IEV2.Vcode == code_next(c)) 3345 3344 { c->Iop = NOP; 3346 3345 continue; 3347 3346 } 3348 3347 break; … … 3691 3690 break; 3692 3691 case 0x40: 3693 3692 size++; /* disp8 */ 3694 3693 break; 3695 3694 case 0x80: 3696 3695 size += 4; /* disp32 */ 3697 3696 break; 3698 3697 } 3699 3698 } 3700 3699 else 3701 3700 { // 16 bit addressing 3702 3701 if (mod == 0x40) /* 01: 8 bit displacement */ 3703 3702 size++; 3704 3703 else if (mod == 0x80 || (mod == 0 && (rm & 7) == 6)) 3705 3704 size += 2; 3706 3705 } 3707 3706 } 3708 3707 3709 3708 Lret: 3710 3709 if (c->Irex) 3711 size++; 3710 { size++; 3711 if (c->Irex & REX_W && (op & 0xF8) == 0xB8) 3712 size += 4; 3713 } 3712 3714 Lret2: 3713 3715 //printf("op = x%02x, size = %d\n",op,size); 3714 3716 return size; 3715 3717 } 3716 3718 3717 3719 /******************************** 3718 3720 * Return !=0 if codes match. 3719 3721 */ 3720 3722 3721 3723 #if 0 3722 3724 3723 3725 int code_match(code *c1,code *c2) 3724 3726 { code cs1,cs2; 3725 3727 unsigned char ins; 3726 3728 3727 3729 if (c1 == c2) 3728 3730 goto match; 3729 3731 cs1 = *c1; 3730 3732 cs2 = *c2; 3731 3733 if (cs1.Iop != cs2.Iop) … … 4026 4028 if (op == 0xC8) 4027 4029 do16bit((enum FL)c->IFL1,&c->IEV1,0); 4028 4030 } 4029 4031 flags &= CFseg | CFoff | CFselfrel; 4030 4032 if (ins & T) /* if second operand */ 4031 4033 { if (ins & E) /* if data-8 */ 4032 4034 do8bit((enum FL) c->IFL2,&c->IEV2); 4033 4035 else if (!I16) 4034 4036 { 4035 4037 switch (op) 4036 4038 { case 0xC2: /* RETN imm16 */ 4037 4039 case 0xCA: /* RETF imm16 */ 4038 4040 do16: 4039 4041 do16bit((enum FL)c->IFL2,&c->IEV2,flags); 4040 4042 break; 4041 4043 4042 4044 case 0xA1: 4043 4045 case 0xA3: 4044 4046 if (I64 && c->Irex) 4045 4047 { 4048 do64: 4046 4049 do64bit((enum FL)c->IFL2,&c->IEV2,flags); 4047 4050 break; 4048 4051 } 4049 4052 case 0xA0: /* MOV AL,byte ptr [] */ 4050 4053 case 0xA2: 4051 4054 if (c->Iflags & CFaddrsize && !I64) 4052 4055 goto do16; 4053 4056 else 4054 4057 do32: 4055 4058 do32bit((enum FL)c->IFL2,&c->IEV2,flags); 4056 4059 break; 4057 4060 case 0x9A: 4058 4061 case 0xEA: 4059 4062 if (c->Iflags & CFopsize) 4060 4063 goto ptr1616; 4061 4064 else 4062 4065 goto ptr1632; 4063 4066 4064 4067 case 0x68: // PUSH immed32 4065 4068 if ((enum FL)c->IFL2 == FLblock) 4066 4069 { 4067 4070 c->IFL2 = FLblockoff; 4068 4071 goto do32; 4069 4072 } 4070 4073 else 4071 4074 goto case_default; 4072 4075 4073 4076 case 0xE8: // CALL rel 4074 4077 case 0xE9: // JMP rel 4075 4078 flags |= CFselfrel; 4079 goto case_default; 4080 4076 4081 default: 4082 if (I64 && (op & 0xF8) == 0xB8 && c->Irex & REX_W) 4083 goto do64; 4077 4084 case_default: 4078 4085 if (c->Iflags & CFopsize) 4079 4086 goto do16; 4080 4087 else 4081 4088 goto do32; 4082 4089 break; 4083 4090 } 4084 4091 } 4085 4092 else 4086 4093 { 4087 4094 switch (op) { 4088 4095 case 0xC2: 4089 4096 case 0xCA: 4090 4097 goto do16; 4091 4098 case 0xA0: 4092 4099 case 0xA1: 4093 4100 case 0xA2: 4094 4101 case 0xA3: 4095 4102 if (c->Iflags & CFaddrsize) 4096 4103 goto do32; branches/dmd-1.x/src/backend/elfobj.c
r582 r589 2316 2316 void reftodatseg(int seg,targ_size_t offset,targ_size_t val, 2317 2317 unsigned targetdatum,int flags) 2318 2318 { 2319 2319 Outbuffer *buf; 2320 2320 int save; 2321 2321 2322 2322 buf = SegData[seg]->SDbuf; 2323 2323 save = buf->size(); 2324 2324 buf->setsize(offset); 2325 2325 #if 0 2326 2326 printf("reftodatseg(seg=%d, offset=x%llx, val=x%llx,data %x, flags %x)\n", 2327 2327 seg,(unsigned long long)offset,(unsigned long long)val,targetdatum,flags); 2328 2328 #endif 2329 2329 /*if (OPT_IS_SET(OPTfwritable_strings)) 2330 2330 { 2331 2331 elf_addrel(seg,offset,RI_TYPE_SYM32,STI_DATA,0); 2332 2332 } 2333 2333 else*/ 2334 2334 { 2335 2335 int relinfo; 2336 targ_size_t v = 0; 2336 2337 2337 2338 if (I64) 2338 2339 { 2339 2340 if (MAP_SEG2TYP(seg) == CODE && config.flags3 & CFG3pic) 2340 relinfo = R_X86_64_PC32; 2341 { relinfo = R_X86_64_PC32; 2342 //v = -4L; 2343 } 2341 2344 else if (MAP_SEG2SEC(targetdatum)->sh_flags & SHF_TLS) 2342 2345 relinfo = config.flags3 & CFG3pic ? R_X86_64_TLSGD : R_X86_64_TPOFF32; 2343 2346 else 2344 2347 relinfo = R_X86_64_32; 2345 2348 } 2346 2349 else 2347 2350 { 2348 2351 if (MAP_SEG2TYP(seg) == CODE && config.flags3 & CFG3pic) 2349 2352 relinfo = RI_TYPE_GOTOFF; 2350 2353 else if (MAP_SEG2SEC(targetdatum)->sh_flags & SHF_TLS) 2351 2354 relinfo = config.flags3 & CFG3pic ? RI_TYPE_TLS_GD : RI_TYPE_TLS_LE; 2352 2355 else 2353 2356 relinfo = RI_TYPE_SYM32; 2354 2357 } 2355 2358 2356 elf_addrel(seg, offset, relinfo, STI_RODAT, 0);2359 elf_addrel(seg, offset, relinfo, STI_RODAT, v); 2357 2360 } 2358 2361 buf->write32(val); 2359 2362 if (save > offset + 4) 2360 2363 buf->setsize(save); 2361 2364 } 2362 2365 2363 2366 /******************************* 2364 2367 * Refer to address that is in the code segment. 2365 2368 * Only offsets are output, regardless of the memory model. 2366 2369 * Used to put values in switch address tables. 2367 2370 * Input: 2368 2371 * seg = where the address is going (CODE or DATA) 2369 2372 * offset = offset within seg 2370 2373 * val = displacement from start of this module 2371 2374 */ 2372 2375 2373 2376 void reftocodseg(int seg,targ_size_t offset,targ_size_t val) 2374 2377 { 2375 2378 Outbuffer *buf; 2376 2379 int save; 2377 2380 int segtyp = MAP_SEG2TYP(seg); 2378 2381 2379 2382 //dbg_printf("reftocodseg(seg=%d, offset=x%lx, val=x%lx )\n",seg,offset,val); 2380 2383 assert(seg > 0); // COMDATs not done yet 2381 2384 buf = SegData[seg]->SDbuf; 2382 2385 save = buf->size(); 2383 2386 buf->setsize(offset); 2384 2387 #if 0 2385 2388 if (segtyp == CODE) 2386 2389 { 2387 2390 val = val - funcsym_p->Soffset; 2388 2391 elf_addrel(seg,offset,RI_TYPE_PC32,funcsym_p->Sxtrnnum,0); 2389 2392 } 2390 2393 else 2391 2394 #endif 2392 2395 { 2393 2396 val = val - funcsym_p->Soffset; 2394 2397 int relinfo; 2398 targ_size_t v = 0; 2395 2399 if (I64) 2396 2400 relinfo = (config.flags3 & CFG3pic) ? R_X86_64_PC32 : R_X86_64_32; 2397 2401 else 2398 2402 relinfo = (config.flags3 & CFG3pic) ? RI_TYPE_GOTOFF : RI_TYPE_SYM32; 2399 elf_addrel(seg,offset, relinfo, funcsym_p->Sxtrnnum, 0);2403 elf_addrel(seg,offset, relinfo, funcsym_p->Sxtrnnum, v); 2400 2404 } 2401 2405 buf->write32(val); 2402 2406 if (save > offset + 4) 2403 2407 buf->setsize(save); 2404 2408 } 2405 2409 2406 2410 /******************************* 2407 2411 * Refer to an identifier. 2408 2412 * Input: 2409 2413 * segtyp = where the address is going (CODE or DATA) 2410 2414 * offset = offset within seg 2411 2415 * s -> Symbol table entry for identifier 2412 2416 * val = displacement from identifier 2413 2417 * flags = CFselfrel: self-relative 2414 2418 * CFseg: get segment 2415 2419 * CFoff: get offset 2416 2420 * CFoffset64: 64 bit fixup 2417 2421 * Returns: 2418 2422 * number of bytes in reference (4 or 8) 2419 2423 */ 2420 2424 2421 2425 int reftoident(int seg, targ_size_t offset, Symbol *s, targ_size_t val, 2422 2426 int flags) 2423 2427 { 2424 2428 tym_t ty; 2425 2429 bool external = TRUE; 2426 2430 Outbuffer *buf; 2427 2431 elf_u32_f32 relinfo,refseg; 2428 2432 int segtyp = MAP_SEG2TYP(seg); 2429 2433 //assert(val == 0); 2430 2434 int retsize = (flags & CFoffset64) ? 8 : 4; 2435 targ_size_t v = 0; 2431 2436 2432 2437 #if 0 2433 2438 printf("\nreftoident('%s' seg %d, offset x%llx, val x%llx, flags x%x)\n", 2434 2439 s->Sident,seg,offset,val,flags); 2435 2440 dbg_printf("Sseg = %d, Sxtrnnum = %d, retsize = %d\n",s->Sseg,s->Sxtrnnum,retsize); 2436 2441 symbol_print(s); 2437 2442 #endif 2438 2443 2439 2444 ty = s->ty(); 2440 2445 if (s->Sxtrnnum) 2441 2446 { // identifier is defined somewhere else 2442 2447 if (I64) 2443 2448 { 2444 2449 if (SymbolTable64[s->Sxtrnnum].st_shndx != SHT_UNDEF) 2445 2450 external = FALSE; 2446 2451 } 2447 2452 else 2448 2453 { 2449 2454 if (SymbolTable[s->Sxtrnnum].st_shndx != SHT_UNDEF) 2450 2455 external = FALSE; 2451 2456 } 2452 2457 } 2453 2458 2454 2459 switch (s->Sclass) 2455 2460 { 2456 2461 case SClocstat: 2457 2462 buf = SegData[seg]->SDbuf; 2458 2463 if (I64) 2459 2464 { 2460 2465 if (s->Sfl == FLtlsdata) 2461 2466 relinfo = config.flags3 & CFG3pic ? R_X86_64_TLSGD : R_X86_64_TPOFF32; 2462 2467 else 2463 relinfo = config.flags3 & CFG3pic ? R_X86_64_PC32 : R_X86_64_32; 2468 { relinfo = config.flags3 & CFG3pic ? R_X86_64_PC32 : R_X86_64_32; 2469 if (config.flags3 & CFG3pic) 2470 v = -4L; 2471 } 2464 2472 } 2465 2473 else 2466 2474 { 2467 2475 if (s->Sfl == FLtlsdata) 2468 2476 relinfo = config.flags3 & CFG3pic ? RI_TYPE_TLS_GD : RI_TYPE_TLS_LE; 2469 2477 else 2470 2478 relinfo = config.flags3 & CFG3pic ? RI_TYPE_GOTOFF : RI_TYPE_SYM32; 2471 2479 } 2472 2480 if (flags & CFoffset64 && relinfo == R_X86_64_32) 2473 2481 { 2474 2482 relinfo = R_X86_64_64; 2475 2483 } 2476 elf_addrel(seg,offset,relinfo,STI_RODAT, 0);2484 elf_addrel(seg,offset,relinfo,STI_RODAT,v); 2477 2485 if (retsize == 8) 2478 2486 buf->write64(val + s->Soffset); 2479 2487 else 2480 2488 buf->write32(val + s->Soffset); 2481 2489 break; 2482 2490 2483 2491 case SCcomdat: 2484 2492 case_SCcomdat: 2485 2493 case SCstatic: 2486 2494 #if 0 2487 2495 if ((s->Sflags & SFLthunk) && s->Soffset) 2488 2496 { // A thunk symbol that has be defined 2489 2497 assert(s->Sseg == seg); 2490 2498 val = (s->Soffset+val) - (offset+4); 2491 2499 goto outaddrval; 2492 2500 } 2493 2501 // FALL_THROUGH 2494 2502 #endif 2495 2503 2496 2504 case SCextern: … … 2596 2604 { 2597 2605 if (s->Sclass == SCstatic) 2598 2606 relinfo = RI_TYPE_TLS_LE; // TLS_GD? 2599 2607 else 2600 2608 relinfo = RI_TYPE_TLS_IE; 2601 2609 } 2602 2610 else 2603 2611 { 2604 2612 if (s->Sclass == SCstatic) 2605 2613 relinfo = RI_TYPE_TLS_LE; 2606 2614 else 2607 2615 relinfo = RI_TYPE_TLS_IE; 2608 2616 } 2609 2617 } 2610 2618 } 2611 2619 if (flags & CFoffset64 && relinfo == R_X86_64_32) 2612 2620 { 2613 2621 relinfo = R_X86_64_64; 2614 2622 } 2615 2623 //printf("\t\t************* adding relocation\n"); 2616 elf_addrel(seg,offset,relinfo,refseg,0); 2624 targ_size_t v = (relinfo == R_X86_64_PC32) ? -4 : 0; 2625 elf_addrel(seg,offset,relinfo,refseg,v); 2617 2626 } 2618 2627 outaddrval: 2619 2628 if (retsize == 8) 2620 2629 buf->write64(val); 2621 2630 else 2622 2631 buf->write32(val); 2623 2632 if (save > offset + retsize) 2624 2633 buf->setsize(save); 2625 2634 } 2626 2635 break; 2627 2636 2628 2637 case SCsinline: 2629 2638 case SCeinline: 2630 2639 printf ("Undefined inline value <<fixme>>\n"); 2631 2640 //warerr(WM_undefined_inline,s->Sident); 2632 2641 case SCinline: 2633 2642 if (tyfunc(ty)) 2634 2643 { 2635 2644 s->Sclass = SCextern; 2636 2645 goto case_extern; … … 2770 2779 * mov [ECX],EAX 2771 2780 * popad 2772 2781 * ret 2773 2782 */ 2774 2783 2775 2784 const int reltype = I64 ? R_X86_64_32 : RI_TYPE_SYM32; 2776 2785 const int refsize = 4; // use 32 bit relocations, even in 64 bit mode 2777 2786 2778 2787 const int seg = CODE; 2779 2788 Outbuffer *buf = SegData[seg]->SDbuf; 2780 2789 SegData[seg]->SDoffset = buf->size(); 2781 2790 codeOffset = SegData[seg]->SDoffset + 1; 2782 2791 buf->writeByte(0xC3); /* ret */ 2783 2792 2784 2793 int off = 0; 2785 2794 if (I32) 2786 2795 { buf->writeByte(0x60); // PUSHAD 2787 2796 off = 1; 2788 2797 } 2789 2798 2790 /* movl ModuleReference*, %eax */ 2791 buf->writeByte(0xB8); 2792 buf->write32(refOffset); 2793 elf_addrel(seg, codeOffset + off + 1, reltype, STI_DATA, 0); 2794 2795 /* movl _Dmodule_ref, %ecx */ 2796 buf->writeByte(0xB9); 2797 buf->write32(0); 2798 elf_addrel(seg, codeOffset + off + 6, reltype, objextern("_Dmodule_ref"), 0); 2799 if (I64 && config.flags3 & CFG3pic) 2800 { // LEA RAX,ModuleReference[RIP] 2801 buf->writeByte(REX | REX_W); 2802 buf->writeByte(0x8D); 2803 buf->writeByte(modregrm(0,AX,5)); 2804 buf->write32(refOffset); 2805 elf_addrel(seg, codeOffset + off + 3, R_X86_64_PC32, STI_DATA, -4); 2806 2807 // LEA RCX,_DmoduleRef[RIP] 2808 buf->writeByte(REX | REX_W); 2809 buf->writeByte(0x8D); 2810 buf->writeByte(modregrm(0,CX,5)); 2811 buf->write32(0); 2812 elf_addrel(seg, codeOffset + off + 10, R_X86_64_PC32, objextern("_Dmodule_ref"), -4); 2813 } 2814 else 2815 { 2816 /* movl ModuleReference*, %eax */ 2817 buf->writeByte(0xB8); 2818 buf->write32(refOffset); 2819 elf_addrel(seg, codeOffset + off + 1, reltype, STI_DATA, 0); 2820 2821 /* movl _Dmodule_ref, %ecx */ 2822 buf->writeByte(0xB9); 2823 buf->write32(0); 2824 elf_addrel(seg, codeOffset + off + 6, reltype, objextern("_Dmodule_ref"), 0); 2825 } 2799 2826 2800 2827 buf->writeByte(0x8B); buf->writeByte(0x11); /* movl (%ecx), %edx */ 2801 2828 buf->writeByte(0x89); buf->writeByte(0x10); /* movl %edx, (%eax) */ 2802 2829 buf->writeByte(0x89); buf->writeByte(0x01); /* movl %eax, (%ecx) */ 2803 2830 2804 2831 if (I32) buf->writeByte(0x61); // POPAD 2805 2832 buf->writeByte(0xC3); /* ret */ 2806 2833 SegData[seg]->SDoffset = buf->size(); 2807 2834 } 2808 2835 2809 2836 /* Add reference to constructor into ".ctors" segment 2810 2837 */ 2811 2838 const int seg = elf_getsegment(".ctors", NULL, SHT_PROGDEF, SHF_ALLOC|SHF_WRITE, NPTRSIZE); 2812 2839 2813 2840 Outbuffer *buf = SegData[seg]->SDbuf; 2814 2841 buf->write32(codeOffset); 2815 2842 elf_addrel(seg, SegData[seg]->SDoffset, I64 ? R_X86_64_64 : RI_TYPE_SYM32, STI_TEXT, 0); 2816 2843 SegData[seg]->SDoffset += NPTRSIZE; 2817 2844 } 2818 2845 trunk/src/backend/cod2.c
r581 r589 3851 3851 case FLdata: 3852 3852 case FLudata: 3853 3853 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 3854 3854 case FLgot: 3855 3855 case FLgotoff: 3856 3856 #endif 3857 3857 case FLcsdata: 3858 3858 L4: 3859 3859 cs.IEVsym2 = e->EV.sp.Vsym; 3860 3860 cs.IEVoffset2 = e->EV.sp.Voffset; 3861 3861 L3: 3862 3862 if (reg == STACK) 3863 3863 { stackchanged = 1; 3864 3864 cs.Iop = 0x68; /* PUSH immed16 */ 3865 3865 c = genadjesp(NULL,REGSIZE); 3866 3866 } 3867 3867 else 3868 3868 { cs.Iop = 0xB8 + (reg & 7); // MOV reg,immed16 3869 3869 if (reg & 8) 3870 3870 cs.Irex |= REX_B; 3871 if (I64 && config.flags3 & CFG3pic) 3872 { // LEA reg,immed32[RIP] 3873 cs.Irex |= REX_W; 3874 cs.Iop = 0x8D; 3875 cs.Irm = modregrm(0,reg & 7,5); 3876 cs.IFL1 = fl; 3877 cs.IEVsym1 = cs.IEVsym2; 3878 cs.IEVoffset1 = cs.IEVoffset2; 3879 } 3871 3880 c = NULL; 3872 3881 } 3873 3882 cs.Iflags = CFoff; /* want offset only */ 3874 3883 cs.IFL2 = fl; 3875 3884 c = gen(c,&cs); 3876 3885 break; 3877 3886 3878 3887 #if 0 && TARGET_LINUX 3879 3888 case FLgot: 3880 3889 case FLgotoff: 3881 3890 { 3882 3891 gotref = 1; 3883 3892 symbol *s = e->EV.sp.Vsym; 3884 3893 // When using 8B (MOV), indicating that rm is used 3885 3894 // rm operands are always placed in IEV1 not IEV2 3886 3895 cs.IEVsym1 = s; 3887 3896 cs.IEVoffset1 = e->EV.sp.Voffset; 3888 3897 cs.Irm = modregrm(2,reg,BX); // reg,disp32[EBX] 3889 3898 cs.IFL1 = fl; 3890 3899 cs.Iop = (fl == FLgotoff) trunk/src/backend/cod3.c
r583 r589 3308 3308 case 5: rm = modregrm(3,0,DI); goto L6; 3309 3309 case 7: rm = modregrm(3,0,BX); goto L6; 3310 3310 L6: c->Irm = rm + reg; 3311 3311 c->Iop = 0x8B; 3312 3312 break; 3313 3313 } 3314 3314 } 3315 3315 } 3316 3316 3317 3317 /* replace LEA reg,0[BP] with MOV reg,BP */ 3318 3318 else if (mod == modregrm(1,0,0) && rm == local_BPRM && 3319 3319 c->IFL1 == FLconst && c->IEVpointer1 == 0) 3320 3320 { c->Iop = 0x8B; /* MOV reg,BP */ 3321 3321 c->Irm = modregrm(3,0,BP) + reg; 3322 3322 } 3323 3323 } 3324 3324 3325 3325 // Replace [R13] with 0[R13] 3326 3326 if (c->Irex & REX_B && (c->Irm & modregrm(3,0,5)) == modregrm(0,0,5)) 3327 3327 { 3328 printf("test1\n");3329 3328 c->Irm |= modregrm(1,0,0); 3330 3329 c->IFL1 = FLconst; 3331 3330 c->IEVpointer1 = 0; 3332 3331 } 3333 3332 } 3334 3333 else 3335 3334 { 3336 3335 switch (op) 3337 3336 { 3338 3337 default: 3339 3338 if ((op & 0xF0) != 0x70) 3340 3339 break; 3341 3340 case JMP: 3342 3341 switch (c->IFL2) 3343 3342 { case FLcode: 3344 3343 if (c->IEV2.Vcode == code_next(c)) 3345 3344 { c->Iop = NOP; 3346 3345 continue; 3347 3346 } 3348 3347 break; … … 3691 3690 break; 3692 3691 case 0x40: 3693 3692 size++; /* disp8 */ 3694 3693 break; 3695 3694 case 0x80: 3696 3695 size += 4; /* disp32 */ 3697 3696 break; 3698 3697 } 3699 3698 } 3700 3699 else 3701 3700 { // 16 bit addressing 3702 3701 if (mod == 0x40) /* 01: 8 bit displacement */ 3703 3702 size++; 3704 3703 else if (mod == 0x80 || (mod == 0 && (rm & 7) == 6)) 3705 3704 size += 2; 3706 3705 } 3707 3706 } 3708 3707 3709 3708 Lret: 3710 3709 if (c->Irex) 3711 size++; 3710 { size++; 3711 if (c->Irex & REX_W && (op & 0xF8) == 0xB8) 3712 size += 4; 3713 } 3712 3714 Lret2: 3713 3715 //printf("op = x%02x, size = %d\n",op,size); 3714 3716 return size; 3715 3717 } 3716 3718 3717 3719 /******************************** 3718 3720 * Return !=0 if codes match. 3719 3721 */ 3720 3722 3721 3723 #if 0 3722 3724 3723 3725 int code_match(code *c1,code *c2) 3724 3726 { code cs1,cs2; 3725 3727 unsigned char ins; 3726 3728 3727 3729 if (c1 == c2) 3728 3730 goto match; 3729 3731 cs1 = *c1; 3730 3732 cs2 = *c2; 3731 3733 if (cs1.Iop != cs2.Iop) … … 4026 4028 if (op == 0xC8) 4027 4029 do16bit((enum FL)c->IFL1,&c->IEV1,0); 4028 4030 } 4029 4031 flags &= CFseg | CFoff | CFselfrel; 4030 4032 if (ins & T) /* if second operand */ 4031 4033 { if (ins & E) /* if data-8 */ 4032 4034 do8bit((enum FL) c->IFL2,&c->IEV2); 4033 4035 else if (!I16) 4034 4036 { 4035 4037 switch (op) 4036 4038 { case 0xC2: /* RETN imm16 */ 4037 4039 case 0xCA: /* RETF imm16 */ 4038 4040 do16: 4039 4041 do16bit((enum FL)c->IFL2,&c->IEV2,flags); 4040 4042 break; 4041 4043 4042 4044 case 0xA1: 4043 4045 case 0xA3: 4044 4046 if (I64 && c->Irex) 4045 4047 { 4048 do64: 4046 4049 do64bit((enum FL)c->IFL2,&c->IEV2,flags); 4047 4050 break; 4048 4051 } 4049 4052 case 0xA0: /* MOV AL,byte ptr [] */ 4050 4053 case 0xA2: 4051 4054 if (c->Iflags & CFaddrsize && !I64) 4052 4055 goto do16; 4053 4056 else 4054 4057 do32: 4055 4058 do32bit((enum FL)c->IFL2,&c->IEV2,flags); 4056 4059 break; 4057 4060 case 0x9A: 4058 4061 case 0xEA: 4059 4062 if (c->Iflags & CFopsize) 4060 4063 goto ptr1616; 4061 4064 else 4062 4065 goto ptr1632; 4063 4066 4064 4067 case 0x68: // PUSH immed32 4065 4068 if ((enum FL)c->IFL2 == FLblock) 4066 4069 { 4067 4070 c->IFL2 = FLblockoff; 4068 4071 goto do32; 4069 4072 } 4070 4073 else 4071 4074 goto case_default; 4072 4075 4073 4076 case 0xE8: // CALL rel 4074 4077 case 0xE9: // JMP rel 4075 4078 flags |= CFselfrel; 4079 goto case_default; 4080 4076 4081 default: 4082 if (I64 && (op & 0xF8) == 0xB8 && c->Irex & REX_W) 4083 goto do64; 4077 4084 case_default: 4078 4085 if (c->Iflags & CFopsize) 4079 4086 goto do16; 4080 4087 else 4081 4088 goto do32; 4082 4089 break; 4083 4090 } 4084 4091 } 4085 4092 else 4086 4093 { 4087 4094 switch (op) { 4088 4095 case 0xC2: 4089 4096 case 0xCA: 4090 4097 goto do16; 4091 4098 case 0xA0: 4092 4099 case 0xA1: 4093 4100 case 0xA2: 4094 4101 case 0xA3: 4095 4102 if (c->Iflags & CFaddrsize) 4096 4103 goto do32; trunk/src/backend/elfobj.c
r582 r589 2316 2316 void reftodatseg(int seg,targ_size_t offset,targ_size_t val, 2317 2317 unsigned targetdatum,int flags) 2318 2318 { 2319 2319 Outbuffer *buf; 2320 2320 int save; 2321 2321 2322 2322 buf = SegData[seg]->SDbuf; 2323 2323 save = buf->size(); 2324 2324 buf->setsize(offset); 2325 2325 #if 0 2326 2326 printf("reftodatseg(seg=%d, offset=x%llx, val=x%llx,data %x, flags %x)\n", 2327 2327 seg,(unsigned long long)offset,(unsigned long long)val,targetdatum,flags); 2328 2328 #endif 2329 2329 /*if (OPT_IS_SET(OPTfwritable_strings)) 2330 2330 { 2331 2331 elf_addrel(seg,offset,RI_TYPE_SYM32,STI_DATA,0); 2332 2332 } 2333 2333 else*/ 2334 2334 { 2335 2335 int relinfo; 2336 targ_size_t v = 0; 2336 2337 2337 2338 if (I64) 2338 2339 { 2339 2340 if (MAP_SEG2TYP(seg) == CODE && config.flags3 & CFG3pic) 2340 relinfo = R_X86_64_PC32; 2341 { relinfo = R_X86_64_PC32; 2342 //v = -4L; 2343 } 2341 2344 else if (MAP_SEG2SEC(targetdatum)->sh_flags & SHF_TLS) 2342 2345 relinfo = config.flags3 & CFG3pic ? R_X86_64_TLSGD : R_X86_64_TPOFF32; 2343 2346 else 2344 2347 relinfo = R_X86_64_32; 2345 2348 } 2346 2349 else 2347 2350 { 2348 2351 if (MAP_SEG2TYP(seg) == CODE && config.flags3 & CFG3pic) 2349 2352 relinfo = RI_TYPE_GOTOFF; 2350 2353 else if (MAP_SEG2SEC(targetdatum)->sh_flags & SHF_TLS) 2351 2354 relinfo = config.flags3 & CFG3pic ? RI_TYPE_TLS_GD : RI_TYPE_TLS_LE; 2352 2355 else 2353 2356 relinfo = RI_TYPE_SYM32; 2354 2357 } 2355 2358 2356 elf_addrel(seg, offset, relinfo, STI_RODAT, 0);2359 elf_addrel(seg, offset, relinfo, STI_RODAT, v); 2357 2360 } 2358 2361 buf->write32(val); 2359 2362 if (save > offset + 4) 2360 2363 buf->setsize(save); 2361 2364 } 2362 2365 2363 2366 /******************************* 2364 2367 * Refer to address that is in the code segment. 2365 2368 * Only offsets are output, regardless of the memory model. 2366 2369 * Used to put values in switch address tables. 2367 2370 * Input: 2368 2371 * seg = where the address is going (CODE or DATA) 2369 2372 * offset = offset within seg 2370 2373 * val = displacement from start of this module 2371 2374 */ 2372 2375 2373 2376 void reftocodseg(int seg,targ_size_t offset,targ_size_t val) 2374 2377 { 2375 2378 Outbuffer *buf; 2376 2379 int save; 2377 2380 int segtyp = MAP_SEG2TYP(seg); 2378 2381 2379 2382 //dbg_printf("reftocodseg(seg=%d, offset=x%lx, val=x%lx )\n",seg,offset,val); 2380 2383 assert(seg > 0); // COMDATs not done yet 2381 2384 buf = SegData[seg]->SDbuf; 2382 2385 save = buf->size(); 2383 2386 buf->setsize(offset); 2384 2387 #if 0 2385 2388 if (segtyp == CODE) 2386 2389 { 2387 2390 val = val - funcsym_p->Soffset; 2388 2391 elf_addrel(seg,offset,RI_TYPE_PC32,funcsym_p->Sxtrnnum,0); 2389 2392 } 2390 2393 else 2391 2394 #endif 2392 2395 { 2393 2396 val = val - funcsym_p->Soffset; 2394 2397 int relinfo; 2398 targ_size_t v = 0; 2395 2399 if (I64) 2396 2400 relinfo = (config.flags3 & CFG3pic) ? R_X86_64_PC32 : R_X86_64_32; 2397 2401 else 2398 2402 relinfo = (config.flags3 & CFG3pic) ? RI_TYPE_GOTOFF : RI_TYPE_SYM32; 2399 elf_addrel(seg,offset, relinfo, funcsym_p->Sxtrnnum, 0);2403 elf_addrel(seg,offset, relinfo, funcsym_p->Sxtrnnum, v); 2400 2404 } 2401 2405 buf->write32(val); 2402 2406 if (save > offset + 4) 2403 2407 buf->setsize(save); 2404 2408 } 2405 2409 2406 2410 /******************************* 2407 2411 * Refer to an identifier. 2408 2412 * Input: 2409 2413 * segtyp = where the address is going (CODE or DATA) 2410 2414 * offset = offset within seg 2411 2415 * s -> Symbol table entry for identifier 2412 2416 * val = displacement from identifier 2413 2417 * flags = CFselfrel: self-relative 2414 2418 * CFseg: get segment 2415 2419 * CFoff: get offset 2416 2420 * CFoffset64: 64 bit fixup 2417 2421 * Returns: 2418 2422 * number of bytes in reference (4 or 8) 2419 2423 */ 2420 2424 2421 2425 int reftoident(int seg, targ_size_t offset, Symbol *s, targ_size_t val, 2422 2426 int flags) 2423 2427 { 2424 2428 tym_t ty; 2425 2429 bool external = TRUE; 2426 2430 Outbuffer *buf; 2427 2431 elf_u32_f32 relinfo,refseg; 2428 2432 int segtyp = MAP_SEG2TYP(seg); 2429 2433 //assert(val == 0); 2430 2434 int retsize = (flags & CFoffset64) ? 8 : 4; 2435 targ_size_t v = 0; 2431 2436 2432 2437 #if 0 2433 2438 printf("\nreftoident('%s' seg %d, offset x%llx, val x%llx, flags x%x)\n", 2434 2439 s->Sident,seg,offset,val,flags); 2435 2440 dbg_printf("Sseg = %d, Sxtrnnum = %d, retsize = %d\n",s->Sseg,s->Sxtrnnum,retsize); 2436 2441 symbol_print(s); 2437 2442 #endif 2438 2443 2439 2444 ty = s->ty(); 2440 2445 if (s->Sxtrnnum) 2441 2446 { // identifier is defined somewhere else 2442 2447 if (I64) 2443 2448 { 2444 2449 if (SymbolTable64[s->Sxtrnnum].st_shndx != SHT_UNDEF) 2445 2450 external = FALSE; 2446 2451 } 2447 2452 else 2448 2453 { 2449 2454 if (SymbolTable[s->Sxtrnnum].st_shndx != SHT_UNDEF) 2450 2455 external = FALSE; 2451 2456 } 2452 2457 } 2453 2458 2454 2459 switch (s->Sclass) 2455 2460 { 2456 2461 case SClocstat: 2457 2462 buf = SegData[seg]->SDbuf; 2458 2463 if (I64) 2459 2464 { 2460 2465 if (s->Sfl == FLtlsdata) 2461 2466 relinfo = config.flags3 & CFG3pic ? R_X86_64_TLSGD : R_X86_64_TPOFF32; 2462 2467 else 2463 relinfo = config.flags3 & CFG3pic ? R_X86_64_PC32 : R_X86_64_32; 2468 { relinfo = config.flags3 & CFG3pic ? R_X86_64_PC32 : R_X86_64_32; 2469 if (config.flags3 & CFG3pic) 2470 v = -4L; 2471 } 2464 2472 } 2465 2473 else 2466 2474 { 2467 2475 if (s->Sfl == FLtlsdata) 2468 2476 relinfo = config.flags3 & CFG3pic ? RI_TYPE_TLS_GD : RI_TYPE_TLS_LE; 2469 2477 else 2470 2478 relinfo = config.flags3 & CFG3pic ? RI_TYPE_GOTOFF : RI_TYPE_SYM32; 2471 2479 } 2472 2480 if (flags & CFoffset64 && relinfo == R_X86_64_32) 2473 2481 { 2474 2482 relinfo = R_X86_64_64; 2475 2483 } 2476 elf_addrel(seg,offset,relinfo,STI_RODAT, 0);2484 elf_addrel(seg,offset,relinfo,STI_RODAT,v); 2477 2485 if (retsize == 8) 2478 2486 buf->write64(val + s->Soffset); 2479 2487 else 2480 2488 buf->write32(val + s->Soffset); 2481 2489 break; 2482 2490 2483 2491 case SCcomdat: 2484 2492 case_SCcomdat: 2485 2493 case SCstatic: 2486 2494 #if 0 2487 2495 if ((s->Sflags & SFLthunk) && s->Soffset) 2488 2496 { // A thunk symbol that has be defined 2489 2497 assert(s->Sseg == seg); 2490 2498 val = (s->Soffset+val) - (offset+4); 2491 2499 goto outaddrval; 2492 2500 } 2493 2501 // FALL_THROUGH 2494 2502 #endif 2495 2503 2496 2504 case SCextern: … … 2596 2604 { 2597 2605 if (s->Sclass == SCstatic) 2598 2606 relinfo = RI_TYPE_TLS_LE; // TLS_GD? 2599 2607 else 2600 2608 relinfo = RI_TYPE_TLS_IE; 2601 2609 } 2602 2610 else 2603 2611 { 2604 2612 if (s->Sclass == SCstatic) 2605 2613 relinfo = RI_TYPE_TLS_LE; 2606 2614 else 2607 2615 relinfo = RI_TYPE_TLS_IE; 2608 2616 } 2609 2617 } 2610 2618 } 2611 2619 if (flags & CFoffset64 && relinfo == R_X86_64_32) 2612 2620 { 2613 2621 relinfo = R_X86_64_64; 2614 2622 } 2615 2623 //printf("\t\t************* adding relocation\n"); 2616 elf_addrel(seg,offset,relinfo,refseg,0); 2624 targ_size_t v = (relinfo == R_X86_64_PC32) ? -4 : 0; 2625 elf_addrel(seg,offset,relinfo,refseg,v); 2617 2626 } 2618 2627 outaddrval: 2619 2628 if (retsize == 8) 2620 2629 buf->write64(val); 2621 2630 else 2622 2631 buf->write32(val); 2623 2632 if (save > offset + retsize) 2624 2633 buf->setsize(save); 2625 2634 } 2626 2635 break; 2627 2636 2628 2637 case SCsinline: 2629 2638 case SCeinline: 2630 2639 printf ("Undefined inline value <<fixme>>\n"); 2631 2640 //warerr(WM_undefined_inline,s->Sident); 2632 2641 case SCinline: 2633 2642 if (tyfunc(ty)) 2634 2643 { 2635 2644 s->Sclass = SCextern; 2636 2645 goto case_extern; … … 2770 2779 * mov [ECX],EAX 2771 2780 * popad 2772 2781 * ret 2773 2782 */ 2774 2783 2775 2784 const int reltype = I64 ? R_X86_64_32 : RI_TYPE_SYM32; 2776 2785 const int refsize = 4; // use 32 bit relocations, even in 64 bit mode 2777 2786 2778 2787 const int seg = CODE; 2779 2788 Outbuffer *buf = SegData[seg]->SDbuf; 2780 2789 SegData[seg]->SDoffset = buf->size(); 2781 2790 codeOffset = SegData[seg]->SDoffset + 1; 2782 2791 buf->writeByte(0xC3); /* ret */ 2783 2792 2784 2793 int off = 0; 2785 2794 if (I32) 2786 2795 { buf->writeByte(0x60); // PUSHAD 2787 2796 off = 1; 2788 2797 } 2789 2798 2790 /* movl ModuleReference*, %eax */ 2791 buf->writeByte(0xB8); 2792 buf->write32(refOffset); 2793 elf_addrel(seg, codeOffset + off + 1, reltype, STI_DATA, 0); 2794 2795 /* movl _Dmodule_ref, %ecx */ 2796 buf->writeByte(0xB9); 2797 buf->write32(0); 2798 elf_addrel(seg, codeOffset + off + 6, reltype, objextern("_Dmodule_ref"), 0); 2799 if (I64 && config.flags3 & CFG3pic) 2800 { // LEA RAX,ModuleReference[RIP] 2801 buf->writeByte(REX | REX_W); 2802 buf->writeByte(0x8D); 2803 buf->writeByte(modregrm(0,AX,5)); 2804 buf->write32(refOffset); 2805 elf_addrel(seg, codeOffset + off + 3, R_X86_64_PC32, STI_DATA, -4); 2806 2807 // LEA RCX,_DmoduleRef[RIP] 2808 buf->writeByte(REX | REX_W); 2809 buf->writeByte(0x8D); 2810 buf->writeByte(modregrm(0,CX,5)); 2811 buf->write32(0); 2812 elf_addrel(seg, codeOffset + off + 10, R_X86_64_PC32, objextern("_Dmodule_ref"), -4); 2813 } 2814 else 2815 { 2816 /* movl ModuleReference*, %eax */ 2817 buf->writeByte(0xB8); 2818 buf->write32(refOffset); 2819 elf_addrel(seg, codeOffset + off + 1, reltype, STI_DATA, 0); 2820 2821 /* movl _Dmodule_ref, %ecx */ 2822 buf->writeByte(0xB9); 2823 buf->write32(0); 2824 elf_addrel(seg, codeOffset + off + 6, reltype, objextern("_Dmodule_ref"), 0); 2825 } 2799 2826 2800 2827 buf->writeByte(0x8B); buf->writeByte(0x11); /* movl (%ecx), %edx */ 2801 2828 buf->writeByte(0x89); buf->writeByte(0x10); /* movl %edx, (%eax) */ 2802 2829 buf->writeByte(0x89); buf->writeByte(0x01); /* movl %eax, (%ecx) */ 2803 2830 2804 2831 if (I32) buf->writeByte(0x61); // POPAD 2805 2832 buf->writeByte(0xC3); /* ret */ 2806 2833 SegData[seg]->SDoffset = buf->size(); 2807 2834 } 2808 2835 2809 2836 /* Add reference to constructor into ".ctors" segment 2810 2837 */ 2811 2838 const int seg = elf_getsegment(".ctors", NULL, SHT_PROGDEF, SHF_ALLOC|SHF_WRITE, NPTRSIZE); 2812 2839 2813 2840 Outbuffer *buf = SegData[seg]->SDbuf; 2814 2841 buf->write32(codeOffset); 2815 2842 elf_addrel(seg, SegData[seg]->SDoffset, I64 ? R_X86_64_64 : RI_TYPE_SYM32, STI_TEXT, 0); 2816 2843 SegData[seg]->SDoffset += NPTRSIZE; 2817 2844 } 2818 2845
