This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] gold: Maintain sparc ELF header bits properly


From: David Miller <davem@davemloft.net>
Date: Fri, 20 Apr 2012 18:44:48 -0400 (EDT)

> From: Cary Coutant <ccoutant@google.com>
> Date: Fri, 20 Apr 2012 15:32:48 -0700
> 
>>> It really would have been nice if I could just call down into the
>>> default implementations after I did the sparc specific bits, but
>>> it's not possible to just simply say:
>>>
>>> ?this->do_make_elf_object_implementation(...)
>> 
>> Sure it is:
>> 
>>     Target::do_make_elf_object(name, input_file, offset, ehdr);
> 
> Indeed, that does the trick, thanks!

Ping?

> gold/
> 
> 	* sparc.cc (class Target_sparc): Add elf_machine_, elf_flags_,
> 	and elf_flags_set_.
> 	(Target_sparc::Target_sparc): Initialize new fields.
> 	(Target_sparc::do_make_elf_object): New function.
> 	(Target_sparc::do_adjust_elf_header): New function.
> ---
>  gold/sparc.cc |  112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 111 insertions(+), 1 deletion(-)
> 
> diff --git a/gold/sparc.cc b/gold/sparc.cc
> index 762da42..004a265 100644
> --- a/gold/sparc.cc
> +++ b/gold/sparc.cc
> @@ -60,7 +60,9 @@ class Target_sparc : public Sized_target<size, big_endian>
>      : Sized_target<size, big_endian>(&sparc_info),
>        got_(NULL), plt_(NULL), rela_dyn_(NULL), rela_ifunc_(NULL),
>        copy_relocs_(elfcpp::R_SPARC_COPY), dynbss_(NULL),
> -      got_mod_index_offset_(-1U), tls_get_addr_sym_(NULL)
> +      got_mod_index_offset_(-1U), tls_get_addr_sym_(NULL),
> +      elf_machine_(sparc_info.machine_code), elf_flags_(0),
> +      elf_flags_set_(false)
>    {
>    }
>  
> @@ -206,6 +208,15 @@ class Target_sparc : public Sized_target<size, big_endian>
>    unsigned int
>    plt_entry_size() const;
>  
> + protected:
> +  // Make an ELF object.
> +  Object*
> +  do_make_elf_object(const std::string&, Input_file*, off_t,
> +		     const elfcpp::Ehdr<size, big_endian>& ehdr);
> +
> +  void
> +  do_adjust_elf_header(unsigned char* view, int len) const;
> +
>   private:
>  
>    // The class which scans relocations.
> @@ -432,6 +443,12 @@ class Target_sparc : public Sized_target<size, big_endian>
>    unsigned int got_mod_index_offset_;
>    // Cached pointer to __tls_get_addr symbol
>    Symbol* tls_get_addr_sym_;
> +  // Accumulated elf machine type
> +  elfcpp::Elf_Half elf_machine_;
> +  // Accumulated elf header flags
> +  elfcpp::Elf_Word elf_flags_;
> +  // Whether elf_flags_ has been set for the first time yet
> +  bool elf_flags_set_;
>  };
>  
>  template<>
> @@ -4071,6 +4088,99 @@ Target_sparc<size, big_endian>::do_dynsym_value(const Symbol* gsym) const
>    return this->plt_section()->address() + gsym->plt_offset();
>  }
>  
> +// do_make_elf_object to override the same function in the base class.
> +// We need to use a target-specific sub-class of
> +// Sized_relobj_file<size, big_endian> to process SPARC specific bits
> +// of the ELF headers.  Hence we need to have our own ELF object creation.
> +
> +template<int size, bool big_endian>
> +Object*
> +Target_sparc<size, big_endian>::do_make_elf_object(
> +    const std::string& name,
> +    Input_file* input_file,
> +    off_t offset, const elfcpp::Ehdr<size, big_endian>& ehdr)
> +{
> +  elfcpp::Elf_Word omm, mm, flags = ehdr.get_e_flags();
> +  elfcpp::Elf_Half machine = ehdr.get_e_machine();
> +  
> +  switch (machine)
> +    {
> +    case elfcpp::EM_SPARC32PLUS:
> +      this->elf_machine_ = elfcpp::EM_SPARC32PLUS;
> +      break;
> +
> +    case elfcpp::EM_SPARC:
> +    case elfcpp::EM_SPARCV9:
> +      break;
> +
> +    default:
> +      break;
> +    }
> +
> +  if (!this->elf_flags_set_)
> +    {
> +      this->elf_flags_ = flags;
> +      this->elf_flags_set_ = true;
> +    }
> +  else
> +    {
> +      // Accumulate cpu feature bits.
> +      this->elf_flags_ |= (flags & (elfcpp::EF_SPARC_32PLUS
> +				    | elfcpp::EF_SPARC_SUN_US1
> +				    | elfcpp::EF_SPARC_HAL_R1
> +				    | elfcpp::EF_SPARC_SUN_US3));
> +
> +      // Bump the memory model setting to the most restrictive
> +      // one we encounter.
> +      omm = (this->elf_flags_ & elfcpp::EF_SPARCV9_MM);
> +      mm = (flags & elfcpp::EF_SPARCV9_MM);
> +      if (omm != mm)
> +	{
> +	  if (mm == elfcpp::EF_SPARCV9_TSO)
> +	    {
> +	      this->elf_flags_ &= ~elfcpp::EF_SPARCV9_MM;
> +	      this->elf_flags_ |= elfcpp::EF_SPARCV9_TSO;
> +	    }
> +	  else if (mm == elfcpp::EF_SPARCV9_PSO
> +		   && omm == elfcpp::EF_SPARCV9_RMO)
> +	    {
> +	      this->elf_flags_ &= ~elfcpp::EF_SPARCV9_MM;
> +	      this->elf_flags_ |= elfcpp::EF_SPARCV9_PSO;
> +	    }
> +	}
> +    }
> +
> +  // Validate that the little-endian flag matches how we've
> +  // been instantiated.
> +  if (!(flags & elfcpp::EF_SPARC_LEDATA) != big_endian)
> +    {
> +      if (big_endian)
> +	gold_error(_("%s: Little endian elf flag set on BE object"),
> +		     name.c_str());
> +      else
> +	gold_error(_("%s: Little endian elf flag clear on LE object"),
> +		     name.c_str());
> +    }
> +
> +  return Target::do_make_elf_object(name, input_file, offset, ehdr);
> +}
> +
> +// Adjust ELF file header.
> +
> +template<int size, bool big_endian>
> +void
> +Target_sparc<size, big_endian>::do_adjust_elf_header(
> +    unsigned char* view,
> +    int len) const
> +{
> +  elfcpp::Ehdr_write<size, big_endian> oehdr(view);
> +
> +  oehdr.put_e_machine(this->elf_machine_);
> +  oehdr.put_e_flags(this->elf_flags_);
> +
> +  Sized_target<size, big_endian>::do_adjust_elf_header(view, len);
> +}
> +
>  // The selector for sparc object files.
>  
>  template<int size, bool big_endian>
> -- 
> 1.7.9.5
> 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]