1/* fixes.h (was taken from write.c in the original GAS) 2 Copyright (C) 1986,1987 Free Software Foundation, Inc. 3 4This file is part of GAS, the GNU Assembler. 5 6GAS is free software; you can redistribute it and/or modify 7it under the terms of the GNU General Public License as published by 8the Free Software Foundation; either version 1, or (at your option) 9any later version. 10 11GAS is distributed in the hope that it will be useful, 12but WITHOUT ANY WARRANTY; without even the implied warranty of 13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14GNU General Public License for more details. 15 16You should have received a copy of the GNU General Public License 17along with GAS; see the file COPYING. If not, write to 18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ 19 20/* FROM line 25 */ 21#include "as.h" 22 23#include "sections.h" 24#include "obstack.h" 25#include "frags.h" 26#include "fixes.h" 27#include "symbols.h" 28#include "input-scrub.h" 29#include <mach-o/x86_64/reloc.h> 30 31 32static fixS * 33fix_new_internal (fragS *frag, /* Which frag? */ 34 int where, /* where in that frag? */ 35 int size, /* 1, 2 or 4 bytes */ 36 symbolS *add_symbol, /* X_add_symbol */ 37 symbolS *sub_symbol, /* X_subtract_symbol */ 38 signed_target_addr_t offset, /* X_add_number */ 39 int pcrel, /* TRUE if PC-relative relocation */ 40 int pcrel_reloc, /* TRUE if must have relocation entry */ 41 int r_type) /* relocation type */ 42{ 43 struct fix *fixP; 44 45 fixP = (struct fix *)obstack_alloc(¬es, sizeof(struct fix)); 46 47 fixP->fx_frag = frag; 48 fixP->fx_where = where; 49 fixP->fx_size = size; 50 fixP->fx_addsy = add_symbol; 51 fixP->fx_subsy = sub_symbol; 52 fixP->fx_offset = offset; 53 fixP->fx_pcrel = pcrel; 54 fixP->fx_pcrel_reloc = pcrel_reloc; 55 fixP->fx_r_type = r_type; 56 fixP->fx_sectdiff_divide_by_two = 0; 57#if defined(I386) && defined(ARCH64) 58 if(fixP->fx_r_type == X86_64_RELOC_SIGNED){ 59 switch(offset){ 60 case -1: 61 fixP->fx_r_type = X86_64_RELOC_SIGNED_1; 62 break; 63 case -2: 64 fixP->fx_r_type = X86_64_RELOC_SIGNED_2; 65 break; 66 case -4: 67 fixP->fx_r_type = X86_64_RELOC_SIGNED_4; 68 break; 69 default: 70 break; 71 } 72 } 73 if(fixP->fx_r_type == X86_64_RELOC_GOT || 74 fixP->fx_r_type == X86_64_RELOC_GOT_LOAD){ 75 /* 76 * GOT and GOT_LOAD relocs are always PC-relative and 77 * should not be converted to non-PC-relative addressing 78 * later. 79 */ 80 fixP->fx_pcrel = TRUE; 81 fixP->fx_pcrel_reloc = TRUE; 82 } 83 /* We don't need this for non-local symbols, but it doesn't hurt. */ 84 fixP->fx_localsy = symbol_new("L0\002", N_SECT, frchain_now->frch_nsect, 85 0, where, frag); 86 symbol_assign_index(fixP->fx_localsy); 87#endif 88 as_file_and_line (&fixP->file, &fixP->line); 89 90 fixP->fx_next = frchain_now->frch_fix_root; 91 frchain_now->frch_fix_root = fixP; 92 93 return fixP; 94} 95 96#include "expr.h" /* HACK */ 97/* 98 * fix_new() creates a fixS in obstack 'notes'. 99 */ 100fixS * 101fix_new( 102fragS *frag, /* which frag? */ 103int where, /* where in that frag? */ 104int size, /* 1, 2 or 4 bytes */ 105symbolS *add_symbol, /* X_add_symbol */ 106symbolS *sub_symbol, /* X_subtract_symbol */ 107 signed_target_addr_t 108 offset, /* X_add_number */ 109int pcrel, /* TRUE if PC-relative relocation */ 110int pcrel_reloc, /* TRUE if must have relocation entry */ 111int r_type) /* relocation type */ 112{ 113 return fix_new_internal (frag, where, size, add_symbol, 114 sub_symbol, offset, pcrel, pcrel_reloc, r_type); 115} 116 117/* FROM write.c line 291 */ 118typedef int RELOC_ENUM; 119#define X_op X_seg 120#define X_op_symbol X_add_symbol 121/* Create a fixup for an expression. Currently we only support fixups 122 for difference expressions. That is itself more than most object 123 file formats support anyhow. */ 124 125fixS * 126fix_new_exp (fragS *frag, /* Which frag? */ 127 int where, /* Where in that frag? */ 128 int size, /* 1, 2, or 4 usually. */ 129 expressionS *exp, /* Expression. */ 130 int pcrel, /* TRUE if PC-relative relocation. */ 131 int pcrel_reloc, /* TRUE if must have relocation entry */ 132 RELOC_ENUM r_type /* Relocation type. */) 133{ 134 symbolS *add = NULL; 135 symbolS *sub = NULL; 136 offsetT off = 0; 137 138 switch (exp->X_op) 139 { 140#ifdef NOTYET 141 case O_absent: 142 break; 143 144 case O_register: 145 as_bad (_("register value used as expression")); 146 break; 147 148 case O_add: 149 /* This comes up when _GLOBAL_OFFSET_TABLE_+(.-L0) is read, if 150 the difference expression cannot immediately be reduced. */ 151 { 152 symbolS *stmp = make_expr_symbol (exp); 153 154 exp->X_op = O_symbol; 155 exp->X_op_symbol = 0; 156 exp->X_add_symbol = stmp; 157 exp->X_add_number = 0; 158 159 return fix_new_exp (frag, where, size, exp, pcrel, r_type); 160 } 161 162 case O_symbol_rva: 163 add = exp->X_add_symbol; 164 off = exp->X_add_number; 165 166#if defined(BFD_ASSEMBLER) 167 r_type = BFD_RELOC_RVA; 168#else 169#if defined(TC_RVA_RELOC) 170 r_type = TC_RVA_RELOC; 171#else 172 as_fatal (_("rva not supported")); 173#endif 174#endif 175 break; 176 177 case O_uminus: 178 sub = exp->X_add_symbol; 179 off = exp->X_add_number; 180 break; 181 182 case O_subtract: 183 sub = exp->X_op_symbol; 184 /* Fall through. */ 185#endif 186 case O_symbol: 187 add = exp->X_add_symbol; 188 /* Fall through. */ 189 case O_constant: 190 off = exp->X_add_number; 191 break; 192 193 default: 194 add = make_expr_symbol (exp); 195 break; 196 } 197 198 return fix_new_internal (frag, where, size, add, sub, off, pcrel, pcrel_reloc, r_type); 199} 200