| OLD | NEW |
| 1 /* SPU specific support for 32-bit ELF | 1 /* SPU specific support for 32-bit ELF |
| 2 | 2 |
| 3 Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. | 3 Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. |
| 4 | 4 |
| 5 This file is part of BFD, the Binary File Descriptor library. | 5 This file is part of BFD, the Binary File Descriptor library. |
| 6 | 6 |
| 7 This program is free software; you can redistribute it and/or modify | 7 This program is free software; you can redistribute it and/or modify |
| 8 it under the terms of the GNU General Public License as published by | 8 it under the terms of the GNU General Public License as published by |
| 9 the Free Software Foundation; either version 3 of the License, or | 9 the Free Software Foundation; either version 3 of the License, or |
| 10 (at your option) any later version. | 10 (at your option) any later version. |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 /* Total number of overlays. */ | 324 /* Total number of overlays. */ |
| 325 unsigned int num_overlays; | 325 unsigned int num_overlays; |
| 326 | 326 |
| 327 /* For soft icache. */ | 327 /* For soft icache. */ |
| 328 unsigned int line_size_log2; | 328 unsigned int line_size_log2; |
| 329 unsigned int num_lines_log2; | 329 unsigned int num_lines_log2; |
| 330 unsigned int fromelem_size_log2; | 330 unsigned int fromelem_size_log2; |
| 331 | 331 |
| 332 /* How much memory we have. */ | 332 /* How much memory we have. */ |
| 333 unsigned int local_store; | 333 unsigned int local_store; |
| 334 /* Local store --auto-overlay should reserve for non-overlay | 334 |
| 335 functions and data. */ | |
| 336 unsigned int overlay_fixed; | |
| 337 /* Local store --auto-overlay should reserve for stack and heap. */ | |
| 338 unsigned int reserved; | |
| 339 /* If reserved is not specified, stack analysis will calculate a value | |
| 340 for the stack. This parameter adjusts that value to allow for | |
| 341 negative sp access (the ABI says 2000 bytes below sp are valid, | |
| 342 and the overlay manager uses some of this area). */ | |
| 343 int extra_stack_space; | |
| 344 /* Count of overlay stubs needed in non-overlay area. */ | 335 /* Count of overlay stubs needed in non-overlay area. */ |
| 345 unsigned int non_ovly_stub; | 336 unsigned int non_ovly_stub; |
| 346 | 337 |
| 347 /* Pointer to the fixup section */ | 338 /* Pointer to the fixup section */ |
| 348 asection *sfixup; | 339 asection *sfixup; |
| 349 | 340 |
| 350 /* Set on error. */ | 341 /* Set on error. */ |
| 351 unsigned int stub_err : 1; | 342 unsigned int stub_err : 1; |
| 352 }; | 343 }; |
| 353 | 344 |
| (...skipping 2331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2685 irela = internal_relocs; | 2676 irela = internal_relocs; |
| 2686 irelaend = irela + sec->reloc_count; | 2677 irelaend = irela + sec->reloc_count; |
| 2687 for (; irela < irelaend; irela++) | 2678 for (; irela < irelaend; irela++) |
| 2688 { | 2679 { |
| 2689 enum elf_spu_reloc_type r_type; | 2680 enum elf_spu_reloc_type r_type; |
| 2690 unsigned int r_indx; | 2681 unsigned int r_indx; |
| 2691 asection *sym_sec; | 2682 asection *sym_sec; |
| 2692 Elf_Internal_Sym *sym; | 2683 Elf_Internal_Sym *sym; |
| 2693 struct elf_link_hash_entry *h; | 2684 struct elf_link_hash_entry *h; |
| 2694 bfd_vma val; | 2685 bfd_vma val; |
| 2695 bfd_boolean reject, is_call; | 2686 bfd_boolean nonbranch, is_call; |
| 2696 struct function_info *caller; | 2687 struct function_info *caller; |
| 2697 struct call_info *callee; | 2688 struct call_info *callee; |
| 2698 | 2689 |
| 2699 reject = FALSE; | |
| 2700 r_type = ELF32_R_TYPE (irela->r_info); | 2690 r_type = ELF32_R_TYPE (irela->r_info); |
| 2701 if (r_type != R_SPU_REL16 | 2691 nonbranch = r_type != R_SPU_REL16 && r_type != R_SPU_ADDR16; |
| 2702 » && r_type != R_SPU_ADDR16) | |
| 2703 » { | |
| 2704 » reject = TRUE; | |
| 2705 » if (!(call_tree && spu_hash_table (info)->params->auto_overlay)) | |
| 2706 » continue; | |
| 2707 » } | |
| 2708 | 2692 |
| 2709 r_indx = ELF32_R_SYM (irela->r_info); | 2693 r_indx = ELF32_R_SYM (irela->r_info); |
| 2710 if (!get_sym_h (&h, &sym, &sym_sec, psyms, r_indx, sec->owner)) | 2694 if (!get_sym_h (&h, &sym, &sym_sec, psyms, r_indx, sec->owner)) |
| 2711 return FALSE; | 2695 return FALSE; |
| 2712 | 2696 |
| 2713 if (sym_sec == NULL | 2697 if (sym_sec == NULL |
| 2714 || sym_sec->output_section == bfd_abs_section_ptr) | 2698 || sym_sec->output_section == bfd_abs_section_ptr) |
| 2715 continue; | 2699 continue; |
| 2716 | 2700 |
| 2717 is_call = FALSE; | 2701 is_call = FALSE; |
| 2718 if (!reject) | 2702 if (!nonbranch) |
| 2719 { | 2703 { |
| 2720 unsigned char insn[4]; | 2704 unsigned char insn[4]; |
| 2721 | 2705 |
| 2722 if (!bfd_get_section_contents (sec->owner, sec, insn, | 2706 if (!bfd_get_section_contents (sec->owner, sec, insn, |
| 2723 irela->r_offset, 4)) | 2707 irela->r_offset, 4)) |
| 2724 return FALSE; | 2708 return FALSE; |
| 2725 if (is_branch (insn)) | 2709 if (is_branch (insn)) |
| 2726 { | 2710 { |
| 2727 is_call = (insn[0] & 0xfd) == 0x31; | 2711 is_call = (insn[0] & 0xfd) == 0x31; |
| 2728 priority = insn[1] & 0x0f; | 2712 priority = insn[1] & 0x0f; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2739 (_("%B(%A+0x%v): call to non-code section" | 2723 (_("%B(%A+0x%v): call to non-code section" |
| 2740 " %B(%A), analysis incomplete\n"), | 2724 " %B(%A), analysis incomplete\n"), |
| 2741 sec->owner, sec, irela->r_offset, | 2725 sec->owner, sec, irela->r_offset, |
| 2742 sym_sec->owner, sym_sec); | 2726 sym_sec->owner, sym_sec); |
| 2743 warned = TRUE; | 2727 warned = TRUE; |
| 2744 continue; | 2728 continue; |
| 2745 } | 2729 } |
| 2746 } | 2730 } |
| 2747 else | 2731 else |
| 2748 { | 2732 { |
| 2749 » reject = TRUE; | 2733 » nonbranch = TRUE; |
| 2750 » if (!(call_tree && spu_hash_table (info)->params->auto_overlay) | 2734 » if (is_hint (insn)) |
| 2751 » » || is_hint (insn)) | |
| 2752 continue; | 2735 continue; |
| 2753 } | 2736 } |
| 2754 } | 2737 } |
| 2755 | 2738 |
| 2756 if (reject) | 2739 if (nonbranch) |
| 2757 { | 2740 { |
| 2758 /* For --auto-overlay, count possible stubs we need for | 2741 /* For --auto-overlay, count possible stubs we need for |
| 2759 function pointer references. */ | 2742 function pointer references. */ |
| 2760 unsigned int sym_type; | 2743 unsigned int sym_type; |
| 2761 if (h) | 2744 if (h) |
| 2762 sym_type = h->type; | 2745 sym_type = h->type; |
| 2763 else | 2746 else |
| 2764 sym_type = ELF_ST_TYPE (sym->st_info); | 2747 sym_type = ELF_ST_TYPE (sym->st_info); |
| 2765 if (sym_type == STT_FUNC) | 2748 if (sym_type == STT_FUNC) |
| 2766 » spu_hash_table (info)->non_ovly_stub += 1; | 2749 » { |
| 2767 » continue; | 2750 » if (call_tree && spu_hash_table (info)->params->auto_overlay) |
| 2751 » » spu_hash_table (info)->non_ovly_stub += 1; |
| 2752 » /* If the symbol type is STT_FUNC then this must be a |
| 2753 » » function pointer initialisation. */ |
| 2754 » continue; |
| 2755 » } |
| 2756 » /* Ignore data references. */ |
| 2757 » if ((sym_sec->flags & (SEC_ALLOC | SEC_LOAD | SEC_CODE)) |
| 2758 » != (SEC_ALLOC | SEC_LOAD | SEC_CODE)) |
| 2759 » continue; |
| 2760 » /* Otherwise we probably have a jump table reloc for |
| 2761 » a switch statement or some other reference to a |
| 2762 » code label. */ |
| 2768 } | 2763 } |
| 2769 | 2764 |
| 2770 if (h) | 2765 if (h) |
| 2771 val = h->root.u.def.value; | 2766 val = h->root.u.def.value; |
| 2772 else | 2767 else |
| 2773 val = sym->st_value; | 2768 val = sym->st_value; |
| 2774 val += irela->r_addend; | 2769 val += irela->r_addend; |
| 2775 | 2770 |
| 2776 if (!call_tree) | 2771 if (!call_tree) |
| 2777 { | 2772 { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2806 if (callee == NULL) | 2801 if (callee == NULL) |
| 2807 return FALSE; | 2802 return FALSE; |
| 2808 | 2803 |
| 2809 callee->fun = find_function (sym_sec, val, info); | 2804 callee->fun = find_function (sym_sec, val, info); |
| 2810 if (callee->fun == NULL) | 2805 if (callee->fun == NULL) |
| 2811 return FALSE; | 2806 return FALSE; |
| 2812 callee->is_tail = !is_call; | 2807 callee->is_tail = !is_call; |
| 2813 callee->is_pasted = FALSE; | 2808 callee->is_pasted = FALSE; |
| 2814 callee->broken_cycle = FALSE; | 2809 callee->broken_cycle = FALSE; |
| 2815 callee->priority = priority; | 2810 callee->priority = priority; |
| 2816 callee->count = 1; | 2811 callee->count = nonbranch? 0 : 1; |
| 2817 if (callee->fun->last_caller != sec) | 2812 if (callee->fun->last_caller != sec) |
| 2818 { | 2813 { |
| 2819 callee->fun->last_caller = sec; | 2814 callee->fun->last_caller = sec; |
| 2820 callee->fun->call_count += 1; | 2815 callee->fun->call_count += 1; |
| 2821 } | 2816 } |
| 2822 if (!insert_callee (caller, callee)) | 2817 if (!insert_callee (caller, callee)) |
| 2823 free (callee); | 2818 free (callee); |
| 2824 else if (!is_call | 2819 else if (!is_call |
| 2825 && !callee->fun->is_func | 2820 && !callee->fun->is_func |
| 2826 && callee->fun->stack == 0) | 2821 && callee->fun->stack == 0) |
| (...skipping 1325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4152 | 4147 |
| 4153 /* Handle --auto-overlay. */ | 4148 /* Handle --auto-overlay. */ |
| 4154 | 4149 |
| 4155 static void | 4150 static void |
| 4156 spu_elf_auto_overlay (struct bfd_link_info *info) | 4151 spu_elf_auto_overlay (struct bfd_link_info *info) |
| 4157 { | 4152 { |
| 4158 bfd *ibfd; | 4153 bfd *ibfd; |
| 4159 bfd **bfd_arr; | 4154 bfd **bfd_arr; |
| 4160 struct elf_segment_map *m; | 4155 struct elf_segment_map *m; |
| 4161 unsigned int fixed_size, lo, hi; | 4156 unsigned int fixed_size, lo, hi; |
| 4157 unsigned int reserved; |
| 4162 struct spu_link_hash_table *htab; | 4158 struct spu_link_hash_table *htab; |
| 4163 unsigned int base, i, count, bfd_count; | 4159 unsigned int base, i, count, bfd_count; |
| 4164 unsigned int region, ovlynum; | 4160 unsigned int region, ovlynum; |
| 4165 asection **ovly_sections, **ovly_p; | 4161 asection **ovly_sections, **ovly_p; |
| 4166 unsigned int *ovly_map; | 4162 unsigned int *ovly_map; |
| 4167 FILE *script; | 4163 FILE *script; |
| 4168 unsigned int total_overlay_size, overlay_size; | 4164 unsigned int total_overlay_size, overlay_size; |
| 4169 const char *ovly_mgr_entry; | 4165 const char *ovly_mgr_entry; |
| 4170 struct elf_link_hash_entry *h; | 4166 struct elf_link_hash_entry *h; |
| 4171 struct _mos_param mos_param; | 4167 struct _mos_param mos_param; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 4187 } | 4183 } |
| 4188 fixed_size = hi + 1 - lo; | 4184 fixed_size = hi + 1 - lo; |
| 4189 | 4185 |
| 4190 if (!discover_functions (info)) | 4186 if (!discover_functions (info)) |
| 4191 goto err_exit; | 4187 goto err_exit; |
| 4192 | 4188 |
| 4193 if (!build_call_tree (info)) | 4189 if (!build_call_tree (info)) |
| 4194 goto err_exit; | 4190 goto err_exit; |
| 4195 | 4191 |
| 4196 htab = spu_hash_table (info); | 4192 htab = spu_hash_table (info); |
| 4197 if (htab->reserved == 0) | 4193 reserved = htab->params->auto_overlay_reserved; |
| 4194 if (reserved == 0) |
| 4198 { | 4195 { |
| 4199 struct _sum_stack_param sum_stack_param; | 4196 struct _sum_stack_param sum_stack_param; |
| 4200 | 4197 |
| 4201 sum_stack_param.emit_stack_syms = 0; | 4198 sum_stack_param.emit_stack_syms = 0; |
| 4202 sum_stack_param.overall_stack = 0; | 4199 sum_stack_param.overall_stack = 0; |
| 4203 if (!for_each_node (sum_stack, info, &sum_stack_param, TRUE)) | 4200 if (!for_each_node (sum_stack, info, &sum_stack_param, TRUE)) |
| 4204 goto err_exit; | 4201 goto err_exit; |
| 4205 htab->reserved = sum_stack_param.overall_stack + htab->extra_stack_space; | 4202 reserved = (sum_stack_param.overall_stack |
| 4203 » » + htab->params->extra_stack_space); |
| 4206 } | 4204 } |
| 4207 | 4205 |
| 4208 /* No need for overlays if everything already fits. */ | 4206 /* No need for overlays if everything already fits. */ |
| 4209 if (fixed_size + htab->reserved <= htab->local_store | 4207 if (fixed_size + reserved <= htab->local_store |
| 4210 && htab->params->ovly_flavour != ovly_soft_icache) | 4208 && htab->params->ovly_flavour != ovly_soft_icache) |
| 4211 { | 4209 { |
| 4212 htab->params->auto_overlay = 0; | 4210 htab->params->auto_overlay = 0; |
| 4213 return; | 4211 return; |
| 4214 } | 4212 } |
| 4215 | 4213 |
| 4216 uos_param.exclude_input_section = 0; | 4214 uos_param.exclude_input_section = 0; |
| 4217 uos_param.exclude_output_section | 4215 uos_param.exclude_output_section |
| 4218 = bfd_get_section_by_name (info->output_bfd, ".interrupt"); | 4216 = bfd_get_section_by_name (info->output_bfd, ".interrupt"); |
| 4219 | 4217 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4312 if (!ok) | 4310 if (!ok) |
| 4313 { | 4311 { |
| 4314 info->callbacks->einfo (_("sorry, no support for duplicate " | 4312 info->callbacks->einfo (_("sorry, no support for duplicate " |
| 4315 "object files in auto-overlay script\n")); | 4313 "object files in auto-overlay script\n")); |
| 4316 bfd_set_error (bfd_error_bad_value); | 4314 bfd_set_error (bfd_error_bad_value); |
| 4317 goto err_exit; | 4315 goto err_exit; |
| 4318 } | 4316 } |
| 4319 } | 4317 } |
| 4320 free (bfd_arr); | 4318 free (bfd_arr); |
| 4321 | 4319 |
| 4322 fixed_size += htab->reserved; | 4320 fixed_size += reserved; |
| 4323 fixed_size += htab->non_ovly_stub * ovl_stub_size (htab->params); | 4321 fixed_size += htab->non_ovly_stub * ovl_stub_size (htab->params); |
| 4324 if (fixed_size + mos_param.max_overlay_size <= htab->local_store) | 4322 if (fixed_size + mos_param.max_overlay_size <= htab->local_store) |
| 4325 { | 4323 { |
| 4326 if (htab->params->ovly_flavour == ovly_soft_icache) | 4324 if (htab->params->ovly_flavour == ovly_soft_icache) |
| 4327 { | 4325 { |
| 4328 /* Stubs in the non-icache area are bigger. */ | 4326 /* Stubs in the non-icache area are bigger. */ |
| 4329 fixed_size += htab->non_ovly_stub * 16; | 4327 fixed_size += htab->non_ovly_stub * 16; |
| 4330 /* Space for icache manager tables. | 4328 /* Space for icache manager tables. |
| 4331 a) Tag array, one quadword per cache line. | 4329 a) Tag array, one quadword per cache line. |
| 4332 - word 0: ia address of present line, init to zero. */ | 4330 - word 0: ia address of present line, init to zero. */ |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4351 } | 4349 } |
| 4352 } | 4350 } |
| 4353 | 4351 |
| 4354 if (fixed_size + mos_param.max_overlay_size > htab->local_store) | 4352 if (fixed_size + mos_param.max_overlay_size > htab->local_store) |
| 4355 info->callbacks->einfo (_("non-overlay size of 0x%v plus maximum overlay " | 4353 info->callbacks->einfo (_("non-overlay size of 0x%v plus maximum overlay " |
| 4356 "size of 0x%v exceeds local store\n"), | 4354 "size of 0x%v exceeds local store\n"), |
| 4357 (bfd_vma) fixed_size, | 4355 (bfd_vma) fixed_size, |
| 4358 (bfd_vma) mos_param.max_overlay_size); | 4356 (bfd_vma) mos_param.max_overlay_size); |
| 4359 | 4357 |
| 4360 /* Now see if we should put some functions in the non-overlay area. */ | 4358 /* Now see if we should put some functions in the non-overlay area. */ |
| 4361 else if (fixed_size < htab->overlay_fixed) | 4359 else if (fixed_size < htab->params->auto_overlay_fixed) |
| 4362 { | 4360 { |
| 4363 unsigned int max_fixed, lib_size; | 4361 unsigned int max_fixed, lib_size; |
| 4364 | 4362 |
| 4365 max_fixed = htab->local_store - mos_param.max_overlay_size; | 4363 max_fixed = htab->local_store - mos_param.max_overlay_size; |
| 4366 if (max_fixed > htab->overlay_fixed) | 4364 if (max_fixed > htab->params->auto_overlay_fixed) |
| 4367 » max_fixed = htab->overlay_fixed; | 4365 » max_fixed = htab->params->auto_overlay_fixed; |
| 4368 lib_size = max_fixed - fixed_size; | 4366 lib_size = max_fixed - fixed_size; |
| 4369 lib_size = auto_ovl_lib_functions (info, lib_size); | 4367 lib_size = auto_ovl_lib_functions (info, lib_size); |
| 4370 if (lib_size == (unsigned int) -1) | 4368 if (lib_size == (unsigned int) -1) |
| 4371 goto err_exit; | 4369 goto err_exit; |
| 4372 fixed_size = max_fixed - lib_size; | 4370 fixed_size = max_fixed - lib_size; |
| 4373 } | 4371 } |
| 4374 | 4372 |
| 4375 /* Build an array of sections, suitably sorted to place into | 4373 /* Build an array of sections, suitably sorted to place into |
| 4376 overlays. */ | 4374 overlays. */ |
| 4377 ovly_sections = bfd_malloc (2 * count * sizeof (*ovly_sections)); | 4375 ovly_sections = bfd_malloc (2 * count * sizeof (*ovly_sections)); |
| (...skipping 1089 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5467 | 5465 |
| 5468 #define elf_backend_additional_program_headers spu_elf_additional_program_heade
rs | 5466 #define elf_backend_additional_program_headers spu_elf_additional_program_heade
rs |
| 5469 #define elf_backend_modify_segment_map spu_elf_modify_segment_map | 5467 #define elf_backend_modify_segment_map spu_elf_modify_segment_map |
| 5470 #define elf_backend_modify_program_headers spu_elf_modify_program_headers | 5468 #define elf_backend_modify_program_headers spu_elf_modify_program_headers |
| 5471 #define elf_backend_post_process_headers spu_elf_post_process_headers | 5469 #define elf_backend_post_process_headers spu_elf_post_process_headers |
| 5472 #define elf_backend_fake_sections spu_elf_fake_sections | 5470 #define elf_backend_fake_sections spu_elf_fake_sections |
| 5473 #define elf_backend_special_sections spu_elf_special_sections | 5471 #define elf_backend_special_sections spu_elf_special_sections |
| 5474 #define bfd_elf32_bfd_final_link spu_elf_final_link | 5472 #define bfd_elf32_bfd_final_link spu_elf_final_link |
| 5475 | 5473 |
| 5476 #include "elf32-target.h" | 5474 #include "elf32-target.h" |
| OLD | NEW |