1//===-- X86ELFWriterInfo.cpp - ELF Writer Info for the X86 backend --------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements ELF writer information for the X86 backend.
11//
12//===----------------------------------------------------------------------===//
13
14#include "X86ELFWriterInfo.h"
15#include "X86Relocations.h"
16#include "llvm/Function.h"
17#include "llvm/Support/ELF.h"
18#include "llvm/Support/ErrorHandling.h"
19#include "llvm/Target/TargetData.h"
20#include "llvm/Target/TargetMachine.h"
21
22using namespace llvm;
23
24//===----------------------------------------------------------------------===//
25//  Implementation of the X86ELFWriterInfo class
26//===----------------------------------------------------------------------===//
27
28X86ELFWriterInfo::X86ELFWriterInfo(bool is64Bit_, bool isLittleEndian_)
29  : TargetELFWriterInfo(is64Bit_, isLittleEndian_) {
30    EMachine = is64Bit ? EM_X86_64 : EM_386;
31  }
32
33X86ELFWriterInfo::~X86ELFWriterInfo() {}
34
35unsigned X86ELFWriterInfo::getRelocationType(unsigned MachineRelTy) const {
36  if (is64Bit) {
37    switch(MachineRelTy) {
38    case X86::reloc_pcrel_word:
39      return ELF::R_X86_64_PC32;
40    case X86::reloc_absolute_word:
41      return ELF::R_X86_64_32;
42    case X86::reloc_absolute_word_sext:
43      return ELF::R_X86_64_32S;
44    case X86::reloc_absolute_dword:
45      return ELF::R_X86_64_64;
46    case X86::reloc_picrel_word:
47    default:
48      llvm_unreachable("unknown x86_64 machine relocation type");
49    }
50  } else {
51    switch(MachineRelTy) {
52    case X86::reloc_pcrel_word:
53      return ELF::R_386_PC32;
54    case X86::reloc_absolute_word:
55      return ELF::R_386_32;
56    case X86::reloc_absolute_word_sext:
57    case X86::reloc_absolute_dword:
58    case X86::reloc_picrel_word:
59    default:
60      llvm_unreachable("unknown x86 machine relocation type");
61    }
62  }
63  return 0;
64}
65
66long int X86ELFWriterInfo::getDefaultAddendForRelTy(unsigned RelTy,
67                                                    long int Modifier) const {
68  if (is64Bit) {
69    switch(RelTy) {
70    case ELF::R_X86_64_PC32: return Modifier - 4;
71    case ELF::R_X86_64_32:
72    case ELF::R_X86_64_32S:
73    case ELF::R_X86_64_64:
74      return Modifier;
75    default:
76      llvm_unreachable("unknown x86_64 relocation type");
77    }
78  } else {
79    switch(RelTy) {
80    case ELF::R_386_PC32: return Modifier - 4;
81    case ELF::R_386_32: return Modifier;
82    default:
83      llvm_unreachable("unknown x86 relocation type");
84    }
85  }
86  return 0;
87}
88
89unsigned X86ELFWriterInfo::getRelocationTySize(unsigned RelTy) const {
90  if (is64Bit) {
91    switch(RelTy) {
92    case ELF::R_X86_64_PC32:
93    case ELF::R_X86_64_32:
94    case ELF::R_X86_64_32S:
95        return 32;
96    case ELF::R_X86_64_64:
97        return 64;
98    default:
99      llvm_unreachable("unknown x86_64 relocation type");
100    }
101  } else {
102    switch(RelTy) {
103    case ELF::R_386_PC32:
104    case ELF::R_386_32:
105        return 32;
106    default:
107      llvm_unreachable("unknown x86 relocation type");
108    }
109  }
110  return 0;
111}
112
113bool X86ELFWriterInfo::isPCRelativeRel(unsigned RelTy) const {
114  if (is64Bit) {
115    switch(RelTy) {
116    case ELF::R_X86_64_PC32:
117        return true;
118    case ELF::R_X86_64_32:
119    case ELF::R_X86_64_32S:
120    case ELF::R_X86_64_64:
121        return false;
122    default:
123      llvm_unreachable("unknown x86_64 relocation type");
124    }
125  } else {
126    switch(RelTy) {
127    case ELF::R_386_PC32:
128        return true;
129    case ELF::R_386_32:
130        return false;
131    default:
132      llvm_unreachable("unknown x86 relocation type");
133    }
134  }
135  return 0;
136}
137
138unsigned X86ELFWriterInfo::getAbsoluteLabelMachineRelTy() const {
139  return is64Bit ?
140    X86::reloc_absolute_dword : X86::reloc_absolute_word;
141}
142
143long int X86ELFWriterInfo::computeRelocation(unsigned SymOffset,
144                                             unsigned RelOffset,
145                                             unsigned RelTy) const {
146
147  if (RelTy == ELF::R_X86_64_PC32 || RelTy == ELF::R_386_PC32)
148    return SymOffset - (RelOffset + 4);
149  else
150    assert(0 && "computeRelocation unknown for this relocation type");
151
152  return 0;
153}
154