PATCH: PR ld/4590: String merging breaks ia64 linker
H. J. Lu
hjl@lucon.org
Mon Jun 11 15:53:00 GMT 2007
More information about the Binutils mailing list
Mon Jun 11 15:53:00 GMT 2007
- Previous message (by thread): PATCH: PR ld/4590: String merging breaks ia64 linker
- Next message (by thread): PATCH: PR ld/4590: String merging breaks ia64 linker
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On Mon, Jun 11, 2007 at 10:37:45AM +0200, Andreas Schwab wrote: > "H. J. Lu" <hjl@lucon.org> writes: > > > Please provide me a testcase to show it. > > This is a better one, it tests more cases: > > .section .rodata.str1.8,"aMS", 1 > .LC1: .string "foo" > .LC2: .string "foo" > .LC3: .string "bar" > .LC4: .string "bar" > .LC5: .string "baz" > .LC6: .string "baz" > .section .data.rel.local,"aw" > .quad .LC2 > .quad .LC4 > .quad .LC5 > .section .rodata,"a" > .LC7: .string "mumble" > .balign 8 > .space 0x400000 > .text > addl r12=@ltoffx(.LC1),r1 ;; > addl r12=@ltoffx(.LC3),r1 ;; > addl r12=@ltoffx(.LC6),r1 ;; > addl r12=@ltoffx(.LC7),r1 ;; > Could you please try this patch? Thanks. H.J. --- 2007-06-11 H.J. Lu <hongjiu.lu@intel.com> PR ld/4590 * elfxx-ia64.c (sort_dyn_sym_info): Take a new argument for string merge. Keep the valid got_offset when removing duplicated entries for string merge (get_dyn_sym_info): Initialize the got_offset field to -1. Update call to sort_dyn_sym_info. (elfNN_ia64_relocate_section): Set addend_merged if the addend is merged with another one. Call sort_dyn_sym_info to sort array of addend and remove duplicates. --- bfd/elfxx-ia64.c.merged 2007-06-09 14:54:39.000000000 -0700 +++ bfd/elfxx-ia64.c 2007-06-11 08:47:53.000000000 -0700 @@ -2233,21 +2233,29 @@ addend_compare (const void *xp, const vo static unsigned int sort_dyn_sym_info (struct elfNN_ia64_dyn_sym_info *info, - unsigned int count) + unsigned int count, bfd_boolean merged) { bfd_vma curr, prev; - unsigned int i, dup, diff, dest, src, len; + unsigned int i, kept, dup, diff, dest, src, len; qsort (info, count, sizeof (*info), addend_compare); /* Find the first duplicate. */ - prev = info [0].addend; + kept = 0; + prev = info [kept].addend; for (i = 1; i < count; i++) { curr = info [i].addend; if (curr == prev) - break; + { + /* If a string is merged with another one, we need to make + sure that KEPT has a valid got_offset. */ + if (merged && info [kept].got_offset == (bfd_vma) -1) + info [kept].got_offset = info [i].got_offset; + break; + } prev = curr; + kept++; } /* Remove duplicates. */ @@ -2264,8 +2272,14 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn if (curr == prev) { for (src = i + 1; src < count; src++) - if (info [src].addend != curr) - break; + { + if (info [src].addend != curr) + break; + /* If a string is merged with another one, we need + to make sure that KEPT has a valid got_offset. */ + if (merged && info [kept].got_offset == (bfd_vma) -1) + info [kept].got_offset = info [src].got_offset; + } } else src = i; @@ -2273,13 +2287,19 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn if (src >= count) break; - /* Find the next duplicate. */ + /* Find the next duplicate. SRC will be kept. */ prev = info [src].addend; for (dup = src + 1; dup < count; dup++) { curr = info [dup].addend; if (curr == prev) - break; + { + /* If a string is merged with another one, we keep + the valid got_offset in SRC. */ + if (merged && info [src].got_offset == (bfd_vma) -1) + info [src].got_offset = info [dup].got_offset; + break; + } prev = curr; } @@ -2290,20 +2310,39 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn if (len == 1 && dup < count) { /* If we only move 1 element, we combine it with the next - one. Find the next different one. */ + one. We will keep DUP instead of SRC. Make sure that + DUP has a valid got_offset. */ + if (merged && info [dup].got_offset == (bfd_vma) -1) + info [dup].got_offset = info [src].got_offset; + + /* Find the next different one. */ for (diff = dup + 1, src++; diff < count; diff++, src++) - if (info [diff].addend != curr) - break; + { + if (info [diff].addend != curr) + break; + /* If a string is merged with another one, we need + to make sure that DUP has a valid got_offset. */ + if (merged && info [dup].got_offset == (bfd_vma) -1) + info [dup].got_offset = info [diff].got_offset; + } if (diff < count) { - /* Find the next duplicate. */ + /* Find the next duplicate. DIFF will be kept. */ prev = info [diff].addend; for (dup = diff + 1; dup < count; dup++) { curr = info [dup].addend; if (curr == prev) - break; + { + /* If a string is merged with another one, + we need to make sure that DIFF has a + valid got_offset. */ + if (merged + && info [diff].got_offset == (bfd_vma) -1) + info [diff].got_offset = info [dup].got_offset; + break; + } prev = curr; diff++; } @@ -2442,6 +2481,7 @@ has_space: /* Append the new one to the array. */ dyn_i = info + count; memset (dyn_i, 0, sizeof (*dyn_i)); + dyn_i->got_offset = (bfd_vma) -1; dyn_i->addend = addend; /* We increment count only since the new ones are unsorted and @@ -2454,7 +2494,7 @@ has_space: array isn't sorted. */ if (count != sorted_count) { - count = sort_dyn_sym_info (info, count); + count = sort_dyn_sym_info (info, count, FALSE); *count_p = count; *sorted_count_p = count; } @@ -4652,9 +4692,16 @@ elfNN_ia64_relocate_section (output_bfd, - sym_sec->output_section->vma - sym_sec->output_offset; } - - qsort (loc_h->info, loc_h->count, - sizeof (*loc_h->info), addend_compare); + + /* We may have introduced duplicated entries. We need + to remove them properly. */ + count = sort_dyn_sym_info (loc_h->info, loc_h->count, + TRUE); + if (count != loc_h->count) + { + loc_h->count = count; + loc_h->sorted_count = count; + } loc_h->sec_merge_done = 1; }
- Previous message (by thread): PATCH: PR ld/4590: String merging breaks ia64 linker
- Next message (by thread): PATCH: PR ld/4590: String merging breaks ia64 linker
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Binutils mailing list