WIP MachO binutils port assisted by AI I may consider upstreaming this in the future.
0

Configure Feed

Select the types of activity you want to include in your feed.

Fix symbol values and relocation addends for relocatable links.

The fix for PR 19291 broke some other cases where -r is used with scripts,
as reported in PR 22266. The original fix for PR 22266 ended up breaking
many cases for REL targets, where the addends are stored in the section data,
and are not being adjusted properly.

The problem was basically that in a relocatable output file (ET_REL),
symbol values are supposed to be relative to the start address of their
section. Usually in a relocatable file, all sections start at 0, so the
failure to get this right is often irrelevant, but with a linker script,
we occasionally see an output section whose starting address is not 0,
and gold would occasionally write a symbol with its relocated value instead
of its section-relative value.

This patch reverts the recent fix for PR 22266 as well as my original fix
for PR 19291. The original fix moved the symbol value adjustment to
write_local_symbols, but neglected to undo a few places where the adjustment
was also being applied, resulting in an occasional double adjustment. The
more recent fix removed those other adjustments, but then failed to
re-account for the adjustment when rewriting the relocations on REL targets.

With the old attempts reverted, we now apply the symbol value adjustment to
the one case that had been missed (non-section symbols in merge sections).
But now we also need to account for the adjustment when rewriting the addends
for RELA relocations.

gold/
PR gold/19291
PR gold/22266
* object.cc (Sized_relobj_file::compute_final_local_value_internal):
Revert changes from 2017-11-08 patch. Adjust symbol value in
relocatable links for non-section symbols.
(Sized_relobj_file::compute_final_local_value): Revert changes from
2017-11-08 patch.
(Sized_relobj_file::do_finalize_local_symbols): Likewise.
(Sized_relobj_file::write_local_symbols): Revert changes from
2015-11-25 patch.
* object.h (Sized_relobj_file::compute_final_local_value_internal):
Revert changes from 2017-11-08 patch.
* powerpc.cc (Target_powerpc::relocate_relocs): Adjust addend for
relocatable links.
* target-reloc.h (relocate_relocs): Adjust addend for relocatable links.
* testsuite/pr22266_a.c (hello): New function.
* testsuite/pr22266_main.c (main): Add test for merge sections.
* testsuite/pr22266_script.t: Add rule for .rodata.

Cary Coutant (Nov 27, 2017, 5:32 PM -0800) 033bfb73 57c1b681

+92 -28
+21
gold/ChangeLog
··· 1 + 2017-11-27 Cary Coutant <ccoutant@gmail.com> 2 + 3 + PR gold/19291 4 + PR gold/22266 5 + * object.cc (Sized_relobj_file::compute_final_local_value_internal): 6 + Revert changes from 2017-11-08 patch. Adjust symbol value in 7 + relocatable links for non-section symbols. 8 + (Sized_relobj_file::compute_final_local_value): Revert changes from 9 + 2017-11-08 patch. 10 + (Sized_relobj_file::do_finalize_local_symbols): Likewise. 11 + (Sized_relobj_file::write_local_symbols): Revert changes from 12 + 2015-11-25 patch. 13 + * object.h (Sized_relobj_file::compute_final_local_value_internal): 14 + Revert changes from 2017-11-08 patch. 15 + * powerpc.cc (Target_powerpc::relocate_relocs): Adjust addend for 16 + relocatable links. 17 + * target-reloc.h (relocate_relocs): Adjust addend for relocatable links. 18 + * testsuite/pr22266_a.c (hello): New function. 19 + * testsuite/pr22266_main.c (main): Add test for merge sections. 20 + * testsuite/pr22266_script.t: Add rule for .rodata. 21 + 1 22 2017-11-19 Ian Lance Taylor <iant@google.com> 2 23 Cary Coutant <ccoutant@gmail.com> 3 24
+26 -16
gold/object.cc
··· 2318 2318 unsigned int r_sym, 2319 2319 const Symbol_value<size>* lv_in, 2320 2320 Symbol_value<size>* lv_out, 2321 + bool relocatable, 2321 2322 const Output_sections& out_sections, 2322 2323 const std::vector<Address>& out_offsets, 2323 2324 const Symbol_table* symtab) ··· 2404 2405 { 2405 2406 // This is not a section symbol. We can determine 2406 2407 // the final value now. 2407 - lv_out->set_output_value( 2408 - os->output_address(this, shndx, lv_in->input_value())); 2408 + uint64_t value = 2409 + os->output_address(this, shndx, lv_in->input_value()); 2410 + if (relocatable) 2411 + value -= os->address(); 2412 + lv_out->set_output_value(value); 2409 2413 } 2410 2414 else if (!os->find_starting_output_address(this, shndx, &start)) 2411 2415 { ··· 2419 2423 os->find_relaxed_input_section(this, shndx); 2420 2424 if (posd != NULL) 2421 2425 { 2422 - lv_out->set_output_value(posd->address()); 2426 + uint64_t value = posd->address(); 2427 + if (relocatable) 2428 + value -= os->address(); 2429 + lv_out->set_output_value(value); 2423 2430 } 2424 2431 else 2425 2432 lv_out->set_output_value(os->address()); ··· 2428 2435 { 2429 2436 // We have to consider the addend to determine the 2430 2437 // value to use in a relocation. START is the start 2431 - // of this input section. 2438 + // of this input section. If we are doing a relocatable 2439 + // link, use offset from start output section instead of 2440 + // address. 2441 + Address adjusted_start = 2442 + relocatable ? start - os->address() : start; 2432 2443 Merged_symbol_value<size>* msv = 2433 2444 new Merged_symbol_value<size>(lv_in->input_value(), 2434 - start); 2445 + adjusted_start); 2435 2446 lv_out->set_merged_symbol_value(msv); 2436 2447 } 2437 2448 } ··· 2442 2453 + secoffset 2443 2454 + lv_in->input_value()); 2444 2455 else 2445 - lv_out->set_output_value(os->address() 2456 + lv_out->set_output_value((relocatable ? 0 : os->address()) 2446 2457 + secoffset 2447 2458 + lv_in->input_value()); 2448 2459 } ··· 2468 2479 const Symbol_table* symtab) 2469 2480 { 2470 2481 // This is just a wrapper of compute_final_local_value_internal. 2482 + const bool relocatable = parameters->options().relocatable(); 2471 2483 const Output_sections& out_sections(this->output_sections()); 2472 2484 const std::vector<Address>& out_offsets(this->section_offsets()); 2473 2485 return this->compute_final_local_value_internal(r_sym, lv_in, lv_out, 2474 - out_sections, out_offsets, 2475 - symtab); 2486 + relocatable, out_sections, 2487 + out_offsets, symtab); 2476 2488 } 2477 2489 2478 2490 // Finalize the local symbols. Here we set the final value in ··· 2492 2504 const unsigned int loccount = this->local_symbol_count_; 2493 2505 this->local_symbol_offset_ = off; 2494 2506 2507 + const bool relocatable = parameters->options().relocatable(); 2495 2508 const Output_sections& out_sections(this->output_sections()); 2496 2509 const std::vector<Address>& out_offsets(this->section_offsets()); 2497 2510 ··· 2500 2513 Symbol_value<size>* lv = &this->local_values_[i]; 2501 2514 2502 2515 Compute_final_local_value_status cflv_status = 2503 - this->compute_final_local_value_internal(i, lv, lv, out_sections, 2504 - out_offsets, symtab); 2516 + this->compute_final_local_value_internal(i, lv, lv, relocatable, 2517 + out_sections, out_offsets, 2518 + symtab); 2505 2519 switch (cflv_status) 2506 2520 { 2507 2521 case CFLV_OK: ··· 2666 2680 elfcpp::Sym<size, big_endian> isym(psyms); 2667 2681 2668 2682 Symbol_value<size>& lv(this->local_values_[i]); 2669 - typename elfcpp::Elf_types<size>::Elf_Addr sym_value = lv.value(this, 0); 2670 2683 2671 2684 bool is_ordinary; 2672 2685 unsigned int st_shndx = this->adjust_sym_shndx(i, isym.get_st_shndx(), ··· 2676 2689 gold_assert(st_shndx < out_sections.size()); 2677 2690 if (out_sections[st_shndx] == NULL) 2678 2691 continue; 2679 - // In relocatable object files symbol values are section relative. 2680 - if (parameters->options().relocatable()) 2681 - sym_value -= out_sections[st_shndx]->address(); 2682 2692 st_shndx = out_sections[st_shndx]->out_shndx(); 2683 2693 if (st_shndx >= elfcpp::SHN_LORESERVE) 2684 2694 { ··· 2698 2708 gold_assert(isym.get_st_name() < strtab_size); 2699 2709 const char* name = pnames + isym.get_st_name(); 2700 2710 osym.put_st_name(sympool->get_offset(name)); 2701 - osym.put_st_value(sym_value); 2711 + osym.put_st_value(lv.value(this, 0)); 2702 2712 osym.put_st_size(isym.get_st_size()); 2703 2713 osym.put_st_info(isym.get_st_info()); 2704 2714 osym.put_st_other(isym.get_st_other()); ··· 2716 2726 gold_assert(isym.get_st_name() < strtab_size); 2717 2727 const char* name = pnames + isym.get_st_name(); 2718 2728 osym.put_st_name(dynpool->get_offset(name)); 2719 - osym.put_st_value(sym_value); 2729 + osym.put_st_value(lv.value(this, 0)); 2720 2730 osym.put_st_size(isym.get_st_size()); 2721 2731 osym.put_st_info(isym.get_st_info()); 2722 2732 osym.put_st_other(isym.get_st_other());
+3 -1
gold/object.h
··· 2772 2772 // LV_IN points to a local symbol value containing the input value. 2773 2773 // LV_OUT points to a local symbol value storing the final output value, 2774 2774 // which must not be a merged symbol value since before calling this 2775 - // method to avoid memory leak. OUT_SECTIONS is an array of output 2775 + // method to avoid memory leak. RELOCATABLE indicates whether we are 2776 + // linking a relocatable output. OUT_SECTIONS is an array of output 2776 2777 // sections. OUT_OFFSETS is an array of offsets of the sections. SYMTAB 2777 2778 // points to a symbol table. 2778 2779 // ··· 2784 2785 compute_final_local_value_internal(unsigned int r_sym, 2785 2786 const Symbol_value<size>* lv_in, 2786 2787 Symbol_value<size>* lv_out, 2788 + bool relocatable, 2787 2789 const Output_sections& out_sections, 2788 2790 const std::vector<Address>& out_offsets, 2789 2791 const Symbol_table* symtab);
+13 -4
gold/powerpc.cc
··· 9734 9734 gold_assert(got2_addend != invalid_address); 9735 9735 } 9736 9736 9737 + const bool relocatable = parameters->options().relocatable(); 9738 + 9737 9739 unsigned char* pwrite = reloc_view; 9738 9740 bool zap_next = false; 9739 9741 for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size) ··· 9829 9831 // In an object file, r_offset is an offset within the section. 9830 9832 // In an executable or dynamic object, generated by 9831 9833 // --emit-relocs, r_offset is an absolute address. 9832 - if (!parameters->options().relocatable()) 9834 + if (!relocatable) 9833 9835 { 9834 9836 offset += view_address; 9835 9837 if (static_cast<Address>(offset_in_output_section) != invalid_address) ··· 9842 9844 else if (strategy == Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA) 9843 9845 { 9844 9846 const Symbol_value<size>* psymval = object->local_symbol(orig_r_sym); 9845 - gold_assert(os != NULL); 9846 - addend = psymval->value(object, addend) - os->address(); 9847 + addend = psymval->value(object, addend); 9848 + // In a relocatable link, the symbol value is relative to 9849 + // the start of the output section. For a non-relocatable 9850 + // link, we need to adjust the addend. 9851 + if (!relocatable) 9852 + { 9853 + gold_assert(os != NULL); 9854 + addend -= os->address(); 9855 + } 9847 9856 } 9848 9857 else if (strategy == Relocatable_relocs::RELOC_SPECIAL) 9849 9858 { ··· 9866 9875 else 9867 9876 gold_unreachable(); 9868 9877 9869 - if (!parameters->options().relocatable()) 9878 + if (!relocatable) 9870 9879 { 9871 9880 if (r_type == elfcpp::R_POWERPC_GOT_TLSGD16 9872 9881 || r_type == elfcpp::R_POWERPC_GOT_TLSGD16_LO
+14 -5
gold/target-reloc.h
··· 755 755 756 756 unsigned char* pwrite = reloc_view; 757 757 758 + const bool relocatable = parameters->options().relocatable(); 759 + 758 760 for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size) 759 761 { 760 762 Relocatable_relocs::Reloc_strategy strategy = relinfo->rr->strategy(i); ··· 857 859 // In an object file, r_offset is an offset within the section. 858 860 // In an executable or dynamic object, generated by 859 861 // --emit-relocs, r_offset is an absolute address. 860 - if (!parameters->options().relocatable()) 862 + if (!relocatable) 861 863 { 862 864 new_offset += view_address; 863 865 if (offset_in_output_section != invalid_address) ··· 892 894 { 893 895 case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA: 894 896 { 895 - typename elfcpp::Elf_types<size>::Elf_Swxword addend; 896 - addend = Classify_reloc::get_r_addend(&reloc); 897 - gold_assert(os != NULL); 898 - addend = psymval->value(object, addend) - os->address(); 897 + typename elfcpp::Elf_types<size>::Elf_Swxword addend 898 + = Classify_reloc::get_r_addend(&reloc); 899 + addend = psymval->value(object, addend); 900 + // In a relocatable link, the symbol value is relative to 901 + // the start of the output section. For a non-relocatable 902 + // link, we need to adjust the addend. 903 + if (!relocatable) 904 + { 905 + gold_assert(os != NULL); 906 + addend -= os->address(); 907 + } 899 908 Classify_reloc::put_r_addend(&reloc_write, addend); 900 909 } 901 910 break;
+8
gold/testsuite/pr22266_a.c
··· 3 3 4 4 __attribute__((section(".data.rel.ro.a"))) 5 5 int *p_int_from_a_2 = &int_from_a_1; 6 + 7 + const char *hello (void); 8 + 9 + const char * 10 + hello (void) 11 + { 12 + return "XXXHello, world!" + 3; 13 + }
+4
gold/testsuite/pr22266_main.c
··· 1 1 #include <stdlib.h> 2 + #include <string.h> 2 3 3 4 extern int *p_int_from_a_2; 5 + extern const char *hello (void); 4 6 5 7 int main (void) { 6 8 if (*p_int_from_a_2 != 0x11223344) 9 + abort (); 10 + if (strcmp(hello(), "Hello, world!") != 0) 7 11 abort (); 8 12 return 0; 9 13 }
+3 -2
gold/testsuite/pr22266_script.t
··· 8 8 .text : { 9 9 *(.text*) 10 10 } 11 - .rodata.cst16 : { 12 - *(.rodata.cst16*) 11 + .rodata : 12 + { 13 + *(.rodata .rodata.* .gnu.linkonce.r.*) 13 14 } 14 15 .data.rel.ro : { 15 16 *(.data.rel.ro*)