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 |