15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- ELFDynamic.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#include <llvm/Support/Host.h>
105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ErrorHandling.h>
115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Target/ELFDynamic.h>
125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Target/GNULDBackend.h>
135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/LD/ELFFileFormat.h>
1422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LinkerConfig.h>
1522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Support/MsgHandling.h>
165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld;
185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace elf_dynamic;
195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// elf_dynamic::EntryIF
22d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===----------------------------------------------------------------------===//
235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoEntryIF::EntryIF()
245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoEntryIF::~EntryIF()
285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// ELFDynamic
33d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===----------------------------------------------------------------------===//
34d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoELFDynamic::ELFDynamic(const GNULDBackend& pParent,
35d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                       const LinkerConfig& pConfig)
36d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  : m_pEntryFactory(NULL), m_Backend(pParent), m_Config(pConfig), m_Idx(0) {
376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // FIXME: support big-endian machine.
386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (m_Config.targets().is32Bits()) {
396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (m_Config.targets().isLittleEndian())
406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_pEntryFactory = new Entry<32, true>();
416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  } else if (m_Config.targets().is64Bits()) {
426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (m_Config.targets().isLittleEndian())
436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      m_pEntryFactory = new Entry<64, true>();
446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  } else {
456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    fatal(diag::unsupported_bitclass) << m_Config.targets().triple().str()
466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                      << m_Config.targets().bitclass();
475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoELFDynamic::~ELFDynamic()
525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (NULL != m_pEntryFactory)
545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    delete m_pEntryFactory;
555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  EntryListType::iterator entry, entryEnd = m_EntryList.end();
575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  for (entry = m_EntryList.begin(); entry != entryEnd; ++entry) {
585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (NULL != *entry)
595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      delete (*entry);
605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  entryEnd = m_NeedList.end();
635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  for (entry = m_NeedList.begin(); entry != entryEnd; ++entry) {
645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (NULL != *entry)
655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      delete (*entry);
665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaosize_t ELFDynamic::size() const
705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return (m_NeedList.size() + m_EntryList.size());
725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaosize_t ELFDynamic::numOfBytes() const
755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return size()*entrySize();
775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaosize_t ELFDynamic::entrySize() const
805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return m_pEntryFactory->size();
825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid ELFDynamic::reserveOne(uint64_t pTag)
855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(NULL != m_pEntryFactory);
876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  m_EntryList.push_back(m_pEntryFactory->clone());
885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid ELFDynamic::applyOne(uint64_t pTag, uint64_t pValue)
915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(m_Idx < m_EntryList.size());
935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  m_EntryList[m_Idx]->setValue(pTag, pValue);
945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ++m_Idx;
955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// reserveEntries - reserve entries
98d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaovoid ELFDynamic::reserveEntries(const ELFFileFormat& pFormat)
995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
100d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (LinkerConfig::DynObj == m_Config.codeGenType()) {
1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reserveOne(llvm::ELF::DT_SONAME); // DT_SONAME
1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
103d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    if (m_Config.options().Bsymbolic())
1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      reserveOne(llvm::ELF::DT_SYMBOLIC); // DT_SYMBOLIC
1055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pFormat.hasInit())
1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reserveOne(llvm::ELF::DT_INIT); // DT_INIT
1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pFormat.hasFini())
1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reserveOne(llvm::ELF::DT_FINI); // DT_FINI
1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
113551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (pFormat.hasPreInitArray()) {
114551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    reserveOne(llvm::ELF::DT_PREINIT_ARRAY); // DT_PREINIT_ARRAY
115551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    reserveOne(llvm::ELF::DT_PREINIT_ARRAYSZ); // DT_PREINIT_ARRAYSZ
116551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
117551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pFormat.hasInitArray()) {
1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reserveOne(llvm::ELF::DT_INIT_ARRAY); // DT_INIT_ARRAY
1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reserveOne(llvm::ELF::DT_INIT_ARRAYSZ); // DT_INIT_ARRAYSZ
1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pFormat.hasFiniArray()) {
1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reserveOne(llvm::ELF::DT_FINI_ARRAY); // DT_FINI_ARRAY
1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reserveOne(llvm::ELF::DT_FINI_ARRAYSZ); // DT_FINI_ARRAYSZ
1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pFormat.hasHashTab())
1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reserveOne(llvm::ELF::DT_HASH); // DT_HASH
1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // FIXME: use llvm enum constant
1326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (pFormat.hasGNUHashTab())
1336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    reserveOne(0x6ffffef5); // DT_GNU_HASH
1346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pFormat.hasDynSymTab()) {
1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reserveOne(llvm::ELF::DT_SYMTAB); // DT_SYMTAB
1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reserveOne(llvm::ELF::DT_SYMENT); // DT_SYMENT
1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pFormat.hasDynStrTab()) {
1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reserveOne(llvm::ELF::DT_STRTAB); // DT_STRTAB
1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reserveOne(llvm::ELF::DT_STRSZ); // DT_STRSZ
1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  reserveTargetEntries(pFormat); // DT_PLTGOT
1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
14787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pFormat.hasRelPlt() || pFormat.hasRelaPlt()) {
1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reserveOne(llvm::ELF::DT_PLTREL); // DT_PLTREL
1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reserveOne(llvm::ELF::DT_JMPREL); // DT_JMPREL
1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reserveOne(llvm::ELF::DT_PLTRELSZ); // DT_PLTRELSZ
1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pFormat.hasRelDyn()) {
1545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reserveOne(llvm::ELF::DT_REL); // DT_REL
1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reserveOne(llvm::ELF::DT_RELSZ); // DT_RELSZ
1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reserveOne(llvm::ELF::DT_RELENT); // DT_RELENT
1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pFormat.hasRelaDyn()) {
1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reserveOne(llvm::ELF::DT_RELA); // DT_RELA
1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reserveOne(llvm::ELF::DT_RELASZ); // DT_RELASZ
1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    reserveOne(llvm::ELF::DT_RELAENT); // DT_RELAENT
1635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
164affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
1656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t dt_flags = 0x0;
1666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (m_Config.options().hasOrigin())
1676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    dt_flags |= llvm::ELF::DF_ORIGIN;
1686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (m_Config.options().Bsymbolic())
1696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    dt_flags |= llvm::ELF::DF_SYMBOLIC;
1706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (m_Config.options().hasNow())
1716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    dt_flags |= llvm::ELF::DF_BIND_NOW;
1726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (m_Backend.hasTextRel())
1736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    dt_flags |= llvm::ELF::DF_TEXTREL;
1746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (m_Backend.hasStaticTLS() &&
1756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      (LinkerConfig::DynObj == m_Config.codeGenType()))
1766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    dt_flags |= llvm::ELF::DF_STATIC_TLS;
1776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if ((m_Config.options().hasNewDTags() && 0x0 != dt_flags) ||
1796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      0 != (dt_flags & llvm::ELF::DF_STATIC_TLS))
180affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    reserveOne(llvm::ELF::DT_FLAGS); // DT_FLAGS
181affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
18222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (m_Backend.hasTextRel())
18322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    reserveOne(llvm::ELF::DT_TEXTREL); // DT_TEXTREL
18422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
185d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (m_Config.options().hasNow()          ||
186d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      m_Config.options().hasLoadFltr()     ||
187d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      m_Config.options().hasOrigin()       ||
188d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      m_Config.options().hasInterPose()    ||
189d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      m_Config.options().hasNoDefaultLib() ||
190d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      m_Config.options().hasNoDump()       ||
191d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      m_Config.options().Bgroup()          ||
192d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      ((LinkerConfig::DynObj == m_Config.codeGenType()) &&
193d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao       (m_Config.options().hasNoDelete()  ||
194d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao        m_Config.options().hasInitFirst() ||
195d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao        m_Config.options().hasNoDLOpen()))) {
196affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    reserveOne(llvm::ELF::DT_FLAGS_1); // DT_FLAGS_1
197affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
198affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  reserveOne(llvm::ELF::DT_NULL); // for DT_NULL
2005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// applyEntries - apply entries
203d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaovoid ELFDynamic::applyEntries(const ELFFileFormat& pFormat)
2045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
205d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (LinkerConfig::DynObj == m_Config.codeGenType() &&
206d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      m_Config.options().Bsymbolic()) {
2075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      applyOne(llvm::ELF::DT_SYMBOLIC, 0x0); // DT_SYMBOLIC
2085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pFormat.hasInit())
2115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    applyOne(llvm::ELF::DT_INIT, pFormat.getInit().addr()); // DT_INIT
2125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pFormat.hasFini())
2145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    applyOne(llvm::ELF::DT_FINI, pFormat.getFini().addr()); // DT_FINI
2155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
216551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (pFormat.hasPreInitArray()) {
217551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    // DT_PREINIT_ARRAY
218551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    applyOne(llvm::ELF::DT_PREINIT_ARRAY, pFormat.getPreInitArray().addr());
219551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    // DT_PREINIT_ARRAYSZ
220551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    applyOne(llvm::ELF::DT_PREINIT_ARRAYSZ, pFormat.getPreInitArray().size());
221551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
222551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
2235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pFormat.hasInitArray()) {
2245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // DT_INIT_ARRAY
2255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    applyOne(llvm::ELF::DT_INIT_ARRAY, pFormat.getInitArray().addr());
2265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // DT_INIT_ARRAYSZ
2285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    applyOne(llvm::ELF::DT_INIT_ARRAYSZ, pFormat.getInitArray().size());
2295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pFormat.hasFiniArray()) {
2325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // DT_FINI_ARRAY
2335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    applyOne(llvm::ELF::DT_FINI_ARRAY, pFormat.getFiniArray().addr());
2345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // DT_FINI_ARRAYSZ
2365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    applyOne(llvm::ELF::DT_FINI_ARRAYSZ, pFormat.getFiniArray().size());
2375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pFormat.hasHashTab())
2405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    applyOne(llvm::ELF::DT_HASH, pFormat.getHashTab().addr()); // DT_HASH
2415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // FIXME: use llvm enum constant
2436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (pFormat.hasGNUHashTab())
2446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    applyOne(0x6ffffef5, pFormat.getGNUHashTab().addr()); // DT_GNU_HASH
2456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pFormat.hasDynSymTab()) {
2475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    applyOne(llvm::ELF::DT_SYMTAB, pFormat.getDynSymTab().addr()); // DT_SYMTAB
2485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    applyOne(llvm::ELF::DT_SYMENT, symbolSize()); // DT_SYMENT
2495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pFormat.hasDynStrTab()) {
2525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    applyOne(llvm::ELF::DT_STRTAB, pFormat.getDynStrTab().addr()); // DT_STRTAB
2535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    applyOne(llvm::ELF::DT_STRSZ, pFormat.getDynStrTab().size()); // DT_STRSZ
2545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  applyTargetEntries(pFormat); // DT_PLTGOT
2575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pFormat.hasRelPlt()) {
2596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_REL); // DT_PLTREL
2605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    applyOne(llvm::ELF::DT_JMPREL, pFormat.getRelPlt().addr()); // DT_JMPREL
2615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    applyOne(llvm::ELF::DT_PLTRELSZ, pFormat.getRelPlt().size()); // DT_PLTRELSZ
2625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else if (pFormat.hasRelaPlt()) {
2646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_RELA); // DT_PLTREL
2656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    applyOne(llvm::ELF::DT_JMPREL, pFormat.getRelaPlt().addr()); // DT_JMPREL
2666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    applyOne(llvm::ELF::DT_PLTRELSZ, pFormat.getRelaPlt().size()); // DT_PLTRELSZ
2676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
2685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pFormat.hasRelDyn()) {
2705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    applyOne(llvm::ELF::DT_REL, pFormat.getRelDyn().addr()); // DT_REL
2715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    applyOne(llvm::ELF::DT_RELSZ, pFormat.getRelDyn().size()); // DT_RELSZ
2725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    applyOne(llvm::ELF::DT_RELENT, m_pEntryFactory->relSize()); // DT_RELENT
2735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pFormat.hasRelaDyn()) {
2765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    applyOne(llvm::ELF::DT_RELA, pFormat.getRelaDyn().addr()); // DT_RELA
2775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    applyOne(llvm::ELF::DT_RELASZ, pFormat.getRelaDyn().size()); // DT_RELASZ
2785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    applyOne(llvm::ELF::DT_RELAENT, m_pEntryFactory->relaSize()); // DT_RELAENT
2795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
28122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (m_Backend.hasTextRel()) {
28222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    applyOne(llvm::ELF::DT_TEXTREL, 0x0); // DT_TEXTREL
28322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
284d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    if (m_Config.options().warnSharedTextrel() &&
285d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao        LinkerConfig::DynObj == m_Config.codeGenType())
28622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      mcld::warning(mcld::diag::warn_shared_textrel);
28722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
28822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
289affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  uint64_t dt_flags = 0x0;
290d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (m_Config.options().hasOrigin())
291affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    dt_flags |= llvm::ELF::DF_ORIGIN;
292d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (m_Config.options().Bsymbolic())
293affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    dt_flags |= llvm::ELF::DF_SYMBOLIC;
294d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (m_Config.options().hasNow())
295affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    dt_flags |= llvm::ELF::DF_BIND_NOW;
29622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (m_Backend.hasTextRel())
29722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    dt_flags |= llvm::ELF::DF_TEXTREL;
29822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (m_Backend.hasStaticTLS() &&
299d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      (LinkerConfig::DynObj == m_Config.codeGenType()))
30022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    dt_flags |= llvm::ELF::DF_STATIC_TLS;
3016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if ((m_Config.options().hasNewDTags() && 0x0 != dt_flags) ||
3036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      0 != (dt_flags & llvm::ELF::DF_STATIC_TLS))
304affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    applyOne(llvm::ELF::DT_FLAGS, dt_flags); // DT_FLAGS
305affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
306affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  uint64_t dt_flags_1 = 0x0;
307d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (m_Config.options().hasNow())
308affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    dt_flags_1 |= llvm::ELF::DF_1_NOW;
309d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (m_Config.options().hasLoadFltr())
310affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    dt_flags_1 |= llvm::ELF::DF_1_LOADFLTR;
311d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (m_Config.options().hasOrigin())
312affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    dt_flags_1 |= llvm::ELF::DF_1_ORIGIN;
313d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (m_Config.options().hasInterPose())
314affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    dt_flags_1 |= llvm::ELF::DF_1_INTERPOSE;
315d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (m_Config.options().hasNoDefaultLib())
316affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    dt_flags_1 |= llvm::ELF::DF_1_NODEFLIB;
317d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (m_Config.options().hasNoDump())
318affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    dt_flags_1 |= llvm::ELF::DF_1_NODUMP;
319d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (m_Config.options().Bgroup())
320affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    dt_flags_1 |= llvm::ELF::DF_1_GROUP;
321d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (LinkerConfig::DynObj == m_Config.codeGenType()) {
322d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    if (m_Config.options().hasNoDelete())
323affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      dt_flags_1 |= llvm::ELF::DF_1_NODELETE;
324d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    if (m_Config.options().hasInitFirst())
325affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      dt_flags_1 |= llvm::ELF::DF_1_INITFIRST;
326d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    if (m_Config.options().hasNoDLOpen())
327affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      dt_flags_1 |= llvm::ELF::DF_1_NOOPEN;
328affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
329affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (0x0 != dt_flags_1)
330affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    applyOne(llvm::ELF::DT_FLAGS_1, dt_flags_1); // DT_FLAGS_1
331affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
3325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  applyOne(llvm::ELF::DT_NULL, 0x0); // for DT_NULL
3335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// symbolSize
3365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaosize_t ELFDynamic::symbolSize() const
3375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return m_pEntryFactory->symbolSize();
3395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// reserveNeedEntry - reserve on DT_NEED entry.
3425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid ELFDynamic::reserveNeedEntry()
3435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  m_NeedList.push_back(m_pEntryFactory->clone());
3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// emit
3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid ELFDynamic::emit(const LDSection& pSection, MemoryRegion& pRegion) const
3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (pRegion.size() < pSection.size()) {
3515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    llvm::report_fatal_error(llvm::Twine("the given memory is smaller") +
3525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                             llvm::Twine(" than the section's demaind.\n"));
3535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
35587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint8_t* address = (uint8_t*)pRegion.begin();
3565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  EntryListType::const_iterator entry, entryEnd = m_NeedList.end();
3575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  for (entry = m_NeedList.begin(); entry != entryEnd; ++entry)
3585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    address += (*entry)->emit(address);
3595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  entryEnd = m_EntryList.end();
3615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  for (entry = m_EntryList.begin(); entry != entryEnd; ++entry)
3625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    address += (*entry)->emit(address);
3635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaovoid ELFDynamic::applySoname(uint64_t pStrTabIdx)
3665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  applyOne(llvm::ELF::DT_SONAME, pStrTabIdx); // DT_SONAME
3685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
370