diff options
author | Cary Coutant <ccoutant@gmail.com> | 2015-12-11 07:43:59 -0800 |
---|---|---|
committer | Cary Coutant <ccoutant@gmail.com> | 2016-01-11 18:51:18 -0800 |
commit | 4d625b70fc3fb7facc7159feb8d49b78ac6641f9 (patch) | |
tree | 437cb92850b8366f4a7ef33c773052e987b8e35b /gold/target-reloc.h | |
parent | b05b120205e697db6291abb95a8cd2be054f99e9 (diff) | |
download | gdb-4d625b70fc3fb7facc7159feb8d49b78ac6641f9.zip gdb-4d625b70fc3fb7facc7159feb8d49b78ac6641f9.tar.gz gdb-4d625b70fc3fb7facc7159feb8d49b78ac6641f9.tar.bz2 |
Refactor gold to enable support for MIPS-64 relocation format.
For MIPS-64, the r_info field in the relocation format is
replaced by several individual fields, including r_sym and
r_type. To enable support for this format, I've refactored
target-independent code to remove almost all uses of the r_info
field. (I've left alone a couple of routines used only for
incremental linking, which I can update if/when the MIPS target
adds support for incremental linking.)
For routines that are already templated on a Classify_reloc class
(namely, gc_process_relocs, relocate_section, and
relocate_relocs), I've extended the Classify_reloc interface to
include sh_type (which no longer needs to be a separate template
parameter) as well as get_r_sym() and get_r_type() methods for
extracting the r_sym and r_type fields. For
scan_relocatable_relocs, I've extended the
Default_scan_relocatable_relocs class by converting it to a class
template with Classify_reloc as a template parameter. For the
remaining routines that need to access r_sym, I've added a
virtual Target::get_r_sym() method with an override for the MIPS
target.
In elfcpp, I've added Mips64_rel, etc., accessor classes and
corresponding internal data structures. The MIPS target uses
these new classes within its own Mips_classify_reloc class.
The Mips64_ accessor classes also expose the r_ssym, r_type2,
and r_type3 fields from the relocation.
These changes should be functionally the same for all but the
MIPS target.
elfcpp/
* elfcpp.h (Mips64_rel, Mips64_rel_write): New classes.
(Mips64_rela, Mips64_rela_write): New classes.
* elfcpp_internal.h (Mips64_rel_data, Mips64_rela_data): New structs.
gold/
* gc.h (get_embedded_addend_size): Remove sh_type parameter.
(gc_process_relocs): Remove sh_type template parameter.
Use Classify_reloc to access r_sym, r_type, and r_addend fields.
* object.h (Sized_relobj_file::split_stack_adjust): Add target
parameter.
(Sized_relobj_file::split_stack_adjust_reltype): Likewise.
* reloc-types.h (Reloc_types::copy_reloc_addend): (SHT_REL and SHT_RELA
specializations) Remove.
* reloc.cc (Emit_relocs_strategy): Rename and move to target-reloc.h.
(Sized_relobj_file::emit_relocs_scan): Call Target::emit_relocs_scan().
(Sized_relobj_file::emit_relocs_scan_reltype): Remove.
(Sized_relobj_file::split_stack_adjust): Add target parameter.
Adjust all callers.
(Sized_relobj_file::split_stack_adjust_reltype): Likewise. Call
Target::get_r_sym() to get r_sym field from relocations.
(Track_relocs::next_symndx): Call Target::get_r_sym().
* target-reloc.h (scan_relocs): Remove sh_type template parameter;
add Classify_reloc template parameter. Use for accessing r_sym and
r_type.
(relocate_section): Likewise.
(Default_classify_reloc): New class (renamed and moved from reloc.cc).
(Default_scan_relocatable_relocs): Remove sh_type template parameter.
(Default_scan_relocatable_relocs::Reltype): New typedef.
(Default_scan_relocatable_relocs::reloc_size): New const.
(Default_scan_relocatable_relocs::sh_type): New const.
(Default_scan_relocatable_relocs::get_r_sym): New method.
(Default_scan_relocatable_relocs::get_r_type): New method.
(Default_emit_relocs_strategy): New class.
(scan_relocatable_relocs): Replace sh_type template parameter with
Scan_relocatable_relocs class. Use it to access r_sym and r_type
fields.
(relocate_relocs): Replace sh_type template parameter with
Classify_reloc class. Use it to access r_sym and r_type fields.
* target.h (Target::is_call_to_non_split): Replace r_type parameter
with pointer to relocation. Adjust all callers.
(Target::do_is_call_to_non_split): Likewise.
(Target::emit_relocs_scan): New virtual method.
(Sized_target::get_r_sym): New virtual method.
* target.cc (Target::do_is_call_to_non_split): Replace r_type parameter
with pointer to relocation.
* aarch64.cc (Target_aarch64::emit_relocs_scan): New method.
(Target_aarch64::Relocatable_size_for_reloc): Remove.
(Target_aarch64::gc_process_relocs): Use Default_classify_reloc.
(Target_aarch64::scan_relocs): Likewise.
(Target_aarch64::relocate_section): Likewise.
(Target_aarch64::Relocatable_size_for_reloc::get_size_for_reloc):
Remove.
(Target_aarch64::scan_relocatable_relocs): Use Default_classify_reloc.
(Target_aarch64::relocate_relocs): Use Default_classify_reloc.
* arm.cc (Target_arm::Arm_scan_relocatable_relocs): Remove sh_type
template parameter.
(Target_arm::emit_relocs_scan): New method.
(Target_arm::Relocatable_size_for_reloc): Replace with...
(Target_arm::Classify_reloc): ...this.
(Target_arm::gc_process_relocs): Use Classify_reloc.
(Target_arm::scan_relocs): Likewise.
(Target_arm::relocate_section): Likewise.
(Target_arm::scan_relocatable_relocs): Likewise.
(Target_arm::relocate_relocs): Likewise.
* i386.cc (Target_i386::emit_relocs_scan): New method.
(Target_i386::Relocatable_size_for_reloc): Replace with...
(Target_i386::Classify_reloc): ...this.
(Target_i386::gc_process_relocs): Use Classify_reloc.
(Target_i386::scan_relocs): Likewise.
(Target_i386::relocate_section): Likewise.
(Target_i386::scan_relocatable_relocs): Likewise.
(Target_i386::relocate_relocs): Likewise.
* mips.cc (Mips_scan_relocatable_relocs): Remove sh_type template
parameter.
(Mips_reloc_types): New class template.
(Mips_classify_reloc): New class template.
(Target_mips::Reltype): New typedef.
(Target_mips::Relatype): New typedef.
(Target_mips::emit_relocs_scan): New method.
(Target_mips::get_r_sym): New method.
(Target_mips::Relocatable_size_for_reloc): Replace with
Mips_classify_reloc.
(Target_mips::copy_reloc): Use Mips_classify_reloc.
(Target_mips::gc_process_relocs): Likewise.
(Target_mips::scan_relocs): Likewise.
(Target_mips::relocate_section): Likewise.
(Target_mips::scan_relocatable_relocs): Likewise.
(Target_mips::relocate_relocs): Likewise.
(mips_get_size_for_reloc): New function, factored out from
Relocatable_size_for_reloc::get_size_for_reloc.
(Target_mips::Scan::local): Use Mips_classify_reloc.
(Target_mips::Scan::global): Likewise.
(Target_mips::Relocate::relocate): Likewise.
* powerpc.cc (Target_powerpc::emit_relocs_scan): New method.
(Target_powerpc::Relocatable_size_for_reloc): Remove.
(Target_powerpc::gc_process_relocs): Use Default_classify_reloc.
(Target_powerpc::scan_relocs): Likewise.
(Target_powerpc::relocate_section): Likewise.
(Powerpc_scan_relocatable_reloc): Convert to class template.
(Powerpc_scan_relocatable_reloc::Reltype): New typedef.
(Powerpc_scan_relocatable_reloc::reloc_size): New const.
(Powerpc_scan_relocatable_reloc::sh_type): New const.
(Powerpc_scan_relocatable_reloc::get_r_sym): New method.
(Powerpc_scan_relocatable_reloc::get_r_type): New method.
(Target_powerpc::scan_relocatable_relocs): Use
Powerpc_scan_relocatable_reloc.
(Target_powerpc::relocate_relocs): Use Default_classify_reloc.
* s390.cc (Target_s390::emit_relocs_scan): New method.
(Target_s390::Relocatable_size_for_reloc): Remove.
(Target_s390::gc_process_relocs): Use Default_classify_reloc.
(Target_s390::scan_relocs): Likewise.
(Target_s390::relocate_section): Likewise.
(Target_s390::Relocatable_size_for_reloc::get_size_for_reloc):
Remove.
(Target_s390::scan_relocatable_relocs): Use Default_classify_reloc.
(Target_s390::relocate_relocs): Use Default_classify_reloc.
* sparc.cc (Target_sparc::emit_relocs_scan): New method.
(Target_sparc::Relocatable_size_for_reloc): Remove.
(Target_sparc::gc_process_relocs): Use Default_classify_reloc.
(Target_sparc::scan_relocs): Likewise.
(Target_sparc::relocate_section): Likewise.
(Target_sparc::Relocatable_size_for_reloc::get_size_for_reloc):
Remove.
(Target_sparc::scan_relocatable_relocs): Use Default_classify_reloc.
(Target_sparc::relocate_relocs): Use Default_classify_reloc.
* tilegx.cc (Target_tilegx::emit_relocs_scan): New method.
(Target_tilegx::Relocatable_size_for_reloc): Remove.
(Target_tilegx::gc_process_relocs): Use Default_classify_reloc.
(Target_tilegx::scan_relocs): Likewise.
(Target_tilegx::relocate_section): Likewise.
(Target_tilegx::Relocatable_size_for_reloc::get_size_for_reloc):
Remove.
(Target_tilegx::scan_relocatable_relocs): Use Default_classify_reloc.
(Target_tilegx::relocate_relocs): Use Default_classify_reloc.
* x86_64.cc (Target_x86_64::emit_relocs_scan): New method.
(Target_x86_64::Relocatable_size_for_reloc): Remove.
(Target_x86_64::gc_process_relocs): Use Default_classify_reloc.
(Target_x86_64::scan_relocs): Likewise.
(Target_x86_64::relocate_section): Likewise.
(Target_x86_64::Relocatable_size_for_reloc::get_size_for_reloc):
Remove.
(Target_x86_64::scan_relocatable_relocs): Use Default_classify_reloc.
(Target_x86_64::relocate_relocs): Use Default_classify_reloc.
* testsuite/testfile.cc (Target_test::emit_relocs_scan): New method.
Diffstat (limited to 'gold/target-reloc.h')
-rw-r--r-- | gold/target-reloc.h | 216 |
1 files changed, 164 insertions, 52 deletions
diff --git a/gold/target-reloc.h b/gold/target-reloc.h index cec5ee1..bdf673d 100644 --- a/gold/target-reloc.h +++ b/gold/target-reloc.h @@ -39,8 +39,8 @@ namespace gold // avoid making a function call for each relocation, and to avoid // repeating the generic code for each target. -template<int size, bool big_endian, typename Target_type, int sh_type, - typename Scan> +template<int size, bool big_endian, typename Target_type, + typename Scan, typename Classify_reloc> inline void scan_relocs( Symbol_table* symtab, @@ -55,8 +55,8 @@ scan_relocs( size_t local_count, const unsigned char* plocal_syms) { - typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype; - const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size; + typedef typename Classify_reloc::Reltype Reltype; + const int reloc_size = Classify_reloc::reloc_size; const int sym_size = elfcpp::Elf_sizes<size>::sym_size; Scan scan; @@ -69,9 +69,8 @@ scan_relocs( reloc.get_r_offset())) continue; - typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info(); - unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info); - unsigned int r_type = elfcpp::elf_r_type<size>(r_info); + unsigned int r_sym = Classify_reloc::get_r_sym(&reloc); + unsigned int r_type = Classify_reloc::get_r_type(&reloc); if (r_sym < local_count) { @@ -253,9 +252,10 @@ issue_undefined_symbol_error(const Symbol* sym) // symbol for the relocation, ignoring the symbol index in the // relocation. -template<int size, bool big_endian, typename Target_type, int sh_type, +template<int size, bool big_endian, typename Target_type, typename Relocate, - typename Relocate_comdat_behavior> + typename Relocate_comdat_behavior, + typename Classify_reloc> inline void relocate_section( const Relocate_info<size, big_endian>* relinfo, @@ -269,8 +269,8 @@ relocate_section( section_size_type view_size, const Reloc_symbol_changes* reloc_symbol_changes) { - typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype; - const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size; + typedef typename Classify_reloc::Reltype Reltype; + const int reloc_size = Classify_reloc::reloc_size; Relocate relocate; Relocate_comdat_behavior relocate_comdat_behavior; @@ -295,8 +295,7 @@ relocate_section( continue; } - typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info(); - unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info); + unsigned int r_sym = Classify_reloc::get_r_sym(&reloc); const Sized_symbol<size>* sym; @@ -399,8 +398,8 @@ relocate_section( if (offset < 0 || static_cast<section_size_type>(offset) >= view_size) v = NULL; - if (!relocate.relocate(relinfo, sh_type, target, output_section, - i, prelocs, sym, psymval, + if (!relocate.relocate(relinfo, Classify_reloc::sh_type, target, + output_section, i, prelocs, sym, psymval, v, view_address + offset, view_size)) continue; @@ -464,18 +463,90 @@ apply_relocation(const Relocate_info<size, big_endian>* relinfo, view + r_offset, address + r_offset, view_size); } +// A class for inquiring about properties of a relocation, +// used while scanning relocs during a relocatable link and +// garbage collection. This class may be used as the default +// for SHT_RELA targets, but SHT_REL targets must implement +// a derived class that overrides get_size_for_reloc. +// The MIPS-64 target also needs to override the methods +// for accessing the r_sym and r_type fields of a relocation, +// due to its non-standard use of the r_info field. + +template<int sh_type_, int size, bool big_endian> +class Default_classify_reloc +{ + public: + typedef typename Reloc_types<sh_type_, size, big_endian>::Reloc + Reltype; + typedef typename Reloc_types<sh_type_, size, big_endian>::Reloc_write + Reltype_write; + static const int reloc_size = + Reloc_types<sh_type_, size, big_endian>::reloc_size; + static const int sh_type = sh_type_; + + // Return the symbol referred to by the relocation. + static inline unsigned int + get_r_sym(const Reltype* reloc) + { return elfcpp::elf_r_sym<size>(reloc->get_r_info()); } + + // Return the type of the relocation. + static inline unsigned int + get_r_type(const Reltype* reloc) + { return elfcpp::elf_r_type<size>(reloc->get_r_info()); } + + // Return the explicit addend of the relocation (return 0 for SHT_REL). + static inline typename elfcpp::Elf_types<size>::Elf_Swxword + get_r_addend(const Reltype* reloc) + { return Reloc_types<sh_type_, size, big_endian>::get_reloc_addend(reloc); } + + // Write the r_info field to a new reloc, using the r_info field from + // the original reloc, replacing the r_sym field with R_SYM. + static inline void + put_r_info(Reltype_write* new_reloc, Reltype* reloc, unsigned int r_sym) + { + unsigned int r_type = elfcpp::elf_r_type<size>(reloc->get_r_info()); + new_reloc->put_r_info(elfcpp::elf_r_info<size>(r_sym, r_type)); + } + + // Write the r_addend field to a new reloc. + static inline void + put_r_addend(Reltype_write* to, + typename elfcpp::Elf_types<size>::Elf_Swxword addend) + { Reloc_types<sh_type_, size, big_endian>::set_reloc_addend(to, addend); } + + // Return the size of the addend of the relocation (only used for SHT_REL). + static unsigned int + get_size_for_reloc(unsigned int, Relobj*) + { + gold_unreachable(); + return 0; + } +}; + // This class may be used as a typical class for the -// Scan_relocatable_reloc parameter to scan_relocatable_relocs. The -// template parameter Classify_reloc must be a class type which -// provides a function get_size_for_reloc which returns the number of -// bytes to which a reloc applies. This class is intended to capture -// the most typical target behaviour, while still permitting targets -// to define their own independent class for Scan_relocatable_reloc. - -template<int sh_type, typename Classify_reloc> +// Scan_relocatable_reloc parameter to scan_relocatable_relocs. +// This class is intended to capture the most typical target behaviour, +// while still permitting targets to define their own independent class +// for Scan_relocatable_reloc. + +template<typename Classify_reloc> class Default_scan_relocatable_relocs { public: + typedef typename Classify_reloc::Reltype Reltype; + static const int reloc_size = Classify_reloc::reloc_size; + static const int sh_type = Classify_reloc::sh_type; + + // Return the symbol referred to by the relocation. + static inline unsigned int + get_r_sym(const Reltype* reloc) + { return Classify_reloc::get_r_sym(reloc); } + + // Return the type of the relocation. + static inline unsigned int + get_r_type(const Reltype* reloc) + { return Classify_reloc::get_r_type(reloc); } + // Return the strategy to use for a local symbol which is not a // section symbol, given the relocation type. inline Relocatable_relocs::Reloc_strategy @@ -497,8 +568,7 @@ class Default_scan_relocatable_relocs return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA; else { - Classify_reloc classify; - switch (classify.get_size_for_reloc(r_type, object)) + switch (Classify_reloc::get_size_for_reloc(r_type, object)) { case 0: return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0; @@ -523,6 +593,56 @@ class Default_scan_relocatable_relocs { return Relocatable_relocs::RELOC_COPY; } }; +// This is a strategy class used with scan_relocatable_relocs +// and --emit-relocs. + +template<typename Classify_reloc> +class Default_emit_relocs_strategy +{ + public: + typedef typename Classify_reloc::Reltype Reltype; + static const int reloc_size = Classify_reloc::reloc_size; + static const int sh_type = Classify_reloc::sh_type; + + // Return the symbol referred to by the relocation. + static inline unsigned int + get_r_sym(const Reltype* reloc) + { return Classify_reloc::get_r_sym(reloc); } + + // Return the type of the relocation. + static inline unsigned int + get_r_type(const Reltype* reloc) + { return Classify_reloc::get_r_type(reloc); } + + // A local non-section symbol. + inline Relocatable_relocs::Reloc_strategy + local_non_section_strategy(unsigned int, Relobj*, unsigned int) + { return Relocatable_relocs::RELOC_COPY; } + + // A local section symbol. + inline Relocatable_relocs::Reloc_strategy + local_section_strategy(unsigned int, Relobj*) + { + if (sh_type == elfcpp::SHT_RELA) + return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA; + else + { + // The addend is stored in the section contents. Since this + // is not a relocatable link, we are going to apply the + // relocation contents to the section as usual. This means + // that we have no way to record the original addend. If the + // original addend is not zero, there is basically no way for + // the user to handle this correctly. Caveat emptor. + return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0; + } + } + + // A global symbol. + inline Relocatable_relocs::Reloc_strategy + global_strategy(unsigned int, Relobj*, unsigned int) + { return Relocatable_relocs::RELOC_COPY; } +}; + // Scan relocs during a relocatable link. This is a default // definition which should work for most targets. // Scan_relocatable_reloc must name a class type which provides three @@ -531,8 +651,7 @@ class Default_scan_relocatable_relocs // local_section_strategy. Most targets should be able to use // Default_scan_relocatable_relocs as this class. -template<int size, bool big_endian, int sh_type, - typename Scan_relocatable_reloc> +template<int size, bool big_endian, typename Scan_relocatable_reloc> void scan_relocatable_relocs( Symbol_table*, @@ -547,8 +666,8 @@ scan_relocatable_relocs( const unsigned char* plocal_syms, Relocatable_relocs* rr) { - typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype; - const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size; + typedef typename Scan_relocatable_reloc::Reltype Reltype; + const int reloc_size = Scan_relocatable_reloc::reloc_size; const int sym_size = elfcpp::Elf_sizes<size>::sym_size; Scan_relocatable_reloc scan; @@ -564,10 +683,9 @@ scan_relocatable_relocs( strategy = Relocatable_relocs::RELOC_DISCARD; else { - typename elfcpp::Elf_types<size>::Elf_WXword r_info = - reloc.get_r_info(); - const unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info); - const unsigned int r_type = elfcpp::elf_r_type<size>(r_info); + const unsigned int r_sym = Scan_relocatable_reloc::get_r_sym(&reloc); + const unsigned int r_type = + Scan_relocatable_reloc::get_r_type(&reloc); if (r_sym >= local_symbol_count) strategy = scan.global_strategy(r_type, object, r_sym); @@ -610,7 +728,7 @@ scan_relocatable_relocs( // Relocate relocs. Called for a relocatable link, and for --emit-relocs. // This is a default definition which should work for most targets. -template<int size, bool big_endian, int sh_type> +template<int size, bool big_endian, typename Classify_reloc> void relocate_relocs( const Relocate_info<size, big_endian>* relinfo, @@ -625,10 +743,9 @@ relocate_relocs( section_size_type reloc_view_size) { typedef typename elfcpp::Elf_types<size>::Elf_Addr Address; - typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype; - typedef typename Reloc_types<sh_type, size, big_endian>::Reloc_write - Reltype_write; - const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size; + typedef typename Classify_reloc::Reltype Reltype; + typedef typename Classify_reloc::Reltype_write Reltype_write; + const int reloc_size = Classify_reloc::reloc_size; const Address invalid_address = static_cast<Address>(0) - 1; Sized_relobj_file<size, big_endian>* const object = relinfo->object; @@ -647,8 +764,8 @@ relocate_relocs( // Target wants to handle this relocation. Sized_target<size, big_endian>* target = parameters->sized_target<size, big_endian>(); - target->relocate_special_relocatable(relinfo, sh_type, prelocs, - i, output_section, + target->relocate_special_relocatable(relinfo, Classify_reloc::sh_type, + prelocs, i, output_section, offset_in_output_section, view, view_address, view_size, pwrite); @@ -658,9 +775,7 @@ relocate_relocs( Reltype reloc(prelocs); Reltype_write reloc_write(pwrite); - typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info(); - const unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info); - const unsigned int r_type = elfcpp::elf_r_type<size>(r_info); + const unsigned int r_sym = Classify_reloc::get_r_sym(&reloc); // Get the new symbol index. @@ -748,16 +863,15 @@ relocate_relocs( } reloc_write.put_r_offset(new_offset); - reloc_write.put_r_info(elfcpp::elf_r_info<size>(new_symndx, r_type)); + Classify_reloc::put_r_info(&reloc_write, &reloc, new_symndx); // Handle the reloc addend based on the strategy. if (strategy == Relocatable_relocs::RELOC_COPY) { - if (sh_type == elfcpp::SHT_RELA) - Reloc_types<sh_type, size, big_endian>:: - copy_reloc_addend(&reloc_write, - &reloc); + if (Classify_reloc::sh_type == elfcpp::SHT_RELA) + Classify_reloc::put_r_addend(&reloc_write, + Classify_reloc::get_r_addend(&reloc)); } else { @@ -777,12 +891,10 @@ relocate_relocs( case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA: { typename elfcpp::Elf_types<size>::Elf_Swxword addend; - addend = Reloc_types<sh_type, size, big_endian>:: - get_reloc_addend(&reloc); + addend = Classify_reloc::get_r_addend(&reloc); gold_assert(os != NULL); addend = psymval->value(object, addend) - os->address(); - Reloc_types<sh_type, size, big_endian>:: - set_reloc_addend(&reloc_write, addend); + Classify_reloc::put_r_addend(&reloc_write, addend); } break; |