[gold][aarch64] Patch for erratum-843419 (1 of 2 - report erratum occurrences)
Hán Shěn (沈涵)
shenhan@google.com
Thu Apr 16 20:46:00 GMT 2015
Hi Cary, thanks a lot for the review. Some comments below.
Re-run and passed all the tests.
For the ease of review, I attached 2 diffs, one is against trunk, the
other is against my previous patch.
Thanks,
Han
On Wed, Apr 15, 2015 at 3:41 PM, Cary Coutant <ccoutant@gmail.com> wrote:
> + // "<" comparator used in ordered_map container.
> + bool
> + operator < (const Mapping_symbol_position& p) const
>
> For consistency, please write this as "operator<(", without spaces
> around the '<'.
Done.
>
> + // Only erratum-fixing work needs mapping symbols, so skip this
> time consuming
> + // processing if not fixing erratum.
> + if (!parameters->options().fix_cortex_a53())
> + return ;
>
> Extra space.
Done.
>
> + // Read the symbol table section header.
> + const unsigned int symtab_shndx = this->symtab_shndx();
> + elfcpp::Shdr<size, big_endian>
> + symtabshdr(this, this->elf_file()->section_header(symtab_shndx));
> + gold_assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB);
>
> It seems wasteful to set up these views of the symbol table, when
> do_count_local_symbols in the parent class has already done all that.
> Both arm and mips targets also do something like this, so a refactor
> of the code could benefit all three targets. I won't ask you to do this,
> but I'll make a note to look at this myself later.
Thanks!
>
> + // Read the local symbols.
> + const int sym_size =elfcpp::Elf_sizes<size>::sym_size;
>
> Space after '='.
>
> + while (p != this->mapping_symbol_info_.end() &&
> + p->first.shndx_ == shndx)
> + {
> + typename Mapping_symbol_info::const_iterator next =
> + this->mapping_symbol_info_.upper_bound(p->first);
>
> Isn't this equivalent to "next = p; ++next"? With map, you'll only
> have a single entry per position, and you know that p->first is
> already in the map. It seems to me that you're doing an unnecessary
> binary search for every element of the map.
Yes, exactly, this is an unnecessary binary search.
>
> I'd suggest doing something like:
>
> typename Mapping_symbol_info::const_iterator prev = p;
> ++p;
>
> At the top of the loop, remove "p = next;" at the bottom, then replace
> "p" with "prev" and "next" with "p" in the body of the loop.
Done, yes, that's much clearer.
>
> + // The 3rd insn is a load or store instruction from the "Load/store
> + // register (unsigned immediate)" encoding class, using Rn as the
> + // base address register.
> + if (Insn_utilities::aarch64_ldst_uimm(insn3) &&
> + Insn_utilities::aarch64_rn(insn3)
> + == Insn_utilities::aarch64_rd(insn1))
>
> Add parentheses around the '==' operation, and indent accordingly.
Done.
>
> + // Erratum sequence is at least 3 insns.
> + if (span_end - span_start < 3 * Insn_utilities::BYTES_PER_INSN)
> + return ;
>
> Extra space. This test is redundant -- you'll drop out of the for loop
> below immediately if the span isn't long enough. It's also wrong -- it
> will fail if there are exactly 3 instructions before the end.
Removed this part.
>
> + Insntype* ip = reinterpret_cast<Insntype*>(input_view + span_start);
> + unsigned int insn_index = 0;
> + for (section_size_type i = span_start; i < span_end;
> + i += Insn_utilities::BYTES_PER_INSN, ++insn_index)
> + {
> + if (span_end - i < 3 * Insn_utilities::BYTES_PER_INSN)
> + break;
>
> Should be "<=".
Done.
>
> Given the constraints on the address, it's inefficient to loop over
> every address. I'd suggest instead something like this:
>
> if (output_address & 0x03 != 0)
'output_address' is output section's output_address, so I use
'output_address + span_start' here.
> return;
> section_size_type offset = 0;
> section_size_type span_length = span_end - span_start;
> // The first instruction must be at page offset 0xFF8 or 0xFFC.
> unsigned int page_offset = output_address & 0xfff;
Same as above, 'output_address' is output section's output_address, so
I use 'output_address + span_start' here.
If there a consensus/guideline on whether to use '0xfff' or '0xFFF'?
> if (page_offset < 0xff8)
> offset = 0xff8 - page_offset;
> while (offset + 3 * Insn_utilities::BYTES_PER_INSN <= span_length)
> {
> Insntype* ip = reinterpret_cast<Insntype*>(input_view + offset);
> Insntype insn1 = ip[0];
> if (!Insn_utilities::is_adrp(insn1))
> continue;
Need to update offset before continue, so I reverse the condition and
wrap everything below inside.
> Insntype insn2 = ip[1];
> Insntype insn3 = ip[2];
>
> // ...
>
> // Advance to next candidate instruction.
> // We only consider instruction sequences starting at
> // a page offset of 0xff8 or 0xffc.
> page_offset = (output_address + offset) & 0xfff;
I use 'output_address + span_start + offset' here.
> if (page_offset == 0xff8)
> offset += 4;
> else // (page_offset == 0xffc)
> offset += 0xffc;
> }
>
> (I used '4' instead of Insn_utilities::BYTES_PER_INSN here, because we
> explicitly want to advance from 0xff8 to 0xffc.)
>
> + if (is_erratum_843419_sequence(insn1, insn2, insn3))
> + do_report = true;
> + else if (span_end - i > 16)
>
> Should be '>='. Do you want "4 * Insn_utilities::BYTES_PER_INSN"
> instead of 16? (I'm not sold on the usefulness of the symbolic constant;
> it seems we're pretty hard-wired to a value of 4.)
>
> + return ;
Done.
>
> Extra space.
>
> + DEFINE_bool(fix_cortex_a53, options::TWO_DASHES, '\0', false,
> + N_("(AArch64 only) Scan and fix binaries for Cortex-A53 erratums."),
> + N_("(AArch64 only) Do not scan for Cortex-A53 erratums."));
>
> The plural of "erratum" is "errata".
Done.
>
> -cary
--
Han Shen
On Wed, Apr 15, 2015 at 3:41 PM, Cary Coutant <ccoutant@gmail.com> wrote:
> + // "<" comparator used in ordered_map container.
> + bool
> + operator < (const Mapping_symbol_position& p) const
>
> For consistency, please write this as "operator<(", without spaces
> around the '<'.
>
> + // Only erratum-fixing work needs mapping symbols, so skip this
> time consuming
> + // processing if not fixing erratum.
> + if (!parameters->options().fix_cortex_a53())
> + return ;
>
> Extra space.
>
> + // Read the symbol table section header.
> + const unsigned int symtab_shndx = this->symtab_shndx();
> + elfcpp::Shdr<size, big_endian>
> + symtabshdr(this, this->elf_file()->section_header(symtab_shndx));
> + gold_assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB);
>
> It seems wasteful to set up these views of the symbol table, when
> do_count_local_symbols in the parent class has already done all that.
> Both arm and mips targets also do something like this, so a refactor
> of the code could benefit all three targets. I won't ask you to do this,
> but I'll make a note to look at this myself later.
>
> + // Read the local symbols.
> + const int sym_size =elfcpp::Elf_sizes<size>::sym_size;
>
> Space after '='.
>
> + while (p != this->mapping_symbol_info_.end() &&
> + p->first.shndx_ == shndx)
> + {
> + typename Mapping_symbol_info::const_iterator next =
> + this->mapping_symbol_info_.upper_bound(p->first);
>
> Isn't this equivalent to "next = p; ++next"? With map, you'll only
> have a single entry per position, and you know that p->first is
> already in the map. It seems to me that you're doing an unnecessary
> binary search for every element of the map.
>
> I'd suggest doing something like:
>
> typename Mapping_symbol_info::const_iterator prev = p;
> ++p;
>
> At the top of the loop, remove "p = next;" at the bottom, then replace
> "p" with "prev" and "next" with "p" in the body of the loop.
>
> + // The 3rd insn is a load or store instruction from the "Load/store
> + // register (unsigned immediate)" encoding class, using Rn as the
> + // base address register.
> + if (Insn_utilities::aarch64_ldst_uimm(insn3) &&
> + Insn_utilities::aarch64_rn(insn3)
> + == Insn_utilities::aarch64_rd(insn1))
>
> Add parentheses around the '==' operation, and indent accordingly.
>
> + // Erratum sequence is at least 3 insns.
> + if (span_end - span_start < 3 * Insn_utilities::BYTES_PER_INSN)
> + return ;
>
> Extra space. This test is redundant -- you'll drop out of the for loop
> below immediately if the span isn't long enough. It's also wrong -- it
> will fail if there are exactly 3 instructions before the end.
>
> + Insntype* ip = reinterpret_cast<Insntype*>(input_view + span_start);
> + unsigned int insn_index = 0;
> + for (section_size_type i = span_start; i < span_end;
> + i += Insn_utilities::BYTES_PER_INSN, ++insn_index)
> + {
> + if (span_end - i < 3 * Insn_utilities::BYTES_PER_INSN)
> + break;
>
> Should be "<=".
>
> Given the constraints on the address, it's inefficient to loop over
> every address. I'd suggest instead something like this:
>
> if (output_address & 0x03 != 0)
> return;
> section_size_type offset = 0;
> section_size_type span_length = span_end - span_start;
> // The first instruction must be at page offset 0xFF8 or 0xFFC.
> unsigned int page_offset = output_address & 0xfff;
> if (page_offset < 0xff8)
> offset = 0xff8 - page_offset;
> while (offset + 3 * Insn_utilities::BYTES_PER_INSN <= span_length)
> {
> Insntype* ip = reinterpret_cast<Insntype*>(input_view + offset);
> Insntype insn1 = ip[0];
> if (!Insn_utilities::is_adrp(insn1))
> continue;
> Insntype insn2 = ip[1];
> Insntype insn3 = ip[2];
>
> // ...
>
> // Advance to next candidate instruction.
> // We only consider instruction sequences starting at
> // a page offset of 0xff8 or 0xffc.
> page_offset = (output_address + offset) & 0xfff;
> if (page_offset == 0xff8)
> offset += 4;
> else // (page_offset == 0xffc)
> offset += 0xffc;
> }
>
> (I used '4' instead of Insn_utilities::BYTES_PER_INSN here, because we
> explicitly want to advance from 0xff8 to 0xffc.)
>
> + if (is_erratum_843419_sequence(insn1, insn2, insn3))
> + do_report = true;
> + else if (span_end - i > 16)
>
> Should be '>='. Do you want "4 * Insn_utilities::BYTES_PER_INSN"
> instead of 16? (I'm not sold on the usefulness of the symbolic constant;
> it seems we're pretty hard-wired to a value of 4.)
>
> + return ;
>
> Extra space.
>
> + DEFINE_bool(fix_cortex_a53, options::TWO_DASHES, '\0', false,
> + N_("(AArch64 only) Scan and fix binaries for Cortex-A53 erratums."),
> + N_("(AArch64 only) Do not scan for Cortex-A53 erratums."));
>
> The plural of "erratum" is "errata".
>
> -cary
--
Han Shen
-------------- next part --------------
A non-text attachment was scrubbed...
Name: erratum-patch2.patch
Type: text/x-patch
Size: 23089 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/binutils/attachments/20150416/cfb0bd16/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: erratum-increment.patch
Type: text/x-patch
Size: 8570 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/binutils/attachments/20150416/cfb0bd16/attachment-0001.bin>
More information about the Binutils
mailing list