ELFReader.cpp revision affc150dc44fab1911775a49636d0ce85333b634
15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- ELFReader.cpp ------------------------------------------------------===// 25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// The MCLinker Project 45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source 65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details. 75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===// 95460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/StringRef.h> 115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/Twine.h> 12affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <llvm/Support/ELF.h> 135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/Host.h> 145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/MC/MCLinker.h> 155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/LD/ELFReader.h> 165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Target/GNULDBackend.h> 17affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MemoryArea.h> 18affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MemoryRegion.h> 19affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h> 205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <cstring> 215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld; 235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===// 255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// ELFReaderIF 265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// getLDSectionKind 275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoLDFileFormat::Kind 285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoELFReaderIF::getLDSectionKind(uint32_t pType, const char* pName) const 295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // name rules 315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao llvm::StringRef name(pName); 32affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (name.startswith(".debug") || 33affc150dc44fab1911775a49636d0ce85333b634Zonr Chang name.startswith(".zdebug") || 34affc150dc44fab1911775a49636d0ce85333b634Zonr Chang name.startswith(".gnu.linkonce.wi.") || 35affc150dc44fab1911775a49636d0ce85333b634Zonr Chang name.startswith(".line") || 36affc150dc44fab1911775a49636d0ce85333b634Zonr Chang name.startswith(".stab")) 375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return LDFileFormat::Debug; 385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (name.startswith(".comment")) 395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return LDFileFormat::MetaData; 405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (name.startswith(".interp") || name.startswith(".dynamic")) 415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return LDFileFormat::Note; 42affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (name.startswith(".eh_frame")) 43affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return LDFileFormat::EhFrame; 44affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (name.startswith(".eh_frame_hdr")) 45affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return LDFileFormat::EhFrameHdr; 46affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (name.startswith(".gcc_except_table")) 47affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return LDFileFormat::GCCExceptTable; 485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // type rules 505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao switch(pType) { 515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::SHT_NULL: 525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return LDFileFormat::Null; 535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::SHT_INIT_ARRAY: 545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::SHT_FINI_ARRAY: 555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::SHT_PREINIT_ARRAY: 565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::SHT_PROGBITS: 575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return LDFileFormat::Regular; 585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::SHT_SYMTAB: 595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::SHT_DYNSYM: 605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::SHT_STRTAB: 615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return LDFileFormat::NamePool; 625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::SHT_RELA: 635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::SHT_REL: 645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return LDFileFormat::Relocation; 655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::SHT_NOBITS: 665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return LDFileFormat::BSS; 675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::SHT_DYNAMIC: 685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::SHT_NOTE: 695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return LDFileFormat::Note; 705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::SHT_HASH: 715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::SHT_SHLIB: 725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return LDFileFormat::MetaData; 735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::SHT_GROUP: 745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return LDFileFormat::Group; 755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::SHT_GNU_versym: 765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::SHT_GNU_verdef: 775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::SHT_GNU_verneed: 785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return LDFileFormat::Version; 795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao default: 805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if ((pType >= llvm::ELF::SHT_LOPROC && pType <= llvm::ELF::SHT_HIPROC) || 815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao (pType >= llvm::ELF::SHT_LOOS && pType <= llvm::ELF::SHT_HIOS) || 825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao (pType >= llvm::ELF::SHT_LOUSER && pType <= llvm::ELF::SHT_HIUSER)) 835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return LDFileFormat::Target; 84affc150dc44fab1911775a49636d0ce85333b634Zonr Chang fatal(diag::err_unsupported_section) << pName << pType; 855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return LDFileFormat::MetaData; 875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// getSymDesc 905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoResolveInfo::Desc ELFReaderIF::getSymDesc(uint16_t pShndx, const Input& pInput) const 915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (pShndx == llvm::ELF::SHN_UNDEF) 935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ResolveInfo::Undefined; 945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (pShndx < llvm::ELF::SHN_LORESERVE) { 965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // an ELF symbol defined in a section which we are not including 975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // must be treated as an Undefined. 985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // @ref Google gold linker: symtab.cc: 1086 995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (NULL == pInput.context()->getSection(pShndx)) 1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ResolveInfo::Undefined; 1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ResolveInfo::Define; 1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (pShndx == llvm::ELF::SHN_ABS) 1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ResolveInfo::Define; 1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (pShndx == llvm::ELF::SHN_COMMON) 1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ResolveInfo::Common; 1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // FIXME: ELF weak alias should be ResolveInfo::Indirect 1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ResolveInfo::NoneDesc; 1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// getSymBinding 1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoResolveInfo::Binding 1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoELFReaderIF::getSymBinding(uint8_t pBinding, uint16_t pShndx, uint8_t pVis) const 1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // TODO: 1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // if --just-symbols option is enabled, the symbol must covert to Absolute 1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao switch(pBinding) { 1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::STB_LOCAL: 1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ResolveInfo::Local; 1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::STB_GLOBAL: 1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ResolveInfo::Global; 1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::STB_WEAK: 1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ResolveInfo::Weak; 1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (pShndx == llvm::ELF::SHN_ABS) 1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ResolveInfo::Absolute; 1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return ResolveInfo::NoneBinding; 1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// getSymFragmentRef 1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoMCFragmentRef* 1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoELFReaderIF::getSymFragmentRef(Input& pInput, 1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MCLinker& pLinker, 1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint16_t pShndx, 1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint32_t pOffset) const 1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (pShndx == llvm::ELF::SHN_UNDEF || pShndx >= llvm::ELF::SHN_LORESERVE) 1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return NULL; 1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao LDSection* sect_hdr = pInput.context()->getSection(pShndx); 1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 150affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (NULL == sect_hdr) 151affc150dc44fab1911775a49636d0ce85333b634Zonr Chang unreachable(diag::unreachable_invalid_section_idx) << pShndx 152affc150dc44fab1911775a49636d0ce85333b634Zonr Chang << pInput.path().native(); 1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao MCFragmentRef* result = pLinker.getLayout().getFragmentRef(*sect_hdr, pOffset); 1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return result; 1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// getSymVisibility 1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoResolveInfo::Visibility 1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoELFReaderIF::getSymVisibility(uint8_t pVis) const 1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return static_cast<ResolveInfo::Visibility>(pVis); 1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// getSymValue - get the section offset of the symbol. 1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaouint64_t ELFReaderIF::getSymValue(uint64_t pValue, 1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao uint16_t pShndx, 1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao const Input& pInput) const 1695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (Input::Object == pInput.type()) { 1715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // In relocatable files, st_value holds alignment constraints for a symbol 1725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // whose section index is SHN_COMMON 1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao if (pShndx == llvm::ELF::SHN_COMMON || pShndx == llvm::ELF::SHN_ABS) { 1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return pValue; 1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // In relocatable files, st_value holds a section offset for a defined symbol. 1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // TODO: 1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // if --just-symbols option are enabled, convert the value from section offset 1805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // to virtual address by adding input section's virtual address. 1815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // The section's virtual address in relocatable files is normally zero, but 1825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // people can use link script to change it. 1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return pValue; 1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // In executable and shared object files, st_value holds a virtual address. 1875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // the virtual address is useless during linking. 1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return 0x0; 1895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 191affc150dc44fab1911775a49636d0ce85333b634Zonr Changbool ELFReaderIF::readEhFrame(Input& pInput, 192affc150dc44fab1911775a49636d0ce85333b634Zonr Chang MCLinker& pLinker, 193affc150dc44fab1911775a49636d0ce85333b634Zonr Chang LDSection& pInputSectHdr) const 194affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{ 195affc150dc44fab1911775a49636d0ce85333b634Zonr Chang LDSection& out_sect = pLinker.getOrCreateOutputSectHdr(pInputSectHdr.name(), 196affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pInputSectHdr.kind(), 197affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pInputSectHdr.type(), 198affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pInputSectHdr.flag()); 199affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 200affc150dc44fab1911775a49636d0ce85333b634Zonr Chang size_t size = pLinker.addEhFrame(pInputSectHdr, *pInput.memArea()); 201affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 202affc150dc44fab1911775a49636d0ce85333b634Zonr Chang out_sect.setSize(out_sect.size() + size); 203affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return true; 204affc150dc44fab1911775a49636d0ce85333b634Zonr Chang} 205