00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "bfd.h"
00026 #include "sysdep.h"
00027
00028 #ifdef ANSI_PROTOTYPES
00029 #include <stdarg.h>
00030 #else
00031 #include <varargs.h>
00032 #endif
00033 #include <strings.h>
00034
00035 #include "bfdlink.h"
00036 #include "libbfd.h"
00037 #include "elf-bfd.h"
00038 #include "elf/xtensa.h"
00039 #include "xtensa-isa.h"
00040 #include "xtensa-config.h"
00041
00042 #define XTENSA_NO_NOP_REMOVAL 0
00043
00044
00045
00046 static bfd_boolean add_extra_plt_sections (bfd *, int);
00047 static char *build_encoding_error_message (xtensa_opcode, bfd_vma);
00048 static bfd_reloc_status_type bfd_elf_xtensa_reloc
00049 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
00050 static bfd_boolean do_fix_for_relocatable_link
00051 (Elf_Internal_Rela *, bfd *, asection *, bfd_byte *);
00052 static void do_fix_for_final_link
00053 (Elf_Internal_Rela *, bfd *, asection *, bfd_byte *, bfd_vma *);
00054
00055
00056
00057 static bfd_boolean is_indirect_call_opcode (xtensa_opcode);
00058 static bfd_boolean is_direct_call_opcode (xtensa_opcode);
00059 static bfd_boolean is_windowed_call_opcode (xtensa_opcode);
00060 static xtensa_opcode get_const16_opcode (void);
00061 static xtensa_opcode get_l32r_opcode (void);
00062 static bfd_vma l32r_offset (bfd_vma, bfd_vma);
00063 static int get_relocation_opnd (xtensa_opcode, int);
00064 static int get_relocation_slot (int);
00065 static xtensa_opcode get_relocation_opcode
00066 (bfd *, asection *, bfd_byte *, Elf_Internal_Rela *);
00067 static bfd_boolean is_l32r_relocation
00068 (bfd *, asection *, bfd_byte *, Elf_Internal_Rela *);
00069 static bfd_boolean is_alt_relocation (int);
00070 static bfd_boolean is_operand_relocation (int);
00071 static bfd_size_type insn_decode_len
00072 (bfd_byte *, bfd_size_type, bfd_size_type);
00073 static xtensa_opcode insn_decode_opcode
00074 (bfd_byte *, bfd_size_type, bfd_size_type, int);
00075 static bfd_boolean check_branch_target_aligned
00076 (bfd_byte *, bfd_size_type, bfd_vma, bfd_vma);
00077 static bfd_boolean check_loop_aligned
00078 (bfd_byte *, bfd_size_type, bfd_vma, bfd_vma);
00079 static bfd_boolean check_branch_target_aligned_address (bfd_vma, int);
00080 static bfd_size_type get_asm_simplify_size
00081 (bfd_byte *, bfd_size_type, bfd_size_type);
00082
00083
00084
00085 static bfd_reloc_status_type elf_xtensa_do_asm_simplify
00086 (bfd_byte *, bfd_vma, bfd_vma, char **);
00087 static bfd_reloc_status_type contract_asm_expansion
00088 (bfd_byte *, bfd_vma, Elf_Internal_Rela *, char **);
00089 static xtensa_opcode swap_callx_for_call_opcode (xtensa_opcode);
00090 static xtensa_opcode get_expanded_call_opcode (bfd_byte *, int, bfd_boolean *);
00091
00092
00093
00094 static Elf_Internal_Rela *retrieve_internal_relocs
00095 (bfd *, asection *, bfd_boolean);
00096 static void pin_internal_relocs (asection *, Elf_Internal_Rela *);
00097 static void release_internal_relocs (asection *, Elf_Internal_Rela *);
00098 static bfd_byte *retrieve_contents (bfd *, asection *, bfd_boolean);
00099 static void pin_contents (asection *, bfd_byte *);
00100 static void release_contents (asection *, bfd_byte *);
00101 static Elf_Internal_Sym *retrieve_local_syms (bfd *);
00102
00103
00104
00105 static asection *elf_xtensa_get_plt_section (bfd *, int);
00106 static asection *elf_xtensa_get_gotplt_section (bfd *, int);
00107 static asection *get_elf_r_symndx_section (bfd *, unsigned long);
00108 static struct elf_link_hash_entry *get_elf_r_symndx_hash_entry
00109 (bfd *, unsigned long);
00110 static bfd_vma get_elf_r_symndx_offset (bfd *, unsigned long);
00111 static bfd_boolean is_reloc_sym_weak (bfd *, Elf_Internal_Rela *);
00112 static bfd_boolean pcrel_reloc_fits (xtensa_opcode, int, bfd_vma, bfd_vma);
00113 static bfd_boolean xtensa_is_property_section (asection *);
00114 static bfd_boolean xtensa_is_littable_section (asection *);
00115 static int internal_reloc_compare (const void *, const void *);
00116 static int internal_reloc_matches (const void *, const void *);
00117 extern char *xtensa_get_property_section_name (asection *, const char *);
00118 static flagword xtensa_get_property_predef_flags (asection *);
00119
00120
00121
00122 typedef void (*deps_callback_t)
00123 (asection *, bfd_vma, asection *, bfd_vma, void *);
00124 extern bfd_boolean xtensa_callback_required_dependence
00125 (bfd *, asection *, struct bfd_link_info *, deps_callback_t, void *);
00126
00127
00128
00129
00130
00131
00132
00133 int elf32xtensa_size_opt;
00134
00135
00136
00137
00138
00139
00140 typedef struct xtensa_relax_info_struct xtensa_relax_info;
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 static int plt_reloc_count = 0;
00151
00152
00153
00154
00155
00156
00157
00158 xtensa_isa xtensa_default_isa;
00159
00160
00161
00162
00163
00164
00165 static bfd_boolean relaxing_section = FALSE;
00166
00167
00168
00169
00170 int elf32xtensa_no_literal_movement = 1;
00171
00172
00173 static reloc_howto_type elf_howto_table[] =
00174 {
00175 HOWTO (R_XTENSA_NONE, 0, 0, 0, FALSE, 0, complain_overflow_dont,
00176 bfd_elf_xtensa_reloc, "R_XTENSA_NONE",
00177 FALSE, 0x00000000, 0x00000000, FALSE),
00178 HOWTO (R_XTENSA_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
00179 bfd_elf_xtensa_reloc, "R_XTENSA_32",
00180 TRUE, 0xffffffff, 0xffffffff, FALSE),
00181
00182
00183
00184
00185
00186 HOWTO (R_XTENSA_RTLD, 0, 2, 32, FALSE, 0, complain_overflow_dont,
00187 NULL, "R_XTENSA_RTLD",
00188 FALSE, 0x00000000, 0x00000000, FALSE),
00189 HOWTO (R_XTENSA_GLOB_DAT, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
00190 bfd_elf_generic_reloc, "R_XTENSA_GLOB_DAT",
00191 FALSE, 0xffffffff, 0xffffffff, FALSE),
00192 HOWTO (R_XTENSA_JMP_SLOT, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
00193 bfd_elf_generic_reloc, "R_XTENSA_JMP_SLOT",
00194 FALSE, 0xffffffff, 0xffffffff, FALSE),
00195 HOWTO (R_XTENSA_RELATIVE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
00196 bfd_elf_generic_reloc, "R_XTENSA_RELATIVE",
00197 FALSE, 0xffffffff, 0xffffffff, FALSE),
00198 HOWTO (R_XTENSA_PLT, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
00199 bfd_elf_xtensa_reloc, "R_XTENSA_PLT",
00200 FALSE, 0xffffffff, 0xffffffff, FALSE),
00201 EMPTY_HOWTO (7),
00202 HOWTO (R_XTENSA_OP0, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00203 bfd_elf_xtensa_reloc, "R_XTENSA_OP0",
00204 FALSE, 0x00000000, 0x00000000, TRUE),
00205 HOWTO (R_XTENSA_OP1, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00206 bfd_elf_xtensa_reloc, "R_XTENSA_OP1",
00207 FALSE, 0x00000000, 0x00000000, TRUE),
00208 HOWTO (R_XTENSA_OP2, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00209 bfd_elf_xtensa_reloc, "R_XTENSA_OP2",
00210 FALSE, 0x00000000, 0x00000000, TRUE),
00211
00212 HOWTO (R_XTENSA_ASM_EXPAND, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00213 bfd_elf_xtensa_reloc, "R_XTENSA_ASM_EXPAND",
00214 FALSE, 0x00000000, 0x00000000, FALSE),
00215
00216 HOWTO (R_XTENSA_ASM_SIMPLIFY, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00217 bfd_elf_xtensa_reloc, "R_XTENSA_ASM_SIMPLIFY",
00218 FALSE, 0x00000000, 0x00000000, TRUE),
00219 EMPTY_HOWTO (13),
00220 EMPTY_HOWTO (14),
00221
00222 HOWTO (R_XTENSA_GNU_VTINHERIT, 0, 2, 0, FALSE, 0, complain_overflow_dont,
00223 NULL, "R_XTENSA_GNU_VTINHERIT",
00224 FALSE, 0x00000000, 0x00000000, FALSE),
00225
00226 HOWTO (R_XTENSA_GNU_VTENTRY, 0, 2, 0, FALSE, 0, complain_overflow_dont,
00227 _bfd_elf_rel_vtable_reloc_fn, "R_XTENSA_GNU_VTENTRY",
00228 FALSE, 0x00000000, 0x00000000, FALSE),
00229
00230
00231 HOWTO (R_XTENSA_DIFF8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,
00232 bfd_elf_xtensa_reloc, "R_XTENSA_DIFF8",
00233 FALSE, 0xffffffff, 0xffffffff, FALSE),
00234 HOWTO (R_XTENSA_DIFF16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
00235 bfd_elf_xtensa_reloc, "R_XTENSA_DIFF16",
00236 FALSE, 0xffffffff, 0xffffffff, FALSE),
00237 HOWTO (R_XTENSA_DIFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
00238 bfd_elf_xtensa_reloc, "R_XTENSA_DIFF32",
00239 FALSE, 0xffffffff, 0xffffffff, FALSE),
00240
00241
00242 HOWTO (R_XTENSA_SLOT0_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00243 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT0_OP",
00244 FALSE, 0x00000000, 0x00000000, TRUE),
00245 HOWTO (R_XTENSA_SLOT1_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00246 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT1_OP",
00247 FALSE, 0x00000000, 0x00000000, TRUE),
00248 HOWTO (R_XTENSA_SLOT2_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00249 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT2_OP",
00250 FALSE, 0x00000000, 0x00000000, TRUE),
00251 HOWTO (R_XTENSA_SLOT3_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00252 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT3_OP",
00253 FALSE, 0x00000000, 0x00000000, TRUE),
00254 HOWTO (R_XTENSA_SLOT4_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00255 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT4_OP",
00256 FALSE, 0x00000000, 0x00000000, TRUE),
00257 HOWTO (R_XTENSA_SLOT5_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00258 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT5_OP",
00259 FALSE, 0x00000000, 0x00000000, TRUE),
00260 HOWTO (R_XTENSA_SLOT6_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00261 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT6_OP",
00262 FALSE, 0x00000000, 0x00000000, TRUE),
00263 HOWTO (R_XTENSA_SLOT7_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00264 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT7_OP",
00265 FALSE, 0x00000000, 0x00000000, TRUE),
00266 HOWTO (R_XTENSA_SLOT8_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00267 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT8_OP",
00268 FALSE, 0x00000000, 0x00000000, TRUE),
00269 HOWTO (R_XTENSA_SLOT9_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00270 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT9_OP",
00271 FALSE, 0x00000000, 0x00000000, TRUE),
00272 HOWTO (R_XTENSA_SLOT10_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00273 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT10_OP",
00274 FALSE, 0x00000000, 0x00000000, TRUE),
00275 HOWTO (R_XTENSA_SLOT11_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00276 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT11_OP",
00277 FALSE, 0x00000000, 0x00000000, TRUE),
00278 HOWTO (R_XTENSA_SLOT12_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00279 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT12_OP",
00280 FALSE, 0x00000000, 0x00000000, TRUE),
00281 HOWTO (R_XTENSA_SLOT13_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00282 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT13_OP",
00283 FALSE, 0x00000000, 0x00000000, TRUE),
00284 HOWTO (R_XTENSA_SLOT14_OP, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00285 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT14_OP",
00286 FALSE, 0x00000000, 0x00000000, TRUE),
00287
00288
00289 HOWTO (R_XTENSA_SLOT0_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00290 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT0_ALT",
00291 FALSE, 0x00000000, 0x00000000, TRUE),
00292 HOWTO (R_XTENSA_SLOT1_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00293 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT1_ALT",
00294 FALSE, 0x00000000, 0x00000000, TRUE),
00295 HOWTO (R_XTENSA_SLOT2_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00296 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT2_ALT",
00297 FALSE, 0x00000000, 0x00000000, TRUE),
00298 HOWTO (R_XTENSA_SLOT3_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00299 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT3_ALT",
00300 FALSE, 0x00000000, 0x00000000, TRUE),
00301 HOWTO (R_XTENSA_SLOT4_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00302 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT4_ALT",
00303 FALSE, 0x00000000, 0x00000000, TRUE),
00304 HOWTO (R_XTENSA_SLOT5_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00305 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT5_ALT",
00306 FALSE, 0x00000000, 0x00000000, TRUE),
00307 HOWTO (R_XTENSA_SLOT6_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00308 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT6_ALT",
00309 FALSE, 0x00000000, 0x00000000, TRUE),
00310 HOWTO (R_XTENSA_SLOT7_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00311 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT7_ALT",
00312 FALSE, 0x00000000, 0x00000000, TRUE),
00313 HOWTO (R_XTENSA_SLOT8_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00314 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT8_ALT",
00315 FALSE, 0x00000000, 0x00000000, TRUE),
00316 HOWTO (R_XTENSA_SLOT9_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00317 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT9_ALT",
00318 FALSE, 0x00000000, 0x00000000, TRUE),
00319 HOWTO (R_XTENSA_SLOT10_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00320 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT10_ALT",
00321 FALSE, 0x00000000, 0x00000000, TRUE),
00322 HOWTO (R_XTENSA_SLOT11_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00323 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT11_ALT",
00324 FALSE, 0x00000000, 0x00000000, TRUE),
00325 HOWTO (R_XTENSA_SLOT12_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00326 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT12_ALT",
00327 FALSE, 0x00000000, 0x00000000, TRUE),
00328 HOWTO (R_XTENSA_SLOT13_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00329 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT13_ALT",
00330 FALSE, 0x00000000, 0x00000000, TRUE),
00331 HOWTO (R_XTENSA_SLOT14_ALT, 0, 0, 0, TRUE, 0, complain_overflow_dont,
00332 bfd_elf_xtensa_reloc, "R_XTENSA_SLOT14_ALT",
00333 FALSE, 0x00000000, 0x00000000, TRUE)
00334 };
00335
00336 #if DEBUG_GEN_RELOC
00337 #define TRACE(str) \
00338 fprintf (stderr, "Xtensa bfd reloc lookup %d (%s)\n", code, str)
00339 #else
00340 #define TRACE(str)
00341 #endif
00342
00343 static reloc_howto_type *
00344 elf_xtensa_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00345 bfd_reloc_code_real_type code)
00346 {
00347 switch (code)
00348 {
00349 case BFD_RELOC_NONE:
00350 TRACE ("BFD_RELOC_NONE");
00351 return &elf_howto_table[(unsigned) R_XTENSA_NONE ];
00352
00353 case BFD_RELOC_32:
00354 TRACE ("BFD_RELOC_32");
00355 return &elf_howto_table[(unsigned) R_XTENSA_32 ];
00356
00357 case BFD_RELOC_XTENSA_DIFF8:
00358 TRACE ("BFD_RELOC_XTENSA_DIFF8");
00359 return &elf_howto_table[(unsigned) R_XTENSA_DIFF8 ];
00360
00361 case BFD_RELOC_XTENSA_DIFF16:
00362 TRACE ("BFD_RELOC_XTENSA_DIFF16");
00363 return &elf_howto_table[(unsigned) R_XTENSA_DIFF16 ];
00364
00365 case BFD_RELOC_XTENSA_DIFF32:
00366 TRACE ("BFD_RELOC_XTENSA_DIFF32");
00367 return &elf_howto_table[(unsigned) R_XTENSA_DIFF32 ];
00368
00369 case BFD_RELOC_XTENSA_RTLD:
00370 TRACE ("BFD_RELOC_XTENSA_RTLD");
00371 return &elf_howto_table[(unsigned) R_XTENSA_RTLD ];
00372
00373 case BFD_RELOC_XTENSA_GLOB_DAT:
00374 TRACE ("BFD_RELOC_XTENSA_GLOB_DAT");
00375 return &elf_howto_table[(unsigned) R_XTENSA_GLOB_DAT ];
00376
00377 case BFD_RELOC_XTENSA_JMP_SLOT:
00378 TRACE ("BFD_RELOC_XTENSA_JMP_SLOT");
00379 return &elf_howto_table[(unsigned) R_XTENSA_JMP_SLOT ];
00380
00381 case BFD_RELOC_XTENSA_RELATIVE:
00382 TRACE ("BFD_RELOC_XTENSA_RELATIVE");
00383 return &elf_howto_table[(unsigned) R_XTENSA_RELATIVE ];
00384
00385 case BFD_RELOC_XTENSA_PLT:
00386 TRACE ("BFD_RELOC_XTENSA_PLT");
00387 return &elf_howto_table[(unsigned) R_XTENSA_PLT ];
00388
00389 case BFD_RELOC_XTENSA_OP0:
00390 TRACE ("BFD_RELOC_XTENSA_OP0");
00391 return &elf_howto_table[(unsigned) R_XTENSA_OP0 ];
00392
00393 case BFD_RELOC_XTENSA_OP1:
00394 TRACE ("BFD_RELOC_XTENSA_OP1");
00395 return &elf_howto_table[(unsigned) R_XTENSA_OP1 ];
00396
00397 case BFD_RELOC_XTENSA_OP2:
00398 TRACE ("BFD_RELOC_XTENSA_OP2");
00399 return &elf_howto_table[(unsigned) R_XTENSA_OP2 ];
00400
00401 case BFD_RELOC_XTENSA_ASM_EXPAND:
00402 TRACE ("BFD_RELOC_XTENSA_ASM_EXPAND");
00403 return &elf_howto_table[(unsigned) R_XTENSA_ASM_EXPAND ];
00404
00405 case BFD_RELOC_XTENSA_ASM_SIMPLIFY:
00406 TRACE ("BFD_RELOC_XTENSA_ASM_SIMPLIFY");
00407 return &elf_howto_table[(unsigned) R_XTENSA_ASM_SIMPLIFY ];
00408
00409 case BFD_RELOC_VTABLE_INHERIT:
00410 TRACE ("BFD_RELOC_VTABLE_INHERIT");
00411 return &elf_howto_table[(unsigned) R_XTENSA_GNU_VTINHERIT ];
00412
00413 case BFD_RELOC_VTABLE_ENTRY:
00414 TRACE ("BFD_RELOC_VTABLE_ENTRY");
00415 return &elf_howto_table[(unsigned) R_XTENSA_GNU_VTENTRY ];
00416
00417 default:
00418 if (code >= BFD_RELOC_XTENSA_SLOT0_OP
00419 && code <= BFD_RELOC_XTENSA_SLOT14_OP)
00420 {
00421 unsigned n = (R_XTENSA_SLOT0_OP +
00422 (code - BFD_RELOC_XTENSA_SLOT0_OP));
00423 return &elf_howto_table[n];
00424 }
00425
00426 if (code >= BFD_RELOC_XTENSA_SLOT0_ALT
00427 && code <= BFD_RELOC_XTENSA_SLOT14_ALT)
00428 {
00429 unsigned n = (R_XTENSA_SLOT0_ALT +
00430 (code - BFD_RELOC_XTENSA_SLOT0_ALT));
00431 return &elf_howto_table[n];
00432 }
00433
00434 break;
00435 }
00436
00437 TRACE ("Unknown");
00438 return NULL;
00439 }
00440
00441
00442
00443
00444
00445 static void
00446 elf_xtensa_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
00447 arelent *cache_ptr,
00448 Elf_Internal_Rela *dst)
00449 {
00450 unsigned int r_type = ELF32_R_TYPE (dst->r_info);
00451
00452 BFD_ASSERT (r_type < (unsigned int) R_XTENSA_max);
00453 cache_ptr->howto = &elf_howto_table[r_type];
00454 }
00455
00456
00457
00458
00459
00460
00461
00462 #define ELF_DYNAMIC_INTERPRETER "/lib/ld.so"
00463
00464
00465
00466
00467
00468 #define PLT_ENTRY_SIZE 16
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480 #define PLT_ENTRIES_PER_CHUNK 254
00481
00482
00483
00484
00485
00486
00487 static const bfd_byte elf_xtensa_be_plt_entry[PLT_ENTRY_SIZE] =
00488 {
00489 0x6c, 0x10, 0x04,
00490 0x18, 0x00, 0x00,
00491 0x1a, 0x00, 0x00,
00492 0x1b, 0x00, 0x00,
00493 0x0a, 0x80, 0x00,
00494 0
00495 };
00496
00497 static const bfd_byte elf_xtensa_le_plt_entry[PLT_ENTRY_SIZE] =
00498 {
00499 0x36, 0x41, 0x00,
00500 0x81, 0x00, 0x00,
00501 0xa1, 0x00, 0x00,
00502 0xb1, 0x00, 0x00,
00503 0xa0, 0x08, 0x00,
00504 0
00505 };
00506
00507
00508 static inline bfd_boolean
00509 xtensa_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
00510 struct bfd_link_info *info)
00511 {
00512
00513
00514
00515
00516
00517
00518 return _bfd_elf_dynamic_symbol_p (h, info, 0);
00519 }
00520
00521
00522 static int
00523 property_table_compare (const void *ap, const void *bp)
00524 {
00525 const property_table_entry *a = (const property_table_entry *) ap;
00526 const property_table_entry *b = (const property_table_entry *) bp;
00527
00528 if (a->address == b->address)
00529 {
00530 if (a->size != b->size)
00531 return (a->size - b->size);
00532
00533 if ((a->flags & XTENSA_PROP_ALIGN) != (b->flags & XTENSA_PROP_ALIGN))
00534 return ((b->flags & XTENSA_PROP_ALIGN)
00535 - (a->flags & XTENSA_PROP_ALIGN));
00536
00537 if ((a->flags & XTENSA_PROP_ALIGN)
00538 && (GET_XTENSA_PROP_ALIGNMENT (a->flags)
00539 != GET_XTENSA_PROP_ALIGNMENT (b->flags)))
00540 return (GET_XTENSA_PROP_ALIGNMENT (a->flags)
00541 - GET_XTENSA_PROP_ALIGNMENT (b->flags));
00542
00543 if ((a->flags & XTENSA_PROP_UNREACHABLE)
00544 != (b->flags & XTENSA_PROP_UNREACHABLE))
00545 return ((b->flags & XTENSA_PROP_UNREACHABLE)
00546 - (a->flags & XTENSA_PROP_UNREACHABLE));
00547
00548 return (a->flags - b->flags);
00549 }
00550
00551 return (a->address - b->address);
00552 }
00553
00554
00555 static int
00556 property_table_matches (const void *ap, const void *bp)
00557 {
00558 const property_table_entry *a = (const property_table_entry *) ap;
00559 const property_table_entry *b = (const property_table_entry *) bp;
00560
00561
00562 if ((b->address >= a->address && b->address < (a->address + a->size))
00563 || (a->address >= b->address && a->address < (b->address + b->size)))
00564 return 0;
00565
00566 return (a->address - b->address);
00567 }
00568
00569
00570
00571
00572
00573
00574 static int
00575 xtensa_read_table_entries (bfd *abfd,
00576 asection *section,
00577 property_table_entry **table_p,
00578 const char *sec_name,
00579 bfd_boolean output_addr)
00580 {
00581 asection *table_section;
00582 char *table_section_name;
00583 bfd_size_type table_size = 0;
00584 bfd_byte *table_data;
00585 property_table_entry *blocks;
00586 int blk, block_count;
00587 bfd_size_type num_records;
00588 Elf_Internal_Rela *internal_relocs;
00589 bfd_vma section_addr;
00590 flagword predef_flags;
00591 bfd_size_type table_entry_size;
00592
00593 if (!section
00594 || !(section->flags & SEC_ALLOC)
00595 || (section->flags & SEC_DEBUGGING))
00596 {
00597 *table_p = NULL;
00598 return 0;
00599 }
00600
00601 table_section_name = xtensa_get_property_section_name (section, sec_name);
00602 table_section = bfd_get_section_by_name (abfd, table_section_name);
00603 free (table_section_name);
00604 if (table_section)
00605 table_size = table_section->size;
00606
00607 if (table_size == 0)
00608 {
00609 *table_p = NULL;
00610 return 0;
00611 }
00612
00613 predef_flags = xtensa_get_property_predef_flags (table_section);
00614 table_entry_size = 12;
00615 if (predef_flags)
00616 table_entry_size -= 4;
00617
00618 num_records = table_size / table_entry_size;
00619 table_data = retrieve_contents (abfd, table_section, TRUE);
00620 blocks = (property_table_entry *)
00621 bfd_malloc (num_records * sizeof (property_table_entry));
00622 block_count = 0;
00623
00624 if (output_addr)
00625 section_addr = section->output_section->vma + section->output_offset;
00626 else
00627 section_addr = section->vma;
00628
00629
00630
00631 internal_relocs = retrieve_internal_relocs (abfd, table_section, TRUE);
00632 if (internal_relocs && !table_section->reloc_done)
00633 {
00634 unsigned i;
00635
00636 for (i = 0; i < table_section->reloc_count; i++)
00637 {
00638 Elf_Internal_Rela *rel = &internal_relocs[i];
00639 unsigned long r_symndx;
00640
00641 if (ELF32_R_TYPE (rel->r_info) == R_XTENSA_NONE)
00642 continue;
00643
00644 BFD_ASSERT (ELF32_R_TYPE (rel->r_info) == R_XTENSA_32);
00645 r_symndx = ELF32_R_SYM (rel->r_info);
00646
00647 if (get_elf_r_symndx_section (abfd, r_symndx) == section)
00648 {
00649 bfd_vma sym_off = get_elf_r_symndx_offset (abfd, r_symndx);
00650 BFD_ASSERT (sym_off == 0);
00651 BFD_ASSERT (rel->r_addend == 0);
00652 blocks[block_count].address =
00653 (section_addr + sym_off + rel->r_addend
00654 + bfd_get_32 (abfd, table_data + rel->r_offset));
00655 blocks[block_count].size =
00656 bfd_get_32 (abfd, table_data + rel->r_offset + 4);
00657 if (predef_flags)
00658 blocks[block_count].flags = predef_flags;
00659 else
00660 blocks[block_count].flags =
00661 bfd_get_32 (abfd, table_data + rel->r_offset + 8);
00662 block_count++;
00663 }
00664 }
00665 }
00666 else
00667 {
00668
00669
00670 bfd_vma off;
00671 bfd_size_type section_limit = bfd_get_section_limit (abfd, section);
00672
00673 for (off = 0; off < table_size; off += table_entry_size)
00674 {
00675 bfd_vma address = bfd_get_32 (abfd, table_data + off);
00676
00677 if (address >= section_addr
00678 && address < section_addr + section_limit)
00679 {
00680 blocks[block_count].address = address;
00681 blocks[block_count].size =
00682 bfd_get_32 (abfd, table_data + off + 4);
00683 if (predef_flags)
00684 blocks[block_count].flags = predef_flags;
00685 else
00686 blocks[block_count].flags =
00687 bfd_get_32 (abfd, table_data + off + 8);
00688 block_count++;
00689 }
00690 }
00691 }
00692
00693 release_contents (table_section, table_data);
00694 release_internal_relocs (table_section, internal_relocs);
00695
00696 if (block_count > 0)
00697 {
00698
00699 qsort (blocks, block_count, sizeof (property_table_entry),
00700 property_table_compare);
00701
00702
00703
00704 for (blk = 1; blk < block_count; blk++)
00705 {
00706
00707
00708
00709
00710 if (blocks[blk - 1].address == blocks[blk].address &&
00711 blocks[blk - 1].size != 0)
00712 {
00713 (*_bfd_error_handler) (_("%B(%A): invalid property table"),
00714 abfd, section);
00715 bfd_set_error (bfd_error_bad_value);
00716 free (blocks);
00717 return -1;
00718 }
00719 }
00720 }
00721
00722 *table_p = blocks;
00723 return block_count;
00724 }
00725
00726
00727 static property_table_entry *
00728 elf_xtensa_find_property_entry (property_table_entry *property_table,
00729 int property_table_size,
00730 bfd_vma addr)
00731 {
00732 property_table_entry entry;
00733 property_table_entry *rv;
00734
00735 if (property_table_size == 0)
00736 return NULL;
00737
00738 entry.address = addr;
00739 entry.size = 1;
00740 entry.flags = 0;
00741
00742 rv = bsearch (&entry, property_table, property_table_size,
00743 sizeof (property_table_entry), property_table_matches);
00744 return rv;
00745 }
00746
00747
00748 static bfd_boolean
00749 elf_xtensa_in_literal_pool (property_table_entry *lit_table,
00750 int lit_table_size,
00751 bfd_vma addr)
00752 {
00753 if (elf_xtensa_find_property_entry (lit_table, lit_table_size, addr))
00754 return TRUE;
00755
00756 return FALSE;
00757 }
00758
00759
00760
00761
00762
00763 static bfd_boolean
00764 elf_xtensa_check_relocs (bfd *abfd,
00765 struct bfd_link_info *info,
00766 asection *sec,
00767 const Elf_Internal_Rela *relocs)
00768 {
00769 Elf_Internal_Shdr *symtab_hdr;
00770 struct elf_link_hash_entry **sym_hashes;
00771 const Elf_Internal_Rela *rel;
00772 const Elf_Internal_Rela *rel_end;
00773
00774 if (info->relocatable)
00775 return TRUE;
00776
00777 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
00778 sym_hashes = elf_sym_hashes (abfd);
00779
00780 rel_end = relocs + sec->reloc_count;
00781 for (rel = relocs; rel < rel_end; rel++)
00782 {
00783 unsigned int r_type;
00784 unsigned long r_symndx;
00785 struct elf_link_hash_entry *h;
00786
00787 r_symndx = ELF32_R_SYM (rel->r_info);
00788 r_type = ELF32_R_TYPE (rel->r_info);
00789
00790 if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
00791 {
00792 (*_bfd_error_handler) (_("%B: bad symbol index: %d"),
00793 abfd, r_symndx);
00794 return FALSE;
00795 }
00796
00797 if (r_symndx < symtab_hdr->sh_info)
00798 h = NULL;
00799 else
00800 {
00801 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
00802 while (h->root.type == bfd_link_hash_indirect
00803 || h->root.type == bfd_link_hash_warning)
00804 h = (struct elf_link_hash_entry *) h->root.u.i.link;
00805 }
00806
00807 switch (r_type)
00808 {
00809 case R_XTENSA_32:
00810 if (h == NULL)
00811 goto local_literal;
00812
00813 if ((sec->flags & SEC_ALLOC) != 0)
00814 {
00815 if (h->got.refcount <= 0)
00816 h->got.refcount = 1;
00817 else
00818 h->got.refcount += 1;
00819 }
00820 break;
00821
00822 case R_XTENSA_PLT:
00823
00824
00825 if (h == NULL)
00826 goto local_literal;
00827
00828 if ((sec->flags & SEC_ALLOC) != 0)
00829 {
00830 if (h->plt.refcount <= 0)
00831 {
00832 h->needs_plt = 1;
00833 h->plt.refcount = 1;
00834 }
00835 else
00836 h->plt.refcount += 1;
00837
00838
00839
00840
00841 plt_reloc_count += 1;
00842
00843 if (elf_hash_table (info)->dynamic_sections_created)
00844 {
00845 if (!add_extra_plt_sections (elf_hash_table (info)->dynobj,
00846 plt_reloc_count))
00847 return FALSE;
00848 }
00849 }
00850 break;
00851
00852 local_literal:
00853 if ((sec->flags & SEC_ALLOC) != 0)
00854 {
00855 bfd_signed_vma *local_got_refcounts;
00856
00857
00858 local_got_refcounts = elf_local_got_refcounts (abfd);
00859 if (local_got_refcounts == NULL)
00860 {
00861 bfd_size_type size;
00862
00863 size = symtab_hdr->sh_info;
00864 size *= sizeof (bfd_signed_vma);
00865 local_got_refcounts =
00866 (bfd_signed_vma *) bfd_zalloc (abfd, size);
00867 if (local_got_refcounts == NULL)
00868 return FALSE;
00869 elf_local_got_refcounts (abfd) = local_got_refcounts;
00870 }
00871 local_got_refcounts[r_symndx] += 1;
00872 }
00873 break;
00874
00875 case R_XTENSA_OP0:
00876 case R_XTENSA_OP1:
00877 case R_XTENSA_OP2:
00878 case R_XTENSA_SLOT0_OP:
00879 case R_XTENSA_SLOT1_OP:
00880 case R_XTENSA_SLOT2_OP:
00881 case R_XTENSA_SLOT3_OP:
00882 case R_XTENSA_SLOT4_OP:
00883 case R_XTENSA_SLOT5_OP:
00884 case R_XTENSA_SLOT6_OP:
00885 case R_XTENSA_SLOT7_OP:
00886 case R_XTENSA_SLOT8_OP:
00887 case R_XTENSA_SLOT9_OP:
00888 case R_XTENSA_SLOT10_OP:
00889 case R_XTENSA_SLOT11_OP:
00890 case R_XTENSA_SLOT12_OP:
00891 case R_XTENSA_SLOT13_OP:
00892 case R_XTENSA_SLOT14_OP:
00893 case R_XTENSA_SLOT0_ALT:
00894 case R_XTENSA_SLOT1_ALT:
00895 case R_XTENSA_SLOT2_ALT:
00896 case R_XTENSA_SLOT3_ALT:
00897 case R_XTENSA_SLOT4_ALT:
00898 case R_XTENSA_SLOT5_ALT:
00899 case R_XTENSA_SLOT6_ALT:
00900 case R_XTENSA_SLOT7_ALT:
00901 case R_XTENSA_SLOT8_ALT:
00902 case R_XTENSA_SLOT9_ALT:
00903 case R_XTENSA_SLOT10_ALT:
00904 case R_XTENSA_SLOT11_ALT:
00905 case R_XTENSA_SLOT12_ALT:
00906 case R_XTENSA_SLOT13_ALT:
00907 case R_XTENSA_SLOT14_ALT:
00908 case R_XTENSA_ASM_EXPAND:
00909 case R_XTENSA_ASM_SIMPLIFY:
00910 case R_XTENSA_DIFF8:
00911 case R_XTENSA_DIFF16:
00912 case R_XTENSA_DIFF32:
00913
00914 break;
00915
00916 case R_XTENSA_GNU_VTINHERIT:
00917
00918
00919 if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
00920 return FALSE;
00921 break;
00922
00923 case R_XTENSA_GNU_VTENTRY:
00924
00925
00926 if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
00927 return FALSE;
00928 break;
00929
00930 default:
00931 break;
00932 }
00933 }
00934
00935 return TRUE;
00936 }
00937
00938
00939 static void
00940 elf_xtensa_make_sym_local (struct bfd_link_info *info,
00941 struct elf_link_hash_entry *h)
00942 {
00943 if (info->shared)
00944 {
00945 if (h->plt.refcount > 0)
00946 {
00947
00948 if (h->got.refcount < 0)
00949 h->got.refcount = 0;
00950 h->got.refcount += h->plt.refcount;
00951 h->plt.refcount = 0;
00952 }
00953 }
00954 else
00955 {
00956
00957 h->plt.refcount = 0;
00958 h->got.refcount = 0;
00959 }
00960 }
00961
00962
00963 static void
00964 elf_xtensa_hide_symbol (struct bfd_link_info *info,
00965 struct elf_link_hash_entry *h,
00966 bfd_boolean force_local)
00967 {
00968
00969
00970 elf_xtensa_make_sym_local (info, h);
00971
00972 _bfd_elf_link_hash_hide_symbol (info, h, force_local);
00973 }
00974
00975
00976
00977
00978
00979 static asection *
00980 elf_xtensa_gc_mark_hook (asection *sec,
00981 struct bfd_link_info *info ATTRIBUTE_UNUSED,
00982 Elf_Internal_Rela *rel,
00983 struct elf_link_hash_entry *h,
00984 Elf_Internal_Sym *sym)
00985 {
00986 if (h)
00987 {
00988 switch (ELF32_R_TYPE (rel->r_info))
00989 {
00990 case R_XTENSA_GNU_VTINHERIT:
00991 case R_XTENSA_GNU_VTENTRY:
00992 break;
00993
00994 default:
00995 switch (h->root.type)
00996 {
00997 case bfd_link_hash_defined:
00998 case bfd_link_hash_defweak:
00999 return h->root.u.def.section;
01000
01001 case bfd_link_hash_common:
01002 return h->root.u.c.p->section;
01003
01004 default:
01005 break;
01006 }
01007 }
01008 }
01009 else
01010 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
01011
01012 return NULL;
01013 }
01014
01015
01016
01017
01018
01019 static bfd_boolean
01020 elf_xtensa_gc_sweep_hook (bfd *abfd,
01021 struct bfd_link_info *info ATTRIBUTE_UNUSED,
01022 asection *sec,
01023 const Elf_Internal_Rela *relocs)
01024 {
01025 Elf_Internal_Shdr *symtab_hdr;
01026 struct elf_link_hash_entry **sym_hashes;
01027 bfd_signed_vma *local_got_refcounts;
01028 const Elf_Internal_Rela *rel, *relend;
01029
01030 if ((sec->flags & SEC_ALLOC) == 0)
01031 return TRUE;
01032
01033 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
01034 sym_hashes = elf_sym_hashes (abfd);
01035 local_got_refcounts = elf_local_got_refcounts (abfd);
01036
01037 relend = relocs + sec->reloc_count;
01038 for (rel = relocs; rel < relend; rel++)
01039 {
01040 unsigned long r_symndx;
01041 unsigned int r_type;
01042 struct elf_link_hash_entry *h = NULL;
01043
01044 r_symndx = ELF32_R_SYM (rel->r_info);
01045 if (r_symndx >= symtab_hdr->sh_info)
01046 {
01047 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
01048 while (h->root.type == bfd_link_hash_indirect
01049 || h->root.type == bfd_link_hash_warning)
01050 h = (struct elf_link_hash_entry *) h->root.u.i.link;
01051 }
01052
01053 r_type = ELF32_R_TYPE (rel->r_info);
01054 switch (r_type)
01055 {
01056 case R_XTENSA_32:
01057 if (h == NULL)
01058 goto local_literal;
01059 if (h->got.refcount > 0)
01060 h->got.refcount--;
01061 break;
01062
01063 case R_XTENSA_PLT:
01064 if (h == NULL)
01065 goto local_literal;
01066 if (h->plt.refcount > 0)
01067 h->plt.refcount--;
01068 break;
01069
01070 local_literal:
01071 if (local_got_refcounts[r_symndx] > 0)
01072 local_got_refcounts[r_symndx] -= 1;
01073 break;
01074
01075 default:
01076 break;
01077 }
01078 }
01079
01080 return TRUE;
01081 }
01082
01083
01084
01085
01086 static bfd_boolean
01087 elf_xtensa_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
01088 {
01089 flagword flags, noalloc_flags;
01090 asection *s;
01091
01092
01093 if (! _bfd_elf_create_dynamic_sections (dynobj, info))
01094 return FALSE;
01095
01096
01097
01098 if (!add_extra_plt_sections (dynobj, plt_reloc_count))
01099 return FALSE;
01100
01101 noalloc_flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY
01102 | SEC_LINKER_CREATED | SEC_READONLY);
01103 flags = noalloc_flags | SEC_ALLOC | SEC_LOAD;
01104
01105
01106 s = bfd_get_section_by_name (dynobj, ".got.plt");
01107 if (s == NULL
01108 || ! bfd_set_section_flags (dynobj, s, flags))
01109 return FALSE;
01110
01111
01112 s = bfd_make_section (dynobj, ".rela.got");
01113 if (s == NULL
01114 || ! bfd_set_section_flags (dynobj, s, flags)
01115 || ! bfd_set_section_alignment (dynobj, s, 2))
01116 return FALSE;
01117
01118
01119 s = bfd_make_section (dynobj, ".got.loc");
01120 if (s == NULL
01121 || ! bfd_set_section_flags (dynobj, s, flags)
01122 || ! bfd_set_section_alignment (dynobj, s, 2))
01123 return FALSE;
01124
01125
01126 s = bfd_make_section (dynobj, ".xt.lit.plt");
01127 if (s == NULL
01128 || ! bfd_set_section_flags (dynobj, s, noalloc_flags)
01129 || ! bfd_set_section_alignment (dynobj, s, 2))
01130 return FALSE;
01131
01132 return TRUE;
01133 }
01134
01135
01136 static bfd_boolean
01137 add_extra_plt_sections (bfd *dynobj, int count)
01138 {
01139 int chunk;
01140
01141
01142
01143 for (chunk = count / PLT_ENTRIES_PER_CHUNK; chunk > 0; chunk--)
01144 {
01145 char *sname;
01146 flagword flags;
01147 asection *s;
01148
01149
01150 if (elf_xtensa_get_plt_section (dynobj, chunk))
01151 break;
01152
01153 flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
01154 | SEC_LINKER_CREATED | SEC_READONLY);
01155
01156 sname = (char *) bfd_malloc (10);
01157 sprintf (sname, ".plt.%u", chunk);
01158 s = bfd_make_section (dynobj, sname);
01159 if (s == NULL
01160 || ! bfd_set_section_flags (dynobj, s, flags | SEC_CODE)
01161 || ! bfd_set_section_alignment (dynobj, s, 2))
01162 return FALSE;
01163
01164 sname = (char *) bfd_malloc (14);
01165 sprintf (sname, ".got.plt.%u", chunk);
01166 s = bfd_make_section (dynobj, sname);
01167 if (s == NULL
01168 || ! bfd_set_section_flags (dynobj, s, flags)
01169 || ! bfd_set_section_alignment (dynobj, s, 2))
01170 return FALSE;
01171 }
01172
01173 return TRUE;
01174 }
01175
01176
01177
01178
01179
01180
01181
01182
01183 static bfd_boolean
01184 elf_xtensa_adjust_dynamic_symbol (struct bfd_link_info *info ATTRIBUTE_UNUSED,
01185 struct elf_link_hash_entry *h)
01186 {
01187
01188
01189
01190 if (h->u.weakdef)
01191 {
01192 BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
01193 || h->u.weakdef->root.type == bfd_link_hash_defweak);
01194 h->root.u.def.section = h->u.weakdef->root.u.def.section;
01195 h->root.u.def.value = h->u.weakdef->root.u.def.value;
01196 return TRUE;
01197 }
01198
01199
01200
01201
01202
01203 return TRUE;
01204 }
01205
01206
01207 static bfd_boolean
01208 elf_xtensa_fix_refcounts (struct elf_link_hash_entry *h, void *arg)
01209 {
01210 struct bfd_link_info *info = (struct bfd_link_info *) arg;
01211
01212 if (h->root.type == bfd_link_hash_warning)
01213 h = (struct elf_link_hash_entry *) h->root.u.i.link;
01214
01215 if (! xtensa_elf_dynamic_symbol_p (h, info))
01216 elf_xtensa_make_sym_local (info, h);
01217
01218 return TRUE;
01219 }
01220
01221
01222 static bfd_boolean
01223 elf_xtensa_allocate_plt_size (struct elf_link_hash_entry *h, void *arg)
01224 {
01225 asection *srelplt = (asection *) arg;
01226
01227 if (h->root.type == bfd_link_hash_warning)
01228 h = (struct elf_link_hash_entry *) h->root.u.i.link;
01229
01230 if (h->plt.refcount > 0)
01231 srelplt->size += (h->plt.refcount * sizeof (Elf32_External_Rela));
01232
01233 return TRUE;
01234 }
01235
01236
01237 static bfd_boolean
01238 elf_xtensa_allocate_got_size (struct elf_link_hash_entry *h, void *arg)
01239 {
01240 asection *srelgot = (asection *) arg;
01241
01242 if (h->root.type == bfd_link_hash_warning)
01243 h = (struct elf_link_hash_entry *) h->root.u.i.link;
01244
01245 if (h->got.refcount > 0)
01246 srelgot->size += (h->got.refcount * sizeof (Elf32_External_Rela));
01247
01248 return TRUE;
01249 }
01250
01251
01252 static void
01253 elf_xtensa_allocate_local_got_size (struct bfd_link_info *info,
01254 asection *srelgot)
01255 {
01256 bfd *i;
01257
01258 for (i = info->input_bfds; i; i = i->link_next)
01259 {
01260 bfd_signed_vma *local_got_refcounts;
01261 bfd_size_type j, cnt;
01262 Elf_Internal_Shdr *symtab_hdr;
01263
01264 local_got_refcounts = elf_local_got_refcounts (i);
01265 if (!local_got_refcounts)
01266 continue;
01267
01268 symtab_hdr = &elf_tdata (i)->symtab_hdr;
01269 cnt = symtab_hdr->sh_info;
01270
01271 for (j = 0; j < cnt; ++j)
01272 {
01273 if (local_got_refcounts[j] > 0)
01274 srelgot->size += (local_got_refcounts[j]
01275 * sizeof (Elf32_External_Rela));
01276 }
01277 }
01278 }
01279
01280
01281
01282
01283 static bfd_boolean
01284 elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
01285 struct bfd_link_info *info)
01286 {
01287 bfd *dynobj, *abfd;
01288 asection *s, *srelplt, *splt, *sgotplt, *srelgot, *spltlittbl, *sgotloc;
01289 bfd_boolean relplt, relgot;
01290 int plt_entries, plt_chunks, chunk;
01291
01292 plt_entries = 0;
01293 plt_chunks = 0;
01294 srelgot = 0;
01295
01296 dynobj = elf_hash_table (info)->dynobj;
01297 if (dynobj == NULL)
01298 abort ();
01299
01300 if (elf_hash_table (info)->dynamic_sections_created)
01301 {
01302
01303 if (info->executable)
01304 {
01305 s = bfd_get_section_by_name (dynobj, ".interp");
01306 if (s == NULL)
01307 abort ();
01308 s->size = sizeof ELF_DYNAMIC_INTERPRETER;
01309 s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
01310 }
01311
01312
01313 s = bfd_get_section_by_name (dynobj, ".got");
01314 if (s == NULL)
01315 abort ();
01316 s->size = 4;
01317
01318
01319 elf_link_hash_traverse (elf_hash_table (info),
01320 elf_xtensa_fix_refcounts,
01321 (void *) info);
01322
01323
01324
01325 srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
01326 if (srelgot == NULL)
01327 abort ();
01328 elf_link_hash_traverse (elf_hash_table (info),
01329 elf_xtensa_allocate_got_size,
01330 (void *) srelgot);
01331
01332
01333
01334
01335 if (info->shared)
01336 elf_xtensa_allocate_local_got_size (info, srelgot);
01337
01338
01339 srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
01340 if (srelplt == NULL)
01341 abort ();
01342 elf_link_hash_traverse (elf_hash_table (info),
01343 elf_xtensa_allocate_plt_size,
01344 (void *) srelplt);
01345
01346
01347
01348
01349
01350
01351 spltlittbl = bfd_get_section_by_name (dynobj, ".xt.lit.plt");
01352 if (spltlittbl == NULL)
01353 abort ();
01354
01355 plt_entries = srelplt->size / sizeof (Elf32_External_Rela);
01356 plt_chunks =
01357 (plt_entries + PLT_ENTRIES_PER_CHUNK - 1) / PLT_ENTRIES_PER_CHUNK;
01358
01359
01360
01361
01362 for (chunk = 0;
01363 (splt = elf_xtensa_get_plt_section (dynobj, chunk)) != NULL;
01364 chunk++)
01365 {
01366 int chunk_entries;
01367
01368 sgotplt = elf_xtensa_get_gotplt_section (dynobj, chunk);
01369 if (sgotplt == NULL)
01370 abort ();
01371
01372 if (chunk < plt_chunks - 1)
01373 chunk_entries = PLT_ENTRIES_PER_CHUNK;
01374 else if (chunk == plt_chunks - 1)
01375 chunk_entries = plt_entries - (chunk * PLT_ENTRIES_PER_CHUNK);
01376 else
01377 chunk_entries = 0;
01378
01379 if (chunk_entries != 0)
01380 {
01381 sgotplt->size = 4 * (chunk_entries + 2);
01382 splt->size = PLT_ENTRY_SIZE * chunk_entries;
01383 srelgot->size += 2 * sizeof (Elf32_External_Rela);
01384 spltlittbl->size += 8;
01385 }
01386 else
01387 {
01388 sgotplt->size = 0;
01389 splt->size = 0;
01390 }
01391 }
01392
01393
01394
01395 sgotloc = bfd_get_section_by_name (dynobj, ".got.loc");
01396 if (sgotloc == NULL)
01397 abort ();
01398 sgotloc->size = spltlittbl->size;
01399 for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
01400 {
01401 if (abfd->flags & DYNAMIC)
01402 continue;
01403 for (s = abfd->sections; s != NULL; s = s->next)
01404 {
01405 if (! elf_discarded_section (s)
01406 && xtensa_is_littable_section (s)
01407 && s != spltlittbl)
01408 sgotloc->size += s->size;
01409 }
01410 }
01411 }
01412
01413
01414 relplt = FALSE;
01415 relgot = FALSE;
01416 for (s = dynobj->sections; s != NULL; s = s->next)
01417 {
01418 const char *name;
01419 bfd_boolean strip;
01420
01421 if ((s->flags & SEC_LINKER_CREATED) == 0)
01422 continue;
01423
01424
01425
01426 name = bfd_get_section_name (dynobj, s);
01427
01428 strip = FALSE;
01429
01430 if (strncmp (name, ".rela", 5) == 0)
01431 {
01432 if (strcmp (name, ".rela.plt") == 0)
01433 relplt = TRUE;
01434 else if (strcmp (name, ".rela.got") == 0)
01435 relgot = TRUE;
01436
01437
01438
01439 s->reloc_count = 0;
01440 }
01441 else if (strncmp (name, ".plt.", 5) == 0
01442 || strncmp (name, ".got.plt.", 9) == 0)
01443 {
01444 if (s->size == 0)
01445 {
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455 strip = TRUE;
01456 }
01457 }
01458 else if (strcmp (name, ".got") != 0
01459 && strcmp (name, ".plt") != 0
01460 && strcmp (name, ".got.plt") != 0
01461 && strcmp (name, ".xt.lit.plt") != 0
01462 && strcmp (name, ".got.loc") != 0)
01463 {
01464
01465 continue;
01466 }
01467
01468 if (strip)
01469 _bfd_strip_section_from_output (info, s);
01470 else
01471 {
01472
01473 s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
01474 if (s->contents == NULL && s->size != 0)
01475 return FALSE;
01476 }
01477 }
01478
01479 if (elf_hash_table (info)->dynamic_sections_created)
01480 {
01481
01482
01483
01484 if (srelgot == NULL)
01485 abort ();
01486 for (chunk = 0; chunk < plt_chunks; chunk++)
01487 {
01488 Elf_Internal_Rela irela;
01489 bfd_byte *loc;
01490
01491 irela.r_offset = 0;
01492 irela.r_info = ELF32_R_INFO (0, R_XTENSA_RTLD);
01493 irela.r_addend = 0;
01494
01495 loc = (srelgot->contents
01496 + srelgot->reloc_count * sizeof (Elf32_External_Rela));
01497 bfd_elf32_swap_reloca_out (output_bfd, &irela, loc);
01498 bfd_elf32_swap_reloca_out (output_bfd, &irela,
01499 loc + sizeof (Elf32_External_Rela));
01500 srelgot->reloc_count += 2;
01501 }
01502
01503
01504
01505
01506
01507
01508 #define add_dynamic_entry(TAG, VAL) \
01509 _bfd_elf_add_dynamic_entry (info, TAG, VAL)
01510
01511 if (! info->shared)
01512 {
01513 if (!add_dynamic_entry (DT_DEBUG, 0))
01514 return FALSE;
01515 }
01516
01517 if (relplt)
01518 {
01519 if (!add_dynamic_entry (DT_PLTGOT, 0)
01520 || !add_dynamic_entry (DT_PLTRELSZ, 0)
01521 || !add_dynamic_entry (DT_PLTREL, DT_RELA)
01522 || !add_dynamic_entry (DT_JMPREL, 0))
01523 return FALSE;
01524 }
01525
01526 if (relgot)
01527 {
01528 if (!add_dynamic_entry (DT_RELA, 0)
01529 || !add_dynamic_entry (DT_RELASZ, 0)
01530 || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
01531 return FALSE;
01532 }
01533
01534 if (!add_dynamic_entry (DT_XTENSA_GOT_LOC_OFF, 0)
01535 || !add_dynamic_entry (DT_XTENSA_GOT_LOC_SZ, 0))
01536 return FALSE;
01537 }
01538 #undef add_dynamic_entry
01539
01540 return TRUE;
01541 }
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551 static bfd_boolean
01552 elf_xtensa_modify_segment_map (bfd *abfd,
01553 struct bfd_link_info *info ATTRIBUTE_UNUSED)
01554 {
01555 struct elf_segment_map **m_p;
01556
01557 m_p = &elf_tdata (abfd)->segment_map;
01558 while (*m_p)
01559 {
01560 if ((*m_p)->p_type == PT_LOAD && (*m_p)->count == 0)
01561 *m_p = (*m_p)->next;
01562 else
01563 m_p = &(*m_p)->next;
01564 }
01565 return TRUE;
01566 }
01567
01568
01569
01570
01571
01572
01573
01574 #define CALL_SEGMENT_BITS (30)
01575 #define CALL_SEGMENT_SIZE (1 << CALL_SEGMENT_BITS)
01576
01577 static bfd_reloc_status_type
01578 elf_xtensa_do_reloc (reloc_howto_type *howto,
01579 bfd *abfd,
01580 asection *input_section,
01581 bfd_vma relocation,
01582 bfd_byte *contents,
01583 bfd_vma address,
01584 bfd_boolean is_weak_undef,
01585 char **error_message)
01586 {
01587 xtensa_format fmt;
01588 xtensa_opcode opcode;
01589 xtensa_isa isa = xtensa_default_isa;
01590 static xtensa_insnbuf ibuff = NULL;
01591 static xtensa_insnbuf sbuff = NULL;
01592 bfd_vma self_address = 0;
01593 bfd_size_type input_size;
01594 int opnd, slot;
01595 uint32 newval;
01596
01597 if (!ibuff)
01598 {
01599 ibuff = xtensa_insnbuf_alloc (isa);
01600 sbuff = xtensa_insnbuf_alloc (isa);
01601 }
01602
01603 input_size = bfd_get_section_limit (abfd, input_section);
01604
01605 switch (howto->type)
01606 {
01607 case R_XTENSA_NONE:
01608 case R_XTENSA_DIFF8:
01609 case R_XTENSA_DIFF16:
01610 case R_XTENSA_DIFF32:
01611 return bfd_reloc_ok;
01612
01613 case R_XTENSA_ASM_EXPAND:
01614 if (!is_weak_undef)
01615 {
01616
01617 xtensa_opcode opcode =
01618 get_expanded_call_opcode (contents + address,
01619 input_size - address, 0);
01620 if (is_windowed_call_opcode (opcode))
01621 {
01622 self_address = (input_section->output_section->vma
01623 + input_section->output_offset
01624 + address);
01625 if ((self_address >> CALL_SEGMENT_BITS)
01626 != (relocation >> CALL_SEGMENT_BITS))
01627 {
01628 *error_message = "windowed longcall crosses 1GB boundary; "
01629 "return may fail";
01630 return bfd_reloc_dangerous;
01631 }
01632 }
01633 }
01634 return bfd_reloc_ok;
01635
01636 case R_XTENSA_ASM_SIMPLIFY:
01637 {
01638
01639 bfd_reloc_status_type retval =
01640 elf_xtensa_do_asm_simplify (contents, address, input_size,
01641 error_message);
01642 if (retval != bfd_reloc_ok)
01643 return bfd_reloc_dangerous;
01644
01645
01646 address += 3;
01647 howto = &elf_howto_table[(unsigned) R_XTENSA_SLOT0_OP ];
01648 }
01649 break;
01650
01651 case R_XTENSA_32:
01652 case R_XTENSA_PLT:
01653 {
01654 bfd_vma x;
01655 x = bfd_get_32 (abfd, contents + address);
01656 x = x + relocation;
01657 bfd_put_32 (abfd, x, contents + address);
01658 }
01659 return bfd_reloc_ok;
01660 }
01661
01662
01663 slot = get_relocation_slot (howto->type);
01664 if (slot == XTENSA_UNDEFINED)
01665 {
01666 *error_message = "unexpected relocation";
01667 return bfd_reloc_dangerous;
01668 }
01669
01670
01671 xtensa_insnbuf_from_chars (isa, ibuff, contents + address,
01672 input_size - address);
01673 fmt = xtensa_format_decode (isa, ibuff);
01674 if (fmt == XTENSA_UNDEFINED)
01675 {
01676 *error_message = "cannot decode instruction format";
01677 return bfd_reloc_dangerous;
01678 }
01679
01680 xtensa_format_get_slot (isa, fmt, slot, ibuff, sbuff);
01681
01682 opcode = xtensa_opcode_decode (isa, fmt, slot, sbuff);
01683 if (opcode == XTENSA_UNDEFINED)
01684 {
01685 *error_message = "cannot decode instruction opcode";
01686 return bfd_reloc_dangerous;
01687 }
01688
01689
01690 if (is_alt_relocation (howto->type))
01691 {
01692 if (opcode == get_l32r_opcode ())
01693 {
01694
01695 bfd *output_bfd = input_section->output_section->owner;
01696 asection *lit4_sec = bfd_get_section_by_name (output_bfd, ".lit4");
01697 if (!lit4_sec)
01698 {
01699 *error_message = "relocation references missing .lit4 section";
01700 return bfd_reloc_dangerous;
01701 }
01702 self_address = ((lit4_sec->vma & ~0xfff)
01703 + 0x40000 - 3);
01704 newval = relocation;
01705 opnd = 1;
01706 }
01707 else if (opcode == get_const16_opcode ())
01708 {
01709
01710 newval = relocation >> 16;
01711 opnd = 1;
01712 }
01713 else
01714 {
01715
01716 *error_message = "unexpected relocation";
01717 return bfd_reloc_dangerous;
01718 }
01719 }
01720 else
01721 {
01722 if (opcode == get_const16_opcode ())
01723 {
01724 newval = relocation & 0xffff;
01725 opnd = 1;
01726 }
01727 else
01728 {
01729
01730
01731
01732 opnd = get_relocation_opnd (opcode, howto->type);
01733 if (opnd == XTENSA_UNDEFINED)
01734 {
01735 *error_message = "unexpected relocation";
01736 return bfd_reloc_dangerous;
01737 }
01738
01739 if (!howto->pc_relative)
01740 {
01741 *error_message = "expected PC-relative relocation";
01742 return bfd_reloc_dangerous;
01743 }
01744
01745
01746 self_address = (input_section->output_section->vma
01747 + input_section->output_offset
01748 + address);
01749
01750 newval = relocation;
01751 }
01752 }
01753
01754
01755 if (xtensa_operand_do_reloc (isa, opcode, opnd, &newval, self_address)
01756 || xtensa_operand_encode (isa, opcode, opnd, &newval)
01757 || xtensa_operand_set_field (isa, opcode, opnd, fmt, slot,
01758 sbuff, newval))
01759 {
01760 *error_message = build_encoding_error_message (opcode, relocation);
01761 return bfd_reloc_dangerous;
01762 }
01763
01764
01765 if (is_direct_call_opcode (opcode)
01766 && is_windowed_call_opcode (opcode))
01767 {
01768 if ((self_address >> CALL_SEGMENT_BITS)
01769 != (relocation >> CALL_SEGMENT_BITS))
01770 {
01771 *error_message =
01772 "windowed call crosses 1GB boundary; return may fail";
01773 return bfd_reloc_dangerous;
01774 }
01775 }
01776
01777
01778 xtensa_format_set_slot (isa, fmt, slot, ibuff, sbuff);
01779 xtensa_insnbuf_to_chars (isa, ibuff, contents + address,
01780 input_size - address);
01781 return bfd_reloc_ok;
01782 }
01783
01784
01785 static char *
01786 vsprint_msg (const char *origmsg, const char *fmt, int arglen, ...)
01787 {
01788
01789
01790 static bfd_size_type alloc_size = 0;
01791 static char *message = NULL;
01792 bfd_size_type orig_len, len = 0;
01793 bfd_boolean is_append;
01794
01795 VA_OPEN (ap, arglen);
01796 VA_FIXEDARG (ap, const char *, origmsg);
01797
01798 is_append = (origmsg == message);
01799
01800 orig_len = strlen (origmsg);
01801 len = orig_len + strlen (fmt) + arglen + 20;
01802 if (len > alloc_size)
01803 {
01804 message = (char *) bfd_realloc (message, len);
01805 alloc_size = len;
01806 }
01807 if (!is_append)
01808 memcpy (message, origmsg, orig_len);
01809 vsprintf (message + orig_len, fmt, ap);
01810 VA_CLOSE (ap);
01811 return message;
01812 }
01813
01814
01815 static char *
01816 build_encoding_error_message (xtensa_opcode opcode, bfd_vma target_address)
01817 {
01818 const char *opname = xtensa_opcode_name (xtensa_default_isa, opcode);
01819 const char *msg;
01820
01821 msg = "cannot encode";
01822 if (is_direct_call_opcode (opcode))
01823 {
01824 if ((target_address & 0x3) != 0)
01825 msg = "misaligned call target";
01826 else
01827 msg = "call target out of range";
01828 }
01829 else if (opcode == get_l32r_opcode ())
01830 {
01831 if ((target_address & 0x3) != 0)
01832 msg = "misaligned literal target";
01833 else
01834 msg = "literal target out of range";
01835 }
01836
01837 return vsprint_msg (opname, ": %s", strlen (msg) + 2, msg);
01838 }
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848 static bfd_reloc_status_type
01849 bfd_elf_xtensa_reloc (bfd *abfd,
01850 arelent *reloc_entry,
01851 asymbol *symbol,
01852 void *data,
01853 asection *input_section,
01854 bfd *output_bfd,
01855 char **error_message)
01856 {
01857 bfd_vma relocation;
01858 bfd_reloc_status_type flag;
01859 bfd_size_type octets = reloc_entry->address * bfd_octets_per_byte (abfd);
01860 bfd_vma output_base = 0;
01861 reloc_howto_type *howto = reloc_entry->howto;
01862 asection *reloc_target_output_section;
01863 bfd_boolean is_weak_undef;
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876 if (output_bfd && (symbol->flags & BSF_SECTION_SYM) == 0)
01877 {
01878 reloc_entry->address += input_section->output_offset;
01879 return bfd_reloc_ok;
01880 }
01881
01882
01883 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
01884 return bfd_reloc_outofrange;
01885
01886
01887
01888
01889
01890 if (bfd_is_com_section (symbol->section))
01891 relocation = 0;
01892 else
01893 relocation = symbol->value;
01894
01895 reloc_target_output_section = symbol->section->output_section;
01896
01897
01898 if ((output_bfd && !howto->partial_inplace)
01899 || reloc_target_output_section == NULL)
01900 output_base = 0;
01901 else
01902 output_base = reloc_target_output_section->vma;
01903
01904 relocation += output_base + symbol->section->output_offset;
01905
01906
01907 relocation += reloc_entry->addend;
01908
01909
01910
01911 if (output_bfd)
01912 {
01913 if (!howto->partial_inplace)
01914 {
01915
01916
01917
01918
01919
01920 BFD_ASSERT (symbol->flags & BSF_SECTION_SYM);
01921 reloc_entry->addend = relocation;
01922 reloc_entry->address += input_section->output_offset;
01923 return bfd_reloc_ok;
01924 }
01925 else
01926 {
01927 reloc_entry->address += input_section->output_offset;
01928 reloc_entry->addend = 0;
01929 }
01930 }
01931
01932 is_weak_undef = (bfd_is_und_section (symbol->section)
01933 && (symbol->flags & BSF_WEAK) != 0);
01934 flag = elf_xtensa_do_reloc (howto, abfd, input_section, relocation,
01935 (bfd_byte *) data, (bfd_vma) octets,
01936 is_weak_undef, error_message);
01937
01938 if (flag == bfd_reloc_dangerous)
01939 {
01940
01941 if (! *error_message)
01942 *error_message = "";
01943 *error_message = vsprint_msg (*error_message, ": (%s + 0x%lx)",
01944 strlen (symbol->name) + 17,
01945 symbol->name, reloc_entry->addend);
01946 }
01947
01948 return flag;
01949 }
01950
01951
01952
01953
01954 static bfd_vma
01955 elf_xtensa_create_plt_entry (bfd *dynobj,
01956 bfd *output_bfd,
01957 unsigned reloc_index)
01958 {
01959 asection *splt, *sgotplt;
01960 bfd_vma plt_base, got_base;
01961 bfd_vma code_offset, lit_offset;
01962 int chunk;
01963
01964 chunk = reloc_index / PLT_ENTRIES_PER_CHUNK;
01965 splt = elf_xtensa_get_plt_section (dynobj, chunk);
01966 sgotplt = elf_xtensa_get_gotplt_section (dynobj, chunk);
01967 BFD_ASSERT (splt != NULL && sgotplt != NULL);
01968
01969 plt_base = splt->output_section->vma + splt->output_offset;
01970 got_base = sgotplt->output_section->vma + sgotplt->output_offset;
01971
01972 lit_offset = 8 + (reloc_index % PLT_ENTRIES_PER_CHUNK) * 4;
01973 code_offset = (reloc_index % PLT_ENTRIES_PER_CHUNK) * PLT_ENTRY_SIZE;
01974
01975
01976
01977 bfd_put_32 (output_bfd, reloc_index * sizeof (Elf32_External_Rela),
01978 sgotplt->contents + lit_offset);
01979
01980
01981 memcpy (splt->contents + code_offset,
01982 (bfd_big_endian (output_bfd)
01983 ? elf_xtensa_be_plt_entry
01984 : elf_xtensa_le_plt_entry),
01985 PLT_ENTRY_SIZE);
01986 bfd_put_16 (output_bfd, l32r_offset (got_base + 0,
01987 plt_base + code_offset + 3),
01988 splt->contents + code_offset + 4);
01989 bfd_put_16 (output_bfd, l32r_offset (got_base + 4,
01990 plt_base + code_offset + 6),
01991 splt->contents + code_offset + 7);
01992 bfd_put_16 (output_bfd, l32r_offset (got_base + lit_offset,
01993 plt_base + code_offset + 9),
01994 splt->contents + code_offset + 10);
01995
01996 return plt_base + code_offset;
01997 }
01998
01999
02000
02001
02002
02003 static bfd_boolean
02004 elf_xtensa_relocate_section (bfd *output_bfd,
02005 struct bfd_link_info *info,
02006 bfd *input_bfd,
02007 asection *input_section,
02008 bfd_byte *contents,
02009 Elf_Internal_Rela *relocs,
02010 Elf_Internal_Sym *local_syms,
02011 asection **local_sections)
02012 {
02013 Elf_Internal_Shdr *symtab_hdr;
02014 Elf_Internal_Rela *rel;
02015 Elf_Internal_Rela *relend;
02016 struct elf_link_hash_entry **sym_hashes;
02017 asection *srelgot, *srelplt;
02018 bfd *dynobj;
02019 property_table_entry *lit_table = 0;
02020 int ltblsize = 0;
02021 char *error_message = NULL;
02022 bfd_size_type input_size;
02023
02024 if (!xtensa_default_isa)
02025 xtensa_default_isa = xtensa_isa_init (0, 0);
02026
02027 dynobj = elf_hash_table (info)->dynobj;
02028 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
02029 sym_hashes = elf_sym_hashes (input_bfd);
02030
02031 srelgot = NULL;
02032 srelplt = NULL;
02033 if (dynobj)
02034 {
02035 srelgot = bfd_get_section_by_name (dynobj, ".rela.got");;
02036 srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
02037 }
02038
02039 if (elf_hash_table (info)->dynamic_sections_created)
02040 {
02041 ltblsize = xtensa_read_table_entries (input_bfd, input_section,
02042 &lit_table, XTENSA_LIT_SEC_NAME,
02043 TRUE);
02044 if (ltblsize < 0)
02045 return FALSE;
02046 }
02047
02048 input_size = bfd_get_section_limit (input_bfd, input_section);
02049
02050 rel = relocs;
02051 relend = relocs + input_section->reloc_count;
02052 for (; rel < relend; rel++)
02053 {
02054 int r_type;
02055 reloc_howto_type *howto;
02056 unsigned long r_symndx;
02057 struct elf_link_hash_entry *h;
02058 Elf_Internal_Sym *sym;
02059 asection *sec;
02060 bfd_vma relocation;
02061 bfd_reloc_status_type r;
02062 bfd_boolean is_weak_undef;
02063 bfd_boolean unresolved_reloc;
02064 bfd_boolean warned;
02065
02066 r_type = ELF32_R_TYPE (rel->r_info);
02067 if (r_type == (int) R_XTENSA_GNU_VTINHERIT
02068 || r_type == (int) R_XTENSA_GNU_VTENTRY)
02069 continue;
02070
02071 if (r_type < 0 || r_type >= (int) R_XTENSA_max)
02072 {
02073 bfd_set_error (bfd_error_bad_value);
02074 return FALSE;
02075 }
02076 howto = &elf_howto_table[r_type];
02077
02078 r_symndx = ELF32_R_SYM (rel->r_info);
02079
02080 if (info->relocatable)
02081 {
02082
02083
02084
02085
02086
02087
02088
02089
02090 if (relaxing_section)
02091 {
02092
02093 if (!do_fix_for_relocatable_link (rel, input_bfd, input_section,
02094 contents))
02095 return FALSE;
02096 r_type = ELF32_R_TYPE (rel->r_info);
02097 }
02098
02099 if (r_type == R_XTENSA_ASM_SIMPLIFY)
02100 {
02101 char *error_message = NULL;
02102
02103
02104 r = contract_asm_expansion (contents, input_size, rel,
02105 &error_message);
02106 if (r != bfd_reloc_ok)
02107 {
02108 if (!((*info->callbacks->reloc_dangerous)
02109 (info, error_message, input_bfd, input_section,
02110 rel->r_offset)))
02111 return FALSE;
02112 }
02113 r_type = ELF32_R_TYPE (rel->r_info);
02114 }
02115
02116
02117
02118
02119
02120 if (r_symndx < symtab_hdr->sh_info)
02121 {
02122 sym = local_syms + r_symndx;
02123 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
02124 {
02125 sec = local_sections[r_symndx];
02126 rel->r_addend += sec->output_offset + sym->st_value;
02127 }
02128 }
02129
02130
02131
02132
02133
02134
02135 if (rel->r_addend)
02136 {
02137 howto = &elf_howto_table[r_type];
02138 if (howto->partial_inplace)
02139 {
02140 r = elf_xtensa_do_reloc (howto, input_bfd, input_section,
02141 rel->r_addend, contents,
02142 rel->r_offset, FALSE,
02143 &error_message);
02144 if (r != bfd_reloc_ok)
02145 {
02146 if (!((*info->callbacks->reloc_dangerous)
02147 (info, error_message, input_bfd, input_section,
02148 rel->r_offset)))
02149 return FALSE;
02150 }
02151 rel->r_addend = 0;
02152 }
02153 }
02154
02155
02156 continue;
02157 }
02158
02159
02160
02161 h = NULL;
02162 sym = NULL;
02163 sec = NULL;
02164 is_weak_undef = FALSE;
02165 unresolved_reloc = FALSE;
02166 warned = FALSE;
02167
02168 if (howto->partial_inplace)
02169 {
02170
02171
02172
02173
02174 rel->r_addend += bfd_get_32 (input_bfd, contents + rel->r_offset);
02175 bfd_put_32 (input_bfd, 0, contents + rel->r_offset);
02176 }
02177
02178 if (r_symndx < symtab_hdr->sh_info)
02179 {
02180 sym = local_syms + r_symndx;
02181 sec = local_sections[r_symndx];
02182 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
02183 }
02184 else
02185 {
02186 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
02187 r_symndx, symtab_hdr, sym_hashes,
02188 h, sec, relocation,
02189 unresolved_reloc, warned);
02190
02191 if (relocation == 0
02192 && !unresolved_reloc
02193 && h->root.type == bfd_link_hash_undefweak)
02194 is_weak_undef = TRUE;
02195 }
02196
02197 if (relaxing_section)
02198 {
02199
02200 do_fix_for_final_link (rel, input_bfd, input_section, contents,
02201 &relocation);
02202
02203
02204 r_type = ELF32_R_TYPE (rel->r_info);
02205 howto = &elf_howto_table[r_type];
02206 }
02207
02208
02209 if (rel->r_offset >= input_size
02210 && ELF32_R_TYPE (rel->r_info) != R_XTENSA_NONE)
02211 {
02212 (*_bfd_error_handler)
02213 (_("%B(%A+0x%lx): relocation offset out of range (size=0x%x)"),
02214 input_bfd, input_section, rel->r_offset, input_size);
02215 bfd_set_error (bfd_error_bad_value);
02216 return FALSE;
02217 }
02218
02219
02220 if (elf_hash_table (info)->dynamic_sections_created)
02221 {
02222 bfd_boolean dynamic_symbol = xtensa_elf_dynamic_symbol_p (h, info);
02223
02224 if (dynamic_symbol && is_operand_relocation (r_type))
02225 {
02226
02227
02228 const char *name = h->root.root.string;
02229 error_message = vsprint_msg ("invalid relocation for dynamic "
02230 "symbol", ": %s",
02231 strlen (name) + 2, name);
02232 if (!((*info->callbacks->reloc_dangerous)
02233 (info, error_message, input_bfd, input_section,
02234 rel->r_offset)))
02235 return FALSE;
02236 }
02237 else if ((r_type == R_XTENSA_32 || r_type == R_XTENSA_PLT)
02238 && (input_section->flags & SEC_ALLOC) != 0
02239 && (dynamic_symbol || info->shared))
02240 {
02241 Elf_Internal_Rela outrel;
02242 bfd_byte *loc;
02243 asection *srel;
02244
02245 if (dynamic_symbol && r_type == R_XTENSA_PLT)
02246 srel = srelplt;
02247 else
02248 srel = srelgot;
02249
02250 BFD_ASSERT (srel != NULL);
02251
02252 outrel.r_offset =
02253 _bfd_elf_section_offset (output_bfd, info,
02254 input_section, rel->r_offset);
02255
02256 if ((outrel.r_offset | 1) == (bfd_vma) -1)
02257 memset (&outrel, 0, sizeof outrel);
02258 else
02259 {
02260 outrel.r_offset += (input_section->output_section->vma
02261 + input_section->output_offset);
02262
02263
02264
02265 if ((input_section->flags & SEC_READONLY) != 0
02266 && !elf_xtensa_in_literal_pool (lit_table, ltblsize,
02267 outrel.r_offset))
02268 {
02269 error_message =
02270 _("dynamic relocation in read-only section");
02271 if (!((*info->callbacks->reloc_dangerous)
02272 (info, error_message, input_bfd, input_section,
02273 rel->r_offset)))
02274 return FALSE;
02275 }
02276
02277 if (dynamic_symbol)
02278 {
02279 outrel.r_addend = rel->r_addend;
02280 rel->r_addend = 0;
02281
02282 if (r_type == R_XTENSA_32)
02283 {
02284 outrel.r_info =
02285 ELF32_R_INFO (h->dynindx, R_XTENSA_GLOB_DAT);
02286 relocation = 0;
02287 }
02288 else
02289 {
02290 outrel.r_info =
02291 ELF32_R_INFO (h->dynindx, R_XTENSA_JMP_SLOT);
02292
02293
02294
02295
02296 relocation =
02297 elf_xtensa_create_plt_entry (dynobj, output_bfd,
02298 srel->reloc_count);
02299 }
02300 unresolved_reloc = FALSE;
02301 }
02302 else
02303 {
02304
02305 outrel.r_info = ELF32_R_INFO (0, R_XTENSA_RELATIVE);
02306 outrel.r_addend = 0;
02307 }
02308 }
02309
02310 loc = (srel->contents
02311 + srel->reloc_count++ * sizeof (Elf32_External_Rela));
02312 bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
02313 BFD_ASSERT (sizeof (Elf32_External_Rela) * srel->reloc_count
02314 <= srel->size);
02315 }
02316 }
02317
02318
02319
02320
02321 if (unresolved_reloc
02322 && !((input_section->flags & SEC_DEBUGGING) != 0
02323 && h->def_dynamic))
02324 (*_bfd_error_handler)
02325 (_("%B(%A+0x%lx): unresolvable relocation against symbol `%s'"),
02326 input_bfd,
02327 input_section,
02328 (long) rel->r_offset,
02329 h->root.root.string);
02330
02331
02332
02333 r = elf_xtensa_do_reloc (howto, input_bfd, input_section,
02334 relocation + rel->r_addend,
02335 contents, rel->r_offset, is_weak_undef,
02336 &error_message);
02337
02338 if (r != bfd_reloc_ok && !warned)
02339 {
02340 const char *name;
02341
02342 BFD_ASSERT (r == bfd_reloc_dangerous || r == bfd_reloc_other);
02343 BFD_ASSERT (error_message != NULL);
02344
02345 if (h)
02346 name = h->root.root.string;
02347 else
02348 {
02349 name = bfd_elf_string_from_elf_section
02350 (input_bfd, symtab_hdr->sh_link, sym->st_name);
02351 if (name && *name == '\0')
02352 name = bfd_section_name (input_bfd, sec);
02353 }
02354 if (name)
02355 {
02356 if (rel->r_addend == 0)
02357 error_message = vsprint_msg (error_message, ": %s",
02358 strlen (name) + 2, name);
02359 else
02360 error_message = vsprint_msg (error_message, ": (%s+0x%x)",
02361 strlen (name) + 22,
02362 name, rel->r_addend);
02363 }
02364
02365 if (!((*info->callbacks->reloc_dangerous)
02366 (info, error_message, input_bfd, input_section,
02367 rel->r_offset)))
02368 return FALSE;
02369 }
02370 }
02371
02372 if (lit_table)
02373 free (lit_table);
02374
02375 input_section->reloc_done = TRUE;
02376
02377 return TRUE;
02378 }
02379
02380
02381
02382
02383
02384 static bfd_boolean
02385 elf_xtensa_finish_dynamic_symbol (bfd *output_bfd ATTRIBUTE_UNUSED,
02386 struct bfd_link_info *info ATTRIBUTE_UNUSED,
02387 struct elf_link_hash_entry *h,
02388 Elf_Internal_Sym *sym)
02389 {
02390 if (h->needs_plt
02391 && !h->def_regular)
02392 {
02393
02394
02395 sym->st_shndx = SHN_UNDEF;
02396 }
02397
02398
02399 if (strcmp (h->root.root.string, "_DYNAMIC") == 0
02400 || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
02401 sym->st_shndx = SHN_ABS;
02402
02403 return TRUE;
02404 }
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415 static int
02416 elf_xtensa_combine_prop_entries (bfd *output_bfd,
02417 asection *sxtlit,
02418 asection *sgotloc)
02419 {
02420 bfd_byte *contents;
02421 property_table_entry *table;
02422 bfd_size_type section_size, sgotloc_size;
02423 bfd_vma offset;
02424 int n, m, num;
02425
02426 section_size = sxtlit->size;
02427 BFD_ASSERT (section_size % 8 == 0);
02428 num = section_size / 8;
02429
02430 sgotloc_size = sgotloc->size;
02431 if (sgotloc_size != section_size)
02432 {
02433 (*_bfd_error_handler)
02434 (_("internal inconsistency in size of .got.loc section"));
02435 return -1;
02436 }
02437
02438 table = bfd_malloc (num * sizeof (property_table_entry));
02439 if (table == 0)
02440 return -1;
02441
02442
02443
02444
02445 sxtlit->flags &= ~SEC_IN_MEMORY;
02446
02447 if (!bfd_malloc_and_get_section (output_bfd, sxtlit, &contents))
02448 {
02449 if (contents != 0)
02450 free (contents);
02451 free (table);
02452 return -1;
02453 }
02454
02455
02456
02457
02458
02459 offset = 0;
02460 for (n = 0; n < num; n++)
02461 {
02462 table[n].address = bfd_get_32 (output_bfd, &contents[offset]);
02463 table[n].size = bfd_get_32 (output_bfd, &contents[offset + 4]);
02464 offset += 8;
02465 }
02466 qsort (table, num, sizeof (property_table_entry), property_table_compare);
02467
02468 for (n = 0; n < num; n++)
02469 {
02470 bfd_boolean remove = FALSE;
02471
02472 if (table[n].size == 0)
02473 remove = TRUE;
02474 else if (n > 0 &&
02475 (table[n-1].address + table[n-1].size == table[n].address))
02476 {
02477 table[n-1].size += table[n].size;
02478 remove = TRUE;
02479 }
02480
02481 if (remove)
02482 {
02483 for (m = n; m < num - 1; m++)
02484 {
02485 table[m].address = table[m+1].address;
02486 table[m].size = table[m+1].size;
02487 }
02488
02489 n--;
02490 num--;
02491 }
02492 }
02493
02494
02495 offset = 0;
02496 for (n = 0; n < num; n++)
02497 {
02498 bfd_put_32 (output_bfd, table[n].address, &contents[offset]);
02499 bfd_put_32 (output_bfd, table[n].size, &contents[offset + 4]);
02500 offset += 8;
02501 }
02502
02503
02504 if ((bfd_size_type) (num * 8) < section_size)
02505 memset (&contents[num * 8], 0, section_size - num * 8);
02506
02507 if (! bfd_set_section_contents (output_bfd, sxtlit, contents, 0,
02508 section_size))
02509 return -1;
02510
02511
02512 memcpy (sgotloc->contents, contents, section_size);
02513
02514 free (contents);
02515 free (table);
02516 return num;
02517 }
02518
02519
02520
02521
02522 static bfd_boolean
02523 elf_xtensa_finish_dynamic_sections (bfd *output_bfd,
02524 struct bfd_link_info *info)
02525 {
02526 bfd *dynobj;
02527 asection *sdyn, *srelplt, *sgot, *sxtlit, *sgotloc;
02528 Elf32_External_Dyn *dyncon, *dynconend;
02529 int num_xtlit_entries;
02530
02531 if (! elf_hash_table (info)->dynamic_sections_created)
02532 return TRUE;
02533
02534 dynobj = elf_hash_table (info)->dynobj;
02535 sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
02536 BFD_ASSERT (sdyn != NULL);
02537
02538
02539
02540 sgot = bfd_get_section_by_name (dynobj, ".got");
02541 if (sgot)
02542 {
02543 BFD_ASSERT (sgot->size == 4);
02544 if (sdyn == NULL)
02545 bfd_put_32 (output_bfd, 0, sgot->contents);
02546 else
02547 bfd_put_32 (output_bfd,
02548 sdyn->output_section->vma + sdyn->output_offset,
02549 sgot->contents);
02550 }
02551
02552 srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
02553 if (srelplt && srelplt->size != 0)
02554 {
02555 asection *sgotplt, *srelgot, *spltlittbl;
02556 int chunk, plt_chunks, plt_entries;
02557 Elf_Internal_Rela irela;
02558 bfd_byte *loc;
02559 unsigned rtld_reloc;
02560
02561 srelgot = bfd_get_section_by_name (dynobj, ".rela.got");;
02562 BFD_ASSERT (srelgot != NULL);
02563
02564 spltlittbl = bfd_get_section_by_name (dynobj, ".xt.lit.plt");
02565 BFD_ASSERT (spltlittbl != NULL);
02566
02567
02568
02569 for (rtld_reloc = 0; rtld_reloc < srelgot->reloc_count; rtld_reloc++)
02570 {
02571 loc = srelgot->contents + rtld_reloc * sizeof (Elf32_External_Rela);
02572 bfd_elf32_swap_reloca_in (output_bfd, loc, &irela);
02573 if (ELF32_R_TYPE (irela.r_info) == R_XTENSA_RTLD)
02574 break;
02575 }
02576 BFD_ASSERT (rtld_reloc < srelgot->reloc_count);
02577
02578 plt_entries = srelplt->size / sizeof (Elf32_External_Rela);
02579 plt_chunks =
02580 (plt_entries + PLT_ENTRIES_PER_CHUNK - 1) / PLT_ENTRIES_PER_CHUNK;
02581
02582 for (chunk = 0; chunk < plt_chunks; chunk++)
02583 {
02584 int chunk_entries = 0;
02585
02586 sgotplt = elf_xtensa_get_gotplt_section (dynobj, chunk);
02587 BFD_ASSERT (sgotplt != NULL);
02588
02589
02590
02591
02592 loc = srelgot->contents + rtld_reloc * sizeof (Elf32_External_Rela);
02593 bfd_elf32_swap_reloca_in (output_bfd, loc, &irela);
02594 BFD_ASSERT (ELF32_R_TYPE (irela.r_info) == R_XTENSA_RTLD);
02595 irela.r_offset = (sgotplt->output_section->vma
02596 + sgotplt->output_offset);
02597 irela.r_addend = 1;
02598 bfd_elf32_swap_reloca_out (output_bfd, &irela, loc);
02599 rtld_reloc += 1;
02600 BFD_ASSERT (rtld_reloc <= srelgot->reloc_count);
02601
02602
02603 loc += sizeof (Elf32_External_Rela);
02604 bfd_elf32_swap_reloca_in (output_bfd, loc, &irela);
02605 BFD_ASSERT (ELF32_R_TYPE (irela.r_info) == R_XTENSA_RTLD);
02606 irela.r_offset = (sgotplt->output_section->vma
02607 + sgotplt->output_offset + 4);
02608
02609 irela.r_addend = 2;
02610 bfd_elf32_swap_reloca_out (output_bfd, &irela, loc);
02611 rtld_reloc += 1;
02612 BFD_ASSERT (rtld_reloc <= srelgot->reloc_count);
02613
02614
02615 if (chunk < plt_chunks - 1)
02616 chunk_entries = PLT_ENTRIES_PER_CHUNK;
02617 else
02618 chunk_entries = plt_entries - (chunk * PLT_ENTRIES_PER_CHUNK);
02619
02620 BFD_ASSERT ((unsigned) (chunk + 1) * 8 <= spltlittbl->size);
02621 bfd_put_32 (output_bfd,
02622 sgotplt->output_section->vma + sgotplt->output_offset,
02623 spltlittbl->contents + (chunk * 8) + 0);
02624 bfd_put_32 (output_bfd,
02625 8 + (chunk_entries * 4),
02626 spltlittbl->contents + (chunk * 8) + 4);
02627 }
02628
02629
02630
02631 if (srelgot->size != (sizeof (Elf32_External_Rela)
02632 * srelgot->reloc_count)
02633 || srelplt->size != (sizeof (Elf32_External_Rela)
02634 * srelplt->reloc_count))
02635 abort ();
02636
02637
02638
02639
02640
02641 if (! bfd_set_section_contents (output_bfd,
02642 spltlittbl->output_section,
02643 spltlittbl->contents,
02644 spltlittbl->output_offset,
02645 spltlittbl->size))
02646 return FALSE;
02647
02648 spltlittbl->flags &= ~SEC_HAS_CONTENTS;
02649 }
02650
02651
02652 BFD_ASSERT (! info->relocatable);
02653 sxtlit = bfd_get_section_by_name (output_bfd, ".xt.lit");
02654 sgotloc = bfd_get_section_by_name (dynobj, ".got.loc");
02655 BFD_ASSERT (sxtlit && sgotloc);
02656 num_xtlit_entries =
02657 elf_xtensa_combine_prop_entries (output_bfd, sxtlit, sgotloc);
02658 if (num_xtlit_entries < 0)
02659 return FALSE;
02660
02661 dyncon = (Elf32_External_Dyn *) sdyn->contents;
02662 dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
02663 for (; dyncon < dynconend; dyncon++)
02664 {
02665 Elf_Internal_Dyn dyn;
02666 const char *name;
02667 asection *s;
02668
02669 bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
02670
02671 switch (dyn.d_tag)
02672 {
02673 default:
02674 break;
02675
02676 case DT_XTENSA_GOT_LOC_SZ:
02677 dyn.d_un.d_val = num_xtlit_entries;
02678 break;
02679
02680 case DT_XTENSA_GOT_LOC_OFF:
02681 name = ".got.loc";
02682 goto get_vma;
02683 case DT_PLTGOT:
02684 name = ".got";
02685 goto get_vma;
02686 case DT_JMPREL:
02687 name = ".rela.plt";
02688 get_vma:
02689 s = bfd_get_section_by_name (output_bfd, name);
02690 BFD_ASSERT (s);
02691 dyn.d_un.d_ptr = s->vma;
02692 break;
02693
02694 case DT_PLTRELSZ:
02695 s = bfd_get_section_by_name (output_bfd, ".rela.plt");
02696 BFD_ASSERT (s);
02697 dyn.d_un.d_val = s->size;
02698 break;
02699
02700 case DT_RELASZ:
02701
02702
02703
02704
02705
02706
02707 s = bfd_get_section_by_name (output_bfd, ".rela.plt");
02708 if (s)
02709 dyn.d_un.d_val -= s->size;
02710 break;
02711 }
02712
02713 bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
02714 }
02715
02716 return TRUE;
02717 }
02718
02719
02720
02721
02722
02723
02724
02725 static bfd_boolean
02726 elf_xtensa_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
02727 {
02728 unsigned out_mach, in_mach;
02729 flagword out_flag, in_flag;
02730
02731
02732 if (!_bfd_generic_verify_endian_match (ibfd, obfd))
02733 return FALSE;
02734
02735
02736 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
02737 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
02738 return FALSE;
02739
02740 out_flag = elf_elfheader (obfd)->e_flags;
02741 in_flag = elf_elfheader (ibfd)->e_flags;
02742
02743 out_mach = out_flag & EF_XTENSA_MACH;
02744 in_mach = in_flag & EF_XTENSA_MACH;
02745 if (out_mach != in_mach)
02746 {
02747 (*_bfd_error_handler)
02748 (_("%B: incompatible machine type. Output is 0x%x. Input is 0x%x"),
02749 ibfd, out_mach, in_mach);
02750 bfd_set_error (bfd_error_wrong_format);
02751 return FALSE;
02752 }
02753
02754 if (! elf_flags_init (obfd))
02755 {
02756 elf_flags_init (obfd) = TRUE;
02757 elf_elfheader (obfd)->e_flags = in_flag;
02758
02759 if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
02760 && bfd_get_arch_info (obfd)->the_default)
02761 return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
02762 bfd_get_mach (ibfd));
02763
02764 return TRUE;
02765 }
02766
02767 if ((out_flag & EF_XTENSA_XT_INSN) != (in_flag & EF_XTENSA_XT_INSN))
02768 elf_elfheader (obfd)->e_flags &= (~ EF_XTENSA_XT_INSN);
02769
02770 if ((out_flag & EF_XTENSA_XT_LIT) != (in_flag & EF_XTENSA_XT_LIT))
02771 elf_elfheader (obfd)->e_flags &= (~ EF_XTENSA_XT_LIT);
02772
02773 return TRUE;
02774 }
02775
02776
02777 static bfd_boolean
02778 elf_xtensa_set_private_flags (bfd *abfd, flagword flags)
02779 {
02780 BFD_ASSERT (!elf_flags_init (abfd)
02781 || elf_elfheader (abfd)->e_flags == flags);
02782
02783 elf_elfheader (abfd)->e_flags |= flags;
02784 elf_flags_init (abfd) = TRUE;
02785
02786 return TRUE;
02787 }
02788
02789
02790 static bfd_boolean
02791 elf_xtensa_print_private_bfd_data (bfd *abfd, void *farg)
02792 {
02793 FILE *f = (FILE *) farg;
02794 flagword e_flags = elf_elfheader (abfd)->e_flags;
02795
02796 fprintf (f, "\nXtensa header:\n");
02797 if ((e_flags & EF_XTENSA_MACH) == E_XTENSA_MACH)
02798 fprintf (f, "\nMachine = Base\n");
02799 else
02800 fprintf (f, "\nMachine Id = 0x%x\n", e_flags & EF_XTENSA_MACH);
02801
02802 fprintf (f, "Insn tables = %s\n",
02803 (e_flags & EF_XTENSA_XT_INSN) ? "true" : "false");
02804
02805 fprintf (f, "Literal tables = %s\n",
02806 (e_flags & EF_XTENSA_XT_LIT) ? "true" : "false");
02807
02808 return _bfd_elf_print_private_bfd_data (abfd, farg);
02809 }
02810
02811
02812
02813
02814 static bfd_boolean
02815 elf_xtensa_object_p (bfd *abfd)
02816 {
02817 int mach;
02818 unsigned long arch = elf_elfheader (abfd)->e_flags & EF_XTENSA_MACH;
02819
02820 switch (arch)
02821 {
02822 case E_XTENSA_MACH:
02823 mach = bfd_mach_xtensa;
02824 break;
02825 default:
02826 return FALSE;
02827 }
02828
02829 (void) bfd_default_set_arch_mach (abfd, bfd_arch_xtensa, mach);
02830 return TRUE;
02831 }
02832
02833
02834
02835
02836
02837
02838 static void
02839 elf_xtensa_final_write_processing (bfd *abfd,
02840 bfd_boolean linker ATTRIBUTE_UNUSED)
02841 {
02842 int mach;
02843 unsigned long val;
02844
02845 switch (mach = bfd_get_mach (abfd))
02846 {
02847 case bfd_mach_xtensa:
02848 val = E_XTENSA_MACH;
02849 break;
02850 default:
02851 return;
02852 }
02853
02854 elf_elfheader (abfd)->e_flags &= (~ EF_XTENSA_MACH);
02855 elf_elfheader (abfd)->e_flags |= val;
02856 }
02857
02858
02859 static enum elf_reloc_type_class
02860 elf_xtensa_reloc_type_class (const Elf_Internal_Rela *rela)
02861 {
02862 switch ((int) ELF32_R_TYPE (rela->r_info))
02863 {
02864 case R_XTENSA_RELATIVE:
02865 return reloc_class_relative;
02866 case R_XTENSA_JMP_SLOT:
02867 return reloc_class_plt;
02868 default:
02869 return reloc_class_normal;
02870 }
02871 }
02872
02873
02874 static bfd_boolean
02875 elf_xtensa_discard_info_for_section (bfd *abfd,
02876 struct elf_reloc_cookie *cookie,
02877 struct bfd_link_info *info,
02878 asection *sec)
02879 {
02880 bfd_byte *contents;
02881 bfd_vma section_size;
02882 bfd_vma offset, actual_offset;
02883 size_t removed_bytes = 0;
02884
02885 section_size = sec->size;
02886 if (section_size == 0 || section_size % 8 != 0)
02887 return FALSE;
02888
02889 if (sec->output_section
02890 && bfd_is_abs_section (sec->output_section))
02891 return FALSE;
02892
02893 contents = retrieve_contents (abfd, sec, info->keep_memory);
02894 if (!contents)
02895 return FALSE;
02896
02897 cookie->rels = retrieve_internal_relocs (abfd, sec, info->keep_memory);
02898 if (!cookie->rels)
02899 {
02900 release_contents (sec, contents);
02901 return FALSE;
02902 }
02903
02904 cookie->rel = cookie->rels;
02905 cookie->relend = cookie->rels + sec->reloc_count;
02906
02907 for (offset = 0; offset < section_size; offset += 8)
02908 {
02909 actual_offset = offset - removed_bytes;
02910
02911
02912
02913 while (cookie->rel < cookie->relend
02914 && cookie->rel->r_offset < offset)
02915 {
02916 cookie->rel->r_offset -= removed_bytes;
02917 cookie->rel++;
02918 }
02919
02920 while (cookie->rel < cookie->relend
02921 && cookie->rel->r_offset == offset)
02922 {
02923 if (bfd_elf_reloc_symbol_deleted_p (offset, cookie))
02924 {
02925
02926
02927
02928 if (ELF32_R_TYPE (cookie->rel->r_info) != R_XTENSA_NONE)
02929 {
02930
02931 if (offset + 8 < section_size)
02932 memmove (&contents[actual_offset],
02933 &contents[actual_offset+8],
02934 section_size - offset - 8);
02935 removed_bytes += 8;
02936 }
02937
02938
02939 cookie->rel->r_info = ELF32_R_INFO (0, R_XTENSA_NONE);
02940 }
02941
02942
02943
02944
02945
02946
02947 if (cookie->rel->r_offset >= removed_bytes)
02948 cookie->rel->r_offset -= removed_bytes;
02949 else
02950 cookie->rel->r_offset = 0;
02951
02952 cookie->rel++;
02953 }
02954 }
02955
02956 if (removed_bytes != 0)
02957 {
02958
02959 for (; cookie->rel < cookie->relend; cookie->rel++)
02960 {
02961 if (cookie->rel->r_offset >= removed_bytes)
02962 cookie->rel->r_offset -= removed_bytes;
02963 else
02964 cookie->rel->r_offset = 0;
02965 }
02966
02967
02968 memset (&contents[section_size - removed_bytes], 0, removed_bytes);
02969
02970 pin_contents (sec, contents);
02971 pin_internal_relocs (sec, cookie->rels);
02972
02973
02974 sec->size = section_size - removed_bytes;
02975
02976 if (xtensa_is_littable_section (sec))
02977 {
02978 bfd *dynobj = elf_hash_table (info)->dynobj;
02979 if (dynobj)
02980 {
02981 asection *sgotloc =
02982 bfd_get_section_by_name (dynobj, ".got.loc");
02983 if (sgotloc)
02984 sgotloc->size -= removed_bytes;
02985 }
02986 }
02987 }
02988 else
02989 {
02990 release_contents (sec, contents);
02991 release_internal_relocs (sec, cookie->rels);
02992 }
02993
02994 return (removed_bytes != 0);
02995 }
02996
02997
02998 static bfd_boolean
02999 elf_xtensa_discard_info (bfd *abfd,
03000 struct elf_reloc_cookie *cookie,
03001 struct bfd_link_info *info)
03002 {
03003 asection *sec;
03004 bfd_boolean changed = FALSE;
03005
03006 for (sec = abfd->sections; sec != NULL; sec = sec->next)
03007 {
03008 if (xtensa_is_property_section (sec))
03009 {
03010 if (elf_xtensa_discard_info_for_section (abfd, cookie, info, sec))
03011 changed = TRUE;
03012 }
03013 }
03014
03015 return changed;
03016 }
03017
03018
03019 static bfd_boolean
03020 elf_xtensa_ignore_discarded_relocs (asection *sec)
03021 {
03022 return xtensa_is_property_section (sec);
03023 }
03024
03025
03026
03027
03028 static bfd_boolean
03029 elf_xtensa_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
03030 {
03031 int offset;
03032 unsigned int size;
03033
03034
03035
03036
03037
03038 elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
03039
03040
03041 elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24);
03042
03043
03044 offset = 72;
03045 size = note->descsz - offset - 4;
03046
03047
03048 return _bfd_elfcore_make_pseudosection (abfd, ".reg",
03049 size, note->descpos + offset);
03050 }
03051
03052
03053 static bfd_boolean
03054 elf_xtensa_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
03055 {
03056 switch (note->descsz)
03057 {
03058 default:
03059 return FALSE;
03060
03061 case 128:
03062 elf_tdata (abfd)->core_program
03063 = _bfd_elfcore_strndup (abfd, note->descdata + 32, 16);
03064 elf_tdata (abfd)->core_command
03065 = _bfd_elfcore_strndup (abfd, note->descdata + 48, 80);
03066 }
03067
03068
03069
03070
03071
03072 {
03073 char *command = elf_tdata (abfd)->core_command;
03074 int n = strlen (command);
03075
03076 if (0 < n && command[n - 1] == ' ')
03077 command[n - 1] = '\0';
03078 }
03079
03080 return TRUE;
03081 }
03082
03083
03084
03085
03086 static xtensa_opcode callx0_op = XTENSA_UNDEFINED;
03087 static xtensa_opcode callx4_op = XTENSA_UNDEFINED;
03088 static xtensa_opcode callx8_op = XTENSA_UNDEFINED;
03089 static xtensa_opcode callx12_op = XTENSA_UNDEFINED;
03090 static xtensa_opcode call0_op = XTENSA_UNDEFINED;
03091 static xtensa_opcode call4_op = XTENSA_UNDEFINED;
03092 static xtensa_opcode call8_op = XTENSA_UNDEFINED;
03093 static xtensa_opcode call12_op = XTENSA_UNDEFINED;
03094
03095 static void
03096 init_call_opcodes (void)
03097 {
03098 if (callx0_op == XTENSA_UNDEFINED)
03099 {
03100 callx0_op = xtensa_opcode_lookup (xtensa_default_isa, "callx0");
03101 callx4_op = xtensa_opcode_lookup (xtensa_default_isa, "callx4");
03102 callx8_op = xtensa_opcode_lookup (xtensa_default_isa, "callx8");
03103 callx12_op = xtensa_opcode_lookup (xtensa_default_isa, "callx12");
03104 call0_op = xtensa_opcode_lookup (xtensa_default_isa, "call0");
03105 call4_op = xtensa_opcode_lookup (xtensa_default_isa, "call4");
03106 call8_op = xtensa_opcode_lookup (xtensa_default_isa, "call8");
03107 call12_op = xtensa_opcode_lookup (xtensa_default_isa, "call12");
03108 }
03109 }
03110
03111
03112 static bfd_boolean
03113 is_indirect_call_opcode (xtensa_opcode opcode)
03114 {
03115 init_call_opcodes ();
03116 return (opcode == callx0_op
03117 || opcode == callx4_op
03118 || opcode == callx8_op
03119 || opcode == callx12_op);
03120 }
03121
03122
03123 static bfd_boolean
03124 is_direct_call_opcode (xtensa_opcode opcode)
03125 {
03126 init_call_opcodes ();
03127 return (opcode == call0_op
03128 || opcode == call4_op
03129 || opcode == call8_op
03130 || opcode == call12_op);
03131 }
03132
03133
03134 static bfd_boolean
03135 is_windowed_call_opcode (xtensa_opcode opcode)
03136 {
03137 init_call_opcodes ();
03138 return (opcode == call4_op
03139 || opcode == call8_op
03140 || opcode == call12_op
03141 || opcode == callx4_op
03142 || opcode == callx8_op
03143 || opcode == callx12_op);
03144 }
03145
03146
03147 static xtensa_opcode
03148 get_const16_opcode (void)
03149 {
03150 static bfd_boolean done_lookup = FALSE;
03151 static xtensa_opcode const16_opcode = XTENSA_UNDEFINED;
03152 if (!done_lookup)
03153 {
03154 const16_opcode = xtensa_opcode_lookup (xtensa_default_isa, "const16");
03155 done_lookup = TRUE;
03156 }
03157 return const16_opcode;
03158 }
03159
03160
03161 static xtensa_opcode
03162 get_l32r_opcode (void)
03163 {
03164 static xtensa_opcode l32r_opcode = XTENSA_UNDEFINED;
03165 static bfd_boolean done_lookup = FALSE;
03166
03167 if (!done_lookup)
03168 {
03169 l32r_opcode = xtensa_opcode_lookup (xtensa_default_isa, "l32r");
03170 done_lookup = TRUE;
03171 }
03172 return l32r_opcode;
03173 }
03174
03175
03176 static bfd_vma
03177 l32r_offset (bfd_vma addr, bfd_vma pc)
03178 {
03179 bfd_vma offset;
03180
03181 offset = addr - ((pc+3) & -4);
03182 BFD_ASSERT ((offset & ((1 << 2) - 1)) == 0);
03183 offset = (signed int) offset >> 2;
03184 BFD_ASSERT ((signed int) offset >> 16 == -1);
03185 return offset;
03186 }
03187
03188
03189 static int
03190 get_relocation_opnd (xtensa_opcode opcode, int r_type)
03191 {
03192 xtensa_isa isa = xtensa_default_isa;
03193 int last_immed, last_opnd, opi;
03194
03195 if (opcode == XTENSA_UNDEFINED)
03196 return XTENSA_UNDEFINED;
03197
03198
03199
03200
03201 last_immed = XTENSA_UNDEFINED;
03202 last_opnd = xtensa_opcode_num_operands (isa, opcode);
03203 for (opi = last_opnd - 1; opi >= 0; opi--)
03204 {
03205 if (xtensa_operand_is_visible (isa, opcode, opi) == 0)
03206 continue;
03207 if (xtensa_operand_is_PCrelative (isa, opcode, opi) == 1)
03208 {
03209 last_immed = opi;
03210 break;
03211 }
03212 if (last_immed == XTENSA_UNDEFINED
03213 && xtensa_operand_is_register (isa, opcode, opi) == 0)
03214 last_immed = opi;
03215 }
03216 if (last_immed < 0)
03217 return XTENSA_UNDEFINED;
03218
03219
03220
03221 if (r_type >= R_XTENSA_OP0 && r_type <= R_XTENSA_OP2)
03222 {
03223 int reloc_opnd = r_type - R_XTENSA_OP0;
03224 if (reloc_opnd != last_immed)
03225 return XTENSA_UNDEFINED;
03226 }
03227
03228 return last_immed;
03229 }
03230
03231
03232 int
03233 get_relocation_slot (int r_type)
03234 {
03235 switch (r_type)
03236 {
03237 case R_XTENSA_OP0:
03238 case R_XTENSA_OP1:
03239 case R_XTENSA_OP2:
03240 return 0;
03241
03242 default:
03243 if (r_type >= R_XTENSA_SLOT0_OP && r_type <= R_XTENSA_SLOT14_OP)
03244 return r_type - R_XTENSA_SLOT0_OP;
03245 if (r_type >= R_XTENSA_SLOT0_ALT && r_type <= R_XTENSA_SLOT14_ALT)
03246 return r_type - R_XTENSA_SLOT0_ALT;
03247 break;
03248 }
03249
03250 return XTENSA_UNDEFINED;
03251 }
03252
03253
03254
03255
03256 static xtensa_opcode
03257 get_relocation_opcode (bfd *abfd,
03258 asection *sec,
03259 bfd_byte *contents,
03260 Elf_Internal_Rela *irel)
03261 {
03262 static xtensa_insnbuf ibuff = NULL;
03263 static xtensa_insnbuf sbuff = NULL;
03264 xtensa_isa isa = xtensa_default_isa;
03265 xtensa_format fmt;
03266 int slot;
03267
03268 if (contents == NULL)
03269 return XTENSA_UNDEFINED;
03270
03271 if (bfd_get_section_limit (abfd, sec) <= irel->r_offset)
03272 return XTENSA_UNDEFINED;
03273
03274 if (ibuff == NULL)
03275 {
03276 ibuff = xtensa_insnbuf_alloc (isa);
03277 sbuff = xtensa_insnbuf_alloc (isa);
03278 }
03279
03280
03281 xtensa_insnbuf_from_chars (isa, ibuff, &contents[irel->r_offset],
03282 sec->size - irel->r_offset);
03283 fmt = xtensa_format_decode (isa, ibuff);
03284 slot = get_relocation_slot (ELF32_R_TYPE (irel->r_info));
03285 if (slot == XTENSA_UNDEFINED)
03286 return XTENSA_UNDEFINED;
03287 xtensa_format_get_slot (isa, fmt, slot, ibuff, sbuff);
03288 return xtensa_opcode_decode (isa, fmt, slot, sbuff);
03289 }
03290
03291
03292 bfd_boolean
03293 is_l32r_relocation (bfd *abfd,
03294 asection *sec,
03295 bfd_byte *contents,
03296 Elf_Internal_Rela *irel)
03297 {
03298 xtensa_opcode opcode;
03299 if (!is_operand_relocation (ELF32_R_TYPE (irel->r_info)))
03300 return FALSE;
03301 opcode = get_relocation_opcode (abfd, sec, contents, irel);
03302 return (opcode == get_l32r_opcode ());
03303 }
03304
03305
03306 static bfd_size_type
03307 get_asm_simplify_size (bfd_byte *contents,
03308 bfd_size_type content_len,
03309 bfd_size_type offset)
03310 {
03311 bfd_size_type insnlen, size = 0;
03312
03313
03314 insnlen = insn_decode_len (contents, content_len, offset);
03315 if (insnlen == 0)
03316 return 0;
03317
03318 size += insnlen;
03319
03320 insnlen = insn_decode_len (contents, content_len, offset + size);
03321 if (insnlen == 0)
03322 return 0;
03323
03324 size += insnlen;
03325 return size;
03326 }
03327
03328
03329 bfd_boolean
03330 is_alt_relocation (int r_type)
03331 {
03332 return (r_type >= R_XTENSA_SLOT0_ALT
03333 && r_type <= R_XTENSA_SLOT14_ALT);
03334 }
03335
03336
03337 bfd_boolean
03338 is_operand_relocation (int r_type)
03339 {
03340 switch (r_type)
03341 {
03342 case R_XTENSA_OP0:
03343 case R_XTENSA_OP1:
03344 case R_XTENSA_OP2:
03345 return TRUE;
03346
03347 default:
03348 if (r_type >= R_XTENSA_SLOT0_OP && r_type <= R_XTENSA_SLOT14_OP)
03349 return TRUE;
03350 if (r_type >= R_XTENSA_SLOT0_ALT && r_type <= R_XTENSA_SLOT14_ALT)
03351 return TRUE;
03352 break;
03353 }
03354
03355 return FALSE;
03356 }
03357
03358
03359 #define MIN_INSN_LENGTH 2
03360
03361
03362
03363 bfd_size_type
03364 insn_decode_len (bfd_byte *contents,
03365 bfd_size_type content_len,
03366 bfd_size_type offset)
03367 {
03368 int insn_len;
03369 xtensa_isa isa = xtensa_default_isa;
03370 xtensa_format fmt;
03371 static xtensa_insnbuf ibuff = NULL;
03372
03373 if (offset + MIN_INSN_LENGTH > content_len)
03374 return 0;
03375
03376 if (ibuff == NULL)
03377 ibuff = xtensa_insnbuf_alloc (isa);
03378 xtensa_insnbuf_from_chars (isa, ibuff, &contents[offset],
03379 content_len - offset);
03380 fmt = xtensa_format_decode (isa, ibuff);
03381 if (fmt == XTENSA_UNDEFINED)
03382 return 0;
03383 insn_len = xtensa_format_length (isa, fmt);
03384 if (insn_len == XTENSA_UNDEFINED)
03385 return 0;
03386 return insn_len;
03387 }
03388
03389
03390
03391
03392
03393 xtensa_opcode
03394 insn_decode_opcode (bfd_byte *contents,
03395 bfd_size_type content_len,
03396 bfd_size_type offset,
03397 int slot)
03398 {
03399 xtensa_isa isa = xtensa_default_isa;
03400 xtensa_format fmt;
03401 static xtensa_insnbuf insnbuf = NULL;
03402 static xtensa_insnbuf slotbuf = NULL;
03403
03404 if (offset + MIN_INSN_LENGTH > content_len)
03405 return XTENSA_UNDEFINED;
03406
03407 if (insnbuf == NULL)
03408 {
03409 insnbuf = xtensa_insnbuf_alloc (isa);
03410 slotbuf = xtensa_insnbuf_alloc (isa);
03411 }
03412
03413 xtensa_insnbuf_from_chars (isa, insnbuf, &contents[offset],
03414 content_len - offset);
03415 fmt = xtensa_format_decode (isa, insnbuf);
03416 if (fmt == XTENSA_UNDEFINED)
03417 return XTENSA_UNDEFINED;
03418
03419 if (slot >= xtensa_format_num_slots (isa, fmt))
03420 return XTENSA_UNDEFINED;
03421
03422 xtensa_format_get_slot (isa, fmt, slot, insnbuf, slotbuf);
03423 return xtensa_opcode_decode (isa, fmt, slot, slotbuf);
03424 }
03425
03426
03427
03428
03429
03430 static bfd_boolean
03431 check_branch_target_aligned (bfd_byte *contents,
03432 bfd_size_type content_length,
03433 bfd_vma offset,
03434 bfd_vma address)
03435 {
03436 bfd_size_type insn_len = insn_decode_len (contents, content_length, offset);
03437 if (insn_len == 0)
03438 return FALSE;
03439 return check_branch_target_aligned_address (address, insn_len);
03440 }
03441
03442
03443 static bfd_boolean
03444 check_loop_aligned (bfd_byte *contents,
03445 bfd_size_type content_length,
03446 bfd_vma offset,
03447 bfd_vma address)
03448 {
03449 bfd_size_type loop_len, insn_len;
03450 xtensa_opcode opcode =
03451 insn_decode_opcode (contents, content_length, offset, 0);
03452 BFD_ASSERT (opcode != XTENSA_UNDEFINED);
03453 if (opcode != XTENSA_UNDEFINED)
03454 return FALSE;
03455 BFD_ASSERT (xtensa_opcode_is_loop (xtensa_default_isa, opcode));
03456 if (!xtensa_opcode_is_loop (xtensa_default_isa, opcode))
03457 return FALSE;
03458
03459 loop_len = insn_decode_len (contents, content_length, offset);
03460 BFD_ASSERT (loop_len != 0);
03461 if (loop_len == 0)
03462 return FALSE;
03463
03464 insn_len = insn_decode_len (contents, content_length, offset + loop_len);
03465 BFD_ASSERT (insn_len != 0);
03466 if (insn_len == 0)
03467 return FALSE;
03468
03469 return check_branch_target_aligned_address (address + loop_len, insn_len);
03470 }
03471
03472
03473 static bfd_boolean
03474 check_branch_target_aligned_address (bfd_vma addr, int len)
03475 {
03476 if (len == 8)
03477 return (addr % 8 == 0);
03478 return ((addr >> 2) == ((addr + len - 1) >> 2));
03479 }
03480
03481
03482
03483
03484
03485
03486
03487
03488
03489
03490 static xtensa_format *op_single_fmt_table = NULL;
03491
03492
03493 static void
03494 init_op_single_format_table (void)
03495 {
03496 xtensa_isa isa = xtensa_default_isa;
03497 xtensa_insnbuf ibuf;
03498 xtensa_opcode opcode;
03499 xtensa_format fmt;
03500 int num_opcodes;
03501
03502 if (op_single_fmt_table)
03503 return;
03504
03505 ibuf = xtensa_insnbuf_alloc (isa);
03506 num_opcodes = xtensa_isa_num_opcodes (isa);
03507
03508 op_single_fmt_table = (xtensa_format *)
03509 bfd_malloc (sizeof (xtensa_format) * num_opcodes);
03510 for (opcode = 0; opcode < num_opcodes; opcode++)
03511 {
03512 op_single_fmt_table[opcode] = XTENSA_UNDEFINED;
03513 for (fmt = 0; fmt < xtensa_isa_num_formats (isa); fmt++)
03514 {
03515 if (xtensa_format_num_slots (isa, fmt) == 1
03516 && xtensa_opcode_encode (isa, fmt, 0, ibuf, opcode) == 0)
03517 {
03518 xtensa_opcode old_fmt = op_single_fmt_table[opcode];
03519 int fmt_length = xtensa_format_length (isa, fmt);
03520 if (old_fmt == XTENSA_UNDEFINED
03521 || fmt_length < xtensa_format_length (isa, old_fmt))
03522 op_single_fmt_table[opcode] = fmt;
03523 }
03524 }
03525 }
03526 xtensa_insnbuf_free (isa, ibuf);
03527 }
03528
03529
03530 static xtensa_format
03531 get_single_format (xtensa_opcode opcode)
03532 {
03533 init_op_single_format_table ();
03534 return op_single_fmt_table[opcode];
03535 }
03536
03537
03538
03539
03540
03541
03542
03543
03544 struct string_pair
03545 {
03546 const char *wide;
03547 const char *narrow;
03548 };
03549
03550 struct string_pair narrowable[] =
03551 {
03552 { "add", "add.n" },
03553 { "addi", "addi.n" },
03554 { "addmi", "addi.n" },
03555 { "l32i", "l32i.n" },
03556 { "movi", "movi.n" },
03557 { "ret", "ret.n" },
03558 { "retw", "retw.n" },
03559 { "s32i", "s32i.n" },
03560 { "or", "mov.n" }
03561 };
03562
03563 struct string_pair widenable[] =
03564 {
03565 { "add", "add.n" },
03566 { "addi", "addi.n" },
03567 { "addmi", "addi.n" },
03568 { "beqz", "beqz.n" },
03569 { "bnez", "bnez.n" },
03570 { "l32i", "l32i.n" },
03571 { "movi", "movi.n" },
03572 { "ret", "ret.n" },
03573 { "retw", "retw.n" },
03574 { "s32i", "s32i.n" },
03575 { "or", "mov.n" }
03576 };
03577
03578
03579
03580
03581
03582
03583
03584
03585 static bfd_boolean
03586 narrow_instruction (bfd_byte *contents,
03587 bfd_size_type content_length,
03588 bfd_size_type offset,
03589 bfd_boolean do_it)
03590 {
03591 xtensa_opcode opcode;
03592 bfd_size_type insn_len, opi;
03593 xtensa_isa isa = xtensa_default_isa;
03594 xtensa_format fmt, o_fmt;
03595
03596 static xtensa_insnbuf insnbuf = NULL;
03597 static xtensa_insnbuf slotbuf = NULL;
03598 static xtensa_insnbuf o_insnbuf = NULL;
03599 static xtensa_insnbuf o_slotbuf = NULL;
03600
03601 if (insnbuf == NULL)
03602 {
03603 insnbuf = xtensa_insnbuf_alloc (isa);
03604 slotbuf = xtensa_insnbuf_alloc (isa);
03605 o_insnbuf = xtensa_insnbuf_alloc (isa);
03606 o_slotbuf = xtensa_insnbuf_alloc (isa);
03607 }
03608
03609 BFD_ASSERT (offset < content_length);
03610
03611 if (content_length < 2)
03612 return FALSE;
03613
03614
03615
03616 xtensa_insnbuf_from_chars (isa, insnbuf, &contents[offset],
03617 content_length - offset);
03618 fmt = xtensa_format_decode (isa, insnbuf);
03619 if (xtensa_format_num_slots (isa, fmt) != 1)
03620 return FALSE;
03621
03622 if (xtensa_format_get_slot (isa, fmt, 0, insnbuf, slotbuf) != 0)
03623 return FALSE;
03624
03625 opcode = xtensa_opcode_decode (isa, fmt, 0, slotbuf);
03626 if (opcode == XTENSA_UNDEFINED)
03627 return FALSE;
03628 insn_len = xtensa_format_length (isa, fmt);
03629 if (insn_len > content_length)
03630 return FALSE;
03631
03632 for (opi = 0; opi < (sizeof (narrowable)/sizeof (struct string_pair)); ++opi)
03633 {
03634 bfd_boolean is_or = (strcmp ("or", narrowable[opi].wide) == 0);
03635
03636 if (opcode == xtensa_opcode_lookup (isa, narrowable[opi].wide))
03637 {
03638 uint32 value, newval;
03639 int i, operand_count, o_operand_count;
03640 xtensa_opcode o_opcode;
03641
03642
03643
03644 bfd_vma self_address = 0;
03645
03646 o_opcode = xtensa_opcode_lookup (isa, narrowable[opi].narrow);
03647 if (o_opcode == XTENSA_UNDEFINED)
03648 return FALSE;
03649 o_fmt = get_single_format (o_opcode);
03650 if (o_fmt == XTENSA_UNDEFINED)
03651 return FALSE;
03652
03653 if (xtensa_format_length (isa, fmt) != 3
03654 || xtensa_format_length (isa, o_fmt) != 2)
03655 return FALSE;
03656
03657 xtensa_format_encode (isa, o_fmt, o_insnbuf);
03658 operand_count = xtensa_opcode_num_operands (isa, opcode);
03659 o_operand_count = xtensa_opcode_num_operands (isa, o_opcode);
03660
03661 if (xtensa_opcode_encode (isa, o_fmt, 0, o_slotbuf, o_opcode) != 0)
03662 return FALSE;
03663
03664 if (!is_or)
03665 {
03666 if (xtensa_opcode_num_operands (isa, o_opcode) != operand_count)
03667 return FALSE;
03668 }
03669 else
03670 {
03671 uint32 rawval0, rawval1, rawval2;
03672
03673 if (o_operand_count + 1 != operand_count)
03674 return FALSE;
03675 if (xtensa_operand_get_field (isa, opcode, 0,
03676 fmt, 0, slotbuf, &rawval0) != 0)
03677 return FALSE;
03678 if (xtensa_operand_get_field (isa, opcode, 1,
03679 fmt, 0, slotbuf, &rawval1) != 0)
03680 return FALSE;
03681 if (xtensa_operand_get_field (isa, opcode, 2,
03682 fmt, 0, slotbuf, &rawval2) != 0)
03683 return FALSE;
03684
03685 if (rawval1 != rawval2)
03686 return FALSE;
03687 if (rawval0 == rawval1)
03688 return FALSE;
03689 }
03690
03691 for (i = 0; i < o_operand_count; ++i)
03692 {
03693 if (xtensa_operand_get_field (isa, opcode, i, fmt, 0,
03694 slotbuf, &value)
03695 || xtensa_operand_decode (isa, opcode, i, &value))
03696 return FALSE;
03697
03698
03699
03700 newval = value;
03701 if (xtensa_operand_do_reloc (isa, o_opcode, i, &newval,
03702 self_address)
03703 || xtensa_operand_encode (isa, o_opcode, i, &newval)
03704 || xtensa_operand_set_field (isa, o_opcode, i, o_fmt, 0,
03705 o_slotbuf, newval))
03706 return FALSE;
03707 }
03708
03709 if (xtensa_format_set_slot (isa, o_fmt, 0,
03710 o_insnbuf, o_slotbuf) != 0)
03711 return FALSE;
03712
03713 if (do_it)
03714 xtensa_insnbuf_to_chars (isa, o_insnbuf, contents + offset,
03715 content_length - offset);
03716 return TRUE;
03717 }
03718 }
03719 return FALSE;
03720 }
03721
03722
03723
03724
03725
03726
03727
03728
03729
03730 static bfd_boolean
03731 widen_instruction (bfd_byte *contents,
03732 bfd_size_type content_length,
03733 bfd_size_type offset,
03734 bfd_boolean do_it)
03735 {
03736 xtensa_opcode opcode;
03737 bfd_size_type insn_len, opi;
03738 xtensa_isa isa = xtensa_default_isa;
03739 xtensa_format fmt, o_fmt;
03740
03741 static xtensa_insnbuf insnbuf = NULL;
03742 static xtensa_insnbuf slotbuf = NULL;
03743 static xtensa_insnbuf o_insnbuf = NULL;
03744 static xtensa_insnbuf o_slotbuf = NULL;
03745
03746 if (insnbuf == NULL)
03747 {
03748 insnbuf = xtensa_insnbuf_alloc (isa);
03749 slotbuf = xtensa_insnbuf_alloc (isa);
03750 o_insnbuf = xtensa_insnbuf_alloc (isa);
03751 o_slotbuf = xtensa_insnbuf_alloc (isa);
03752 }
03753
03754 BFD_ASSERT (offset < content_length);
03755
03756 if (content_length < 2)
03757 return FALSE;
03758
03759
03760
03761 xtensa_insnbuf_from_chars (isa, insnbuf, &contents[offset],
03762 content_length - offset);
03763 fmt = xtensa_format_decode (isa, insnbuf);
03764 if (xtensa_format_num_slots (isa, fmt) != 1)
03765 return FALSE;
03766
03767 if (xtensa_format_get_slot (isa, fmt, 0, insnbuf, slotbuf) != 0)
03768 return FALSE;
03769
03770 opcode = xtensa_opcode_decode (isa, fmt, 0, slotbuf);
03771 if (opcode == XTENSA_UNDEFINED)
03772 return FALSE;
03773 insn_len = xtensa_format_length (isa, fmt);
03774 if (insn_len > content_length)
03775 return FALSE;
03776
03777 for (opi = 0; opi < (sizeof (widenable)/sizeof (struct string_pair)); ++opi)
03778 {
03779 bfd_boolean is_or = (strcmp ("or", widenable[opi].wide) == 0);
03780 bfd_boolean is_branch = (strcmp ("beqz", widenable[opi].wide) == 0
03781 || strcmp ("bnez", widenable[opi].wide) == 0);
03782
03783 if (opcode == xtensa_opcode_lookup (isa, widenable[opi].narrow))
03784 {
03785 uint32 value, newval;
03786 int i, operand_count, o_operand_count, check_operand_count;
03787 xtensa_opcode o_opcode;
03788
03789
03790
03791 bfd_vma self_address = 0;
03792
03793 o_opcode = xtensa_opcode_lookup (isa, widenable[opi].wide);
03794 if (o_opcode == XTENSA_UNDEFINED)
03795 return FALSE;
03796 o_fmt = get_single_format (o_opcode);
03797 if (o_fmt == XTENSA_UNDEFINED)
03798 return FALSE;
03799
03800 if (xtensa_format_length (isa, fmt) != 2
03801 || xtensa_format_length (isa, o_fmt) != 3)
03802 return FALSE;
03803
03804 xtensa_format_encode (isa, o_fmt, o_insnbuf);
03805 operand_count = xtensa_opcode_num_operands (isa, opcode);
03806 o_operand_count = xtensa_opcode_num_operands (isa, o_opcode);
03807 check_operand_count = o_operand_count;
03808
03809 if (xtensa_opcode_encode (isa, o_fmt, 0, o_slotbuf, o_opcode) != 0)
03810 return FALSE;
03811
03812 if (!is_or)
03813 {
03814 if (xtensa_opcode_num_operands (isa, o_opcode) != operand_count)
03815 return FALSE;
03816 }
03817 else
03818 {
03819 uint32 rawval0, rawval1;
03820
03821 if (o_operand_count != operand_count + 1)
03822 return FALSE;
03823 if (xtensa_operand_get_field (isa, opcode, 0,
03824 fmt, 0, slotbuf, &rawval0) != 0)
03825 return FALSE;
03826 if (xtensa_operand_get_field (isa, opcode, 1,
03827 fmt, 0, slotbuf, &rawval1) != 0)
03828 return FALSE;
03829 if (rawval0 == rawval1)
03830 return FALSE;
03831 }
03832 if (is_branch)
03833 check_operand_count--;
03834
03835 for (i = 0; i < check_operand_count; ++i)
03836 {
03837 int new_i = i;
03838 if (is_or && i == o_operand_count - 1)
03839 new_i = i - 1;
03840 if (xtensa_operand_get_field (isa, opcode, new_i, fmt, 0,
03841 slotbuf, &value)
03842 || xtensa_operand_decode (isa, opcode, new_i, &value))
03843 return FALSE;
03844
03845
03846
03847 newval = value;
03848 if (xtensa_operand_do_reloc (isa, o_opcode, i, &newval,
03849 self_address)
03850 || xtensa_operand_encode (isa, o_opcode, i, &newval)
03851 || xtensa_operand_set_field (isa, o_opcode, i, o_fmt, 0,
03852 o_slotbuf, newval))
03853 return FALSE;
03854 }
03855
03856 if (xtensa_format_set_slot (isa, o_fmt, 0, o_insnbuf, o_slotbuf))
03857 return FALSE;
03858
03859 if (do_it)
03860 xtensa_insnbuf_to_chars (isa, o_insnbuf, contents + offset,
03861 content_length - offset);
03862 return TRUE;
03863 }
03864 }
03865 return FALSE;
03866 }
03867
03868
03869
03870
03871 static bfd_reloc_status_type
03872 elf_xtensa_do_asm_simplify (bfd_byte *contents,
03873 bfd_vma address,
03874 bfd_vma content_length,
03875 char **error_message)
03876 {
03877 static xtensa_insnbuf insnbuf = NULL;
03878 static xtensa_insnbuf slotbuf = NULL;
03879 xtensa_format core_format = XTENSA_UNDEFINED;
03880 xtensa_opcode opcode;
03881 xtensa_opcode direct_call_opcode;
03882 xtensa_isa isa = xtensa_default_isa;
03883 bfd_byte *chbuf = contents + address;
03884 int opn;
03885
03886 if (insnbuf == NULL)
03887 {
03888 insnbuf = xtensa_insnbuf_alloc (isa);
03889 slotbuf = xtensa_insnbuf_alloc (isa);
03890 }
03891
03892 if (content_length < address)
03893 {
03894 *error_message = _("Attempt to convert L32R/CALLX to CALL failed");
03895 return bfd_reloc_other;
03896 }
03897
03898 opcode = get_expanded_call_opcode (chbuf, content_length - address, 0);
03899 direct_call_opcode = swap_callx_for_call_opcode (opcode);
03900 if (direct_call_opcode == XTENSA_UNDEFINED)
03901 {
03902 *error_message = _("Attempt to convert L32R/CALLX to CALL failed");
03903 return bfd_reloc_other;
03904 }
03905
03906
03907 core_format = xtensa_format_lookup (isa, "x24");
03908 opcode = xtensa_opcode_lookup (isa, "or");
03909 xtensa_opcode_encode (isa, core_format, 0, slotbuf, opcode);
03910 for (opn = 0; opn < 3; opn++)
03911 {
03912 uint32 regno = 1;
03913 xtensa_operand_encode (isa, opcode, opn, ®no);
03914 xtensa_operand_set_field (isa, opcode, opn, core_format, 0,
03915 slotbuf, regno);
03916 }
03917 xtensa_format_encode (isa, core_format, insnbuf);
03918 xtensa_format_set_slot (isa, core_format, 0, insnbuf, slotbuf);
03919 xtensa_insnbuf_to_chars (isa, insnbuf, chbuf, content_length - address);
03920
03921
03922 xtensa_opcode_encode (isa, core_format, 0, slotbuf, direct_call_opcode);
03923 xtensa_operand_set_field (isa, opcode, 0, core_format, 0, slotbuf, 0);
03924
03925 xtensa_format_encode (isa, core_format, insnbuf);
03926 xtensa_format_set_slot (isa, core_format, 0, insnbuf, slotbuf);
03927 xtensa_insnbuf_to_chars (isa, insnbuf, chbuf + 3,
03928 content_length - address - 3);
03929
03930 return bfd_reloc_ok;
03931 }
03932
03933
03934 static bfd_reloc_status_type
03935 contract_asm_expansion (bfd_byte *contents,
03936 bfd_vma content_length,
03937 Elf_Internal_Rela *irel,
03938 char **error_message)
03939 {
03940 bfd_reloc_status_type retval =
03941 elf_xtensa_do_asm_simplify (contents, irel->r_offset, content_length,
03942 error_message);
03943
03944 if (retval != bfd_reloc_ok)
03945 return bfd_reloc_dangerous;
03946
03947
03948
03949 irel->r_offset += 3;
03950 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_XTENSA_SLOT0_OP);
03951 return bfd_reloc_ok;
03952 }
03953
03954
03955 static xtensa_opcode
03956 swap_callx_for_call_opcode (xtensa_opcode opcode)
03957 {
03958 init_call_opcodes ();
03959
03960 if (opcode == callx0_op) return call0_op;
03961 if (opcode == callx4_op) return call4_op;
03962 if (opcode == callx8_op) return call8_op;
03963 if (opcode == callx12_op) return call12_op;
03964
03965
03966 return XTENSA_UNDEFINED;
03967 }
03968
03969
03970
03971
03972
03973
03974 #define L32R_TARGET_REG_OPERAND 0
03975 #define CONST16_TARGET_REG_OPERAND 0
03976 #define CALLN_SOURCE_OPERAND 0
03977
03978 static xtensa_opcode
03979 get_expanded_call_opcode (bfd_byte *buf, int bufsize, bfd_boolean *p_uses_l32r)
03980 {
03981 static xtensa_insnbuf insnbuf = NULL;
03982 static xtensa_insnbuf slotbuf = NULL;
03983 xtensa_format fmt;
03984 xtensa_opcode opcode;
03985 xtensa_isa isa = xtensa_default_isa;
03986 uint32 regno, const16_regno, call_regno;
03987 int offset = 0;
03988
03989 if (insnbuf == NULL)
03990 {
03991 insnbuf = xtensa_insnbuf_alloc (isa);
03992 slotbuf = xtensa_insnbuf_alloc (isa);
03993 }
03994
03995 xtensa_insnbuf_from_chars (isa, insnbuf, buf, bufsize);
03996 fmt = xtensa_format_decode (isa, insnbuf);
03997 if (fmt == XTENSA_UNDEFINED
03998 || xtensa_format_get_slot (isa, fmt, 0, insnbuf, slotbuf))
03999 return XTENSA_UNDEFINED;
04000
04001 opcode = xtensa_opcode_decode (isa, fmt, 0, slotbuf);
04002 if (opcode == XTENSA_UNDEFINED)
04003 return XTENSA_UNDEFINED;
04004
04005 if (opcode == get_l32r_opcode ())
04006 {
04007 if (p_uses_l32r)
04008 *p_uses_l32r = TRUE;
04009 if (xtensa_operand_get_field (isa, opcode, L32R_TARGET_REG_OPERAND,
04010 fmt, 0, slotbuf, ®no)
04011 || xtensa_operand_decode (isa, opcode, L32R_TARGET_REG_OPERAND,
04012 ®no))
04013 return XTENSA_UNDEFINED;
04014 }
04015 else if (opcode == get_const16_opcode ())
04016 {
04017 if (p_uses_l32r)
04018 *p_uses_l32r = FALSE;
04019 if (xtensa_operand_get_field (isa, opcode, CONST16_TARGET_REG_OPERAND,
04020 fmt, 0, slotbuf, ®no)
04021 || xtensa_operand_decode (isa, opcode, CONST16_TARGET_REG_OPERAND,
04022 ®no))
04023 return XTENSA_UNDEFINED;
04024
04025
04026 offset += xtensa_format_length (isa, fmt);
04027 xtensa_insnbuf_from_chars (isa, insnbuf, buf + offset, bufsize - offset);
04028 fmt = xtensa_format_decode (isa, insnbuf);
04029 if (fmt == XTENSA_UNDEFINED
04030 || xtensa_format_get_slot (isa, fmt, 0, insnbuf, slotbuf))
04031 return XTENSA_UNDEFINED;
04032 opcode = xtensa_opcode_decode (isa, fmt, 0, slotbuf);
04033 if (opcode != get_const16_opcode ())
04034 return XTENSA_UNDEFINED;
04035
04036 if (xtensa_operand_get_field (isa, opcode, CONST16_TARGET_REG_OPERAND,
04037 fmt, 0, slotbuf, &const16_regno)
04038 || xtensa_operand_decode (isa, opcode, CONST16_TARGET_REG_OPERAND,
04039 &const16_regno)
04040 || const16_regno != regno)
04041 return XTENSA_UNDEFINED;
04042 }
04043 else
04044 return XTENSA_UNDEFINED;
04045
04046
04047 offset += xtensa_format_length (isa, fmt);
04048 xtensa_insnbuf_from_chars (isa, insnbuf, buf + offset, bufsize - offset);
04049 fmt = xtensa_format_decode (isa, insnbuf);
04050 if (fmt == XTENSA_UNDEFINED
04051 || xtensa_format_get_slot (isa, fmt, 0, insnbuf, slotbuf))
04052 return XTENSA_UNDEFINED;
04053 opcode = xtensa_opcode_decode (isa, fmt, 0, slotbuf);
04054 if (opcode == XTENSA_UNDEFINED
04055 || !is_indirect_call_opcode (opcode))
04056 return XTENSA_UNDEFINED;
04057
04058 if (xtensa_operand_get_field (isa, opcode, CALLN_SOURCE_OPERAND,
04059 fmt, 0, slotbuf, &call_regno)
04060 || xtensa_operand_decode (isa, opcode, CALLN_SOURCE_OPERAND,
04061 &call_regno))
04062 return XTENSA_UNDEFINED;
04063
04064 if (call_regno != regno)
04065 return XTENSA_UNDEFINED;
04066
04067 return opcode;
04068 }
04069
04070
04071
04072
04073
04074
04075
04076
04077
04078
04079
04080
04081
04082
04083
04084
04085
04086
04087
04088
04089
04090 typedef struct r_reloc_struct r_reloc;
04091
04092 struct r_reloc_struct
04093 {
04094 bfd *abfd;
04095 Elf_Internal_Rela rela;
04096 bfd_vma target_offset;
04097 bfd_vma virtual_offset;
04098 };
04099
04100
04101
04102
04103
04104
04105
04106
04107 static bfd_boolean
04108 r_reloc_is_const (const r_reloc *r_rel)
04109 {
04110 return (r_rel->abfd == NULL);
04111 }
04112
04113
04114 static bfd_vma
04115 r_reloc_get_target_offset (const r_reloc *r_rel)
04116 {
04117 bfd_vma target_offset;
04118 unsigned long r_symndx;
04119
04120 BFD_ASSERT (!r_reloc_is_const (r_rel));
04121 r_symndx = ELF32_R_SYM (r_rel->rela.r_info);
04122 target_offset = get_elf_r_symndx_offset (r_rel->abfd, r_symndx);
04123 return (target_offset + r_rel->rela.r_addend);
04124 }
04125
04126
04127 static struct elf_link_hash_entry *
04128 r_reloc_get_hash_entry (const r_reloc *r_rel)
04129 {
04130 unsigned long r_symndx = ELF32_R_SYM (r_rel->rela.r_info);
04131 return get_elf_r_symndx_hash_entry (r_rel->abfd, r_symndx);
04132 }
04133
04134
04135 static asection *
04136 r_reloc_get_section (const r_reloc *r_rel)
04137 {
04138 unsigned long r_symndx = ELF32_R_SYM (r_rel->rela.r_info);
04139 return get_elf_r_symndx_section (r_rel->abfd, r_symndx);
04140 }
04141
04142
04143 static bfd_boolean
04144 r_reloc_is_defined (const r_reloc *r_rel)
04145 {
04146 asection *sec;
04147 if (r_rel == NULL)
04148 return FALSE;
04149
04150 sec = r_reloc_get_section (r_rel);
04151 if (sec == bfd_abs_section_ptr
04152 || sec == bfd_com_section_ptr
04153 || sec == bfd_und_section_ptr)
04154 return FALSE;
04155 return TRUE;
04156 }
04157
04158
04159 static void
04160 r_reloc_init (r_reloc *r_rel,
04161 bfd *abfd,
04162 Elf_Internal_Rela *irel,
04163 bfd_byte *contents,
04164 bfd_size_type content_length)
04165 {
04166 int r_type;
04167 reloc_howto_type *howto;
04168
04169 if (irel)
04170 {
04171 r_rel->rela = *irel;
04172 r_rel->abfd = abfd;
04173 r_rel->target_offset = r_reloc_get_target_offset (r_rel);
04174 r_rel->virtual_offset = 0;
04175 r_type = ELF32_R_TYPE (r_rel->rela.r_info);
04176 howto = &elf_howto_table[r_type];
04177 if (howto->partial_inplace)
04178 {
04179 bfd_vma inplace_val;
04180 BFD_ASSERT (r_rel->rela.r_offset < content_length);
04181
04182 inplace_val = bfd_get_32 (abfd, &contents[r_rel->rela.r_offset]);
04183 r_rel->target_offset += inplace_val;
04184 }
04185 }
04186 else
04187 memset (r_rel, 0, sizeof (r_reloc));
04188 }
04189
04190
04191 #if DEBUG
04192
04193 static void
04194 print_r_reloc (FILE *fp, const r_reloc *r_rel)
04195 {
04196 if (r_reloc_is_defined (r_rel))
04197 {
04198 asection *sec = r_reloc_get_section (r_rel);
04199 fprintf (fp, " %s(%s + ", sec->owner->filename, sec->name);
04200 }
04201 else if (r_reloc_get_hash_entry (r_rel))
04202 fprintf (fp, " %s + ", r_reloc_get_hash_entry (r_rel)->root.root.string);
04203 else
04204 fprintf (fp, " ?? + ");
04205
04206 fprintf_vma (fp, r_rel->target_offset);
04207 if (r_rel->virtual_offset)
04208 {
04209 fprintf (fp, " + ");
04210 fprintf_vma (fp, r_rel->virtual_offset);
04211 }
04212
04213 fprintf (fp, ")");
04214 }
04215
04216 #endif
04217
04218
04219
04220
04221
04222
04223
04224
04225
04226
04227
04228
04229
04230
04231
04232
04233
04234
04235
04236 typedef struct source_reloc_struct source_reloc;
04237
04238 struct source_reloc_struct
04239 {
04240 asection *source_sec;
04241 r_reloc r_rel;
04242 xtensa_opcode opcode;
04243 int opnd;
04244 bfd_boolean is_null;
04245 bfd_boolean is_abs_literal;
04246 };
04247
04248
04249 static void
04250 init_source_reloc (source_reloc *reloc,
04251 asection *source_sec,
04252 const r_reloc *r_rel,
04253 xtensa_opcode opcode,
04254 int opnd,
04255 bfd_boolean is_abs_literal)
04256 {
04257 reloc->source_sec = source_sec;
04258 reloc->r_rel = *r_rel;
04259 reloc->opcode = opcode;
04260 reloc->opnd = opnd;
04261 reloc->is_null = FALSE;
04262 reloc->is_abs_literal = is_abs_literal;
04263 }
04264
04265
04266
04267
04268
04269
04270 static source_reloc *
04271 find_source_reloc (source_reloc *src_relocs,
04272 int src_count,
04273 asection *sec,
04274 Elf_Internal_Rela *irel)
04275 {
04276 int i;
04277
04278 for (i = 0; i < src_count; i++)
04279 {
04280 if (src_relocs[i].source_sec == sec
04281 && src_relocs[i].r_rel.rela.r_offset == irel->r_offset
04282 && (ELF32_R_TYPE (src_relocs[i].r_rel.rela.r_info)
04283 == ELF32_R_TYPE (irel->r_info)))
04284 return &src_relocs[i];
04285 }
04286
04287 return NULL;
04288 }
04289
04290
04291 static int
04292 source_reloc_compare (const void *ap, const void *bp)
04293 {
04294 const source_reloc *a = (const source_reloc *) ap;
04295 const source_reloc *b = (const source_reloc *) bp;
04296
04297 if (a->r_rel.target_offset != b->r_rel.target_offset)
04298 return (a->r_rel.target_offset - b->r_rel.target_offset);
04299
04300
04301
04302
04303
04304
04305
04306
04307 if ((!a->is_null) - (!b->is_null))
04308 return ((!a->is_null) - (!b->is_null));
04309 return internal_reloc_compare (&a->r_rel.rela, &b->r_rel.rela);
04310 }
04311
04312
04313
04314
04315
04316
04317
04318
04319
04320
04321
04322
04323
04324
04325
04326 typedef struct literal_value_struct literal_value;
04327 typedef struct value_map_struct value_map;
04328 typedef struct value_map_hash_table_struct value_map_hash_table;
04329
04330 struct literal_value_struct
04331 {
04332 r_reloc r_rel;
04333 unsigned long value;
04334 bfd_boolean is_abs_literal;
04335 };
04336
04337 struct value_map_struct
04338 {
04339 literal_value val;
04340 r_reloc loc;
04341 value_map *next;
04342 };
04343
04344 struct value_map_hash_table_struct
04345 {
04346 unsigned bucket_count;
04347 value_map **buckets;
04348 unsigned count;
04349 bfd_boolean has_last_loc;
04350 r_reloc last_loc;
04351 };
04352
04353
04354 static void
04355 init_literal_value (literal_value *lit,
04356 const r_reloc *r_rel,
04357 unsigned long value,
04358 bfd_boolean is_abs_literal)
04359 {
04360 lit->r_rel = *r_rel;
04361 lit->value = value;
04362 lit->is_abs_literal = is_abs_literal;
04363 }
04364
04365
04366 static bfd_boolean
04367 literal_value_equal (const literal_value *src1,
04368 const literal_value *src2,
04369 bfd_boolean final_static_link)
04370 {
04371 struct elf_link_hash_entry *h1, *h2;
04372
04373 if (r_reloc_is_const (&src1->r_rel) != r_reloc_is_const (&src2->r_rel))
04374 return FALSE;
04375
04376 if (r_reloc_is_const (&src1->r_rel))
04377 return (src1->value == src2->value);
04378
04379 if (ELF32_R_TYPE (src1->r_rel.rela.r_info)
04380 != ELF32_R_TYPE (src2->r_rel.rela.r_info))
04381 return FALSE;
04382
04383 if (src1->r_rel.target_offset != src2->r_rel.target_offset)
04384 return FALSE;
04385
04386 if (src1->r_rel.virtual_offset != src2->r_rel.virtual_offset)
04387 return FALSE;
04388
04389 if (src1->value != src2->value)
04390 return FALSE;
04391
04392
04393
04394 h1 = r_reloc_get_hash_entry (&src1->r_rel);
04395 h2 = r_reloc_get_hash_entry (&src2->r_rel);
04396 if (r_reloc_is_defined (&src1->r_rel)
04397 && (final_static_link
04398 || ((!h1 || h1->root.type != bfd_link_hash_defweak)
04399 && (!h2 || h2->root.type != bfd_link_hash_defweak))))
04400 {
04401 if (r_reloc_get_section (&src1->r_rel)
04402 != r_reloc_get_section (&src2->r_rel))
04403 return FALSE;
04404 }
04405 else
04406 {
04407
04408 if (h1 != h2 || h1 == 0)
04409 return FALSE;
04410 }
04411
04412 if (src1->is_abs_literal != src2->is_abs_literal)
04413 return FALSE;
04414
04415 return TRUE;
04416 }
04417
04418
04419
04420 #define INITIAL_HASH_RELOC_BUCKET_COUNT 1024
04421
04422 static value_map_hash_table *
04423 value_map_hash_table_init (void)
04424 {
04425 value_map_hash_table *values;
04426
04427 values = (value_map_hash_table *)
04428 bfd_zmalloc (sizeof (value_map_hash_table));
04429 values->bucket_count = INITIAL_HASH_RELOC_BUCKET_COUNT;
04430 values->count = 0;
04431 values->buckets = (value_map **)
04432 bfd_zmalloc (sizeof (value_map *) * values->bucket_count);
04433 if (values->buckets == NULL)
04434 {
04435 free (values);
04436 return NULL;
04437 }
04438 values->has_last_loc = FALSE;
04439
04440 return values;
04441 }
04442
04443
04444 static void
04445 value_map_hash_table_delete (value_map_hash_table *table)
04446 {
04447 free (table->buckets);
04448 free (table);
04449 }
04450
04451
04452 static unsigned
04453 hash_bfd_vma (bfd_vma val)
04454 {
04455 return (val >> 2) + (val >> 10);
04456 }
04457
04458
04459 static unsigned
04460 literal_value_hash (const literal_value *src)
04461 {
04462 unsigned hash_val;
04463
04464 hash_val = hash_bfd_vma (src->value);
04465 if (!r_reloc_is_const (&src->r_rel))
04466 {
04467 void *sec_or_hash;
04468
04469 hash_val += hash_bfd_vma (src->is_abs_literal * 1000);
04470 hash_val += hash_bfd_vma (src->r_rel.target_offset);
04471 hash_val += hash_bfd_vma (src->r_rel.virtual_offset);
04472
04473
04474 if (r_reloc_is_defined (&src->r_rel))
04475 sec_or_hash = r_reloc_get_section (&src->r_rel);
04476 else
04477 sec_or_hash = r_reloc_get_hash_entry (&src->r_rel);
04478 hash_val += hash_bfd_vma ((bfd_vma) (size_t) sec_or_hash);
04479 }
04480 return hash_val;
04481 }
04482
04483
04484
04485
04486 static value_map *
04487 value_map_get_cached_value (value_map_hash_table *map,
04488 const literal_value *val,
04489 bfd_boolean final_static_link)
04490 {
04491 value_map *map_e;
04492 value_map *bucket;
04493 unsigned idx;
04494
04495 idx = literal_value_hash (val);
04496 idx = idx & (map->bucket_count - 1);
04497 bucket = map->buckets[idx];
04498 for (map_e = bucket; map_e; map_e = map_e->next)
04499 {
04500 if (literal_value_equal (&map_e->val, val, final_static_link))
04501 return map_e;
04502 }
04503 return NULL;
04504 }
04505
04506
04507
04508
04509
04510 static value_map *
04511 add_value_map (value_map_hash_table *map,
04512 const literal_value *val,
04513 const r_reloc *loc,
04514 bfd_boolean final_static_link)
04515 {
04516 value_map **bucket_p;
04517 unsigned idx;
04518
04519 value_map *val_e = (value_map *) bfd_zmalloc (sizeof (value_map));
04520 if (val_e == NULL)
04521 {
04522 bfd_set_error (bfd_error_no_memory);
04523 return NULL;
04524 }
04525
04526 BFD_ASSERT (!value_map_get_cached_value (map, val, final_static_link));
04527 val_e->val = *val;
04528 val_e->loc = *loc;
04529
04530 idx = literal_value_hash (val);
04531 idx = idx & (map->bucket_count - 1);
04532 bucket_p = &map->buckets[idx];
04533
04534 val_e->next = *bucket_p;
04535 *bucket_p = val_e;
04536 map->count++;
04537
04538
04539 return val_e;
04540 }
04541
04542
04543
04544
04545
04546
04547
04548
04549
04550
04551
04552
04553
04554
04555
04556
04557
04558
04559
04560
04561
04562
04563
04564
04565
04566
04567
04568
04569
04570 typedef struct text_action_struct text_action;
04571 typedef struct text_action_list_struct text_action_list;
04572 typedef enum text_action_enum_t text_action_t;
04573
04574 enum text_action_enum_t
04575 {
04576 ta_none,
04577 ta_remove_insn,
04578 ta_remove_longcall,
04579 ta_convert_longcall,
04580 ta_narrow_insn,
04581 ta_widen_insn,
04582 ta_fill,
04583 ta_remove_literal,
04584 ta_add_literal
04585 };
04586
04587
04588
04589 struct text_action_struct
04590 {
04591 text_action_t action;
04592 asection *sec;
04593 bfd_vma offset;
04594 bfd_vma virtual_offset;
04595 int removed_bytes;
04596 literal_value value;
04597
04598 text_action *next;
04599 };
04600
04601
04602
04603 struct text_action_list_struct
04604 {
04605 text_action *head;
04606 };
04607
04608
04609 static text_action *
04610 find_fill_action (text_action_list *l, asection *sec, bfd_vma offset)
04611 {
04612 text_action **m_p;
04613
04614
04615 if (sec->size == offset)
04616 return NULL;
04617
04618 for (m_p = &l->head; *m_p && (*m_p)->offset <= offset; m_p = &(*m_p)->next)
04619 {
04620 text_action *t = *m_p;
04621
04622
04623 if (t->offset == offset && t->action == ta_fill)
04624 return t;
04625 }
04626 return NULL;
04627 }
04628
04629
04630 static int
04631 compute_removed_action_diff (const text_action *ta,
04632 asection *sec,
04633 bfd_vma offset,
04634 int removed,
04635 int removable_space)
04636 {
04637 int new_removed;
04638 int current_removed = 0;
04639
04640 if (ta)
04641 current_removed = ta->removed_bytes;
04642
04643 BFD_ASSERT (ta == NULL || ta->offset == offset);
04644 BFD_ASSERT (ta == NULL || ta->action == ta_fill);
04645
04646
04647 if (sec->size == offset)
04648 new_removed = removable_space - 0;
04649 else
04650 {
04651 int space;
04652 int added = -removed - current_removed;
04653
04654 added = ((1 << sec->alignment_power) - 1) & added;
04655 new_removed = (-added);
04656
04657
04658 space = removable_space - new_removed;
04659 new_removed = (removable_space
04660 - (((1 << sec->alignment_power) - 1) & space));
04661 }
04662 return (new_removed - current_removed);
04663 }
04664
04665
04666 static void
04667 adjust_fill_action (text_action *ta, int fill_diff)
04668 {
04669 ta->removed_bytes += fill_diff;
04670 }
04671
04672
04673
04674
04675
04676
04677
04678 static void
04679 text_action_add (text_action_list *l,
04680 text_action_t action,
04681 asection *sec,
04682 bfd_vma offset,
04683 int removed)
04684 {
04685 text_action **m_p;
04686 text_action *ta;
04687
04688
04689 if (action == ta_fill && sec->size == offset)
04690 return;
04691
04692
04693 if (action == ta_fill && removed == 0)
04694 return;
04695
04696 for (m_p = &l->head; *m_p && (*m_p)->offset <= offset; m_p = &(*m_p)->next)
04697 {
04698 text_action *t = *m_p;
04699
04700
04701 if (t->offset == offset && t->action == ta_fill && action == ta_fill)
04702 {
04703 t->removed_bytes += removed;
04704 return;
04705 }
04706 }
04707
04708
04709 ta = (text_action *) bfd_zmalloc (sizeof (text_action));
04710 ta->action = action;
04711 ta->sec = sec;
04712 ta->offset = offset;
04713 ta->removed_bytes = removed;
04714 ta->next = (*m_p);
04715 *m_p = ta;
04716 }
04717
04718
04719 static void
04720 text_action_add_literal (text_action_list *l,
04721 text_action_t action,
04722 const r_reloc *loc,
04723 const literal_value *value,
04724 int removed)
04725 {
04726 text_action **m_p;
04727 text_action *ta;
04728 asection *sec = r_reloc_get_section (loc);
04729 bfd_vma offset = loc->target_offset;
04730 bfd_vma virtual_offset = loc->virtual_offset;
04731
04732 BFD_ASSERT (action == ta_add_literal);
04733
04734 for (m_p = &l->head; *m_p != NULL; m_p = &(*m_p)->next)
04735 {
04736 if ((*m_p)->offset > offset
04737 && ((*m_p)->offset != offset
04738 || (*m_p)->virtual_offset > virtual_offset))
04739 break;
04740 }
04741
04742
04743 ta = (text_action *) bfd_zmalloc (sizeof (text_action));
04744 ta->action = action;
04745 ta->sec = sec;
04746 ta->offset = offset;
04747 ta->virtual_offset = virtual_offset;
04748 ta->value = *value;
04749 ta->removed_bytes = removed;
04750 ta->next = (*m_p);
04751 *m_p = ta;
04752 }
04753
04754
04755 static bfd_vma
04756 offset_with_removed_text (text_action_list *action_list, bfd_vma offset)
04757 {
04758 text_action *r;
04759 int removed = 0;
04760
04761 for (r = action_list->head; r && r->offset <= offset; r = r->next)
04762 {
04763 if (r->offset < offset
04764 || (r->action == ta_fill && r->removed_bytes < 0))
04765 removed += r->removed_bytes;
04766 }
04767
04768 return (offset - removed);
04769 }
04770
04771
04772 static bfd_vma
04773 offset_with_removed_text_before_fill (text_action_list *action_list,
04774 bfd_vma offset)
04775 {
04776 text_action *r;
04777 int removed = 0;
04778
04779 for (r = action_list->head; r && r->offset < offset; r = r->next)
04780 removed += r->removed_bytes;
04781
04782 return (offset - removed);
04783 }
04784
04785
04786
04787
04788 static text_action *
04789 find_insn_action (text_action_list *action_list, bfd_vma offset)
04790 {
04791 text_action *t;
04792 for (t = action_list->head; t; t = t->next)
04793 {
04794 if (t->offset == offset)
04795 {
04796 switch (t->action)
04797 {
04798 case ta_none:
04799 case ta_fill:
04800 break;
04801 case ta_remove_insn:
04802 case ta_remove_longcall:
04803 case ta_convert_longcall:
04804 case ta_narrow_insn:
04805 case ta_widen_insn:
04806 return t;
04807 case ta_remove_literal:
04808 case ta_add_literal:
04809 BFD_ASSERT (0);
04810 break;
04811 }
04812 }
04813 }
04814 return NULL;
04815 }
04816
04817
04818 #if DEBUG
04819
04820 static void
04821 print_action_list (FILE *fp, text_action_list *action_list)
04822 {
04823 text_action *r;
04824
04825 fprintf (fp, "Text Action\n");
04826 for (r = action_list->head; r != NULL; r = r->next)
04827 {
04828 const char *t = "unknown";
04829 switch (r->action)
04830 {
04831 case ta_remove_insn:
04832 t = "remove_insn"; break;
04833 case ta_remove_longcall:
04834 t = "remove_longcall"; break;
04835 case ta_convert_longcall:
04836 t = "remove_longcall"; break;
04837 case ta_narrow_insn:
04838 t = "narrow_insn"; break;
04839 case ta_widen_insn:
04840 t = "widen_insn"; break;
04841 case ta_fill:
04842 t = "fill"; break;
04843 case ta_none:
04844 t = "none"; break;
04845 case ta_remove_literal:
04846 t = "remove_literal"; break;
04847 case ta_add_literal:
04848 t = "add_literal"; break;
04849 }
04850
04851 fprintf (fp, "%s: %s[0x%lx] \"%s\" %d\n",
04852 r->sec->owner->filename,
04853 r->sec->name, r->offset, t, r->removed_bytes);
04854 }
04855 }
04856
04857 #endif
04858
04859
04860
04861
04862
04863
04864
04865
04866
04867
04868 typedef struct removed_literal_struct removed_literal;
04869 typedef struct removed_literal_list_struct removed_literal_list;
04870
04871 struct removed_literal_struct
04872 {
04873 r_reloc from;
04874 r_reloc to;
04875 removed_literal *next;
04876 };
04877
04878 struct removed_literal_list_struct
04879 {
04880 removed_literal *head;
04881 removed_literal *tail;
04882 };
04883
04884
04885
04886
04887
04888 static void
04889 add_removed_literal (removed_literal_list *removed_list,
04890 const r_reloc *from,
04891 const r_reloc *to)
04892 {
04893 removed_literal *r, *new_r, *next_r;
04894
04895 new_r = (removed_literal *) bfd_zmalloc (sizeof (removed_literal));
04896
04897 new_r->from = *from;
04898 if (to)
04899 new_r->to = *to;
04900 else
04901 new_r->to.abfd = NULL;
04902 new_r->next = NULL;
04903
04904 r = removed_list->head;
04905 if (r == NULL)
04906 {
04907 removed_list->head = new_r;
04908 removed_list->tail = new_r;
04909 }
04910
04911 else if (removed_list->tail->from.target_offset < from->target_offset)
04912 {
04913 removed_list->tail->next = new_r;
04914 removed_list->tail = new_r;
04915 }
04916 else
04917 {
04918 while (r->from.target_offset < from->target_offset && r->next)
04919 {
04920 r = r->next;
04921 }
04922 next_r = r->next;
04923 r->next = new_r;
04924 new_r->next = next_r;
04925 if (next_r == NULL)
04926 removed_list->tail = new_r;
04927 }
04928 }
04929
04930
04931
04932
04933
04934 static removed_literal *
04935 find_removed_literal (removed_literal_list *removed_list, bfd_vma addr)
04936 {
04937 removed_literal *r = removed_list->head;
04938 while (r && r->from.target_offset < addr)
04939 r = r->next;
04940 if (r && r->from.target_offset == addr)
04941 return r;
04942 return NULL;
04943 }
04944
04945
04946 #if DEBUG
04947
04948 static void
04949 print_removed_literals (FILE *fp, removed_literal_list *removed_list)
04950 {
04951 removed_literal *r;
04952 r = removed_list->head;
04953 if (r)
04954 fprintf (fp, "Removed Literals\n");
04955 for (; r != NULL; r = r->next)
04956 {
04957 print_r_reloc (fp, &r->from);
04958 fprintf (fp, " => ");
04959 if (r->to.abfd == NULL)
04960 fprintf (fp, "REMOVED");
04961 else
04962 print_r_reloc (fp, &r->to);
04963 fprintf (fp, "\n");
04964 }
04965 }
04966
04967 #endif
04968
04969
04970
04971
04972 typedef struct reloc_bfd_fix_struct reloc_bfd_fix;
04973
04974 struct xtensa_relax_info_struct
04975 {
04976 bfd_boolean is_relaxable_literal_section;
04977 bfd_boolean is_relaxable_asm_section;
04978 int visited;
04979
04980 source_reloc *src_relocs;
04981 int src_count;
04982 int src_next;
04983
04984 removed_literal_list removed_list;
04985 text_action_list action_list;
04986
04987 reloc_bfd_fix *fix_list;
04988 reloc_bfd_fix *fix_array;
04989 unsigned fix_array_count;
04990
04991
04992
04993
04994
04995
04996 Elf_Internal_Rela *allocated_relocs;
04997 unsigned relocs_count;
04998 unsigned allocated_relocs_count;
04999 };
05000
05001 struct elf_xtensa_section_data
05002 {
05003 struct bfd_elf_section_data elf;
05004 xtensa_relax_info relax_info;
05005 };
05006
05007
05008 static bfd_boolean
05009 elf_xtensa_new_section_hook (bfd *abfd, asection *sec)
05010 {
05011 struct elf_xtensa_section_data *sdata;
05012 bfd_size_type amt = sizeof (*sdata);
05013
05014 sdata = (struct elf_xtensa_section_data *) bfd_zalloc (abfd, amt);
05015 if (sdata == NULL)
05016 return FALSE;
05017 sec->used_by_bfd = (void *) sdata;
05018
05019 return _bfd_elf_new_section_hook (abfd, sec);
05020 }
05021
05022
05023 static xtensa_relax_info *
05024 get_xtensa_relax_info (asection *sec)
05025 {
05026 struct elf_xtensa_section_data *section_data;
05027
05028
05029 if (!sec || sec == sec->output_section)
05030 return NULL;
05031
05032 section_data = (struct elf_xtensa_section_data *) elf_section_data (sec);
05033 return §ion_data->relax_info;
05034 }
05035
05036
05037 static void
05038 init_xtensa_relax_info (asection *sec)
05039 {
05040 xtensa_relax_info *relax_info = get_xtensa_relax_info (sec);
05041
05042 relax_info->is_relaxable_literal_section = FALSE;
05043 relax_info->is_relaxable_asm_section = FALSE;
05044 relax_info->visited = 0;
05045
05046 relax_info->src_relocs = NULL;
05047 relax_info->src_count = 0;
05048 relax_info->src_next = 0;
05049
05050 relax_info->removed_list.head = NULL;
05051 relax_info->removed_list.tail = NULL;
05052
05053 relax_info->action_list.head = NULL;
05054
05055 relax_info->fix_list = NULL;
05056 relax_info->fix_array = NULL;
05057 relax_info->fix_array_count = 0;
05058
05059 relax_info->allocated_relocs = NULL;
05060 relax_info->relocs_count = 0;
05061 relax_info->allocated_relocs_count = 0;
05062 }
05063
05064
05065
05066
05067
05068
05069
05070
05071
05072
05073
05074 struct reloc_bfd_fix_struct
05075 {
05076 asection *src_sec;
05077 bfd_vma src_offset;
05078 unsigned src_type;
05079
05080 bfd *target_abfd;
05081 asection *target_sec;
05082 bfd_vma target_offset;
05083 bfd_boolean translated;
05084
05085 reloc_bfd_fix *next;
05086 };
05087
05088
05089 static reloc_bfd_fix *
05090 reloc_bfd_fix_init (asection *src_sec,
05091 bfd_vma src_offset,
05092 unsigned src_type,
05093 bfd *target_abfd,
05094 asection *target_sec,
05095 bfd_vma target_offset,
05096 bfd_boolean translated)
05097 {
05098 reloc_bfd_fix *fix;
05099
05100 fix = (reloc_bfd_fix *) bfd_malloc (sizeof (reloc_bfd_fix));
05101 fix->src_sec = src_sec;
05102 fix->src_offset = src_offset;
05103 fix->src_type = src_type;
05104 fix->target_abfd = target_abfd;
05105 fix->target_sec = target_sec;
05106 fix->target_offset = target_offset;
05107 fix->translated = translated;
05108
05109 return fix;
05110 }
05111
05112
05113 static void
05114 add_fix (asection *src_sec, reloc_bfd_fix *fix)
05115 {
05116 xtensa_relax_info *relax_info;
05117
05118 relax_info = get_xtensa_relax_info (src_sec);
05119 fix->next = relax_info->fix_list;
05120 relax_info->fix_list = fix;
05121 }
05122
05123
05124 static int
05125 fix_compare (const void *ap, const void *bp)
05126 {
05127 const reloc_bfd_fix *a = (const reloc_bfd_fix *) ap;
05128 const reloc_bfd_fix *b = (const reloc_bfd_fix *) bp;
05129
05130 if (a->src_offset != b->src_offset)
05131 return (a->src_offset - b->src_offset);
05132 return (a->src_type - b->src_type);
05133 }
05134
05135
05136 static void
05137 cache_fix_array (asection *sec)
05138 {
05139 unsigned i, count = 0;
05140 reloc_bfd_fix *r;
05141 xtensa_relax_info *relax_info = get_xtensa_relax_info (sec);
05142
05143 if (relax_info == NULL)
05144 return;
05145 if (relax_info->fix_list == NULL)
05146 return;
05147
05148 for (r = relax_info->fix_list; r != NULL; r = r->next)
05149 count++;
05150
05151 relax_info->fix_array =
05152 (reloc_bfd_fix *) bfd_malloc (sizeof (reloc_bfd_fix) * count);
05153 relax_info->fix_array_count = count;
05154
05155 r = relax_info->fix_list;
05156 for (i = 0; i < count; i++, r = r->next)
05157 {
05158 relax_info->fix_array[count - 1 - i] = *r;
05159 relax_info->fix_array[count - 1 - i].next = NULL;
05160 }
05161
05162 qsort (relax_info->fix_array, relax_info->fix_array_count,
05163 sizeof (reloc_bfd_fix), fix_compare);
05164 }
05165
05166
05167 static reloc_bfd_fix *
05168 get_bfd_fix (asection *sec, bfd_vma offset, unsigned type)
05169 {
05170 xtensa_relax_info *relax_info = get_xtensa_relax_info (sec);
05171 reloc_bfd_fix *rv;
05172 reloc_bfd_fix key;
05173
05174 if (relax_info == NULL)
05175 return NULL;
05176 if (relax_info->fix_list == NULL)
05177 return NULL;
05178
05179 if (relax_info->fix_array == NULL)
05180 cache_fix_array (sec);
05181
05182 key.src_offset = offset;
05183 key.src_type = type;
05184 rv = bsearch (&key, relax_info->fix_array, relax_info->fix_array_count,
05185 sizeof (reloc_bfd_fix), fix_compare);
05186 return rv;
05187 }
05188
05189
05190
05191
05192 typedef struct section_cache_struct section_cache_t;
05193
05194 struct section_cache_struct
05195 {
05196 asection *sec;
05197
05198 bfd_byte *contents;
05199 bfd_size_type content_length;
05200
05201 property_table_entry *ptbl;
05202 unsigned pte_count;
05203
05204 Elf_Internal_Rela *relocs;
05205 unsigned reloc_count;
05206 };
05207
05208
05209 static void
05210 init_section_cache (section_cache_t *sec_cache)
05211 {
05212 memset (sec_cache, 0, sizeof (*sec_cache));
05213 }
05214
05215
05216 static void
05217 clear_section_cache (section_cache_t *sec_cache)
05218 {
05219 if (sec_cache->sec)
05220 {
05221 release_contents (sec_cache->sec, sec_cache->contents);
05222 release_internal_relocs (sec_cache->sec, sec_cache->relocs);
05223 if (sec_cache->ptbl)
05224 free (sec_cache->ptbl);
05225 memset (sec_cache, 0, sizeof (sec_cache));
05226 }
05227 }
05228
05229
05230 static bfd_boolean
05231 section_cache_section (section_cache_t *sec_cache,
05232 asection *sec,
05233 struct bfd_link_info *link_info)
05234 {
05235 bfd *abfd;
05236 property_table_entry *prop_table = NULL;
05237 int ptblsize = 0;
05238 bfd_byte *contents = NULL;
05239 Elf_Internal_Rela *internal_relocs = NULL;
05240 bfd_size_type sec_size;
05241
05242 if (sec == NULL)
05243 return FALSE;
05244 if (sec == sec_cache->sec)
05245 return TRUE;
05246
05247 abfd = sec->owner;
05248 sec_size = bfd_get_section_limit (abfd, sec);
05249
05250
05251 contents = retrieve_contents (abfd, sec, link_info->keep_memory);
05252 if (contents == NULL && sec_size != 0)
05253 goto err;
05254
05255
05256 internal_relocs = retrieve_internal_relocs (abfd, sec,
05257 link_info->keep_memory);
05258
05259
05260 ptblsize = xtensa_read_table_entries (abfd, sec, &prop_table,
05261 XTENSA_PROP_SEC_NAME, FALSE);
05262 if (ptblsize < 0)
05263 goto err;
05264
05265
05266 clear_section_cache (sec_cache);
05267 memset (sec_cache, 0, sizeof (sec_cache));
05268
05269 sec_cache->sec = sec;
05270 sec_cache->contents = contents;
05271 sec_cache->content_length = sec_size;
05272 sec_cache->relocs = internal_relocs;
05273 sec_cache->reloc_count = sec->reloc_count;
05274 sec_cache->pte_count = ptblsize;
05275 sec_cache->ptbl = prop_table;
05276
05277 return TRUE;
05278
05279 err:
05280 release_contents (sec, contents);
05281 release_internal_relocs (sec, internal_relocs);
05282 if (prop_table)
05283 free (prop_table);
05284 return FALSE;
05285 }
05286
05287
05288
05289
05290
05291
05292
05293
05294
05295
05296
05297
05298
05299 typedef struct ebb_struct ebb_t;
05300
05301 struct ebb_struct
05302 {
05303 asection *sec;
05304
05305 bfd_byte *contents;
05306 bfd_size_type content_length;
05307
05308 property_table_entry *ptbl;
05309 unsigned pte_count;
05310
05311 Elf_Internal_Rela *relocs;
05312 unsigned reloc_count;
05313
05314 bfd_vma start_offset;
05315 unsigned start_ptbl_idx;
05316 unsigned start_reloc_idx;
05317
05318 bfd_vma end_offset;
05319 unsigned end_ptbl_idx;
05320 unsigned end_reloc_idx;
05321
05322 bfd_boolean ends_section;
05323
05324
05325
05326 property_table_entry *ends_unreachable;
05327 };
05328
05329
05330 enum ebb_target_enum
05331 {
05332 EBB_NO_ALIGN = 0,
05333 EBB_DESIRE_TGT_ALIGN,
05334 EBB_REQUIRE_TGT_ALIGN,
05335 EBB_REQUIRE_LOOP_ALIGN,
05336 EBB_REQUIRE_ALIGN
05337 };
05338
05339
05340
05341
05342
05343
05344
05345
05346
05347
05348 typedef struct proposed_action_struct proposed_action;
05349
05350 struct proposed_action_struct
05351 {
05352 enum ebb_target_enum align_type;
05353 bfd_vma alignment_pow;
05354 text_action_t action;
05355 bfd_vma offset;
05356 int removed_bytes;
05357 bfd_boolean do_action;
05358 };
05359
05360
05361
05362
05363
05364 typedef struct ebb_constraint_struct ebb_constraint;
05365
05366 struct ebb_constraint_struct
05367 {
05368 ebb_t ebb;
05369 bfd_boolean start_movable;
05370
05371
05372 int start_extra_space;
05373
05374 enum ebb_target_enum start_align;
05375
05376 bfd_boolean end_movable;
05377
05378
05379 int end_extra_space;
05380
05381 unsigned action_count;
05382 unsigned action_allocated;
05383
05384
05385 proposed_action *actions;
05386
05387
05388 enum ebb_target_enum *action_aligns;
05389 };
05390
05391
05392 static void
05393 init_ebb_constraint (ebb_constraint *c)
05394 {
05395 memset (c, 0, sizeof (ebb_constraint));
05396 }
05397
05398
05399 static void
05400 free_ebb_constraint (ebb_constraint *c)
05401 {
05402 if (c->actions)
05403 free (c->actions);
05404 }
05405
05406
05407 static void
05408 init_ebb (ebb_t *ebb,
05409 asection *sec,
05410 bfd_byte *contents,
05411 bfd_size_type content_length,
05412 property_table_entry *prop_table,
05413 unsigned ptblsize,
05414 Elf_Internal_Rela *internal_relocs,
05415 unsigned reloc_count)
05416 {
05417 memset (ebb, 0, sizeof (ebb_t));
05418 ebb->sec = sec;
05419 ebb->contents = contents;
05420 ebb->content_length = content_length;
05421 ebb->ptbl = prop_table;
05422 ebb->pte_count = ptblsize;
05423 ebb->relocs = internal_relocs;
05424 ebb->reloc_count = reloc_count;
05425 ebb->start_offset = 0;
05426 ebb->end_offset = ebb->content_length - 1;
05427 ebb->start_ptbl_idx = 0;
05428 ebb->end_ptbl_idx = ptblsize;
05429 ebb->start_reloc_idx = 0;
05430 ebb->end_reloc_idx = reloc_count;
05431 }
05432
05433
05434
05435
05436
05437
05438
05439
05440 static bfd_boolean extend_ebb_bounds_forward (ebb_t *);
05441 static bfd_boolean extend_ebb_bounds_backward (ebb_t *);
05442 static bfd_size_type insn_block_decodable_len
05443 (bfd_byte *, bfd_size_type, bfd_vma, bfd_size_type);
05444
05445 static bfd_boolean
05446 extend_ebb_bounds (ebb_t *ebb)
05447 {
05448 if (!extend_ebb_bounds_forward (ebb))
05449 return FALSE;
05450 if (!extend_ebb_bounds_backward (ebb))
05451 return FALSE;
05452 return TRUE;
05453 }
05454
05455
05456 static bfd_boolean
05457 extend_ebb_bounds_forward (ebb_t *ebb)
05458 {
05459 property_table_entry *the_entry, *new_entry;
05460
05461 the_entry = &ebb->ptbl[ebb->end_ptbl_idx];
05462
05463
05464
05465
05466
05467 while (1)
05468 {
05469 bfd_vma entry_end;
05470 bfd_size_type insn_block_len;
05471
05472 entry_end = the_entry->address - ebb->sec->vma + the_entry->size;
05473 insn_block_len =
05474 insn_block_decodable_len (ebb->contents, ebb->content_length,
05475 ebb->end_offset,
05476 entry_end - ebb->end_offset);
05477 if (insn_block_len != (entry_end - ebb->end_offset))
05478 {
05479 (*_bfd_error_handler)
05480 (_("%B(%A+0x%lx): could not decode instruction; possible configuration mismatch"),
05481 ebb->sec->owner, ebb->sec, ebb->end_offset + insn_block_len);
05482 return FALSE;
05483 }
05484 ebb->end_offset += insn_block_len;
05485
05486 if (ebb->end_offset == ebb->sec->size)
05487 ebb->ends_section = TRUE;
05488
05489
05490 while (ebb->end_reloc_idx + 1 < ebb->reloc_count
05491 && (ebb->relocs[ebb->end_reloc_idx + 1].r_offset
05492 < ebb->end_offset))
05493 {
05494 ebb->end_reloc_idx++;
05495 }
05496
05497 if (ebb->end_ptbl_idx + 1 == ebb->pte_count)
05498 return TRUE;
05499
05500 new_entry = &ebb->ptbl[ebb->end_ptbl_idx + 1];
05501 if (((new_entry->flags & XTENSA_PROP_INSN) == 0)
05502 || ((new_entry->flags & XTENSA_PROP_INSN_NO_TRANSFORM) != 0)
05503 || ((the_entry->flags & XTENSA_PROP_ALIGN) != 0))
05504 break;
05505
05506 if (the_entry->address + the_entry->size != new_entry->address)
05507 break;
05508
05509 the_entry = new_entry;
05510 ebb->end_ptbl_idx++;
05511 }
05512
05513
05514 if (ebb->end_ptbl_idx + 1 == ebb->pte_count)
05515 {
05516 if (ebb->end_offset == ebb->content_length)
05517 ebb->ends_section = TRUE;
05518 }
05519 else
05520 {
05521 new_entry = &ebb->ptbl[ebb->end_ptbl_idx + 1];
05522 if ((new_entry->flags & XTENSA_PROP_UNREACHABLE) != 0
05523 && the_entry->address + the_entry->size == new_entry->address)
05524 ebb->ends_unreachable = new_entry;
05525 }
05526
05527
05528 return TRUE;
05529 }
05530
05531
05532 static bfd_boolean
05533 extend_ebb_bounds_backward (ebb_t *ebb)
05534 {
05535 property_table_entry *the_entry, *new_entry;
05536
05537 the_entry = &ebb->ptbl[ebb->start_ptbl_idx];
05538
05539
05540
05541
05542
05543 while (1)
05544 {
05545 bfd_vma block_begin;
05546 bfd_size_type insn_block_len;
05547
05548 block_begin = the_entry->address - ebb->sec->vma;
05549 insn_block_len =
05550 insn_block_decodable_len (ebb->contents, ebb->content_length,
05551 block_begin,
05552 ebb->start_offset - block_begin);
05553 if (insn_block_len != ebb->start_offset - block_begin)
05554 {
05555 (*_bfd_error_handler)
05556 (_("%B(%A+0x%lx): could not decode instruction; possible configuration mismatch"),
05557 ebb->sec->owner, ebb->sec, ebb->end_offset + insn_block_len);
05558 return FALSE;
05559 }
05560 ebb->start_offset -= insn_block_len;
05561
05562
05563 while (ebb->start_reloc_idx > 0
05564 && (ebb->relocs[ebb->start_reloc_idx - 1].r_offset
05565 >= ebb->start_offset))
05566 {
05567 ebb->start_reloc_idx--;
05568 }
05569
05570 if (ebb->start_ptbl_idx == 0)
05571 return TRUE;
05572
05573 new_entry = &ebb->ptbl[ebb->start_ptbl_idx - 1];
05574 if ((new_entry->flags & XTENSA_PROP_INSN) == 0
05575 || ((new_entry->flags & XTENSA_PROP_INSN_NO_TRANSFORM) != 0)
05576 || ((new_entry->flags & XTENSA_PROP_ALIGN) != 0))
05577 return TRUE;
05578 if (new_entry->address + new_entry->size != the_entry->address)
05579 return TRUE;
05580
05581 the_entry = new_entry;
05582 ebb->start_ptbl_idx--;
05583 }
05584 return TRUE;
05585 }
05586
05587
05588 static bfd_size_type
05589 insn_block_decodable_len (bfd_byte *contents,
05590 bfd_size_type content_len,
05591 bfd_vma block_offset,
05592 bfd_size_type block_len)
05593 {
05594 bfd_vma offset = block_offset;
05595
05596 while (offset < block_offset + block_len)
05597 {
05598 bfd_size_type insn_len = 0;
05599
05600 insn_len = insn_decode_len (contents, content_len, offset);
05601 if (insn_len == 0)
05602 return (offset - block_offset);
05603 offset += insn_len;
05604 }
05605 return (offset - block_offset);
05606 }
05607
05608
05609 static void
05610 ebb_propose_action (ebb_constraint *c,
05611 enum ebb_target_enum align_type,
05612 bfd_vma alignment_pow,
05613 text_action_t action,
05614 bfd_vma offset,
05615 int removed_bytes,
05616 bfd_boolean do_action)
05617 {
05618 proposed_action *act;
05619
05620 if (c->action_allocated <= c->action_count)
05621 {
05622 unsigned new_allocated, i;
05623 proposed_action *new_actions;
05624
05625 new_allocated = (c->action_count + 2) * 2;
05626 new_actions = (proposed_action *)
05627 bfd_zmalloc (sizeof (proposed_action) * new_allocated);
05628
05629 for (i = 0; i < c->action_count; i++)
05630 new_actions[i] = c->actions[i];
05631 if (c->actions)
05632 free (c->actions);
05633 c->actions = new_actions;
05634 c->action_allocated = new_allocated;
05635 }
05636
05637 act = &c->actions[c->action_count];
05638 act->align_type = align_type;
05639 act->alignment_pow = alignment_pow;
05640 act->action = action;
05641 act->offset = offset;
05642 act->removed_bytes = removed_bytes;
05643 act->do_action = do_action;
05644
05645 c->action_count++;
05646 }
05647
05648
05649
05650
05651
05652
05653
05654
05655
05656
05657
05658 static Elf_Internal_Rela *
05659 retrieve_internal_relocs (bfd *abfd, asection *sec, bfd_boolean keep_memory)
05660 {
05661 Elf_Internal_Rela *internal_relocs;
05662
05663 if ((sec->flags & SEC_LINKER_CREATED) != 0)
05664 return NULL;
05665
05666 internal_relocs = elf_section_data (sec)->relocs;
05667 if (internal_relocs == NULL)
05668 internal_relocs = (_bfd_elf_link_read_relocs
05669 (abfd, sec, NULL, NULL, keep_memory));
05670 return internal_relocs;
05671 }
05672
05673
05674 static void
05675 pin_internal_relocs (asection *sec, Elf_Internal_Rela *internal_relocs)
05676 {
05677 elf_section_data (sec)->relocs = internal_relocs;
05678 }
05679
05680
05681 static void
05682 release_internal_relocs (asection *sec, Elf_Internal_Rela *internal_relocs)
05683 {
05684 if (internal_relocs
05685 && elf_section_data (sec)->relocs != internal_relocs)
05686 free (internal_relocs);
05687 }
05688
05689
05690 static bfd_byte *
05691 retrieve_contents (bfd *abfd, asection *sec, bfd_boolean keep_memory)
05692 {
05693 bfd_byte *contents;
05694 bfd_size_type sec_size;
05695
05696 sec_size = bfd_get_section_limit (abfd, sec);
05697 contents = elf_section_data (sec)->this_hdr.contents;
05698
05699 if (contents == NULL && sec_size != 0)
05700 {
05701 if (!bfd_malloc_and_get_section (abfd, sec, &contents))
05702 {
05703 if (contents)
05704 free (contents);
05705 return NULL;
05706 }
05707 if (keep_memory)
05708 elf_section_data (sec)->this_hdr.contents = contents;
05709 }
05710 return contents;
05711 }
05712
05713
05714 static void
05715 pin_contents (asection *sec, bfd_byte *contents)
05716 {
05717 elf_section_data (sec)->this_hdr.contents = contents;
05718 }
05719
05720
05721 static void
05722 release_contents (asection *sec, bfd_byte *contents)
05723 {
05724 if (contents && elf_section_data (sec)->this_hdr.contents != contents)
05725 free (contents);
05726 }
05727
05728
05729 static Elf_Internal_Sym *
05730 retrieve_local_syms (bfd *input_bfd)
05731 {
05732 Elf_Internal_Shdr *symtab_hdr;
05733 Elf_Internal_Sym *isymbuf;
05734 size_t locsymcount;
05735
05736 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
05737 locsymcount = symtab_hdr->sh_info;
05738
05739 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
05740 if (isymbuf == NULL && locsymcount != 0)
05741 isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, locsymcount, 0,
05742 NULL, NULL, NULL);
05743
05744
05745 if (isymbuf && isymbuf != (Elf_Internal_Sym *) symtab_hdr->contents)
05746 symtab_hdr->contents = (unsigned char *) isymbuf;
05747
05748 return isymbuf;
05749 }
05750
05751
05752
05753
05754
05755 static bfd_boolean analyze_relocations (struct bfd_link_info *);
05756 static bfd_boolean find_relaxable_sections
05757 (bfd *, asection *, struct bfd_link_info *, bfd_boolean *);
05758 static bfd_boolean collect_source_relocs
05759 (bfd *, asection *, struct bfd_link_info *);
05760 static bfd_boolean is_resolvable_asm_expansion
05761 (bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, struct bfd_link_info *,
05762 bfd_boolean *);
05763 static Elf_Internal_Rela *find_associated_l32r_irel
05764 (bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Rela *);
05765 static bfd_boolean compute_text_actions
05766 (bfd *, asection *, struct bfd_link_info *);
05767 static bfd_boolean compute_ebb_proposed_actions (ebb_constraint *);
05768 static bfd_boolean compute_ebb_actions (ebb_constraint *);
05769 static bfd_boolean check_section_ebb_pcrels_fit
05770 (bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, const ebb_constraint *);
05771 static bfd_boolean check_section_ebb_reduces (const ebb_constraint *);
05772 static void text_action_add_proposed
05773 (text_action_list *, const ebb_constraint *, asection *);
05774 static int compute_fill_extra_space (property_table_entry *);
05775
05776
05777 static bfd_boolean compute_removed_literals
05778 (bfd *, asection *, struct bfd_link_info *, value_map_hash_table *);
05779 static Elf_Internal_Rela *get_irel_at_offset
05780 (asection *, Elf_Internal_Rela *, bfd_vma);
05781 static bfd_boolean is_removable_literal
05782 (const source_reloc *, int, const source_reloc *, int);
05783 static bfd_boolean remove_dead_literal
05784 (bfd *, asection *, struct bfd_link_info *, Elf_Internal_Rela *,
05785 Elf_Internal_Rela *, source_reloc *, property_table_entry *, int);
05786 static bfd_boolean identify_literal_placement
05787 (bfd *, asection *, bfd_byte *, struct bfd_link_info *,
05788 value_map_hash_table *, bfd_boolean *, Elf_Internal_Rela *, int,
05789 source_reloc *, property_table_entry *, int, section_cache_t *,
05790 bfd_boolean);
05791 static bfd_boolean relocations_reach (source_reloc *, int, const r_reloc *);
05792 static bfd_boolean coalesce_shared_literal
05793 (asection *, source_reloc *, property_table_entry *, int, value_map *);
05794 static bfd_boolean move_shared_literal
05795 (asection *, struct bfd_link_info *, source_reloc *, property_table_entry *,
05796 int, const r_reloc *, const literal_value *, section_cache_t *);
05797
05798
05799 static bfd_boolean relax_section (bfd *, asection *, struct bfd_link_info *);
05800 static bfd_boolean translate_section_fixes (asection *);
05801 static bfd_boolean translate_reloc_bfd_fix (reloc_bfd_fix *);
05802 static void translate_reloc (const r_reloc *, r_reloc *);
05803 static void shrink_dynamic_reloc_sections
05804 (struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *);
05805 static bfd_boolean move_literal
05806 (bfd *, struct bfd_link_info *, asection *, bfd_vma, bfd_byte *,
05807 xtensa_relax_info *, Elf_Internal_Rela **, const literal_value *);
05808 static bfd_boolean relax_property_section
05809 (bfd *, asection *, struct bfd_link_info *);
05810
05811
05812 static bfd_boolean relax_section_symbols (bfd *, asection *);
05813
05814
05815 static bfd_boolean
05816 elf_xtensa_relax_section (bfd *abfd,
05817 asection *sec,
05818 struct bfd_link_info *link_info,
05819 bfd_boolean *again)
05820 {
05821 static value_map_hash_table *values = NULL;
05822 static bfd_boolean relocations_analyzed = FALSE;
05823 xtensa_relax_info *relax_info;
05824
05825 if (!relocations_analyzed)
05826 {
05827
05828 values = value_map_hash_table_init ();
05829 if (values == NULL)
05830 return FALSE;
05831 relaxing_section = TRUE;
05832 if (!analyze_relocations (link_info))
05833 return FALSE;
05834 relocations_analyzed = TRUE;
05835 }
05836 *again = FALSE;
05837
05838
05839 if ((sec->flags & SEC_LINKER_CREATED) != 0)
05840 return TRUE;
05841
05842 relax_info = get_xtensa_relax_info (sec);
05843 BFD_ASSERT (relax_info != NULL);
05844
05845 switch (relax_info->visited)
05846 {
05847 case 0:
05848
05849
05850
05851 if (!compute_removed_literals (abfd, sec, link_info, values))
05852 return FALSE;
05853 *again = TRUE;
05854 break;
05855
05856 case 1:
05857 if (values)
05858 value_map_hash_table_delete (values);
05859 values = NULL;
05860 if (!relax_section (abfd, sec, link_info))
05861 return FALSE;
05862 *again = TRUE;
05863 break;
05864
05865 case 2:
05866 if (!relax_section_symbols (abfd, sec))
05867 return FALSE;
05868 break;
05869 }
05870
05871 relax_info->visited++;
05872 return TRUE;
05873 }
05874
05875
05876
05877
05878
05879
05880
05881
05882
05883
05884
05885
05886
05887
05888
05889
05890 static bfd_boolean
05891 analyze_relocations (struct bfd_link_info *link_info)
05892 {
05893 bfd *abfd;
05894 asection *sec;
05895 bfd_boolean is_relaxable = FALSE;
05896
05897
05898 for (abfd = link_info->input_bfds; abfd != NULL; abfd = abfd->link_next)
05899 for (sec = abfd->sections; sec != NULL; sec = sec->next)
05900 {
05901 init_xtensa_relax_info (sec);
05902 }
05903
05904
05905 for (abfd = link_info->input_bfds; abfd != NULL; abfd = abfd->link_next)
05906 for (sec = abfd->sections; sec != NULL; sec = sec->next)
05907 {
05908 if (!find_relaxable_sections (abfd, sec, link_info, &is_relaxable))
05909 return FALSE;
05910 }
05911
05912
05913 if (!is_relaxable)
05914 return TRUE;
05915
05916
05917 for (abfd = link_info->input_bfds; abfd != NULL; abfd = abfd->link_next)
05918 for (sec = abfd->sections; sec != NULL; sec = sec->next)
05919 {
05920 xtensa_relax_info *relax_info;
05921
05922 relax_info = get_xtensa_relax_info (sec);
05923 if (relax_info->is_relaxable_literal_section
05924 || relax_info->is_relaxable_asm_section)
05925 {
05926 relax_info->src_relocs = (source_reloc *)
05927 bfd_malloc (relax_info->src_count * sizeof (source_reloc));
05928 }
05929 }
05930
05931
05932 for (abfd = link_info->input_bfds; abfd != NULL; abfd = abfd->link_next)
05933 for (sec = abfd->sections; sec != NULL; sec = sec->next)
05934 {
05935 if (!collect_source_relocs (abfd, sec, link_info))
05936 return FALSE;
05937 }
05938
05939
05940 for (abfd = link_info->input_bfds; abfd != NULL; abfd = abfd->link_next)
05941 for (sec = abfd->sections; sec != NULL; sec = sec->next)
05942 {
05943 if (!compute_text_actions (abfd, sec, link_info))
05944 return FALSE;
05945 }
05946
05947 return TRUE;
05948 }
05949
05950
05951
05952
05953
05954
05955
05956
05957
05958
05959
05960
05961 static bfd_boolean
05962 find_relaxable_sections (bfd *abfd,
05963 asection *sec,
05964 struct bfd_link_info *link_info,
05965 bfd_boolean *is_relaxable_p)
05966 {
05967 Elf_Internal_Rela *internal_relocs;
05968 bfd_byte *contents;
05969 bfd_boolean ok = TRUE;
05970 unsigned i;
05971 xtensa_relax_info *source_relax_info;
05972
05973 internal_relocs = retrieve_internal_relocs (abfd, sec,
05974 link_info->keep_memory);
05975 if (internal_relocs == NULL)
05976 return ok;
05977
05978 contents = retrieve_contents (abfd, sec, link_info->keep_memory);
05979 if (contents == NULL && sec->size != 0)
05980 {
05981 ok = FALSE;
05982 goto error_return;
05983 }
05984
05985 source_relax_info = get_xtensa_relax_info (sec);
05986 for (i = 0; i < sec->reloc_count; i++)
05987 {
05988 Elf_Internal_Rela *irel = &internal_relocs[i];
05989 r_reloc r_rel;
05990 asection *target_sec;
05991 xtensa_relax_info *target_relax_info;
05992
05993
05994
05995
05996
05997 if (source_relax_info
05998 && !source_relax_info->is_relaxable_asm_section
05999 && ELF32_R_TYPE (irel->r_info) == R_XTENSA_ASM_EXPAND)
06000 {
06001 bfd_boolean is_reachable = FALSE;
06002 if (is_resolvable_asm_expansion (abfd, sec, contents, irel,
06003 link_info, &is_reachable)
06004 && is_reachable)
06005 {
06006 source_relax_info->is_relaxable_asm_section = TRUE;
06007 *is_relaxable_p = TRUE;
06008 }
06009 }
06010
06011 r_reloc_init (&r_rel, abfd, irel, contents,
06012 bfd_get_section_limit (abfd, sec));
06013
06014 target_sec = r_reloc_get_section (&r_rel);
06015 target_relax_info = get_xtensa_relax_info (target_sec);
06016 if (!target_relax_info)
06017 continue;
06018
06019
06020
06021
06022 if (is_operand_relocation (ELF32_R_TYPE (irel->r_info))
06023 && (!is_alt_relocation (ELF32_R_TYPE (irel->r_info))
06024 || is_l32r_relocation (abfd, sec, contents, irel)))
06025 target_relax_info->src_count++;
06026
06027 if (is_l32r_relocation (abfd, sec, contents, irel)
06028 && r_reloc_is_defined (&r_rel))
06029 {
06030
06031 target_relax_info->is_relaxable_literal_section = TRUE;
06032 *is_relaxable_p = TRUE;
06033 }
06034 }
06035
06036 error_return:
06037 release_contents (sec, contents);
06038 release_internal_relocs (sec, internal_relocs);
06039 return ok;
06040 }
06041
06042
06043
06044
06045
06046
06047 static bfd_boolean
06048 collect_source_relocs (bfd *abfd,
06049 asection *sec,
06050 struct bfd_link_info *link_info)
06051 {
06052 Elf_Internal_Rela *internal_relocs;
06053 bfd_byte *contents;
06054 bfd_boolean ok = TRUE;
06055 unsigned i;
06056 bfd_size_type sec_size;
06057
06058 internal_relocs = retrieve_internal_relocs (abfd, sec,
06059 link_info->keep_memory);
06060 if (internal_relocs == NULL)
06061 return ok;
06062
06063 sec_size = bfd_get_section_limit (abfd, sec);
06064 contents = retrieve_contents (abfd, sec, link_info->keep_memory);
06065 if (contents == NULL && sec_size != 0)
06066 {
06067 ok = FALSE;
06068 goto error_return;
06069 }
06070
06071
06072 for (i = 0; i < sec->reloc_count; i++)
06073 {
06074 Elf_Internal_Rela *irel = &internal_relocs[i];
06075 r_reloc r_rel;
06076 asection *target_sec;
06077 xtensa_relax_info *target_relax_info;
06078
06079 r_reloc_init (&r_rel, abfd, irel, contents, sec_size);
06080
06081 target_sec = r_reloc_get_section (&r_rel);
06082 target_relax_info = get_xtensa_relax_info (target_sec);
06083
06084 if (target_relax_info
06085 && (target_relax_info->is_relaxable_literal_section
06086 || target_relax_info->is_relaxable_asm_section))
06087 {
06088 xtensa_opcode opcode = XTENSA_UNDEFINED;
06089 int opnd = -1;
06090 bfd_boolean is_abs_literal = FALSE;
06091
06092 if (is_alt_relocation (ELF32_R_TYPE (irel->r_info)))
06093 {
06094
06095
06096
06097
06098 opcode = get_relocation_opcode (abfd, sec, contents, irel);
06099 if (opcode == get_l32r_opcode ())
06100 {
06101 is_abs_literal = TRUE;
06102 opnd = 1;
06103 }
06104 else
06105 opcode = XTENSA_UNDEFINED;
06106 }
06107 else if (is_operand_relocation (ELF32_R_TYPE (irel->r_info)))
06108 {
06109 opcode = get_relocation_opcode (abfd, sec, contents, irel);
06110 opnd = get_relocation_opnd (opcode, ELF32_R_TYPE (irel->r_info));
06111 }
06112
06113 if (opcode != XTENSA_UNDEFINED)
06114 {
06115 int src_next = target_relax_info->src_next++;
06116 source_reloc *s_reloc = &target_relax_info->src_relocs[src_next];
06117
06118 init_source_reloc (s_reloc, sec, &r_rel, opcode, opnd,
06119 is_abs_literal);
06120 }
06121 }
06122 }
06123
06124
06125
06126
06127
06128
06129
06130 for (i = 0; i < sec->reloc_count; i++)
06131 {
06132 Elf_Internal_Rela *irel = &internal_relocs[i];
06133 bfd_boolean is_reachable;
06134
06135 if (!is_resolvable_asm_expansion (abfd, sec, contents, irel, link_info,
06136 &is_reachable))
06137 continue;
06138
06139 if (is_reachable)
06140 {
06141 Elf_Internal_Rela *l32r_irel;
06142 r_reloc r_rel;
06143 asection *target_sec;
06144 xtensa_relax_info *target_relax_info;
06145
06146
06147
06148
06149 l32r_irel = find_associated_l32r_irel (abfd, sec, contents,
06150 irel, internal_relocs);
06151 if (l32r_irel == NULL)
06152 continue;
06153
06154 r_reloc_init (&r_rel, abfd, l32r_irel, contents, sec_size);
06155
06156 target_sec = r_reloc_get_section (&r_rel);
06157 target_relax_info = get_xtensa_relax_info (target_sec);
06158
06159 if (target_relax_info
06160 && (target_relax_info->is_relaxable_literal_section
06161 || target_relax_info->is_relaxable_asm_section))
06162 {
06163 source_reloc *s_reloc;
06164
06165
06166
06167
06168
06169 s_reloc = find_source_reloc (target_relax_info->src_relocs,
06170 target_relax_info->src_next,
06171 sec, l32r_irel);
06172 BFD_ASSERT (s_reloc);
06173 s_reloc->is_null = TRUE;
06174 }
06175
06176
06177 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
06178 R_XTENSA_ASM_SIMPLIFY);
06179 l32r_irel->r_info = ELF32_R_INFO (0, R_XTENSA_NONE);
06180
06181 pin_internal_relocs (sec, internal_relocs);
06182 }
06183 else
06184 {
06185
06186
06187
06188 irel->r_info = ELF32_R_INFO (0, R_XTENSA_NONE);
06189 pin_internal_relocs (sec, internal_relocs);
06190 }
06191 }
06192
06193 error_return:
06194 release_contents (sec, contents);
06195 release_internal_relocs (sec, internal_relocs);
06196 return ok;
06197 }
06198
06199
06200
06201
06202
06203
06204
06205
06206 bfd_boolean
06207 is_resolvable_asm_expansion (bfd *abfd,
06208 asection *sec,
06209 bfd_byte *contents,
06210 Elf_Internal_Rela *irel,
06211 struct bfd_link_info *link_info,
06212 bfd_boolean *is_reachable_p)
06213 {
06214 asection *target_sec;
06215 bfd_vma target_offset;
06216 r_reloc r_rel;
06217 xtensa_opcode opcode, direct_call_opcode;
06218 bfd_vma self_address;
06219 bfd_vma dest_address;
06220 bfd_boolean uses_l32r;
06221 bfd_size_type sec_size;
06222
06223 *is_reachable_p = FALSE;
06224
06225 if (contents == NULL)
06226 return FALSE;
06227
06228 if (ELF32_R_TYPE (irel->r_info) != R_XTENSA_ASM_EXPAND)
06229 return FALSE;
06230
06231 sec_size = bfd_get_section_limit (abfd, sec);
06232 opcode = get_expanded_call_opcode (contents + irel->r_offset,
06233 sec_size - irel->r_offset, &uses_l32r);
06234
06235 if (!uses_l32r)
06236 return FALSE;
06237
06238 direct_call_opcode = swap_callx_for_call_opcode (opcode);
06239 if (direct_call_opcode == XTENSA_UNDEFINED)
06240 return FALSE;
06241
06242
06243 r_reloc_init (&r_rel, abfd, irel, contents, sec_size);
06244 if (!r_reloc_is_defined (&r_rel))
06245 return FALSE;
06246
06247 target_sec = r_reloc_get_section (&r_rel);
06248 target_offset = r_rel.target_offset;
06249
06250
06251
06252
06253
06254 if (!target_sec->output_section)
06255 return FALSE;
06256
06257
06258
06259
06260 if (link_info->relocatable
06261 && (target_sec->output_section != sec->output_section
06262 || is_reloc_sym_weak (abfd, irel)))
06263 return FALSE;
06264
06265 self_address = (sec->output_section->vma
06266 + sec->output_offset + irel->r_offset + 3);
06267 dest_address = (target_sec->output_section->vma
06268 + target_sec->output_offset + target_offset);
06269
06270 *is_reachable_p = pcrel_reloc_fits (direct_call_opcode, 0,
06271 self_address, dest_address);
06272
06273 if ((self_address >> CALL_SEGMENT_BITS) !=
06274 (dest_address >> CALL_SEGMENT_BITS))
06275 return FALSE;
06276
06277 return TRUE;
06278 }
06279
06280
06281 static Elf_Internal_Rela *
06282 find_associated_l32r_irel (bfd *abfd,
06283 asection *sec,
06284 bfd_byte *contents,
06285 Elf_Internal_Rela *other_irel,
06286 Elf_Internal_Rela *internal_relocs)
06287 {
06288 unsigned i;
06289
06290 for (i = 0; i < sec->reloc_count; i++)
06291 {
06292 Elf_Internal_Rela *irel = &internal_relocs[i];
06293
06294 if (irel == other_irel)
06295 continue;
06296 if (irel->r_offset != other_irel->r_offset)
06297 continue;
06298 if (is_l32r_relocation (abfd, sec, contents, irel))
06299 return irel;
06300 }
06301
06302 return NULL;
06303 }
06304
06305
06306
06307
06308
06309
06310
06311
06312
06313
06314
06315
06316
06317 bfd_boolean
06318 compute_text_actions (bfd *abfd,
06319 asection *sec,
06320 struct bfd_link_info *link_info)
06321 {
06322 xtensa_relax_info *relax_info;
06323 bfd_byte *contents;
06324 Elf_Internal_Rela *internal_relocs;
06325 bfd_boolean ok = TRUE;
06326 unsigned i;
06327 property_table_entry *prop_table = 0;
06328 int ptblsize = 0;
06329 bfd_size_type sec_size;
06330 static bfd_boolean no_insn_move = FALSE;
06331
06332 if (no_insn_move)
06333 return ok;
06334
06335
06336 relax_info = get_xtensa_relax_info (sec);
06337 BFD_ASSERT (relax_info);
06338 if (!relax_info->is_relaxable_asm_section)
06339 return ok;
06340
06341 internal_relocs = retrieve_internal_relocs (abfd, sec,
06342 link_info->keep_memory);
06343
06344 if (internal_relocs)
06345 qsort (internal_relocs, sec->reloc_count, sizeof (Elf_Internal_Rela),
06346 internal_reloc_compare);
06347
06348 sec_size = bfd_get_section_limit (abfd, sec);
06349 contents = retrieve_contents (abfd, sec, link_info->keep_memory);
06350 if (contents == NULL && sec_size != 0)
06351 {
06352 ok = FALSE;
06353 goto error_return;
06354 }
06355
06356 ptblsize = xtensa_read_table_entries (abfd, sec, &prop_table,
06357 XTENSA_PROP_SEC_NAME, FALSE);
06358 if (ptblsize < 0)
06359 {
06360 ok = FALSE;
06361 goto error_return;
06362 }
06363
06364 for (i = 0; i < sec->reloc_count; i++)
06365 {
06366 Elf_Internal_Rela *irel = &internal_relocs[i];
06367 bfd_vma r_offset;
06368 property_table_entry *the_entry;
06369 int ptbl_idx;
06370 ebb_t *ebb;
06371 ebb_constraint ebb_table;
06372 bfd_size_type simplify_size;
06373
06374 if (irel && ELF32_R_TYPE (irel->r_info) != R_XTENSA_ASM_SIMPLIFY)
06375 continue;
06376 r_offset = irel->r_offset;
06377
06378 simplify_size = get_asm_simplify_size (contents, sec_size, r_offset);
06379 if (simplify_size == 0)
06380 {
06381 (*_bfd_error_handler)
06382 (_("%B(%A+0x%lx): could not decode instruction for XTENSA_ASM_SIMPLIFY relocation; possible configuration mismatch"),
06383 sec->owner, sec, r_offset);
06384 continue;
06385 }
06386
06387
06388
06389 the_entry = elf_xtensa_find_property_entry (prop_table, ptblsize,
06390 sec->vma + irel->r_offset);
06391 if (the_entry == NULL || XTENSA_NO_NOP_REMOVAL)
06392 {
06393 text_action_add (&relax_info->action_list,
06394 ta_convert_longcall, sec, r_offset,
06395 0);
06396 continue;
06397 }
06398
06399
06400
06401 ptbl_idx = the_entry - prop_table;
06402 while ((the_entry->flags & XTENSA_PROP_UNREACHABLE)
06403 && the_entry->size == 0
06404 && ptbl_idx + 1 < ptblsize
06405 && (prop_table[ptbl_idx + 1].address
06406 == prop_table[ptbl_idx].address))
06407 {
06408 ptbl_idx++;
06409 the_entry++;
06410 }
06411
06412 if (the_entry->flags & XTENSA_PROP_INSN_NO_TRANSFORM)
06413
06414 continue;
06415
06416 init_ebb_constraint (&ebb_table);
06417 ebb = &ebb_table.ebb;
06418 init_ebb (ebb, sec, contents, sec_size, prop_table, ptblsize,
06419 internal_relocs, sec->reloc_count);
06420 ebb->start_offset = r_offset + simplify_size;
06421 ebb->end_offset = r_offset + simplify_size;
06422 ebb->start_ptbl_idx = ptbl_idx;
06423 ebb->end_ptbl_idx = ptbl_idx;
06424 ebb->start_reloc_idx = i;
06425 ebb->end_reloc_idx = i;
06426
06427 if (!extend_ebb_bounds (ebb)
06428 || !compute_ebb_proposed_actions (&ebb_table)
06429 || !compute_ebb_actions (&ebb_table)
06430 || !check_section_ebb_pcrels_fit (abfd, sec, contents,
06431 internal_relocs, &ebb_table)
06432 || !check_section_ebb_reduces (&ebb_table))
06433 {
06434
06435
06436
06437
06438 text_action_add (&relax_info->action_list,
06439 ta_convert_longcall, sec, r_offset, 0);
06440 i = ebb_table.ebb.end_reloc_idx;
06441 free_ebb_constraint (&ebb_table);
06442 continue;
06443 }
06444
06445 text_action_add_proposed (&relax_info->action_list, &ebb_table, sec);
06446
06447
06448
06449 i = ebb_table.ebb.end_reloc_idx;
06450 free_ebb_constraint (&ebb_table);
06451 }
06452
06453 #if DEBUG
06454 if (relax_info->action_list.head)
06455 print_action_list (stderr, &relax_info->action_list);
06456 #endif
06457
06458 error_return:
06459 release_contents (sec, contents);
06460 release_internal_relocs (sec, internal_relocs);
06461 if (prop_table)
06462 free (prop_table);
06463
06464 return ok;
06465 }
06466
06467
06468
06469
06470 bfd_boolean
06471 compute_ebb_proposed_actions (ebb_constraint *ebb_table)
06472 {
06473 const ebb_t *ebb = &ebb_table->ebb;
06474 unsigned rel_idx = ebb->start_reloc_idx;
06475 property_table_entry *entry, *start_entry, *end_entry;
06476
06477 start_entry = &ebb->ptbl[ebb->start_ptbl_idx];
06478 end_entry = &ebb->ptbl[ebb->end_ptbl_idx];
06479
06480 for (entry = start_entry; entry <= end_entry; entry++)
06481 {
06482 bfd_vma offset, start_offset, end_offset;
06483 bfd_size_type insn_len;
06484
06485 start_offset = entry->address - ebb->sec->vma;
06486 end_offset = entry->address + entry->size - ebb->sec->vma;
06487
06488 if (entry == start_entry)
06489 start_offset = ebb->start_offset;
06490 if (entry == end_entry)
06491 end_offset = ebb->end_offset;
06492 offset = start_offset;
06493
06494 if (offset == entry->address - ebb->sec->vma
06495 && (entry->flags & XTENSA_PROP_INSN_BRANCH_TARGET) != 0)
06496 {
06497 enum ebb_target_enum align_type = EBB_DESIRE_TGT_ALIGN;
06498 BFD_ASSERT (offset != end_offset);
06499 if (offset == end_offset)
06500 return FALSE;
06501
06502 insn_len = insn_decode_len (ebb->contents, ebb->content_length,
06503 offset);
06504
06505
06506 if (insn_len == 0)
06507 {
06508 (*_bfd_error_handler)
06509 (_("%B(%A+0x%lx): could not decode instruction; possible configuration mismatch"),
06510 ebb->sec->owner, ebb->sec, offset);
06511 return FALSE;
06512 }
06513 if (check_branch_target_aligned_address (offset, insn_len))
06514 align_type = EBB_REQUIRE_TGT_ALIGN;
06515
06516 ebb_propose_action (ebb_table, align_type, 0,
06517 ta_none, offset, 0, TRUE);
06518 }
06519
06520 while (offset != end_offset)
06521 {
06522 Elf_Internal_Rela *irel;
06523 xtensa_opcode opcode;
06524
06525 while (rel_idx < ebb->end_reloc_idx
06526 && (ebb->relocs[rel_idx].r_offset < offset
06527 || (ebb->relocs[rel_idx].r_offset == offset
06528 && (ELF32_R_TYPE (ebb->relocs[rel_idx].r_info)
06529 != R_XTENSA_ASM_SIMPLIFY))))
06530 rel_idx++;
06531
06532
06533 irel = &ebb->relocs[rel_idx];
06534 if (irel->r_offset == offset
06535 && ELF32_R_TYPE (irel->r_info) == R_XTENSA_ASM_SIMPLIFY)
06536 {
06537 bfd_size_type simplify_size;
06538
06539 simplify_size = get_asm_simplify_size (ebb->contents,
06540 ebb->content_length,
06541 irel->r_offset);
06542 if (simplify_size == 0)
06543 {
06544 (*_bfd_error_handler)
06545 (_("%B(%A+0x%lx): could not decode instruction for XTENSA_ASM_SIMPLIFY relocation; possible configuration mismatch"),
06546 ebb->sec->owner, ebb->sec, offset);
06547 return FALSE;
06548 }
06549
06550 ebb_propose_action (ebb_table, EBB_NO_ALIGN, 0,
06551 ta_convert_longcall, offset, 0, TRUE);
06552
06553 offset += simplify_size;
06554 continue;
06555 }
06556
06557 insn_len = insn_decode_len (ebb->contents, ebb->content_length,
06558 offset);
06559
06560 if (insn_len == 0)
06561 {
06562 (*_bfd_error_handler)
06563 (_("%B(%A+0x%lx): could not decode instruction; possible configuration mismatch"),
06564 ebb->sec->owner, ebb->sec, offset);
06565 return FALSE;
06566 }
06567
06568 if ((entry->flags & XTENSA_PROP_INSN_NO_DENSITY) == 0
06569 && (entry->flags & XTENSA_PROP_INSN_NO_TRANSFORM) == 0
06570 && narrow_instruction (ebb->contents, ebb->content_length,
06571 offset, FALSE))
06572 {
06573
06574 ebb_propose_action (ebb_table, EBB_NO_ALIGN, 0,
06575 ta_narrow_insn, offset, 0, FALSE);
06576 offset += insn_len;
06577 continue;
06578 }
06579 if ((entry->flags & XTENSA_PROP_INSN_NO_TRANSFORM) == 0
06580 && widen_instruction (ebb->contents, ebb->content_length,
06581 offset, FALSE))
06582 {
06583
06584 ebb_propose_action (ebb_table, EBB_NO_ALIGN, 0,
06585 ta_widen_insn, offset, 0, FALSE);
06586 offset += insn_len;
06587 continue;
06588 }
06589 opcode = insn_decode_opcode (ebb->contents, ebb->content_length,
06590 offset, 0);
06591 if (xtensa_opcode_is_loop (xtensa_default_isa, opcode))
06592 {
06593
06594 ebb_propose_action (ebb_table, EBB_REQUIRE_LOOP_ALIGN, 0,
06595 ta_none, offset, 0, TRUE);
06596 offset += insn_len;
06597 continue;
06598 }
06599
06600 offset += insn_len;
06601 }
06602 }
06603
06604 if (ebb->ends_unreachable)
06605 {
06606 ebb_propose_action (ebb_table, EBB_NO_ALIGN, 0,
06607 ta_fill, ebb->end_offset, 0, TRUE);
06608 }
06609
06610 return TRUE;
06611 }
06612
06613
06614
06615
06616
06617
06618
06619
06620
06621
06622
06623
06624
06625
06626
06627
06628
06629
06630
06631 bfd_boolean
06632 compute_ebb_actions (ebb_constraint *ebb_table)
06633 {
06634 unsigned i = 0;
06635 unsigned j;
06636 int removed_bytes = 0;
06637 ebb_t *ebb = &ebb_table->ebb;
06638 unsigned seg_idx_start = 0;
06639 unsigned seg_idx_end = 0;
06640
06641
06642
06643
06644
06645
06646
06647
06648 for (seg_idx_end = 0; seg_idx_end < ebb_table->action_count; seg_idx_end++)
06649 {
06650 bfd_boolean requires_text_end_align = FALSE;
06651 unsigned longcall_count = 0;
06652 unsigned longcall_convert_count = 0;
06653 unsigned narrowable_count = 0;
06654 unsigned narrowable_convert_count = 0;
06655 unsigned widenable_count = 0;
06656 unsigned widenable_convert_count = 0;
06657
06658 proposed_action *action = NULL;
06659 int align = (1 << ebb_table->ebb.sec->alignment_power);
06660
06661 seg_idx_start = seg_idx_end;
06662
06663 for (i = seg_idx_start; i < ebb_table->action_count; i++)
06664 {
06665 action = &ebb_table->actions[i];
06666 if (action->action == ta_convert_longcall)
06667 longcall_count++;
06668 if (action->action == ta_narrow_insn)
06669 narrowable_count++;
06670 if (action->action == ta_widen_insn)
06671 widenable_count++;
06672 if (action->action == ta_fill)
06673 break;
06674 if (action->align_type == EBB_REQUIRE_LOOP_ALIGN)
06675 break;
06676 if (action->align_type == EBB_REQUIRE_TGT_ALIGN
06677 && !elf32xtensa_size_opt)
06678 break;
06679 }
06680 seg_idx_end = i;
06681
06682 if (seg_idx_end == ebb_table->action_count && !ebb->ends_unreachable)
06683 requires_text_end_align = TRUE;
06684
06685 if (elf32xtensa_size_opt && !requires_text_end_align
06686 && action->align_type != EBB_REQUIRE_LOOP_ALIGN
06687 && action->align_type != EBB_REQUIRE_TGT_ALIGN)
06688 {
06689 longcall_convert_count = longcall_count;
06690 narrowable_convert_count = narrowable_count;
06691 widenable_convert_count = 0;
06692 }
06693 else
06694 {
06695
06696 narrowable_convert_count = 0;
06697 longcall_convert_count = 0;
06698 widenable_convert_count = 0;
06699
06700 for (j = 0; j < longcall_count; j++)
06701 {
06702 int removed = (longcall_count - j) * 3 & (align - 1);
06703 unsigned desire_narrow = (align - removed) & (align - 1);
06704 unsigned desire_widen = removed;
06705 if (desire_narrow <= narrowable_count)
06706 {
06707 narrowable_convert_count = desire_narrow;
06708 narrowable_convert_count +=
06709 (align * ((narrowable_count - narrowable_convert_count)
06710 / align));
06711 longcall_convert_count = (longcall_count - j);
06712 widenable_convert_count = 0;
06713 break;
06714 }
06715 if (desire_widen <= widenable_count && !elf32xtensa_size_opt)
06716 {
06717 narrowable_convert_count = 0;
06718 longcall_convert_count = longcall_count - j;
06719 widenable_convert_count = desire_widen;
06720 break;
06721 }
06722 }
06723 }
06724
06725
06726 for (i = seg_idx_start; i < seg_idx_end; i++)
06727 {
06728 action = &ebb_table->actions[i];
06729 switch (action->action)
06730 {
06731 case ta_convert_longcall:
06732 if (longcall_convert_count != 0)
06733 {
06734 action->action = ta_remove_longcall;
06735 action->do_action = TRUE;
06736 action->removed_bytes += 3;
06737 longcall_convert_count--;
06738 }
06739 break;
06740 case ta_narrow_insn:
06741 if (narrowable_convert_count != 0)
06742 {
06743 action->do_action = TRUE;
06744 action->removed_bytes += 1;
06745 narrowable_convert_count--;
06746 }
06747 break;
06748 case ta_widen_insn:
06749 if (widenable_convert_count != 0)
06750 {
06751 action->do_action = TRUE;
06752 action->removed_bytes -= 1;
06753 widenable_convert_count--;
06754 }
06755 break;
06756 default:
06757 break;
06758 }
06759 }
06760 }
06761
06762
06763
06764
06765 if (ebb_table->ebb.ends_section || ebb_table->ebb.ends_unreachable)
06766 {
06767 removed_bytes = 0;
06768 for (i = 0; i < ebb_table->action_count; i++)
06769 {
06770 int old_removed_bytes = removed_bytes;
06771 proposed_action *action = &ebb_table->actions[i];
06772
06773 if (action->do_action && action->action == ta_convert_longcall)
06774 {
06775 bfd_boolean bad_alignment = FALSE;
06776 removed_bytes += 3;
06777 for (j = i + 1; j < ebb_table->action_count; j++)
06778 {
06779 proposed_action *new_action = &ebb_table->actions[j];
06780 bfd_vma offset = new_action->offset;
06781 if (new_action->align_type == EBB_REQUIRE_TGT_ALIGN)
06782 {
06783 if (!check_branch_target_aligned
06784 (ebb_table->ebb.contents,
06785 ebb_table->ebb.content_length,
06786 offset, offset - removed_bytes))
06787 {
06788 bad_alignment = TRUE;
06789 break;
06790 }
06791 }
06792 if (new_action->align_type == EBB_REQUIRE_LOOP_ALIGN)
06793 {
06794 if (!check_loop_aligned (ebb_table->ebb.contents,
06795 ebb_table->ebb.content_length,
06796 offset,
06797 offset - removed_bytes))
06798 {
06799 bad_alignment = TRUE;
06800 break;
06801 }
06802 }
06803 if (new_action->action == ta_narrow_insn
06804 && !new_action->do_action
06805 && ebb_table->ebb.sec->alignment_power == 2)
06806 {
06807
06808 new_action->do_action = TRUE;
06809 new_action->removed_bytes += 1;
06810 bad_alignment = FALSE;
06811 break;
06812 }
06813 if (new_action->action == ta_widen_insn
06814 && new_action->do_action
06815 && ebb_table->ebb.sec->alignment_power == 2)
06816 {
06817
06818 new_action->do_action = FALSE;
06819 new_action->removed_bytes += 1;
06820 bad_alignment = FALSE;
06821 break;
06822 }
06823 }
06824 if (!bad_alignment)
06825 {
06826 action->removed_bytes += 3;
06827 action->action = ta_remove_longcall;
06828 action->do_action = TRUE;
06829 }
06830 }
06831 removed_bytes = old_removed_bytes;
06832 if (action->do_action)
06833 removed_bytes += action->removed_bytes;
06834 }
06835 }
06836
06837 removed_bytes = 0;
06838 for (i = 0; i < ebb_table->action_count; ++i)
06839 {
06840 proposed_action *action = &ebb_table->actions[i];
06841 if (action->do_action)
06842 removed_bytes += action->removed_bytes;
06843 }
06844
06845 if ((removed_bytes % (1 << ebb_table->ebb.sec->alignment_power)) != 0
06846 && ebb->ends_unreachable)
06847 {
06848 proposed_action *action;
06849 int br;
06850 int extra_space;
06851
06852 BFD_ASSERT (ebb_table->action_count != 0);
06853 action = &ebb_table->actions[ebb_table->action_count - 1];
06854 BFD_ASSERT (action->action == ta_fill);
06855 BFD_ASSERT (ebb->ends_unreachable->flags & XTENSA_PROP_UNREACHABLE);
06856
06857 extra_space = compute_fill_extra_space (ebb->ends_unreachable);
06858 br = action->removed_bytes + removed_bytes + extra_space;
06859 br = br & ((1 << ebb->sec->alignment_power ) - 1);
06860
06861 action->removed_bytes = extra_space - br;
06862 }
06863 return TRUE;
06864 }
06865
06866
06867
06868
06869
06870
06871 static bfd_boolean
06872 check_section_ebb_pcrels_fit (bfd *abfd,
06873 asection *sec,
06874 bfd_byte *contents,
06875 Elf_Internal_Rela *internal_relocs,
06876 const ebb_constraint *constraint)
06877 {
06878 unsigned i, j;
06879 Elf_Internal_Rela *irel;
06880 xtensa_relax_info *relax_info;
06881
06882 relax_info = get_xtensa_relax_info (sec);
06883
06884 for (i = 0; i < sec->reloc_count; i++)
06885 {
06886 r_reloc r_rel;
06887 bfd_vma orig_self_offset, orig_target_offset;
06888 bfd_vma self_offset, target_offset;
06889 int r_type;
06890 reloc_howto_type *howto;
06891 int self_removed_bytes, target_removed_bytes;
06892
06893 irel = &internal_relocs[i];
06894 r_type = ELF32_R_TYPE (irel->r_info);
06895
06896 howto = &elf_howto_table[r_type];
06897
06898
06899
06900
06901 if (ELF32_R_TYPE (irel->r_info) == R_XTENSA_ASM_SIMPLIFY
06902 || !howto->pc_relative)
06903 continue;
06904
06905 r_reloc_init (&r_rel, abfd, irel, contents,
06906 bfd_get_section_limit (abfd, sec));
06907
06908 if (r_reloc_get_section (&r_rel) != sec)
06909 continue;
06910
06911 orig_self_offset = irel->r_offset;
06912 orig_target_offset = r_rel.target_offset;
06913
06914 self_offset = orig_self_offset;
06915 target_offset = orig_target_offset;
06916
06917 if (relax_info)
06918 {
06919 self_offset = offset_with_removed_text (&relax_info->action_list,
06920 orig_self_offset);
06921 target_offset = offset_with_removed_text (&relax_info->action_list,
06922 orig_target_offset);
06923 }
06924
06925 self_removed_bytes = 0;
06926 target_removed_bytes = 0;
06927
06928 for (j = 0; j < constraint->action_count; ++j)
06929 {
06930 proposed_action *action = &constraint->actions[j];
06931 bfd_vma offset = action->offset;
06932 int removed_bytes = action->removed_bytes;
06933 if (offset < orig_self_offset
06934 || (offset == orig_self_offset && action->action == ta_fill
06935 && action->removed_bytes < 0))
06936 self_removed_bytes += removed_bytes;
06937 if (offset < orig_target_offset
06938 || (offset == orig_target_offset && action->action == ta_fill
06939 && action->removed_bytes < 0))
06940 target_removed_bytes += removed_bytes;
06941 }
06942 self_offset -= self_removed_bytes;
06943 target_offset -= target_removed_bytes;
06944
06945
06946 if (is_alt_relocation (ELF32_R_TYPE (irel->r_info)))
06947 {
06948
06949
06950 }
06951 else
06952 {
06953 xtensa_opcode opcode;
06954 int opnum;
06955
06956 opcode = get_relocation_opcode (abfd, sec, contents, irel);
06957 if (opcode == XTENSA_UNDEFINED)
06958 return FALSE;
06959
06960 opnum = get_relocation_opnd (opcode, ELF32_R_TYPE (irel->r_info));
06961 if (opnum == XTENSA_UNDEFINED)
06962 return FALSE;
06963
06964 if (!pcrel_reloc_fits (opcode, opnum, self_offset, target_offset))
06965 return FALSE;
06966 }
06967 }
06968
06969 return TRUE;
06970 }
06971
06972
06973 static bfd_boolean
06974 check_section_ebb_reduces (const ebb_constraint *constraint)
06975 {
06976 int removed = 0;
06977 unsigned i;
06978
06979 for (i = 0; i < constraint->action_count; i++)
06980 {
06981 const proposed_action *action = &constraint->actions[i];
06982 if (action->do_action)
06983 removed += action->removed_bytes;
06984 }
06985 if (removed < 0)
06986 return FALSE;
06987
06988 return TRUE;
06989 }
06990
06991
06992 void
06993 text_action_add_proposed (text_action_list *l,
06994 const ebb_constraint *ebb_table,
06995 asection *sec)
06996 {
06997 unsigned i;
06998
06999 for (i = 0; i < ebb_table->action_count; i++)
07000 {
07001 proposed_action *action = &ebb_table->actions[i];
07002
07003 if (!action->do_action)
07004 continue;
07005 switch (action->action)
07006 {
07007 case ta_remove_insn:
07008 case ta_remove_longcall:
07009 case ta_convert_longcall:
07010 case ta_narrow_insn:
07011 case ta_widen_insn:
07012 case ta_fill:
07013 case ta_remove_literal:
07014 text_action_add (l, action->action, sec, action->offset,
07015 action->removed_bytes);
07016 break;
07017 case ta_none:
07018 break;
07019 default:
07020 BFD_ASSERT (0);
07021 break;
07022 }
07023 }
07024 }
07025
07026
07027 int
07028 compute_fill_extra_space (property_table_entry *entry)
07029 {
07030 int fill_extra_space;
07031
07032 if (!entry)
07033 return 0;
07034
07035 if ((entry->flags & XTENSA_PROP_UNREACHABLE) == 0)
07036 return 0;
07037
07038 fill_extra_space = entry->size;
07039 if ((entry->flags & XTENSA_PROP_ALIGN) != 0)
07040 {
07041
07042
07043 int pow = GET_XTENSA_PROP_ALIGNMENT (entry->flags);
07044 int nsm = (1 << pow) - 1;
07045 bfd_vma addr = entry->address + entry->size;
07046 bfd_vma align_fill = nsm - ((addr + nsm) & nsm);
07047 fill_extra_space += align_fill;
07048 }
07049 return fill_extra_space;
07050 }
07051
07052
07053
07054
07055
07056
07057
07058
07059
07060
07061 static bfd_boolean
07062 compute_removed_literals (bfd *abfd,
07063 asection *sec,
07064 struct bfd_link_info *link_info,
07065 value_map_hash_table *values)
07066 {
07067 xtensa_relax_info *relax_info;
07068 bfd_byte *contents;
07069 Elf_Internal_Rela *internal_relocs;
07070 source_reloc *src_relocs, *rel;
07071 bfd_boolean ok = TRUE;
07072 property_table_entry *prop_table = NULL;
07073 int ptblsize;
07074 int i, prev_i;
07075 bfd_boolean last_loc_is_prev = FALSE;
07076 bfd_vma last_target_offset = 0;
07077 section_cache_t target_sec_cache;
07078 bfd_size_type sec_size;
07079
07080 init_section_cache (&target_sec_cache);
07081
07082
07083 relax_info = get_xtensa_relax_info (sec);
07084 BFD_ASSERT (relax_info);
07085 if (!relax_info->is_relaxable_literal_section)
07086 return ok;
07087
07088 internal_relocs = retrieve_internal_relocs (abfd, sec,
07089 link_info->keep_memory);
07090
07091 sec_size = bfd_get_section_limit (abfd, sec);
07092 contents = retrieve_contents (abfd, sec, link_info->keep_memory);
07093 if (contents == NULL && sec_size != 0)
07094 {
07095 ok = FALSE;
07096 goto error_return;
07097 }
07098
07099
07100 src_relocs = relax_info->src_relocs;
07101 qsort (src_relocs, relax_info->src_count,
07102 sizeof (source_reloc), source_reloc_compare);
07103 qsort (internal_relocs, sec->reloc_count, sizeof (Elf_Internal_Rela),
07104 internal_reloc_compare);
07105
07106 ptblsize = xtensa_read_table_entries (abfd, sec, &prop_table,
07107 XTENSA_PROP_SEC_NAME, FALSE);
07108 if (ptblsize < 0)
07109 {
07110 ok = FALSE;
07111 goto error_return;
07112 }
07113
07114 prev_i = -1;
07115 for (i = 0; i < relax_info->src_count; i++)
07116 {
07117 Elf_Internal_Rela *irel = NULL;
07118
07119 rel = &src_relocs[i];
07120 if (get_l32r_opcode () != rel->opcode)
07121 continue;
07122 irel = get_irel_at_offset (sec, internal_relocs,
07123 rel->r_rel.target_offset);
07124
07125
07126
07127
07128 if (irel && (ELF32_R_TYPE (irel->r_info) != R_XTENSA_32
07129 && ELF32_R_TYPE (irel->r_info) != R_XTENSA_PLT))
07130 continue;
07131
07132
07133
07134
07135 if (i != 0 && prev_i != -1
07136 && src_relocs[i-1].r_rel.target_offset == rel->r_rel.target_offset)
07137 continue;
07138 prev_i = i;
07139
07140 if (last_loc_is_prev &&
07141 last_target_offset + 4 != rel->r_rel.target_offset)
07142 last_loc_is_prev = FALSE;
07143
07144
07145
07146
07147 if (is_removable_literal (rel, i, src_relocs, relax_info->src_count))
07148 {
07149 if (!remove_dead_literal (abfd, sec, link_info, internal_relocs,
07150 irel, rel, prop_table, ptblsize))
07151 {
07152 ok = FALSE;
07153 goto error_return;
07154 }
07155 last_target_offset = rel->r_rel.target_offset;
07156 continue;
07157 }
07158
07159 if (!identify_literal_placement (abfd, sec, contents, link_info,
07160 values,
07161 &last_loc_is_prev, irel,
07162 relax_info->src_count - i, rel,
07163 prop_table, ptblsize,
07164 &target_sec_cache, rel->is_abs_literal))
07165 {
07166 ok = FALSE;
07167 goto error_return;
07168 }
07169 last_target_offset = rel->r_rel.target_offset;
07170 }
07171
07172 #if DEBUG
07173 print_removed_literals (stderr, &relax_info->removed_list);
07174 print_action_list (stderr, &relax_info->action_list);
07175 #endif
07176
07177 error_return:
07178 if (prop_table) free (prop_table);
07179 clear_section_cache (&target_sec_cache);
07180
07181 release_contents (sec, contents);
07182 release_internal_relocs (sec, internal_relocs);
07183 return ok;
07184 }
07185
07186
07187 static Elf_Internal_Rela *
07188 get_irel_at_offset (asection *sec,
07189 Elf_Internal_Rela *internal_relocs,
07190 bfd_vma offset)
07191 {
07192 unsigned i;
07193 Elf_Internal_Rela *irel;
07194 unsigned r_type;
07195 Elf_Internal_Rela key;
07196
07197 if (!internal_relocs)
07198 return NULL;
07199
07200 key.r_offset = offset;
07201 irel = bsearch (&key, internal_relocs, sec->reloc_count,
07202 sizeof (Elf_Internal_Rela), internal_reloc_matches);
07203 if (!irel)
07204 return NULL;
07205
07206
07207
07208 i = irel - internal_relocs;
07209 while (i > 0)
07210 {
07211 if (internal_relocs[i-1].r_offset != offset)
07212 break;
07213 i--;
07214 }
07215 for ( ; i < sec->reloc_count; i++)
07216 {
07217 irel = &internal_relocs[i];
07218 r_type = ELF32_R_TYPE (irel->r_info);
07219 if (irel->r_offset == offset && r_type != R_XTENSA_NONE)
07220 return irel;
07221 }
07222
07223 return NULL;
07224 }
07225
07226
07227 bfd_boolean
07228 is_removable_literal (const source_reloc *rel,
07229 int i,
07230 const source_reloc *src_relocs,
07231 int src_count)
07232 {
07233 const source_reloc *curr_rel;
07234 if (!rel->is_null)
07235 return FALSE;
07236
07237 for (++i; i < src_count; ++i)
07238 {
07239 curr_rel = &src_relocs[i];
07240
07241 if (curr_rel->r_rel.target_offset != rel->r_rel.target_offset)
07242 return TRUE;
07243
07244 if (!curr_rel->is_null
07245 && !xtensa_is_property_section (curr_rel->source_sec)
07246 && !(curr_rel->source_sec->flags & SEC_DEBUGGING))
07247 return FALSE;
07248 }
07249 return TRUE;
07250 }
07251
07252
07253 bfd_boolean
07254 remove_dead_literal (bfd *abfd,
07255 asection *sec,
07256 struct bfd_link_info *link_info,
07257 Elf_Internal_Rela *internal_relocs,
07258 Elf_Internal_Rela *irel,
07259 source_reloc *rel,
07260 property_table_entry *prop_table,
07261 int ptblsize)
07262 {
07263 property_table_entry *entry;
07264 xtensa_relax_info *relax_info;
07265
07266 relax_info = get_xtensa_relax_info (sec);
07267 if (!relax_info)
07268 return FALSE;
07269
07270 entry = elf_xtensa_find_property_entry (prop_table, ptblsize,
07271 sec->vma + rel->r_rel.target_offset);
07272
07273
07274 add_removed_literal (&relax_info->removed_list, &rel->r_rel, NULL);
07275
07276 text_action_add (&relax_info->action_list,
07277 ta_remove_literal, sec, rel->r_rel.target_offset, 4);
07278
07279
07280 if (sec->alignment_power > 2)
07281 {
07282 int fill_extra_space;
07283 bfd_vma entry_sec_offset;
07284 text_action *fa;
07285 property_table_entry *the_add_entry;
07286 int removed_diff;
07287
07288 if (entry)
07289 entry_sec_offset = entry->address - sec->vma + entry->size;
07290 else
07291 entry_sec_offset = rel->r_rel.target_offset + 4;
07292
07293
07294
07295 the_add_entry = elf_xtensa_find_property_entry (prop_table, ptblsize,
07296 entry_sec_offset);
07297 fill_extra_space = compute_fill_extra_space (the_add_entry);
07298
07299 fa = find_fill_action (&relax_info->action_list, sec, entry_sec_offset);
07300 removed_diff = compute_removed_action_diff (fa, sec, entry_sec_offset,
07301 -4, fill_extra_space);
07302 if (fa)
07303 adjust_fill_action (fa, removed_diff);
07304 else
07305 text_action_add (&relax_info->action_list,
07306 ta_fill, sec, entry_sec_offset, removed_diff);
07307 }
07308
07309
07310 if (irel)
07311 {
07312 if (elf_hash_table (link_info)->dynamic_sections_created)
07313 shrink_dynamic_reloc_sections (link_info, abfd, sec, irel);
07314
07315 irel->r_info = ELF32_R_INFO (0, R_XTENSA_NONE);
07316 pin_internal_relocs (sec, internal_relocs);
07317 }
07318
07319
07320 return TRUE;
07321 }
07322
07323
07324 bfd_boolean
07325 identify_literal_placement (bfd *abfd,
07326 asection *sec,
07327 bfd_byte *contents,
07328 struct bfd_link_info *link_info,
07329 value_map_hash_table *values,
07330 bfd_boolean *last_loc_is_prev_p,
07331 Elf_Internal_Rela *irel,
07332 int remaining_src_rels,
07333 source_reloc *rel,
07334 property_table_entry *prop_table,
07335 int ptblsize,
07336 section_cache_t *target_sec_cache,
07337 bfd_boolean is_abs_literal)
07338 {
07339 literal_value val;
07340 value_map *val_map;
07341 xtensa_relax_info *relax_info;
07342 bfd_boolean literal_placed = FALSE;
07343 r_reloc r_rel;
07344 unsigned long value;
07345 bfd_boolean final_static_link;
07346 bfd_size_type sec_size;
07347
07348 relax_info = get_xtensa_relax_info (sec);
07349 if (!relax_info)
07350 return FALSE;
07351
07352 sec_size = bfd_get_section_limit (abfd, sec);
07353
07354 final_static_link =
07355 (!link_info->relocatable
07356 && !elf_hash_table (link_info)->dynamic_sections_created);
07357
07358
07359
07360
07361
07362
07363
07364
07365
07366
07367
07368 value = 0;
07369 r_reloc_init (&r_rel, abfd, irel, contents, sec_size);
07370 if (!irel)
07371 {
07372 BFD_ASSERT (rel->r_rel.target_offset < sec_size);
07373 value = bfd_get_32 (abfd, contents + rel->r_rel.target_offset);
07374 }
07375 init_literal_value (&val, &r_rel, value, is_abs_literal);
07376
07377
07378
07379 val_map = value_map_get_cached_value (values, &val, final_static_link);
07380
07381 if (val_map
07382 && (r_reloc_get_section (&val_map->loc)->output_section
07383 == sec->output_section)
07384 && relocations_reach (rel, remaining_src_rels, &val_map->loc)
07385 && coalesce_shared_literal (sec, rel, prop_table, ptblsize, val_map))
07386 {
07387
07388 literal_placed = TRUE;
07389 }
07390
07391
07392
07393
07394 if (!link_info->relocatable && !literal_placed
07395 && values->has_last_loc && !(*last_loc_is_prev_p))
07396 {
07397 asection *target_sec = r_reloc_get_section (&values->last_loc);
07398 if (target_sec && target_sec->output_section == sec->output_section)
07399 {
07400
07401 r_reloc try_loc = values->last_loc;
07402 try_loc.virtual_offset += 4;
07403
07404
07405 if (relocations_reach (rel, remaining_src_rels, &try_loc)
07406 && move_shared_literal (sec, link_info, rel,
07407 prop_table, ptblsize,
07408 &try_loc, &val, target_sec_cache))
07409 {
07410 values->last_loc.virtual_offset += 4;
07411 literal_placed = TRUE;
07412 if (!val_map)
07413 val_map = add_value_map (values, &val, &try_loc,
07414 final_static_link);
07415 else
07416 val_map->loc = try_loc;
07417 }
07418 }
07419 }
07420
07421 if (!literal_placed)
07422 {
07423
07424 values->has_last_loc = TRUE;
07425 values->last_loc = rel->r_rel;
07426 if (!val_map)
07427 val_map = add_value_map (values, &val, &rel->r_rel, final_static_link);
07428 else
07429 val_map->loc = rel->r_rel;
07430 *last_loc_is_prev_p = TRUE;
07431 }
07432
07433 return TRUE;
07434 }
07435
07436
07437
07438
07439
07440
07441
07442
07443
07444