1d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao//===- X86Relocator.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//===----------------------------------------------------------------------===//
96f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include "X86Relocator.h"
106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include "X86RelocationFunctions.h"
116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
12f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/LinkerConfig.h>
13f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/IRBuilder.h>
146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/Support/MsgHandling.h>
156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/LD/LDSymbol.h>
16f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#include <mcld/Object/ObjectBuilder.h>
175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/Twine.h>
195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/DataTypes.h>
205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ELF.h>
215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld;
235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
2567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation Functions and Tables
2667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesDECL_X86_32_APPLY_RELOC_FUNCS
285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao/// the prototype of applying function
306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinestypedef Relocator::Result (*X86_32ApplyFunctionType)(Relocation& pReloc,
316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines						     X86_32Relocator& pParent);
3267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
3367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// the table entry of applying functions
346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstruct X86_32ApplyFunctionTriple
3567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{
366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32ApplyFunctionType func;
3767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  unsigned int type;
3867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  const char* name;
396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned int size;
4067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao};
4167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
4267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// declare the table of applying functions
436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic const X86_32ApplyFunctionTriple X86_32ApplyFunctions[] = {
446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  DECL_X86_32_APPLY_RELOC_FUNC_PTRS
4567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao};
4667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===--------------------------------------------------------------------===//
48d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// X86Relocator
4967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
50f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesX86Relocator::X86Relocator(const LinkerConfig& pConfig)
51f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  : Relocator(pConfig) {
525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
54d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoX86Relocator::~X86Relocator()
555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
58f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86Relocator::scanRelocation(Relocation& pReloc,
59f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                  IRBuilder& pLinker,
60f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                  Module& pModule,
61f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                  LDSection& pSection)
62f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
63f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (LinkerConfig::Object == config().codeGenType())
64f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return;
65f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // rsym - The relocation target symbol
66f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
67f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(NULL != rsym &&
68f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines         "ResolveInfo of relocation not set while scanRelocation");
69f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
70f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pReloc.updateAddend();
71f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(NULL != pSection.getLink());
72f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC))
73f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return;
74f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
75f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // Scan relocation type to determine if the GOT/PLT/Dynamic Relocation
76f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // entries should be created.
77f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (rsym->isLocal()) // rsym is local
78f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    scanLocalReloc(pReloc, pLinker, pModule, pSection);
79f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  else // rsym is external
80f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    scanGlobalReloc(pReloc, pLinker, pModule, pSection);
81f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
82f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // check if we should issue undefined reference for the relocation target
83f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // symbol
84f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
85f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    fatal(diag::undefined_reference) << rsym->name();
86f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
87f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
88f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86Relocator::addCopyReloc(ResolveInfo& pSym, X86GNULDBackend& pTarget)
89f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
90f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Relocation& rel_entry = *pTarget.getRelDyn().consumeEntry();
91f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  rel_entry.setType(pTarget.getCopyRelType());
92f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(pSym.outSymbol()->hasFragRef());
93f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
94f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  rel_entry.setSymInfo(&pSym);
95f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
96f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
97f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// defineSymbolforCopyReloc
98f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// For a symbol needing copy relocation, define a copy symbol in the BSS
99f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// section and all other reference to this symbol should refer to this
100f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// copy.
101f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// @note This is executed at `scan relocation' stage.
102f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesLDSymbol& X86Relocator::defineSymbolforCopyReloc(IRBuilder& pBuilder,
103f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                                 const ResolveInfo& pSym,
104f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                                 X86GNULDBackend& pTarget)
105f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
106f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // get or create corresponding BSS LDSection
107f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  LDSection* bss_sect_hdr = NULL;
108f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ELFFileFormat* file_format = pTarget.getOutputFormat();
109f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (ResolveInfo::ThreadLocal == pSym.type())
110f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    bss_sect_hdr = &file_format->getTBSS();
111f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  else
112f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    bss_sect_hdr = &file_format->getBSS();
113f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
114f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // get or create corresponding BSS SectionData
115f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(NULL != bss_sect_hdr);
116f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  SectionData* bss_section = NULL;
117f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (bss_sect_hdr->hasSectionData())
118f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    bss_section = bss_sect_hdr->getSectionData();
119f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  else
120f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    bss_section = IRBuilder::CreateSectionData(*bss_sect_hdr);
121f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
122f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // Determine the alignment by the symbol value
123f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // FIXME: here we use the largest alignment
124f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  uint32_t addralign = config().targets().bitclass() / 8;
125f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
126f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // allocate space in BSS for the copy symbol
127f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Fragment* frag = new FillFragment(0x0, 1, pSym.size());
128f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  uint64_t size = ObjectBuilder::AppendFragment(*frag,
129f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                                *bss_section,
130f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                                addralign);
131f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  bss_sect_hdr->setSize(bss_sect_hdr->size() + size);
132f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
133f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // change symbol binding to Global if it's a weak symbol
134f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding();
135f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (binding == ResolveInfo::Weak)
136f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    binding = ResolveInfo::Global;
137f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
138f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // Define the copy symbol in the bss section and resolve it
139f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  LDSymbol* cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
140f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                      pSym.name(),
141f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                      (ResolveInfo::Type)pSym.type(),
142f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                      ResolveInfo::Define,
143f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                      binding,
144f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                      pSym.size(),  // size
145f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                      0x0,          // value
146f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                      FragmentRef::Create(*frag, 0x0),
147f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                      (ResolveInfo::Visibility)pSym.other());
148f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
149f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // output all other alias symbols if any
150f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Module &pModule = pBuilder.getModule();
151f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Module::AliasList* alias_list = pModule.getAliasList(pSym);
152f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (NULL!=alias_list) {
153f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    Module::alias_iterator it, it_e=alias_list->end();
154f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    for (it=alias_list->begin(); it!=it_e; ++it) {
155f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      const ResolveInfo* alias = *it;
156f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (alias!=&pSym && alias->isDyn()) {
157f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
158f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                           alias->name(),
159f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                           (ResolveInfo::Type)alias->type(),
160f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                           ResolveInfo::Define,
161f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                           binding,
162f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                           alias->size(),  // size
163f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                           0x0,          // value
164f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                           FragmentRef::Create(*frag, 0x0),
165f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                           (ResolveInfo::Visibility)alias->other());
166f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
167f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
168f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
169f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
170f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return *cpy_sym;
171f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
172f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===//
1746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// X86_32Relocator
1756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===//
176f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesX86_32Relocator::X86_32Relocator(X86_32GNULDBackend& pParent,
177f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                 const LinkerConfig& pConfig)
178f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  : X86Relocator(pConfig), m_Target(pParent) {
1796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
1806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
181d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator::Result
1826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32Relocator::applyRelocation(Relocation& pRelocation)
1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
1845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation::Type type = pRelocation.type();
1855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (type >= sizeof (X86_32ApplyFunctions) / sizeof (X86_32ApplyFunctions[0]) ) {
18767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao    return Unknown;
1885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // apply the relocation
1916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86_32ApplyFunctions[type].func(pRelocation, *this);
1925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesconst char* X86_32Relocator::getName(Relocation::Type pType) const
19567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao{
1966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86_32ApplyFunctions[pType].name;
1976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
1986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocator::Size X86_32Relocator::getSize(Relocation::Type pType) const
2006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
2016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86_32ApplyFunctions[pType].size;;
20267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}
2035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
204f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86_32Relocator::scanLocalReloc(Relocation& pReloc,
205f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines															     	 IRBuilder& pBuilder,
206f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines																		 Module& pModule,
207f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines																		 LDSection& pSection)
208f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
209f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // rsym - The relocation target symbol
210f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
211f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
212f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  switch(pReloc.type()){
213f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
214f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_32:
215f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_16:
216f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_8:
217f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // If buiding PIC object (shared library or PIC executable),
218f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // a dynamic relocations with RELATIVE type to this location is needed.
219f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Reserve an entry in .rel.dyn
220f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (config().isCodeIndep()) {
221f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().reserveEntry();
222f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // set Rel bit
223f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
224f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
225f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
226f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
227f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
228f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_PLT32:
229f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
230f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
231f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_GOTOFF:
232f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_GOTPC:
233f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // FIXME: A GOT section is needed
234f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
235f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
236f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_GOT32:
237f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Symbol needs GOT entry, reserve entry in .got
238f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // return if we already create GOT for this symbol
239f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (rsym->reserved() & (ReserveGOT | GOTRel))
240f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
241f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // FIXME: check STT_GNU_IFUNC symbol
242f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getGOT().reserve();
243f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
244f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // If the GOT is used in statically linked binaries,
245f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // the GOT entry is enough and no relocation is needed.
246f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (config().isCodeStatic()) {
247f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveGOT);
248f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
249f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
250f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // If building shared object or the symbol is undefined, a dynamic
251f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // relocation is needed to relocate this GOT entry. Reserve an
252f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // entry in .rel.dyn
253f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (LinkerConfig::DynObj ==
254f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                   config().codeGenType() || rsym->isUndef() || rsym->isDyn()) {
255f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().reserveEntry();
256f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // set GOTRel bit
257f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | GOTRel);
258f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
259f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
260f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // set GOT bit
261f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      rsym->setReserved(rsym->reserved() | ReserveGOT);
262f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
263f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
264f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_PC32:
265f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_PC16:
266f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_PC8:
267f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
268f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
269f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_GD: {
270f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // FIXME: no linker optimization for TLS relocation
271f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (rsym->reserved() & GOTRel)
272f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
273f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getGOT().reserve(2);
274f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // reserve an rel entry
275f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getRelDyn().reserveEntry();
276f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // set GOTRel bit
277f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      rsym->setReserved(rsym->reserved() | GOTRel);
278f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // define the section symbol for .tdata or .tbss
279f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // the target symbol of the created dynamic relocation should be the
280f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // section symbol of the section which this symbol defined. so we
281f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // need to define that section symbol here
282f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      ELFFileFormat* file_format = getTarget().getOutputFormat();
283f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      const LDSection* sym_sect =
284f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines               &rsym->outSymbol()->fragRef()->frag()->getParent()->getSection();
285f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (&file_format->getTData() == sym_sect) {
286f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (!getTarget().hasTDATASymbol())
287f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().setTDATASymbol(*pModule.getSectionSymbolSet().get(*sym_sect));
288f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
289f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      else if (&file_format->getTBSS() == sym_sect || rsym->isCommon()) {
290f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (!getTarget().hasTBSSSymbol())
291f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().setTBSSSymbol(*pModule.getSectionSymbolSet().get(*sym_sect));
292f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
293f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      else
294f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        error(diag::invalid_tls) << rsym->name() << sym_sect->name();
295f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
296f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
297f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
298f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_LDM:
299f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTLSModuleID();
300f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
301f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
302f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_LDO_32:
303f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
304f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
305f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_IE:
306f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().setHasStaticTLS();
307f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // if buildint shared object, a RELATIVE dynamic relocation is needed
308f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (LinkerConfig::DynObj == config().codeGenType()) {
309f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().reserveEntry();
310f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
311f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
312f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      } else {
313f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // for local sym, we can convert ie to le if not building shared object
314f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        convertTLSIEtoLE(pReloc, pSection);
315f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
316f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
317f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (rsym->reserved() & GOTRel)
318f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
319f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // reserve got and dyn relocation entries for tp-relative offset
320f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getGOT().reserve();
321f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getRelDyn().reserveEntry();
322f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // set GOTRel bit
323f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      rsym->setReserved(rsym->reserved() | GOTRel);
324f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
325f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
326f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
327f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_GOTIE:
328f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().setHasStaticTLS();
329f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (rsym->reserved() & GOTRel)
330f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
331f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // reserve got and dyn relocation entries for tp-relative offset
332f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getGOT().reserve();
333f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getRelDyn().reserveEntry();
334f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // set GOTRel bit
335f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      rsym->setReserved(rsym->reserved() | GOTRel);
336f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
337f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
338f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
339f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_LE:
340f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_LE_32:
341f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().setHasStaticTLS();
342f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // if buildint shared object, a dynamic relocation is needed
343f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (LinkerConfig::DynObj == config().codeGenType()) {
344f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().reserveEntry();
345f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
346f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
347f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // the target symbol of the dynamic relocation is rsym, so we need to
348f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // emit it into .dynsym
349f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        assert(NULL != rsym->outSymbol());
350f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
351f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
352f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
353f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
354f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    default:
355f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      fatal(diag::unsupported_relocation) << (int)pReloc.type()
356f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                          << "mclinker@googlegroups.com";
357f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
358f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  } // end switch
359f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
360f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
361f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86_32Relocator::scanGlobalReloc(Relocation& pReloc,
362f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines								 				 				 		  IRBuilder& pBuilder,
363f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines								 				 				 		  Module& pModule,
364f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines								 				 				 		  LDSection& pSection)
365f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
366f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // rsym - The relocation target symbol
367f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
368f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
369f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  switch(pReloc.type()) {
370f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_32:
371f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_16:
372f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_8:
373f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Absolute relocation type, symbol may needs PLT entry or
374f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // dynamic relocation entry
375f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().symbolNeedsPLT(*rsym)) {
376f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // create plt for this symbol if it does not have one
377f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (!(rsym->reserved() & ReservePLT)){
378f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // Symbol needs PLT entry, we need to reserve a PLT entry
379f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // and the corresponding GOT and dynamic relocation entry
380f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // in .got and .rel.plt. (GOT entry will be reserved simultaneously
381f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // when calling X86PLT->reserveEntry())
382f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().getPLT().reserveEntry();
383f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().getGOTPLT().reserve();
384f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().getRelPLT().reserveEntry();
385f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // set PLT bit
386f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          rsym->setReserved(rsym->reserved() | ReservePLT);
387f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
388f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
389f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
390f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), true)) {
391f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
392f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().reserveEntry();
393f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
394f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, getTarget());
395f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          addCopyReloc(*cpy_sym.resolveInfo(), getTarget());
396f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
397f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        else {
398f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // set Rel bit
399f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          rsym->setReserved(rsym->reserved() | ReserveRel);
400f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().checkAndSetHasTextRel(pSection);
401f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
402f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
403f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
404f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
405f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_GOTOFF:
406f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_GOTPC: {
407f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // FIXME: A GOT section is needed
408f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
409f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
410f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
411f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_PLT32:
412f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // A PLT entry is needed when building shared library
413f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
414f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // return if we already create plt for this symbol
415f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (rsym->reserved() & ReservePLT)
416f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
417f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
418f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // if the symbol's value can be decided at link time, then no need plt
419f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().symbolFinalValueIsKnown(*rsym))
420f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
421f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
422f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // if symbol is defined in the ouput file and it's not
423f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // preemptible, no need plt
424f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (rsym->isDefine() && !rsym->isDyn() &&
425f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines         !getTarget().isSymbolPreemptible(*rsym)) {
426f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
427f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
428f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
429f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Symbol needs PLT entry, we need to reserve a PLT entry
430f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // and the corresponding GOT and dynamic relocation entry
431f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // in .got and .rel.plt. (GOT entry will be reserved simultaneously
432f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // when calling X86PLT->reserveEntry())
433f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getPLT().reserveEntry();
434f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getGOTPLT().reserve();
435f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getRelPLT().reserveEntry();
436f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // set PLT bit
437f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      rsym->setReserved(rsym->reserved() | ReservePLT);
438f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
439f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
440f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_GOT32:
441f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Symbol needs GOT entry, reserve entry in .got
442f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // return if we already create GOT for this symbol
443f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (rsym->reserved() & (ReserveGOT | GOTRel))
444f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
445f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getGOT().reserve();
446f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
447f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // If the GOT is used in statically linked binaries,
448f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // the GOT entry is enough and no relocation is needed.
449f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (config().isCodeStatic()) {
450f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveGOT);
451f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
452f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
453f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // If building shared object or the symbol is undefined, a dynamic
454f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // relocation is needed to relocate this GOT entry. Reserve an
455f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // entry in .rel.dyn
456f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (LinkerConfig::DynObj ==
457f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                   config().codeGenType() || rsym->isUndef() || rsym->isDyn()) {
458f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().reserveEntry();
459f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // set GOTRel bit
460f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | GOTRel);
461f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
462f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
463f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // set GOT bit
464f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      rsym->setReserved(rsym->reserved() | ReserveGOT);
465f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
466f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
467f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_PC32:
468f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_PC16:
469f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_PC8:
470f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
471f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().symbolNeedsPLT(*rsym) &&
472f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          LinkerConfig::DynObj != config().codeGenType()) {
473f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // create plt for this symbol if it does not have one
474f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (!(rsym->reserved() & ReservePLT)){
475f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // Symbol needs PLT entry, we need to reserve a PLT entry
476f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // and the corresponding GOT and dynamic relocation entry
477f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // in .got and .rel.plt. (GOT entry will be reserved simultaneously
478f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // when calling X86PLT->reserveEntry())
479f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().getPLT().reserveEntry();
480f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().getGOTPLT().reserve();
481f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().getRelPLT().reserveEntry();
482f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // set PLT bit
483f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          rsym->setReserved(rsym->reserved() | ReservePLT);
484f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
485f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
486f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
487f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), false)) {
488f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
489f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().reserveEntry();
490f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
491f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, getTarget());
492f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          addCopyReloc(*cpy_sym.resolveInfo(), getTarget());
493f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
494f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        else {
495f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // set Rel bit
496f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          rsym->setReserved(rsym->reserved() | ReserveRel);
497f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().checkAndSetHasTextRel(pSection);
498f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
499f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
500f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
501f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
502f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_GD: {
503f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // FIXME: no linker optimization for TLS relocation
504f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (rsym->reserved() & GOTRel)
505f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
506f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // reserve two pairs of got entry and dynamic relocation
507f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getGOT().reserve(2);
508f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getRelDyn().reserveEntry(2);
509f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
510f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // set GOTRel bit
511f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      rsym->setReserved(rsym->reserved() | GOTRel);
512f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
513f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
514f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
515f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_LDM:
516f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTLSModuleID();
517f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
518f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
519f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_LDO_32:
520f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
521f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
522f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_IE:
523f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().setHasStaticTLS();
524f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // if buildint shared object, a RELATIVE dynamic relocation is needed
525f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (LinkerConfig::DynObj == config().codeGenType()) {
526f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().reserveEntry();
527f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
528f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
529f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      } else {
530f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // for global sym, we can convert ie to le if its final value is known
531f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (getTarget().symbolFinalValueIsKnown(*rsym)) {
532f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          convertTLSIEtoLE(pReloc, pSection);
533f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          return;
534f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
535f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
536f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (rsym->reserved() & GOTRel)
537f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
538f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // reserve got and dyn relocation entries for tp-relative offset
539f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getGOT().reserve();
540f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getRelDyn().reserveEntry();
541f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
542f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // set GOTRel bit
543f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      rsym->setReserved(rsym->reserved() | GOTRel);
544f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
545f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
546f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_GOTIE:
547f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().setHasStaticTLS();
548f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (rsym->reserved() & GOTRel)
549f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
550f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // reserve got and dyn relocation entries for tp-relative offset
551f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getGOT().reserve();
552f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getRelDyn().reserveEntry();
553f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
554f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // set GOTRel bit
555f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      rsym->setReserved(rsym->reserved() | GOTRel);
556f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
557f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
558f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_LE:
559f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_LE_32:
560f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().setHasStaticTLS();
561f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // if buildint shared object, a dynamic relocation is needed
562f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (LinkerConfig::DynObj == config().codeGenType()) {
563f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().reserveEntry();
564f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
565f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
566f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
567f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
568f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
569f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
570f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    default: {
571f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      fatal(diag::unsupported_relocation) << (int)pReloc.type()
572f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                          << "mclinker@googlegroups.com";
573f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
574f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
575f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  } // end switch
576f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
577f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
578f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// Create a GOT entry for the TLS module index
579f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesX86_32GOTEntry& X86_32Relocator::getTLSModuleID()
580f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
581f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  static X86_32GOTEntry* got_entry = NULL;
582f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (NULL != got_entry)
583f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return *got_entry;
584f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
585f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // Allocate 2 got entries and 1 dynamic reloc for R_386_TLS_LDM
586f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  getTarget().getGOT().reserve(2);
587f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  got_entry = getTarget().getGOT().consume();
588f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  getTarget().getGOT().consume()->setValue(0x0);
589f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
590f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  getTarget().getRelDyn().reserveEntry();
591f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Relocation* rel_entry = getTarget().getRelDyn().consumeEntry();
592f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  rel_entry->setType(llvm::ELF::R_386_TLS_DTPMOD32);
593f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  rel_entry->targetRef().assign(*got_entry, 0x0);
594f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  rel_entry->setSymInfo(NULL);
595f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
596f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return *got_entry;
597f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
598f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
599f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// convert R_386_TLS_IE to R_386_TLS_LE
600f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86_32Relocator::convertTLSIEtoLE(Relocation& pReloc,
601f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                       LDSection& pSection)
602f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
603f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(pReloc.type() == llvm::ELF::R_386_TLS_IE);
604f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(NULL != pReloc.targetRef().frag());
605f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
606f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // 1. create the fragment references and new relocs
607f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  uint64_t off = pReloc.targetRef().offset();
608f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (off >= 4)
609f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    off -= 4;
610f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  else
611f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    off = 0;
612f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
613f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  FragmentRef* fragref = FragmentRef::Create(*pReloc.targetRef().frag(), off);
614f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // TODO: add symbols for R_386_TLS_OPT relocs
615f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Relocation* reloc = Relocation::Create(X86_32Relocator::R_386_TLS_OPT,
616f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                         *fragref,
617f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                         0x0);
618f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
619f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // 2. modify the opcodes to the appropriate ones
620f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  uint8_t* op =  (reinterpret_cast<uint8_t*>(&reloc->target()));
621f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  off = pReloc.targetRef().offset() - reloc->targetRef().offset() - 1;
622f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (op[off] == 0xa1) {
623f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    op[off] = 0xb8;
624f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  } else {
625f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    switch (op[off - 1]) {
626f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      case 0x8b:
627f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        assert((op[off] & 0xc7) == 0x05);
628f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        op[off - 1] = 0xc7;
629f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        op[off]     = 0xc0 | ((op[off] >> 3) & 7);
630f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        break;
631f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      case 0x03:
632f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        assert((op[off] & 0xc7) == 0x05);
633f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        op[off - 1] = 0x81;
634f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        op[off]     = 0xc0 | ((op[off] >> 3) & 7);
635f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        break;
636f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      default:
637f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        assert(0);
638f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        break;
639f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
640f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
641f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
642f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // 3. insert the new relocs "BEFORE" the original reloc.
643f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pSection.getRelocData()->getRelocationList().insert(
644f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    RelocData::iterator(pReloc), reloc);
645f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
646f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // 4. change the type of the original reloc
647f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pReloc.setType(llvm::ELF::R_386_TLS_LE);
648f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
649f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
65067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
65167e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// Relocation helper function
65267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
6535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
65422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// helper_DynRel - Get an relocation entry in .rel.dyn
65522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaostatic
65622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoRelocation& helper_DynRel(ResolveInfo* pSym,
65722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                          Fragment& pFrag,
65822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                          uint64_t pOffset,
659d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                          X86Relocator::Type pType,
6606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          X86_32Relocator& pParent)
66122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
6626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32GNULDBackend& ld_backend = pParent.getTarget();
66322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
66422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  rel_entry.setType(pType);
66522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  rel_entry.targetRef().assign(pFrag, pOffset);
66622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (pType == llvm::ELF::R_386_RELATIVE || NULL == pSym)
66722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    rel_entry.setSymInfo(0);
66822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else
66922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    rel_entry.setSymInfo(pSym);
67022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
67122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return rel_entry;
67222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
67322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
67422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
67522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// helper_use_relative_reloc - Check if symbol can use relocation
67622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// R_386_RELATIVE
6775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic bool
6785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaohelper_use_relative_reloc(const ResolveInfo& pSym,
6796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          const X86_32Relocator& pFactory)
6805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
6825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // if symbol is dynamic or undefine or preemptible
683affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (pSym.isDyn() ||
68422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      pSym.isUndef() ||
68522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      pFactory.getTarget().isSymbolPreemptible(pSym))
6865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return false;
6875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return true;
6885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
6916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32GOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
6926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines					X86_32Relocator& pParent)
6935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
6945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // rsym - The relocation target symbol
6955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
6966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32GNULDBackend& ld_backend = pParent.getTarget();
6975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
69922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL != got_entry)
70022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return *got_entry;
70122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
70222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // not found
70322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  got_entry = ld_backend.getGOT().consume();
70422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pParent.getSymGOTMap().record(*rsym, *got_entry);
70522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
70622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // If we first get this GOT entry, we should initialize it.
707f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (rsym->reserved() & X86Relocator::ReserveGOT) {
70822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // No corresponding dynamic relocation, initialize to the symbol value.
709d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    got_entry->setValue(pReloc.symValue());
71022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
711f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  else if (rsym->reserved() & X86Relocator::GOTRel) {
71222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // Initialize got_entry content and the corresponding dynamic relocation.
71322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (helper_use_relative_reloc(*rsym, pParent)) {
71422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_386_RELATIVE, pParent);
715d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      got_entry->setValue(pReloc.symValue());
7165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
7175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    else {
71822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_386_GLOB_DAT, pParent);
719d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      got_entry->setValue(0);
7205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
7215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
72222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else {
72322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    fatal(diag::reserve_entry_number_mismatch_got);
72422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
72522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return *got_entry;
7265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
7275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
7306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_GOT_ORG(X86_32Relocator& pParent)
7315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
73222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return pParent.getTarget().getGOTPLT().addr();
7335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
7345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
7376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_GOT(Relocation& pReloc, X86_32Relocator& pParent)
7385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
7396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent);
740d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address got_addr = pParent.getTarget().getGOT().addr();
74122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return got_addr + got_entry.getOffset();
7425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
7435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
7466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesPLTEntryBase& helper_get_PLT_and_init(Relocation& pReloc,
7476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines				      X86_32Relocator& pParent)
7485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
7495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // rsym - The relocation target symbol
7505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
7516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32GNULDBackend& ld_backend = pParent.getTarget();
7525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
753d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(*rsym);
75422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL != plt_entry)
75522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return *plt_entry;
75622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
75722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // not found
75822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  plt_entry = ld_backend.getPLT().consume();
75922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pParent.getSymPLTMap().record(*rsym, *plt_entry);
76022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // If we first get this PLT entry, we should initialize it.
761f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (rsym->reserved() & X86Relocator::ReservePLT) {
7626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    X86_32GOTEntry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym);
76322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!");
76422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    gotplt_entry = ld_backend.getGOTPLT().consume();
76522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
76622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // init the corresponding rel entry in .rel.plt
76722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    Relocation& rel_entry = *ld_backend.getRelPLT().consumeEntry();
76822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    rel_entry.setType(llvm::ELF::R_386_JUMP_SLOT);
76922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    rel_entry.targetRef().assign(*gotplt_entry);
77022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    rel_entry.setSymInfo(rsym);
77122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
77222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else {
77322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    fatal(diag::reserve_entry_number_mismatch_plt);
7745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
7755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
77622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return *plt_entry;
77722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
7785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
7816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_PLT_ORG(X86_32Relocator& pParent)
7825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
78322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return pParent.getTarget().getPLT().addr();
7845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
7855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaostatic
7886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_PLT(Relocation& pReloc, X86_32Relocator& pParent)
7895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
790d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  PLTEntryBase& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
79122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return helper_PLT_ORG(pParent) + plt_entry.getOffset();
7925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
7935460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
7965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Each relocation function implementation //
7975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//=========================================//
7985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_NONE
8006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result none(Relocation& pReloc, X86_32Relocator& pParent)
8015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
802d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
8035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
8045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_32: S + A
80622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_16
80722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_8
8086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result abs(Relocation& pReloc, X86_32Relocator& pParent)
8095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
8105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
811d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
812d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord S = pReloc.symValue();
81367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
81422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                              *rsym,
815f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                              (rsym->reserved() & X86Relocator::ReservePLT),
81622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                              true);
817f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  FragmentRef &target_fragref = pReloc.targetRef();
818f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Fragment *target_frag = target_fragref.frag();
8195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
820f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  LDSection& target_sect = target_frag->getParent()->getSection();
821affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // If the flag of target section is not ALLOC, we will not scan this relocation
822affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // but perform static relocation. (e.g., applying .debug section)
82322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
824affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = S + A;
825d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return X86Relocator::OK;
826affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
827affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
828affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // A local symbol may need REL Type dynamic relocation
82967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  if (rsym->isLocal() && has_dyn_rel) {
830f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    X86Relocator::Type pType = pReloc.type();
831f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (llvm::ELF::R_386_32 == pType)
832f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      pType = llvm::ELF::R_386_RELATIVE;
833f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    helper_DynRel(rsym, *target_frag, target_fragref.offset(), pType, pParent);
8345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    pReloc.target() = S + A;
835d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return X86Relocator::OK;
8365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
837affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
838affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // An external symbol may need PLT and dynamic relocation
839affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!rsym->isLocal()) {
840f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (rsym->reserved() & X86Relocator::ReservePLT) {
8415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      S = helper_PLT(pReloc, pParent);
8425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
843affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // If we generate a dynamic relocation (except R_386_RELATIVE)
844affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // for a place, we should not perform static relocation on it
845affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // in order to keep the addend store in the place correct.
84667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao    if (has_dyn_rel) {
84722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      if (llvm::ELF::R_386_32 == pReloc.type() &&
84822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao          helper_use_relative_reloc(*rsym, pParent)) {
849f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        helper_DynRel(rsym, *target_frag, target_fragref.offset(),
850f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines              llvm::ELF::R_386_RELATIVE, pParent);
8515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      }
8525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      else {
853f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        helper_DynRel(rsym, *target_frag, target_fragref.offset(),
854f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                      pReloc.type(), pParent);
855d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao        return X86Relocator::OK;
8565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      }
8575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
8585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
8595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // perform static relocation
8615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = S + A;
862d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
8635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
8645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_PC32: S + A - P
86622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_PC16
86722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_PC8
8686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result rel(Relocation& pReloc, X86_32Relocator& pParent)
8695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
870affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ResolveInfo* rsym = pReloc.symInfo();
871d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
872d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord S = pReloc.symValue();
873d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord P = pReloc.place();
874affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
87522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
876affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // If the flag of target section is not ALLOC, we will not scan this relocation
877affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // but perform static relocation. (e.g., applying .debug section)
87822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
879affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = S + A - P;
880d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return X86Relocator::OK;
881affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
882affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
883affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // An external symbol may need PLT and dynamic relocation
884affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!rsym->isLocal()) {
885f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (rsym->reserved() & X86Relocator::ReservePLT) {
886affc150dc44fab1911775a49636d0ce85333b634Zonr Chang       S = helper_PLT(pReloc, pParent);
887affc150dc44fab1911775a49636d0ce85333b634Zonr Chang       pReloc.target() = S + A - P;
888affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
889affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (pParent.getTarget().symbolNeedsDynRel(
89022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                              *rsym,
891f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                              (rsym->reserved() & X86Relocator::ReservePLT),
89222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                              false)) {
89322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      if (helper_use_relative_reloc(*rsym, pParent) ) {
89422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        helper_DynRel(rsym, *pReloc.targetRef().frag(),
89522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao              pReloc.targetRef().offset(), llvm::ELF::R_386_RELATIVE, pParent);
896affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      }
897affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      else {
89822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        helper_DynRel(rsym, *pReloc.targetRef().frag(),
89922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                          pReloc.targetRef().offset(), pReloc.type(), pParent);
900d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao          return X86Relocator::OK;
901affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      }
902affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
903affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
904affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
905affc150dc44fab1911775a49636d0ce85333b634Zonr Chang   // perform static relocation
906affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  pReloc.target() = S + A - P;
907d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
9085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
9095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOTOFF: S + A - GOT_ORG
9116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result gotoff32(Relocation& pReloc, X86_32Relocator& pParent)
9125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
913d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord      A = pReloc.target() + pReloc.addend();
914d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
915d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address S = pReloc.symValue();
9165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = S + A - GOT_ORG;
918d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
9195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
9205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOTPC: GOT_ORG + A - P
9226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result gotpc32(Relocation& pReloc, X86_32Relocator& pParent)
9235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
924d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord      A       = pReloc.target() + pReloc.addend();
925d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
9265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Apply relocation.
92722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pReloc.target() = GOT_ORG + A - pReloc.place();
928d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
9295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
9305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOT32: GOT(S) + A - GOT_ORG
9326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result got32(Relocation& pReloc, X86_32Relocator& pParent)
9335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
934affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!(pReloc.symInfo()->reserved()
935f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines       & (X86Relocator::ReserveGOT | X86Relocator::GOTRel))) {
936d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return X86Relocator::BadReloc;
9375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
938d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address GOT_S   = helper_GOT(pReloc, pParent);
939d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord      A       = pReloc.target() + pReloc.addend();
940d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
9415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Apply relocation.
9425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = GOT_S + A - GOT_ORG;
943d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
9445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
9455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_PLT32: PLT(S) + A - P
9476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result plt32(Relocation& pReloc, X86_32Relocator& pParent)
9485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
9495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // PLT_S depends on if there is a PLT entry.
950d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address PLT_S;
951f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if ((pReloc.symInfo()->reserved() & X86Relocator::ReservePLT))
9525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    PLT_S = helper_PLT(pReloc, pParent);
9535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else
9545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    PLT_S = pReloc.symValue();
955d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord      A = pReloc.target() + pReloc.addend();
956d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address P = pReloc.place();
9575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = PLT_S + A - P;
958d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
9595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
96022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
96122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_GD:
9626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_gd(Relocation& pReloc, X86_32Relocator& pParent)
96322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
96422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // global-dynamic
96522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
96622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // must reserve two pairs of got and dynamic relocation
967f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (!(rsym->reserved() & X86Relocator::GOTRel)) {
968d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao     return X86Relocator::BadReloc;
96922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
97022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
9716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32GNULDBackend& ld_backend = pParent.getTarget();
97222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ELFFileFormat* file_format = pParent.getTarget().getOutputFormat();
97322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // setup corresponding got and dynamic relocatio entries:
97422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get first got entry, if there is already a got entry for rsym, then apply
97522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // this relocation to the got entry directly. If not, setup the corresponding
97622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // got and dyn relocation entries
9776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32GOTEntry* got_entry1 = pParent.getSymGOTMap().lookUp(*rsym);
97822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
97922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL == got_entry1) {
98022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get and init two got entries if not exist
98122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    got_entry1 = ld_backend.getGOT().consume();
98222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    pParent.getSymGOTMap().record(*rsym, *got_entry1);
9836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    X86_32GOTEntry* got_entry2 = ld_backend.getGOT().consume();
984d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    got_entry1->setValue(0x0);
985d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    got_entry2->setValue(0x0);
98622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // setup dyn rel for get_entry1
98722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    Relocation& rel_entry1 = helper_DynRel(rsym, *got_entry1, 0x0,
98822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                        llvm::ELF::R_386_TLS_DTPMOD32, pParent);
98922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (rsym->isLocal()) {
99022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // for local symbol, set got_entry2 to symbol value
991d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      got_entry2->setValue(pReloc.symValue());
99222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
99322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // for local tls symbol, add rel entry against the section symbol this
99422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // symbol belong to (.tdata or .tbss)
99522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      const LDSection* sym_sect =
99622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao         &rsym->outSymbol()->fragRef()->frag()->getParent()->getSection();
99722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      ResolveInfo* sect_sym = NULL;
99822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      if (&file_format->getTData() == sym_sect)
99922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        sect_sym = pParent.getTarget().getTDATASymbol().resolveInfo();
100022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      else
100122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        sect_sym = pParent.getTarget().getTBSSSymbol().resolveInfo();
100222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      rel_entry1.setSymInfo(sect_sym);
100322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
100422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    else {
100522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // for non-local symbol, add a pair of rel entries against this symbol
100622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // for those two got entries
100722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      helper_DynRel(rsym, *got_entry2, 0x0,
100822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                        llvm::ELF::R_386_TLS_DTPOFF32, pParent);
100922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
101022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
101122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
101222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // perform relocation to the first got entry
1013d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
101422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // GOT_OFF - the offset between the got_entry1 and _GLOBAL_OFFSET_TABLE (the
101522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // .got.plt section)
1016d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address GOT_OFF =
101722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao     file_format->getGOT().addr() +
101822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao     got_entry1->getOffset() -
101922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao     file_format->getGOTPLT().addr();
102022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pReloc.target() = GOT_OFF + A;
1021d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
102222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
102322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
102422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_LDM
10256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_ldm(Relocation& pReloc, X86_32Relocator& pParent)
102622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
102722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // FIXME: no linker optimization for TLS relocation
1028f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  const X86_32GOTEntry& got_entry = pParent.getTLSModuleID();
102922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
103022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // All GOT offsets are relative to the end of the GOT.
1031d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::SWord GOT_S = got_entry.getOffset() -
103222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                      (pParent.getTarget().getGOTPLT().addr() -
103322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                       pParent.getTarget().getGOT().addr());
1034d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
103522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pReloc.target() = GOT_S + A;
103622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1037d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
103822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
103922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
104022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_LDO_32
10416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_ldo_32(Relocation& pReloc, X86_32Relocator& pParent)
104222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
104322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // FIXME: no linker optimization for TLS relocation
1044d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
1045d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address S = pReloc.symValue();
104622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pReloc.target() = S + A;
1047d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
104822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
104922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
105022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_X86_TLS_IE
10516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_ie(Relocation& pReloc, X86_32Relocator& pParent)
105222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
105322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
1054f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (!(rsym->reserved() & X86Relocator::GOTRel)) {
1055d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao     return X86Relocator::BadReloc;
105622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
105722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1058f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (rsym->reserved() & X86Relocator::ReserveRel) {
105922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // when building shared object, set up a RELATIVE dynamic relocation
106022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    helper_DynRel(rsym, *pReloc.targetRef().frag(), pReloc.targetRef().offset(),
106122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                            llvm::ELF::R_386_RELATIVE, pParent);
106222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
106322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
106422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // set up the got and dynamic relocation entries if not exist
10656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
106622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL == got_entry) {
106722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // set got entry
10686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    X86_32GNULDBackend& ld_backend = pParent.getTarget();
106922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    got_entry = ld_backend.getGOT().consume();
107022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    pParent.getSymGOTMap().record(*rsym, *got_entry);
1071d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    got_entry->setValue(0x0);
107222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // set relocation entry
107322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
107422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    rel_entry.setType(llvm::ELF::R_386_TLS_TPOFF);
107522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    rel_entry.setSymInfo(rsym);
107622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    rel_entry.targetRef().assign(*got_entry);
107722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
107822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
107922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // perform relocation to the absolute address of got_entry
1080d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address GOT_S =
108122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                 pParent.getTarget().getGOT().addr() + got_entry->getOffset();
108222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1083d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
108422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pReloc.target() = GOT_S + A;
108522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1086d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
108722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
108822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
108922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_GOTIE
10906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_gotie(Relocation& pReloc, X86_32Relocator& pParent)
109122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
109222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
1093f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (!(rsym->reserved() & X86Relocator::GOTRel)) {
1094d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao     return X86Relocator::BadReloc;
109522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
109622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
109722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // set up the got and dynamic relocation entries if not exist
10986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
109922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL == got_entry) {
110022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // set got entry
11016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    X86_32GNULDBackend& ld_backend = pParent.getTarget();
110222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    got_entry = ld_backend.getGOT().consume();
110322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    pParent.getSymGOTMap().record(*rsym, *got_entry);
1104d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    got_entry->setValue(0x0);
110522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // set relocation entry
110622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
110722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    rel_entry.setType(llvm::ELF::R_386_TLS_TPOFF);
110822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    rel_entry.setSymInfo(rsym);
110922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    rel_entry.targetRef().assign(*got_entry);
111022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
111122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
111222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // All GOT offsets are relative to the end of the GOT.
1113d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::SWord GOT_S = got_entry->getOffset() -
111422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    (pParent.getTarget().getGOTPLT().addr() - pParent.getTarget().getGOT().addr());
1115d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
111622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pReloc.target() = GOT_S + A;
111722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1118d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
111922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
112022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
112122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_X86_TLS_LE
11226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result tls_le(Relocation& pReloc, X86_32Relocator& pParent)
112322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
112422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
1125f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (pReloc.symInfo()->reserved() & X86Relocator::ReserveRel) {
112622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    helper_DynRel(rsym,
112722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                  *pReloc.targetRef().frag(),
112822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                  pReloc.targetRef().offset(),
112922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                  llvm::ELF::R_386_TLS_TPOFF,
113022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                  pParent);
1131d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return X86Relocator::OK;
113222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
113322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
113422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // perform static relocation
113522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get TLS segment
113622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ELFSegment* tls_seg = pParent.getTarget().elfSegmentTable().find(
113722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                       llvm::ELF::PT_TLS, llvm::ELF::PF_R, 0x0);
1138d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
1139d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  X86Relocator::Address S = pReloc.symValue();
114022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pReloc.target() = S + A - tls_seg->memsz();
1141d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::OK;
114222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
114322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
11446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result unsupport(Relocation& pReloc, X86_32Relocator& pParent)
114522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
1146d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return X86Relocator::Unsupport;
114722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
114822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
11496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===//
11506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// Relocation Functions and Tables
11516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===//
11526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesDECL_X86_64_APPLY_RELOC_FUNCS
11536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
11546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// the prototype of applying function
11556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinestypedef Relocator::Result (*X86_64ApplyFunctionType)(Relocation& pReloc,
11566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines						     X86_64Relocator& pParent);
11576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
11586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// the table entry of applying functions
11596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstruct X86_64ApplyFunctionTriple
11606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
11616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_64ApplyFunctionType func;
11626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned int type;
11636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const char* name;
11646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned int size;
11656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines};
11666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
11676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// declare the table of applying functions
11686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic const X86_64ApplyFunctionTriple X86_64ApplyFunctions[] = {
11696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  DECL_X86_64_APPLY_RELOC_FUNC_PTRS
11706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines};
11716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
11726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===//
11736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// X86_64Relocator
11746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===//
1175f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesX86_64Relocator::X86_64Relocator(X86_64GNULDBackend& pParent,
1176f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                 const LinkerConfig& pConfig)
1177f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  : X86Relocator(pConfig), m_Target(pParent) {
11786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
11796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
11806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocator::Result
11816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64Relocator::applyRelocation(Relocation& pRelocation)
11826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
11836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocation::Type type = pRelocation.type();
11846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
11856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (type >= sizeof (X86_64ApplyFunctions) / sizeof (X86_64ApplyFunctions[0]) ) {
11866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return Unknown;
11876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
11886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
11896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // apply the relocation
11906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86_64ApplyFunctions[type].func(pRelocation, *this);
11916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
11926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
11936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesconst char* X86_64Relocator::getName(Relocation::Type pType) const
11946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
11956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86_64ApplyFunctions[pType].name;
11966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
11976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
11986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocator::Size X86_64Relocator::getSize(Relocation::Type pType) const
11996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
12006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86_64ApplyFunctions[pType].size;
12016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
12026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1203f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86_64Relocator::scanLocalReloc(Relocation& pReloc,
1204f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                     IRBuilder& pBuilder,
1205f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                     Module& pModule,
1206f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                     LDSection& pSection)
1207f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
1208f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // rsym - The relocation target symbol
1209f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
1210f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1211f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  switch(pReloc.type()){
1212f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_64:
1213f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_32:
1214f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_16:
1215f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_8:
1216f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_32S:
1217f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // If buiding PIC object (shared library or PIC executable),
1218f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // a dynamic relocations with RELATIVE type to this location is needed.
1219f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Reserve an entry in .rela.dyn
1220f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (config().isCodeIndep()) {
1221f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().reserveEntry();
1222f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // set Rel bit
1223f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
1224f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
1225f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
1226f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
1227f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1228f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_PC32:
1229f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_PC16:
1230f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_PC8:
1231f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
1232f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1233f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_GOTPCREL:
1234f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Symbol needs GOT entry, reserve entry in .got
1235f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // return if we already create GOT for this symbol
1236f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (rsym->reserved() & (ReserveGOT | GOTRel))
1237f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
1238f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getGOT().reserve();
1239f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1240f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // If the GOT is used in statically linked binaries,
1241f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // the GOT entry is enough and no relocation is needed.
1242f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (config().isCodeStatic()) {
1243f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveGOT);
1244f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
1245f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
1246f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // If building shared object or the symbol is undefined, a dynamic
1247f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // relocation is needed to relocate this GOT entry. Reserve an
1248f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // entry in .rela.dyn
1249f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (LinkerConfig::DynObj ==
1250f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                   config().codeGenType() || rsym->isUndef() || rsym->isDyn()) {
1251f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().reserveEntry();
1252f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // set GOTRel bit
1253f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | GOTRel);
1254f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
1255f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
1256f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // set GOT bit
1257f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      rsym->setReserved(rsym->reserved() | ReserveGOT);
1258f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
1259f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1260f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    default:
1261f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      fatal(diag::unsupported_relocation) << (int)pReloc.type()
1262f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                          << "mclinker@googlegroups.com";
1263f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
1264f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  } // end switch
1265f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
1266f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1267f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86_64Relocator::scanGlobalReloc(Relocation& pReloc,
1268f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                      IRBuilder& pBuilder,
1269f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                      Module& pModule,
1270f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                      LDSection& pSection)
1271f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines{
1272f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // rsym - The relocation target symbol
1273f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
1274f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1275f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  switch(pReloc.type()) {
1276f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_64:
1277f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_32:
1278f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_16:
1279f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_8:
1280f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_32S:
1281f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Absolute relocation type, symbol may needs PLT entry or
1282f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // dynamic relocation entry
1283f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().symbolNeedsPLT(*rsym)) {
1284f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // create plt for this symbol if it does not have one
1285f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (!(rsym->reserved() & ReservePLT)){
1286f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // Symbol needs PLT entry, we need to reserve a PLT entry
1287f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // and the corresponding GOT and dynamic relocation entry
1288f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // in .got and .rela.plt. (GOT entry will be reserved simultaneously
1289f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // when calling X86PLT->reserveEntry())
1290f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().getPLT().reserveEntry();
1291f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().getGOTPLT().reserve();
1292f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().getRelPLT().reserveEntry();
1293f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // set PLT bit
1294f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          rsym->setReserved(rsym->reserved() | ReservePLT);
1295f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
1296f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
1297f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1298f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), true)) {
1299f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // symbol needs dynamic relocation entry, reserve an entry in .rela.dyn
1300f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().reserveEntry();
1301f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
1302f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, getTarget());
1303f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          addCopyReloc(*cpy_sym.resolveInfo(), getTarget());
1304f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
1305f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        else {
1306f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // set Rel bit
1307f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          rsym->setReserved(rsym->reserved() | ReserveRel);
1308f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines	        getTarget().checkAndSetHasTextRel(*pSection.getLink());
1309f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
1310f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
1311f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
1312f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1313f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_GOTPCREL:
1314f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Symbol needs GOT entry, reserve entry in .got
1315f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // return if we already create GOT for this symbol
1316f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (rsym->reserved() & (ReserveGOT | GOTRel))
1317f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
1318f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getGOT().reserve();
1319f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1320f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // If the GOT is used in statically linked binaries,
1321f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // the GOT entry is enough and no relocation is needed.
1322f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (config().isCodeStatic()) {
1323f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveGOT);
1324f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
1325f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
1326f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // If building shared object or the symbol is undefined, a dynamic
1327f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // relocation is needed to relocate this GOT entry. Reserve an
1328f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // entry in .rela.dyn
1329f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (LinkerConfig::DynObj ==
1330f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                   config().codeGenType() || rsym->isUndef() || rsym->isDyn()) {
1331f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().reserveEntry();
1332f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // set GOTRel bit
1333f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | GOTRel);
1334f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
1335f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
1336f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // set GOT bit
1337f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      rsym->setReserved(rsym->reserved() | ReserveGOT);
1338f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
1339f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1340f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_PLT32:
1341f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // A PLT entry is needed when building shared library
1342f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1343f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // return if we already create plt for this symbol
1344f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (rsym->reserved() & ReservePLT)
1345f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
1346f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1347f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // if the symbol's value can be decided at link time, then no need plt
1348f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().symbolFinalValueIsKnown(*rsym))
1349f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
1350f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1351f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // if symbol is defined in the ouput file and it's not
1352f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // preemptible, no need plt
1353f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (rsym->isDefine() && !rsym->isDyn() &&
1354f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines         !getTarget().isSymbolPreemptible(*rsym)) {
1355f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
1356f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
1357f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1358f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Symbol needs PLT entry, we need to reserve a PLT entry
1359f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // and the corresponding GOT and dynamic relocation entry
1360f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // in .got and .rel.plt. (GOT entry will be reserved simultaneously
1361f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // when calling X86PLT->reserveEntry())
1362f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getPLT().reserveEntry();
1363f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getGOTPLT().reserve();
1364f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getRelPLT().reserveEntry();
1365f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // set PLT bit
1366f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      rsym->setReserved(rsym->reserved() | ReservePLT);
1367f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
1368f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1369f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_PC32:
1370f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_PC16:
1371f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_PC8:
1372f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().symbolNeedsPLT(*rsym) &&
1373f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          LinkerConfig::DynObj != config().codeGenType()) {
1374f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // create plt for this symbol if it does not have one
1375f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (!(rsym->reserved() & ReservePLT)){
1376f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // Symbol needs PLT entry, we need to reserve a PLT entry
1377f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // and the corresponding GOT and dynamic relocation entry
1378f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // in .got and .rel.plt. (GOT entry will be reserved simultaneously
1379f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // when calling X86PLT->reserveEntry())
1380f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().getPLT().reserveEntry();
1381f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().getGOTPLT().reserve();
1382f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          getTarget().getRelPLT().reserveEntry();
1383f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // set PLT bit
1384f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          rsym->setReserved(rsym->reserved() | ReservePLT);
1385f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
1386f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
1387f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1388f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Only PC relative relocation against dynamic symbol needs a
1389f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // dynamic relocation.  Only dynamic copy relocation is allowed
1390f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // and PC relative relocation will be resolved to the local copy.
1391f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // All other dynamic relocations may lead to run-time relocation
1392f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // overflow.
1393f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().isDynamicSymbol(*rsym) &&
1394f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines	  getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), false) &&
1395f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines	  getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
1396f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().reserveEntry();
1397f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines   	LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, getTarget());
1398f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines	  addCopyReloc(*cpy_sym.resolveInfo(), getTarget());
1399f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
1400f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
1401f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1402f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    default:
1403f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      fatal(diag::unsupported_relocation) << (int)pReloc.type()
1404f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                          << "mclinker@googlegroups.com";
1405f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
1406f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  } // end switch
1407f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
1408f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1409f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===--------------------------------------------------------------------===//
1410f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// Relocation helper function
1411f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines//===--------------------------------------------------------------------===//
14126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// helper_DynRel - Get an relocation entry in .rela.dyn
14136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic
14146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesRelocation& helper_DynRel(ResolveInfo* pSym,
14156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          Fragment& pFrag,
14166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          uint64_t pOffset,
14176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          X86Relocator::Type pType,
14186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          X86_64Relocator& pParent)
14196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
14206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_64GNULDBackend& ld_backend = pParent.getTarget();
14216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
14226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  rel_entry.setType(pType);
14236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  rel_entry.targetRef().assign(pFrag, pOffset);
14246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (pType == llvm::ELF::R_X86_64_RELATIVE || NULL == pSym)
14256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    rel_entry.setSymInfo(0);
14266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else
14276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    rel_entry.setSymInfo(pSym);
14286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
14296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return rel_entry;
14306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
14316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
14326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
14336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// helper_use_relative_reloc - Check if symbol can use relocation
14346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// R_X86_64_RELATIVE
14356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic bool
14366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hineshelper_use_relative_reloc(const ResolveInfo& pSym,
14376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          const X86_64Relocator& pFactory)
14386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
14396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
14406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // if symbol is dynamic or undefine or preemptible
14416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (pSym.isDyn() ||
14426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      pSym.isUndef() ||
14436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      pFactory.getTarget().isSymbolPreemptible(pSym))
14446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return false;
14456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
14466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
14476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
14486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic
14496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64GOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
14506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines					X86_64Relocator& pParent)
14516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
14526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // rsym - The relocation target symbol
14536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
14546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_64GNULDBackend& ld_backend = pParent.getTarget();
14556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
14566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
14576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (NULL != got_entry)
14586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return *got_entry;
14596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
14606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // not found
14616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  got_entry = ld_backend.getGOT().consume();
14626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pParent.getSymGOTMap().record(*rsym, *got_entry);
14636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
14646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // If we first get this GOT entry, we should initialize it.
1465f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (rsym->reserved() & X86Relocator::ReserveGOT) {
14666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // No corresponding dynamic relocation, initialize to the symbol value.
14676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    got_entry->setValue(pReloc.symValue());
14686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
1469f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  else if (rsym->reserved() & X86Relocator::GOTRel) {
14706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // Initialize got_entry content and the corresponding dynamic relocation.
14716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (helper_use_relative_reloc(*rsym, pParent)) {
14726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      Relocation& rel_entry = helper_DynRel(rsym, *got_entry, 0x0,
14736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines					    llvm::ELF::R_X86_64_RELATIVE,
14746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines					    pParent);
14756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      rel_entry.setAddend(pReloc.symValue());
14766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
14776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
14786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_X86_64_GLOB_DAT,
14796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines		    pParent);
14806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
14816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    got_entry->setValue(0);
14826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
14836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else {
14846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    fatal(diag::reserve_entry_number_mismatch_got);
14856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
14866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return *got_entry;
14876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
14886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
14896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic
14906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_GOT_ORG(X86_64Relocator& pParent)
14916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
14926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return pParent.getTarget().getGOT().addr();
14936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
14946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
14956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic
14966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_GOT(Relocation& pReloc, X86_64Relocator& pParent)
14976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
14986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_64GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent);
14996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return got_entry.getOffset();
15006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
15016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
15026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic
15036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesPLTEntryBase& helper_get_PLT_and_init(Relocation& pReloc,
15046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines				      X86_64Relocator& pParent)
15056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
15066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // rsym - The relocation target symbol
15076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
15086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_64GNULDBackend& ld_backend = pParent.getTarget();
15096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
15106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(*rsym);
15116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (NULL != plt_entry)
15126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return *plt_entry;
15136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
15146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // not found
15156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  plt_entry = ld_backend.getPLT().consume();
15166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pParent.getSymPLTMap().record(*rsym, *plt_entry);
15176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // If we first get this PLT entry, we should initialize it.
1518f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (rsym->reserved() & X86Relocator::ReservePLT) {
15196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    X86_64GOTEntry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym);
15206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!");
15216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    gotplt_entry = ld_backend.getGOTPLT().consume();
15226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
15236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // init the corresponding rel entry in .rel.plt
15246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    Relocation& rel_entry = *ld_backend.getRelPLT().consumeEntry();
15256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    rel_entry.setType(llvm::ELF::R_X86_64_JUMP_SLOT);
15266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    rel_entry.targetRef().assign(*gotplt_entry);
15276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    rel_entry.setSymInfo(rsym);
15286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
15296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else {
15306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    fatal(diag::reserve_entry_number_mismatch_plt);
15316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
15326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
15336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return *plt_entry;
15346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
15356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
15366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic
15376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_PLT_ORG(X86_64Relocator& pParent)
15386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
15396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return pParent.getTarget().getPLT().addr();
15406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
15416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
15426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic
15436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Address helper_PLT(Relocation& pReloc, X86_64Relocator& pParent)
15446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
15456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  PLTEntryBase& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
15466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return helper_PLT_ORG(pParent) + plt_entry.getOffset();
15476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
15486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
15496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//
15506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_NONE
15516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result none(Relocation& pReloc, X86_64Relocator& pParent)
15526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
15536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86Relocator::OK;
15546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
15556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
15566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_64: S + A
15576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_32:
15586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_16:
15596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_8
15606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result abs(Relocation& pReloc, X86_64Relocator& pParent)
15616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
15626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
1563f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Relocator::DWord A = pReloc.target() + pReloc.addend();
15646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocator::DWord S = pReloc.symValue();
15656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
15666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                              *rsym,
1567f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                              (rsym->reserved() & X86Relocator::ReservePLT),
15686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                              true);
15696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1570f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  FragmentRef &target_fragref = pReloc.targetRef();
1571f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Fragment *target_frag = target_fragref.frag();
1572f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1573f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  LDSection& target_sect = target_frag->getParent()->getSection();
15746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // If the flag of target section is not ALLOC, we will not scan this relocation
15756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // but perform static relocation. (e.g., applying .debug section)
15766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
15776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    pReloc.target() = S + A;
15786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return X86Relocator::OK;
15796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
15806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1581f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // A local symbol may need RELA Type dynamic relocation
15826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (rsym->isLocal() && has_dyn_rel) {
1583f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    X86Relocator::Type pType = pReloc.type();
1584f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (llvm::ELF::R_X86_64_64 == pType)
1585f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      pType = llvm::ELF::R_X86_64_RELATIVE;
1586f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    Relocation& rel_entry = helper_DynRel(rsym, *target_frag,
1587f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        target_fragref.offset(), pType, pParent);
1588f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    rel_entry.setAddend(S + A);
15896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return X86Relocator::OK;
15906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
15916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
15926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // An external symbol may need PLT and dynamic relocation
15936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (!rsym->isLocal()) {
1594f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (rsym->reserved() & X86Relocator::ReservePLT) {
15956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      S = helper_PLT(pReloc, pParent);
15966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
1597f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // If we generate a dynamic relocation (except R_X86_64_RELATIVE)
1598f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // for a place, we should not perform static relocation on it
1599f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // in order to keep the addend store in the place correct.
1600f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (has_dyn_rel) {
1601f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (llvm::ELF::R_X86_64_64 == pReloc.type() &&
1602f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          helper_use_relative_reloc(*rsym, pParent)) {
1603f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        Relocation& rel_entry = helper_DynRel(rsym, *target_frag,
1604f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines            target_fragref.offset(), llvm::ELF::R_X86_64_RELATIVE, pParent);
1605f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rel_entry.setAddend(S + A);
1606f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
1607f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      else {
1608f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        Relocation& rel_entry = helper_DynRel(rsym, *target_frag,
1609f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines            target_fragref.offset(), pReloc.type(), pParent);
1610f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rel_entry.setAddend(A);
1611f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return X86Relocator::OK;
1612f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
1613f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
16146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
16156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
16166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // perform static relocation
16176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pReloc.target() = S + A;
16186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86Relocator::OK;
16196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
16206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
16216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_32S: S + A
16226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result signed32(Relocation& pReloc, X86_64Relocator& pParent)
16236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
16246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
1625f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Relocator::DWord A = pReloc.target() + pReloc.addend();
16266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocator::DWord S = pReloc.symValue();
16276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
16286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                              *rsym,
1629f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                              (rsym->reserved() & X86Relocator::ReservePLT),
16306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                              true);
16316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
16326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // There should be no dynamic relocations for R_X86_64_32S.
16336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (has_dyn_rel)
16346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return X86Relocator::BadReloc;
1635f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
16366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
16376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // If the flag of target section is not ALLOC, we will not scan this relocation
16386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // but perform static relocation. (e.g., applying .debug section)
16396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // An external symbol may need PLT and dynamic relocation
16406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag()) &&
1641f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      !rsym->isLocal() && rsym->reserved() & X86Relocator::ReservePLT)
16426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    S = helper_PLT(pReloc, pParent);
16436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1644f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#if notyet
16456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // Check 32-bit signed overflow.
16466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocator::SWord V = S + A;
16476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (V > INT64_C(0x7fffffff) || V < INT64_C(-0x80000000))
16486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return X86Relocator::Overflow;
1649f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#endif
16506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
16516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // perform static relocation
16526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pReloc.target() = S + A;
16536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86Relocator::OK;
16546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
16556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
16566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_GOTPCREL: GOT(S) + GOT_ORG + A - P
16576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result gotpcrel(Relocation& pReloc, X86_64Relocator& pParent)
16586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
16596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (!(pReloc.symInfo()->reserved()
1660f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines       & (X86Relocator::ReserveGOT | X86Relocator::GOTRel))) {
16616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return X86Relocator::BadReloc;
16626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
16636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86Relocator::Address GOT_S   = helper_GOT(pReloc, pParent);
1664f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Relocator::DWord      A       = pReloc.target() + pReloc.addend();
16656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
16666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // Apply relocation.
16676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pReloc.target() = GOT_S + GOT_ORG + A - pReloc.place();
16686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86Relocator::OK;
16696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
16706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
16716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PLT32: PLT(S) + A - P
16726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result plt32(Relocation& pReloc, X86_64Relocator& pParent)
16736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
16746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // PLT_S depends on if there is a PLT entry.
16756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86Relocator::Address PLT_S;
1676f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if ((pReloc.symInfo()->reserved() & X86Relocator::ReservePLT))
16776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    PLT_S = helper_PLT(pReloc, pParent);
16786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else
16796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    PLT_S = pReloc.symValue();
1680f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Relocator::DWord      A = pReloc.target() + pReloc.addend();
16816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86Relocator::Address P = pReloc.place();
16826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pReloc.target() = PLT_S + A - P;
16836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86Relocator::OK;
16846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
16856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
16866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PC32: S + A - P
16876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PC16
16886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PC8
16896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result rel(Relocation& pReloc, X86_64Relocator& pParent)
16906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
16916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
1692f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Relocator::DWord A = pReloc.target() + pReloc.addend();
16936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocator::DWord S = pReloc.symValue();
16946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocator::DWord P = pReloc.place();
16956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
16966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
16976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // If the flag of target section is not ALLOC, we will not scan this relocation
16986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // but perform static relocation. (e.g., applying .debug section)
16996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
17006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    pReloc.target() = S + A - P;
17016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return X86Relocator::OK;
17026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
17036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
17046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // An external symbol may need PLT and dynamic relocation
17056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (!rsym->isLocal()) {
1706f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (rsym->reserved() & X86Relocator::ReservePLT) {
17076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines       S = helper_PLT(pReloc, pParent);
17086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines       pReloc.target() = S + A - P;
17096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
17106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (pParent.getTarget().symbolNeedsDynRel(
17116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                              *rsym,
1712f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                              (rsym->reserved() & X86Relocator::ReservePLT),
17136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                              false)) {
17146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines          return X86Relocator::Overflow;
17156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
17166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
17176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
17186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines   // perform static relocation
17196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pReloc.target() = S + A - P;
17206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86Relocator::OK;
17216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
17226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
17236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86Relocator::Result unsupport(Relocation& pReloc, X86_64Relocator& pParent)
17246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
17256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86Relocator::Unsupport;
17266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
1727