1551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===- AArch64GOT.cpp -----------------------------------------------------===//
2551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//
3551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//                     The MCLinker Project
4551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//
5551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// This file is distributed under the University of Illinois Open Source
6551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// License. See LICENSE.TXT for details.
7551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//
8551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===//
9551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines#include "AArch64GOT.h"
10551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSection.h"
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDFileFormat.h"
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h"
14551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <llvm/Support/Casting.h>
16551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
17551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesnamespace {
1837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst unsigned int AArch64GOT0Num = 3;
1937b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // end of anonymous namespace
20551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
2137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
22551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
23551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===----------------------------------------------------------------------===//
24551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines// AArch64GOT
25551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen HinesAArch64GOT::AArch64GOT(LDSection& pSection)
2637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : GOT(pSection), m_pGOTPLTFront(NULL), m_pGOTFront(NULL) {
27551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
28551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
2937b74a387bb3993387029859c2d9d051c41c724eStephen HinesAArch64GOT::~AArch64GOT() {
30551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
31551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
3237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid AArch64GOT::createGOT0() {
33551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // create GOT0, and put them into m_SectionData immediately
34551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  for (unsigned int i = 0; i < AArch64GOT0Num; ++i)
35551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    new AArch64GOTEntry(0, m_SectionData);
36551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
37551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
3837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool AArch64GOT::hasGOT1() const {
39551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return ((!m_GOT.empty()) || (!m_GOTPLT.empty()));
40551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
41551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
4237b74a387bb3993387029859c2d9d051c41c724eStephen HinesAArch64GOTEntry* AArch64GOT::createGOT() {
43551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  AArch64GOTEntry* entry = new AArch64GOTEntry(0, NULL);
44551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  m_GOT.push_back(entry);
45551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return entry;
46551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
47551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
4837b74a387bb3993387029859c2d9d051c41c724eStephen HinesAArch64GOTEntry* AArch64GOT::createGOTPLT() {
49551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  AArch64GOTEntry* entry = new AArch64GOTEntry(0, NULL);
50551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  m_GOTPLT.push_back(entry);
51551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return entry;
52551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
53551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
5437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid AArch64GOT::finalizeSectionSize() {
55551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  uint32_t offset = 0;
56551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  SectionData::FragmentListType& frag_list = m_SectionData->getFragmentList();
57551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // setup GOT0 offset
58551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  SectionData::iterator frag, fragEnd = m_SectionData->end();
59551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  for (frag = m_SectionData->begin(); frag != fragEnd; ++frag) {
60551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    frag->setOffset(offset);
61551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    offset += frag->size();
62551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
63551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
64551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // push GOTPLT into the SectionData and setup the offset
65551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (!m_GOTPLT.empty()) {
66551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    m_pGOTPLTFront = m_GOTPLT.front();
67551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    entry_iterator it, end = m_GOTPLT.end();
68551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    for (it = m_GOTPLT.begin(); it != end; ++it) {
69551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      AArch64GOTEntry* entry = *it;
70551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      frag_list.push_back(entry);
71551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      entry->setParent(m_SectionData);
72551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      entry->setOffset(offset);
73551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      offset += entry->size();
74551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    }
75551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
76551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  m_GOTPLT.clear();
77551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
78551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // push GOT into the SectionData and setup the offset
79551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (!m_GOT.empty()) {
80551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    m_pGOTFront = m_GOT.front();
81551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    entry_iterator it, end = m_GOT.end();
82551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    for (it = m_GOT.begin(); it != end; ++it) {
83551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      AArch64GOTEntry* entry = *it;
84551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      frag_list.push_back(entry);
85551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      entry->setParent(m_SectionData);
86551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      entry->setOffset(offset);
87551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      offset += entry->size();
88551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    }
89551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
90551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  m_GOT.clear();
91551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
92551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // set section size
93551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  m_Section.setSize(offset);
94551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
95551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
9637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid AArch64GOT::applyGOT0(uint64_t pAddress) {
9737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  llvm::cast<AArch64GOTEntry>(*(m_SectionData->getFragmentList().begin()))
9837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      .setValue(pAddress);
99551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
100551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
10137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid AArch64GOT::applyGOTPLT(uint64_t pPLTBase) {
10237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (m_pGOTPLTFront == NULL)
103551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return;
104551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
105551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  SectionData::iterator entry(m_pGOTPLTFront);
106551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  SectionData::iterator e_end;
10737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (m_pGOTFront == NULL)
108551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    e_end = m_SectionData->end();
109551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  else
110551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    e_end = SectionData::iterator(m_pGOTFront);
111551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
112551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  while (entry != e_end) {
113551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    llvm::cast<AArch64GOTEntry>(entry)->setValue(pPLTBase);
114551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    ++entry;
115551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
116551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
117551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
11837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesuint64_t AArch64GOT::emit(MemoryRegion& pRegion) {
119551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  uint64_t* buffer = reinterpret_cast<uint64_t*>(pRegion.begin());
120551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
121551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  AArch64GOTEntry* got = NULL;
122551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  uint64_t result = 0x0;
123551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  for (iterator it = begin(), ie = end(); it != ie; ++it, ++buffer) {
12437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    got = &(llvm::cast<AArch64GOTEntry>((*it)));
12537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    *buffer = static_cast<uint64_t>(got->getValue());
12637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    result += AArch64GOTEntry::EntrySize;
127551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  }
128551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return result;
129551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines}
130551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines
13137b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
132