summaryrefslogtreecommitdiff
path: root/gdb/gdbarch.h
diff options
context:
space:
mode:
authorLuis Machado <luis.machado@linaro.org>2021-07-20 07:29:28 -0300
committerLuis Machado <luis.machado@linaro.org>2021-07-20 07:29:28 -0300
commit05558223b5b52bf41036eb80335d2e541187e78f (patch)
tree6b3e9e3d3e7304da44c5d46176adfb1d463fa4cc /gdb/gdbarch.h
parentcb959bd8956f9dfc39f7f9a5ee56c1606979d33e (diff)
downloadbinutils-gdb-05558223b5b52bf41036eb80335d2e541187e78f.tar.gz
Fix printing of non-address types when memory tagging is enabled
When the architecture supports memory tagging, we handle pointer/reference types in a special way, so we can validate tags and show mismatches. Unfortunately, the currently implementation errors out when the user prints non-address values: composite types, floats, references, member functions and other things. 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 few problems here. The first one is that after print_command_1 evaluates the expression to print, the tag validation code call value_as_address unconditionally, without making sure we have have a suitable type where it makes to sense to call it. That results in value_as_address (if it isn't given a pointer-like type) trying to treat the value as an integer and convert it to an address, which #1 - doesn't make sense (i.e., no sense in validating tags after "print 1"), and throws for non-integer-convertible types. We fix this by making sure we have a pointer or reference type first, and only if so then proceed to check if the address-like value has tags. The second is that we're calling value_as_address even if we have an optimized out or unavailable value, which throws, because the value's contents aren't fully accessible/readable. This error currently escapes out and aborts the print. This case is fixed by checking for optimized out / unavailable explicitly. Third, the tag checking process does not gracefully handle exceptions. If any exception is thrown from the tag validation code, we abort the print. E.g., the target may fail to access tags via a running thread. Or the needed /proc files aren't available. Or some other untold reason. This is a bit too rigid. This commit changes print_command_1 to catch errors, print them, and still continue with the normal expression printing path instead of erroring out and printing nothing useful. With this 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 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28110
Diffstat (limited to 'gdb/gdbarch.h')
-rw-r--r--gdb/gdbarch.h3
1 files changed, 2 insertions, 1 deletions
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index ece765b826f..7db3e36d76a 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. ADDRESS
+ must be either a pointer or a reference type. */
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);