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
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/IRBuilder.h"
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LinkerConfig.h"
1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFFileFormat.h"
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFSegmentFactory.h"
1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFSegment.h"
1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSymbol.h"
1837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Object/ObjectBuilder.h"
1937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h"
205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/Twine.h>
225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/DataTypes.h>
235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ELF.h>
245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
2887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// X86_32 Relocation helper function
2987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===--------------------------------------------------------------------===//
3087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/// helper_DynRel - Get an relocation entry in .rel.dyn
3137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic Relocation& helper_DynRel_init(ResolveInfo* pSym,
3237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      Fragment& pFrag,
3337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      uint64_t pOffset,
3437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      Relocator::Type pType,
3537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      X86_32Relocator& pParent) {
3687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  X86_32GNULDBackend& ld_backend = pParent.getTarget();
3787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation& rel_entry = *ld_backend.getRelDyn().create();
3887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  rel_entry.setType(pType);
3987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  rel_entry.targetRef().assign(pFrag, pOffset);
4037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (pType == llvm::ELF::R_386_RELATIVE || pSym == NULL)
4187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    rel_entry.setSymInfo(NULL);
4287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else
4387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    rel_entry.setSymInfo(pSym);
4487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
4587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return rel_entry;
4687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
4787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
4887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/// helper_use_relative_reloc - Check if symbol ceuse relocation
4987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/// R_386_RELATIVE
5037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic bool helper_use_relative_reloc(const ResolveInfo& pSym,
5137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      const X86_32Relocator& pFactory) {
5287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // if symbol is dynamic or undefine or preemptible
5337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (pSym.isDyn() || pSym.isUndef() ||
5487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pFactory.getTarget().isSymbolPreemptible(pSym))
5587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return false;
5687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return true;
5787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
5887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
5937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic X86_32GOTEntry& helper_GOT_init(Relocation& pReloc,
6037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                       bool pHasRel,
6137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                       X86_32Relocator& pParent) {
6287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // rsym - The relocation target symbol
6387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.symInfo();
6487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  X86_32GNULDBackend& ld_backend = pParent.getTarget();
6537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(pParent.getSymGOTMap().lookUp(*rsym) == NULL);
6687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
6787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  X86_32GOTEntry* got_entry = ld_backend.getGOT().create();
6887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pParent.getSymGOTMap().record(*rsym, *got_entry);
6987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
7087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!pHasRel) {
7187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // No corresponding dynamic relocation, initialize to the symbol value.
7287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    got_entry->setValue(X86Relocator::SymVal);
7337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
7487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Initialize got_entry content and the corresponding dynamic relocation.
7587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (helper_use_relative_reloc(*rsym, pParent)) {
7637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      helper_DynRel_init(
7737b74a387bb3993387029859c2d9d051c41c724eStephen Hines          rsym, *got_entry, 0x0, llvm::ELF::R_386_RELATIVE, pParent);
7887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      got_entry->setValue(X86Relocator::SymVal);
7937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else {
8037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      helper_DynRel_init(
8137b74a387bb3993387029859c2d9d051c41c724eStephen Hines          rsym, *got_entry, 0x0, llvm::ELF::R_386_GLOB_DAT, pParent);
8287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      got_entry->setValue(0x0);
8387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
8487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
8587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *got_entry;
8687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
8787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
8837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic Relocator::Address helper_GOT_ORG(X86_32Relocator& pParent) {
8987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return pParent.getTarget().getGOTPLT().addr();
9087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
9187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
9237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic Relocator::Address helper_get_GOT_address(Relocation& pReloc,
9337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                 X86_32Relocator& pParent) {
9487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo());
9537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(got_entry != NULL);
9687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return pParent.getTarget().getGOT().addr() + got_entry->getOffset();
9787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
9887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
9937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic PLTEntryBase& helper_PLT_init(Relocation& pReloc,
10037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                     X86_32Relocator& pParent) {
10187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // rsym - The relocation target symbol
10287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.symInfo();
10387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  X86_32GNULDBackend& ld_backend = pParent.getTarget();
10437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(pParent.getSymPLTMap().lookUp(*rsym) == NULL);
10587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
10687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  PLTEntryBase* plt_entry = ld_backend.getPLT().create();
10787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pParent.getSymPLTMap().record(*rsym, *plt_entry);
10887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
10987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // initialize plt and the corresponding gotplt and dyn rel entry.
11037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(pParent.getSymGOTPLTMap().lookUp(*rsym) == NULL &&
11187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines         "PLT entry not exist, but GOTPLT entry exist!");
11287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  X86_32GOTEntry* gotplt_entry = ld_backend.getGOTPLT().create();
11387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
11487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
11587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // init the corresponding rel entry in .rel.plt
11687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation& rel_entry = *ld_backend.getRelPLT().create();
11787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  rel_entry.setType(llvm::ELF::R_386_JUMP_SLOT);
11887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  rel_entry.targetRef().assign(*gotplt_entry);
11987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  rel_entry.setSymInfo(rsym);
12087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *plt_entry;
12187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
12287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
12337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic Relocator::Address helper_get_PLT_address(ResolveInfo& pSym,
12437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                 X86_32Relocator& pParent) {
12587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(pSym);
12637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(plt_entry != NULL);
12787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return pParent.getTarget().getPLT().addr() + plt_entry->getOffset();
12887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
12987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
13087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===--------------------------------------------------------------------===//
13187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// X86_32 Relocation Functions and Tables
13267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
1336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesDECL_X86_32_APPLY_RELOC_FUNCS
1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
13567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao/// the prototype of applying function
1366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinestypedef Relocator::Result (*X86_32ApplyFunctionType)(Relocation& pReloc,
137551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                     X86_32Relocator& pParent);
13867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
13967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// the table entry of applying functions
14037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstruct X86_32ApplyFunctionTriple {
1416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32ApplyFunctionType func;
14267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  unsigned int type;
14367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  const char* name;
1446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned int size;
14567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao};
14667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
14767e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao// declare the table of applying functions
1486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic const X86_32ApplyFunctionTriple X86_32ApplyFunctions[] = {
14937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    DECL_X86_32_APPLY_RELOC_FUNC_PTRS};
15067e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao
1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===--------------------------------------------------------------------===//
152d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao// X86Relocator
15367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao//===--------------------------------------------------------------------===//
15437b74a387bb3993387029859c2d9d051c41c724eStephen HinesX86Relocator::X86Relocator(const LinkerConfig& pConfig) : Relocator(pConfig) {
1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
15737b74a387bb3993387029859c2d9d051c41c724eStephen HinesX86Relocator::~X86Relocator() {
1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
160f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86Relocator::scanRelocation(Relocation& pReloc,
161f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                  IRBuilder& pLinker,
162f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                  Module& pModule,
16387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                  LDSection& pSection,
16437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                  Input& pInput) {
165f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (LinkerConfig::Object == config().codeGenType())
166f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return;
167f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // rsym - The relocation target symbol
168f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
16937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(rsym != NULL &&
170f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines         "ResolveInfo of relocation not set while scanRelocation");
171f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
17237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(pSection.getLink() != NULL);
17337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if ((pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC) == 0)
174f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return;
175f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
176f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // Scan relocation type to determine if the GOT/PLT/Dynamic Relocation
177f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // entries should be created.
17837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (rsym->isLocal())  // rsym is local
179f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    scanLocalReloc(pReloc, pLinker, pModule, pSection);
18037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  else  // rsym is external
181f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    scanGlobalReloc(pReloc, pLinker, pModule, pSection);
182f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
183f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // check if we should issue undefined reference for the relocation target
184f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // symbol
185f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
18687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    issueUndefRef(pReloc, pSection, pInput);
187f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
188f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
18937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86Relocator::addCopyReloc(ResolveInfo& pSym, X86GNULDBackend& pTarget) {
19087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation& rel_entry = *pTarget.getRelDyn().create();
191f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  rel_entry.setType(pTarget.getCopyRelType());
192f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(pSym.outSymbol()->hasFragRef());
193f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
194f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  rel_entry.setSymInfo(&pSym);
195f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
196f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
197f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// defineSymbolforCopyReloc
198f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// For a symbol needing copy relocation, define a copy symbol in the BSS
199f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// section and all other reference to this symbol should refer to this
200f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// copy.
201f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// @note This is executed at `scan relocation' stage.
202f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesLDSymbol& X86Relocator::defineSymbolforCopyReloc(IRBuilder& pBuilder,
203f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                                 const ResolveInfo& pSym,
20437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                 X86GNULDBackend& pTarget) {
205f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // get or create corresponding BSS LDSection
206f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  LDSection* bss_sect_hdr = NULL;
207f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ELFFileFormat* file_format = pTarget.getOutputFormat();
208f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (ResolveInfo::ThreadLocal == pSym.type())
209f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    bss_sect_hdr = &file_format->getTBSS();
210f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  else
211f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    bss_sect_hdr = &file_format->getBSS();
212f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
213f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // get or create corresponding BSS SectionData
21437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(bss_sect_hdr != NULL);
215f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  SectionData* bss_section = NULL;
216f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (bss_sect_hdr->hasSectionData())
217f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    bss_section = bss_sect_hdr->getSectionData();
218f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  else
219f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    bss_section = IRBuilder::CreateSectionData(*bss_sect_hdr);
220f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
221f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // Determine the alignment by the symbol value
222f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // FIXME: here we use the largest alignment
223f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  uint32_t addralign = config().targets().bitclass() / 8;
224f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
225f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // allocate space in BSS for the copy symbol
226f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Fragment* frag = new FillFragment(0x0, 1, pSym.size());
22737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint64_t size = ObjectBuilder::AppendFragment(*frag, *bss_section, addralign);
228f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  bss_sect_hdr->setSize(bss_sect_hdr->size() + size);
229f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
230f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // change symbol binding to Global if it's a weak symbol
231f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding();
232f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (binding == ResolveInfo::Weak)
233f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    binding = ResolveInfo::Global;
234f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
235f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // Define the copy symbol in the bss section and resolve it
236f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  LDSymbol* cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
23737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pSym.name(),
23837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      (ResolveInfo::Type)pSym.type(),
23937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      ResolveInfo::Define,
24037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      binding,
24137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pSym.size(),  // size
24237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0x0,          // value
24337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      FragmentRef::Create(*frag, 0x0),
24437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      (ResolveInfo::Visibility)pSym.other());
245f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
246f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // output all other alias symbols if any
24737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Module& pModule = pBuilder.getModule();
248f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Module::AliasList* alias_list = pModule.getAliasList(pSym);
24937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (alias_list != NULL) {
25037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    Module::alias_iterator it, it_e = alias_list->end();
25137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    for (it = alias_list->begin(); it != it_e; ++it) {
252f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      const ResolveInfo* alias = *it;
25337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (alias != &pSym && alias->isDyn()) {
254f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
25537b74a387bb3993387029859c2d9d051c41c724eStephen Hines            alias->name(),
25637b74a387bb3993387029859c2d9d051c41c724eStephen Hines            (ResolveInfo::Type)alias->type(),
25737b74a387bb3993387029859c2d9d051c41c724eStephen Hines            ResolveInfo::Define,
25837b74a387bb3993387029859c2d9d051c41c724eStephen Hines            binding,
25937b74a387bb3993387029859c2d9d051c41c724eStephen Hines            alias->size(),  // size
26037b74a387bb3993387029859c2d9d051c41c724eStephen Hines            0x0,            // value
26137b74a387bb3993387029859c2d9d051c41c724eStephen Hines            FragmentRef::Create(*frag, 0x0),
26237b74a387bb3993387029859c2d9d051c41c724eStephen Hines            (ResolveInfo::Visibility)alias->other());
263f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
264f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
265f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
266f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
267f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return *cpy_sym;
268f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
269f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
27037b74a387bb3993387029859c2d9d051c41c724eStephen Hines//===----------------------------------------------------------------------===//
2716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// X86_32Relocator
27237b74a387bb3993387029859c2d9d051c41c724eStephen Hines//===----------------------------------------------------------------------===//
273f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesX86_32Relocator::X86_32Relocator(X86_32GNULDBackend& pParent,
274f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                 const LinkerConfig& pConfig)
27537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : X86Relocator(pConfig), m_Target(pParent) {
2766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
2776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
27837b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result X86_32Relocator::applyRelocation(Relocation& pRelocation) {
2795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  Relocation::Type type = pRelocation.type();
2805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
28137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (type >= sizeof(X86_32ApplyFunctions) / sizeof(X86_32ApplyFunctions[0])) {
28267e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao    return Unknown;
2835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // apply the relocation
2866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86_32ApplyFunctions[type].func(pRelocation, *this);
2875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
28937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst char* X86_32Relocator::getName(Relocation::Type pType) const {
2906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86_32ApplyFunctions[pType].name;
2916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
2926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
29337b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Size X86_32Relocator::getSize(Relocation::Type pType) const {
29437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  return X86_32ApplyFunctions[pType].size;
29567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao}
2965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
29737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool X86_32Relocator::mayHaveFunctionPointerAccess(
29837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    const Relocation& pReloc) const {
2990dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  switch (pReloc.type()) {
3000dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    case llvm::ELF::R_386_32:
3010dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    case llvm::ELF::R_386_16:
3020dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    case llvm::ELF::R_386_8:
3030dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    case llvm::ELF::R_386_GOTOFF:
3040dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    case llvm::ELF::R_386_GOT32: {
3050dea6bc96bb52346737966839ac68644f7939f58Stephen Hines      return true;
3060dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    }
30737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    default: { return false; }
3080dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  }
3090dea6bc96bb52346737966839ac68644f7939f58Stephen Hines}
3100dea6bc96bb52346737966839ac68644f7939f58Stephen Hines
311f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86_32Relocator::scanLocalReloc(Relocation& pReloc,
31287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                     IRBuilder& pBuilder,
31387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                     Module& pModule,
31437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                     LDSection& pSection) {
315f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // rsym - The relocation target symbol
316f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
317f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
31837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  switch (pReloc.type()) {
319f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_32:
32087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // If buiding PIC object (shared library or PIC executable),
32187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // a dynamic relocations with RELATIVE type to this location is needed.
32287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Reserve an entry in .rel.dyn
32387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (config().isCodeIndep()) {
32487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // set Rel bit
32587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
32687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
32787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // set up the dyn rel directly
32887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        helper_DynRel_init(rsym,
32987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                           *pReloc.targetRef().frag(),
33087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                           pReloc.targetRef().offset(),
33187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                           llvm::ELF::R_386_RELATIVE,
33287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                           *this);
33387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
33487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return;
33587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
336f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_16:
337f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_8:
338f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // If buiding PIC object (shared library or PIC executable),
339f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // a dynamic relocations with RELATIVE type to this location is needed.
340f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Reserve an entry in .rel.dyn
341f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (config().isCodeIndep()) {
34287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // set up the dyn rel directly
34337b74a387bb3993387029859c2d9d051c41c724eStephen Hines        helper_DynRel_init(rsym,
34437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                           *pReloc.targetRef().frag(),
34537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                           pReloc.targetRef().offset(),
34637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                           pReloc.type(),
34737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                           *this);
348f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // set Rel bit
349f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
350f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
351f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
352f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
353f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
354f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_PLT32:
355f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
356f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
357f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_GOTOFF:
358f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_GOTPC:
359f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // FIXME: A GOT section is needed
360f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
361f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
362f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_GOT32:
363f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Symbol needs GOT entry, reserve entry in .got
364f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // return if we already create GOT for this symbol
36587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (rsym->reserved() & ReserveGOT)
366f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
36787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
368f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // FIXME: check STT_GNU_IFUNC symbol
369f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
37037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      // If building PIC object, a dynamic relocation with
37137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      // type RELATIVE is needed to relocate this GOT entry.
37237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (config().isCodeIndep())
37387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        helper_GOT_init(pReloc, true, *this);
37437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      else
37537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        helper_GOT_init(pReloc, false, *this);
37687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
37737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      // set GOT bit
378f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      rsym->setReserved(rsym->reserved() | ReserveGOT);
379f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
380f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
381f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_PC32:
382f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_PC16:
383f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_PC8:
384f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
385f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
386f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_GD: {
387f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // FIXME: no linker optimization for TLS relocation
38887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (rsym->reserved() & ReserveGOT)
389f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
39087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
391f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // define the section symbol for .tdata or .tbss
392f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // the target symbol of the created dynamic relocation should be the
393f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // section symbol of the section which this symbol defined. so we
394f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // need to define that section symbol here
395f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      ELFFileFormat* file_format = getTarget().getOutputFormat();
396f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      const LDSection* sym_sect =
39737b74a387bb3993387029859c2d9d051c41c724eStephen Hines          &rsym->outSymbol()->fragRef()->frag()->getParent()->getSection();
39887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      LDSymbol* sect_sym = NULL;
399f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (&file_format->getTData() == sym_sect) {
40087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        if (!getTarget().hasTDATASymbol()) {
40187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          sect_sym = pModule.getSectionSymbolSet().get(*sym_sect);
40287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          getTarget().setTDATASymbol(*sect_sym);
40387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
40437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      } else if (&file_format->getTBSS() == sym_sect || rsym->isCommon()) {
40587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        if (!getTarget().hasTBSSSymbol()) {
40687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          sect_sym = pModule.getSectionSymbolSet().get(*sym_sect);
40787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          getTarget().setTBSSSymbol(*sect_sym);
40887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
40937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      } else {
410f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        error(diag::invalid_tls) << rsym->name() << sym_sect->name();
41137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      }
41287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
41387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // set up a pair of got entries and a dyn rel
41487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // set GOT bit
41587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      rsym->setReserved(rsym->reserved() | ReserveGOT);
41687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      X86_32GOTEntry* got_entry1 = getTarget().getGOT().create();
41787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      X86_32GOTEntry* got_entry2 = getTarget().getGOT().create();
41887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      getSymGOTMap().record(*rsym, *got_entry1, *got_entry2);
41987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // set up value of got entries, the value of got_entry2 should be the
42087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // symbol value, which has to be set during apply relocation
42187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      got_entry1->setValue(0x0);
42287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
42387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // setup dyn rel for got_entry1
42437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      Relocation& rel_entry1 = helper_DynRel_init(
42537b74a387bb3993387029859c2d9d051c41c724eStephen Hines          rsym, *got_entry1, 0x0, llvm::ELF::R_386_TLS_DTPMOD32, *this);
42687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // for local tls symbol, add rel entry against the section symbol this
42787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // symbol belong to (.tdata or .tbss)
42887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      rel_entry1.setSymInfo(sect_sym->resolveInfo());
429f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
430f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
431f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_LDM:
432f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTLSModuleID();
433f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
434f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
435f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_LDO_32:
436f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
437f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
43887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case llvm::ELF::R_386_TLS_IE: {
439f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().setHasStaticTLS();
44087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
44187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // if building shared object, a RELATIVE dynamic relocation is needed
442f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (LinkerConfig::DynObj == config().codeGenType()) {
44337b74a387bb3993387029859c2d9d051c41c724eStephen Hines        helper_DynRel_init(rsym,
44437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                           *pReloc.targetRef().frag(),
44537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                           pReloc.targetRef().offset(),
44637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                           llvm::ELF::R_386_RELATIVE,
44737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                           *this);
448f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
449f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
45037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      } else {
451f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // for local sym, we can convert ie to le if not building shared object
452f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        convertTLSIEtoLE(pReloc, pSection);
453f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
454f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
45587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
45687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (rsym->reserved() & ReserveGOT)
457f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
45887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
45987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // set up the got and the corresponding rel entry
46087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      X86_32GOTEntry* got_entry = getTarget().getGOT().create();
46187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      getSymGOTMap().record(*rsym, *got_entry);
46287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      got_entry->setValue(0x0);
46337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      helper_DynRel_init(
46437b74a387bb3993387029859c2d9d051c41c724eStephen Hines          rsym, *got_entry, 0x0, llvm::ELF::R_386_TLS_TPOFF, *this);
46587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // set GOT bit
46687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      rsym->setReserved(rsym->reserved() | ReserveGOT);
46787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // add symbol to dyn sym table
468f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
469f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
47087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
471f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
47287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case llvm::ELF::R_386_TLS_GOTIE: {
473f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().setHasStaticTLS();
47487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (rsym->reserved() & ReserveGOT)
475f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
47687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // set up the got and the corresponding dyn rel
47787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      X86_32GOTEntry* got_entry = getTarget().getGOT().create();
47887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      getSymGOTMap().record(*rsym, *got_entry);
47987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      got_entry->setValue(0x0);
48037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      helper_DynRel_init(
48137b74a387bb3993387029859c2d9d051c41c724eStephen Hines          rsym, *got_entry, 0x0, llvm::ELF::R_386_TLS_TPOFF, *this);
48287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // set GOT bit
48387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      rsym->setReserved(rsym->reserved() | ReserveGOT);
484f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
485f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
48687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
487f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
488f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_LE:
489f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_LE_32:
490f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().setHasStaticTLS();
491f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // if buildint shared object, a dynamic relocation is needed
492f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (LinkerConfig::DynObj == config().codeGenType()) {
49387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        helper_DynRel_init(rsym,
49487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                           *pReloc.targetRef().frag(),
49587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                           pReloc.targetRef().offset(),
49687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                           llvm::ELF::R_386_TLS_TPOFF,
49787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                           *this);
498f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
499f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
500f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // the target symbol of the dynamic relocation is rsym, so we need to
501f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // emit it into .dynsym
50237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        assert(rsym->outSymbol() != NULL);
503f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
504f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
505f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
506f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
507f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    default:
50837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      fatal(diag::unsupported_relocation) << static_cast<int>(pReloc.type())
509f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                          << "mclinker@googlegroups.com";
510f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
51137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }  // end switch
512f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
513f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
514f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86_32Relocator::scanGlobalReloc(Relocation& pReloc,
51587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      IRBuilder& pBuilder,
51687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      Module& pModule,
51737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      LDSection& pSection) {
518f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // rsym - The relocation target symbol
519f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
520f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
52137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  switch (pReloc.type()) {
522f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_32:
523f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_16:
524f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_8:
525f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Absolute relocation type, symbol may needs PLT entry or
526f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // dynamic relocation entry
527f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().symbolNeedsPLT(*rsym)) {
528f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // create plt for this symbol if it does not have one
52937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        if (!(rsym->reserved() & ReservePLT)) {
53087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // Symbol needs PLT entry, we need a PLT entry
531f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // and the corresponding GOT and dynamic relocation entry
53287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // in .got and .rel.plt.
53387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          helper_PLT_init(pReloc, *this);
534f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // set PLT bit
535f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          rsym->setReserved(rsym->reserved() | ReservePLT);
536f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
537f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
538f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
53937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (getTarget()
54037b74a387bb3993387029859c2d9d051c41c724eStephen Hines              .symbolNeedsDynRel(
54137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                  *rsym, (rsym->reserved() & ReservePLT), true)) {
54287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // symbol needs dynamic relocation entry, set up the dynrel entry
543f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
54437b74a387bb3993387029859c2d9d051c41c724eStephen Hines          LDSymbol& cpy_sym =
54537b74a387bb3993387029859c2d9d051c41c724eStephen Hines              defineSymbolforCopyReloc(pBuilder, *rsym, getTarget());
546f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          addCopyReloc(*cpy_sym.resolveInfo(), getTarget());
54737b74a387bb3993387029859c2d9d051c41c724eStephen Hines        } else {
54887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // set Rel bit and the dyn rel
549f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          rsym->setReserved(rsym->reserved() | ReserveRel);
55087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          getTarget().checkAndSetHasTextRel(*pSection.getLink());
55187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          if (llvm::ELF::R_386_32 == pReloc.type() &&
55237b74a387bb3993387029859c2d9d051c41c724eStephen Hines              helper_use_relative_reloc(*rsym, *this)) {
55387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            helper_DynRel_init(rsym,
55487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                               *pReloc.targetRef().frag(),
55587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                               pReloc.targetRef().offset(),
55687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                               llvm::ELF::R_386_RELATIVE,
55787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                               *this);
55837b74a387bb3993387029859c2d9d051c41c724eStephen Hines          } else {
55987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            helper_DynRel_init(rsym,
56087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                               *pReloc.targetRef().frag(),
56187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                               pReloc.targetRef().offset(),
56287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                               pReloc.type(),
56387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                               *this);
56437b74a387bb3993387029859c2d9d051c41c724eStephen Hines          }
565f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
566f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
567f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
568f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
569f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_GOTOFF:
570f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_GOTPC: {
571f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // FIXME: A GOT section is needed
572f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
573f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
574f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
575f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_PLT32:
576f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // A PLT entry is needed when building shared library
577f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
578f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // return if we already create plt for this symbol
579f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (rsym->reserved() & ReservePLT)
580f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
581f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
582f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // if the symbol's value can be decided at link time, then no need plt
583f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().symbolFinalValueIsKnown(*rsym))
584f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
585f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
586f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // if symbol is defined in the ouput file and it's not
587f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // preemptible, no need plt
588f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (rsym->isDefine() && !rsym->isDyn() &&
58987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          !getTarget().isSymbolPreemptible(*rsym))
590f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
591f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
59287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Symbol needs PLT entry, we need a PLT entry
593f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // and the corresponding GOT and dynamic relocation entry
59487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // in .got and .rel.plt
59587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      helper_PLT_init(pReloc, *this);
596f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // set PLT bit
597f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      rsym->setReserved(rsym->reserved() | ReservePLT);
598f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
599f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
600f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_GOT32:
601f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Symbol needs GOT entry, reserve entry in .got
602f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // return if we already create GOT for this symbol
60387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (rsym->reserved() & ReserveGOT)
604f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
60537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      // if the symbol cannot be fully resolved at link time, then we need a
60637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      // dynamic relocation
60737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (!getTarget().symbolFinalValueIsKnown(*rsym))
60887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        helper_GOT_init(pReloc, true, *this);
60987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      else
61087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        helper_GOT_init(pReloc, false, *this);
611f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // set GOT bit
612f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      rsym->setReserved(rsym->reserved() | ReserveGOT);
613f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
614f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
615f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_PC32:
616f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_PC16:
617f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_PC8:
618f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
619f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().symbolNeedsPLT(*rsym) &&
620f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          LinkerConfig::DynObj != config().codeGenType()) {
621f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // create plt for this symbol if it does not have one
62237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        if (!(rsym->reserved() & ReservePLT)) {
62387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // Symbol needs PLT entry, we need a PLT entry
624f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // and the corresponding GOT and dynamic relocation entry
62587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // in .got and .rel.plt.
626f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // set PLT bit
62787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          helper_PLT_init(pReloc, *this);
628f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          rsym->setReserved(rsym->reserved() | ReservePLT);
629f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
630f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
631f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
63237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (getTarget()
63337b74a387bb3993387029859c2d9d051c41c724eStephen Hines              .symbolNeedsDynRel(
63437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                  *rsym, (rsym->reserved() & ReservePLT), false)) {
63587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // symbol needs dynamic relocation entry, setup an entry in .rel.dyn
636f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
63737b74a387bb3993387029859c2d9d051c41c724eStephen Hines          LDSymbol& cpy_sym =
63837b74a387bb3993387029859c2d9d051c41c724eStephen Hines              defineSymbolforCopyReloc(pBuilder, *rsym, getTarget());
639f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          addCopyReloc(*cpy_sym.resolveInfo(), getTarget());
64037b74a387bb3993387029859c2d9d051c41c724eStephen Hines        } else {
64187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // set Rel bit and the dyn rel
642f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          rsym->setReserved(rsym->reserved() | ReserveRel);
64387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          getTarget().checkAndSetHasTextRel(*pSection.getLink());
64487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          if (llvm::ELF::R_386_32 == pReloc.type() &&
64537b74a387bb3993387029859c2d9d051c41c724eStephen Hines              helper_use_relative_reloc(*rsym, *this)) {
64687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            helper_DynRel_init(rsym,
64787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                               *pReloc.targetRef().frag(),
64887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                               pReloc.targetRef().offset(),
64987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                               llvm::ELF::R_386_RELATIVE,
65087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                               *this);
65137b74a387bb3993387029859c2d9d051c41c724eStephen Hines          } else {
65287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            helper_DynRel_init(rsym,
65387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                               *pReloc.targetRef().frag(),
65487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                               pReloc.targetRef().offset(),
65587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                               pReloc.type(),
65687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                               *this);
65737b74a387bb3993387029859c2d9d051c41c724eStephen Hines          }
658f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
659f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
660f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
661f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
662f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_GD: {
663f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // FIXME: no linker optimization for TLS relocation
66487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (rsym->reserved() & ReserveGOT)
665f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
66687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
66787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // set up a pair of got entries and a pair of dyn rel
66887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      X86_32GOTEntry* got_entry1 = getTarget().getGOT().create();
66987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      X86_32GOTEntry* got_entry2 = getTarget().getGOT().create();
67087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      getSymGOTMap().record(*rsym, *got_entry1, *got_entry2);
67187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      got_entry1->setValue(0x0);
67287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      got_entry2->setValue(0x0);
67387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // setup dyn rel for got entries against rsym
67437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      helper_DynRel_init(
67537b74a387bb3993387029859c2d9d051c41c724eStephen Hines          rsym, *got_entry1, 0x0, llvm::ELF::R_386_TLS_DTPMOD32, *this);
67637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      helper_DynRel_init(
67737b74a387bb3993387029859c2d9d051c41c724eStephen Hines          rsym, *got_entry2, 0x0, llvm::ELF::R_386_TLS_DTPOFF32, *this);
67887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
67987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // add the rsym to dynamic symbol table
680f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
68187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // set GOT bit
68287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      rsym->setReserved(rsym->reserved() | ReserveGOT);
683f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
684f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
685f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
686f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_LDM:
687f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTLSModuleID();
688f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
689f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
690f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_LDO_32:
691f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
692f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
69387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case llvm::ELF::R_386_TLS_IE: {
694f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().setHasStaticTLS();
695f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // if buildint shared object, a RELATIVE dynamic relocation is needed
696f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (LinkerConfig::DynObj == config().codeGenType()) {
69737b74a387bb3993387029859c2d9d051c41c724eStephen Hines        helper_DynRel_init(rsym,
69837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                           *pReloc.targetRef().frag(),
69937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                           pReloc.targetRef().offset(),
70037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                           llvm::ELF::R_386_RELATIVE,
70137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                           *this);
702f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
703f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
704f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      } else {
705f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // for global sym, we can convert ie to le if its final value is known
706f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (getTarget().symbolFinalValueIsKnown(*rsym)) {
707f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          convertTLSIEtoLE(pReloc, pSection);
708f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          return;
709f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
710f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
71187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (rsym->reserved() & ReserveGOT)
712f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
71387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // set up the got and the corresponding rel entry
71487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      X86_32GOTEntry* got_entry = getTarget().getGOT().create();
71587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      getSymGOTMap().record(*rsym, *got_entry);
71687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      got_entry->setValue(0x0);
71737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      helper_DynRel_init(
71837b74a387bb3993387029859c2d9d051c41c724eStephen Hines          rsym, *got_entry, 0x0, llvm::ELF::R_386_TLS_TPOFF, *this);
71987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // set GOT bit
72087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      rsym->setReserved(rsym->reserved() | ReserveGOT);
721f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
72287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
723f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
72487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case llvm::ELF::R_386_TLS_GOTIE: {
725f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().setHasStaticTLS();
72687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (rsym->reserved() & ReserveGOT)
727f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
72887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // set up the got and the corresponding dyn rel
72987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      X86_32GOTEntry* got_entry = getTarget().getGOT().create();
73087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      getSymGOTMap().record(*rsym, *got_entry);
73187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      got_entry->setValue(0x0);
73237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      helper_DynRel_init(
73337b74a387bb3993387029859c2d9d051c41c724eStephen Hines          rsym, *got_entry, 0x0, llvm::ELF::R_386_TLS_TPOFF, *this);
734f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
73587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // set GOT bit
73687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      rsym->setReserved(rsym->reserved() | ReserveGOT);
737f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
73887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
739f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
740f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_LE:
741f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_386_TLS_LE_32:
742f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      getTarget().setHasStaticTLS();
743f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // if buildint shared object, a dynamic relocation is needed
744f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (LinkerConfig::DynObj == config().codeGenType()) {
74587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        helper_DynRel_init(rsym,
74687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                           *pReloc.targetRef().frag(),
74787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                           pReloc.targetRef().offset(),
74887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                           llvm::ELF::R_386_TLS_TPOFF,
74987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                           *this);
750f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
751f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
752f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
753f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
754f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
755f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
756f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    default: {
75737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      fatal(diag::unsupported_relocation) << static_cast<int>(pReloc.type())
758f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                          << "mclinker@googlegroups.com";
759f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
760f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
76137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }  // end switch
762f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
763f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
764f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines// Create a GOT entry for the TLS module index
76537b74a387bb3993387029859c2d9d051c41c724eStephen HinesX86_32GOTEntry& X86_32Relocator::getTLSModuleID() {
766f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  static X86_32GOTEntry* got_entry = NULL;
76737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (got_entry != NULL)
768f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return *got_entry;
769f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
770f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // Allocate 2 got entries and 1 dynamic reloc for R_386_TLS_LDM
77187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  got_entry = getTarget().getGOT().create();
77287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  getTarget().getGOT().create()->setValue(0x0);
773f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
77437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  helper_DynRel_init(
77537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      NULL, *got_entry, 0x0, llvm::ELF::R_386_TLS_DTPMOD32, *this);
776f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  return *got_entry;
777f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
778f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
779f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines/// convert R_386_TLS_IE to R_386_TLS_LE
780f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86_32Relocator::convertTLSIEtoLE(Relocation& pReloc,
78137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                       LDSection& pSection) {
782f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  assert(pReloc.type() == llvm::ELF::R_386_TLS_IE);
78337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(pReloc.targetRef().frag() != NULL);
784f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
785551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  // 1. create the new relocs
786551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocation* reloc =
78737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      Relocation::Create(X86_32Relocator::R_386_TLS_OPT,
78837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                         *FragmentRef::Create(*pReloc.targetRef().frag(),
78937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                              pReloc.targetRef().offset() - 1),
79037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                         0x0);
79187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // FIXME: should we create a special symbol for the tls opt instead?
79287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  reloc->setSymInfo(pReloc.symInfo());
793f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
794f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // 2. modify the opcodes to the appropriate ones
79537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint8_t* op = (reinterpret_cast<uint8_t*>(&reloc->target()));
796551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  if (op[0] == 0xa1) {
797551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    op[0] = 0xb8;
798f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  } else {
799551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    // create the new reloc (move 1 byte forward).
80037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    reloc = Relocation::Create(
80137b74a387bb3993387029859c2d9d051c41c724eStephen Hines        X86_32Relocator::R_386_TLS_OPT,
80237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        *FragmentRef::Create(*pReloc.targetRef().frag(),
80337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                             pReloc.targetRef().offset() - 2),
80437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        0x0);
805551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    reloc->setSymInfo(pReloc.symInfo());
806551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    op = (reinterpret_cast<uint8_t*>(&reloc->target()));
807551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    switch (op[0]) {
808f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      case 0x8b:
809551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        assert((op[1] & 0xc7) == 0x05);
810551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        op[0] = 0xc7;
811551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        op[1] = 0xc0 | ((op[1] >> 3) & 7);
812f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        break;
813f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      case 0x03:
814551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        assert((op[1] & 0xc7) == 0x05);
815551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        op[0] = 0x81;
816551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        op[1] = 0xc0 | ((op[1] >> 3) & 7);
817f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        break;
818f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      default:
819f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        assert(0);
820f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        break;
821f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
822f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
823f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
824f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // 3. insert the new relocs "BEFORE" the original reloc.
825551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  assert(reloc != NULL);
826f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pSection.getRelocData()->getRelocationList().insert(
82737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      RelocData::iterator(pReloc), reloc);
828f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
829f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // 4. change the type of the original reloc
830f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  pReloc.setType(llvm::ELF::R_386_TLS_LE);
831f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
832f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
83337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesuint32_t X86_32Relocator::getDebugStringOffset(Relocation& pReloc) const {
83437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (pReloc.type() != llvm::ELF::R_386_32)
83537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    error(diag::unsupport_reloc_for_debug_string)
83637b74a387bb3993387029859c2d9d051c41c724eStephen Hines        << getName(pReloc.type()) << "mclinker@googlegroups.com";
83737b74a387bb3993387029859c2d9d051c41c724eStephen Hines
83837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (pReloc.symInfo()->type() == ResolveInfo::Section)
83937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    return pReloc.target();
84037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  else
84137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    return pReloc.symInfo()->outSymbol()->fragRef()->offset() +
84237b74a387bb3993387029859c2d9d051c41c724eStephen Hines               pReloc.target() + pReloc.addend();
84337b74a387bb3993387029859c2d9d051c41c724eStephen Hines}
84437b74a387bb3993387029859c2d9d051c41c724eStephen Hines
84537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86_32Relocator::applyDebugStringOffset(Relocation& pReloc,
84637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                             uint32_t pOffset) {
84737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  pReloc.target() = pOffset;
84837b74a387bb3993387029859c2d9d051c41c724eStephen Hines}
84937b74a387bb3993387029859c2d9d051c41c724eStephen Hines
85087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//================================================//
85187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// X86_32 Each relocation function implementation //
85287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//================================================//
8535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_NONE
85537b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result none(Relocation& pReloc, X86_32Relocator& pParent) {
856551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
8575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
8585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_32: S + A
86022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_16
86122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_8
86237b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result abs(Relocation& pReloc, X86_32Relocator& pParent) {
8635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
864d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
865d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord S = pReloc.symValue();
86667e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
86737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      *rsym, (rsym->reserved() & X86Relocator::ReservePLT), true);
86887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
86987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
87037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  // If the flag of target section is not ALLOC, we will not scan this
87137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  // relocation but perform static relocation. (e.g., applying .debug section)
87237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if ((llvm::ELF::SHF_ALLOC & target_sect.flag()) == 0x0) {
873affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = S + A;
874551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
875affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
876affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
877affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // An external symbol may need PLT and dynamic relocation
878affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!rsym->isLocal()) {
879f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (rsym->reserved() & X86Relocator::ReservePLT) {
88087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      S = helper_get_PLT_address(*rsym, pParent);
8815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
882affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // If we generate a dynamic relocation (except R_386_RELATIVE)
883affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // for a place, we should not perform static relocation on it
884affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // in order to keep the addend store in the place correct.
88587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (has_dyn_rel)
88687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (llvm::ELF::R_386_32 != pReloc.type() ||
88787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          (!helper_use_relative_reloc(*rsym, pParent)))
888551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        return Relocator::OK;
8895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
8905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // perform static relocation
8925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = S + A;
893551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
8945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
8955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_PC32: S + A - P
89722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_PC16
89822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_PC8
89937b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result rel(Relocation& pReloc, X86_32Relocator& pParent) {
900affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ResolveInfo* rsym = pReloc.symInfo();
901d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
902d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord S = pReloc.symValue();
903d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord P = pReloc.place();
90487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
90537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      *rsym, (rsym->reserved() & X86Relocator::ReservePLT), true);
906affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
90722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
90837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  // If the flag of target section is not ALLOC, we will not scan this
90937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  // relocation
910affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // but perform static relocation. (e.g., applying .debug section)
91137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if ((llvm::ELF::SHF_ALLOC & target_sect.flag()) == 0x0) {
912affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pReloc.target() = S + A - P;
913551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
914affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
915affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
916affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // An external symbol may need PLT and dynamic relocation
917affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!rsym->isLocal()) {
918f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (rsym->reserved() & X86Relocator::ReservePLT) {
91987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      S = helper_get_PLT_address(*rsym, pParent);
92087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pReloc.target() = S + A - P;
921affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
92287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (has_dyn_rel)
92387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (!helper_use_relative_reloc(*rsym, pParent))
924551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        return Relocator::OK;
925affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
926affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
92737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  // perform static relocation
928affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  pReloc.target() = S + A - P;
929551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
9305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
9315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOTOFF: S + A - GOT_ORG
93337b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result gotoff32(Relocation& pReloc, X86_32Relocator& pParent) {
93437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocator::DWord A = pReloc.target() + pReloc.addend();
935551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
936551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
9375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = S + A - GOT_ORG;
939551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
9405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
9415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOTPC: GOT_ORG + A - P
94337b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result gotpc32(Relocation& pReloc, X86_32Relocator& pParent) {
94437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocator::DWord A = pReloc.target() + pReloc.addend();
945551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
9465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Apply relocation.
94722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pReloc.target() = GOT_ORG + A - pReloc.place();
948551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
9495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
9505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_GOT32: GOT(S) + A - GOT_ORG
95237b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result got32(Relocation& pReloc, X86_32Relocator& pParent) {
95387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.symInfo();
95487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!(rsym->reserved() & (X86Relocator::ReserveGOT)))
955551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::BadReloc;
95687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
95787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // set up got entry value if the got has no dyn rel or
95887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // the dyn rel is RELATIVE
95987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo());
96037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(got_entry != NULL);
96187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (got_entry->getValue() == X86Relocator::SymVal)
96287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    got_entry->setValue(pReloc.symValue());
96387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
96437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocator::Address GOT_S = helper_get_GOT_address(pReloc, pParent);
96537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocator::DWord A = pReloc.target() + pReloc.addend();
966551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
9675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Apply relocation.
9685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = GOT_S + A - GOT_ORG;
969551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
9705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
9715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
9725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// R_386_PLT32: PLT(S) + A - P
97337b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result plt32(Relocation& pReloc, X86_32Relocator& pParent) {
9745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // PLT_S depends on if there is a PLT entry.
975551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address PLT_S;
976f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if ((pReloc.symInfo()->reserved() & X86Relocator::ReservePLT))
97787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    PLT_S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
9785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  else
9795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    PLT_S = pReloc.symValue();
98037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocator::DWord A = pReloc.target() + pReloc.addend();
981551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address P = pReloc.place();
9825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  pReloc.target() = PLT_S + A - P;
983551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
9845460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
98522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
98622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_GD:
98737b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result tls_gd(Relocation& pReloc, X86_32Relocator& pParent) {
98822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // global-dynamic
98922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
99022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // must reserve two pairs of got and dynamic relocation
99187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!(rsym->reserved() & X86Relocator::ReserveGOT))
992551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::BadReloc;
99322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
99422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ELFFileFormat* file_format = pParent.getTarget().getOutputFormat();
99522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // setup corresponding got and dynamic relocatio entries:
99622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get first got entry, if there is already a got entry for rsym, then apply
99722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // this relocation to the got entry directly. If not, setup the corresponding
99822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // got and dyn relocation entries
99987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  X86_32GOTEntry* got_entry1 = pParent.getSymGOTMap().lookUpFirstEntry(*rsym);
100022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
100187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // set the got_entry2 value to symbol value
100287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (rsym->isLocal())
100337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    pParent.getSymGOTMap().lookUpSecondEntry(*rsym)->setValue(
100437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        pReloc.symValue());
100522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
100622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // perform relocation to the first got entry
1007d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
100822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // GOT_OFF - the offset between the got_entry1 and _GLOBAL_OFFSET_TABLE (the
100922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // .got.plt section)
101037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocator::Address GOT_OFF = file_format->getGOT().addr() +
101137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                               got_entry1->getOffset() -
101237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                               file_format->getGOTPLT().addr();
101322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pReloc.target() = GOT_OFF + A;
1014551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
101522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
101622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
101722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_LDM
101837b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result tls_ldm(Relocation& pReloc, X86_32Relocator& pParent) {
101922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // FIXME: no linker optimization for TLS relocation
1020f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  const X86_32GOTEntry& got_entry = pParent.getTLSModuleID();
102122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
102222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // All GOT offsets are relative to the end of the GOT.
102337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  X86Relocator::SWord GOT_S =
102437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      got_entry.getOffset() - (pParent.getTarget().getGOTPLT().addr() -
102537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                               pParent.getTarget().getGOT().addr());
1026d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
102722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pReloc.target() = GOT_S + A;
102822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1029551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
103022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
103122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
103222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_LDO_32
103337b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result tls_ldo_32(Relocation& pReloc, X86_32Relocator& pParent) {
103422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // FIXME: no linker optimization for TLS relocation
1035d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
1036551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
103722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pReloc.target() = S + A;
1038551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
103922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
104022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
104122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_X86_TLS_IE
104237b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result tls_ie(Relocation& pReloc, X86_32Relocator& pParent) {
104322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
104487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!(rsym->reserved() & X86Relocator::ReserveGOT)) {
104537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    return Relocator::BadReloc;
104622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
104722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
104822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // set up the got and dynamic relocation entries if not exist
10496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
105037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(got_entry != NULL);
105122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // perform relocation to the absolute address of got_entry
1052551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address GOT_S =
105337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pParent.getTarget().getGOT().addr() + got_entry->getOffset();
105422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1055d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
105622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pReloc.target() = GOT_S + A;
105722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1058551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
105922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
106022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
106122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_386_TLS_GOTIE
106237b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result tls_gotie(Relocation& pReloc, X86_32Relocator& pParent) {
106322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ResolveInfo* rsym = pReloc.symInfo();
106487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!(rsym->reserved() & X86Relocator::ReserveGOT)) {
106537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    return Relocator::BadReloc;
106622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
106722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
106822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // set up the got and dynamic relocation entries if not exist
10696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
107037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(got_entry != NULL);
107122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
107222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // All GOT offsets are relative to the end of the GOT.
107337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  X86Relocator::SWord GOT_S =
107437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      got_entry->getOffset() - (pParent.getTarget().getGOTPLT().addr() -
107537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                pParent.getTarget().getGOT().addr());
1076d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
107722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pReloc.target() = GOT_S + A;
107822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1079551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
108022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
108122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
108222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// R_X86_TLS_LE
108337b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result tls_le(Relocation& pReloc, X86_32Relocator& pParent) {
108487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pReloc.symInfo()->reserved() & X86Relocator::ReserveRel)
1085551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
108622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
108722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // perform static relocation
108822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get TLS segment
108987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ELFSegmentFactory::const_iterator tls_seg =
109037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pParent.getTarget().elfSegmentTable().find(
109137b74a387bb3993387029859c2d9d051c41c724eStephen Hines          llvm::ELF::PT_TLS, llvm::ELF::PF_R, 0x0);
109287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(tls_seg != pParent.getTarget().elfSegmentTable().end());
1093d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  Relocator::DWord A = pReloc.target() + pReloc.addend();
1094551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address S = pReloc.symValue();
109587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pReloc.target() = S + A - (*tls_seg)->memsz();
1096551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
109722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
109822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
109937b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result unsupported(Relocation& pReloc, X86_32Relocator& pParent) {
110037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  return Relocator::Unsupported;
110122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
110222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
11036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===//
110487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// X86_64 Relocation helper function
110587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===--------------------------------------------------------------------===//
110687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/// helper_DynRel - Get an relocation entry in .rela.dyn
110737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic Relocation& helper_DynRel_init(ResolveInfo* pSym,
110837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      Fragment& pFrag,
110937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      uint64_t pOffset,
111037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      Relocator::Type pType,
111137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      X86_64Relocator& pParent) {
111287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  X86_64GNULDBackend& ld_backend = pParent.getTarget();
111387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation& rel_entry = *ld_backend.getRelDyn().create();
111487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  rel_entry.setType(pType);
111587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  rel_entry.targetRef().assign(pFrag, pOffset);
111637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (pType == llvm::ELF::R_X86_64_RELATIVE || pSym == NULL)
111787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    rel_entry.setSymInfo(NULL);
111887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  else
111987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    rel_entry.setSymInfo(pSym);
112087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
112187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return rel_entry;
112287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
112387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
112487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/// helper_use_relative_reloc - Check if symbol can use relocation
112587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/// R_X86_64_RELATIVE
112637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic bool helper_use_relative_reloc(const ResolveInfo& pSym,
112737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      const X86_64Relocator& pFactory) {
112887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // if symbol is dynamic or undefine or preemptible
112937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (pSym.isDyn() || pSym.isUndef() ||
113087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pFactory.getTarget().isSymbolPreemptible(pSym))
113187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return false;
113287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return true;
113387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
113487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
113537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic X86_64GOTEntry& helper_GOT_init(Relocation& pReloc,
113637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                       bool pHasRel,
113737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                       X86_64Relocator& pParent) {
113887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // rsym - The relocation target symbol
113987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.symInfo();
114087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  X86_64GNULDBackend& ld_backend = pParent.getTarget();
114137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(pParent.getSymGOTMap().lookUp(*rsym) == NULL);
114287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
114387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  X86_64GOTEntry* got_entry = ld_backend.getGOT().create();
114487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pParent.getSymGOTMap().record(*rsym, *got_entry);
114587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
114687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // If we first get this GOT entry, we should initialize it.
114787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!pHasRel) {
114887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // No corresponding dynamic relocation, initialize to the symbol value.
114987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    got_entry->setValue(X86Relocator::SymVal);
115037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
115187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Initialize got_entry content and the corresponding dynamic relocation.
115287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (helper_use_relative_reloc(*rsym, pParent)) {
115337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      Relocation& rel_entry = helper_DynRel_init(
115437b74a387bb3993387029859c2d9d051c41c724eStephen Hines          rsym, *got_entry, 0x0, llvm::ELF::R_X86_64_RELATIVE, pParent);
115537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      rel_entry.setAddend(X86Relocator::SymVal);
115637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pParent.getRelRelMap().record(pReloc, rel_entry);
115737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else {
115837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      helper_DynRel_init(
115937b74a387bb3993387029859c2d9d051c41c724eStephen Hines          rsym, *got_entry, 0x0, llvm::ELF::R_X86_64_GLOB_DAT, pParent);
116087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
116187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    got_entry->setValue(0);
116287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
116387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *got_entry;
116487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
116587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
116637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic Relocator::Address helper_GOT_ORG(X86_64Relocator& pParent) {
116787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return pParent.getTarget().getGOT().addr();
116887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
116987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
117037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic Relocator::Address helper_get_GOT_address(Relocation& pReloc,
117137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                 X86_64Relocator& pParent) {
117287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  X86_64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo());
117337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(got_entry != NULL);
117487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return got_entry->getOffset();
117587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
117687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
117737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic Relocator::Address helper_get_PLT_address(ResolveInfo& pSym,
117837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                 X86_64Relocator& pParent) {
117987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(pSym);
118037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(plt_entry != NULL);
118187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return pParent.getTarget().getPLT().addr() + plt_entry->getOffset();
118287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
118387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
118437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic PLTEntryBase& helper_PLT_init(Relocation& pReloc,
118537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                     X86_64Relocator& pParent) {
118687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // rsym - The relocation target symbol
118787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ResolveInfo* rsym = pReloc.symInfo();
118887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  X86_64GNULDBackend& ld_backend = pParent.getTarget();
118937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(pParent.getSymPLTMap().lookUp(*rsym) == NULL);
119087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
119187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  PLTEntryBase* plt_entry = ld_backend.getPLT().create();
119287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pParent.getSymPLTMap().record(*rsym, *plt_entry);
119387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
119487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // initialize plt and the corresponding gotplt and dyn rel entry.
119537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(pParent.getSymGOTPLTMap().lookUp(*rsym) == NULL &&
119687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines         "PLT entry not exist, but DynRel entry exist!");
119787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  X86_64GOTEntry* gotplt_entry = ld_backend.getGOTPLT().create();
119887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
119987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
120087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // init the corresponding rel entry in .rel.plt
120187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation& rel_entry = *ld_backend.getRelPLT().create();
120287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  rel_entry.setType(llvm::ELF::R_X86_64_JUMP_SLOT);
120387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  rel_entry.targetRef().assign(*gotplt_entry);
120487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  rel_entry.setSymInfo(rsym);
120587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *plt_entry;
120687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
120787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
120837b74a387bb3993387029859c2d9d051c41c724eStephen Hines//===----------------------------------------------------------------------===//
120987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// X86_64 Relocation Functions and Tables
121037b74a387bb3993387029859c2d9d051c41c724eStephen Hines//===----------------------------------------------------------------------===//
12116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesDECL_X86_64_APPLY_RELOC_FUNCS
12126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
12136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// the prototype of applying function
12146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinestypedef Relocator::Result (*X86_64ApplyFunctionType)(Relocation& pReloc,
1215551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines                                                     X86_64Relocator& pParent);
12166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
12176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// the table entry of applying functions
121837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstruct X86_64ApplyFunctionTriple {
12196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  X86_64ApplyFunctionType func;
12206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned int type;
12216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const char* name;
12226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  unsigned int size;
12236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines};
12246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
12256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// declare the table of applying functions
12266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic const X86_64ApplyFunctionTriple X86_64ApplyFunctions[] = {
122737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    DECL_X86_64_APPLY_RELOC_FUNC_PTRS};
12286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
12296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===//
12306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// X86_64Relocator
12316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===--------------------------------------------------------------------===//
1232f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen HinesX86_64Relocator::X86_64Relocator(X86_64GNULDBackend& pParent,
1233f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                 const LinkerConfig& pConfig)
123437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : X86Relocator(pConfig), m_Target(pParent) {
12356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
12366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
123737b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result X86_64Relocator::applyRelocation(Relocation& pRelocation) {
12386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocation::Type type = pRelocation.type();
12396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
124037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (type >= sizeof(X86_64ApplyFunctions) / sizeof(X86_64ApplyFunctions[0])) {
12416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return Unknown;
12426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
12436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
12446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // apply the relocation
12456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86_64ApplyFunctions[type].func(pRelocation, *this);
12466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
12476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
124837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst char* X86_64Relocator::getName(Relocation::Type pType) const {
12496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86_64ApplyFunctions[pType].name;
12506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
12516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
125237b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Size X86_64Relocator::getSize(Relocation::Type pType) const {
12536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return X86_64ApplyFunctions[pType].size;
12546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
12556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
125637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool X86_64Relocator::mayHaveFunctionPointerAccess(
125737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    const Relocation& pReloc) const {
12580dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  bool possible_funcptr_reloc = false;
12590dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  switch (pReloc.type()) {
12600dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    case llvm::ELF::R_X86_64_64:
12610dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    case llvm::ELF::R_X86_64_32:
12620dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    case llvm::ELF::R_X86_64_32S:
12630dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    case llvm::ELF::R_X86_64_16:
12640dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    case llvm::ELF::R_X86_64_8:
12650dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    case llvm::ELF::R_X86_64_GOT64:
12660dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    case llvm::ELF::R_X86_64_GOT32:
12670dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    case llvm::ELF::R_X86_64_GOTPCREL64:
12680dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    case llvm::ELF::R_X86_64_GOTPCREL:
12690dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    case llvm::ELF::R_X86_64_GOTPLT64: {
12700dea6bc96bb52346737966839ac68644f7939f58Stephen Hines      possible_funcptr_reloc = true;
12710dea6bc96bb52346737966839ac68644f7939f58Stephen Hines      break;
12720dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    }
12730dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    default: {
12740dea6bc96bb52346737966839ac68644f7939f58Stephen Hines      possible_funcptr_reloc = false;
12750dea6bc96bb52346737966839ac68644f7939f58Stephen Hines      break;
12760dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    }
12770dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  }
12780dea6bc96bb52346737966839ac68644f7939f58Stephen Hines
127937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (pReloc.symInfo()->isGlobal()) {
12800dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    return (config().codeGenType() == LinkerConfig::DynObj) &&
12810dea6bc96bb52346737966839ac68644f7939f58Stephen Hines           ((pReloc.symInfo()->visibility() != ResolveInfo::Default) ||
12820dea6bc96bb52346737966839ac68644f7939f58Stephen Hines            possible_funcptr_reloc);
128337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
12840dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    return (config().codeGenType() == LinkerConfig::DynObj) ||
12850dea6bc96bb52346737966839ac68644f7939f58Stephen Hines           possible_funcptr_reloc;
128637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }
12870dea6bc96bb52346737966839ac68644f7939f58Stephen Hines}
12880dea6bc96bb52346737966839ac68644f7939f58Stephen Hines
1289f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86_64Relocator::scanLocalReloc(Relocation& pReloc,
1290f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                     IRBuilder& pBuilder,
1291f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                     Module& pModule,
129237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                     LDSection& pSection) {
1293f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // rsym - The relocation target symbol
1294f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
1295f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
129637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  switch (pReloc.type()) {
1297f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_64:
129887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // If buiding PIC object (shared library or PIC executable),
129987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // a dynamic relocations with RELATIVE type to this location is needed.
130087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Reserve an entry in .rela.dyn
130187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (config().isCodeIndep()) {
130287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        Relocation& reloc = helper_DynRel_init(rsym,
130387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                               *pReloc.targetRef().frag(),
130487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                               pReloc.targetRef().offset(),
130587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                               llvm::ELF::R_X86_64_RELATIVE,
130687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                               *this);
130787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        getRelRelMap().record(pReloc, reloc);
130887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // set Rel bit
130987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
131087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
131187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
131287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return;
131387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1314f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_32:
1315f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_16:
1316f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_8:
1317f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_32S:
1318f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // If buiding PIC object (shared library or PIC executable),
1319f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // a dynamic relocations with RELATIVE type to this location is needed.
1320f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Reserve an entry in .rela.dyn
1321f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (config().isCodeIndep()) {
132287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        Relocation& reloc = helper_DynRel_init(rsym,
132387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                               *pReloc.targetRef().frag(),
132487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                               pReloc.targetRef().offset(),
132587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                               pReloc.type(),
132687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                               *this);
132787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        getRelRelMap().record(pReloc, reloc);
1328f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // set Rel bit
1329f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        rsym->setReserved(rsym->reserved() | ReserveRel);
1330f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        getTarget().checkAndSetHasTextRel(*pSection.getLink());
1331f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
1332f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
1333f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1334f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_PC32:
1335f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_PC16:
1336f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_PC8:
1337f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
1338f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1339f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_GOTPCREL:
1340f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Symbol needs GOT entry, reserve entry in .got
1341f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // return if we already create GOT for this symbol
134287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (rsym->reserved() & ReserveGOT)
1343f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
1344f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
134537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      // If building PIC object, a dynamic relocation with
134637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      // type RELATIVE is needed to relocate this GOT entry.
134737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (config().isCodeIndep())
134887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        helper_GOT_init(pReloc, true, *this);
134987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      else
135087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        helper_GOT_init(pReloc, false, *this);
1351f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      rsym->setReserved(rsym->reserved() | ReserveGOT);
1352f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
1353f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1354f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    default:
135537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      fatal(diag::unsupported_relocation) << static_cast<int>(pReloc.type())
1356f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                          << "mclinker@googlegroups.com";
1357f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
135837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }  // end switch
1359f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
1360f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1361f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesvoid X86_64Relocator::scanGlobalReloc(Relocation& pReloc,
1362f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                      IRBuilder& pBuilder,
1363f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                      Module& pModule,
136437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      LDSection& pSection) {
1365f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // rsym - The relocation target symbol
1366f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
1367f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
136837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  switch (pReloc.type()) {
1369f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_64:
1370f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_32:
1371f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_16:
1372f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_8:
1373f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_32S:
1374f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Absolute relocation type, symbol may needs PLT entry or
1375f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // dynamic relocation entry
1376f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().symbolNeedsPLT(*rsym)) {
1377f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // create plt for this symbol if it does not have one
137837b74a387bb3993387029859c2d9d051c41c724eStephen Hines        if (!(rsym->reserved() & ReservePLT)) {
1379f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // Symbol needs PLT entry, we need to reserve a PLT entry
1380f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // and the corresponding GOT and dynamic relocation entry
138187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // in .got and .rela.plt.
138287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          helper_PLT_init(pReloc, *this);
1383f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // set PLT bit
1384f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          rsym->setReserved(rsym->reserved() | ReservePLT);
1385f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
1386f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
1387f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
138837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (getTarget()
138937b74a387bb3993387029859c2d9d051c41c724eStephen Hines              .symbolNeedsDynRel(
139037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                  *rsym, (rsym->reserved() & ReservePLT), true)) {
139187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // symbol needs dynamic relocation entry, set up the dynrel entry
1392f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
139337b74a387bb3993387029859c2d9d051c41c724eStephen Hines          LDSymbol& cpy_sym =
139437b74a387bb3993387029859c2d9d051c41c724eStephen Hines              defineSymbolforCopyReloc(pBuilder, *rsym, getTarget());
1395f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          addCopyReloc(*cpy_sym.resolveInfo(), getTarget());
139637b74a387bb3993387029859c2d9d051c41c724eStephen Hines        } else {
139787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // set Rel bit and the dyn rel
1398f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          rsym->setReserved(rsym->reserved() | ReserveRel);
139987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          getTarget().checkAndSetHasTextRel(*pSection.getLink());
140087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          if (llvm::ELF::R_386_32 == pReloc.type() &&
140187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines              helper_use_relative_reloc(*rsym, *this)) {
140287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            Relocation& reloc = helper_DynRel_init(rsym,
140387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                                   *pReloc.targetRef().frag(),
140487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                                   pReloc.targetRef().offset(),
140587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                                   llvm::ELF::R_X86_64_RELATIVE,
140687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                                   *this);
140787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            getRelRelMap().record(pReloc, reloc);
140837b74a387bb3993387029859c2d9d051c41c724eStephen Hines          } else {
140987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            Relocation& reloc = helper_DynRel_init(rsym,
141087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                                   *pReloc.targetRef().frag(),
141187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                                   pReloc.targetRef().offset(),
141287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                                   pReloc.type(),
141387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                                   *this);
141487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            getRelRelMap().record(pReloc, reloc);
141587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          }
1416551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines          getTarget().checkAndSetHasTextRel(*pSection.getLink());
1417f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
1418f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
1419f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
1420f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1421f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_GOTPCREL:
1422f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Symbol needs GOT entry, reserve entry in .got
1423f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // return if we already create GOT for this symbol
142487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (rsym->reserved() & ReserveGOT)
1425f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
1426f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
142737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      // if the symbol cannot be fully resolved at link time, then we need a
142837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      // dynamic relocation
142937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (!getTarget().symbolFinalValueIsKnown(*rsym))
143087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        helper_GOT_init(pReloc, true, *this);
143187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      else
143287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        helper_GOT_init(pReloc, false, *this);
1433f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // set GOT bit
1434f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      rsym->setReserved(rsym->reserved() | ReserveGOT);
1435f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
1436f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1437f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_PLT32:
1438f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // A PLT entry is needed when building shared library
1439f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1440f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // return if we already create plt for this symbol
1441f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (rsym->reserved() & ReservePLT)
1442f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
1443f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1444f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // if the symbol's value can be decided at link time, then no need plt
1445f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().symbolFinalValueIsKnown(*rsym))
1446f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
1447f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1448f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // if symbol is defined in the ouput file and it's not
1449f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // preemptible, no need plt
1450f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (rsym->isDefine() && !rsym->isDyn() &&
145137b74a387bb3993387029859c2d9d051c41c724eStephen Hines          !getTarget().isSymbolPreemptible(*rsym)) {
1452f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        return;
1453f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
1454f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
145587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Symbol needs PLT entry, we need a PLT entry
1456f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // and the corresponding GOT and dynamic relocation entry
145787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // in .got and .rel.plt.
145887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      helper_PLT_init(pReloc, *this);
1459f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // set PLT bit
1460f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      rsym->setReserved(rsym->reserved() | ReservePLT);
1461f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
1462f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1463f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_PC32:
1464f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_PC16:
1465f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    case llvm::ELF::R_X86_64_PC8:
1466f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().symbolNeedsPLT(*rsym) &&
1467f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          LinkerConfig::DynObj != config().codeGenType()) {
1468f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        // create plt for this symbol if it does not have one
146937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        if (!(rsym->reserved() & ReservePLT)) {
147087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // Symbol needs PLT entry, we need a PLT entry
1471f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // and the corresponding GOT and dynamic relocation entry
147287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // in .got and .rel.plt.
147387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          helper_PLT_init(pReloc, *this);
1474f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          // set PLT bit
1475f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          rsym->setReserved(rsym->reserved() | ReservePLT);
1476f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        }
1477f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
1478f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1479f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // Only PC relative relocation against dynamic symbol needs a
1480f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // dynamic relocation.  Only dynamic copy relocation is allowed
1481f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // and PC relative relocation will be resolved to the local copy.
1482f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // All other dynamic relocations may lead to run-time relocation
1483f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      // overflow.
1484f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (getTarget().isDynamicSymbol(*rsym) &&
148537b74a387bb3993387029859c2d9d051c41c724eStephen Hines          getTarget()
148637b74a387bb3993387029859c2d9d051c41c724eStephen Hines              .symbolNeedsDynRel(
148737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                  *rsym, (rsym->reserved() & ReservePLT), false) &&
148837b74a387bb3993387029859c2d9d051c41c724eStephen Hines          getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
148937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        LDSymbol& cpy_sym =
149037b74a387bb3993387029859c2d9d051c41c724eStephen Hines            defineSymbolforCopyReloc(pBuilder, *rsym, getTarget());
1491551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        addCopyReloc(*cpy_sym.resolveInfo(), getTarget());
1492f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
1493f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      return;
1494f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1495f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    default:
149637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      fatal(diag::unsupported_relocation) << static_cast<int>(pReloc.type())
1497f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                                          << "mclinker@googlegroups.com";
1498f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      break;
149937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }  // end switch
1500f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
1501f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
150237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesuint32_t X86_64Relocator::getDebugStringOffset(Relocation& pReloc) const {
150337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (pReloc.type() != llvm::ELF::R_X86_64_32)
150437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    error(diag::unsupport_reloc_for_debug_string)
150537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        << getName(pReloc.type()) << "mclinker@googlegroups.com";
150637b74a387bb3993387029859c2d9d051c41c724eStephen Hines
150737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (pReloc.symInfo()->type() == ResolveInfo::Section)
150837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    return pReloc.target();
150937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  else
151037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    return pReloc.symInfo()->outSymbol()->fragRef()->offset() +
151137b74a387bb3993387029859c2d9d051c41c724eStephen Hines               pReloc.target() + pReloc.addend();
151237b74a387bb3993387029859c2d9d051c41c724eStephen Hines}
151337b74a387bb3993387029859c2d9d051c41c724eStephen Hines
151437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid X86_64Relocator::applyDebugStringOffset(Relocation& pReloc,
151537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                             uint32_t pOffset) {
151637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  pReloc.target() = pOffset;
151737b74a387bb3993387029859c2d9d051c41c724eStephen Hines}
151837b74a387bb3993387029859c2d9d051c41c724eStephen Hines
151937b74a387bb3993387029859c2d9d051c41c724eStephen Hines//------------------------------------------------//
152037b74a387bb3993387029859c2d9d051c41c724eStephen Hines// X86_64 Each relocation function implementation //
152137b74a387bb3993387029859c2d9d051c41c724eStephen Hines//------------------------------------------------//
15226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_NONE
152337b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result none(Relocation& pReloc, X86_64Relocator& pParent) {
1524551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
15256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
15266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
15276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_64: S + A
15286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_32:
15296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_16:
15306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_8
153137b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result abs(Relocation& pReloc, X86_64Relocator& pParent) {
15326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
1533f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Relocator::DWord A = pReloc.target() + pReloc.addend();
15346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocator::DWord S = pReloc.symValue();
153587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation* dyn_rel = pParent.getRelRelMap().lookUp(pReloc);
153637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  bool has_dyn_rel = (dyn_rel != NULL);
1537f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
153887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
153937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  // If the flag of target section is not ALLOC, we will not scan this
154037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  // relocation but perform static relocation. (e.g., applying .debug section)
154137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if ((llvm::ELF::SHF_ALLOC & target_sect.flag()) == 0x0) {
15426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    pReloc.target() = S + A;
1543551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
15446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
15456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1546f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // A local symbol may need RELA Type dynamic relocation
15476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (rsym->isLocal() && has_dyn_rel) {
154887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    dyn_rel->setAddend(S + A);
1549551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
15506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
15516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
15526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // An external symbol may need PLT and dynamic relocation
15536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (!rsym->isLocal()) {
1554f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (rsym->reserved() & X86Relocator::ReservePLT) {
155587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      S = helper_get_PLT_address(*rsym, pParent);
15566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
1557f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // If we generate a dynamic relocation (except R_X86_64_RELATIVE)
1558f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // for a place, we should not perform static relocation on it
1559f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // in order to keep the addend store in the place correct.
1560f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (has_dyn_rel) {
1561f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (llvm::ELF::R_X86_64_64 == pReloc.type() &&
1562f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          helper_use_relative_reloc(*rsym, pParent)) {
156387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        dyn_rel->setAddend(S + A);
156437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      } else {
156587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        dyn_rel->setAddend(A);
1566551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        return Relocator::OK;
1567f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
1568f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
15696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
15706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
15716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // perform static relocation
15726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pReloc.target() = S + A;
1573551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
15746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
15756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
15766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_32S: S + A
157737b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result signed32(Relocation& pReloc, X86_64Relocator& pParent) {
15786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
1579f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Relocator::DWord A = pReloc.target() + pReloc.addend();
15806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocator::DWord S = pReloc.symValue();
15816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
15826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // There should be no dynamic relocations for R_X86_64_32S.
158337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (pParent.getRelRelMap().lookUp(pReloc) != NULL)
1584551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::BadReloc;
1585f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
15866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
158737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  // If the flag of target section is not ALLOC, we will not scan this
158837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  // relocation but perform static relocation. (e.g., applying .debug section)
15896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // An external symbol may need PLT and dynamic relocation
159037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if ((llvm::ELF::SHF_ALLOC & target_sect.flag()) != 0x0 && !rsym->isLocal() &&
159137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      rsym->reserved() & X86Relocator::ReservePLT)
159287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    S = helper_get_PLT_address(*rsym, pParent);
15936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1594f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#if notyet
15956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // Check 32-bit signed overflow.
15966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocator::SWord V = S + A;
15976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (V > INT64_C(0x7fffffff) || V < INT64_C(-0x80000000))
1598551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::Overflow;
1599f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines#endif
16006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
16016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // perform static relocation
16026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pReloc.target() = S + A;
1603551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
16046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
16056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
16066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_GOTPCREL: GOT(S) + GOT_ORG + A - P
160737b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result gotpcrel(Relocation& pReloc, X86_64Relocator& pParent) {
160887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!(pReloc.symInfo()->reserved() & X86Relocator::ReserveGOT)) {
1609551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::BadReloc;
16106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
161187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
161287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // set symbol value of the got entry if needed
161387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  X86_64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo());
161487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (X86Relocator::SymVal == got_entry->getValue())
161587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    got_entry->setValue(pReloc.symValue());
161687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
161787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // setup relocation addend if needed
161887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation* dyn_rel = pParent.getRelRelMap().lookUp(pReloc);
161937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if ((dyn_rel != NULL) && (X86Relocator::SymVal == dyn_rel->addend())) {
162087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    dyn_rel->setAddend(pReloc.symValue());
162187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
162287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
162337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocator::Address GOT_S = helper_get_GOT_address(pReloc, pParent);
162437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocator::DWord A = pReloc.target() + pReloc.addend();
1625551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
16266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // Apply relocation.
16276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pReloc.target() = GOT_S + GOT_ORG + A - pReloc.place();
1628551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
16296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
16306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
16316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PLT32: PLT(S) + A - P
163237b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result plt32(Relocation& pReloc, X86_64Relocator& pParent) {
16336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // PLT_S depends on if there is a PLT entry.
1634551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address PLT_S;
1635f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if ((pReloc.symInfo()->reserved() & X86Relocator::ReservePLT))
163687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    PLT_S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
16376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else
16386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    PLT_S = pReloc.symValue();
163937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Relocator::DWord A = pReloc.target() + pReloc.addend();
1640551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  Relocator::Address P = pReloc.place();
16416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pReloc.target() = PLT_S + A - P;
1642551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
16436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
16446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
16456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PC32: S + A - P
16466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PC16
16476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// R_X86_64_PC8
164837b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result rel(Relocation& pReloc, X86_64Relocator& pParent) {
16496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ResolveInfo* rsym = pReloc.symInfo();
1650f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Relocator::DWord A = pReloc.target() + pReloc.addend();
16516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocator::DWord S = pReloc.symValue();
16526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Relocator::DWord P = pReloc.place();
16536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
16546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
165537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  // If the flag of target section is not ALLOC, we will not scan this
165637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  // relocation but perform static relocation. (e.g., applying .debug section)
165737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if ((llvm::ELF::SHF_ALLOC & target_sect.flag()) == 0x0) {
16586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    pReloc.target() = S + A - P;
1659551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines    return Relocator::OK;
16606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
16616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
166287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // setup relocation addend if needed
166387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Relocation* dyn_rel = pParent.getRelRelMap().lookUp(pReloc);
166437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if ((dyn_rel != NULL) && (X86Relocator::SymVal == dyn_rel->addend())) {
166587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    dyn_rel->setAddend(S);
166687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
166787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
16686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // An external symbol may need PLT and dynamic relocation
16696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (!rsym->isLocal()) {
1670f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if (rsym->reserved() & X86Relocator::ReservePLT) {
167137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      S = helper_get_PLT_address(*rsym, pParent);
16726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
167337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (pParent.getTarget()
167437b74a387bb3993387029859c2d9d051c41c724eStephen Hines            .symbolNeedsDynRel(
167537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                *rsym, (rsym->reserved() & X86Relocator::ReservePLT), false)) {
1676551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      return Relocator::Overflow;
16776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
16786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
16796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
168037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  // perform static relocation
16816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pReloc.target() = S + A - P;
1682551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines  return Relocator::OK;
16836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
16846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
168537b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator::Result unsupported(Relocation& pReloc, X86_64Relocator& pParent) {
168637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  return Relocator::Unsupported;
16876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
168837b74a387bb3993387029859c2d9d051c41c724eStephen Hines
168937b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
1690