From 8dbd69dd1627d0b7159b96718eaa281d3b3bdde7 Mon Sep 17 00:00:00 2001 From: Luis Machado Date: Fri, 13 May 2022 16:08:35 +0100 Subject: [PATCH] Fix fetching of auxv for PCuABI The entries of the auxv for the PCuABI are 128-bit in size. Teach GDB about this so it can at least fetch some sane values. It currently can't fetch the capabilities, but should be enough for now. --- gdb/aarch64-linux-nat.c | 62 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c index b98ecf80eb2..4ca2e373851 100644 --- a/gdb/aarch64-linux-nat.c +++ b/gdb/aarch64-linux-nat.c @@ -113,6 +113,11 @@ public: gdb::byte_vector read_capability (CORE_ADDR addr) override; bool write_capability (CORE_ADDR addr, gdb::array_view buffer) override; + /* Required to differentiate Morello AUXV entries, since they are 128-bit + in size. */ + int auxv_parse (gdb_byte **readptr, + gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp) + override; }; static aarch64_linux_nat_target the_aarch64_linux_nat_target; @@ -1016,6 +1021,63 @@ aarch64_linux_nat_target::write_capability (CORE_ADDR addr, return true; } +/* Implement the "auxv_parse" target_ops method. */ + +int +aarch64_linux_nat_target::auxv_parse (gdb_byte **readptr, + gdb_byte *endptr, CORE_ADDR *typep, + CORE_ADDR *valp) +{ + /* Do some sanity checks first. */ + if (endptr == *readptr) + return 0; + + if (endptr - *readptr < 16) + return -1; + + size_t offset_to_skip = 0; + enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); + + /* We're dealing with three different AUXV layouts: + + A - The regular AArch64 format: Each type entry is 64-bit and each value + is 64-bit. This is also the case for Morello Hybrid binaries. + B - The Morello pure capability format with libshim: This is a compability + layout and it keeps the 64-bit types and 64-bit values. + C - The Morello pure capability format without libshim: This layout has + 64-bit types followed by 64-bit padding. The value is 128-bit. + + We need to determine what layout we have, so we can read the data + correctly. + + The easiest way to tell the difference is to assume 8-byte entries and + look for any types outside the range [AT_NULL, AT_MINSIGSTKSZ]. If we + find one such type, assume that we have layout C. Otherwise we have + layouts A or B. */ + gdb_byte *ptr = *readptr; + while (ptr < endptr) + { + CORE_ADDR type = extract_unsigned_integer (ptr, 8, byte_order); + if (type > AT_MINSIGSTKSZ) + { + offset_to_skip = 8; + break; + } + ptr += 16; + } + + /* Now we know what the layout looks like. Read the data. */ + ptr = *readptr; + *typep = extract_unsigned_integer (ptr, 8, byte_order); + ptr += 8 + offset_to_skip; + *valp = extract_unsigned_integer (ptr, 8, byte_order); + ptr += 8 + offset_to_skip; + + *readptr = ptr; + + return 1; +} + void _initialize_aarch64_linux_nat (); void _initialize_aarch64_linux_nat () -- 2.47.2