|
View:
New views
1 Messages
—
Rating Filter:
Alert me
|
|
|
[commit, spu] Handle non-branch relocs when building call graphHello,
when using a software i-cache compiler on the SPU that splits functions up into multiple sections, the linker currently may not always recognize all part of that function. The unrecognized sections will then be treated as "pasted" sections (like .init) that must join the preceding section. This can cause suboptimal placement decisions or even cache line overflows. The reason why sections may not be recognized as part of a function is that mark_functions_via_relocs currently does not handle relocations on anything but branch instructions. This means that parts of function code that are reachable only via a code label reference from anything but a branch (e.g. jump table entries or other references to load a code label as data) will be ignored. The following patch fixes this problem by handling such references as well. Note that while they must contribute to the call graph, they do not require stubs to be generated in the software i-cache case; this is reflected by setting the call_info.count field to zero for these cases. Tested with no regressions on spu-elf on mainline and the 2_20 branch. Approved off-line by Alan Modra; committed to mainline and branch. Bye, Ulrich 2009-11-03 Alan Modra <amodra@...> Ulrich Weigand <uweigand@...> * elf32-spu.c (mark_functions_via_relocs): Handle non-branch relocs (jump tables or other references to code labels) as well. diff -urNp src.orig/bfd/elf32-spu.c src/bfd/elf32-spu.c --- src.orig/bfd/elf32-spu.c 2009-11-02 16:26:03.000000000 +0100 +++ src/bfd/elf32-spu.c 2009-11-02 16:33:56.000000000 +0100 @@ -2670,19 +2670,12 @@ mark_functions_via_relocs (asection *sec Elf_Internal_Sym *sym; struct elf_link_hash_entry *h; bfd_vma val; - bfd_boolean reject, is_call; + bfd_boolean nonbranch, is_call; struct function_info *caller; struct call_info *callee; - reject = FALSE; r_type = ELF32_R_TYPE (irela->r_info); - if (r_type != R_SPU_REL16 - && r_type != R_SPU_ADDR16) - { - reject = TRUE; - if (!(call_tree && spu_hash_table (info)->params->auto_overlay)) - continue; - } + nonbranch = r_type != R_SPU_REL16 && r_type != R_SPU_ADDR16; r_indx = ELF32_R_SYM (irela->r_info); if (!get_sym_h (&h, &sym, &sym_sec, psyms, r_indx, sec->owner)) @@ -2693,7 +2686,7 @@ mark_functions_via_relocs (asection *sec continue; is_call = FALSE; - if (!reject) + if (!nonbranch) { unsigned char insn[4]; @@ -2724,14 +2717,13 @@ mark_functions_via_relocs (asection *sec } else { - reject = TRUE; - if (!(call_tree && spu_hash_table (info)->params->auto_overlay) - || is_hint (insn)) + nonbranch = TRUE; + if (is_hint (insn)) continue; } } - if (reject) + if (nonbranch) { /* For --auto-overlay, count possible stubs we need for function pointer references. */ @@ -2741,8 +2733,20 @@ mark_functions_via_relocs (asection *sec else sym_type = ELF_ST_TYPE (sym->st_info); if (sym_type == STT_FUNC) - spu_hash_table (info)->non_ovly_stub += 1; - continue; + { + if (call_tree && spu_hash_table (info)->params->auto_overlay) + spu_hash_table (info)->non_ovly_stub += 1; + /* If the symbol type is STT_FUNC then this must be a + function pointer initialisation. */ + continue; + } + /* Ignore data references. */ + if ((sym_sec->flags & (SEC_ALLOC | SEC_LOAD | SEC_CODE)) + != (SEC_ALLOC | SEC_LOAD | SEC_CODE)) + continue; + /* Otherwise we probably have a jump table reloc for + a switch statement or some other reference to a + code label. */ } if (h) @@ -2791,7 +2795,7 @@ mark_functions_via_relocs (asection *sec callee->is_pasted = FALSE; callee->broken_cycle = FALSE; callee->priority = priority; - callee->count = 1; + callee->count = nonbranch? 0 : 1; if (callee->fun->last_caller != sec) { callee->fun->last_caller = sec; -- Dr. Ulrich Weigand GNU Toolchain for Linux on System z and Cell BE Ulrich.Weigand@... |
| Free embeddable forum powered by Nabble | Forum Help |