ARMPLT.cpp revision 551ae4ebd3e9d137ea668fb83ae4a55b8cfba451
15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- ARMPLT.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"
105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "ARMPLT.h"
11cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
12cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <new>
13cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
14cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <llvm/Support/Casting.h>
15cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
1622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/LDSection.h>
17affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h>
185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld;
205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoARMPLT0::ARMPLT0(SectionData& pParent)
22d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  : PLT::Entry<sizeof(arm_plt0)>(pParent) {}
235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoARMPLT1::ARMPLT1(SectionData& pParent)
25d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  : PLT::Entry<sizeof(arm_plt1)>(pParent) {}
265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// ARMPLT
295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3087f34658dec9097d987d254a990ea7f311bfc95fStephen HinesARMPLT::ARMPLT(LDSection& pSection, ARMGOT &pGOTPLT)
3187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  : PLT(pSection), m_GOT(pGOTPLT) {
32551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  new ARMPLT0(*m_pSectionData);
3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoARMPLT::~ARMPLT()
3622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
3722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ARMPLT::hasPLT1() const
4022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
41551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return (m_pSectionData->size() > 1);
425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid ARMPLT::finalizeSectionSize()
455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
46551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  uint64_t size = (m_pSectionData->size() - 1) * sizeof(arm_plt1) +
4722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                     sizeof(arm_plt0);
4822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  m_Section.setSize(size);
4922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
5022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t offset = 0;
51551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  SectionData::iterator frag, fragEnd = m_pSectionData->end();
52551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  for (frag = m_pSectionData->begin(); frag != fragEnd; ++frag) {
5322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    frag->setOffset(offset);
5422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    offset += frag->size();
5522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5887f34658dec9097d987d254a990ea7f311bfc95fStephen HinesARMPLT1* ARMPLT::create()
595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
60551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ARMPLT1* plt1_entry = new (std::nothrow) ARMPLT1(*m_pSectionData);
6187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!plt1_entry)
6287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    fatal(diag::fail_allocate_memory_plt);
6387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return plt1_entry;
645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
66551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesvoid ARMPLT::applyPLT0()
67551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{
685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint64_t plt_base = m_Section.addr();
695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(plt_base && ".plt base address is NULL!");
705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint64_t got_base = m_GOT.addr();
725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(got_base && ".got base address is NULL!");
735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint32_t offset = 0;
755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (got_base > plt_base)
775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    offset = got_base - (plt_base + 16);
785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else
795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    offset = (plt_base + 16) - got_base;
805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
81551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  iterator first = m_pSectionData->getFragmentList().begin();
825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
83551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  assert(first != m_pSectionData->getFragmentList().end() &&
8467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao         "FragmentList is empty, applyPLT0 failed!");
855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMPLT0* plt0 = &(llvm::cast<ARMPLT0>(*first));
875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint32_t* data = 0;
89d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  data = static_cast<uint32_t*>(malloc(ARMPLT0::EntrySize));
905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (!data)
92cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    fatal(diag::fail_allocate_memory_plt);
935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
94d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  memcpy(data, arm_plt0, ARMPLT0::EntrySize);
955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  data[4] = offset;
965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
97d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  plt0->setValue(reinterpret_cast<unsigned char*>(data));
985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
100551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hinesvoid ARMPLT::applyPLT1()
101551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines{
1025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint64_t plt_base = m_Section.addr();
1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(plt_base && ".plt base address is NULL!");
1045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint64_t got_base = m_GOT.addr();
1065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(got_base && ".got base address is NULL!");
1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
108551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ARMPLT::iterator it = m_pSectionData->begin();
109551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  ARMPLT::iterator ie = m_pSectionData->end();
11067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  assert(it != ie && "FragmentList is empty, applyPLT1 failed!");
1115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
112d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  uint32_t GOTEntrySize = ARMGOTEntry::EntrySize;
1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint32_t GOTEntryAddress =
1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    got_base +  GOTEntrySize * 3;
1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint64_t PLTEntryAddress =
117d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    plt_base + ARMPLT0::EntrySize; //Offset of PLT0
1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ++it; //skip PLT0
120d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  uint64_t PLT1EntrySize = ARMPLT1::EntrySize;
1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMPLT1* plt1 = NULL;
1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint32_t* Out = NULL;
1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  while (it != ie) {
1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    plt1 = &(llvm::cast<ARMPLT1>(*it));
126d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    Out = static_cast<uint32_t*>(malloc(ARMPLT1::EntrySize));
1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (!Out)
129cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      fatal(diag::fail_allocate_memory_plt);
1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // Offset is the distance between the last PLT entry and the associated
1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // GOT entry.
1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    int32_t Offset = (GOTEntryAddress - (PLTEntryAddress + 8));
1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    Out[0] = arm_plt1[0] | ((Offset >> 20) & 0xFF);
1365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    Out[1] = arm_plt1[1] | ((Offset >> 12) & 0xFF);
1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    Out[2] = arm_plt1[2] | (Offset & 0xFFF);
1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
139d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    plt1->setValue(reinterpret_cast<unsigned char*>(Out));
1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    ++it;
1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    GOTEntryAddress += GOTEntrySize;
1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    PLTEntryAddress += PLT1EntrySize;
1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
14622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  m_GOT.applyGOTPLT(plt_base);
1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaouint64_t ARMPLT::emit(MemoryRegion& pRegion)
1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  uint64_t result = 0x0;
1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  iterator it = begin();
1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
15487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  unsigned char* buffer = pRegion.begin();
155d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  memcpy(buffer, llvm::cast<ARMPLT0>((*it)).getValue(), ARMPLT0::EntrySize);
156d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  result += ARMPLT0::EntrySize;
1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ++it;
1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMPLT1* plt1 = 0;
1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ARMPLT::iterator ie = end();
1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  while (it != ie) {
1625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    plt1 = &(llvm::cast<ARMPLT1>(*it));
163d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    memcpy(buffer + result, plt1->getValue(), ARMPLT1::EntrySize);
164d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    result += ARMPLT1::EntrySize;
1655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    ++it;
1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return result;
1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
169affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
170