You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
238 lines
9.9 KiB
238 lines
9.9 KiB
//===- ELFFileFormat.cpp --------------------------------------------------===//
|
|
//
|
|
// The MCLinker Project
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
#include "mcld/LD/ELFFileFormat.h"
|
|
#include "mcld/Object/ObjectBuilder.h"
|
|
#include "mcld/Target/GNULDBackend.h"
|
|
|
|
#include <llvm/Support/ELF.h>
|
|
|
|
namespace mcld {
|
|
|
|
ELFFileFormat::ELFFileFormat()
|
|
: f_pNULLSection(NULL),
|
|
f_pGOT(NULL),
|
|
f_pPLT(NULL),
|
|
f_pRelDyn(NULL),
|
|
f_pRelPlt(NULL),
|
|
f_pRelaDyn(NULL),
|
|
f_pRelaPlt(NULL),
|
|
f_pComment(NULL),
|
|
f_pData1(NULL),
|
|
f_pDebug(NULL),
|
|
f_pDynamic(NULL),
|
|
f_pDynStrTab(NULL),
|
|
f_pDynSymTab(NULL),
|
|
f_pFini(NULL),
|
|
f_pFiniArray(NULL),
|
|
f_pHashTab(NULL),
|
|
f_pInit(NULL),
|
|
f_pInitArray(NULL),
|
|
f_pInterp(NULL),
|
|
f_pLine(NULL),
|
|
f_pNote(NULL),
|
|
f_pPreInitArray(NULL),
|
|
f_pROData1(NULL),
|
|
f_pShStrTab(NULL),
|
|
f_pStrTab(NULL),
|
|
f_pSymTab(NULL),
|
|
f_pTBSS(NULL),
|
|
f_pTData(NULL),
|
|
f_pCtors(NULL),
|
|
f_pDataRelRo(NULL),
|
|
f_pDtors(NULL),
|
|
f_pEhFrame(NULL),
|
|
f_pEhFrameHdr(NULL),
|
|
f_pGCCExceptTable(NULL),
|
|
f_pGNUVersion(NULL),
|
|
f_pGNUVersionD(NULL),
|
|
f_pGNUVersionR(NULL),
|
|
f_pGOTPLT(NULL),
|
|
f_pJCR(NULL),
|
|
f_pNoteABITag(NULL),
|
|
f_pStab(NULL),
|
|
f_pStabStr(NULL),
|
|
f_pStack(NULL),
|
|
f_pStackNote(NULL),
|
|
f_pDataRelRoLocal(NULL),
|
|
f_pGNUHashTab(NULL) {
|
|
}
|
|
|
|
void ELFFileFormat::initStdSections(ObjectBuilder& pBuilder,
|
|
unsigned int pBitClass) {
|
|
f_pTextSection =
|
|
pBuilder.CreateSection(".text",
|
|
LDFileFormat::TEXT,
|
|
llvm::ELF::SHT_PROGBITS,
|
|
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
|
|
0x1);
|
|
f_pNULLSection =
|
|
pBuilder.CreateSection("", LDFileFormat::Null, llvm::ELF::SHT_NULL, 0x0);
|
|
f_pReadOnlySection = pBuilder.CreateSection(".rodata",
|
|
LDFileFormat::TEXT,
|
|
llvm::ELF::SHT_PROGBITS,
|
|
llvm::ELF::SHF_ALLOC,
|
|
0x1);
|
|
|
|
f_pBSSSection =
|
|
pBuilder.CreateSection(".bss",
|
|
LDFileFormat::BSS,
|
|
llvm::ELF::SHT_NOBITS,
|
|
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
|
|
0x1);
|
|
f_pComment = pBuilder.CreateSection(
|
|
".comment", LDFileFormat::MetaData, llvm::ELF::SHT_PROGBITS, 0x0, 0x1);
|
|
f_pDataSection =
|
|
pBuilder.CreateSection(".data",
|
|
LDFileFormat::DATA,
|
|
llvm::ELF::SHT_PROGBITS,
|
|
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
|
|
0x1);
|
|
f_pData1 = pBuilder.CreateSection(".data1",
|
|
LDFileFormat::DATA,
|
|
llvm::ELF::SHT_PROGBITS,
|
|
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
|
|
0x1);
|
|
f_pDebug = pBuilder.CreateSection(
|
|
".debug", LDFileFormat::Debug, llvm::ELF::SHT_PROGBITS, 0x0, 0x1);
|
|
f_pInit =
|
|
pBuilder.CreateSection(".init",
|
|
LDFileFormat::TEXT,
|
|
llvm::ELF::SHT_PROGBITS,
|
|
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
|
|
0x1);
|
|
f_pInitArray =
|
|
pBuilder.CreateSection(".init_array",
|
|
LDFileFormat::DATA,
|
|
llvm::ELF::SHT_INIT_ARRAY,
|
|
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
|
|
0x1);
|
|
f_pFini =
|
|
pBuilder.CreateSection(".fini",
|
|
LDFileFormat::TEXT,
|
|
llvm::ELF::SHT_PROGBITS,
|
|
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
|
|
0x1);
|
|
f_pFiniArray =
|
|
pBuilder.CreateSection(".fini_array",
|
|
LDFileFormat::DATA,
|
|
llvm::ELF::SHT_FINI_ARRAY,
|
|
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
|
|
0x1);
|
|
f_pLine = pBuilder.CreateSection(
|
|
".line", LDFileFormat::Debug, llvm::ELF::SHT_PROGBITS, 0x0, 0x1);
|
|
f_pPreInitArray =
|
|
pBuilder.CreateSection(".preinit_array",
|
|
LDFileFormat::DATA,
|
|
llvm::ELF::SHT_PREINIT_ARRAY,
|
|
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
|
|
0x1);
|
|
// the definition of SHF_XXX attributes of rodata in Linux Standard Base
|
|
// conflicts with System V standard. We follow System V standard.
|
|
f_pROData1 = pBuilder.CreateSection(".rodata1",
|
|
LDFileFormat::TEXT,
|
|
llvm::ELF::SHT_PROGBITS,
|
|
llvm::ELF::SHF_ALLOC,
|
|
0x1);
|
|
f_pShStrTab = pBuilder.CreateSection(
|
|
".shstrtab", LDFileFormat::NamePool, llvm::ELF::SHT_STRTAB, 0x0, 0x1);
|
|
// In ELF Spec Book I, p1-16. If symbol table and string table are in
|
|
// loadable segments, set the attribute to SHF_ALLOC bit. But in the
|
|
// real world, this bit always turn off.
|
|
f_pSymTab = pBuilder.CreateSection(".symtab",
|
|
LDFileFormat::NamePool,
|
|
llvm::ELF::SHT_SYMTAB,
|
|
0x0,
|
|
pBitClass / 8);
|
|
|
|
f_pStrTab = pBuilder.CreateSection(
|
|
".strtab", LDFileFormat::NamePool, llvm::ELF::SHT_STRTAB, 0x0, 0x1);
|
|
f_pTBSS = pBuilder.CreateSection(
|
|
".tbss",
|
|
LDFileFormat::BSS,
|
|
llvm::ELF::SHT_NOBITS,
|
|
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE | llvm::ELF::SHF_TLS,
|
|
0x1);
|
|
f_pTData = pBuilder.CreateSection(
|
|
".tdata",
|
|
LDFileFormat::DATA,
|
|
llvm::ELF::SHT_PROGBITS,
|
|
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE | llvm::ELF::SHF_TLS,
|
|
0x1);
|
|
|
|
/// @ref 10.3.1.2, ISO/IEC 23360, Part 1:2010(E), p. 24.
|
|
f_pCtors = pBuilder.CreateSection(".ctors",
|
|
LDFileFormat::DATA,
|
|
llvm::ELF::SHT_PROGBITS,
|
|
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
|
|
0x1);
|
|
f_pDataRelRo =
|
|
pBuilder.CreateSection(".data.rel.ro",
|
|
LDFileFormat::DATA,
|
|
llvm::ELF::SHT_PROGBITS,
|
|
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
|
|
0x1);
|
|
f_pDtors = pBuilder.CreateSection(".dtors",
|
|
LDFileFormat::DATA,
|
|
llvm::ELF::SHT_PROGBITS,
|
|
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
|
|
0x1);
|
|
f_pEhFrame = pBuilder.CreateSection(".eh_frame",
|
|
LDFileFormat::EhFrame,
|
|
llvm::ELF::SHT_PROGBITS,
|
|
llvm::ELF::SHF_ALLOC,
|
|
0x4);
|
|
f_pGCCExceptTable = pBuilder.CreateSection(".gcc_except_table",
|
|
LDFileFormat::GCCExceptTable,
|
|
llvm::ELF::SHT_PROGBITS,
|
|
llvm::ELF::SHF_ALLOC,
|
|
0x4);
|
|
f_pGNUVersion = pBuilder.CreateSection(".gnu.version",
|
|
LDFileFormat::Version,
|
|
llvm::ELF::SHT_GNU_versym,
|
|
llvm::ELF::SHF_ALLOC,
|
|
0x1);
|
|
f_pGNUVersionD = pBuilder.CreateSection(".gnu.version_d",
|
|
LDFileFormat::Version,
|
|
llvm::ELF::SHT_GNU_verdef,
|
|
llvm::ELF::SHF_ALLOC,
|
|
0x1);
|
|
f_pGNUVersionR = pBuilder.CreateSection(".gnu.version_r",
|
|
LDFileFormat::Version,
|
|
llvm::ELF::SHT_GNU_verneed,
|
|
llvm::ELF::SHF_ALLOC,
|
|
0x1);
|
|
f_pJCR = pBuilder.CreateSection(".jcr",
|
|
LDFileFormat::DATA,
|
|
llvm::ELF::SHT_PROGBITS,
|
|
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
|
|
0x1);
|
|
f_pStab = pBuilder.CreateSection(
|
|
".stab", LDFileFormat::Debug, llvm::ELF::SHT_PROGBITS, 0x0, 0x1);
|
|
f_pStabStr = pBuilder.CreateSection(
|
|
".stabstr", LDFileFormat::Debug, llvm::ELF::SHT_STRTAB, 0x0, 0x1);
|
|
f_pStackNote = pBuilder.CreateSection(".note.GNU-stack",
|
|
LDFileFormat::StackNote,
|
|
llvm::ELF::SHT_PROGBITS,
|
|
0x0,
|
|
0x1);
|
|
|
|
/// @ref GCC convention, see http://www.airs.com/blog/archives/189
|
|
f_pDataRelRoLocal =
|
|
pBuilder.CreateSection(".data.rel.ro.local",
|
|
LDFileFormat::DATA,
|
|
llvm::ELF::SHT_PROGBITS,
|
|
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
|
|
0x1);
|
|
/// Initialize format dependent sections. (sections for executable and shared
|
|
/// objects)
|
|
initObjectFormat(pBuilder, pBitClass);
|
|
}
|
|
|
|
} // namespace mcld
|