void ElfSectionManager::AddSection(ElfSection & aSection){
	EnsureSectionStringTableSectionAdded();
	if (aSection.GetName().size() > 0){
		// rename sections for GDB (yuk!)
		String sectionName(aSection.GetName());
		String ro("ER_RO");
		String text(".text");
		if (sectionName == ro){
			sectionName = text;
		} else {
			String rw("ER_RW");
			String data(".data");
			if (sectionName == rw){
				sectionName = data;
			} else {
				String zi("ER_ZI");
				String bss(".bss");
				if (sectionName == zi)
					sectionName = bss;
			}
		}
		size_t nameOffset = iStringTable.AddName(sectionName);
		aSection.SetNameOffset(nameOffset);
	} else {
		// use the initial Null String.
		size_t nameOffset = iStringTable.AllocateInitialNullString();
		aSection.SetNameOffset(nameOffset);
	}
	aSection.SetIndex(iSections.size());
	iSections.push_back(aSection);
	iElf32Header.AddSectionHdr();
}
Ejemplo n.º 2
0
status_t
DwarfImageDebugInfo::Init()
{
	status_t error = fLock.InitCheck();
	if (error != B_OK)
		return error;

	fTextSegment = fFile->GetElfFile()->TextSegment();
	if (fTextSegment == NULL)
		return B_ENTRY_NOT_FOUND;

	fRelocationDelta = fImageInfo.TextBase() - fTextSegment->LoadAddress();

	ElfSection* section = fFile->GetElfFile()->FindSection(".text");
	if (section != NULL) {
		fTextSectionStart = section->LoadAddress() + fRelocationDelta;
		fTextSectionEnd = fTextSectionStart + section->Size();
	}

	section = fFile->GetElfFile()->FindSection(".plt");
	if (section != NULL) {
		fPLTSectionStart = section->LoadAddress() + fRelocationDelta;
		fPLTSectionEnd = fPLTSectionStart + section->Size();
	}

	return B_OK;
}
Ejemplo n.º 3
0
void ElfFile::loadSectionNames()
{
	if (fileHeader.e_shstrndx == SHN_UNDEF) return;

	// check if the string table is actually a string table
	// sometimes it gives the wrong section id
	int strTablePos = sections[fileHeader.e_shstrndx]->getOffset();
	int strTableSize = sections[fileHeader.e_shstrndx]->getSize();
	for (int i = 0; i < strTableSize; i++)
	{
		if (fileData[strTablePos+i] != 0 && fileData[strTablePos+i] < 0x20)
			return;
		if (fileData[strTablePos+i] > 0x7F)
			return;
	}

	for (int i = 0; i < (int)sections.size(); i++)
	{
		ElfSection* section = sections[i];
		if (section->getType() == SHT_NULL) continue;

		int strTablePos = sections[fileHeader.e_shstrndx]->getOffset();
		int offset = strTablePos+section->getNameOffset();

		char* name = (char*) fileData.data(offset);
		std::string strName = name;
		section->setName(strName);
	}
}
Ejemplo n.º 4
0
void
ElfSymbol::Write(Bytes& bytes, const ElfConfig& config, Diagnostic& diags)
{
    // Pull referenced elf symbol information type and size
    if (m_value_rel)
    {
        ElfSymbol* elfrel = m_value_rel->getAssocData<ElfSymbol>();
        if (elfrel)
        {
            if (!hasType() && elfrel->hasType())
                m_type = elfrel->m_type;
            if (!hasSize() && elfrel->hasSize())
            {
                m_size = elfrel->m_size;
                m_size_source = elfrel->m_size_source;
                // just in case, simplify it
                SimplifyCalcDist(m_size, diags);
                if (!m_size.isIntNum())
                    diags.Report(m_size_source, diag::err_size_integer);
            }
        }
    }

    bytes.resize(0);
    config.setEndian(bytes);

    Write32(bytes, m_name_index);

    if (config.cls == ELFCLASS32)
    {
        Write32(bytes, m_value);
        Write32(bytes, hasSize() && m_size.isIntNum() ? m_size.getIntNum() : 0);
    }

    Write8(bytes, ELF_ST_INFO(m_bind, m_type));
    Write8(bytes, ELF_ST_OTHER(m_vis));

    if (m_sect)
    {
        ElfSection* elfsect = m_sect->getAssocData<ElfSection>();
        assert(elfsect != 0);
        Write16(bytes, elfsect->getIndex());
    }
    else
    {
        Write16(bytes, m_index);
    }

    if (config.cls == ELFCLASS64)
    {
        Write64(bytes, m_value);
        Write64(bytes, hasSize() ? m_size.getIntNum() : 0);
    }

    if (config.cls == ELFCLASS32)
        assert(bytes.size() == SYMTAB32_SIZE);
    else if (config.cls == ELFCLASS64)
        assert(bytes.size() == SYMTAB64_SIZE);
}
Ejemplo n.º 5
0
ElfSection*
ElfFile::GetSection(const char* name)
{
	ElfSection* section = FindSection(name);
	if (section != NULL && section->Load() == B_OK)
		return section;

	return NULL;
}
Ejemplo n.º 6
0
ElfSection*
ElfFile::FindSection(uint32 type) const
{
	int32 count = fSections.CountItems();
	for (int32 i = 0; i < count; i++) {
		ElfSection* section = fSections.ItemAt(i);
		if (section->Type() == type)
			return section;
	}

	return NULL;
}
Ejemplo n.º 7
0
ElfSection*
ElfFile::FindSection(const char* name) const
{
	int32 count = fSections.CountItems();
	for (int32 i = 0; i < count; i++) {
		ElfSection* section = fSections.ItemAt(i);
		if (strcmp(section->Name(), name) == 0)
			return section;
	}

	return NULL;
}
Ejemplo n.º 8
0
ElfSymbol::ElfSymbol(const ElfConfig&           config,
                     const llvm::MemoryBuffer&  in,
                     const ElfSection&          symtab_sect,
                     ElfSymbolIndex             index,
                     Section*                   sections[],
                     Diagnostic&                diags)
    : m_sect(0)
    , m_name_index(0)
    , m_value(0)
    , m_symindex(index)
    , m_in_table(true)
    , m_weak_ref(false)
    , m_weak_refr(false)
{
    InputBuffer inbuf(in);

    ElfSize symsize = symtab_sect.getEntSize();
    inbuf.setPosition(symtab_sect.getFileOffset() + index * symsize);
    if (inbuf.getReadableSize() < symsize)
    {
        diags.Report(SourceLocation(), diag::err_symbol_unreadable);
        return;
    }

    config.setEndian(inbuf);

    m_name_index = ReadU32(inbuf);

    if (config.cls == ELFCLASS32)
    {
        m_value = ReadU32(inbuf);
        m_size = Expr(ReadU32(inbuf));
    }

    unsigned char info = ReadU8(inbuf);
    m_bind = ELF_ST_BIND(info);
    m_type = ELF_ST_TYPE(info);
    m_vis = ELF_ST_VISIBILITY(ReadU8(inbuf));

    m_index = static_cast<ElfSectionIndex>(ReadU16(inbuf));
    if (m_index != SHN_UNDEF && m_index < config.secthead_count)
        m_sect = sections[m_index];

    if (config.cls == ELFCLASS64)
    {
        m_value = ReadU64(inbuf);
        m_size = Expr(ReadU64(inbuf));
    }
}
Ejemplo n.º 9
0
bool
ElfFile::_FindSymbolSections(ElfSection*& _symbolSection,
	ElfSection*& _stringSection, uint32 type) const
{
	// get the symbol table section
	ElfSection* symbolSection = FindSection(type);
	if (symbolSection == NULL)
		return false;

	// The symbol table section is linked to the corresponding string section.
	ElfSection* stringSection = SectionAt(symbolSection->LinkIndex());
	if (stringSection == NULL || stringSection->Type() != SHT_STRTAB)
		return false;

	_symbolSection = symbolSection;
	_stringSection = stringSection;
	return true;
}
Ejemplo n.º 10
0
bool
ElfConfig::ReadSymbolTable(const MemoryBuffer&  in,
                           const ElfSection&    symtab_sect,
                           ElfSymtab&           symtab,
                           Object&              object,
                           const StringTable&   strtab,
                           Section*             sections[],
                           DiagnosticsEngine&   diags) const
{
    ElfSize symsize = symtab_sect.getEntSize();
    if (symsize == 0)
    {
        diags.Report(SourceLocation(), diag::err_symbol_entity_size_zero);
        return false;
    }

    unsigned long size = symtab_sect.getSize().getUInt();

    // Symbol table always starts with null entry
    symtab.push_back(SymbolRef(0));

    ElfSymbolIndex index = 1;
    for (unsigned long pos=symsize; pos<size; pos += symsize, ++index)
    {
        std::auto_ptr<ElfSymbol> elfsym(
            new ElfSymbol(*this, in, symtab_sect, index, sections, diags));
        if (diags.hasErrorOccurred())
            return false;

        SymbolRef sym = elfsym->CreateSymbol(object, strtab);
        symtab.push_back(sym);

        if (sym)
            sym->AddAssocData(elfsym);  // Associate symbol data with symbol
    }
    return true;
}
Ejemplo n.º 11
0
    void serialize(std::ofstream &file, char ei_class, char ei_data)
    {
        // Readjust code offsets
        for (std::vector<ElfSection *>::iterator c = code.begin(); c != code.end(); c++)
            (*c)->getShdr().sh_addr += getAddr();

        // Apply relocations
        for (ElfSection *rel = elf->getSection(1); rel != NULL; rel = rel->getNext())
            if ((rel->getType() == SHT_REL) || (rel->getType() == SHT_RELA)) {
                ElfSection *section = rel->getInfo().section;
                if ((section->getType() == SHT_PROGBITS) && (section->getFlags() & SHF_EXECINSTR)) {
                    if (rel->getType() == SHT_REL)
                        apply_relocations((ElfRel_Section<Elf_Rel> *)rel, section);
                    else
                        apply_relocations((ElfRel_Section<Elf_Rela> *)rel, section);
                }
            }

        ElfSection::serialize(file, ei_class, ei_data);
    }
Ejemplo n.º 12
0
bool ElfFile::load(ByteArray& data, bool sort)
{
	fileData = data;

	memcpy(&fileHeader,&fileData[0],sizeof(Elf32_Ehdr));
	symTab = NULL;
	strTab = NULL;

	// load segments
	for (int i = 0; i < fileHeader.e_phnum; i++)
	{
		int pos = fileHeader.e_phoff+i*fileHeader.e_phentsize;
		
		Elf32_Phdr sectionHeader;
		memcpy(&sectionHeader,&fileData[pos],sizeof(Elf32_Phdr));

		ByteArray segmentData = fileData.mid(sectionHeader.p_offset,sectionHeader.p_filesz);
		ElfSegment* segment = new ElfSegment(sectionHeader,segmentData);
		segments.push_back(segment);
	}
	
	// load sections and assign them to segments
	for (int i = 0; i < fileHeader.e_shnum; i++)
	{
		int pos = fileHeader.e_shoff+i*fileHeader.e_shentsize;

		Elf32_Shdr sectionHeader;
		memcpy(&sectionHeader,&fileData[pos],sizeof(Elf32_Shdr));

		ElfSection* section = new ElfSection(sectionHeader);
		sections.push_back(section);

		// check if the section belongs to a segment
		ElfSegment* owner = NULL;
		for (int k = 0; k < (int)segments.size(); k++)
		{
			if (segments[k]->isSectionPartOf(section))
			{
				owner = segments[k];
				break;
			}
		}

		if (owner != NULL)
		{
			owner->addSection(section);
		} else {
			if (section->getType() != SHT_NOBITS && section->getType() != SHT_NULL)
			{
				ByteArray data = fileData.mid(section->getOffset(),section->getSize());
				section->setData(data);
			}

			switch (section->getType())
			{
			case SHT_SYMTAB:
				symTab = section;
				break;
			case SHT_STRTAB:
				strTab = section;
				break;
			}

			segmentlessSections.push_back(section);
		}
	}
	
	determinePartOrder();
	loadSectionNames();

	if (sort)
	{
		std::sort(segmentlessSections.begin(),segmentlessSections.end(),compareSection);

		for (int i = 0; i < (int)segments.size(); i++)
		{
			segments[i]->sortSections();
		}
	}

	return true;
}
Ejemplo n.º 13
0
bool ElfRelocator::init(const std::wstring& inputName)
{
	relocator = Arch->getElfRelocator();
	if (relocator == NULL)
	{
		Logger::printError(Logger::Error,L"Object importing not supported for this architecture");
		return false;
	}

	auto inputFiles = loadArArchive(inputName);
	if (inputFiles.size() == 0)
	{
		Logger::printError(Logger::Error,L"Could not load library");
		return false;
	}

	for (ArFileEntry& entry: inputFiles)
	{
		ElfRelocatorFile file;

		ElfFile* elf = new ElfFile();
		if (elf->load(entry.data,false) == false)
		{
			Logger::printError(Logger::Error,L"Could not load object file %s",entry.name);
			return false;
		}

		if (elf->getType() != 1)
		{
			Logger::printError(Logger::Error,L"Unexpected ELF type %d in object file %s",elf->getType(),entry.name);
			return false;
		}

		if (elf->getSegmentCount() != 0)
		{
			Logger::printError(Logger::Error,L"Unexpected segment count %d in object file %s",elf->getSegmentCount(),entry.name);
			return false;
		}

		// load all relevant sections of this file
		for (size_t s = 0; s < elf->getSegmentlessSectionCount(); s++)
		{
			ElfSection* sec = elf->getSegmentlessSection(s);
			if (!(sec->getFlags() & SHF_ALLOC))
				continue;

			if (sec->getType() == SHT_PROGBITS || sec->getType() == SHT_NOBITS || sec->getType() == SHT_INIT_ARRAY)
			{
				ElfRelocatorSection sectionEntry;
				sectionEntry.section = sec;
				sectionEntry.index = s;
				sectionEntry.relSection = NULL;
				sectionEntry.label = NULL;

				// search relocation section
				for (size_t k = 0; k < elf->getSegmentlessSectionCount(); k++)
				{
					ElfSection* relSection = elf->getSegmentlessSection(k);
					if (relSection->getType() != SHT_REL)
						continue;
					if (relSection->getInfo() != s)
						continue;

					// got it
					sectionEntry.relSection = relSection;
					break;
				}

				// keep track of constructor sections
				if (sec->getName() == ".ctors" || sec->getName() == ".init_array")
				{
					ElfRelocatorCtor ctor;
					ctor.symbolName = Global.symbolTable.getUniqueLabelName();
					ctor.size = sec->getSize();

					sectionEntry.label = Global.symbolTable.getLabel(ctor.symbolName,-1,-1);
					sectionEntry.label->setDefined(true);

					ctors.push_back(ctor);
				}

				file.sections.push_back(sectionEntry);
			}
		}

		// init exportable symbols
		for (int i = 0; i < elf->getSymbolCount(); i++)
		{
			Elf32_Sym symbol;
			bool found = elf->getSymbol(symbol, i);

			if (ELF32_ST_BIND(symbol.st_info) == STB_GLOBAL && symbol.st_shndx != 0)
			{
				ElfRelocatorSymbol symEntry;
				symEntry.type = ELF32_ST_TYPE(symbol.st_info);
				symEntry.name = convertUtf8ToWString(elf->getStrTableString(symbol.st_name));
				symEntry.relativeAddress = symbol.st_value;
				symEntry.section = symbol.st_shndx;
				symEntry.size = symbol.st_size;
				symEntry.label = NULL;

				file.symbols.push_back(symEntry);
			}
		}

		file.elf = elf;
		file.name = entry.name;
		files.push_back(file);
	}

	return true;
}
Ejemplo n.º 14
0
    ElfRelHackCode_Section(Elf_Shdr &s, Elf &e)
    : ElfSection(s, NULL, NULL), parent(e) {
        std::string file(rundir);
        init = parent.getDynSection()->getSectionForType(DT_INIT);
        file += "/inject/";
        switch (parent.getMachine()) {
        case EM_386:
            file += "x86";
            break;
        case EM_X86_64:
            file += "x86_64";
            break;
        case EM_ARM:
            file += "arm";
            break;
        default:
            throw std::runtime_error("unsupported architecture");
        }
        if (init == NULL)
            file += "-noinit";
        file += ".o";
        std::ifstream inject(file.c_str(), std::ios::in|std::ios::binary);
        elf = new Elf(inject);
        if (elf->getType() != ET_REL)
            throw std::runtime_error("object for injected code is not ET_REL");
        if (elf->getMachine() != parent.getMachine())
            throw std::runtime_error("architecture of object for injected code doesn't match");

        ElfSymtab_Section *symtab = NULL;

        // Get all executable sections from the injected code object.
        // Most of the time, there will only be one for the init function,
        // but on e.g. x86, there is a separate section for
        // __i686.get_pc_thunk.$reg
        // Find the symbol table at the same time.
        for (ElfSection *section = elf->getSection(1); section != NULL;
             section = section->getNext()) {
            if ((section->getType() == SHT_PROGBITS) &&
                (section->getFlags() & SHF_EXECINSTR)) {
                code.push_back(section);
                // We need to align this section depending on the greater
                // alignment required by code sections.
                if (shdr.sh_addralign < section->getAddrAlign())
                    shdr.sh_addralign = section->getAddrAlign();
            } else if (section->getType() == SHT_SYMTAB) {
                symtab = (ElfSymtab_Section *) section;
            }
        }
        assert(code.size() != 0);
        if (symtab == NULL)
            throw std::runtime_error("Couldn't find a symbol table for the injected code");

        // Find the init symbol
        entry_point = -1;
        int shndx = 0;
        for (std::vector<Elf_SymValue>::iterator sym = symtab->syms.begin();
             sym != symtab->syms.end(); sym++) {
            if (strcmp(sym->name, "init") == 0) {
                entry_point = sym->value.getValue();
                shndx = sym->value.getSection()->getIndex();
                break;
            }
        }
        if (entry_point == -1)
            throw std::runtime_error("Couldn't find an 'init' symbol in the injected code");

        // Adjust code sections offsets according to their size
        std::vector<ElfSection *>::iterator c = code.begin();
        (*c)->getShdr().sh_addr = 0;
        for(ElfSection *last = *(c++); c != code.end(); c++) {
            unsigned int addr = last->getShdr().sh_addr + last->getSize();
            if (addr & ((*c)->getAddrAlign() - 1))
                addr = (addr | ((*c)->getAddrAlign() - 1)) + 1;
            (*c)->getShdr().sh_addr = addr;
        }
        shdr.sh_size = code.back()->getAddr() + code.back()->getSize();
        data = new char[shdr.sh_size];
        char *buf = data;
        for (c = code.begin(); c != code.end(); c++) {
            memcpy(buf, (*c)->getData(), (*c)->getSize());
            buf += (*c)->getSize();
            if ((*c)->getIndex() < shndx)
                entry_point += (*c)->getSize();
        }
        name = elfhack_text;
    }
Ejemplo n.º 15
0
void
ElfSymbol::Finalize(Symbol& sym, Diagnostic& diags)
{
    // If symbol is a weakrefr, make it weak at this point.
    if (m_weak_refr)
    {
        if (!sym.isDefined() &&
            (sym.getVisibility() & (Symbol::GLOBAL | Symbol::COMMON)) == 0)
        {
            if (sym.isUsed())
            {
                setInTable(true);
                sym.Declare(Symbol::GLOBAL);
                setBinding(STB_WEAK);
            }
            else
            {
                setInTable(false);
                return;
            }
        }
        else if (!sym.isDefined() &&
                 (sym.getVisibility() & Symbol::GLOBAL) != 0)
        {
            setBinding(STB_GLOBAL);
        }
    }

    // Don't put the LHS of weakrefs into the symbol table unless they're
    // specifically requested.
    if (m_weak_ref && (sym.getVisibility() == Symbol::DLOCAL ||
                       sym.getVisibility() == Symbol::LOCAL))
    {
        setInTable(false);
        return;
    }

    // If symbol is in a TLS section, force its type to TLS.
    Location loc;
    Section* sect;
    ElfSection* elfsect;
    if (sym.getLabel(&loc) &&
        (sect = loc.bc->getContainer()->AsSection()) &&
        (elfsect = sect->getAssocData<ElfSection>()) &&
        (elfsect->getFlags() & SHF_TLS))
    {
        m_type = STT_TLS;
    }

    // get size (if specified); expr overrides stored integer
    if (!m_size.isEmpty())
    {
        if (!ExpandEqu(m_size))
        {
            diags.Report(m_size_source, diag::err_equ_circular_reference);
            return;
        }
        SimplifyCalcDist(m_size, diags);
        if (!m_size.isIntNum())
            diags.Report(m_size_source, diag::err_size_integer);
    }

    // get EQU value for constants
    const Expr* equ_expr_c = sym.getEqu();

    if (equ_expr_c != 0)
    {
        Expr equ_expr = *equ_expr_c;
        if (!ExpandEqu(equ_expr))
        {
            diags.Report(sym.getDefSource(), diag::err_equ_circular_reference);
            return;
        }
        SimplifyCalcDist(equ_expr, diags);

        // trivial case: simple integer
        if (equ_expr.isIntNum())
        {
            m_index = SHN_ABS;
            m_value = equ_expr.getIntNum();
            return;
        }

        // otherwise might contain relocatable value (e.g. symbol alias)
        std::auto_ptr<Expr> equ_expr_p(new Expr);
        equ_expr_p->swap(equ_expr);
        Value val(64, equ_expr_p);
        val.setSource(sym.getDefSource());
        if (!val.Finalize(diags, diag::err_equ_too_complex))
            return;
        if (val.isComplexRelative())
        {
            diags.Report(sym.getDefSource(), diag::err_equ_too_complex);
            return;
        }

        // set section appropriately based on if value is relative
        if (val.isRelative())
        {
            SymbolRef rel = val.getRelative();
            Location loc;
            if (!rel->getLabel(&loc) || !loc.bc)
            {
                // Referencing an undefined label? Don't gen the symbol.
                diags.Report(sym.getDefSource(), diag::warn_equ_undef_ref);
                m_in_table = false;
                return;
            }

            m_sect = loc.bc->getContainer()->AsSection();
            m_value = loc.getOffset();
            m_value_rel = rel;
        }
        else
        {
            m_index = SHN_ABS;
            m_value = 0;
        }

        // add in any remaining absolute portion
        if (Expr* abs = val.getAbs())
        {
            SimplifyCalcDist(*abs, diags);
            if (!abs->isIntNum())
            {
                diags.Report(sym.getDefSource(), diag::err_equ_not_integer);
                return;
            }
            m_value += abs->getIntNum();
        }
    }
}
Ejemplo n.º 16
0
status_t
ElfFile::Init(const char* fileName)
{
	// open file
	fFD = open(fileName, O_RDONLY);
	if (fFD < 0) {
		WARNING("Failed to open \"%s\": %s\n", fileName, strerror(errno));
		return errno;
	}

	// stat() file to get its size
	struct stat st;
	if (fstat(fFD, &st) < 0) {
		WARNING("Failed to stat \"%s\": %s\n", fileName, strerror(errno));
		return errno;
	}
	fFileSize = st.st_size;

	// read the elf header
	fElfHeader = (Elf32_Ehdr*)malloc(sizeof(Elf32_Ehdr));
	if (fElfHeader == NULL)
		return B_NO_MEMORY;

	ssize_t bytesRead = pread(fFD, fElfHeader, sizeof(Elf32_Ehdr), 0);
	if (bytesRead != (ssize_t)sizeof(Elf32_Ehdr))
		return bytesRead < 0 ? errno : B_ERROR;

	// check the ELF header
	if (!_CheckRange(0, sizeof(Elf32_Ehdr)) || !_CheckElfHeader()) {
		WARNING("\"%s\": Not an ELF file\n", fileName);
		return B_BAD_DATA;
	}

	// check section header table values
	off_t sectionHeadersOffset = fElfHeader->e_shoff;
	size_t sectionHeaderSize = fElfHeader->e_shentsize;
	int sectionCount = fElfHeader->e_shnum;
	size_t sectionHeaderTableSize = sectionHeaderSize * sectionCount;
	if (!_CheckRange(sectionHeadersOffset, sectionHeaderTableSize)) {
		WARNING("\"%s\": Invalid ELF header\n", fileName);
		return B_BAD_DATA;
	}

	// read the section header table
	uint8* sectionHeaderTable = (uint8*)malloc(sectionHeaderTableSize);
	if (sectionHeaderTable == NULL)
		return B_NO_MEMORY;
	MemoryDeleter sectionHeaderTableDeleter(sectionHeaderTable);

	bytesRead = pread(fFD, sectionHeaderTable, sectionHeaderTableSize,
		sectionHeadersOffset);
	if (bytesRead != (ssize_t)sectionHeaderTableSize)
		return bytesRead < 0 ? errno : B_ERROR;

	// check and get the section header string section
	Elf32_Shdr* stringSectionHeader = (Elf32_Shdr*)(sectionHeaderTable
		+ fElfHeader->e_shstrndx * sectionHeaderSize);
	if (!_CheckRange(stringSectionHeader->sh_offset,
			stringSectionHeader->sh_size)) {
		WARNING("\"%s\": Invalid string section header\n", fileName);
		return B_BAD_DATA;
	}
	size_t sectionStringSize = stringSectionHeader->sh_size;

	ElfSection* sectionStringSection = new(std::nothrow) ElfSection(".shstrtab",
		fFD, stringSectionHeader->sh_offset, sectionStringSize,
		stringSectionHeader->sh_addr, stringSectionHeader->sh_flags);
	if (sectionStringSection == NULL)
		return B_NO_MEMORY;
	fSections.Add(sectionStringSection);

	status_t error = sectionStringSection->Load();
	if (error != B_OK)
		return error;

	const char* sectionStrings = (const char*)sectionStringSection->Data();

	// read the other sections
	for (int i = 0; i < sectionCount; i++) {
		Elf32_Shdr* sectionHeader = (Elf32_Shdr*)(sectionHeaderTable
			+ i * sectionHeaderSize);
		// skip invalid sections and the section header string section
		const char* name = sectionStrings + sectionHeader->sh_name;
		if (sectionHeader->sh_name >= sectionStringSize
			|| !_CheckRange(sectionHeader->sh_offset, sectionHeader->sh_size)
			|| i == fElfHeader->e_shstrndx) {
			continue;
		}

		// create an ElfSection
		ElfSection* section = new(std::nothrow) ElfSection(name, fFD,
			sectionHeader->sh_offset, sectionHeader->sh_size,
			sectionHeader->sh_addr, sectionHeader->sh_flags);
		if (section == NULL)
			return B_NO_MEMORY;
		fSections.Add(section);
	}

	// check program header table values
	off_t programHeadersOffset = fElfHeader->e_phoff;
	size_t programHeaderSize = fElfHeader->e_phentsize;
	int segmentCount = fElfHeader->e_phnum;
	size_t programHeaderTableSize = programHeaderSize * segmentCount;
	if (!_CheckRange(programHeadersOffset, programHeaderTableSize)) {
		WARNING("\"%s\": Invalid ELF header\n", fileName);
		return B_BAD_DATA;
	}

	// read the program header table
	uint8* programHeaderTable = (uint8*)malloc(programHeaderTableSize);
	if (programHeaderTable == NULL)
		return B_NO_MEMORY;
	MemoryDeleter programHeaderTableDeleter(programHeaderTable);

	bytesRead = pread(fFD, programHeaderTable, programHeaderTableSize,
		programHeadersOffset);
	if (bytesRead != (ssize_t)programHeaderTableSize)
		return bytesRead < 0 ? errno : B_ERROR;

	// read the program headers and create ElfSegment objects
	for (int i = 0; i < segmentCount; i++) {
		Elf32_Phdr* programHeader = (Elf32_Phdr*)(programHeaderTable
			+ i * programHeaderSize);
		// skip program headers we aren't interested in or that are invalid
		if (programHeader->p_type != PT_LOAD || programHeader->p_filesz == 0
			|| programHeader->p_memsz == 0
			|| !_CheckRange(programHeader->p_offset, programHeader->p_filesz)) {
			continue;
		}

		// create an ElfSegment
		ElfSegment* segment = new(std::nothrow) ElfSegment(
			programHeader->p_offset, programHeader->p_filesz,
			programHeader->p_vaddr, programHeader->p_memsz,
			(programHeader->p_flags & PF_WRITE) != 0);
		if (segment == NULL)
			return B_NO_MEMORY;
		fSegments.Add(segment);
	}

	return B_OK;
}
Ejemplo n.º 17
0
status_t
ElfFile::_LoadFile(const char* fileName)
{
	typedef typename ElfClass::Ehdr Ehdr;
	typedef typename ElfClass::Phdr Phdr;
	typedef typename ElfClass::Shdr Shdr;

	// read the elf header
	Ehdr elfHeader;
	ssize_t bytesRead = pread(fFD, &elfHeader, sizeof(elfHeader), 0);
	if (bytesRead != (ssize_t)sizeof(elfHeader))
		return bytesRead < 0 ? errno : B_ERROR;

	// check the ELF header
	if (!_CheckRange(0, sizeof(elfHeader))
		|| !_CheckElfHeader<ElfClass>(elfHeader)) {
		WARNING("\"%s\": Not a valid ELF file\n", fileName);
		return B_BAD_DATA;
	}

	fType = Get(elfHeader.e_type);
	fMachine = Get(elfHeader.e_machine);

	if (Get(elfHeader.e_shnum) > 0) {
		// check section header table values
		uint64 sectionHeadersOffset = Get(elfHeader.e_shoff);
		size_t sectionHeaderSize = Get(elfHeader.e_shentsize);
		int sectionCount = Get(elfHeader.e_shnum);
		size_t sectionHeaderTableSize = sectionHeaderSize * sectionCount;
		if (!_CheckRange(sectionHeadersOffset, sectionHeaderTableSize)) {
			WARNING("\"%s\": Invalid ELF header\n", fileName);
			return B_BAD_DATA;
		}

		// read the section header table
		uint8* sectionHeaderTable = (uint8*)malloc(sectionHeaderTableSize);
		if (sectionHeaderTable == NULL)
			return B_NO_MEMORY;
		MemoryDeleter sectionHeaderTableDeleter(sectionHeaderTable);

		bytesRead = pread(fFD, sectionHeaderTable, sectionHeaderTableSize,
			sectionHeadersOffset);
		if (bytesRead != (ssize_t)sectionHeaderTableSize)
			return bytesRead < 0 ? errno : B_ERROR;

		// check and get the section header string section
		Shdr* stringSectionHeader = (Shdr*)(sectionHeaderTable
			+ Get(elfHeader.e_shstrndx) * sectionHeaderSize);
		if (!_CheckRange(Get(stringSectionHeader->sh_offset),
				Get(stringSectionHeader->sh_size))) {
			WARNING("\"%s\": Invalid string section header\n", fileName);
			return B_BAD_DATA;
		}
		size_t sectionStringSize = Get(stringSectionHeader->sh_size);

		ElfSection* sectionStringSection = new(std::nothrow) ElfSection(
			".shstrtab", Get(stringSectionHeader->sh_type),fFD,
			Get(stringSectionHeader->sh_offset), sectionStringSize,
			Get(stringSectionHeader->sh_addr),
			Get(stringSectionHeader->sh_flags),
			Get(stringSectionHeader->sh_link));
		if (sectionStringSection == NULL)
			return B_NO_MEMORY;
		if (!fSections.AddItem(sectionStringSection)) {
			delete sectionStringSection;
			return B_NO_MEMORY;
		}

		status_t error = sectionStringSection->Load();
		if (error != B_OK)
			return error;

		const char* sectionStrings = (const char*)sectionStringSection->Data();

		// read the other sections
		for (int i = 0; i < sectionCount; i++) {
			Shdr* sectionHeader = (Shdr*)(sectionHeaderTable + i
				* sectionHeaderSize);
			// skip invalid sections and the section header string section
			const char* name = sectionStrings + Get(sectionHeader->sh_name);
			if (Get(sectionHeader->sh_name) >= sectionStringSize
				|| !_CheckRange(Get(sectionHeader->sh_offset),
					Get(sectionHeader->sh_size))
				|| i == Get(elfHeader.e_shstrndx)) {
				continue;
			}

			// create an ElfSection
			ElfSection* section = new(std::nothrow) ElfSection(name,
				Get(sectionHeader->sh_type), fFD, Get(sectionHeader->sh_offset),
				Get(sectionHeader->sh_size), Get(sectionHeader->sh_addr),
				Get(sectionHeader->sh_flags), Get(sectionHeader->sh_link));
			if (section == NULL)
				return B_NO_MEMORY;
			if (!fSections.AddItem(section)) {
				delete section;
				return B_NO_MEMORY;
			}
		}
	}

	if (Get(elfHeader.e_phnum) > 0) {
		// check program header table values
		uint64 programHeadersOffset = Get(elfHeader.e_phoff);
		size_t programHeaderSize = Get(elfHeader.e_phentsize);
		int segmentCount = Get(elfHeader.e_phnum);
		size_t programHeaderTableSize = programHeaderSize * segmentCount;
		if (!_CheckRange(programHeadersOffset, programHeaderTableSize)) {
			WARNING("\"%s\": Invalid ELF header\n", fileName);
			return B_BAD_DATA;
		}

		// read the program header table
		uint8* programHeaderTable = (uint8*)malloc(programHeaderTableSize);
		if (programHeaderTable == NULL)
			return B_NO_MEMORY;
		MemoryDeleter programHeaderTableDeleter(programHeaderTable);

		bytesRead = pread(fFD, programHeaderTable, programHeaderTableSize,
			programHeadersOffset);
		if (bytesRead != (ssize_t)programHeaderTableSize)
			return bytesRead < 0 ? errno : B_ERROR;

		// read the program headers and create ElfSegment objects
		for (int i = 0; i < segmentCount; i++) {
			Phdr* programHeader = (Phdr*)(programHeaderTable + i
				* programHeaderSize);
			// skip invalid program headers
			if (Get(programHeader->p_filesz) > 0
				&& !_CheckRange(Get(programHeader->p_offset),
					Get(programHeader->p_filesz))) {
				continue;
			}

			// create an ElfSegment
			ElfSegment* segment = new(std::nothrow) ElfSegment(
				Get(programHeader->p_type), Get(programHeader->p_offset),
				Get(programHeader->p_filesz), Get(programHeader->p_vaddr),
				Get(programHeader->p_memsz), Get(programHeader->p_flags));
			if (segment == NULL)
				return B_NO_MEMORY;
			if (!fSegments.AddItem(segment)) {
				delete segment;
				return B_NO_MEMORY;
			}
		}
	}

	return B_OK;
}
Ejemplo n.º 18
0
status_t
ElfFile::CreateSymbolLookup(uint64 textDelta, ElfSymbolLookup*& _lookup) const
{
	// Get the symbol table + corresponding string section. There may be two
	// symbol tables: the dynamic and the non-dynamic one. The former contains
	// only the symbols needed at run-time. The latter, if existing, is likely
	// more complete. So try to find and use the latter one, falling back to the
	// former.
	ElfSection* symbolSection;
	ElfSection* stringSection;
	if (!_FindSymbolSections(symbolSection, stringSection, SHT_SYMTAB)
		&& !_FindSymbolSections(symbolSection, stringSection, SHT_DYNSYM)) {
		return B_ENTRY_NOT_FOUND;
	}

	// create a source with a segment for each section
	SymbolLookupSource* source = new(std::nothrow) SymbolLookupSource(fFD);
	if (source == NULL)
		return B_NO_MEMORY;
	BReference<SymbolLookupSource> sourceReference(source, true);

	if (!source->AddSegment(symbolSection->Offset(), symbolSection->Size(),
				symbolSection->Offset())
		|| !source->AddSegment(stringSection->Offset(), stringSection->Size(),
				stringSection->Offset())) {
		return B_NO_MEMORY;
	}

	// create the lookup
	size_t symbolTableEntrySize = Is64Bit()
		? sizeof(ElfClass64::Sym) : sizeof(ElfClass32::Sym);
	uint32 symbolCount = uint32(symbolSection->Size() / symbolTableEntrySize);

	return ElfSymbolLookup::Create(source, symbolSection->Offset(), 0,
		stringSection->Offset(), symbolCount, symbolTableEntrySize, textDelta,
		f64Bit, fSwappedByteOrder, true, _lookup);
}
Ejemplo n.º 19
0
bool ElfRelocator::relocateFile(ElfRelocatorFile& file, u64& relocationAddress)
{
	ElfFile* elf = file.elf;
	u64 start = relocationAddress;

	// calculate address for each section
	std::map<u64,u64> relocationOffsets;
	for (ElfRelocatorSection& entry: file.sections)
	{
		ElfSection* section = entry.section;
		size_t index = entry.index;
		int size = section->getSize();

		while (relocationAddress % section->getAlignment())
			relocationAddress++;

		if (entry.label != NULL)
			entry.label->setValue(relocationAddress);

		relocationOffsets[index] = relocationAddress;
		relocationAddress += size;
	}

	size_t dataStart = outputData.size();
	outputData.reserveBytes((size_t)(relocationAddress-start));

	// load sections
	bool error = false;
	for (ElfRelocatorSection& entry: file.sections)
	{
		ElfSection* section = entry.section;
		size_t index = entry.index;

		if (section->getType() == SHT_NOBITS)
		{
			// reserveBytes initialized the data to 0 already
			continue;
		}
		
		ByteArray sectionData = section->getData();

		// relocate if necessary
		ElfSection* relSection = entry.relSection;
		if (relSection != NULL)
		{
			for (unsigned int relOffset = 0; relOffset < relSection->getSize(); relOffset += sizeof(Elf32_Rel))
			{
				Elf32_Rel rel;
				loadRelocation(rel, relSection->getData(), relOffset, elf->isBigEndian());
				int pos = rel.r_offset;

				int symNum = rel.getSymbolNum();
				if (symNum <= 0)
				{
					Logger::queueError(Logger::Warning,L"Invalid symbol num %06X",symNum);
					error = true;
					continue;
				}

				Elf32_Sym sym;
				auto found = elf->getSymbol(sym, symNum);
				int symSection = sym.st_shndx;
				
				RelocationData relData;
				relData.opcode = sectionData.getDoubleWord(pos, elf->isBigEndian());
				relData.opcodeOffset = pos+relocationOffsets[index];
				relocator->setSymbolAddress(relData,sym.st_value,sym.st_info & 0xF);

				// externs?
				if (relData.targetSymbolType == STT_NOTYPE && sym.st_shndx == 0)
				{
					std::wstring symName = toWLowercase(elf->getStrTableString(sym.st_name));

					Label* label = Global.symbolTable.getLabel(symName,-1,-1);
					if (label == NULL)
					{
						Logger::queueError(Logger::Error,L"Invalid external symbol %s",symName);	
						error = true;
						continue;
					}
					if (label->isDefined() == false)
					{
						Logger::queueError(Logger::Error,L"Undefined external symbol %s in file %s",symName,file.name);
						error = true;
						continue;
					}
					
					relData.relocationBase = (unsigned int) label->getValue();
					relData.targetSymbolType = label->isData() ? STT_OBJECT : STT_FUNC;
					relData.targetSymbolInfo = label->getInfo();
				} else {
					relData.relocationBase = relocationOffsets[symSection]+relData.symbolAddress;
				}

				if (relocator->relocateOpcode(rel.getType(),relData) == false)
				{
					Logger::queueError(Logger::Error,relData.errorMessage);
					error = true;
					continue;
				}

				sectionData.replaceDoubleWord(pos,relData.opcode, elf->isBigEndian());
			}
		}

		size_t arrayStart = (size_t) (dataStart+relocationOffsets[index]-start);
		memcpy(outputData.data(arrayStart),sectionData.data(),sectionData.size());
	}
	
	// now update symbols
	for (ElfRelocatorSymbol& sym: file.symbols)
	{
		u64 oldAddress = sym.relocatedAddress;

		switch (sym.section)
		{
		case SHN_ABS:		// address does not change
			sym.relocatedAddress = sym.relativeAddress;
			break;
		case SHN_COMMON:	// needs to be allocated. relativeAddress gives alignment constraint
			{
				u64 start = relocationAddress;

				while (relocationAddress % sym.relativeAddress)
					relocationAddress++;

				sym.relocatedAddress = relocationAddress;
				relocationAddress += sym.size;
				outputData.reserveBytes((size_t)(relocationAddress-start));
			}
			break;
		default:			// normal relocated symbol
			sym.relocatedAddress = sym.relativeAddress+relocationOffsets[sym.section];
			break;
		}

		if (sym.label != NULL)
			sym.label->setValue(sym.relocatedAddress);

		if (oldAddress != sym.relocatedAddress)
			dataChanged = true;
	}

	return !error;
}