15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- impl.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 "ARMGOT.h"
10cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
11cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <llvm/Support/Casting.h>
12cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
1322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/LDSection.h>
145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/LD/LDFileFormat.h>
155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Support/MemoryRegion.h>
16affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h>
175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaonamespace {
1922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const unsigned int ARMGOT0Num = 3;
205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} // end of anonymous namespace
215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld;
235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// ARMGOT
2622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoARMGOT::ARMGOT(LDSection& pSection)
27d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  : GOT(pSection), m_pLast(NULL)
285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Create GOT0 entries.
3022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  reserve(ARMGOT0Num);
315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Skip GOT0 entries.
3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (unsigned int i = 0; i < ARMGOT0Num; ++i) {
3422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    consume();
355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMGOT::~ARMGOT()
395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ARMGOT::hasGOT1() const
435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
4422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return (m_SectionData->size() > ARMGOT0Num);
455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
47d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaovoid ARMGOT::reserve(size_t pNum)
48d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{
49d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  for (size_t i = 0; i < pNum; i++) {
50d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    new ARMGOTEntry(0, m_SectionData);
51d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  }
52d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
53d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
54d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMGOTEntry* ARMGOT::consume()
55d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{
56d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (NULL == m_pLast) {
57d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    assert(!empty() && "Consume empty GOT entry!");
58d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    m_pLast = llvm::cast<ARMGOTEntry>(&m_SectionData->front());
59d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return m_pLast;
60d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  }
61d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
62d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  m_pLast = llvm::cast<ARMGOTEntry>(m_pLast->getNextNode());
63d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return m_pLast;
64d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
65d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
6622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid ARMGOT::reserveGOTPLT()
675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
68d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  ARMGOTEntry* entry = new ARMGOTEntry(0, m_SectionData);
6922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL == m_GOTPLT.front) {
7022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // GOTPLT is empty
7122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (NULL == m_GOT.front) {
7222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // GOT part is also empty. Since entry is the last entry, we can assign
7322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // it to GOTPLT directly.
7422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      m_GOTPLT.front = entry;
7522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
7622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    else {
7722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // GOTn is not empty. Shift GOTn backward by one entry.
7822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      m_GOTPLT.front = m_GOT.front;
79d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      m_GOT.front = llvm::cast<ARMGOTEntry>(m_GOT.front->getNextNode());
8022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
8122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
8222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else {
8322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // GOTPLT is not empty
8422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (NULL != m_GOT.front)
85d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      m_GOT.front = llvm::cast<ARMGOTEntry>(m_GOT.front->getNextNode());
865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid ARMGOT::reserveGOT()
905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
91d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  ARMGOTEntry* entry = new ARMGOTEntry(0, m_SectionData);
9222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL == m_GOT.front) {
9322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // Entry must be the last entry. We can directly assign it to GOT part.
9422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    m_GOT.front = entry;
9522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
98d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMGOTEntry* ARMGOT::consumeGOTPLT()
995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
10022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  assert(NULL != m_GOTPLT.front && "Consuming empty GOTPLT section!");
1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
10222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL == m_GOTPLT.last_used) {
10322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    m_GOTPLT.last_used = m_GOTPLT.front;
10422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else {
106d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    m_GOTPLT.last_used = llvm::cast<ARMGOTEntry>(m_GOTPLT.last_used->getNextNode());
10722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    assert(m_GOTPLT.last_used != m_GOT.front && "No GOT/PLT entry to consume!");
10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
10922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return m_GOTPLT.last_used;
1105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
112d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMGOTEntry* ARMGOT::consumeGOT()
1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
11422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  assert(NULL != m_GOT.front && "Consuming empty GOT section!");
1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
11622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL == m_GOT.last_used) {
11722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    m_GOT.last_used = m_GOT.front;
11822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
11922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else {
120d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    m_GOT.last_used = llvm::cast<ARMGOTEntry>(m_GOT.last_used->getNextNode());
12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    assert(m_GOT.last_used != NULL && "No GOTn entry to consume!");
12222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
12322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return m_GOT.last_used;
1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
12622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid ARMGOT::applyGOT0(uint64_t pAddress)
1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
128d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  llvm::cast<ARMGOTEntry>
129d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    (*(m_SectionData->getFragmentList().begin())).setValue(pAddress);
1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
13222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid ARMGOT::applyGOTPLT(uint64_t pPLTBase)
1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
13422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL == m_GOTPLT.front)
13522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return;
1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
13722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  SectionData::iterator entry(m_GOTPLT.front);
13822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  SectionData::iterator e_end;
13922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL == m_GOT.front)
14022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    e_end = m_SectionData->end();
14122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else
14222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    e_end = SectionData::iterator(m_GOT.front);
1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
14422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  while (entry != e_end) {
145d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    llvm::cast<ARMGOTEntry>(entry)->setValue(pPLTBase);
14622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    ++entry;
14722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaouint64_t ARMGOT::emit(MemoryRegion& pRegion)
1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
154d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  ARMGOTEntry* got = NULL;
1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint64_t result = 0x0;
15622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (iterator it = begin(), ie = end(); it != ie; ++it, ++buffer) {
157d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      got = &(llvm::cast<ARMGOTEntry>((*it)));
158d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      *buffer = static_cast<uint32_t>(got->getValue());
159d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      result += ARMGOTEntry::EntrySize;
1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return result;
1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
163affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
164