public inbox for libabigail@sourceware.org
 help / color / mirror / Atom feed
From: Dodji Seketeli <dodji@seketeli.org>
To: Mark Wielaard <mark@klomp.org>
Cc: gprocida@google.com,  maennich@google.com, libabigail@sourceware.org
Subject: Re: [PATCH] symtab-reader: Setup aliases before checking ppc64 opd function entries
Date: Fri, 27 May 2022 18:33:07 +0200	[thread overview]
Message-ID: <877d67szp8.fsf@seketeli.org> (raw)
In-Reply-To: <aecc7208ed5d4656f56d38b17b0899bee86321a7.camel@klomp.org> (Mark Wielaard's message of "Tue, 17 May 2022 11:59:50 +0200")

Hello Mark & Giuliano and Matthias!

Mark Wielaard <mark@klomp.org> a écrit:

[...]

> It looks good to me, some small comments below. I don't have access to
> a ppc64[be] setup anymore, but the buildbot has:
> https://builder.sourceware.org/buildbot/#/builders/libabigail-debian-ppc64
> So hopefully after this patch that will turn green.

Thank you for the review!  I have updated the patch accordingly and I am
posting an updated version below.

[...]

>> It is in that function that the call to
>> update_function_entry_address_symbol_map is performed, the arm32 symbol address
>> cleanup is done and the ppc64 ELFv1 function address plumbing
>> is done.
>
> Is that second line too long?

Yes it is.  Fixed.

>> So arranging for update_function_entry_address_symbol_map to be called
>> after symbol aliases are setup for ppc64 is also done in that
>> function.  That way, symtab::load_ only have to call
>> symtab::setup_symbol_lookup_tables to have aliases setup.
>
> Same for the first line here.

Hmmh, that one is 70 columns wide, so less than 80, as far as I can
tell.

[...]

>> @@ -476,9 +470,9 @@ symtab::update_main_symbol(GElf_Addr addr, const std::string& name)
>>  ///
>>  /// @return a possibly-adjusted symbol value
>>  GElf_Addr
>> -symtab::get_symbol_value(Elf* elf_handle,
>> -			 GElf_Sym* elf_symbol,
>> -			 const elf_symbol_sptr& symbol_sptr)
>> +symtab::setup_symbol_lookup_tables(Elf* elf_handle,
>> +				   GElf_Sym* elf_symbol,
>> +				   const elf_symbol_sptr& symbol_sptr)
>>  {
>>    const bool is_arm32 = elf_helpers::architecture_is_arm32(elf_handle);
>>    const bool is_arm64 = elf_helpers::architecture_is_arm64(elf_handle);
>> @@ -488,23 +482,33 @@ symtab::get_symbol_value(Elf* elf_handle,
>>      elf_helpers::maybe_adjust_et_rel_sym_addr_to_abs_addr(elf_handle,
>>  							  elf_symbol);
>>  
>> -  if (symbol_sptr->is_function())
>> -    {
>> -      if (is_arm32)
>> -	// Clear bit zero of ARM32 addresses as per "ELF for the Arm
>> -	// Architecture" section 5.5.3.
>> -	// https://static.docs.arm.com/ihi0044/g/aaelf32.pdf
>> -	symbol_value &= ~1;
>> -      else if (is_ppc64)
>> -	update_function_entry_address_symbol_map(elf_handle, elf_symbol,
>> -						 symbol_sptr);
>> -    }
>> +  if (symbol_sptr->is_function() && is_arm32)
>> +    // Clear bit zero of ARM32 addresses as per "ELF for the Arm
>> +    // Architecture" section 5.5.3.
>> +    // https://static.docs.arm.com/ihi0044/g/aaelf32.pdf
>> +    symbol_value &= ~1;
>> +
>>    if (is_arm64)
>>      // Copy bit 55 over bits 56 to 63 which may be tag information.
>>      symbol_value = symbol_value & (1ULL<<55)
>>  		   ? symbol_value | (0xffULL<<56)
>>  		   : symbol_value &~ (0xffULL<<56);
>
> This part is new. I think it is correct to do this, before setting up
> the aliases, just like we mask off the zero bit for arm32. But it would
> be good if Giuliano could confirm.

Thanks for commenting on this.  We'll see how Giuliano thinks.

[...]

>
>> +  if (symbol_sptr->is_defined())
>> +    {
>> +      const auto result =
>> +	addr_symbol_map_.emplace(symbol_value, symbol_sptr);
>> +      if (!result.second)
>> +	// A symbol with the same address already exists.  This
>> +	// means this symbol is an alias of the main symbol with
>> +	// that address.  So let's register this new alias as such.
>> +	result.first->second->get_main_symbol()->add_alias(symbol_sptr);
>> +    }
>> +
>> +  if (symbol_sptr->is_function() && is_ppc64)
>> +    update_function_entry_address_symbol_map(elf_handle, elf_symbol,
>> +					     symbol_sptr);
>
> I would add a comment here to say something like:
>
> // Note, update_function_entry_address_symbol_map depends
> // on the symbol aliases been setup.
>
> So it is clear why this needs to be done after the add_alias call
> above.

Absolutely.  Fixed.  Thanks.

[...]

> Looks good.

Thanks!

[...]

Giuliano Procida <gprocida@google.com> a écrit:

> Hi.

Hey Giuliano,

> I have some minor comments. Other than that, it looks good to me.
>
> I'm CCing Matthias as he did a lot of the reworking into the current
> structure, I think.

Thank you for the review.  I have updated the patch according to your
comments.  Let's look at them once again.

[...]

>> > @@ -468,6 +458,10 @@ symtab::update_main_symbol(GElf_Addr addr, const std::string& name)
>> >  /// Various adjustments and bookkeeping may be needed to provide a correct
>> >  /// interpretation (one that matches DWARF addresses) of raw symbol values.
>> >  ///
>> > +/// This is a sub-routine for symtab::load_and
>> > +/// symtab::add_alternative_address_lookups and and must be called
>
> and and / and

Spot on.  Thanks.  Fixed.

[...]

>> > +/// only once during the execution of the former.
>
> I've lost a bit of the context, but where comments say "only once"
> should that be "only once per symbol"?

You are right.  Fixed.

[...]

>> >  /// @return a possibly-adjusted symbol value
>> >  GElf_Addr
>> > -symtab::get_symbol_value(Elf* elf_handle,
>> > -                      GElf_Sym* elf_symbol,
>> > -                      const elf_symbol_sptr& symbol_sptr)
>> > +symtab::setup_symbol_lookup_tables(Elf* elf_handle,
>> > +                                GElf_Sym* elf_symbol,
>> > +                                const elf_symbol_sptr& symbol_sptr)
>> >  {
>> >    const bool is_arm32 = elf_helpers::architecture_is_arm32(elf_handle);
>> >    const bool is_arm64 = elf_helpers::architecture_is_arm64(elf_handle);
>> > @@ -488,23 +482,33 @@ symtab::get_symbol_value(Elf* elf_handle,
>> >      elf_helpers::maybe_adjust_et_rel_sym_addr_to_abs_addr(elf_handle,
>> >                                                         elf_symbol);
>> >
>> > -  if (symbol_sptr->is_function())
>> > -    {
>> > -      if (is_arm32)
>> > -     // Clear bit zero of ARM32 addresses as per "ELF for the Arm
>> > -     // Architecture" section 5.5.3.
>> > -     // https://static.docs.arm.com/ihi0044/g/aaelf32.pdf
>> > -     symbol_value &= ~1;
>> > -      else if (is_ppc64)
>> > -     update_function_entry_address_symbol_map(elf_handle, elf_symbol,
>> > -                                              symbol_sptr);
>> > -    }
>> > +  if (symbol_sptr->is_function() && is_arm32)
>> > +    // Clear bit zero of ARM32 addresses as per "ELF for the Arm
>> > +    // Architecture" section 5.5.3.
>> > +    // https://static.docs.arm.com/ihi0044/g/aaelf32.pdf
>> > +    symbol_value &= ~1;
>> > +
>> >    if (is_arm64)
>> >      // Copy bit 55 over bits 56 to 63 which may be tag information.
>> >      symbol_value = symbol_value & (1ULL<<55)
>> >                  ? symbol_value | (0xffULL<<56)
>> >                  : symbol_value &~ (0xffULL<<56);
>>
>> This part is new. I think it is correct to do this, before setting up
>> the aliases, just like we mask off the zero bit for arm32. But it would
>> be good if Giuliano could confirm.
>>
>
> The two ARM adjustments belong together. I wasn't sure about PPC, so
> I'm glad that it's getting moved to the right place.

Great, thanks to both of you.

[...]

>
>> > +  if (symbol_sptr->is_defined())
>> > +    {
>> > +      const auto result =
>> > +     addr_symbol_map_.emplace(symbol_value, symbol_sptr);
>> > +      if (!result.second)
>> > +     // A symbol with the same address already exists.  This
>> > +     // means this symbol is an alias of the main symbol with
>> > +     // that address.  So let's register this new alias as such.
>> > +     result.first->second->get_main_symbol()->add_alias(symbol_sptr);
>> > +    }
>> > +
>> > +  if (symbol_sptr->is_function() && is_ppc64)
>
> IIRC, someone said that this should apply to PPC32 as well, perhaps you, Mark?

[...]

Mark Wielaard <mark@klomp.org> a écrit:

> Yes, in theory both ppc32 and ppc64 use function descriptors (and both
> are big endian). But I haven't seen a real ppc32 setup in years.
>
> If you want to support that then it should be as simple as defining a
> architecture_is_ppc32 which is precisely like architecture_is_ppc64
> with s/EM_PPC64/EM_PPC/

OK, thanks Giuliano and Mark.

I have added support for ppc32 as well, as outlined above.

Please find below the updated patch that I am proposing.

Thanks!

From 8d44b582529ccd02689043918ef3ec3dd85155bc Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mark@klomp.org>
Date: Mon, 16 May 2022 10:53:55 +0200
Subject: [PATCH] symtab-reader: Setup aliases before checking ppc64 opd
 function entries

The update_function_entry_address_symbol_map function checks whether
the given symbol is an alias of another symbol or a special ppc64
ELFv1 function entry symbol. This requires the symbol aliases to
already been setup. But the alias entries were only setup after
calling update_function_entry_address_symbol_map. Make sure that the
symbol aliases have been setup and only then call the special ppc64
update_function_entry_address_symbol_map function. But make sure the
arm32 function symbol entry address cleanup is done before checking
for aliases.

This patch renames symtab::get_symbol_value into
symtab::setup_symbol_lookup_tables to better reflect what it does.

It is in that function that the call to
update_function_entry_address_symbol_map is performed, the arm32
symbol address cleanup is done and the ppc64 ELFv1 function address
plumbing is done.

So arranging for update_function_entry_address_symbol_map to be called
after symbol aliases are setup for ppc64 is also done in that
function.  That way, symtab::load_ only have to call
symtab::setup_symbol_lookup_tables to have aliases setup.

This fixes runtestslowselfcompare.sh on ppc64 (ELFv1) with
ENABLE_SLOW_TEST=yes

	* src/abg-elf-helpers.h (architecture_is_ppc32): Declare new
	function.
	* src/abg-elf-helpers.cc (architecture_is_ppc32): Define it.
	* src/abg-symtab-reader.cc
	(symtab::setup_symbol_lookup_tables): Rename
	symtab::get_symbol_value into this. Setup symbol aliases before
	setting up function entry address maps for ppc{32,64} ELFv1 and
	after fixing up arm32/64 addresses.
	(symtab::load_): Invoke the new setup_symbol_lookup_tables.
	update_function_entry_address_symbol_map after setting up aliases.
	No need to setup symbol aliases anymore.
	(symtab::add_alternative_address_lookups): Invoke the new
	setup_symbol_lookup_tables.

Signed-off-by: Mark Wielaard <mark@klomp.org>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
---
 src/abg-elf-helpers.cc   | 13 +++++++++
 src/abg-elf-helpers.h    |  3 ++
 src/abg-symtab-reader.cc | 62 ++++++++++++++++++++++------------------
 src/abg-symtab-reader.h  |  6 ++--
 4 files changed, 53 insertions(+), 31 deletions(-)

diff --git a/src/abg-elf-helpers.cc b/src/abg-elf-helpers.cc
index c41e339e..2a2cc6c2 100644
--- a/src/abg-elf-helpers.cc
+++ b/src/abg-elf-helpers.cc
@@ -918,6 +918,19 @@ architecture_is_ppc64(Elf* elf_handle)
   return (elf_header && elf_header->e_machine == EM_PPC64);
 }
 
+/// Test if the architecture of the current binary is ppc32.
+///
+/// @param elf_handle the ELF handle to consider.
+///
+/// @return true iff the architecture of the current binary is ppc32.
+bool
+architecture_is_ppc32(Elf* elf_handle)
+{
+  GElf_Ehdr  eh_mem;
+  GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem);
+  return (elf_header && elf_header->e_machine == EM_PPC);
+}
+
 /// Test if the architecture of the current binary is arm32.
 ///
 /// @param elf_handle the ELF handle to consider.
diff --git a/src/abg-elf-helpers.h b/src/abg-elf-helpers.h
index ee406863..0dc987d4 100644
--- a/src/abg-elf-helpers.h
+++ b/src/abg-elf-helpers.h
@@ -147,6 +147,9 @@ get_version_for_symbol(Elf*			elf_handle,
 bool
 architecture_is_ppc64(Elf* elf_handle);
 
+bool
+architecture_is_ppc32(Elf* elf_handle);
+
 bool
 architecture_is_arm32(Elf* elf_handle);
 
diff --git a/src/abg-symtab-reader.cc b/src/abg-symtab-reader.cc
index 3740cb7a..0c2f8ccc 100644
--- a/src/abg-symtab-reader.cc
+++ b/src/abg-symtab-reader.cc
@@ -343,17 +343,7 @@ symtab::load_(Elf*	       elf_handle,
 	    }
 	}
       else if (symbol_sptr->is_defined())
-	{
-	  const GElf_Addr symbol_value =
-	    get_symbol_value(elf_handle, sym, symbol_sptr);
-	  const auto result =
-	    addr_symbol_map_.emplace(symbol_value, symbol_sptr);
-	  if (!result.second)
-	    // A symbol with the same address already exists.  This
-	    // means this symbol is an alias of the main symbol with
-	    // that address.  So let's register this new alias as such.
-	    result.first->second->get_main_symbol()->add_alias(symbol_sptr);
-	}
+	setup_symbol_lookup_tables(elf_handle, sym, symbol_sptr);
     }
 
   add_alternative_address_lookups(elf_handle);
@@ -468,6 +458,10 @@ symtab::update_main_symbol(GElf_Addr addr, const std::string& name)
 /// Various adjustments and bookkeeping may be needed to provide a correct
 /// interpretation (one that matches DWARF addresses) of raw symbol values.
 ///
+/// This is a sub-routine for symtab::load_and
+/// symtab::add_alternative_address_lookups and must be called only
+/// once (per symbol) during the execution of the former.
+///
 /// @param elf_handle the ELF handle
 ///
 /// @param elf_symbol the ELF symbol
@@ -476,35 +470,49 @@ symtab::update_main_symbol(GElf_Addr addr, const std::string& name)
 ///
 /// @return a possibly-adjusted symbol value
 GElf_Addr
-symtab::get_symbol_value(Elf* elf_handle,
-			 GElf_Sym* elf_symbol,
-			 const elf_symbol_sptr& symbol_sptr)
+symtab::setup_symbol_lookup_tables(Elf* elf_handle,
+				   GElf_Sym* elf_symbol,
+				   const elf_symbol_sptr& symbol_sptr)
 {
   const bool is_arm32 = elf_helpers::architecture_is_arm32(elf_handle);
   const bool is_arm64 = elf_helpers::architecture_is_arm64(elf_handle);
   const bool is_ppc64 = elf_helpers::architecture_is_ppc64(elf_handle);
+  const bool is_ppc32 = elf_helpers::architecture_is_ppc32(elf_handle);
 
   GElf_Addr symbol_value =
     elf_helpers::maybe_adjust_et_rel_sym_addr_to_abs_addr(elf_handle,
 							  elf_symbol);
 
-  if (symbol_sptr->is_function())
-    {
-      if (is_arm32)
-	// Clear bit zero of ARM32 addresses as per "ELF for the Arm
-	// Architecture" section 5.5.3.
-	// https://static.docs.arm.com/ihi0044/g/aaelf32.pdf
-	symbol_value &= ~1;
-      else if (is_ppc64)
-	update_function_entry_address_symbol_map(elf_handle, elf_symbol,
-						 symbol_sptr);
-    }
+  if (is_arm32 && symbol_sptr->is_function())
+    // Clear bit zero of ARM32 addresses as per "ELF for the Arm
+    // Architecture" section 5.5.3.
+    // https://static.docs.arm.com/ihi0044/g/aaelf32.pdf
+    symbol_value &= ~1;
+
   if (is_arm64)
     // Copy bit 55 over bits 56 to 63 which may be tag information.
     symbol_value = symbol_value & (1ULL<<55)
 		   ? symbol_value | (0xffULL<<56)
 		   : symbol_value &~ (0xffULL<<56);
 
+  if (symbol_sptr->is_defined())
+    {
+      const auto result =
+	addr_symbol_map_.emplace(symbol_value, symbol_sptr);
+      if (!result.second)
+	// A symbol with the same address already exists.  This
+	// means this symbol is an alias of the main symbol with
+	// that address.  So let's register this new alias as such.
+	result.first->second->get_main_symbol()->add_alias(symbol_sptr);
+    }
+
+  // Please note that update_function_entry_address_symbol_map depends
+  // on the symbol aliases been setup.  This is why, the
+  // elf_symbol::add_alias call is done above BEFORE this point.
+  if ((is_ppc64 || is_ppc32) && symbol_sptr->is_function())
+    update_function_entry_address_symbol_map(elf_handle, elf_symbol,
+					     symbol_sptr);
+
   return symbol_value;
 }
 
@@ -656,9 +664,7 @@ symtab::add_alternative_address_lookups(Elf* elf_handle)
 	  if (symbols.size() == 1)
 	    {
 	      const auto& symbol_sptr = symbols[0];
-	      const GElf_Addr symbol_value =
-		get_symbol_value(elf_handle, sym, symbol_sptr);
-	      addr_symbol_map_.emplace(symbol_value, symbol_sptr);
+		setup_symbol_lookup_tables(elf_handle, sym, symbol_sptr);
 	    }
 	}
     }
diff --git a/src/abg-symtab-reader.h b/src/abg-symtab-reader.h
index bddde2f6..948fc270 100644
--- a/src/abg-symtab-reader.h
+++ b/src/abg-symtab-reader.h
@@ -290,9 +290,9 @@ private:
        string_elf_symbols_map_sptr variables_symbol_map);
 
   GElf_Addr
-  get_symbol_value(Elf* elf_handle,
-		   GElf_Sym* elf_symbol,
-		   const elf_symbol_sptr& symbol_sptr);
+  setup_symbol_lookup_tables(Elf* elf_handle,
+			     GElf_Sym* elf_symbol,
+			     const elf_symbol_sptr& symbol_sptr);
 
   void
   update_function_entry_address_symbol_map(Elf*	     elf_handle,
-- 
2.36.1

Cheers,

-- 
		Dodji

  parent reply	other threads:[~2022-05-27 16:33 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-16  9:43 Dodji Seketeli
2022-05-17  9:59 ` Mark Wielaard
2022-05-17 13:51   ` Giuliano Procida
2022-05-17 14:03     ` Mark Wielaard
2022-05-27 16:33   ` Dodji Seketeli [this message]
2022-05-27 23:05     ` Mark Wielaard
2022-05-30  8:44       ` Dodji Seketeli
  -- strict thread matches above, loose matches on Subject: below --
2022-05-01 22:16 Mark Wielaard

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=877d67szp8.fsf@seketeli.org \
    --to=dodji@seketeli.org \
    --cc=gprocida@google.com \
    --cc=libabigail@sourceware.org \
    --cc=maennich@google.com \
    --cc=mark@klomp.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).