示例#1
0
文件: machoexport.cpp 项目: 8l/polyml
/* Get the index corresponding to an address. */
PolyWord MachoExport::createRelocation(PolyWord p, void *relocAddr)
{
    void *addr = p.AsAddress();
    unsigned addrArea = findArea(addr);
    POLYUNSIGNED offset = (char*)addr - (char*)memTable[addrArea].mtAddr;
    adjustOffset(addrArea, offset);

    // It looks as though struct relocation_info entries are only used
    // with GENERIC_RELOC_VANILLA types.
    struct relocation_info relInfo;
    setRelocationAddress(relocAddr, &relInfo.r_address);
    relInfo.r_symbolnum = addrArea+1; // Section numbers start at 1
    relInfo.r_pcrel = 0;
#if (SIZEOF_VOIDP == 8)
    relInfo.r_length = 3; // 8 bytes
    relInfo.r_type = X86_64_RELOC_UNSIGNED;
#else
    relInfo.r_length = 2; // 4 bytes
    relInfo.r_type = GENERIC_RELOC_VANILLA;
#endif
    relInfo.r_extern = 0; // r_symbolnum is a section number.  It should be 1 if we make the IO area a common.

    fwrite(&relInfo, sizeof(relInfo), 1, exportFile);
    relocationCount++;
    return PolyWord::FromUnsigned(offset);
}
示例#2
0
// Create a relocation entry for an address at a given location.
PolyWord SaveStateExport::createRelocation(PolyWord p, void *relocAddr)
{
    RelocationEntry reloc;
    // Set the offset within the section we're scanning.
    setRelocationAddress(relocAddr, &reloc.relocAddress);
    void *addr = p.AsAddress();
    unsigned addrArea = findArea(addr);
    reloc.targetAddress = (char*)addr - (char*)memTable[addrArea].mtAddr;
    reloc.targetSegment = (unsigned)memTable[addrArea].mtIndex;
    reloc.relKind = PROCESS_RELOC_DIRECT;
    fwrite(&reloc, sizeof(reloc), 1, exportFile);
    relocationCount++;
    return p; // Don't change the contents
}
示例#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 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++;
}
示例#4
0
文件: machoexport.cpp 项目: 8l/polyml
/* 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.
    }
}
示例#5
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.
    }
}