diff options
author | David S. Miller <davem@redhat.com> | 2010-02-13 00:01:20 +0000 |
---|---|---|
committer | David S. Miller <davem@redhat.com> | 2010-02-13 00:01:20 +0000 |
commit | 0da6fa6c5b5a2b4fc5b64fbae25ccd9509210860 (patch) | |
tree | a304521001df4408cebe902130aaef71886598d7 /gold/sparc.cc | |
parent | bbad93606c8371d432b810d8d1f606f773060018 (diff) | |
download | gdb-0da6fa6c5b5a2b4fc5b64fbae25ccd9509210860.zip gdb-0da6fa6c5b5a2b4fc5b64fbae25ccd9509210860.tar.gz gdb-0da6fa6c5b5a2b4fc5b64fbae25ccd9509210860.tar.bz2 |
* output.h (Output_reloc<SHT_REL>::Output_reloc): Add
is_symbolless parameter.
(Output_reloc<SHT_REL>::is_symbolless): New.
(Output_reloc<SHT_REL>::is_symbolless_): New.
(Output_reloc<SHT_REL>::type_): Decrease to 29 bits.
(Output_reloc<SHT_RELA>::Output_reloc): Add is_symbolless parameter.
(Output_reloc<SHT_RELA>::is_symbolless): New.
(Output_data_reloc::add_global): Handle is_symbolless.
(Output_data_reloc::add_global_relative): Likewise.
(Output_data_reloc::add_local): Likewise.
(Output_data_reloc::add_local_relative): Likewise.
(Output_data_reloc::add_symbolless_global_addend): New.
(Output_data_reloc::add_symbolless_local_addend): New.
* output.cc (Output_reloc<SHT_REL>::Output_reloc): Handle
is_symbolless.
(Output_reloc::set_needs_dynsym_index): Test ->is_symbolless_
instead of ->is_relative_
(Output_reloc::write): Likewise.
(Output_reloc::get_symbol_index): Return 0 when ->is_symbolless_
(Output_reloc::write_rel): Simplify.
* sparc.cc (Target_sparc::Scan::local): Use
->add_symbolless_local_addend as needed.
(Target_sparc::Scan::global): Use ->add_symbolless_global_addend as
needed. Also, emit appropriate unaligned vs. aligned dynamic reloc
based upon relocation offset.
Diffstat (limited to 'gold/sparc.cc')
-rw-r--r-- | gold/sparc.cc | 94 |
1 files changed, 64 insertions, 30 deletions
diff --git a/gold/sparc.cc b/gold/sparc.cc index 234c5f5..ab25203 100644 --- a/gold/sparc.cc +++ b/gold/sparc.cc @@ -1686,20 +1686,11 @@ Target_sparc<size, big_endian>::Scan::local( } else { - unsigned int shndx = lsym.get_st_shndx(); - bool is_ordinary; - gold_assert(lsym.get_st_value() == 0); - shndx = object->adjust_sym_shndx(r_sym, shndx, - &is_ordinary); - if (!is_ordinary) - object->error(_("section symbol %u has bad shndx %u"), - r_sym, shndx); - else - rela_dyn->add_local_section(object, shndx, - r_type, output_section, - data_shndx, reloc.get_r_offset(), - reloc.get_r_addend()); + rela_dyn->add_symbolless_local_addend(object, r_sym, orig_r_type, + output_section, data_shndx, + reloc.get_r_offset(), + reloc.get_r_addend()); } } break; @@ -1847,13 +1838,15 @@ Target_sparc<size, big_endian>::Scan::local( if (!object->local_has_got_offset(r_sym, GOT_TYPE_TLS_OFFSET)) { Reloc_section* rela_dyn = target->rela_dyn_section(layout); + unsigned int off = got->add_constant(0); + + object->set_local_got_offset(r_sym, GOT_TYPE_TLS_OFFSET, off); - got->add_local_with_rela(object, r_sym, - GOT_TYPE_TLS_OFFSET, - rela_dyn, - (size == 64 ? - elfcpp::R_SPARC_TLS_TPOFF64 : - elfcpp::R_SPARC_TLS_TPOFF32)); + rela_dyn->add_symbolless_local_addend(object, r_sym, + (size == 64 ? + elfcpp::R_SPARC_TLS_TPOFF64 : + elfcpp::R_SPARC_TLS_TPOFF32), + got, off, 0); } } else if (optimized_type != tls::TLSOPT_TO_LE) @@ -1869,9 +1862,9 @@ Target_sparc<size, big_endian>::Scan::local( gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION); unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); Reloc_section* rela_dyn = target->rela_dyn_section(layout); - rela_dyn->add_local(object, r_sym, r_type, - output_section, data_shndx, - reloc.get_r_offset(), 0); + rela_dyn->add_symbolless_local_addend(object, r_sym, r_type, + output_section, data_shndx, + reloc.get_r_offset(), 0); } break; } @@ -2046,6 +2039,38 @@ Target_sparc<size, big_endian>::Scan::global( // Make a dynamic relocation if necessary. if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF)) { + unsigned int r_off = reloc.get_r_offset(); + + // The assembler can sometimes emit unaligned relocations + // for dwarf2 cfi directives. + switch (r_type) + { + case elfcpp::R_SPARC_16: + if (r_off & 0x1) + orig_r_type = r_type = elfcpp::R_SPARC_UA16; + break; + case elfcpp::R_SPARC_32: + if (r_off & 0x3) + orig_r_type = r_type = elfcpp::R_SPARC_UA32; + break; + case elfcpp::R_SPARC_64: + if (r_off & 0x7) + orig_r_type = r_type = elfcpp::R_SPARC_UA64; + break; + case elfcpp::R_SPARC_UA16: + if (!(r_off & 0x1)) + orig_r_type = r_type = elfcpp::R_SPARC_16; + break; + case elfcpp::R_SPARC_UA32: + if (!(r_off & 0x3)) + orig_r_type = r_type = elfcpp::R_SPARC_32; + break; + case elfcpp::R_SPARC_UA64: + if (!(r_off & 0x7)) + orig_r_type = r_type = elfcpp::R_SPARC_64; + break; + } + if (gsym->may_need_copy_reloc()) { target->copy_reloc(symtab, layout, object, @@ -2066,10 +2091,19 @@ Target_sparc<size, big_endian>::Scan::global( Reloc_section* rela_dyn = target->rela_dyn_section(layout); check_non_pic(object, r_type); - rela_dyn->add_global(gsym, orig_r_type, output_section, - object, data_shndx, - reloc.get_r_offset(), - reloc.get_r_addend()); + if (gsym->is_from_dynobj() + || gsym->is_undefined() + || gsym->is_preemptible()) + rela_dyn->add_global(gsym, orig_r_type, output_section, + object, data_shndx, + reloc.get_r_offset(), + reloc.get_r_addend()); + else + rela_dyn->add_symbolless_global_addend(gsym, orig_r_type, + output_section, + object, data_shndx, + reloc.get_r_offset(), + reloc.get_r_addend()); } } } @@ -2201,10 +2235,10 @@ Target_sparc<size, big_endian>::Scan::global( if (parameters->options().shared()) { Reloc_section* rela_dyn = target->rela_dyn_section(layout); - rela_dyn->add_global(gsym, orig_r_type, - output_section, object, - data_shndx, reloc.get_r_offset(), - 0); + rela_dyn->add_symbolless_global_addend(gsym, orig_r_type, + output_section, object, + data_shndx, reloc.get_r_offset(), + 0); } break; |