Example #1
0
// Process a constant within the code.  This is a direct copy of ScanAddress::ScanConstant
// with the addition of the locking.
void MTGCProcessMarkPointers::ScanConstant(byte *addressOfConstant, ScanRelocationKind code)
{
    // If this code is in the local area there's the possibility that
    // ScanObjectAddress could return an updated address for a
    // constant within the code.  This could happen if the code is
    // in the allocation area or if it has been moved into the
    // mutable/immutable area by the last incomplete partial GC.
    // Constants can be aligned on any byte offset so another thread
    // scanning the same code could see an invalid address if it read
    // the constant while it was being updated.  We put a lock round
    // this just in case.
    LocalMemSpace *space = gMem.LocalSpaceForAddress(addressOfConstant);

    if (space != 0)
        space->spaceLock.Lock();
    PolyWord p = GetConstantValue(addressOfConstant, code);
    if (space != 0)
        space->spaceLock.Unlock();

    if (! IS_INT(p))
    {
        PolyWord oldValue = p;
        ScanAddress::ScanAddressAt(&p);
        if (p != oldValue) // Update it if it has changed.
        {
            if (space != 0)
                space->spaceLock.Lock();
            SetConstantValue(addressOfConstant, p, code);
            if (space != 0)
                space->spaceLock.Unlock();
        }
    }
}
 string UserConstExpression::ToString() const
 {
     auto Op = GetOp();
     if (Op->IsAnon()) {
         return Op->GetConstantValue()->ToString();
     } else {
         return Op->GetName();
     }
 }
Example #3
0
/* This is called for each constant within the code. 
   Print a relocation entry for the word and return a value that means
   that the offset is saved in original word. */
void PExport::ScanConstant(byte *addr, ScanRelocationKind code)
{
    PolyWord p = GetConstantValue(addr, code);
    // We put in all the values including tagged constants.
    PolyObject *obj = ObjCodePtrToPtr(addr);
    // Put in the byte offset and the relocation type code.
    fprintf(exportFile, "%" POLYUFMT ",%d,", (POLYUNSIGNED)(addr - (byte*)obj), code);
    printValue(p); // The value to plug in.
    fprintf(exportFile, " ");
}
Example #4
0
// The default action is to call the DEFAULT ScanAddressAt NOT the virtual which means that it calls
// ScanObjectAddress for the base address of the object referred to.
void ScanAddress::ScanConstant(byte *addressOfConstant, ScanRelocationKind code)
{
    PolyWord p = GetConstantValue(addressOfConstant, code);

    if (! IS_INT(p))
    {
        PolyWord oldValue = p;
        ScanAddress::ScanAddressAt(&p);
        if (p != oldValue) // Update it if it has changed.
            SetConstantValue(addressOfConstant, p, code);
    }
}
Example #5
0
// How a button saves itself to a file
int MyButton::SaveLayout(FILE *fp) {
    switch ( GetButtonType() ) {
        case FL_OP_INPUT_BUTTON:
            fprintf(fp, "    in \"%s\"\n", label());
            break;
        case FL_OP_OUTPUT_BUTTON:
            fprintf(fp, "    out \"%s\"\n", label());
            break;
    }
    if ( GetConstantValue() != "" ) {
        std::string dt;
        fprintf(fp, "    {\n");
        fprintf(fp, "        dtype %s\n", GetDataTypeStr().c_str());
        fprintf(fp, "        const %s\n", GetConstantValue().c_str());
        fprintf(fp, "    }\n");
    } else {
        fprintf(fp, "    {\n");
        fprintf(fp, "        dtype %s\n", GetDataTypeStr().c_str());
        fprintf(fp, "    }\n");
    }
    return(0);
}
Example #6
0
/* This is called for each constant within the code. 
   Print a relocation entry for the word and return a value that means
   that the offset is saved in original word. */
void SaveStateExport::ScanConstant(byte *addr, ScanRelocationKind code)
{
    PolyWord p = GetConstantValue(addr, code);

    if (IS_INT(p) || p == PolyWord::FromUnsigned(0))
        return;

    void *a = p.AsAddress();
    unsigned aArea = findArea(a);

    // We don't need a relocation if this is relative to the current segment
    // since the relative address will already be right.
    if (code == PROCESS_RELOC_I386RELATIVE && aArea == findArea(addr))
        return;

    // Set the value at the address to the offset relative to the symbol.
    RelocationEntry reloc;
    setRelocationAddress(addr, &reloc.relocAddress);
    reloc.targetAddress = (char*)a - (char*)memTable[aArea].mtAddr;
    reloc.targetSegment = (unsigned)memTable[aArea].mtIndex;
    reloc.relKind = code;
    fwrite(&reloc, sizeof(reloc), 1, exportFile);
    relocationCount++;
}
Example #7
0
/* This is called for each constant within the code. 
   Print a relocation entry for the word and return a value that means
   that the offset is saved in original word. */
void MachoExport::ScanConstant(byte *addr, ScanRelocationKind code)
{
    PolyWord p = GetConstantValue(addr, code);

    if (IS_INT(p) || p == PolyWord::FromUnsigned(0))
        return;

    void *a = p.AsAddress();
    unsigned aArea = findArea(a);

    // Set the value at the address to the offset relative to the symbol.
    POLYUNSIGNED offset = (char*)a - (char*)memTable[aArea].mtAddr;
    adjustOffset(aArea, offset);

    switch (code)
    {
    case PROCESS_RELOC_DIRECT: // 32 bit address of target
        {
            struct relocation_info reloc;
            setRelocationAddress(addr, &reloc.r_address);
            reloc.r_symbolnum = aArea+1; // Section numbers start at 1
            reloc.r_pcrel = 0;
#if (defined(HOSTARCHITECTURE_X86_64))
            reloc.r_length = 3; // 8 bytes
            reloc.r_type = X86_64_RELOC_UNSIGNED;
#else
            reloc.r_length = 2; // 4 bytes
            reloc.r_type = GENERIC_RELOC_VANILLA;
#endif
            reloc.r_extern = 0; // r_symbolnum is a section number.  It should be 1 if we make the IO area a common.

            for (unsigned i = 0; i < sizeof(PolyWord); i++)
            {
                addr[i] = (byte)(offset & 0xff);
                offset >>= 8;
            }
            fwrite(&reloc, sizeof(reloc), 1, exportFile);
            relocationCount++;
        }
        break;
#if (defined(HOSTARCHITECTURE_X86) || defined(HOSTARCHITECTURE_X86_64))
     case PROCESS_RELOC_I386RELATIVE:         // 32 bit relative address
        {
            unsigned addrArea = findArea(addr);
            // If it's in the same area we don't need a relocation because the
            // relative offset will be unchanged.
            if (addrArea != aArea)
            {
                struct relocation_info reloc;
                setRelocationAddress(addr, &reloc.r_address);
                reloc.r_symbolnum = aArea+1; // Section numbers start at 1
                reloc.r_pcrel = 1;
                reloc.r_length = 2; // 4 bytes
#if (defined(HOSTARCHITECTURE_X86_64))
                reloc.r_type = X86_64_RELOC_SIGNED;
#else
                reloc.r_type = GENERIC_RELOC_VANILLA;
#endif
                reloc.r_extern = 0; // r_symbolnum is a section number.
                fwrite(&reloc, sizeof(reloc), 1, exportFile);
                relocationCount++;

                POLYUNSIGNED addrOffset = (char*)addr - (char*)memTable[addrArea].mtAddr;
                adjustOffset(addrArea, addrOffset);
                offset -= addrOffset + 4;

                for (unsigned i = 0; i < 4; i++)
                {
                    addr[i] = (byte)(offset & 0xff);
                    offset >>= 8;
                }
            }
        }
        break;
#endif
        default:
            ASSERT(0); // Wrong type of relocation for this architecture.
    }
}
Example #8
0
/* This is called for each constant within the code. 
   Print a relocation entry for the word and return a value that means
   that the offset is saved in original word. */
void MachoExport::ScanConstant(byte *addr, ScanRelocationKind code)
{
    PolyWord p = GetConstantValue(addr, code);

    if (IS_INT(p) || p == PolyWord::FromUnsigned(0))
        return;

    void *a = p.AsAddress();
    unsigned aArea = findArea(a);

    // Set the value at the address to the offset relative to the symbol.
    POLYUNSIGNED offset = (char*)a - (char*)memTable[aArea].mtAddr;
    adjustOffset(aArea, offset);

    switch (code)
    {
    case PROCESS_RELOC_DIRECT: // 32 bit address of target
        {
            struct relocation_info reloc;
            setRelocationAddress(addr, &reloc.r_address);
            reloc.r_symbolnum = aArea+1; // Section numbers start at 1
            reloc.r_pcrel = 0;
#if (defined(HOSTARCHITECTURE_X86_64))
            reloc.r_length = 3; // 8 bytes
            reloc.r_type = X86_64_RELOC_UNSIGNED;
#else
            reloc.r_length = 2; // 4 bytes
            reloc.r_type = GENERIC_RELOC_VANILLA;
#endif
            reloc.r_extern = 0; // r_symbolnum is a section number.  It should be 1 if we make the IO area a common.

            for (unsigned i = 0; i < sizeof(PolyWord); i++)
            {
                addr[i] = (byte)(offset & 0xff);
                offset >>= 8;
            }
            fwrite(&reloc, sizeof(reloc), 1, exportFile);
            relocationCount++;
        }
        break;
#if (defined(HOSTARCHITECTURE_X86))
     case PROCESS_RELOC_I386RELATIVE:         // 32 bit relative address
        {
            unsigned addrArea = findArea(addr);
            // If it's in the same area we don't need a relocation because the
            // relative offset will be unchanged.
            if (addrArea != aArea)
            {
                struct relocation_info reloc;
                setRelocationAddress(addr, &reloc.r_address);
                reloc.r_symbolnum = aArea+1; // Section numbers start at 1
                reloc.r_pcrel = 1;
                reloc.r_length = 2; // 4 bytes
                reloc.r_type = GENERIC_RELOC_VANILLA;
                reloc.r_extern = 0; // r_symbolnum is a section number.
                fwrite(&reloc, sizeof(reloc), 1, exportFile);
                relocationCount++;

                POLYUNSIGNED addrOffset = (char*)addr - (char*)memTable[addrArea].mtAddr;
                adjustOffset(addrArea, addrOffset);
                offset -= addrOffset + 4;

                for (unsigned i = 0; i < sizeof(PolyWord); i++)
                {
                    addr[i] = (byte)(offset & 0xff);
                    offset >>= 8;
                }
            }
        }
        break;
#endif
#ifdef HOSTARCHITECTURE_PPC
    case PROCESS_RELOC_PPCDUAL16SIGNED:       // Power PC - two consecutive words
    case PROCESS_RELOC_PPCDUAL16UNSIGNED:
        {
            struct relocation_info reloc;
            setRelocationAddress(addr, &reloc.r_address);
            POLYUNSIGNED hi = offset >> 16; // N.B. No adjustment yet.
            POLYUNSIGNED lo = offset & 0xffff;
            // We use two consecutive words for our address but Mach-O requires separate
            // relocations for each.  It stores one half of the address in the instruction
            // itself and the other half is carried in a PPC_RELOC_PAIR relocation entry.
            // We need four relocations here in total.
            reloc.r_symbolnum = aArea+1; // Section numbers start at 1
            reloc.r_extern = 0; // r_symbolnum is a section number.
            reloc.r_pcrel = 0;
            reloc.r_length = 2; // 4 bytes
            reloc.r_type = code == PROCESS_RELOC_PPCDUAL16SIGNED ? PPC_RELOC_HA16 : PPC_RELOC_HI16;
            fwrite(&reloc, sizeof(reloc), 1, exportFile);
            relocationCount++;
            // Next must be a "pair" containing the low-order part of the address.
            // The high-order part is stored in the instruction.
            reloc.r_symbolnum = 0xffffff; // Not sure why 
            reloc.r_type = PPC_RELOC_PAIR;
            reloc.r_extern = 0;
            reloc.r_pcrel = 0;
            reloc.r_address = lo;
            fwrite(&reloc, sizeof(reloc), 1, exportFile);
            relocationCount++;

            // Now the low-order part.
            setRelocationAddress(addr+sizeof(PolyWord), &reloc.r_address);
            reloc.r_symbolnum = aArea+1; // Section numbers start at 1
            reloc.r_extern = 0; // r_symbolnum is a section number.
            reloc.r_pcrel = 0;
            reloc.r_length = 2; // 4 bytes
            reloc.r_type = PPC_RELOC_LO16;
            fwrite(&reloc, sizeof(reloc), 1, exportFile);
            relocationCount++;
            // Finally a "pair" containing the high-order part of the address to
            // match the low-order part in the instruction.
            reloc.r_symbolnum = 0xffffff; // Not sure why 
            reloc.r_type = PPC_RELOC_PAIR;
            reloc.r_extern = 0;
            reloc.r_pcrel = 0;
            reloc.r_address = hi; // Must NOT be adjusted for sign extension.
            fwrite(&reloc, sizeof(reloc), 1, exportFile);
            relocationCount++;
             // Adjust for sign extension and store in the instruction.
            if ((lo & 0x8000) && (code == PROCESS_RELOC_PPCDUAL16SIGNED)) hi++;
            POLYUNSIGNED *pt = (POLYUNSIGNED *)addr;
            // Store the offset into the instructions.
            pt[0] = (pt[0] & 0xffff0000) | hi;
            pt[1] = (pt[1] & 0xffff0000) | lo;
       }
        break;
#endif
        default:
            ASSERT(0); // Wrong type of relocation for this architecture.
    }
}