Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Changeset 589

Show
Ignore:
Timestamp:
07/27/10 01:20:32 (14 years ago)
Author:
walter
Message:

PIC fixes for 64

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/dmd-1.x/src/backend/cod2.c

    r581 r589  
    38513851    case FLdata: 
    38523852    case FLudata: 
    38533853#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    38543854    case FLgot: 
    38553855    case FLgotoff: 
    38563856#endif 
    38573857    case FLcsdata: 
    38583858    L4: 
    38593859        cs.IEVsym2 = e->EV.sp.Vsym; 
    38603860        cs.IEVoffset2 = e->EV.sp.Voffset; 
    38613861    L3: 
    38623862        if (reg == STACK) 
    38633863        {   stackchanged = 1; 
    38643864            cs.Iop = 0x68;              /* PUSH immed16                 */ 
    38653865            c = genadjesp(NULL,REGSIZE); 
    38663866        } 
    38673867        else 
    38683868        {   cs.Iop = 0xB8 + (reg & 7);  // MOV reg,immed16 
    38693869            if (reg & 8) 
    38703870                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            } 
    38713880            c = NULL; 
    38723881        } 
    38733882        cs.Iflags = CFoff;              /* want offset only             */ 
    38743883        cs.IFL2 = fl; 
    38753884        c = gen(c,&cs); 
    38763885        break; 
    38773886 
    38783887#if 0 && TARGET_LINUX 
    38793888    case FLgot: 
    38803889    case FLgotoff: 
    38813890        { 
    38823891        gotref = 1; 
    38833892        symbol *s = e->EV.sp.Vsym; 
    38843893        // When using 8B (MOV), indicating that rm is used 
    38853894        // rm operands are always placed in IEV1 not IEV2 
    38863895        cs.IEVsym1 = s; 
    38873896        cs.IEVoffset1 = e->EV.sp.Voffset; 
    38883897        cs.Irm = modregrm(2,reg,BX);    // reg,disp32[EBX] 
    38893898        cs.IFL1 = fl; 
    38903899        cs.Iop = (fl == FLgotoff) 
  • branches/dmd-1.x/src/backend/cod3.c

    r583 r589  
    33083308                            case 5:     rm = modregrm(3,0,DI);  goto L6; 
    33093309                            case 7:     rm = modregrm(3,0,BX);  goto L6; 
    33103310                            L6:     c->Irm = rm + reg; 
    33113311                                    c->Iop = 0x8B; 
    33123312                                    break; 
    33133313                        } 
    33143314                    } 
    33153315                } 
    33163316 
    33173317                /* replace LEA reg,0[BP] with MOV reg,BP        */ 
    33183318                else if (mod == modregrm(1,0,0) && rm == local_BPRM && 
    33193319                        c->IFL1 == FLconst && c->IEVpointer1 == 0) 
    33203320                {       c->Iop = 0x8B;          /* MOV reg,BP   */ 
    33213321                        c->Irm = modregrm(3,0,BP) + reg; 
    33223322                } 
    33233323            } 
    33243324 
    33253325            // Replace [R13] with 0[R13] 
    33263326            if (c->Irex & REX_B && (c->Irm & modregrm(3,0,5)) == modregrm(0,0,5)) 
    33273327            { 
    3328 printf("test1\n"); 
    33293328                c->Irm |= modregrm(1,0,0); 
    33303329                c->IFL1 = FLconst; 
    33313330                c->IEVpointer1 = 0; 
    33323331            } 
    33333332        } 
    33343333        else 
    33353334        { 
    33363335            switch (op) 
    33373336            { 
    33383337                default: 
    33393338                    if ((op & 0xF0) != 0x70) 
    33403339                        break; 
    33413340                case JMP: 
    33423341                    switch (c->IFL2) 
    33433342                    {   case FLcode: 
    33443343                                if (c->IEV2.Vcode == code_next(c)) 
    33453344                                {       c->Iop = NOP; 
    33463345                                        continue; 
    33473346                                } 
    33483347                                break; 
     
    36913690                    break; 
    36923691                case 0x40: 
    36933692                    size++;             /* disp8                        */ 
    36943693                    break; 
    36953694                case 0x80: 
    36963695                    size += 4;          /* disp32                       */ 
    36973696                    break; 
    36983697            } 
    36993698        } 
    37003699        else 
    37013700        {   // 16 bit addressing 
    37023701            if (mod == 0x40)            /* 01: 8 bit displacement       */ 
    37033702                size++; 
    37043703            else if (mod == 0x80 || (mod == 0 && (rm & 7) == 6)) 
    37053704                size += 2; 
    37063705        } 
    37073706    } 
    37083707 
    37093708Lret: 
    37103709    if (c->Irex) 
    3711         size++; 
     3710    {   size++; 
     3711        if (c->Irex & REX_W && (op & 0xF8) == 0xB8) 
     3712            size += 4; 
     3713    } 
    37123714Lret2: 
    37133715    //printf("op = x%02x, size = %d\n",op,size); 
    37143716    return size; 
    37153717} 
    37163718 
    37173719/******************************** 
    37183720 * Return !=0 if codes match. 
    37193721 */ 
    37203722 
    37213723#if 0 
    37223724 
    37233725int code_match(code *c1,code *c2) 
    37243726{   code cs1,cs2; 
    37253727    unsigned char ins; 
    37263728 
    37273729    if (c1 == c2) 
    37283730        goto match; 
    37293731    cs1 = *c1; 
    37303732    cs2 = *c2; 
    37313733    if (cs1.Iop != cs2.Iop) 
     
    40264028            if (op == 0xC8) 
    40274029                do16bit((enum FL)c->IFL1,&c->IEV1,0); 
    40284030        } 
    40294031        flags &= CFseg | CFoff | CFselfrel; 
    40304032        if (ins & T)                    /* if second operand            */ 
    40314033        {       if (ins & E)            /* if data-8                    */ 
    40324034                    do8bit((enum FL) c->IFL2,&c->IEV2); 
    40334035                else if (!I16) 
    40344036                { 
    40354037                    switch (op) 
    40364038                    {   case 0xC2:              /* RETN imm16           */ 
    40374039                        case 0xCA:              /* RETF imm16           */ 
    40384040                        do16: 
    40394041                            do16bit((enum FL)c->IFL2,&c->IEV2,flags); 
    40404042                            break; 
    40414043 
    40424044                        case 0xA1: 
    40434045                        case 0xA3: 
    40444046                            if (I64 && c->Irex) 
    40454047                            { 
     4048                        do64: 
    40464049                                do64bit((enum FL)c->IFL2,&c->IEV2,flags); 
    40474050                                break; 
    40484051                            } 
    40494052                        case 0xA0:              /* MOV AL,byte ptr []   */ 
    40504053                        case 0xA2: 
    40514054                            if (c->Iflags & CFaddrsize && !I64) 
    40524055                                goto do16; 
    40534056                            else 
    40544057                        do32: 
    40554058                                do32bit((enum FL)c->IFL2,&c->IEV2,flags); 
    40564059                            break; 
    40574060                        case 0x9A: 
    40584061                        case 0xEA: 
    40594062                            if (c->Iflags & CFopsize) 
    40604063                                goto ptr1616; 
    40614064                            else 
    40624065                                goto ptr1632; 
    40634066 
    40644067                        case 0x68:              // PUSH immed32 
    40654068                            if ((enum FL)c->IFL2 == FLblock) 
    40664069                            { 
    40674070                                c->IFL2 = FLblockoff; 
    40684071                                goto do32; 
    40694072                            } 
    40704073                            else 
    40714074                                goto case_default; 
    40724075 
    40734076                        case 0xE8:              // CALL rel 
    40744077                        case 0xE9:              // JMP  rel 
    40754078                            flags |= CFselfrel; 
     4079                            goto case_default; 
     4080 
    40764081                        default: 
     4082                            if (I64 && (op & 0xF8) == 0xB8 && c->Irex & REX_W) 
     4083                                goto do64; 
    40774084                        case_default: 
    40784085                            if (c->Iflags & CFopsize) 
    40794086                                goto do16; 
    40804087                            else 
    40814088                                goto do32; 
    40824089                            break; 
    40834090                    } 
    40844091                } 
    40854092                else 
    40864093                { 
    40874094                    switch (op) { 
    40884095                        case 0xC2: 
    40894096                        case 0xCA: 
    40904097                            goto do16; 
    40914098                        case 0xA0: 
    40924099                        case 0xA1: 
    40934100                        case 0xA2: 
    40944101                        case 0xA3: 
    40954102                            if (c->Iflags & CFaddrsize) 
    40964103                                goto do32; 
  • branches/dmd-1.x/src/backend/elfobj.c

    r582 r589  
    23162316void reftodatseg(int seg,targ_size_t offset,targ_size_t val, 
    23172317        unsigned targetdatum,int flags) 
    23182318{ 
    23192319    Outbuffer *buf; 
    23202320    int save; 
    23212321 
    23222322    buf = SegData[seg]->SDbuf; 
    23232323    save = buf->size(); 
    23242324    buf->setsize(offset); 
    23252325#if 0 
    23262326    printf("reftodatseg(seg=%d, offset=x%llx, val=x%llx,data %x, flags %x)\n", 
    23272327        seg,(unsigned long long)offset,(unsigned long long)val,targetdatum,flags); 
    23282328#endif 
    23292329    /*if (OPT_IS_SET(OPTfwritable_strings)) 
    23302330    { 
    23312331        elf_addrel(seg,offset,RI_TYPE_SYM32,STI_DATA,0); 
    23322332    } 
    23332333    else*/ 
    23342334    { 
    23352335        int relinfo; 
     2336        targ_size_t v = 0; 
    23362337 
    23372338        if (I64) 
    23382339        { 
    23392340            if (MAP_SEG2TYP(seg) == CODE && config.flags3 & CFG3pic) 
    2340                 relinfo = R_X86_64_PC32; 
     2341            {   relinfo = R_X86_64_PC32; 
     2342                //v = -4L; 
     2343            } 
    23412344            else if (MAP_SEG2SEC(targetdatum)->sh_flags & SHF_TLS) 
    23422345                relinfo = config.flags3 & CFG3pic ? R_X86_64_TLSGD : R_X86_64_TPOFF32; 
    23432346            else 
    23442347                relinfo = R_X86_64_32; 
    23452348        } 
    23462349        else 
    23472350        { 
    23482351            if (MAP_SEG2TYP(seg) == CODE && config.flags3 & CFG3pic) 
    23492352                relinfo = RI_TYPE_GOTOFF; 
    23502353            else if (MAP_SEG2SEC(targetdatum)->sh_flags & SHF_TLS) 
    23512354                relinfo = config.flags3 & CFG3pic ? RI_TYPE_TLS_GD : RI_TYPE_TLS_LE; 
    23522355            else 
    23532356                relinfo = RI_TYPE_SYM32; 
    23542357        } 
    23552358 
    2356         elf_addrel(seg, offset, relinfo, STI_RODAT, 0); 
     2359        elf_addrel(seg, offset, relinfo, STI_RODAT, v); 
    23572360    } 
    23582361    buf->write32(val); 
    23592362    if (save > offset + 4) 
    23602363        buf->setsize(save); 
    23612364} 
    23622365 
    23632366/******************************* 
    23642367 * Refer to address that is in the code segment. 
    23652368 * Only offsets are output, regardless of the memory model. 
    23662369 * Used to put values in switch address tables. 
    23672370 * Input: 
    23682371 *      seg =           where the address is going (CODE or DATA) 
    23692372 *      offset =        offset within seg 
    23702373 *      val =           displacement from start of this module 
    23712374 */ 
    23722375 
    23732376void reftocodseg(int seg,targ_size_t offset,targ_size_t val) 
    23742377{ 
    23752378    Outbuffer *buf; 
    23762379    int save; 
    23772380    int segtyp = MAP_SEG2TYP(seg); 
    23782381 
    23792382    //dbg_printf("reftocodseg(seg=%d, offset=x%lx, val=x%lx )\n",seg,offset,val); 
    23802383    assert(seg > 0);            // COMDATs not done yet 
    23812384    buf = SegData[seg]->SDbuf; 
    23822385    save = buf->size(); 
    23832386    buf->setsize(offset); 
    23842387#if 0 
    23852388    if (segtyp == CODE) 
    23862389    { 
    23872390        val = val - funcsym_p->Soffset; 
    23882391        elf_addrel(seg,offset,RI_TYPE_PC32,funcsym_p->Sxtrnnum,0); 
    23892392    } 
    23902393    else 
    23912394#endif 
    23922395    { 
    23932396        val = val - funcsym_p->Soffset; 
    23942397        int relinfo; 
     2398        targ_size_t v = 0; 
    23952399        if (I64) 
    23962400            relinfo = (config.flags3 & CFG3pic) ? R_X86_64_PC32 : R_X86_64_32; 
    23972401        else 
    23982402            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); 
    24002404    } 
    24012405    buf->write32(val); 
    24022406    if (save > offset + 4) 
    24032407        buf->setsize(save); 
    24042408} 
    24052409 
    24062410/******************************* 
    24072411 * Refer to an identifier. 
    24082412 * Input: 
    24092413 *      segtyp =        where the address is going (CODE or DATA) 
    24102414 *      offset =        offset within seg 
    24112415 *      s ->            Symbol table entry for identifier 
    24122416 *      val =           displacement from identifier 
    24132417 *      flags =         CFselfrel: self-relative 
    24142418 *                      CFseg: get segment 
    24152419 *                      CFoff: get offset 
    24162420 *                      CFoffset64: 64 bit fixup 
    24172421 * Returns: 
    24182422 *      number of bytes in reference (4 or 8) 
    24192423 */ 
    24202424 
    24212425int reftoident(int seg, targ_size_t offset, Symbol *s, targ_size_t val, 
    24222426        int flags) 
    24232427{ 
    24242428    tym_t ty; 
    24252429    bool external = TRUE; 
    24262430    Outbuffer *buf; 
    24272431    elf_u32_f32 relinfo,refseg; 
    24282432    int segtyp = MAP_SEG2TYP(seg); 
    24292433    //assert(val == 0); 
    24302434    int retsize = (flags & CFoffset64) ? 8 : 4; 
     2435    targ_size_t v = 0; 
    24312436 
    24322437#if 0 
    24332438    printf("\nreftoident('%s' seg %d, offset x%llx, val x%llx, flags x%x)\n", 
    24342439        s->Sident,seg,offset,val,flags); 
    24352440    dbg_printf("Sseg = %d, Sxtrnnum = %d, retsize = %d\n",s->Sseg,s->Sxtrnnum,retsize); 
    24362441    symbol_print(s); 
    24372442#endif 
    24382443 
    24392444    ty = s->ty(); 
    24402445    if (s->Sxtrnnum) 
    24412446    {                           // identifier is defined somewhere else 
    24422447        if (I64) 
    24432448        { 
    24442449            if (SymbolTable64[s->Sxtrnnum].st_shndx != SHT_UNDEF) 
    24452450                external = FALSE; 
    24462451        } 
    24472452        else 
    24482453        { 
    24492454            if (SymbolTable[s->Sxtrnnum].st_shndx != SHT_UNDEF) 
    24502455                external = FALSE; 
    24512456        } 
    24522457    } 
    24532458 
    24542459    switch (s->Sclass) 
    24552460    { 
    24562461        case SClocstat: 
    24572462            buf = SegData[seg]->SDbuf; 
    24582463            if (I64) 
    24592464            { 
    24602465                if (s->Sfl == FLtlsdata) 
    24612466                    relinfo = config.flags3 & CFG3pic ? R_X86_64_TLSGD : R_X86_64_TPOFF32; 
    24622467                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                } 
    24642472            } 
    24652473            else 
    24662474            { 
    24672475                if (s->Sfl == FLtlsdata) 
    24682476                    relinfo = config.flags3 & CFG3pic ? RI_TYPE_TLS_GD : RI_TYPE_TLS_LE; 
    24692477                else 
    24702478                    relinfo = config.flags3 & CFG3pic ? RI_TYPE_GOTOFF : RI_TYPE_SYM32; 
    24712479            } 
    24722480            if (flags & CFoffset64 && relinfo == R_X86_64_32) 
    24732481            { 
    24742482                relinfo = R_X86_64_64; 
    24752483            } 
    2476             elf_addrel(seg,offset,relinfo,STI_RODAT,0); 
     2484            elf_addrel(seg,offset,relinfo,STI_RODAT,v); 
    24772485            if (retsize == 8) 
    24782486                buf->write64(val + s->Soffset); 
    24792487            else 
    24802488                buf->write32(val + s->Soffset); 
    24812489            break; 
    24822490 
    24832491        case SCcomdat: 
    24842492        case_SCcomdat: 
    24852493        case SCstatic: 
    24862494#if 0 
    24872495            if ((s->Sflags & SFLthunk) && s->Soffset) 
    24882496            {                   // A thunk symbol that has be defined 
    24892497                assert(s->Sseg == seg); 
    24902498                val = (s->Soffset+val) - (offset+4); 
    24912499                goto outaddrval; 
    24922500            } 
    24932501            // FALL_THROUGH 
    24942502#endif 
    24952503 
    24962504        case SCextern: 
     
    25962604                            { 
    25972605                                if (s->Sclass == SCstatic) 
    25982606                                    relinfo = RI_TYPE_TLS_LE;  // TLS_GD? 
    25992607                                else 
    26002608                                    relinfo = RI_TYPE_TLS_IE; 
    26012609                            } 
    26022610                            else 
    26032611                            { 
    26042612                                if (s->Sclass == SCstatic) 
    26052613                                    relinfo = RI_TYPE_TLS_LE; 
    26062614                                else 
    26072615                                    relinfo = RI_TYPE_TLS_IE; 
    26082616                            } 
    26092617                        } 
    26102618                    } 
    26112619                    if (flags & CFoffset64 && relinfo == R_X86_64_32) 
    26122620                    { 
    26132621                        relinfo = R_X86_64_64; 
    26142622                    } 
    26152623                    //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); 
    26172626                } 
    26182627outaddrval: 
    26192628                if (retsize == 8) 
    26202629                    buf->write64(val); 
    26212630                else 
    26222631                    buf->write32(val); 
    26232632                if (save > offset + retsize) 
    26242633                    buf->setsize(save); 
    26252634            } 
    26262635            break; 
    26272636 
    26282637        case SCsinline: 
    26292638        case SCeinline: 
    26302639            printf ("Undefined inline value <<fixme>>\n"); 
    26312640            //warerr(WM_undefined_inline,s->Sident); 
    26322641        case SCinline: 
    26332642            if (tyfunc(ty)) 
    26342643            { 
    26352644                s->Sclass = SCextern; 
    26362645                goto case_extern; 
     
    27702779         *      mov     [ECX],EAX 
    27712780         *      popad 
    27722781         *      ret 
    27732782         */ 
    27742783 
    27752784        const int reltype = I64 ? R_X86_64_32 : RI_TYPE_SYM32; 
    27762785        const int refsize = 4;                          // use 32 bit relocations, even in 64 bit mode 
    27772786 
    27782787        const int seg = CODE; 
    27792788        Outbuffer *buf = SegData[seg]->SDbuf; 
    27802789        SegData[seg]->SDoffset = buf->size(); 
    27812790        codeOffset = SegData[seg]->SDoffset + 1; 
    27822791        buf->writeByte(0xC3); /* ret */ 
    27832792 
    27842793        int off = 0; 
    27852794        if (I32) 
    27862795        {   buf->writeByte(0x60); // PUSHAD 
    27872796            off = 1; 
    27882797        } 
    27892798 
    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        } 
    27992826 
    28002827        buf->writeByte(0x8B); buf->writeByte(0x11); /* movl (%ecx), %edx */ 
    28012828        buf->writeByte(0x89); buf->writeByte(0x10); /* movl %edx, (%eax) */ 
    28022829        buf->writeByte(0x89); buf->writeByte(0x01); /* movl %eax, (%ecx) */ 
    28032830 
    28042831        if (I32) buf->writeByte(0x61); // POPAD 
    28052832        buf->writeByte(0xC3); /* ret */ 
    28062833        SegData[seg]->SDoffset = buf->size(); 
    28072834    } 
    28082835 
    28092836    /* Add reference to constructor into ".ctors" segment 
    28102837     */ 
    28112838    const int seg = elf_getsegment(".ctors", NULL, SHT_PROGDEF, SHF_ALLOC|SHF_WRITE, NPTRSIZE); 
    28122839 
    28132840    Outbuffer *buf = SegData[seg]->SDbuf; 
    28142841    buf->write32(codeOffset); 
    28152842    elf_addrel(seg, SegData[seg]->SDoffset, I64 ? R_X86_64_64 : RI_TYPE_SYM32, STI_TEXT, 0); 
    28162843    SegData[seg]->SDoffset += NPTRSIZE; 
    28172844} 
    28182845 
  • trunk/src/backend/cod2.c

    r581 r589  
    38513851    case FLdata: 
    38523852    case FLudata: 
    38533853#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 
    38543854    case FLgot: 
    38553855    case FLgotoff: 
    38563856#endif 
    38573857    case FLcsdata: 
    38583858    L4: 
    38593859        cs.IEVsym2 = e->EV.sp.Vsym; 
    38603860        cs.IEVoffset2 = e->EV.sp.Voffset; 
    38613861    L3: 
    38623862        if (reg == STACK) 
    38633863        {   stackchanged = 1; 
    38643864            cs.Iop = 0x68;              /* PUSH immed16                 */ 
    38653865            c = genadjesp(NULL,REGSIZE); 
    38663866        } 
    38673867        else 
    38683868        {   cs.Iop = 0xB8 + (reg & 7);  // MOV reg,immed16 
    38693869            if (reg & 8) 
    38703870                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            } 
    38713880            c = NULL; 
    38723881        } 
    38733882        cs.Iflags = CFoff;              /* want offset only             */ 
    38743883        cs.IFL2 = fl; 
    38753884        c = gen(c,&cs); 
    38763885        break; 
    38773886 
    38783887#if 0 && TARGET_LINUX 
    38793888    case FLgot: 
    38803889    case FLgotoff: 
    38813890        { 
    38823891        gotref = 1; 
    38833892        symbol *s = e->EV.sp.Vsym; 
    38843893        // When using 8B (MOV), indicating that rm is used 
    38853894        // rm operands are always placed in IEV1 not IEV2 
    38863895        cs.IEVsym1 = s; 
    38873896        cs.IEVoffset1 = e->EV.sp.Voffset; 
    38883897        cs.Irm = modregrm(2,reg,BX);    // reg,disp32[EBX] 
    38893898        cs.IFL1 = fl; 
    38903899        cs.Iop = (fl == FLgotoff) 
  • trunk/src/backend/cod3.c

    r583 r589  
    33083308                            case 5:     rm = modregrm(3,0,DI);  goto L6; 
    33093309                            case 7:     rm = modregrm(3,0,BX);  goto L6; 
    33103310                            L6:     c->Irm = rm + reg; 
    33113311                                    c->Iop = 0x8B; 
    33123312                                    break; 
    33133313                        } 
    33143314                    } 
    33153315                } 
    33163316 
    33173317                /* replace LEA reg,0[BP] with MOV reg,BP        */ 
    33183318                else if (mod == modregrm(1,0,0) && rm == local_BPRM && 
    33193319                        c->IFL1 == FLconst && c->IEVpointer1 == 0) 
    33203320                {       c->Iop = 0x8B;          /* MOV reg,BP   */ 
    33213321                        c->Irm = modregrm(3,0,BP) + reg; 
    33223322                } 
    33233323            } 
    33243324 
    33253325            // Replace [R13] with 0[R13] 
    33263326            if (c->Irex & REX_B && (c->Irm & modregrm(3,0,5)) == modregrm(0,0,5)) 
    33273327            { 
    3328 printf("test1\n"); 
    33293328                c->Irm |= modregrm(1,0,0); 
    33303329                c->IFL1 = FLconst; 
    33313330                c->IEVpointer1 = 0; 
    33323331            } 
    33333332        } 
    33343333        else 
    33353334        { 
    33363335            switch (op) 
    33373336            { 
    33383337                default: 
    33393338                    if ((op & 0xF0) != 0x70) 
    33403339                        break; 
    33413340                case JMP: 
    33423341                    switch (c->IFL2) 
    33433342                    {   case FLcode: 
    33443343                                if (c->IEV2.Vcode == code_next(c)) 
    33453344                                {       c->Iop = NOP; 
    33463345                                        continue; 
    33473346                                } 
    33483347                                break; 
     
    36913690                    break; 
    36923691                case 0x40: 
    36933692                    size++;             /* disp8                        */ 
    36943693                    break; 
    36953694                case 0x80: 
    36963695                    size += 4;          /* disp32                       */ 
    36973696                    break; 
    36983697            } 
    36993698        } 
    37003699        else 
    37013700        {   // 16 bit addressing 
    37023701            if (mod == 0x40)            /* 01: 8 bit displacement       */ 
    37033702                size++; 
    37043703            else if (mod == 0x80 || (mod == 0 && (rm & 7) == 6)) 
    37053704                size += 2; 
    37063705        } 
    37073706    } 
    37083707 
    37093708Lret: 
    37103709    if (c->Irex) 
    3711         size++; 
     3710    {   size++; 
     3711        if (c->Irex & REX_W && (op & 0xF8) == 0xB8) 
     3712            size += 4; 
     3713    } 
    37123714Lret2: 
    37133715    //printf("op = x%02x, size = %d\n",op,size); 
    37143716    return size; 
    37153717} 
    37163718 
    37173719/******************************** 
    37183720 * Return !=0 if codes match. 
    37193721 */ 
    37203722 
    37213723#if 0 
    37223724 
    37233725int code_match(code *c1,code *c2) 
    37243726{   code cs1,cs2; 
    37253727    unsigned char ins; 
    37263728 
    37273729    if (c1 == c2) 
    37283730        goto match; 
    37293731    cs1 = *c1; 
    37303732    cs2 = *c2; 
    37313733    if (cs1.Iop != cs2.Iop) 
     
    40264028            if (op == 0xC8) 
    40274029                do16bit((enum FL)c->IFL1,&c->IEV1,0); 
    40284030        } 
    40294031        flags &= CFseg | CFoff | CFselfrel; 
    40304032        if (ins & T)                    /* if second operand            */ 
    40314033        {       if (ins & E)            /* if data-8                    */ 
    40324034                    do8bit((enum FL) c->IFL2,&c->IEV2); 
    40334035                else if (!I16) 
    40344036                { 
    40354037                    switch (op) 
    40364038                    {   case 0xC2:              /* RETN imm16           */ 
    40374039                        case 0xCA:              /* RETF imm16           */ 
    40384040                        do16: 
    40394041                            do16bit((enum FL)c->IFL2,&c->IEV2,flags); 
    40404042                            break; 
    40414043 
    40424044                        case 0xA1: 
    40434045                        case 0xA3: 
    40444046                            if (I64 && c->Irex) 
    40454047                            { 
     4048                        do64: 
    40464049                                do64bit((enum FL)c->IFL2,&c->IEV2,flags); 
    40474050                                break; 
    40484051                            } 
    40494052                        case 0xA0:              /* MOV AL,byte ptr []   */ 
    40504053                        case 0xA2: 
    40514054                            if (c->Iflags & CFaddrsize && !I64) 
    40524055                                goto do16; 
    40534056                            else 
    40544057                        do32: 
    40554058                                do32bit((enum FL)c->IFL2,&c->IEV2,flags); 
    40564059                            break; 
    40574060                        case 0x9A: 
    40584061                        case 0xEA: 
    40594062                            if (c->Iflags & CFopsize) 
    40604063                                goto ptr1616; 
    40614064                            else 
    40624065                                goto ptr1632; 
    40634066 
    40644067                        case 0x68:              // PUSH immed32 
    40654068                            if ((enum FL)c->IFL2 == FLblock) 
    40664069                            { 
    40674070                                c->IFL2 = FLblockoff; 
    40684071                                goto do32; 
    40694072                            } 
    40704073                            else 
    40714074                                goto case_default; 
    40724075 
    40734076                        case 0xE8:              // CALL rel 
    40744077                        case 0xE9:              // JMP  rel 
    40754078                            flags |= CFselfrel; 
     4079                            goto case_default; 
     4080 
    40764081                        default: 
     4082                            if (I64 && (op & 0xF8) == 0xB8 && c->Irex & REX_W) 
     4083                                goto do64; 
    40774084                        case_default: 
    40784085                            if (c->Iflags & CFopsize) 
    40794086                                goto do16; 
    40804087                            else 
    40814088                                goto do32; 
    40824089                            break; 
    40834090                    } 
    40844091                } 
    40854092                else 
    40864093                { 
    40874094                    switch (op) { 
    40884095                        case 0xC2: 
    40894096                        case 0xCA: 
    40904097                            goto do16; 
    40914098                        case 0xA0: 
    40924099                        case 0xA1: 
    40934100                        case 0xA2: 
    40944101                        case 0xA3: 
    40954102                            if (c->Iflags & CFaddrsize) 
    40964103                                goto do32; 
  • trunk/src/backend/elfobj.c

    r582 r589  
    23162316void reftodatseg(int seg,targ_size_t offset,targ_size_t val, 
    23172317        unsigned targetdatum,int flags) 
    23182318{ 
    23192319    Outbuffer *buf; 
    23202320    int save; 
    23212321 
    23222322    buf = SegData[seg]->SDbuf; 
    23232323    save = buf->size(); 
    23242324    buf->setsize(offset); 
    23252325#if 0 
    23262326    printf("reftodatseg(seg=%d, offset=x%llx, val=x%llx,data %x, flags %x)\n", 
    23272327        seg,(unsigned long long)offset,(unsigned long long)val,targetdatum,flags); 
    23282328#endif 
    23292329    /*if (OPT_IS_SET(OPTfwritable_strings)) 
    23302330    { 
    23312331        elf_addrel(seg,offset,RI_TYPE_SYM32,STI_DATA,0); 
    23322332    } 
    23332333    else*/ 
    23342334    { 
    23352335        int relinfo; 
     2336        targ_size_t v = 0; 
    23362337 
    23372338        if (I64) 
    23382339        { 
    23392340            if (MAP_SEG2TYP(seg) == CODE && config.flags3 & CFG3pic) 
    2340                 relinfo = R_X86_64_PC32; 
     2341            {   relinfo = R_X86_64_PC32; 
     2342                //v = -4L; 
     2343            } 
    23412344            else if (MAP_SEG2SEC(targetdatum)->sh_flags & SHF_TLS) 
    23422345                relinfo = config.flags3 & CFG3pic ? R_X86_64_TLSGD : R_X86_64_TPOFF32; 
    23432346            else 
    23442347                relinfo = R_X86_64_32; 
    23452348        } 
    23462349        else 
    23472350        { 
    23482351            if (MAP_SEG2TYP(seg) == CODE && config.flags3 & CFG3pic) 
    23492352                relinfo = RI_TYPE_GOTOFF; 
    23502353            else if (MAP_SEG2SEC(targetdatum)->sh_flags & SHF_TLS) 
    23512354                relinfo = config.flags3 & CFG3pic ? RI_TYPE_TLS_GD : RI_TYPE_TLS_LE; 
    23522355            else 
    23532356                relinfo = RI_TYPE_SYM32; 
    23542357        } 
    23552358 
    2356         elf_addrel(seg, offset, relinfo, STI_RODAT, 0); 
     2359        elf_addrel(seg, offset, relinfo, STI_RODAT, v); 
    23572360    } 
    23582361    buf->write32(val); 
    23592362    if (save > offset + 4) 
    23602363        buf->setsize(save); 
    23612364} 
    23622365 
    23632366/******************************* 
    23642367 * Refer to address that is in the code segment. 
    23652368 * Only offsets are output, regardless of the memory model. 
    23662369 * Used to put values in switch address tables. 
    23672370 * Input: 
    23682371 *      seg =           where the address is going (CODE or DATA) 
    23692372 *      offset =        offset within seg 
    23702373 *      val =           displacement from start of this module 
    23712374 */ 
    23722375 
    23732376void reftocodseg(int seg,targ_size_t offset,targ_size_t val) 
    23742377{ 
    23752378    Outbuffer *buf; 
    23762379    int save; 
    23772380    int segtyp = MAP_SEG2TYP(seg); 
    23782381 
    23792382    //dbg_printf("reftocodseg(seg=%d, offset=x%lx, val=x%lx )\n",seg,offset,val); 
    23802383    assert(seg > 0);            // COMDATs not done yet 
    23812384    buf = SegData[seg]->SDbuf; 
    23822385    save = buf->size(); 
    23832386    buf->setsize(offset); 
    23842387#if 0 
    23852388    if (segtyp == CODE) 
    23862389    { 
    23872390        val = val - funcsym_p->Soffset; 
    23882391        elf_addrel(seg,offset,RI_TYPE_PC32,funcsym_p->Sxtrnnum,0); 
    23892392    } 
    23902393    else 
    23912394#endif 
    23922395    { 
    23932396        val = val - funcsym_p->Soffset; 
    23942397        int relinfo; 
     2398        targ_size_t v = 0; 
    23952399        if (I64) 
    23962400            relinfo = (config.flags3 & CFG3pic) ? R_X86_64_PC32 : R_X86_64_32; 
    23972401        else 
    23982402            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); 
    24002404    } 
    24012405    buf->write32(val); 
    24022406    if (save > offset + 4) 
    24032407        buf->setsize(save); 
    24042408} 
    24052409 
    24062410/******************************* 
    24072411 * Refer to an identifier. 
    24082412 * Input: 
    24092413 *      segtyp =        where the address is going (CODE or DATA) 
    24102414 *      offset =        offset within seg 
    24112415 *      s ->            Symbol table entry for identifier 
    24122416 *      val =           displacement from identifier 
    24132417 *      flags =         CFselfrel: self-relative 
    24142418 *                      CFseg: get segment 
    24152419 *                      CFoff: get offset 
    24162420 *                      CFoffset64: 64 bit fixup 
    24172421 * Returns: 
    24182422 *      number of bytes in reference (4 or 8) 
    24192423 */ 
    24202424 
    24212425int reftoident(int seg, targ_size_t offset, Symbol *s, targ_size_t val, 
    24222426        int flags) 
    24232427{ 
    24242428    tym_t ty; 
    24252429    bool external = TRUE; 
    24262430    Outbuffer *buf; 
    24272431    elf_u32_f32 relinfo,refseg; 
    24282432    int segtyp = MAP_SEG2TYP(seg); 
    24292433    //assert(val == 0); 
    24302434    int retsize = (flags & CFoffset64) ? 8 : 4; 
     2435    targ_size_t v = 0; 
    24312436 
    24322437#if 0 
    24332438    printf("\nreftoident('%s' seg %d, offset x%llx, val x%llx, flags x%x)\n", 
    24342439        s->Sident,seg,offset,val,flags); 
    24352440    dbg_printf("Sseg = %d, Sxtrnnum = %d, retsize = %d\n",s->Sseg,s->Sxtrnnum,retsize); 
    24362441    symbol_print(s); 
    24372442#endif 
    24382443 
    24392444    ty = s->ty(); 
    24402445    if (s->Sxtrnnum) 
    24412446    {                           // identifier is defined somewhere else 
    24422447        if (I64) 
    24432448        { 
    24442449            if (SymbolTable64[s->Sxtrnnum].st_shndx != SHT_UNDEF) 
    24452450                external = FALSE; 
    24462451        } 
    24472452        else 
    24482453        { 
    24492454            if (SymbolTable[s->Sxtrnnum].st_shndx != SHT_UNDEF) 
    24502455                external = FALSE; 
    24512456        } 
    24522457    } 
    24532458 
    24542459    switch (s->Sclass) 
    24552460    { 
    24562461        case SClocstat: 
    24572462            buf = SegData[seg]->SDbuf; 
    24582463            if (I64) 
    24592464            { 
    24602465                if (s->Sfl == FLtlsdata) 
    24612466                    relinfo = config.flags3 & CFG3pic ? R_X86_64_TLSGD : R_X86_64_TPOFF32; 
    24622467                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                } 
    24642472            } 
    24652473            else 
    24662474            { 
    24672475                if (s->Sfl == FLtlsdata) 
    24682476                    relinfo = config.flags3 & CFG3pic ? RI_TYPE_TLS_GD : RI_TYPE_TLS_LE; 
    24692477                else 
    24702478                    relinfo = config.flags3 & CFG3pic ? RI_TYPE_GOTOFF : RI_TYPE_SYM32; 
    24712479            } 
    24722480            if (flags & CFoffset64 && relinfo == R_X86_64_32) 
    24732481            { 
    24742482                relinfo = R_X86_64_64; 
    24752483            } 
    2476             elf_addrel(seg,offset,relinfo,STI_RODAT,0); 
     2484            elf_addrel(seg,offset,relinfo,STI_RODAT,v); 
    24772485            if (retsize == 8) 
    24782486                buf->write64(val + s->Soffset); 
    24792487            else 
    24802488                buf->write32(val + s->Soffset); 
    24812489            break; 
    24822490 
    24832491        case SCcomdat: 
    24842492        case_SCcomdat: 
    24852493        case SCstatic: 
    24862494#if 0 
    24872495            if ((s->Sflags & SFLthunk) && s->Soffset) 
    24882496            {                   // A thunk symbol that has be defined 
    24892497                assert(s->Sseg == seg); 
    24902498                val = (s->Soffset+val) - (offset+4); 
    24912499                goto outaddrval; 
    24922500            } 
    24932501            // FALL_THROUGH 
    24942502#endif 
    24952503 
    24962504        case SCextern: 
     
    25962604                            { 
    25972605                                if (s->Sclass == SCstatic) 
    25982606                                    relinfo = RI_TYPE_TLS_LE;  // TLS_GD? 
    25992607                                else 
    26002608                                    relinfo = RI_TYPE_TLS_IE; 
    26012609                            } 
    26022610                            else 
    26032611                            { 
    26042612                                if (s->Sclass == SCstatic) 
    26052613                                    relinfo = RI_TYPE_TLS_LE; 
    26062614                                else 
    26072615                                    relinfo = RI_TYPE_TLS_IE; 
    26082616                            } 
    26092617                        } 
    26102618                    } 
    26112619                    if (flags & CFoffset64 && relinfo == R_X86_64_32) 
    26122620                    { 
    26132621                        relinfo = R_X86_64_64; 
    26142622                    } 
    26152623                    //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); 
    26172626                } 
    26182627outaddrval: 
    26192628                if (retsize == 8) 
    26202629                    buf->write64(val); 
    26212630                else 
    26222631                    buf->write32(val); 
    26232632                if (save > offset + retsize) 
    26242633                    buf->setsize(save); 
    26252634            } 
    26262635            break; 
    26272636 
    26282637        case SCsinline: 
    26292638        case SCeinline: 
    26302639            printf ("Undefined inline value <<fixme>>\n"); 
    26312640            //warerr(WM_undefined_inline,s->Sident); 
    26322641        case SCinline: 
    26332642            if (tyfunc(ty)) 
    26342643            { 
    26352644                s->Sclass = SCextern; 
    26362645                goto case_extern; 
     
    27702779         *      mov     [ECX],EAX 
    27712780         *      popad 
    27722781         *      ret 
    27732782         */ 
    27742783 
    27752784        const int reltype = I64 ? R_X86_64_32 : RI_TYPE_SYM32; 
    27762785        const int refsize = 4;                          // use 32 bit relocations, even in 64 bit mode 
    27772786 
    27782787        const int seg = CODE; 
    27792788        Outbuffer *buf = SegData[seg]->SDbuf; 
    27802789        SegData[seg]->SDoffset = buf->size(); 
    27812790        codeOffset = SegData[seg]->SDoffset + 1; 
    27822791        buf->writeByte(0xC3); /* ret */ 
    27832792 
    27842793        int off = 0; 
    27852794        if (I32) 
    27862795        {   buf->writeByte(0x60); // PUSHAD 
    27872796            off = 1; 
    27882797        } 
    27892798 
    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        } 
    27992826 
    28002827        buf->writeByte(0x8B); buf->writeByte(0x11); /* movl (%ecx), %edx */ 
    28012828        buf->writeByte(0x89); buf->writeByte(0x10); /* movl %edx, (%eax) */ 
    28022829        buf->writeByte(0x89); buf->writeByte(0x01); /* movl %eax, (%ecx) */ 
    28032830 
    28042831        if (I32) buf->writeByte(0x61); // POPAD 
    28052832        buf->writeByte(0xC3); /* ret */ 
    28062833        SegData[seg]->SDoffset = buf->size(); 
    28072834    } 
    28082835 
    28092836    /* Add reference to constructor into ".ctors" segment 
    28102837     */ 
    28112838    const int seg = elf_getsegment(".ctors", NULL, SHT_PROGDEF, SHF_ALLOC|SHF_WRITE, NPTRSIZE); 
    28122839 
    28132840    Outbuffer *buf = SegData[seg]->SDbuf; 
    28142841    buf->write32(codeOffset); 
    28152842    elf_addrel(seg, SegData[seg]->SDoffset, I64 ? R_X86_64_64 : RI_TYPE_SYM32, STI_TEXT, 0); 
    28162843    SegData[seg]->SDoffset += NPTRSIZE; 
    28172844} 
    28182845