1 1.1 christos /* DLX specific support for 32-bit ELF 2 1.11 christos Copyright (C) 2002-2024 Free Software Foundation, Inc. 3 1.1 christos 4 1.1 christos This file is part of BFD, the Binary File Descriptor library. 5 1.1 christos 6 1.1 christos This program is free software; you can redistribute it and/or modify 7 1.1 christos it under the terms of the GNU General Public License as published by 8 1.1 christos the Free Software Foundation; either version 3 of the License, or 9 1.1 christos (at your option) any later version. 10 1.1 christos 11 1.1 christos This program is distributed in the hope that it will be useful, 12 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 1.1 christos GNU General Public License for more details. 15 1.1 christos 16 1.1 christos You should have received a copy of the GNU General Public License 17 1.1 christos along with this program; if not, write to the Free Software 18 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 19 1.1 christos MA 02110-1301, USA. */ 20 1.1 christos 21 1.1 christos #include "sysdep.h" 22 1.1 christos #include "bfd.h" 23 1.1 christos #include "libbfd.h" 24 1.1 christos #include "elf-bfd.h" 25 1.1 christos #include "elf/dlx.h" 26 1.6 christos #include "elf32-dlx.h" 27 1.1 christos 28 1.1 christos #define USE_REL 1 29 1.1 christos 30 1.1 christos #define bfd_elf32_bfd_reloc_type_lookup elf32_dlx_reloc_type_lookup 31 1.1 christos #define bfd_elf32_bfd_reloc_name_lookup elf32_dlx_reloc_name_lookup 32 1.8 christos #define elf_info_to_howto elf32_dlx_info_to_howto 33 1.8 christos #define elf_info_to_howto_rel elf32_dlx_info_to_howto_rel 34 1.8 christos #define elf_backend_check_relocs elf32_dlx_check_relocs 35 1.1 christos 36 1.1 christos /* The gas default behavior is not to preform the %hi modifier so that the 37 1.1 christos GNU assembler can have the lower 16 bits offset placed in the insn, BUT 38 1.1 christos we do like the gas to indicate it is %hi reloc type so when we in the link 39 1.1 christos loader phase we can have the corrected hi16 vale replace the buggous lo16 40 1.1 christos value that was placed there by gas. */ 41 1.1 christos 42 1.1 christos static int skip_dlx_elf_hi16_reloc = 0; 43 1.1 christos 44 1.1 christos int 45 1.1 christos set_dlx_skip_hi16_flag (int flag) 46 1.1 christos { 47 1.1 christos skip_dlx_elf_hi16_reloc = flag; 48 1.1 christos return flag; 49 1.1 christos } 50 1.1 christos 51 1.1 christos static bfd_reloc_status_type 52 1.1 christos _bfd_dlx_elf_hi16_reloc (bfd *abfd, 53 1.1 christos arelent *reloc_entry, 54 1.1 christos asymbol *symbol, 55 1.1 christos void * data, 56 1.1 christos asection *input_section, 57 1.1 christos bfd *output_bfd, 58 1.1 christos char **error_message) 59 1.1 christos { 60 1.1 christos bfd_reloc_status_type ret; 61 1.1 christos bfd_vma relocation; 62 1.1 christos 63 1.1 christos /* If the skip flag is set then we simply do the generic relocating, this 64 1.1 christos is more of a hack for dlx gas/gld, so we do not need to do the %hi/%lo 65 1.1 christos fixup like mips gld did. */ 66 1.1 christos if (skip_dlx_elf_hi16_reloc) 67 1.1 christos return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 68 1.8 christos input_section, output_bfd, error_message); 69 1.1 christos 70 1.1 christos /* If we're relocating, and this an external symbol, we don't want 71 1.1 christos to change anything. */ 72 1.1 christos if (output_bfd != (bfd *) NULL 73 1.1 christos && (symbol->flags & BSF_SECTION_SYM) == 0 74 1.1 christos && reloc_entry->addend == 0) 75 1.1 christos { 76 1.1 christos reloc_entry->address += input_section->output_offset; 77 1.1 christos return bfd_reloc_ok; 78 1.1 christos } 79 1.1 christos 80 1.1 christos ret = bfd_reloc_ok; 81 1.1 christos 82 1.1 christos if (bfd_is_und_section (symbol->section) 83 1.1 christos && output_bfd == (bfd *) NULL) 84 1.1 christos ret = bfd_reloc_undefined; 85 1.1 christos 86 1.1 christos relocation = (bfd_is_com_section (symbol->section)) ? 0 : symbol->value; 87 1.1 christos relocation += symbol->section->output_section->vma; 88 1.1 christos relocation += symbol->section->output_offset; 89 1.1 christos relocation += reloc_entry->addend; 90 1.1 christos relocation += bfd_get_16 (abfd, (bfd_byte *)data + reloc_entry->address); 91 1.1 christos 92 1.1 christos if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) 93 1.1 christos return bfd_reloc_outofrange; 94 1.1 christos 95 1.1 christos bfd_put_16 (abfd, (short)((relocation >> 16) & 0xFFFF), 96 1.8 christos (bfd_byte *)data + reloc_entry->address); 97 1.1 christos 98 1.1 christos return ret; 99 1.1 christos } 100 1.1 christos 101 1.1 christos /* ELF relocs are against symbols. If we are producing relocatable 102 1.1 christos output, and the reloc is against an external symbol, and nothing 103 1.1 christos has given us any additional addend, the resulting reloc will also 104 1.1 christos be against the same symbol. In such a case, we don't want to 105 1.1 christos change anything about the way the reloc is handled, since it will 106 1.1 christos all be done at final link time. Rather than put special case code 107 1.1 christos into bfd_perform_relocation, all the reloc types use this howto 108 1.1 christos function. It just short circuits the reloc if producing 109 1.1 christos relocatable output against an external symbol. */ 110 1.1 christos 111 1.1 christos static bfd_reloc_status_type 112 1.1 christos elf32_dlx_relocate16 (bfd *abfd, 113 1.1 christos arelent *reloc_entry, 114 1.1 christos asymbol *symbol, 115 1.1 christos void * data, 116 1.1 christos asection *input_section, 117 1.1 christos bfd *output_bfd, 118 1.1 christos char **error_message ATTRIBUTE_UNUSED) 119 1.1 christos { 120 1.1 christos unsigned long insn, vallo, allignment; 121 1.8 christos int val; 122 1.1 christos 123 1.1 christos /* HACK: I think this first condition is necessary when producing 124 1.1 christos relocatable output. After the end of HACK, the code is identical 125 1.1 christos to bfd_elf_generic_reloc(). I would _guess_ the first change 126 1.1 christos belongs there rather than here. martindo 1998-10-23. */ 127 1.1 christos 128 1.1 christos if (skip_dlx_elf_hi16_reloc) 129 1.1 christos return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 130 1.8 christos input_section, output_bfd, error_message); 131 1.1 christos 132 1.1 christos /* Check undefined section and undefined symbols. */ 133 1.1 christos if (bfd_is_und_section (symbol->section) 134 1.1 christos && output_bfd == (bfd *) NULL) 135 1.1 christos return bfd_reloc_undefined; 136 1.1 christos 137 1.1 christos /* Can not support a long jump to sections other then .text. */ 138 1.1 christos if (strcmp (input_section->name, symbol->section->output_section->name) != 0) 139 1.1 christos { 140 1.7 christos _bfd_error_handler 141 1.8 christos (_("branch (PC rel16) to section (%s) not supported"), 142 1.7 christos symbol->section->output_section->name); 143 1.1 christos return bfd_reloc_undefined; 144 1.1 christos } 145 1.1 christos 146 1.1 christos insn = bfd_get_32 (abfd, (bfd_byte *)data + reloc_entry->address); 147 1.1 christos allignment = 1 << (input_section->output_section->alignment_power - 1); 148 1.1 christos vallo = insn & 0x0000FFFF; 149 1.1 christos 150 1.1 christos if (vallo & 0x8000) 151 1.1 christos vallo = ~(vallo | 0xFFFF0000) + 1; 152 1.1 christos 153 1.1 christos /* vallo points to the vma of next instruction. */ 154 1.1 christos vallo += (((unsigned long)(input_section->output_section->vma + 155 1.8 christos input_section->output_offset) + 156 1.8 christos allignment) & ~allignment); 157 1.1 christos 158 1.1 christos /* val is the displacement (PC relative to next instruction). */ 159 1.1 christos val = (symbol->section->output_offset + 160 1.1 christos symbol->section->output_section->vma + 161 1.1 christos symbol->value) - vallo; 162 1.1 christos 163 1.1 christos if (abs ((int) val) > 0x00007FFF) 164 1.1 christos return bfd_reloc_outofrange; 165 1.1 christos 166 1.1 christos insn = (insn & 0xFFFF0000) | (val & 0x0000FFFF); 167 1.1 christos 168 1.1 christos bfd_put_32 (abfd, insn, 169 1.8 christos (bfd_byte *) data + reloc_entry->address); 170 1.1 christos 171 1.1 christos return bfd_reloc_ok; 172 1.1 christos } 173 1.1 christos 174 1.1 christos static bfd_reloc_status_type 175 1.1 christos elf32_dlx_relocate26 (bfd *abfd, 176 1.1 christos arelent *reloc_entry, 177 1.1 christos asymbol *symbol, 178 1.1 christos void * data, 179 1.1 christos asection *input_section, 180 1.1 christos bfd *output_bfd, 181 1.1 christos char **error_message ATTRIBUTE_UNUSED) 182 1.1 christos { 183 1.1 christos unsigned long insn, vallo, allignment; 184 1.8 christos int val; 185 1.1 christos 186 1.1 christos /* HACK: I think this first condition is necessary when producing 187 1.1 christos relocatable output. After the end of HACK, the code is identical 188 1.1 christos to bfd_elf_generic_reloc(). I would _guess_ the first change 189 1.1 christos belongs there rather than here. martindo 1998-10-23. */ 190 1.1 christos 191 1.1 christos if (skip_dlx_elf_hi16_reloc) 192 1.1 christos return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, 193 1.8 christos input_section, output_bfd, error_message); 194 1.1 christos 195 1.1 christos /* Check undefined section and undefined symbols. */ 196 1.1 christos if (bfd_is_und_section (symbol->section) 197 1.1 christos && output_bfd == (bfd *) NULL) 198 1.1 christos return bfd_reloc_undefined; 199 1.1 christos 200 1.1 christos /* Can not support a long jump to sections other then .text */ 201 1.1 christos if (strcmp (input_section->name, symbol->section->output_section->name) != 0) 202 1.1 christos { 203 1.7 christos _bfd_error_handler 204 1.8 christos (_("jump (PC rel26) to section (%s) not supported"), 205 1.7 christos symbol->section->output_section->name); 206 1.1 christos return bfd_reloc_undefined; 207 1.1 christos } 208 1.1 christos 209 1.1 christos insn = bfd_get_32 (abfd, (bfd_byte *)data + reloc_entry->address); 210 1.1 christos allignment = 1 << (input_section->output_section->alignment_power - 1); 211 1.1 christos vallo = insn & 0x03FFFFFF; 212 1.1 christos 213 1.1 christos if (vallo & 0x03000000) 214 1.1 christos vallo = ~(vallo | 0xFC000000) + 1; 215 1.1 christos 216 1.1 christos /* vallo is the vma for the next instruction. */ 217 1.1 christos vallo += (((unsigned long) (input_section->output_section->vma + 218 1.1 christos input_section->output_offset) + 219 1.1 christos allignment) & ~allignment); 220 1.1 christos 221 1.1 christos /* val is the displacement (PC relative to next instruction). */ 222 1.1 christos val = (symbol->section->output_offset + 223 1.1 christos symbol->section->output_section->vma + symbol->value) 224 1.1 christos - vallo; 225 1.1 christos 226 1.1 christos if (abs ((int) val) > 0x01FFFFFF) 227 1.1 christos return bfd_reloc_outofrange; 228 1.1 christos 229 1.1 christos insn = (insn & 0xFC000000) | (val & 0x03FFFFFF); 230 1.1 christos bfd_put_32 (abfd, insn, 231 1.8 christos (bfd_byte *) data + reloc_entry->address); 232 1.1 christos 233 1.1 christos return bfd_reloc_ok; 234 1.1 christos } 235 1.1 christos 236 1.1 christos static reloc_howto_type dlx_elf_howto_table[]= 237 1.1 christos { 238 1.1 christos /* No relocation. */ 239 1.8 christos HOWTO (R_DLX_NONE, /* Type. */ 240 1.8 christos 0, /* Rightshift. */ 241 1.10 christos 0, /* size. */ 242 1.8 christos 0, /* Bitsize. */ 243 1.10 christos false, /* PC_relative. */ 244 1.8 christos 0, /* Bitpos. */ 245 1.1 christos complain_overflow_dont,/* Complain_on_overflow. */ 246 1.1 christos bfd_elf_generic_reloc, /* Special_function. */ 247 1.8 christos "R_DLX_NONE", /* Name. */ 248 1.10 christos false, /* Partial_inplace. */ 249 1.8 christos 0, /* Src_mask. */ 250 1.8 christos 0, /* Dst_mask. */ 251 1.10 christos false), /* PCrel_offset. */ 252 1.1 christos 253 1.1 christos /* 8 bit relocation. */ 254 1.8 christos HOWTO (R_DLX_RELOC_8, /* Type. */ 255 1.8 christos 0, /* Rightshift. */ 256 1.10 christos 1, /* Size. */ 257 1.8 christos 8, /* Bitsize. */ 258 1.10 christos false, /* PC_relative. */ 259 1.8 christos 0, /* Bitpos. */ 260 1.1 christos complain_overflow_dont,/* Complain_on_overflow. */ 261 1.1 christos bfd_elf_generic_reloc, /* Special_function. */ 262 1.8 christos "R_DLX_RELOC_8", /* Name. */ 263 1.10 christos true, /* Partial_inplace. */ 264 1.8 christos 0xff, /* Src_mask. */ 265 1.8 christos 0xff, /* Dst_mask. */ 266 1.10 christos false), /* PCrel_offset. */ 267 1.1 christos 268 1.1 christos /* 16 bit relocation. */ 269 1.8 christos HOWTO (R_DLX_RELOC_16, /* Type. */ 270 1.8 christos 0, /* Rightshift. */ 271 1.10 christos 2, /* Size. */ 272 1.8 christos 16, /* Bitsize. */ 273 1.10 christos false, /* PC_relative. */ 274 1.8 christos 0, /* Bitpos. */ 275 1.1 christos complain_overflow_dont,/* Complain_on_overflow. */ 276 1.1 christos bfd_elf_generic_reloc, /* Special_function. */ 277 1.8 christos "R_DLX_RELOC_16", /* Name. */ 278 1.10 christos true, /* Partial_inplace. */ 279 1.8 christos 0xffff, /* Src_mask. */ 280 1.8 christos 0xffff, /* Dst_mask. */ 281 1.10 christos false), /* PCrel_offset. */ 282 1.1 christos 283 1.1 christos /* 32 bit relocation. */ 284 1.8 christos HOWTO (R_DLX_RELOC_32, /* Type. */ 285 1.8 christos 0, /* Rightshift. */ 286 1.10 christos 4, /* Size. */ 287 1.8 christos 32, /* Bitsize. */ 288 1.10 christos false, /* PC_relative. */ 289 1.8 christos 0, /* Bitpos. */ 290 1.1 christos complain_overflow_dont,/* Complain_on_overflow. */ 291 1.1 christos bfd_elf_generic_reloc, /* Special_function. */ 292 1.8 christos "R_DLX_RELOC_32", /* Name. */ 293 1.10 christos true, /* Partial_inplace. */ 294 1.8 christos 0xffffffff, /* Src_mask. */ 295 1.8 christos 0xffffffff, /* Dst_mask. */ 296 1.10 christos false), /* PCrel_offset. */ 297 1.1 christos 298 1.1 christos /* GNU extension to record C++ vtable hierarchy. */ 299 1.8 christos HOWTO (R_DLX_GNU_VTINHERIT, /* Type. */ 300 1.1 christos 0, /* Rightshift. */ 301 1.10 christos 4, /* Size. */ 302 1.1 christos 0, /* Bitsize. */ 303 1.10 christos false, /* PC_relative. */ 304 1.1 christos 0, /* Bitpos. */ 305 1.1 christos complain_overflow_dont,/* Complain_on_overflow. */ 306 1.1 christos NULL, /* Special_function. */ 307 1.1 christos "R_DLX_GNU_VTINHERIT", /* Name. */ 308 1.10 christos false, /* Partial_inplace. */ 309 1.1 christos 0, /* Src_mask. */ 310 1.1 christos 0, /* Dst_mask. */ 311 1.10 christos false), /* PCrel_offset. */ 312 1.1 christos 313 1.1 christos /* GNU extension to record C++ vtable member usage. */ 314 1.8 christos HOWTO (R_DLX_GNU_VTENTRY, /* Type. */ 315 1.1 christos 0, /* Rightshift. */ 316 1.10 christos 4, /* Size. */ 317 1.1 christos 0, /* Bitsize. */ 318 1.10 christos false, /* PC_relative. */ 319 1.1 christos 0, /* Bitpos. */ 320 1.1 christos complain_overflow_dont,/* Complain_on_overflow. */ 321 1.1 christos _bfd_elf_rel_vtable_reloc_fn,/* Special_function. */ 322 1.1 christos "R_DLX_GNU_VTENTRY", /* Name. */ 323 1.10 christos false, /* Partial_inplace. */ 324 1.1 christos 0, /* Src_mask. */ 325 1.1 christos 0, /* Dst_mask. */ 326 1.10 christos false) /* PCrel_offset. */ 327 1.1 christos }; 328 1.1 christos 329 1.1 christos /* 16 bit offset for pc-relative branches. */ 330 1.1 christos static reloc_howto_type elf_dlx_gnu_rel16_s2 = 331 1.8 christos HOWTO (R_DLX_RELOC_16_PCREL, /* Type. */ 332 1.8 christos 0, /* Rightshift. */ 333 1.10 christos 2, /* Size. */ 334 1.8 christos 16, /* Bitsize. */ 335 1.10 christos true, /* PC_relative. */ 336 1.8 christos 0, /* Bitpos. */ 337 1.1 christos complain_overflow_signed, /* Complain_on_overflow. */ 338 1.8 christos elf32_dlx_relocate16, /* Special_function. */ 339 1.1 christos "R_DLX_RELOC_16_PCREL",/* Name. */ 340 1.10 christos true, /* Partial_inplace. */ 341 1.8 christos 0xffff, /* Src_mask. */ 342 1.8 christos 0xffff, /* Dst_mask. */ 343 1.10 christos true); /* PCrel_offset. */ 344 1.1 christos 345 1.1 christos /* 26 bit offset for pc-relative branches. */ 346 1.1 christos static reloc_howto_type elf_dlx_gnu_rel26_s2 = 347 1.8 christos HOWTO (R_DLX_RELOC_26_PCREL, /* Type. */ 348 1.8 christos 0, /* Rightshift. */ 349 1.10 christos 4, /* Size. */ 350 1.8 christos 26, /* Bitsize. */ 351 1.10 christos true, /* PC_relative. */ 352 1.8 christos 0, /* Bitpos. */ 353 1.1 christos complain_overflow_dont,/* Complain_on_overflow. */ 354 1.8 christos elf32_dlx_relocate26, /* Special_function. */ 355 1.1 christos "R_DLX_RELOC_26_PCREL",/* Name. */ 356 1.10 christos true, /* Partial_inplace. */ 357 1.8 christos 0xffff, /* Src_mask. */ 358 1.8 christos 0xffff, /* Dst_mask. */ 359 1.10 christos true); /* PCrel_offset. */ 360 1.1 christos 361 1.1 christos /* High 16 bits of symbol value. */ 362 1.1 christos static reloc_howto_type elf_dlx_reloc_16_hi = 363 1.8 christos HOWTO (R_DLX_RELOC_16_HI, /* Type. */ 364 1.8 christos 16, /* Rightshift. */ 365 1.10 christos 4, /* Size. */ 366 1.8 christos 32, /* Bitsize. */ 367 1.10 christos false, /* PC_relative. */ 368 1.8 christos 0, /* Bitpos. */ 369 1.1 christos complain_overflow_dont,/* Complain_on_overflow. */ 370 1.1 christos _bfd_dlx_elf_hi16_reloc,/* Special_function. */ 371 1.8 christos "R_DLX_RELOC_16_HI", /* Name. */ 372 1.10 christos true, /* Partial_inplace. */ 373 1.8 christos 0xFFFF, /* Src_mask. */ 374 1.8 christos 0xffff, /* Dst_mask. */ 375 1.10 christos false); /* PCrel_offset. */ 376 1.1 christos 377 1.1 christos /* Low 16 bits of symbol value. */ 378 1.1 christos static reloc_howto_type elf_dlx_reloc_16_lo = 379 1.8 christos HOWTO (R_DLX_RELOC_16_LO, /* Type. */ 380 1.8 christos 0, /* Rightshift. */ 381 1.10 christos 2, /* Size. */ 382 1.8 christos 16, /* Bitsize. */ 383 1.10 christos false, /* PC_relative. */ 384 1.8 christos 0, /* Bitpos. */ 385 1.1 christos complain_overflow_dont,/* Complain_on_overflow. */ 386 1.1 christos bfd_elf_generic_reloc, /* Special_function. */ 387 1.8 christos "R_DLX_RELOC_16_LO", /* Name. */ 388 1.10 christos true, /* Partial_inplace. */ 389 1.8 christos 0xffff, /* Src_mask. */ 390 1.8 christos 0xffff, /* Dst_mask. */ 391 1.10 christos false); /* PCrel_offset. */ 392 1.1 christos 393 1.1 christos /* A mapping from BFD reloc types to DLX ELF reloc types. 394 1.1 christos Stolen from elf32-mips.c. 395 1.1 christos 396 1.1 christos More about this table - for dlx elf relocation we do not really 397 1.1 christos need this table, if we have a rtype defined in this table will 398 1.1 christos caused tc_gen_relocate confused and die on us, but if we remove 399 1.1 christos this table it will caused more problem, so for now simple solution 400 1.1 christos is to remove those entries which may cause problem. */ 401 1.1 christos struct elf_reloc_map 402 1.1 christos { 403 1.1 christos bfd_reloc_code_real_type bfd_reloc_val; 404 1.1 christos enum elf_dlx_reloc_type elf_reloc_val; 405 1.1 christos }; 406 1.1 christos 407 1.1 christos static const struct elf_reloc_map dlx_reloc_map[] = 408 1.1 christos { 409 1.8 christos { BFD_RELOC_NONE, R_DLX_NONE }, 410 1.8 christos { BFD_RELOC_16, R_DLX_RELOC_16 }, 411 1.8 christos { BFD_RELOC_32, R_DLX_RELOC_32 }, 412 1.1 christos { BFD_RELOC_DLX_HI16_S, R_DLX_RELOC_16_HI }, 413 1.8 christos { BFD_RELOC_DLX_LO16, R_DLX_RELOC_16_LO }, 414 1.1 christos { BFD_RELOC_VTABLE_INHERIT, R_DLX_GNU_VTINHERIT }, 415 1.1 christos { BFD_RELOC_VTABLE_ENTRY, R_DLX_GNU_VTENTRY } 416 1.1 christos }; 417 1.1 christos 418 1.1 christos /* Look through the relocs for a section during the first phase. 419 1.1 christos Since we don't do .gots or .plts, we just need to consider the 420 1.1 christos virtual table relocs for gc. */ 421 1.1 christos 422 1.10 christos static bool 423 1.1 christos elf32_dlx_check_relocs (bfd *abfd, 424 1.1 christos struct bfd_link_info *info, 425 1.1 christos asection *sec, 426 1.1 christos const Elf_Internal_Rela *relocs) 427 1.1 christos { 428 1.1 christos Elf_Internal_Shdr *symtab_hdr; 429 1.1 christos struct elf_link_hash_entry **sym_hashes; 430 1.1 christos const Elf_Internal_Rela *rel; 431 1.1 christos const Elf_Internal_Rela *rel_end; 432 1.1 christos 433 1.6 christos if (bfd_link_relocatable (info)) 434 1.10 christos return true; 435 1.1 christos 436 1.1 christos symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 437 1.1 christos sym_hashes = elf_sym_hashes (abfd); 438 1.1 christos 439 1.1 christos rel_end = relocs + sec->reloc_count; 440 1.1 christos for (rel = relocs; rel < rel_end; rel++) 441 1.1 christos { 442 1.1 christos struct elf_link_hash_entry *h; 443 1.1 christos unsigned long r_symndx; 444 1.1 christos 445 1.1 christos r_symndx = ELF32_R_SYM (rel->r_info); 446 1.1 christos if (r_symndx < symtab_hdr->sh_info) 447 1.8 christos h = NULL; 448 1.1 christos else 449 1.1 christos { 450 1.1 christos h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 451 1.1 christos while (h->root.type == bfd_link_hash_indirect 452 1.1 christos || h->root.type == bfd_link_hash_warning) 453 1.1 christos h = (struct elf_link_hash_entry *) h->root.u.i.link; 454 1.1 christos } 455 1.1 christos 456 1.1 christos switch (ELF32_R_TYPE (rel->r_info)) 457 1.8 christos { 458 1.8 christos /* This relocation describes the C++ object vtable hierarchy. 459 1.8 christos Reconstruct it for later use during GC. */ 460 1.8 christos case R_DLX_GNU_VTINHERIT: 461 1.8 christos if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) 462 1.10 christos return false; 463 1.8 christos break; 464 1.8 christos 465 1.8 christos /* This relocation describes which C++ vtable entries are actually 466 1.8 christos used. Record for later use during GC. */ 467 1.8 christos case R_DLX_GNU_VTENTRY: 468 1.9 christos if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) 469 1.10 christos return false; 470 1.8 christos break; 471 1.8 christos } 472 1.1 christos } 473 1.1 christos 474 1.10 christos return true; 475 1.1 christos } 476 1.1 christos 477 1.1 christos /* Given a BFD reloc type, return a howto structure. */ 478 1.1 christos 479 1.1 christos static reloc_howto_type * 480 1.1 christos elf32_dlx_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 481 1.1 christos bfd_reloc_code_real_type code) 482 1.1 christos { 483 1.1 christos unsigned int i; 484 1.1 christos 485 1.1 christos for (i = 0; i < sizeof (dlx_reloc_map) / sizeof (struct elf_reloc_map); i++) 486 1.1 christos if (dlx_reloc_map[i].bfd_reloc_val == code) 487 1.1 christos return &dlx_elf_howto_table[(int) dlx_reloc_map[i].elf_reloc_val]; 488 1.1 christos 489 1.1 christos switch (code) 490 1.1 christos { 491 1.1 christos default: 492 1.1 christos bfd_set_error (bfd_error_bad_value); 493 1.1 christos return NULL; 494 1.1 christos case BFD_RELOC_16_PCREL_S2: 495 1.1 christos return &elf_dlx_gnu_rel16_s2; 496 1.1 christos case BFD_RELOC_DLX_JMP26: 497 1.1 christos return &elf_dlx_gnu_rel26_s2; 498 1.1 christos case BFD_RELOC_HI16_S: 499 1.1 christos return &elf_dlx_reloc_16_hi; 500 1.1 christos case BFD_RELOC_LO16: 501 1.1 christos return &elf_dlx_reloc_16_lo; 502 1.1 christos } 503 1.1 christos } 504 1.1 christos 505 1.1 christos static reloc_howto_type * 506 1.1 christos elf32_dlx_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 507 1.1 christos const char *r_name) 508 1.1 christos { 509 1.1 christos unsigned int i; 510 1.1 christos 511 1.1 christos for (i = 0; 512 1.1 christos i < sizeof (dlx_elf_howto_table) / sizeof (dlx_elf_howto_table[0]); 513 1.1 christos i++) 514 1.1 christos if (dlx_elf_howto_table[i].name != NULL 515 1.1 christos && strcasecmp (dlx_elf_howto_table[i].name, r_name) == 0) 516 1.1 christos return &dlx_elf_howto_table[i]; 517 1.1 christos 518 1.1 christos if (strcasecmp (elf_dlx_gnu_rel16_s2.name, r_name) == 0) 519 1.1 christos return &elf_dlx_gnu_rel16_s2; 520 1.1 christos if (strcasecmp (elf_dlx_gnu_rel26_s2.name, r_name) == 0) 521 1.1 christos return &elf_dlx_gnu_rel26_s2; 522 1.1 christos if (strcasecmp (elf_dlx_reloc_16_hi.name, r_name) == 0) 523 1.1 christos return &elf_dlx_reloc_16_hi; 524 1.1 christos if (strcasecmp (elf_dlx_reloc_16_lo.name, r_name) == 0) 525 1.1 christos return &elf_dlx_reloc_16_lo; 526 1.1 christos 527 1.1 christos return NULL; 528 1.1 christos } 529 1.1 christos 530 1.1 christos static reloc_howto_type * 531 1.8 christos dlx_rtype_to_howto (bfd *abfd, unsigned int r_type) 532 1.1 christos { 533 1.1 christos switch (r_type) 534 1.1 christos { 535 1.1 christos case R_DLX_RELOC_16_PCREL: 536 1.1 christos return & elf_dlx_gnu_rel16_s2; 537 1.1 christos case R_DLX_RELOC_26_PCREL: 538 1.1 christos return & elf_dlx_gnu_rel26_s2; 539 1.1 christos case R_DLX_RELOC_16_HI: 540 1.1 christos return & elf_dlx_reloc_16_hi; 541 1.1 christos case R_DLX_RELOC_16_LO: 542 1.1 christos return & elf_dlx_reloc_16_lo; 543 1.1 christos default: 544 1.3 christos if (r_type >= (unsigned int) R_DLX_max) 545 1.3 christos { 546 1.8 christos _bfd_error_handler (_("%pB: unsupported relocation type %#x"), 547 1.8 christos abfd, r_type); 548 1.8 christos bfd_set_error (bfd_error_bad_value); 549 1.8 christos return NULL; 550 1.3 christos } 551 1.1 christos return & dlx_elf_howto_table[r_type]; 552 1.1 christos } 553 1.1 christos } 554 1.1 christos 555 1.10 christos static bool 556 1.1 christos elf32_dlx_info_to_howto (bfd * abfd ATTRIBUTE_UNUSED, 557 1.1 christos arelent * cache_ptr ATTRIBUTE_UNUSED, 558 1.1 christos Elf_Internal_Rela * dst ATTRIBUTE_UNUSED) 559 1.1 christos { 560 1.10 christos return false; 561 1.1 christos } 562 1.1 christos 563 1.10 christos static bool 564 1.8 christos elf32_dlx_info_to_howto_rel (bfd *abfd, 565 1.1 christos arelent *cache_ptr, 566 1.1 christos Elf_Internal_Rela *dst) 567 1.1 christos { 568 1.1 christos unsigned int r_type; 569 1.1 christos 570 1.1 christos r_type = ELF32_R_TYPE (dst->r_info); 571 1.8 christos cache_ptr->howto = dlx_rtype_to_howto (abfd, r_type); 572 1.8 christos return cache_ptr->howto != NULL; 573 1.1 christos } 574 1.1 christos 575 1.8 christos #define TARGET_BIG_SYM dlx_elf32_be_vec 576 1.8 christos #define TARGET_BIG_NAME "elf32-dlx" 577 1.8 christos #define ELF_ARCH bfd_arch_dlx 578 1.8 christos #define ELF_MACHINE_CODE EM_DLX 579 1.8 christos #define ELF_MAXPAGESIZE 1 /* FIXME: This number is wrong, It should be the page size in bytes. */ 580 1.1 christos 581 1.1 christos #include "elf32-target.h" 582