[PATCH] libebl: Handle aarch64 bti, pac bits in gnu property note

2020-09-03 Thread Mark Wielaard
When building with gcc -mbranch-protection= we might get a gnu property
note indicating BTI (Branch Target Identification) and/or PAC (Pointer
Authentication Code) is being used.

Add a small testcase to show eu-readelf -n now properly lists those
bits in the gnu property note.

Signed-off-by: Mark Wielaard 
---
 libebl/ChangeLog |   5 ++
 libebl/eblobjnote.c  |  67 +++
 tests/ChangeLog  |   5 ++
 tests/run-readelf-n.sh   |  31 +
 tests/testfile-gnu-property-note-aarch64.bz2 | Bin 0 -> 1952 bytes
 5 files changed, 108 insertions(+)
 create mode 100755 tests/testfile-gnu-property-note-aarch64.bz2

diff --git a/libebl/ChangeLog b/libebl/ChangeLog
index e54aa2c9..aa43b31f 100644
--- a/libebl/ChangeLog
+++ b/libebl/ChangeLog
@@ -1,3 +1,8 @@
+2020-09-03  Mark Wielaard  
+
+   * eblobjnote.c (ebl_object_note): For EM_AARCH64 handle BTI and PAC
+   in GNU_PROPERTY_AARCH64_FEATURE_1_AND.
+
 2020-07-19  Mark Wielaard  
 
* libebl.h: Only typedef Ebl if _LIBASM_H is undefined.
diff --git a/libebl/eblobjnote.c b/libebl/eblobjnote.c
index f7ac915c..37cbc499 100644
--- a/libebl/eblobjnote.c
+++ b/libebl/eblobjnote.c
@@ -476,6 +476,73 @@ ebl_object_note (Ebl *ebl, uint32_t namesz, const char 
*name, uint32_t type,
}
}
}
+ else if (prop.pr_type >= GNU_PROPERTY_LOPROC
+  && prop.pr_type <= GNU_PROPERTY_HIPROC
+  && ehdr.e_machine == EM_AARCH64)
+   {
+ printf ("AARCH64 ");
+ if (prop.pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND)
+   {
+ printf ("FEATURE_1_AND: ");
+
+ if (prop.pr_datasz == 4)
+   {
+ GElf_Word data;
+ in.d_type = ELF_T_WORD;
+ out.d_type = ELF_T_WORD;
+ in.d_size = 4;
+ out.d_size = 4;
+ in.d_buf = (void *) desc;
+ out.d_buf = (void *) &data;
+
+ if (gelf_xlatetom (ebl->elf, &out, &in,
+elfident[EI_DATA]) == NULL)
+   {
+ printf ("%s\n", elf_errmsg (-1));
+ return;
+   }
+ printf ("%08" PRIx32 " ", data);
+
+ if ((data & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
+ != 0)
+   {
+ printf ("BTI");
+ data &= ~GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
+ if (data != 0)
+   printf (" ");
+   }
+
+ if ((data & GNU_PROPERTY_AARCH64_FEATURE_1_PAC)
+ != 0)
+   {
+ printf ("PAC");
+ data &= ~GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
+ if (data != 0)
+   printf (" ");
+   }
+
+ if (data != 0)
+   printf ("UNKNOWN");
+   }
+ else
+   printf ("",
+   prop.pr_datasz);
+
+ printf ("\n");
+   }
+ else
+   {
+ printf ("%#" PRIx32, prop.pr_type);
+ if (prop.pr_datasz > 0)
+   {
+ printf (" data: ");
+ size_t i;
+ for (i = 0; i < prop.pr_datasz - 1; i++)
+   printf ("%02" PRIx8 " ", (uint8_t) desc[i]);
+ printf ("%02" PRIx8 "\n", (uint8_t) desc[i]);
+   }
+   }
+   }
  else
{
  if (prop.pr_type >= GNU_PROPERTY_LOPROC
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 047100b0..cb2e9956 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,8 @@
+2020-09-03  Mark Wielaard  
+
+   * testfile-gnu-property-note-aarch64.bz2: New file.
+   * run-readelf-n.sh: Handle testfile-gnu-property-note-aarch64.
+
 2020-07-19  Mark Wielaard  
 
* asm-tst1.c: Include libebl.h after libasm.h.
diff --git a/tests/run-readelf-n.sh b/tests/run-readelf-n.sh
index cc7d7f66..4c

[PATCH] libdw: Remove duplicate local wildcards from map file.

2020-09-03 Thread Mark Wielaard
We only need one local: * entry to capture all private local symbols.

Signed-off-by: Mark Wielaard 
---
 libdw/ChangeLog |  8 
 libdw/libdw.map | 10 --
 2 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 796dbfb7..13683ef0 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,11 @@
+2020-09-03  Mark Wielaard  
+
+   * libdw.map (ELFUTILS_0.126): Remove local wildcard.
+   (ELFUTILS_0.127): Likewise.
+   (ELFUTILS_0.130): Likewise.
+   (ELFUTILS_0.136): Likewise.
+   (ELFUTILS_0.138): Likewise.
+
 2020-08-25  Mark Wielaard  
 
* dwarf_getlocation.c (check_constant_offset): Rename to...
diff --git a/libdw/libdw.map b/libdw/libdw.map
index decac05c..8ab0a2a0 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -149,8 +149,6 @@ ELFUTILS_0.126 {
   global:
 dwarf_getelf;
 
-  local:
-*;
 } ELFUTILS_0.122;
 
 ELFUTILS_0.127 {
@@ -161,8 +159,6 @@ ELFUTILS_0.127 {
 dwfl_report_begin_add;
 dwfl_module_address_section;
 
-  local:
-*;
 } ELFUTILS_0.126;
 
 ELFUTILS_0.130 {
@@ -172,8 +168,6 @@ ELFUTILS_0.130 {
 dwfl_module_build_id;
 dwfl_module_report_build_id;
 
-  local:
-*;
 } ELFUTILS_0.127;
 
 ELFUTILS_0.136 {
@@ -181,8 +175,6 @@ ELFUTILS_0.136 {
 dwfl_addrsegment;
 dwfl_report_segment;
 
-  local:
-*;
 } ELFUTILS_0.130;
 
 ELFUTILS_0.138 {
@@ -190,8 +182,6 @@ ELFUTILS_0.138 {
 # Replaced ELFUTILS_0.130 version, which has bug-compatibility wrapper.
 dwfl_module_build_id;
 
-  local:
-*;
 } ELFUTILS_0.136;
 
 ELFUTILS_0.142 {
-- 
2.18.4



Re: [PATCH] libebl: Handle aarch64 bti, pac bits in gnu property note

2020-09-03 Thread Mark Wielaard
On Thu, 2020-09-03 at 11:56 +0200, Mark Wielaard wrote:
> When building with gcc -mbranch-protection= we might get a gnu property
> note indicating BTI (Branch Target Identification) and/or PAC (Pointer
> Authentication Code) is being used.
> 
> Add a small testcase to show eu-readelf -n now properly lists those
> bits in the gnu property note.

Oops. Forgot to add the new testfile to EXTRA_DIST.

diff --git a/tests/ChangeLog b/tests/ChangeLog
index cb2e9956..61c6cb7c 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -2,6 +2,8 @@
 
* testfile-gnu-property-note-aarch64.bz2: New file.
* run-readelf-n.sh: Handle testfile-gnu-property-note-aarch64.
+   * Makefile.am (EXTRA_DIST): Add
+   testfile-gnu-property-note-aarch64.bz2.
 
 2020-07-19  Mark Wielaard  
 
diff --git a/tests/Makefile.am b/tests/Makefile.am
index d30b8218..939bbb6a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -319,6 +319,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
 testfile_gnu_props.64le.o.bz2 \
 testfile_gnu_props.32be.o.bz2 \
 testfile_gnu_props.64be.o.bz2 \
+testfile-gnu-property-note-aarch64.bz2 \
 run-allfcts-multi.sh \
 test-offset-loop.bz2 test-offset-loop.alt.bz2 \
 run-prelink-addr-test.sh \

> 
> Signed-off-by: Mark Wielaard 
> ---
>  libebl/ChangeLog |   5 ++
>  libebl/eblobjnote.c  |  67 +++
>  tests/ChangeLog  |   5 ++
>  tests/run-readelf-n.sh   |  31 +
>  tests/testfile-gnu-property-note-aarch64.bz2 | Bin 0 -> 1952 bytes
>  5 files changed, 108 insertions(+)
>  create mode 100755 tests/testfile-gnu-property-note-aarch64.bz2
> 
> diff --git a/libebl/ChangeLog b/libebl/ChangeLog
> index e54aa2c9..aa43b31f 100644
> --- a/libebl/ChangeLog
> +++ b/libebl/ChangeLog
> @@ -1,3 +1,8 @@
> +2020-09-03  Mark Wielaard  
> +
> + * eblobjnote.c (ebl_object_note): For EM_AARCH64 handle BTI and PAC
> + in GNU_PROPERTY_AARCH64_FEATURE_1_AND.
> +
>  2020-07-19  Mark Wielaard  
>  
>   * libebl.h: Only typedef Ebl if _LIBASM_H is undefined.
> diff --git a/libebl/eblobjnote.c b/libebl/eblobjnote.c
> index f7ac915c..37cbc499 100644
> --- a/libebl/eblobjnote.c
> +++ b/libebl/eblobjnote.c
> @@ -476,6 +476,73 @@ ebl_object_note (Ebl *ebl, uint32_t namesz, const char 
> *name, uint32_t type,
>   }
>   }
>   }
> +   else if (prop.pr_type >= GNU_PROPERTY_LOPROC
> +&& prop.pr_type <= GNU_PROPERTY_HIPROC
> +&& ehdr.e_machine == EM_AARCH64)
> + {
> +   printf ("AARCH64 ");
> +   if (prop.pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND)
> + {
> +   printf ("FEATURE_1_AND: ");
> +
> +   if (prop.pr_datasz == 4)
> + {
> +   GElf_Word data;
> +   in.d_type = ELF_T_WORD;
> +   out.d_type = ELF_T_WORD;
> +   in.d_size = 4;
> +   out.d_size = 4;
> +   in.d_buf = (void *) desc;
> +   out.d_buf = (void *) &data;
> +
> +   if (gelf_xlatetom (ebl->elf, &out, &in,
> +  elfident[EI_DATA]) == NULL)
> + {
> +   printf ("%s\n", elf_errmsg (-1));
> +   return;
> + }
> +   printf ("%08" PRIx32 " ", data);
> +
> +   if ((data & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
> +   != 0)
> + {
> +   printf ("BTI");
> +   data &= ~GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
> +   if (data != 0)
> + printf (" ");
> + }
> +
> +   if ((data & GNU_PROPERTY_AARCH64_FEATURE_1_PAC)
> +   != 0)
> + {
> +   printf ("PAC");
> +   data &= ~GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
> +   if (data != 0)
> + printf (" ");
> + }
> +
> +   if (data != 0)
> + printf ("UNKNOWN");
> + }
> +   else
> + printf ("",
> + prop.pr_datasz);
> +
> +   printf ("\n");
> + }
> +   else
> +  

[PATCH] libdw,readelf: Recognize DW_CFA_AARCH64_negate_ra_state

2020-09-03 Thread Mark Wielaard
DW_CFA_AARCH64_negate_ra_state is used on aarch64 to indicate whether
or not the return address is mangled or not. This has the same value
as the DW_CFA_GNU_window_save. So we have to pass around the e_machine
value of the process or core we are inspecting to know which one to
use.

Note that it isn't actually implemented yet. It needs ARMv8.3 hardware.
If we don't have such hardware it is enough to simply ignore the
DW_CFA_AARCH64_negate_ra_state (and not confuse it with
DW_CFA_GNU_window_save) to get backtraces to work on aarch64.

Add a testcase for eu-readelf --debug-dump=frames to show the value
is correctly recognized. Also don't warn we cannot find any DWARF
if we are just dumping frames (those will come from .eh_frame if
there is no .debug_frame).

Signed-off-by: Mark Wielaard 
---
 libdw/ChangeLog |  12 +++
 libdw/cfi.c |  41 +
 libdw/cfi.h |   2 +
 libdw/dwarf.h   |   1 +
 libdw/dwarf_getcfi.c|   5 ++
 libdw/dwarf_getcfi_elf.c|   8 +-
 src/ChangeLog   |   7 ++
 src/readelf.c   |  13 +--
 tests/ChangeLog |   6 ++
 tests/Makefile.am   |   2 +
 tests/run-readelf-frames.sh | 173 
 11 files changed, 247 insertions(+), 23 deletions(-)
 create mode 100755 tests/run-readelf-frames.sh

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 796dbfb7..fc2d872c 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,15 @@
+2020-09-03  Mark Wielaard  
+
+   * dwarf.h: Add DW_CFA_AARCH64_negate_ra_state.
+   * cfi.h (struct Dwarf_CFI_s): Add e_machine field.
+   * cfi.c (execute_cfi): Recognize, but ignore
+   DW_CFA_AARCH64_negate_ra_state on aarch64.
+   * dwarf_getcfi.c (dwarf_getcfi): Set cfi e_machine.
+   * dwarf_getcfi_elf.c (allocate_cfi): Take ehdr as argument and set
+   cfi e_machine.
+   (getcfi_gnu_eh_frame): Pass ehdr to allocate_cfi.
+   (getcfi_scn_eh_frame): Likewise.
+
 2020-08-25  Mark Wielaard  
 
* dwarf_getlocation.c (check_constant_offset): Rename to...
diff --git a/libdw/cfi.c b/libdw/cfi.c
index 6705294f..a73fb03f 100644
--- a/libdw/cfi.c
+++ b/libdw/cfi.c
@@ -350,24 +350,35 @@ execute_cfi (Dwarf_CFI *cache,
case DW_CFA_nop:
  continue;
 
-   case DW_CFA_GNU_window_save:
- /* This is magic shorthand used only by SPARC.  It's equivalent
-to a bunch of DW_CFA_register and DW_CFA_offset operations.  */
- if (unlikely (! enough_registers (31, &fs, &result)))
-   goto out;
- for (regno = 8; regno < 16; ++regno)
+   case DW_CFA_GNU_window_save: /* DW_CFA_AARCH64_negate_ra_state */
+ if (cache->e_machine == EM_AARCH64)
{
- /* Find each %oN in %iN.  */
- fs->regs[regno].rule = reg_register;
- fs->regs[regno].value = regno + 16;
+ /* Toggles the return address state, indicating whether
+the return address is encrypted or not on
+aarch64. XXX not handled yet.  */
}
- unsigned int address_size = (cache->e_ident[EI_CLASS] == ELFCLASS32
-  ? 4 : 8);
- for (; regno < 32; ++regno)
+ else
{
- /* Find %l0..%l7 and %i0..%i7 in a block at the CFA.  */
- fs->regs[regno].rule = reg_offset;
- fs->regs[regno].value = (regno - 16) * address_size;
+ /* This is magic shorthand used only by SPARC.  It's
+equivalent to a bunch of DW_CFA_register and
+DW_CFA_offset operations.  */
+ if (unlikely (! enough_registers (31, &fs, &result)))
+   goto out;
+ for (regno = 8; regno < 16; ++regno)
+   {
+ /* Find each %oN in %iN.  */
+ fs->regs[regno].rule = reg_register;
+ fs->regs[regno].value = regno + 16;
+   }
+ unsigned int address_size;
+ address_size = (cache->e_ident[EI_CLASS] == ELFCLASS32
+ ? 4 : 8);
+ for (; regno < 32; ++regno)
+   {
+ /* Find %l0..%l7 and %i0..%i7 in a block at the CFA.  */
+ fs->regs[regno].rule = reg_offset;
+ fs->regs[regno].value = (regno - 16) * address_size;
+   }
}
  continue;
 
diff --git a/libdw/cfi.h b/libdw/cfi.h
index 1ebf2dc3..1b0d712f 100644
--- a/libdw/cfi.h
+++ b/libdw/cfi.h
@@ -108,6 +108,8 @@ struct Dwarf_CFI_s
   size_t search_table_entries;
   uint8_t search_table_encoding;
 
+  uint16_t e_machine;
+
   /* True if the file has a byte order different from the host.  */
   bool other_byte_order;
 
diff --git a/libdw/dwarf.h b/libdw/dwarf.h
index 71ca2baa..98b10437 100644
--- a/libdw/dwarf.h
+++ b/libdw/dwarf.h
@@ -966,6 +966,7 @@ enum
 DW_CFA_low_user = 0x1c,
 DW_CFA_MIPS_advance_loc

Re: [PATCH] libdw: Remove duplicate local wildcards from map file.

2020-09-03 Thread Dmitry V. Levin
On Thu, Sep 03, 2020 at 03:00:36PM +0200, Mark Wielaard wrote:
> We only need one local: * entry to capture all private local symbols.

Yes, the first one (inside ELFUTILS_0.122) is enough.

> Signed-off-by: Mark Wielaard 
> ---
>  libdw/ChangeLog |  8 
>  libdw/libdw.map | 10 --
>  2 files changed, 8 insertions(+), 10 deletions(-)
> 
> diff --git a/libdw/ChangeLog b/libdw/ChangeLog
> index 796dbfb7..13683ef0 100644
> --- a/libdw/ChangeLog
> +++ b/libdw/ChangeLog
> @@ -1,3 +1,11 @@
> +2020-09-03  Mark Wielaard  
> +
> + * libdw.map (ELFUTILS_0.126): Remove local wildcard.
> + (ELFUTILS_0.127): Likewise.
> + (ELFUTILS_0.130): Likewise.
> + (ELFUTILS_0.136): Likewise.
> + (ELFUTILS_0.138): Likewise.
> +
>  2020-08-25  Mark Wielaard  
>  
>   * dwarf_getlocation.c (check_constant_offset): Rename to...
> diff --git a/libdw/libdw.map b/libdw/libdw.map
> index decac05c..8ab0a2a0 100644
> --- a/libdw/libdw.map
> +++ b/libdw/libdw.map
> @@ -149,8 +149,6 @@ ELFUTILS_0.126 {
>global:
>  dwarf_getelf;
>  
> -  local:
> -*;
>  } ELFUTILS_0.122;
>  
>  ELFUTILS_0.127 {
> @@ -161,8 +159,6 @@ ELFUTILS_0.127 {
>  dwfl_report_begin_add;
>  dwfl_module_address_section;
>  
> -  local:
> -*;
>  } ELFUTILS_0.126;
>  
>  ELFUTILS_0.130 {
> @@ -172,8 +168,6 @@ ELFUTILS_0.130 {
>  dwfl_module_build_id;
>  dwfl_module_report_build_id;
>  
> -  local:
> -*;
>  } ELFUTILS_0.127;
>  
>  ELFUTILS_0.136 {
> @@ -181,8 +175,6 @@ ELFUTILS_0.136 {
>  dwfl_addrsegment;
>  dwfl_report_segment;
>  
> -  local:
> -*;
>  } ELFUTILS_0.130;
>  
>  ELFUTILS_0.138 {
> @@ -190,8 +182,6 @@ ELFUTILS_0.138 {
>  # Replaced ELFUTILS_0.130 version, which has bug-compatibility wrapper.
>  dwfl_module_build_id;
>  
> -  local:
> -*;
>  } ELFUTILS_0.136;
>  
>  ELFUTILS_0.142 {
> -- 
> 2.18.4

-- 
ldv


Re: [PATCH] libdw: Remove duplicate local wildcards from map file.

2020-09-03 Thread Mark Wielaard
On Thu, Sep 03, 2020 at 07:57:15PM +0300, Dmitry V. Levin wrote:
> On Thu, Sep 03, 2020 at 03:00:36PM +0200, Mark Wielaard wrote:
> > We only need one local: * entry to capture all private local symbols.
> 
> Yes, the first one (inside ELFUTILS_0.122) is enough.

Thanks for the review.
Pushed to master.