1551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines//===- ARMGOT.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>
15affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h>
165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaonamespace {
1822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const unsigned int ARMGOT0Num = 3;
195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} // end of anonymous namespace
205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld;
225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// ARMGOT
2522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoARMGOT::ARMGOT(LDSection& pSection)
2687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  : GOT(pSection), m_pGOTPLTFront(NULL), m_pGOTFront(NULL)
275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
2887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // create GOT0, and put them into m_SectionData immediately
2987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (unsigned int i = 0; i < ARMGOT0Num; ++i)
3087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    new ARMGOTEntry(0, m_SectionData);
315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoARMGOT::~ARMGOT()
345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ARMGOT::hasGOT1() const
385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
3987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return ((!m_GOT.empty()) || (!m_GOTPLT.empty()));
40d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
41d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
4287f34658dec9097d987d254a990ea7f311bfc95fStephen HinesARMGOTEntry* ARMGOT::createGOT()
43d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao{
4487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ARMGOTEntry* entry = new ARMGOTEntry(0, NULL);
4587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_GOT.push_back(entry);
4687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return entry;
47d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
48d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
4987f34658dec9097d987d254a990ea7f311bfc95fStephen HinesARMGOTEntry* ARMGOT::createGOTPLT()
505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
5187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ARMGOTEntry* entry = new ARMGOTEntry(0, NULL);
5287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_GOTPLT.push_back(entry);
5387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return entry;
545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5687f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid ARMGOT::finalizeSectionSize()
575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
5887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t offset = 0;
5987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  SectionData::FragmentListType& frag_list = m_SectionData->getFragmentList();
6087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // setup GOT0 offset
6187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  SectionData::iterator frag, fragEnd = m_SectionData->end();
6287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (frag = m_SectionData->begin(); frag != fragEnd; ++frag) {
6387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    frag->setOffset(offset);
6487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    offset += frag->size();
6522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // push GOTPLT into the SectionData and setup the offset
6887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!m_GOTPLT.empty()) {
6987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_pGOTPLTFront = m_GOTPLT.front();
7087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    entry_iterator it, end = m_GOTPLT.end();
7187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    for (it = m_GOTPLT.begin(); it != end; ++it) {
7287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      ARMGOTEntry* entry = *it;
7387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      frag_list.push_back(entry);
7487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      entry->setParent(m_SectionData);
7587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      entry->setOffset(offset);
7687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      offset += entry->size();
7787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
7822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
7987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_GOTPLT.clear();
8087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
8187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // push GOT into the SectionData and setup the offset
8287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!m_GOT.empty()) {
8387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_pGOTFront = m_GOT.front();
8487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    entry_iterator it, end = m_GOT.end();
8587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    for (it = m_GOT.begin(); it != end; ++it) {
8687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      ARMGOTEntry* entry = *it;
8787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      frag_list.push_back(entry);
8887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      entry->setParent(m_SectionData);
8987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      entry->setOffset(offset);
9087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      offset += entry->size();
9187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
9222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
9387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_GOT.clear();
945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // set section size
9687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_Section.setSize(offset);
975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid ARMGOT::applyGOT0(uint64_t pAddress)
1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
101d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  llvm::cast<ARMGOTEntry>
102d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    (*(m_SectionData->getFragmentList().begin())).setValue(pAddress);
1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid ARMGOT::applyGOTPLT(uint64_t pPLTBase)
1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
10787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (NULL == m_pGOTPLTFront)
10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return;
1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
11087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  SectionData::iterator entry(m_pGOTPLTFront);
11122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  SectionData::iterator e_end;
11287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (NULL == m_pGOTFront)
11322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    e_end = m_SectionData->end();
11422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else
11587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    e_end = SectionData::iterator(m_pGOTFront);
1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
11722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  while (entry != e_end) {
118d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    llvm::cast<ARMGOTEntry>(entry)->setValue(pPLTBase);
11922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    ++entry;
12022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaouint64_t ARMGOT::emit(MemoryRegion& pRegion)
1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
12587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.begin());
1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
127d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  ARMGOTEntry* got = NULL;
1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint64_t result = 0x0;
12922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (iterator it = begin(), ie = end(); it != ie; ++it, ++buffer) {
130d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      got = &(llvm::cast<ARMGOTEntry>((*it)));
131d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      *buffer = static_cast<uint32_t>(got->getValue());
132d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      result += ARMGOTEntry::EntrySize;
1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return result;
1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
136affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
137