[PING][PATCH] Fix printing of non pointer types when memory tagging is enabled
Luis Machado
luis.machado@linaro.org
Thu Jul 1 13:50:00 GMT 2021
On 6/21/21 10:37 PM, Luis Machado wrote:
> Updates on v2:
>
> - Guard against thrown exceptions in the gdbarch_tagged_address_p hook as
> opposed to doing it at a higher scope.
>
> --
>
> When the architecture supports memory tagging, we handle pointer types
> in a special way, so we can validate tags and show mismatches.
>
> I noticed some errors while printing composite types, floats, references,
> member functions and other things that implicitly get dereferenced by GDB to
> show the contents rather than the pointer.
>
> Vector registers:
>
> (gdb) p $v0
> Value can't be converted to integer.
>
> Non-existent internal variables:
>
> (gdb) p $foo
> Value can't be converted to integer.
>
> The same happens for complex types and printing struct/union types.
>
> There are a couple problems. The first one is that we try to evaluate the
> expression to print and eventually call value_as_address (...) before making
> sure we have a suitable TYPE_CODE_PTR type. That may throw for some types. We
> fix this by making sure we have a TYPE_CODE_PTR first, and then proceed to
> check if we need to validate tags.
>
> The second problem is that the evaluation process may naturally throw an
> error. One such case is when we have an optimized out variable. Thus we
> guard the evaluation path with a try/catch.
>
> If the evaluation throws, we want to resume the default expression printing
> path instead of erroring out and printing nothing useful.
>
> This isn't ideal, but GDB does some magic, internally, in order to provide an
> improved user experience. This allows users to print the contents of some types
> without having to use the dereference operator.
>
> With the patch, printing works correctly again:
>
> (gdb) p $v0
> $1 = {d = {f = {2.0546950501119882e-81, 2.0546950501119882e-81}, u = {3399988123389603631, 3399988123389603631}, s = {
> 3399988123389603631, 3399988123389603631}}, s = {f = {1.59329203e-10, 1.59329203e-10, 1.59329203e-10, 1.59329203e-10}, u = {
> 791621423, 791621423, 791621423, 791621423}, s = {791621423, 791621423, 791621423, 791621423}}, h = {bf = {1.592e-10,
> 1.592e-10, 1.592e-10, 1.592e-10, 1.592e-10, 1.592e-10, 1.592e-10, 1.592e-10}, f = {0.11224, 0.11224, 0.11224, 0.11224, 0.11224,
> 0.11224, 0.11224, 0.11224}, u = {12079, 12079, 12079, 12079, 12079, 12079, 12079, 12079}, s = {12079, 12079, 12079, 12079,
> 12079, 12079, 12079, 12079}}, b = {u = {47 <repeats 16 times>}, s = {47 <repeats 16 times>}}, q = {u = {
> 62718710765820030520700417840365121327}, s = {62718710765820030520700417840365121327}}}
> (gdb) p $foo
> $2 = void
> (gdb) p 2 + 2i
> $3 = 2 + 2i
>
> gdb/ChangeLog
>
> YYYY-MM-DD Luis Machado <luis.machado@linaro.org>
>
> * gdbarch.sh: Updated documentation for gdbarch_tagged_address_p.
> * gdbarch.h: Regenerate.
> * printcmd.c (should_validate_memtags): Reorder comparisons and only
> validate tags for TYPE_CODE_PTR types.
> * aarch64-linux-tdep.c (aarch64_linux_tagged_address_p): Guard call
> to value_as_address with a try/catch block.
> ---
> gdb/aarch64-linux-tdep.c | 14 +++++++++++++-
> gdb/gdbarch.h | 3 ++-
> gdb/gdbarch.sh | 3 ++-
> gdb/printcmd.c | 20 ++++++++++----------
> 4 files changed, 27 insertions(+), 13 deletions(-)
>
> diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
> index e9761ed2189..84ef616ee35 100644
> --- a/gdb/aarch64-linux-tdep.c
> +++ b/gdb/aarch64-linux-tdep.c
> @@ -1559,7 +1559,19 @@ aarch64_linux_tagged_address_p (struct gdbarch *gdbarch, struct value *address)
> {
> gdb_assert (address != nullptr);
>
> - CORE_ADDR addr = value_as_address (address);
> + CORE_ADDR addr;
> +
> + /* value_as_address may throw if, for example, the value is optimized
> + out. Make sure we handle that gracefully. */
> + try
> + {
> + addr = value_as_address (address);
> + }
> + catch (const gdb_exception_error &ex)
> + {
> + /* Give up and assume the address is untagged. */
> + return false;
> + }
>
> /* Remove the top byte for the memory range check. */
> addr = address_significant (gdbarch, addr);
> diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
> index 7157e5596fd..4118e6c37ef 100644
> --- a/gdb/gdbarch.h
> +++ b/gdb/gdbarch.h
> @@ -730,7 +730,8 @@ typedef std::string (gdbarch_memtag_to_string_ftype) (struct gdbarch *gdbarch, s
> extern std::string gdbarch_memtag_to_string (struct gdbarch *gdbarch, struct value *tag);
> extern void set_gdbarch_memtag_to_string (struct gdbarch *gdbarch, gdbarch_memtag_to_string_ftype *memtag_to_string);
>
> -/* Return true if ADDRESS contains a tag and false otherwise. */
> +/* Return true if ADDRESS contains a tag and false otherwise. The
> + implementation of this hook should never throw an exception. */
>
> typedef bool (gdbarch_tagged_address_p_ftype) (struct gdbarch *gdbarch, struct value *address);
> extern bool gdbarch_tagged_address_p (struct gdbarch *gdbarch, struct value *address);
> diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
> index 43e51341f97..77088228d9a 100755
> --- a/gdb/gdbarch.sh
> +++ b/gdb/gdbarch.sh
> @@ -608,7 +608,8 @@ v;int;significant_addr_bit;;;;;;0
> # Return a string representation of the memory tag TAG.
> m;std::string;memtag_to_string;struct value *tag;tag;;default_memtag_to_string;;0
>
> -# Return true if ADDRESS contains a tag and false otherwise.
> +# Return true if ADDRESS contains a tag and false otherwise. The
> +# implementation of this hook should never throw an exception.
> m;bool;tagged_address_p;struct value *address;address;;default_tagged_address_p;;0
>
> # Return true if the tag from ADDRESS matches the memory tag for that
> diff --git a/gdb/printcmd.c b/gdb/printcmd.c
> index 22fa5c074d1..cd7d002c503 100644
> --- a/gdb/printcmd.c
> +++ b/gdb/printcmd.c
> @@ -1266,18 +1266,18 @@ print_value (value *val, const value_print_options &opts)
> static bool
> should_validate_memtags (struct value *value)
> {
> - if (target_supports_memory_tagging ()
> - && gdbarch_tagged_address_p (target_gdbarch (), value))
> - {
> - gdb_assert (value != nullptr && value_type (value) != nullptr);
> + if (value == nullptr)
> + return false;
>
> - enum type_code code = value_type (value)->code ();
> + enum type_code code = value_type (value)->code ();
> +
> + /* Only validate memory tags if we have a pointer type and if the address
> + is within a tagged memory area. */
> + if (code == TYPE_CODE_PTR
> + && target_supports_memory_tagging ()
> + && gdbarch_tagged_address_p (target_gdbarch (), value))
> + return true;
>
> - return (code == TYPE_CODE_PTR
> - || code == TYPE_CODE_REF
> - || code == TYPE_CODE_METHODPTR
> - || code == TYPE_CODE_MEMBERPTR);
> - }
> return false;
> }
>
>
More information about the Gdb-patches
mailing list