[1/4] aarch64: add STO_AARCH64_VARIANT_PCS and DT_AARCH64_VARIANT_PCS

Message ID 58f77e81-07e8-f194-89ac-e461e2b33da4@arm.com
State New
Headers show
Series
  • aarch64: Add STO_AARCH64_VARIANT_PCS support
Related show

Commit Message

Szabolcs Nagy May 23, 2019, 11:07 a.m.
The bottom 2 bits of st_other are used for visibility, the top 6 bits are
de facto reserved for processor specific use.  This patch defines a
bits to mark function symbols that follow a variant procedure call standard
with different register usage convention.

A dynamic tag is also defined that marks modules with R_<CLS>_JUMP_SLOT
relocations referencing symbols marked with STO_AARCH64_VARIANT_PCS.
This can be used by dynamic linkers that support lazy binding to decide
what registers need to be preserved during symbol resolution.

binutils/ChangeLog:

2019-05-22  Szabolcs Nagy  <szabolcs.nagy@arm.com>

	* readelf.c (get_aarch64_dynamic_type): Handle DT_AARCH64_VARIANT_PCS.
	(get_aarch64_symbol_other): New, handles STO_AARCH64_VARIANT_PCS.
	(get_symbol_other): Call get_aarch64_symbol_other.

include/ChangeLog:

2019-05-22  Szabolcs Nagy  <szabolcs.nagy@arm.com>

	* elf/aarch64.h (DT_AARCH64_VARIANT_PCS): Define.
	(STO_AARCH64_VARIANT_PCS): Define.

Comments

Nick Clifton May 24, 2019, 10:23 a.m. | #1
Hi Szabolcs,

  A little bit of paranoia...

> +static const char *

> +get_aarch64_symbol_other (unsigned int other)

> +{

> +  static char buf[32];

> +

> +  if (other & STO_AARCH64_VARIANT_PCS)

> +    {

> +      other &= ~STO_AARCH64_VARIANT_PCS;

> +      if (other == 0)

> +	return "VARIANT_PCS";

> +      snprintf (buf, sizeof buf, "VARIANT_PCS | %x", other);

> +      return buf;


On a host where an unsigned int is a 64-bit quantity, it is
theoretically possible for the snprintf function to have to
truncate the output, possibly confusing the user.  Could you
increase the buffer size a little bit please ?

Cheers
  Nick
Jan Beulich May 24, 2019, 10:58 a.m. | #2
>>> On 24.05.19 at 12:23, <nickc@redhat.com> wrote:

> Hi Szabolcs,

> 

>   A little bit of paranoia...

> 

>> +static const char *

>> +get_aarch64_symbol_other (unsigned int other)

>> +{

>> +  static char buf[32];

>> +

>> +  if (other & STO_AARCH64_VARIANT_PCS)

>> +    {

>> +      other &= ~STO_AARCH64_VARIANT_PCS;

>> +      if (other == 0)

>> +	return "VARIANT_PCS";

>> +      snprintf (buf, sizeof buf, "VARIANT_PCS | %x", other);

>> +      return buf;

> 

> On a host where an unsigned int is a 64-bit quantity, it is

> theoretically possible for the snprintf function to have to

> truncate the output, possibly confusing the user.  Could you

> increase the buffer size a little bit please ?


Hmm, %x can be at most 16 digits then, and I count 14
literal characters and a nul. I.e. 32 looks to be sufficient
for that case.

Jan
Nick Clifton May 24, 2019, 11:01 a.m. | #3
Hi Jan,

>>> +  static char buf[32];


>>> +      snprintf (buf, sizeof buf, "VARIANT_PCS | %x", other);


>> On a host where an unsigned int is a 64-bit quantity, it is

>> theoretically possible for the snprintf function to have to

>> truncate the output, possibly confusing the user.  Could you

>> increase the buffer size a little bit please ?

> 

> Hmm, %x can be at most 16 digits then, and I count 14

> literal characters and a nul. I.e. 32 looks to be sufficient

> for that case.


Oh bananas - yes you are right - I can't count.  Please ignore this request. :-)

Cheers
  Nick

Patch

diff --git a/binutils/readelf.c b/binutils/readelf.c
index c31a5c1266..0e8b27bcfe 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -1804,6 +1804,7 @@  get_aarch64_dynamic_type (unsigned long type)
     {
     case DT_AARCH64_BTI_PLT:  return "AARCH64_BTI_PLT";
     case DT_AARCH64_PAC_PLT:  return "AARCH64_PAC_PLT";
+    case DT_AARCH64_VARIANT_PCS:  return "AARCH64_VARIANT_PCS";
     default:
       return NULL;
     }
@@ -11095,6 +11096,22 @@  get_solaris_symbol_visibility (unsigned int visibility)
     }
 }
 
+static const char *
+get_aarch64_symbol_other (unsigned int other)
+{
+  static char buf[32];
+
+  if (other & STO_AARCH64_VARIANT_PCS)
+    {
+      other &= ~STO_AARCH64_VARIANT_PCS;
+      if (other == 0)
+	return "VARIANT_PCS";
+      snprintf (buf, sizeof buf, "VARIANT_PCS | %x", other);
+      return buf;
+    }
+  return NULL;
+}
+
 static const char *
 get_mips_symbol_other (unsigned int other)
 {
@@ -11206,6 +11223,9 @@  get_symbol_other (Filedata * filedata, unsigned int other)
 
   switch (filedata->file_header.e_machine)
     {
+    case EM_AARCH64:
+      result = get_aarch64_symbol_other (other);
+      break;
     case EM_MIPS:
       result = get_mips_symbol_other (other);
       break;
diff --git a/include/elf/aarch64.h b/include/elf/aarch64.h
index 4466547626..721378abf8 100644
--- a/include/elf/aarch64.h
+++ b/include/elf/aarch64.h
@@ -38,6 +38,11 @@ 
 /* Processor specific dynamic array tags.  */
 #define DT_AARCH64_BTI_PLT	(DT_LOPROC + 1)
 #define DT_AARCH64_PAC_PLT	(DT_LOPROC + 3)
+#define DT_AARCH64_VARIANT_PCS	(DT_LOPROC + 5)
+
+/* AArch64-specific values for st_other.  */
+#define STO_AARCH64_VARIANT_PCS	0x80  /* Symbol may follow different call
+					 convention from the base PCS.  */
 
 /* Relocation types.  */