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