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: [GOLD] advice on powerpc64 .opd handling


On Thu, Aug 16, 2012 at 6:43 AM, Alan Modra <amodra@gmail.com> wrote:
>
>         * powerpc.cc: Formatting and white space.
>         (Powerpc_relobj): Rename got2_section_ to special_.
>         Add opd_ent_count_, opd_ent_shndx_, opd_ent_off_.
>         (Powerpc_relobj::opd_shndx, init_opd, get_opd_ent, set_opd_ent,
>         do_read_relocs, opd_ent_ndx): New functions.
>         (Target_powerpc::is_branch_reloc): New function.
>         (Powerpc_relobj::do_find_special_sections): Find .opd for 64-bit.
>         (ld_2_1, cror_15_15_15, cror_31_31_31): New insn constants.
>         (Output_data_glink): Rename pltresolve_size to pltresolve_size_.
>         (Output_data_glink::pltresolve_size): New function.
>         (Output_data_glink::do_write): Correct toc base.  Don't try to use
>         uint16_t for 24-bit offset.
>         (Target_powerpc::Scan::local): Handle more relocs.
>         (Target_powerpc::do_finalize_sections): Set up DT_PPC64_GLINK.
>         (Target_powerpc::Relocate::relocate): Correct toc base calculation.
>         Plug in toc restoring insn after plt calls.  Translate branches
>         to function descriptor symbols to corresponding entry point.
>         * symtab.h: Comment typo.
>
>    Powerpc_relobj(const std::string& name, Input_file* input_file, off_t offset,
>                  const typename elfcpp::Ehdr<size, big_endian>& ehdr)
>      : Sized_relobj_file<size, big_endian>(name, input_file, offset, ehdr),
> -      got2_section_(0)
> +      special_(0)
>    { }

You should initialize all the new fields in the constructor, even if
you just initialize them to 0.


> +  unsigned int special_;
> +  size_t opd_ent_count_;
> +  unsigned int* opd_ent_shndx_;
> +  typename elfcpp::Elf_types<size>::Elf_Off* opd_ent_off_;

Please add comments for each describing the values they hold,
especially for special_.

Normally a C array should be std::vector in C++.  This should probably be

  std::vector<unsigned int> ent_shndx_;
  std::vector<typename elfcpp::Elf_Types<size>::Elf_Off> opd_ent_off_;

You may want to add a typedef for Elf_Off in the class, e.g., Address
in Sized_relobj in object.h.


> +         unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
> +         if (r_type == elfcpp::R_PPC64_ADDR64)
> +           {
> +             unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
> +             typename elfcpp::Elf_types<size>::Elf_Addr value;
> +             bool is_ordinary;
> +             unsigned int shndx;
> +             if (r_sym < this->local_symbol_count())
> +               {
> +                 typename elfcpp::Sym<size, big_endian>
> +                   lsym(plocal_syms + r_sym * sym_size);
> +                 shndx = lsym.get_st_shndx();
> +                 shndx = this->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
> +                 value = lsym.get_st_value();
> +               }
> +             else
> +               shndx = this->symbol_section_and_value(r_sym, &value,
> +                                                      &is_ordinary);

This isn't necessarily something to worry about right now, but
symbol_section_and_value is kind of a slow function.  If there are a
lot of global symbols in .opd sections, it will be better to get a
view of the global symbols once.

> +  if (size == 64)
> +    {
> +      for (Read_relocs_data::Relocs_list::iterator p = rd->relocs.begin();
> +          p != rd->relocs.end();
> +          ++p)
> +       if (p->data_shndx == this->opd_shndx())
> +         {
> +           this->init_opd(this->section_size(this->opd_shndx()));
> +           this->scan_opd_relocs(p->reloc_count, p->contents->data(),
> +                                 rd->local_symbols->data());
> +           break;
> +         }
> +    }

When there is more than a single line in a for body, I prefer to see
curly braces.


>   private:
> -  static const int pltresolve_size = 16*4;
> +  static const int pltresolve_size_ = 16*4;

Although data member names always end in underscore, it's not
necessary for the name of a constant to end in underscore.

> +         if (!can_plt_call)
> +           {
> +             if (parameters->options().output_is_executable())

What should happen for a shared library here?  Should this be
!relocatable() instead?

> +         if (value >= opd_addr
> +             && value < opd_addr + symobj->section_size(shndx))
> +           {
> +             symobj->get_opd_ent(value - opd_addr, &shndx, &value);
> +             value += (symobj->output_section(shndx)->address()
> +                       + symobj->output_section_offset(shndx));

Should get_opd_ent double-check that it is not returning an undefined symbol?

Will this work correctly if the symbol is defined in a SHT_GROUP
section that is discarded?  Code like this usually calls
get_output_section_offset, not output_section_offset, and checks for a
return == invalid_address.  In that case it needs to call
output_section->output_address.  See examples in output.cc.

Ian


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