16f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===- ELFReader.cpp ------------------------------------------------------===//
26f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//
36f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//                     The MCLinker Project
46f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//
56f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// This file is distributed under the University of Illinois Open Source
66f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// License. See LICENSE.TXT for details.
76f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//
86f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
96f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/LD/ELFReaderIf.h>
106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/IRBuilder.h>
126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/Fragment/FillFragment.h>
136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/LD/EhFrame.h>
146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/LD/SectionData.h>
156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/Target/GNULDBackend.h>
166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <cstring>
186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <llvm/ADT/StringRef.h>
206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <llvm/ADT/Twine.h>
216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <llvm/Support/ELF.h>
226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <llvm/Support/Host.h>
236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesusing namespace mcld;
256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// ELFReaderIF
286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// getSymType
306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesResolveInfo::Type ELFReaderIF::getSymType(uint8_t pInfo, uint16_t pShndx) const
316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ResolveInfo::Type result = static_cast<ResolveInfo::Type>(pInfo & 0xF);
336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (llvm::ELF::SHN_ABS == pShndx && ResolveInfo::Section == result) {
346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // In Mips, __gp_disp is a special section symbol. Its name comes from
356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // .strtab, not .shstrtab. However, it is unique. Only it is also a ABS
366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // symbol. So here is a tricky to identify __gp_disp and convert it to
376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // Object symbol.
386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return ResolveInfo::Object;
396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return result;
426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// getSymDesc
456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesResolveInfo::Desc ELFReaderIF::getSymDesc(uint16_t pShndx, const Input& pInput) const
466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (pShndx == llvm::ELF::SHN_UNDEF)
486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return ResolveInfo::Undefined;
496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (pShndx < llvm::ELF::SHN_LORESERVE) {
516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // an ELF symbol defined in a section which we are not including
526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // must be treated as an Undefined.
536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // @ref Google gold linker: symtab.cc: 1086
546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (NULL == pInput.context()->getSection(pShndx) ||
556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        LDFileFormat::Ignore == pInput.context()->getSection(pShndx)->kind())
566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      return ResolveInfo::Undefined;
576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return ResolveInfo::Define;
586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (pShndx == llvm::ELF::SHN_ABS)
616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return ResolveInfo::Define;
626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (pShndx == llvm::ELF::SHN_COMMON)
646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return ResolveInfo::Common;
656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (pShndx >= llvm::ELF::SHN_LOPROC &&
676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      pShndx <= llvm::ELF::SHN_HIPROC)
686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return target().getSymDesc(pShndx);
696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // FIXME: ELF weak alias should be ResolveInfo::Indirect
716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return ResolveInfo::NoneDesc;
726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// getSymBinding
756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesResolveInfo::Binding
766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesELFReaderIF::getSymBinding(uint8_t pBinding, uint16_t pShndx, uint8_t pVis) const
776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // TODO:
806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // if --just-symbols option is enabled, the symbol must covert to Absolute
816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  switch(pBinding) {
836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  case llvm::ELF::STB_LOCAL:
846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return ResolveInfo::Local;
856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  case llvm::ELF::STB_GLOBAL:
86f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (pShndx == llvm::ELF::SHN_ABS)
87f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return ResolveInfo::Absolute;
886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return ResolveInfo::Global;
896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  case llvm::ELF::STB_WEAK:
906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return ResolveInfo::Weak;
916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return ResolveInfo::NoneBinding;
946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// getSymFragmentRef
976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesFragmentRef*
986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesELFReaderIF::getSymFragmentRef(Input& pInput,
996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                               uint16_t pShndx,
1006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                               uint32_t pOffset) const
1016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
1026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (Input::DynObj == pInput.type())
1046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return FragmentRef::Null();
1056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (pShndx == llvm::ELF::SHN_UNDEF)
1076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return FragmentRef::Null();
1086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (pShndx >= llvm::ELF::SHN_LORESERVE) // including ABS and COMMON
1106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return FragmentRef::Null();
1116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  LDSection* sect_hdr = pInput.context()->getSection(pShndx);
1136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (NULL == sect_hdr)
1156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    unreachable(diag::unreachable_invalid_section_idx) << pShndx
1166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                                       << pInput.path().native();
1176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (LDFileFormat::Ignore == sect_hdr->kind())
1196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return FragmentRef::Null();
1206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (LDFileFormat::Group == sect_hdr->kind())
1226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return FragmentRef::Null();
1236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return FragmentRef::Create(*sect_hdr, pOffset);
1256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
1266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// getSymVisibility
1286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesResolveInfo::Visibility
1296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesELFReaderIF::getSymVisibility(uint8_t pVis) const
1306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
1316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return static_cast<ResolveInfo::Visibility>(pVis);
1326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
1336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// getSymValue - get the section offset of the symbol.
1356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesuint64_t ELFReaderIF::getSymValue(uint64_t pValue,
1366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                  uint16_t pShndx,
1376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                  const Input& pInput) const
1386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
1396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (Input::Object == pInput.type()) {
1406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // In relocatable files, st_value holds alignment constraints for a symbol
1416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // whose section index is SHN_COMMON
1426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (pShndx == llvm::ELF::SHN_COMMON || pShndx == llvm::ELF::SHN_ABS) {
1436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      return pValue;
1446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
1456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // In relocatable files, st_value holds a section offset for a defined symbol.
1476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // TODO:
1486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // if --just-symbols option are enabled, convert the value from section offset
1496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // to virtual address by adding input section's virtual address.
1506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // The section's virtual address in relocatable files is normally zero, but
1516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // people can use link script to change it.
1526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return pValue;
1536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
1546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // In executable and shared object files, st_value holds a virtual address.
156f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // the virtual address is needed for alias identification.
157f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return pValue;
1586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
1596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
160