⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 section.cc

📁 tcpmp.src.0.72RC1 优秀的多媒体播放器TCPMP的源代码
💻 CC
字号:
/********** * Copyright (c) 2004 Greg Parker.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY GREG PARKER ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. **********/#include <string>#include <vector>#include <stdint.h>#include "elf.h"#include "got.h"#include "swap.h"#include "image.h"#include "symbol.h"#include "complain.h"#include "relocation.h"#include "stringtable.h"#include "section.h"Section::Section(Image& newImage)    : mImage(newImage){ }Section::Section(Image &newImage, string newName, uint32_t newType, uint32_t newFlags, uint32_t newVMAddr, uint8_t *newContents, uint32_t newSize)    : mName(newName),       mType(newType),       mFlags(newFlags),       mVMaddr(newVMAddr),       mAlign(4),       mSize(newSize),       mContents(newContents),       mLink(0),       mInfo(0),       mEntrySize(0),       mImage(newImage),       mBaseSymbol(NULL){ }void Section::read(Elf32_Shdr *shdr){    if (mImage.strtab()) {        mName = (*mImage.strtab())[swap32(shdr->sh_name)];    } else {        mName = ".shstrtab";  // this is the section name strtab itself    }    mType = swap32(shdr->sh_type);    mFlags = swap32(shdr->sh_flags);    mVMaddr = swap32(shdr->sh_addr);    mAlign = swap32(shdr->sh_addralign);    mSize = swap32(shdr->sh_size);    mContents = mImage.contents() + swap32(shdr->sh_offset);    // relocations will be read later    mLink = 0;    mInfo = 0;    mEntrySize = swap32(shdr->sh_entsize);    mBaseSymbol = NULL;}void Section::reserveThumbThunk(const Relocation &r){    Thunk query(r.symbol(), r.addend());    vector<Thunk>::iterator t;    // fixme slow, should use hash_map    t = find(mThumbThunks.begin(), mThumbThunks.end(), query);    if (t == mThumbThunks.end()) mThumbThunks.push_back(query);}void Section::reserveARMThunk(const Relocation &r){    Thunk query(r.symbol(), r.addend());    vector<Thunk>::iterator t;    // fixme slow, should use hash_map    t = find(mARMThunks.begin(), mARMThunks.end(), query);    if (t == mARMThunks.end()) mARMThunks.push_back(query);}void Section::reserveThunkFromThumb(const Relocation &r, uint16_t insn1,                                     uint16_t insn2){    uint16_t opcode1 = insn1 >> 11;    uint16_t opcode2 = insn2 >> 11;    if (opcode1 == 0x001e  &&  opcode2 == 0x001f) {        // BL: Thumb->Thumb branch, use Thumb thunk        reserveThumbThunk(r);    } else if (opcode1 == 0x001e  &&  opcode2 == 0x001d) {        // BLX: Thumb->ARM branch, use ARM thunk        reserveARMThunk(r);    } else {        unimplemented("unexpected R_ARM_THM_PC22 relocation for Thumb insns "                      "0x%x, 0x%x", insn1, insn2);    }}void Section::reserveThunkFromARM(const Relocation &r, uint32_t insn){    uint32_t cond = (insn & 0xf0000000) >> 28;    uint32_t opcode = (insn & 0x0e000000) >> 25;    if (opcode == 0x05) {        if (cond == 0x0f) {            // BLX: ARM->Thumb branch, use Thumb thunk            reserveThumbThunk(r);        } else {            // Bcc, BLcc: ARM->ARM branch, use ARM thunk            reserveARMThunk(r);        }    } else {        // unknown instruction        unimplemented("unexpected R_ARM_PC24 relocation for ARM insn 0x%x",                       insn);    }}void Section::applyRelocations(Elf32_Shdr *rhdr){    Elf32_Rel *rel = (Elf32_Rel *)        (mImage.contents() + swap32(rhdr->sh_offset));    Elf32_Rel *relEnd = (Elf32_Rel *)        ((uint8_t *)rel + swap32(rhdr->sh_size));        for ( ; rel < relEnd; ++rel) {        Relocation r(rel, mImage.symtab(), *this);        const Section *symSection = r.symbol()->section();        if (!symSection) unimplemented("relocation relative to absolute or common symbol");        
		uint32_t symoffset = symSection->vmaddr();
		Symbol *sym = symSection->baseSymbol();
		if (symSection->isLib())
		{
			sym = r.symbol();
			symoffset += sym->offset();
		}
        switch (r.type()) {        case R_ARM_PC24:            // Linker stored the offset from here to a symbol in a branch insn.            // This needs no additional relocation if here and the symbol             // are in the same section.            if (this == symSection) {                // Source and dest are in the same section - nothing to do            } else {                // Source and dest are in different sections, which may slide                // relative to each other - create a relocation and a thunk                int32_t offset = peek32(r.offset()) & 0x00ffffff; // SIGNED!!                // sign-extend and convert to byte offset from start of insn                offset = ((offset << 8) >> 8) * 4 + 8;                Relocation r2 = Relocation(R_ARM_PC24, r.offset(),                                            sym,                                            vmaddr() + r.offset() +                                            offset - symoffset);                mRelocations.push_back(r2);                reserveThunkFromARM(r2, peek32(r.offset()));            }            break;        case R_ARM_THM_PC22:            // Like R_ARM_PC24, except each of the next two Thumb             // instructions contains half of a 22-bit offset.            if (this == symSection) {                // Source and dest are in the same section - nothing to do            } else {                // Source and dest are in different sections, which may slide                // relative to each other - create a relocation and a thunk                int32_t offset_hi = peek16(r.offset()) & 0x07ff;                int32_t offset_lo = peek16(r.offset()+2) & 0x07ff;                int32_t offset = (offset_hi << 11) | offset_lo;                // sign-extend and convert to byte offset from start of insn                offset = ((offset << 10) >> 10) * 2 + 4;                Relocation r2 = Relocation(R_ARM_THM_PC22, r.offset(),                                            sym,                                            vmaddr() + r.offset() +                                            offset - symoffset);                                mRelocations.push_back(r2);                reserveThunkFromThumb(r2, peek16(r.offset()),                                      peek16(r.offset()+2));            }            break;        case R_ARM_GOTOFF:            // Linker stored the offset from the GOT to a target symbol.            // This needs no additional relocation if the symbol is in r/w mem.            if (!symSection->isReadOnly()) {                // Target symbol is in a r/w section - nothing to do                // At runtime, the GOT and all r/w sections will be                 // in the same places relative to each other, so                 // linker-generated GOT offsets will be correct.            } else {                // Target symbol is in a r/o section - create relocation                // At runtime, the GOT and the r/o sections will move                 // relative to each other.                 mRelocations.push_back                    (Relocation(R_ARM_GOTOFF, r.offset(),                                symSection->baseSymbol(),                                 peek32(r.offset()) - (symSection->vmaddr() - mImage.got().vmaddr())));            }            break;        case R_ARM_GOT32: {            // Linker stored the absolute address of a symbol in the GOT.             // Find the GOT entry containing the symbol, and create a             // relocation that will change the *GOT entry* at runtime.            // These new relocations aren't actually created until             // GOT::buildRelocations() is called.            uint32_t sym_vmaddr = r.symbol()->vmaddr(thumb);            GOT& got = mImage.got();            unsigned int g;            for (g = 0; g < got.entries().size(); g++) {                if (got.entries()[g] == sym_vmaddr) {                    if (got.symbols()[g] == NULL) {                        got.symbols()[g] = r.symbol();                    } else if (got.symbols()[g] != r.symbol()) {                        error("single GOT entry has multiple R_ARM_GOT32 uses");                    }                    break;                }            }            if (g == got.entries().size()) {                error("R_ARM_GOT32 relocation has no associated GOT entry (symbol %s, symbol vmaddr 0x%x, section %s", r.symbol()->name().c_str(), sym_vmaddr, symSection->name().c_str());            }            break;        }        case R_ARM_ABS32:			// Linker stored an absolute address at r.offset() in this section			// Subtract symbol section's linker-determined vmaddr and relocate 			// at runtime using symbol section's base symbol.			mRelocations.push_back				(Relocation(R_ARM_ABS32, r.offset(), sym, 							peek32(r.offset()) - symoffset));
            break;        case R_ARM_REL32:            // Linker stored the offset between here and the symbol.            // If here and the symbol are in different sections, they             // may move relative to each other at runtime.             if (this == symSection) {                // Source and dest are in the same section - nothing to do			}
			else {                // Source and dest are in different sections, which may slide                // relative to each other - create a relocation
                mRelocations.push_back                    (Relocation(R_ARM_REL32, r.offset(),                                 sym,                                 vmaddr() + r.offset() + peek32(r.offset()) - symoffset));            }            break;        case R_ARM_GOTPC:            // Like R_ARM_REL32, but the symbol is the start of the GOT.            // Replace with an ordinary R_ARM_REL32 relocation that uses             // the GOT's section symbol instead of _GLOBAL_OFFSET_TABLE_.            if (isReadOnly()) {                mRelocations.push_back                    (Relocation(R_ARM_REL32, r.offset(),                                mImage.got().baseSymbol(),                                 vmaddr() + r.offset() + peek32(r.offset()) - mImage.got().vmaddr()));            } else {                // read/write sections do not move relative to the GOT.            }            break;        case R_ARM_PLT32:            if (this != symSection) 
				warning("ignoring R_ARM_PLT32 relocation (symbol '%s')", 						r.symbol()->name().c_str());            break;                    default:            unimplemented("relocation type %d", r.type());            break;        }    }}bool Section::isLib(void) const { return strncmp(mName.c_str(),".lib",4)==0; }
bool Section::isReadOnly(void) const { return ! (mFlags & SHF_WRITE); }const string& Section::name(void) const { return mName; }uint32_t Section::vmaddr(void) const { return mVMaddr; }uint32_t Section::type(void) const { return mType; }Symbol *Section::baseSymbol(void) const {    if (!mBaseSymbol) {        mBaseSymbol = new Symbol(mName, this, 0, STB_WEAK, STT_SECTION);    }    return mBaseSymbol;}void Section::setLink(uint32_t newLink) { mLink = newLink; }void Section::setInfo(uint32_t newInfo) { mInfo = newInfo; }void Section::setEntrySize(uint32_t newEntrySize) { mEntrySize = newEntrySize; }void Section::emit(Elf32_Shdr *shdr, uint8_t *&buf, uint32_t& bufLen){    uint32_t offset = bufLen;    // add blank space for relocation thunks    mThunkSize = 0;    mThunkSize += mThumbThunks.size() * 16;       // Thumb thunks 16 bytes each    mThunkSize += mARMThunks.size() * 8;          // ARM thunks 8 bytes each    if (mThunkSize && (mSize % 4)) mThunkSize += 4 - (mSize%4);  // thunks are 4-byte aligned    mSize += mThunkSize;    // write shdr before buf gets reallocated (shdr points into buf)    shdr->sh_name = swap32(mImage.strtab()->indexOf(mName));    shdr->sh_type = swap32(mType);    shdr->sh_flags = swap32(mFlags);    shdr->sh_addr = swap32(mVMaddr);    shdr->sh_offset = swap32(offset);    shdr->sh_size = swap32(mSize);    shdr->sh_link = swap32(mLink);    shdr->sh_info = swap32(mInfo);    shdr->sh_addralign = swap32(mAlign);    shdr->sh_entsize = swap32(mEntrySize);    if (mType != SHT_NOBITS) {        bufLen += mSize;        buf = (uint8_t *)realloc(buf, bufLen);        memcpy(buf+offset, mContents, mSize - mThunkSize);        memset(buf+offset+mSize-mThunkSize, 0, mThunkSize);    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -