1 /* Zilog (e)Z80-specific support for 32-bit ELF 2 Copyright (C) 1999-2019 Free Software Foundation, Inc. 3 (Heavily copied from the S12Z port by Sergey Belyashov (sergey.belyashov@gmail.com)) 4 5 This file is part of BFD, the Binary File Descriptor library. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 20 MA 02110-1301, USA. */ 21 22 #include "sysdep.h" 23 #include "bfd.h" 24 #include "bfdlink.h" 25 #include "libbfd.h" 26 #include "elf-bfd.h" 27 28 #include "elf/z80.h" 29 30 /* All users of this file have bfd_octets_per_byte (abfd, sec) == 1. */ 31 #define OCTETS_PER_BYTE(ABFD, SEC) 1 32 33 /* Relocation functions. */ 34 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup 35 (bfd *, bfd_reloc_code_real_type); 36 static bfd_boolean z80_info_to_howto_rel 37 (bfd *, arelent *, Elf_Internal_Rela *); 38 39 typedef struct { 40 bfd_reloc_code_real_type r_type; 41 reloc_howto_type howto; 42 } bfd_howto_type; 43 44 #define BFD_EMPTY_HOWTO(rt,x) {rt, EMPTY_HOWTO(x)} 45 #define BFD_HOWTO(rt,a,b,c,d,e,f,g,h,i,j,k,l,m) {rt, HOWTO(a,b,c,d,e,f,g,h,i,j,k,l,m)} 46 47 static const 48 bfd_howto_type elf_z80_howto_table[] = 49 { 50 /* This reloc does nothing. */ 51 BFD_HOWTO (BFD_RELOC_NONE, 52 R_Z80_NONE, /* type */ 53 0, /* rightshift */ 54 3, /* size (0 = byte, 1 = short, 2 = long) */ 55 0, /* bitsize */ 56 FALSE, /* pc_relative */ 57 0, /* bitpos */ 58 complain_overflow_dont,/* complain_on_overflow */ 59 bfd_elf_generic_reloc, /* special_function */ 60 "R_NONE", /* name */ 61 FALSE, /* partial_inplace */ 62 0, /* src_mask */ 63 0, /* dst_mask */ 64 FALSE), /* pcrel_offset */ 65 66 /* A 8 bit relocation */ 67 BFD_HOWTO (BFD_RELOC_8, 68 R_Z80_8, /* type */ 69 0, /* rightshift */ 70 0, /* size (0 = byte, 1 = short, 2 = long) */ 71 8, /* bitsize */ 72 FALSE, /* pc_relative */ 73 0, /* bitpos */ 74 complain_overflow_bitfield, /* complain_on_overflow */ 75 bfd_elf_generic_reloc, /* special_function */ 76 "r_imm8", /* name */ 77 FALSE, /* partial_inplace */ 78 0x00, /* src_mask */ 79 0xff, /* dst_mask */ 80 FALSE), /* pcrel_offset */ 81 82 /* A 8 bit index register displacement relocation */ 83 BFD_HOWTO (BFD_RELOC_Z80_DISP8, 84 R_Z80_8_DIS, /* type */ 85 0, /* rightshift */ 86 0, /* size (0 = byte, 1 = short, 2 = long) */ 87 8, /* bitsize */ 88 FALSE, /* pc_relative */ 89 0, /* bitpos */ 90 complain_overflow_signed, /* complain_on_overflow */ 91 bfd_elf_generic_reloc, /* special_function */ 92 "r_off", /* name */ 93 FALSE, /* partial_inplace */ 94 0x00, /* src_mask */ 95 0xff, /* dst_mask */ 96 FALSE), /* pcrel_offset */ 97 98 /* A 8 bit PC-rel relocation */ 99 BFD_HOWTO (BFD_RELOC_8_PCREL, 100 R_Z80_8_PCREL, /* type */ 101 0, /* rightshift */ 102 0, /* size (0 = byte, 1 = short, 2 = long) */ 103 8, /* bitsize */ 104 TRUE, /* pc_relative */ 105 0, /* bitpos */ 106 complain_overflow_signed, /* complain_on_overflow */ 107 bfd_elf_generic_reloc, /* special_function */ 108 "r_jr", /* name */ 109 FALSE, /* partial_inplace */ 110 0x00, /* src_mask */ 111 0xff, /* dst_mask */ 112 TRUE), /* pcrel_offset */ 113 114 /* An 16 bit absolute relocation */ 115 BFD_HOWTO (BFD_RELOC_16, 116 R_Z80_16, /* type */ 117 0, /* rightshift */ 118 1, /* size (0 = byte, 1 = short, 2 = long) */ 119 16, /* bitsize */ 120 FALSE, /* pc_relative */ 121 0, /* bitpos */ 122 complain_overflow_bitfield, /* complain_on_overflow */ 123 bfd_elf_generic_reloc, /* special_function */ 124 "r_imm16", /* name */ 125 FALSE, /* partial_inplace */ 126 0x00000000, /* src_mask */ 127 0x0000ffff, /* dst_mask */ 128 FALSE), /* pcrel_offset */ 129 130 /* A 24 bit absolute relocation emitted by ADL mode operands */ 131 BFD_HOWTO (BFD_RELOC_24, 132 R_Z80_24, /* type */ 133 0, /* rightshift */ 134 5, /* size (0 = byte, 1 = short, 2 = long) */ 135 24, /* bitsize */ 136 FALSE, /* pc_relative */ 137 0, /* bitpos */ 138 complain_overflow_bitfield, /* complain_on_overflow */ 139 bfd_elf_generic_reloc, /* special_function */ 140 "r_imm24", /* name */ 141 FALSE, /* partial_inplace */ 142 0x00000000, /* src_mask */ 143 0x00ffffff, /* dst_mask */ 144 FALSE), /* pcrel_offset */ 145 146 BFD_HOWTO (BFD_RELOC_32, 147 R_Z80_32, /* type */ 148 0, /* rightshift */ 149 2, /* size (0 = byte, 1 = short, 2 = long) */ 150 32, /* bitsize */ 151 FALSE, /* pc_relative */ 152 0, /* bitpos */ 153 complain_overflow_dont,/* complain_on_overflow */ 154 bfd_elf_generic_reloc, /* special_function */ 155 "r_imm32", /* name */ 156 FALSE, /* partial_inplace */ 157 0x00000000, /* src_mask */ 158 0xffffffff, /* dst_mask */ 159 FALSE), /* pcrel_offset */ 160 161 /* First (lowest) 8 bits of multibyte relocation */ 162 BFD_HOWTO (BFD_RELOC_Z80_BYTE0, 163 R_Z80_BYTE0, /* type */ 164 0, /* rightshift */ 165 0, /* size (0 = byte, 1 = short, 2 = long) */ 166 32, /* bitsize */ 167 FALSE, /* pc_relative */ 168 0, /* bitpos */ 169 complain_overflow_dont,/* complain_on_overflow */ 170 bfd_elf_generic_reloc, /* special_function */ 171 "r_byte0", /* name */ 172 FALSE, /* partial_inplace */ 173 0, /* src_mask */ 174 0xff, /* dst_mask */ 175 FALSE), /* pcrel_offset */ 176 177 /* Second 8 bits of multibyte relocation */ 178 BFD_HOWTO (BFD_RELOC_Z80_BYTE1, 179 R_Z80_BYTE1, /* type */ 180 8, /* rightshift */ 181 0, /* size (0 = byte, 1 = short, 2 = long) */ 182 32, /* bitsize */ 183 FALSE, /* pc_relative */ 184 0, /* bitpos */ 185 complain_overflow_dont,/* complain_on_overflow */ 186 bfd_elf_generic_reloc, /* special_function */ 187 "r_byte1", /* name */ 188 FALSE, /* partial_inplace */ 189 0, /* src_mask */ 190 0xff, /* dst_mask */ 191 FALSE), /* pcrel_offset */ 192 193 /* Third 8 bits of multibyte relocation */ 194 BFD_HOWTO (BFD_RELOC_Z80_BYTE2, 195 R_Z80_BYTE2, /* type */ 196 16, /* rightshift */ 197 0, /* size (0 = byte, 1 = short, 2 = long) */ 198 32, /* bitsize */ 199 FALSE, /* pc_relative */ 200 0, /* bitpos */ 201 complain_overflow_dont,/* complain_on_overflow */ 202 bfd_elf_generic_reloc, /* special_function */ 203 "r_byte2", /* name */ 204 FALSE, /* partial_inplace */ 205 0, /* src_mask */ 206 0xff, /* dst_mask */ 207 FALSE), /* pcrel_offset */ 208 209 /* Fourth (highest) 8 bits of multibyte relocation */ 210 BFD_HOWTO (BFD_RELOC_Z80_BYTE3, 211 R_Z80_BYTE3, /* type */ 212 24, /* rightshift */ 213 0, /* size (0 = byte, 1 = short, 2 = long) */ 214 32, /* bitsize */ 215 FALSE, /* pc_relative */ 216 0, /* bitpos */ 217 complain_overflow_dont,/* complain_on_overflow */ 218 bfd_elf_generic_reloc, /* special_function */ 219 "r_byte3", /* name */ 220 FALSE, /* partial_inplace */ 221 0, /* src_mask */ 222 0xff, /* dst_mask */ 223 FALSE), /* pcrel_offset */ 224 225 /* An 16 bit absolute relocation of lower word of multibyte value */ 226 BFD_HOWTO (BFD_RELOC_Z80_WORD0, 227 R_Z80_WORD0, /* type */ 228 0, /* rightshift */ 229 1, /* size (0 = byte, 1 = short, 2 = long) */ 230 32, /* bitsize */ 231 FALSE, /* pc_relative */ 232 0, /* bitpos */ 233 complain_overflow_dont,/* complain_on_overflow */ 234 bfd_elf_generic_reloc, /* special_function */ 235 "r_word0", /* name */ 236 FALSE, /* partial_inplace */ 237 0, /* src_mask */ 238 0xffff, /* dst_mask */ 239 FALSE), /* pcrel_offset */ 240 241 /* An 16 bit absolute relocation of higher word of multibyte value */ 242 BFD_HOWTO (BFD_RELOC_Z80_WORD1, 243 R_Z80_WORD1, /* type */ 244 16, /* rightshift */ 245 1, /* size (0 = byte, 1 = short, 2 = long) */ 246 32, /* bitsize */ 247 FALSE, /* pc_relative */ 248 0, /* bitpos */ 249 complain_overflow_dont,/* complain_on_overflow */ 250 bfd_elf_generic_reloc, /* special_function */ 251 "r_word1", /* name */ 252 FALSE, /* partial_inplace */ 253 0, /* src_mask */ 254 0xffff, /* dst_mask */ 255 FALSE), /* pcrel_offset */ 256 }; 257 258 static reloc_howto_type * 259 bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 260 bfd_reloc_code_real_type code) 261 { 262 enum 263 { 264 table_size = sizeof (elf_z80_howto_table) / sizeof (elf_z80_howto_table[0]) 265 }; 266 unsigned int i; 267 268 for (i = 0; i < table_size; i++) 269 { 270 if (elf_z80_howto_table[i].r_type == code) 271 return &elf_z80_howto_table[i].howto; 272 } 273 274 printf ("%s:%d Not found type %d\n", __FILE__, __LINE__, code); 275 276 return NULL; 277 } 278 279 static reloc_howto_type * 280 bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) 281 { 282 enum 283 { 284 table_size = sizeof (elf_z80_howto_table) / sizeof (elf_z80_howto_table[0]) 285 }; 286 unsigned int i; 287 288 for (i = 0; i < table_size; i++) 289 { 290 if (elf_z80_howto_table[i].howto.name != NULL 291 && strcasecmp (elf_z80_howto_table[i].howto.name, r_name) == 0) 292 return &elf_z80_howto_table[i].howto; 293 } 294 295 return NULL; 296 } 297 298 /* Set the howto pointer for an z80 ELF reloc. */ 299 300 static bfd_boolean 301 z80_info_to_howto_rel (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst) 302 { 303 enum 304 { 305 table_size = sizeof (elf_z80_howto_table) / sizeof (elf_z80_howto_table[0]) 306 }; 307 unsigned int i; 308 unsigned int r_type = ELF32_R_TYPE (dst->r_info); 309 310 for (i = 0; i < table_size; i++) 311 { 312 if (elf_z80_howto_table[i].howto.type == r_type) 313 { 314 cache_ptr->howto = &elf_z80_howto_table[i].howto; 315 return TRUE; 316 } 317 } 318 319 /* xgettext:c-format */ 320 _bfd_error_handler (_("%pB: unsupported relocation type %#x"), 321 abfd, r_type); 322 bfd_set_error (bfd_error_bad_value); 323 return FALSE; 324 } 325 326 static bfd_boolean 327 z80_elf_set_mach_from_flags (bfd *abfd) 328 { 329 int mach; 330 switch (elf_elfheader (abfd)->e_flags) 331 { 332 case EF_Z80_MACH_GBZ80: 333 mach = bfd_mach_gbz80; 334 break; 335 case EF_Z80_MACH_Z80: 336 mach = bfd_mach_z80; 337 break; 338 case EF_Z80_MACH_Z180: 339 mach = bfd_mach_z180; 340 break; 341 case EF_Z80_MACH_EZ80_Z80: 342 mach = bfd_mach_ez80_z80; 343 break; 344 case EF_Z80_MACH_EZ80_ADL: 345 mach = bfd_mach_ez80_adl; 346 break; 347 case EF_Z80_MACH_R800: 348 mach = bfd_mach_r800; 349 break; 350 default: 351 mach = bfd_mach_z80; 352 break; 353 } 354 355 bfd_default_set_arch_mach (abfd, bfd_arch_z80, mach); 356 return TRUE; 357 } 358 359 static int 360 z80_is_local_label_name (bfd * abfd ATTRIBUTE_UNUSED, 361 const char * name) 362 { 363 return (name[0] == '.' && name[1] == 'L') || 364 _bfd_elf_is_local_label_name (abfd, name); 365 } 366 367 368 #define ELF_ARCH bfd_arch_z80 369 #define ELF_MACHINE_CODE EM_Z80 370 #define ELF_MAXPAGESIZE 0x10000 371 372 #define TARGET_LITTLE_SYM z80_elf32_vec 373 #define TARGET_LITTLE_NAME "elf32-z80" 374 375 #define elf_info_to_howto NULL 376 #define elf_info_to_howto_rel z80_info_to_howto_rel 377 #define elf_backend_object_p z80_elf_set_mach_from_flags 378 #define bfd_elf32_bfd_is_local_label_name z80_is_local_label_name 379 380 #include "elf32-target.h" 381