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}
64
65long int X86ELFWriterInfo::getDefaultAddendForRelTy(unsigned RelTy,
66                                                    long int Modifier) const {
67  if (is64Bit) {
68    switch(RelTy) {
69    case ELF::R_X86_64_PC32: return Modifier - 4;
70    case ELF::R_X86_64_32:
71    case ELF::R_X86_64_32S:
72    case ELF::R_X86_64_64:
73      return Modifier;
74    default:
75      llvm_unreachable("unknown x86_64 relocation type");
76    }
77  } else {
78    switch(RelTy) {
79    case ELF::R_386_PC32: return Modifier - 4;
80    case ELF::R_386_32: return Modifier;
81    default:
82      llvm_unreachable("unknown x86 relocation type");
83    }
84  }
85}
86
87unsigned X86ELFWriterInfo::getRelocationTySize(unsigned RelTy) const {
88  if (is64Bit) {
89    switch(RelTy) {
90    case ELF::R_X86_64_PC32:
91    case ELF::R_X86_64_32:
92    case ELF::R_X86_64_32S:
93        return 32;
94    case ELF::R_X86_64_64:
95        return 64;
96    default:
97      llvm_unreachable("unknown x86_64 relocation type");
98    }
99  } else {
100    switch(RelTy) {
101    case ELF::R_386_PC32:
102    case ELF::R_386_32:
103        return 32;
104    default:
105      llvm_unreachable("unknown x86 relocation type");
106    }
107  }
108}
109
110bool X86ELFWriterInfo::isPCRelativeRel(unsigned RelTy) const {
111  if (is64Bit) {
112    switch(RelTy) {
113    case ELF::R_X86_64_PC32:
114        return true;
115    case ELF::R_X86_64_32:
116    case ELF::R_X86_64_32S:
117    case ELF::R_X86_64_64:
118        return false;
119    default:
120      llvm_unreachable("unknown x86_64 relocation type");
121    }
122  } else {
123    switch(RelTy) {
124    case ELF::R_386_PC32:
125        return true;
126    case ELF::R_386_32:
127        return false;
128    default:
129      llvm_unreachable("unknown x86 relocation type");
130    }
131  }
132}
133
134unsigned X86ELFWriterInfo::getAbsoluteLabelMachineRelTy() const {
135  return is64Bit ?
136    X86::reloc_absolute_dword : X86::reloc_absolute_word;
137}
138
139long int X86ELFWriterInfo::computeRelocation(unsigned SymOffset,
140                                             unsigned RelOffset,
141                                             unsigned RelTy) const {
142
143  if (RelTy == ELF::R_X86_64_PC32 || RelTy == ELF::R_386_PC32)
144    return SymOffset - (RelOffset + 4);
145
146  llvm_unreachable("computeRelocation unknown for this relocation type");
147}
148