diff options
-rw-r--r-- | gdb/ChangeLog | 15 | ||||
-rw-r--r-- | gdb/NEWS | 4 | ||||
-rw-r--r-- | gdb/aarch64-tdep.c | 17 | ||||
-rw-r--r-- | gdb/doc/ChangeLog | 4 | ||||
-rw-r--r-- | gdb/doc/gdb.texinfo | 8 | ||||
-rw-r--r-- | gdb/frame.c | 28 | ||||
-rw-r--r-- | gdb/frame.h | 9 | ||||
-rw-r--r-- | gdb/python/py-framefilter.c | 2 | ||||
-rw-r--r-- | gdb/stack.c | 6 |
9 files changed, 82 insertions, 11 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 82e0819c136..bacf5d76368 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,18 @@ +2019-08-07 Alan Hayward <alan.hayward@arm.com> + + * NEWS: Expand the Pointer Authentication entry. + * aarch64-tdep.c (aarch64_frame_unmask_address): Rename from this. + (aarch64_frame_unmask_lr): ... to this. + (aarch64_prologue_prev_register, aarch64_dwarf2_prev_register): + Call aarch64_frame_unmask_lr. + * frame.c (struct frame_info): Add "masked" variable. + (frame_set_previous_pc_masked) (frame_get_pc_masked): New functions. + (fprint_frame): Check for masked pc. + * frame.h (frame_set_previous_pc_masked) (frame_get_pc_masked): New + declarations. + * python/py-framefilter.c (py_print_frame): Check for masked pc. + * stack.c (print_frame): Check for masked pc. + 2019-08-06 Tom Tromey <tom@tromey.com> * stabsread.c (patch_block_stabs, read_one_struct_field) @@ -16,7 +16,9 @@ architectures require kernel changes. TLS is not yet supported for amd64 and i386 process core dumps. -* Support for Pointer Authentication on AArch64 Linux. +* Support for Pointer Authentication (PAC) on AArch64 Linux. Return + addresses that required unmasking are shown in the backtrace with the + postfix [PAC]. * Two new convenience functions $_cimag and $_creal that extract the imaginary and real parts respectively from complex numbers. diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index e23cc3f9567..9b6324f0fcf 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -250,13 +250,13 @@ class instruction_reader : public abstract_instruction_reader } // namespace -/* If address signing is enabled, mask off the signature bits from ADDR, using - the register values in THIS_FRAME. */ +/* If address signing is enabled, mask off the signature bits from the link + register, which is passed by value in ADDR, using the register values in + THIS_FRAME. */ static CORE_ADDR -aarch64_frame_unmask_address (struct gdbarch_tdep *tdep, - struct frame_info *this_frame, - CORE_ADDR addr) +aarch64_frame_unmask_lr (struct gdbarch_tdep *tdep, + struct frame_info *this_frame, CORE_ADDR addr) { if (tdep->has_pauth () && frame_unwind_register_unsigned (this_frame, @@ -265,6 +265,9 @@ aarch64_frame_unmask_address (struct gdbarch_tdep *tdep, int cmask_num = AARCH64_PAUTH_CMASK_REGNUM (tdep->pauth_reg_base); CORE_ADDR cmask = frame_unwind_register_unsigned (this_frame, cmask_num); addr = addr & ~cmask; + + /* Record in the frame that the link register required unmasking. */ + set_frame_previous_pc_masked (this_frame); } return addr; @@ -952,7 +955,7 @@ aarch64_prologue_prev_register (struct frame_info *this_frame, if (tdep->has_pauth () && trad_frame_value_p (cache->saved_regs, tdep->pauth_ra_state_regnum)) - lr = aarch64_frame_unmask_address (tdep, this_frame, lr); + lr = aarch64_frame_unmask_lr (tdep, this_frame, lr); return frame_unwind_got_constant (this_frame, prev_regnum, lr); } @@ -1119,7 +1122,7 @@ aarch64_dwarf2_prev_register (struct frame_info *this_frame, { case AARCH64_PC_REGNUM: lr = frame_unwind_register_unsigned (this_frame, AARCH64_LR_REGNUM); - lr = aarch64_frame_unmask_address (tdep, this_frame, lr); + lr = aarch64_frame_unmask_lr (tdep, this_frame, lr); return frame_unwind_got_constant (this_frame, regnum, lr); default: diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 6faf5f359d6..702bb7c7a02 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +2019-08-07 Alan Hayward <alan.hayward@arm.com> + + * gdb.texinfo (AArch64 Pointer Authentication): New subsection. + 2019-08-05 Christian Biesinger <cbiesinger@google.com> * python.texi (Blocks In Python): Document dictionary access on blocks. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 89b1eda2c17..7f8c0aff1cd 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -24390,6 +24390,14 @@ but the lengths of the @code{z} and @code{p} registers will not change. This is a known limitation of @value{GDBN} and does not affect the execution of the target process. +@subsubsection AArch64 Pointer Authentication. +@cindex AArch64 Pointer Authentication. + +When @value{GDBN} is debugging the AArch64 architecture, and the program is +using the v8.3-A feature Pointer Authentication (PAC), then whenever the link +register @code{$lr} is pointing to an PAC function it's value will be masked. +When GDB prints a backtrace, any addresses that required unmasking will be +postfixed with the marker [PAC]. @node i386 @subsection x86 Architecture-specific Issues diff --git a/gdb/frame.c b/gdb/frame.c index adac24f68c6..b62fd5cd852 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -123,6 +123,8 @@ struct frame_info /* Cached copy of the previous frame's resume address. */ struct { enum cached_copy_status status; + /* Did VALUE require unmasking when being read. */ + bool masked; CORE_ADDR value; } prev_pc; @@ -161,6 +163,25 @@ struct frame_info const char *stop_string; }; +/* See frame.h. */ + +void +set_frame_previous_pc_masked (struct frame_info *frame) +{ + frame->prev_pc.masked = true; +} + +/* See frame.h. */ + +bool +get_frame_pc_masked (const struct frame_info *frame) +{ + gdb_assert (frame->next != nullptr); + gdb_assert (frame->next->prev_pc.status == CC_VALUE); + + return frame->next->prev_pc.masked; +} + /* A frame stash used to speed up frame lookups. Create a hash table to stash frames previously accessed from the frame cache for quicker subsequent retrieval. The hash table is emptied whenever @@ -429,8 +450,11 @@ fprint_frame (struct ui_file *file, struct frame_info *fi) if (fi->next == NULL || fi->next->prev_pc.status == CC_UNKNOWN) fprintf_unfiltered (file, "<unknown>"); else if (fi->next->prev_pc.status == CC_VALUE) - fprintf_unfiltered (file, "%s", - hex_string (fi->next->prev_pc.value)); + { + fprintf_unfiltered (file, "%s", hex_string (fi->next->prev_pc.value)); + if (fi->next->prev_pc.masked) + fprintf_unfiltered (file, "[PAC]"); + } else if (fi->next->prev_pc.status == CC_NOT_SAVED) val_print_not_saved (file); else if (fi->next->prev_pc.status == CC_UNAVAILABLE) diff --git a/gdb/frame.h b/gdb/frame.h index ccc285005aa..fdb401d84f1 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -949,4 +949,13 @@ extern const gdb::option::option_def set_backtrace_option_defs[2]; /* The values behind the global "set backtrace ..." settings. */ extern set_backtrace_options user_set_backtrace_options; +/* Mark that the PC value is masked for the previous frame. */ + +extern void set_frame_previous_pc_masked (struct frame_info *frame); + +/* Get whether the PC value is masked for the given frame. */ + +extern bool get_frame_pc_masked (const struct frame_info *frame); + + #endif /* !defined (FRAME_H) */ diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c index a2a96ac0d39..d805ec68f23 100644 --- a/gdb/python/py-framefilter.c +++ b/gdb/python/py-framefilter.c @@ -901,6 +901,8 @@ py_print_frame (PyObject *filter, frame_filter_flags flags, { annotate_frame_address (); out->field_core_addr ("addr", gdbarch, address); + if (get_frame_pc_masked (frame)) + out->field_string ("pac", " [PAC]"); annotate_frame_address_end (); out->text (" in "); } diff --git a/gdb/stack.c b/gdb/stack.c index c68b3876d35..0859815baf4 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -1298,7 +1298,11 @@ print_frame (const frame_print_options &fp_opts, { annotate_frame_address (); if (pc_p) - uiout->field_core_addr ("addr", gdbarch, pc); + { + uiout->field_core_addr ("addr", gdbarch, pc); + if (get_frame_pc_masked (frame)) + uiout->field_string ("pac", " [PAC]"); + } else uiout->field_string ("addr", "<unavailable>", ui_out_style_kind::ADDRESS); |