From: Luis Machado <lgustavo@codesourcery.com>
To: Yao Qi <qiyaoltc@gmail.com>, <gdb-patches@sourceware.org>
Subject: Re: [PATCH 1/2] Add unit test to aarch64 prologue analyzer
Date: Wed, 30 Nov 2016 19:30:00 -0000 [thread overview]
Message-ID: <55ea5ba0-6ea7-686d-1841-48875ed8587c@codesourcery.com> (raw)
In-Reply-To: <1480428758-2481-1-git-send-email-yao.qi@linaro.org>
On 11/29/2016 08:12 AM, Yao Qi wrote:
> We don't have an effective way to test prologue analyzer which is
> highly dependent on instruction patterns in prologue generated by
> compiler. GDB prologue analyzer may not handle the new sequences
> generated by new compiler, or may still handle some sequences that
> generated by very old compilers which are no longer used. The
> former is a functionality issue, while the latter is a maintenance
> issue.
>
> The input and output of prologue analyzer is quite clear, so it
> fits for unit test. The input is series of instructions, and the
> output are 1) where prologue end, 2) where registers are saved.
> In aarch64, they are represented in 'struct aarch64_prologue_cache'.
>
> This patch refactors aarch64_analyze_prologue so it can read
> instructions from either real target or test harness. In unit
> test aarch64_analyze_prologue_test, aarch64_analyze_prologue gets
> instructions we prepared in the test, as the input of prologue
> analyzer. Then, we checked various fields in
> 'struct aarch64_prologue_cache'.
>
> gdb:
>
> 2016-11-28 Yao Qi <yao.qi@linaro.org>
>
> * aarch64-tdep.c: Include "selftest.h".
> (abstract_instruction_reader): New class.
> (instruction_reader): New class.
> (aarch64_analyze_prologue): Add new parameter reader. Call
> reader.read instead of read_memory_unsigned_integer.
> [GDB_SELF_TEST] (instruction_reader_test): New class.
> (aarch64_analyze_prologue_test): New function.
> (_initialize_aarch64_tdep) [GDB_SELF_TEST]: Register
> selftests::aarch64_analyze_prologue_test.
> * trad-frame.c (trad_frame_cache_zalloc):
> (trad_frame_alloc_saved_regs): Add a new function.
> * trad-frame.h (trad_frame_alloc_saved_regs): Declare.
> ---
> gdb/aarch64-tdep.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
> gdb/trad-frame.c | 21 ++++++----
> gdb/trad-frame.h | 1 +
> 3 files changed, 129 insertions(+), 9 deletions(-)
>
> diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
> index 6b95d7c..b10002a 100644
> --- a/gdb/aarch64-tdep.c
> +++ b/gdb/aarch64-tdep.c
> @@ -44,6 +44,7 @@
> #include "infcall.h"
> #include "ax.h"
> #include "ax-gdb.h"
> +#include "selftest.h"
>
> #include "aarch64-tdep.h"
>
> @@ -195,6 +196,29 @@ show_aarch64_debug (struct ui_file *file, int from_tty,
> fprintf_filtered (file, _("AArch64 debugging is %s.\n"), value);
> }
>
> +/* Abstract instruction reader. */
> +
> +class abstract_instruction_reader
> +{
There is a new line before the class declaration here, but not on some
of the other declarations.
> +public:
> + /* Read in one instruction. */
> + virtual ULONGEST read (CORE_ADDR memaddr, int len,
> + enum bfd_endian byte_order) = 0;
> +};
> +
> +/* Instruction reader from real target. */
> +
> +class instruction_reader : public abstract_instruction_reader
> +{
> + public:
> + instruction_reader () = default;
> +
> + ULONGEST read (CORE_ADDR memaddr, int len, enum bfd_endian byte_order)
> + {
> + return read_memory_unsigned_integer (memaddr, len, byte_order);
> + }
> +};
> +
> /* Analyze a prologue, looking for a recognizable stack frame
> and frame pointer. Scan until we encounter a store that could
> clobber the stack frame unexpectedly, or an unknown instruction. */
> @@ -202,7 +226,8 @@ show_aarch64_debug (struct ui_file *file, int from_tty,
> static CORE_ADDR
> aarch64_analyze_prologue (struct gdbarch *gdbarch,
> CORE_ADDR start, CORE_ADDR limit,
> - struct aarch64_prologue_cache *cache)
> + struct aarch64_prologue_cache *cache,
> + abstract_instruction_reader& reader)
> {
> enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
> int i;
> @@ -221,7 +246,7 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
> uint32_t insn;
> aarch64_inst inst;
>
> - insn = read_memory_unsigned_integer (start, 4, byte_order_for_code);
> + insn = reader.read (start, 4, byte_order_for_code);
>
> if (aarch64_decode_insn (insn, &inst, 1) != 0)
> break;
> @@ -436,6 +461,89 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
> return start;
> }
>
> +static CORE_ADDR
> +aarch64_analyze_prologue (struct gdbarch *gdbarch,
> + CORE_ADDR start, CORE_ADDR limit,
> + struct aarch64_prologue_cache *cache)
> +{
> + instruction_reader reader { };
> +
> + return aarch64_analyze_prologue (gdbarch, start, limit, cache,
> + reader);
> +}
> +
> +#if GDB_SELF_TEST
> +
> +namespace selftests {
> +
> + /* Instruction reader from manually cooked instruction sequences. */
> + class instruction_reader_test : public abstract_instruction_reader
> + {
No newline between class declaration and comment.
> + public:
> + instruction_reader_test() = default ;
> + instruction_reader_test (std::initializer_list<uint32_t> init)
> + : insns{init} {}
> +
> + ULONGEST read (CORE_ADDR memaddr, int len, enum bfd_endian byte_order)
> + {
> + SELF_CHECK (len == 4);
> + SELF_CHECK (memaddr % 4 == 0);
> + SELF_CHECK (memaddr / 4 < insns.size());
> +
> + return insns[memaddr / 4];
> + }
> +
> + private:
> + std::vector<uint32_t> insns;
> + };
Should the curly braces both be on their own lines as the rest of the
uses? I see mixed formatting in the uses of namespace we currently have.
We should pick one and go with it.
I particularly dislike the curly brace on the same line being used to
GNU's coding standards.
> +
> +static void
> +aarch64_analyze_prologue_test (void)
> +{
> + struct gdbarch_info info;
> +
> + gdbarch_info_init (&info);
> + info.bfd_arch_info = bfd_scan_arch ("aarch64");
> +
> + struct gdbarch *gdbarch = gdbarch_find_by_info (info);
> + SELF_CHECK (gdbarch != NULL);
> +
> + struct aarch64_prologue_cache cache;
> + cache.saved_regs = trad_frame_alloc_saved_regs (gdbarch);
> +
> + instruction_reader_test test {
> + 0xa9af7bfd, /* stp x29, x30, [sp,#-272]! */
> + 0x910003fd, /* mov x29, sp */
> + 0x97ffffe6, /* bl 0x400580 */
> + };
Same here.
> +
> + CORE_ADDR end = aarch64_analyze_prologue (gdbarch, 0, 128,
> + &cache, test);
> + SELF_CHECK (end == 4 * 2);
> +
> + SELF_CHECK (cache.framereg == AARCH64_FP_REGNUM);
> + SELF_CHECK (cache.framesize == 272);
> +
> + for (int i = 0; i < AARCH64_X_REGISTER_COUNT; i++)
> + {
> + if (i == AARCH64_FP_REGNUM)
> + SELF_CHECK (cache.saved_regs[i].addr == -272);
> + else if (i == AARCH64_LR_REGNUM)
> + SELF_CHECK (cache.saved_regs[i].addr == -264);
> + else
> + SELF_CHECK (cache.saved_regs[i].addr == -1);
> + }
> +
> + for (int i = 0; i < AARCH64_D_REGISTER_COUNT; i++)
> + {
> + int regnum = gdbarch_num_regs (gdbarch);
> +
> + SELF_CHECK (cache.saved_regs[i + regnum + AARCH64_D0_REGNUM].addr == -1);
> + }
> +}
> +}
> +#endif /* GDB_SELF_TEST */
> +
> /* Implement the "skip_prologue" gdbarch method. */
>
> static CORE_ADDR
> @@ -2864,6 +2972,10 @@ When on, AArch64 specific debugging is enabled."),
> NULL,
> show_aarch64_debug,
> &setdebuglist, &showdebuglist);
> +
> +#if GDB_SELF_TEST
> + register_self_test (selftests::aarch64_analyze_prologue_test);
> +#endif
> }
>
> /* AArch64 process record-replay related structures, defines etc. */
> diff --git a/gdb/trad-frame.c b/gdb/trad-frame.c
> index ebf19df..4430dd5 100644
> --- a/gdb/trad-frame.c
> +++ b/gdb/trad-frame.c
> @@ -43,16 +43,10 @@ trad_frame_cache_zalloc (struct frame_info *this_frame)
> return this_trad_cache;
> }
>
> -/* A traditional frame is unwound by analysing the function prologue
> - and using the information gathered to track registers. For
> - non-optimized frames, the technique is reliable (just need to check
> - for all potential instruction sequences). */
> -
> struct trad_frame_saved_reg *
> -trad_frame_alloc_saved_regs (struct frame_info *this_frame)
> +trad_frame_alloc_saved_regs (struct gdbarch *gdbarch)
> {
> int regnum;
> - struct gdbarch *gdbarch = get_frame_arch (this_frame);
> int numregs = gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
> struct trad_frame_saved_reg *this_saved_regs
> = FRAME_OBSTACK_CALLOC (numregs, struct trad_frame_saved_reg);
> @@ -65,6 +59,19 @@ trad_frame_alloc_saved_regs (struct frame_info *this_frame)
> return this_saved_regs;
> }
>
> +/* A traditional frame is unwound by analysing the function prologue
> + and using the information gathered to track registers. For
> + non-optimized frames, the technique is reliable (just need to check
> + for all potential instruction sequences). */
> +
> +struct trad_frame_saved_reg *
> +trad_frame_alloc_saved_regs (struct frame_info *this_frame)
> +{
> + struct gdbarch *gdbarch = get_frame_arch (this_frame);
> +
> + return trad_frame_alloc_saved_regs (gdbarch);
> +}
> +
> enum { TF_REG_VALUE = -1, TF_REG_UNKNOWN = -2 };
>
> int
> diff --git a/gdb/trad-frame.h b/gdb/trad-frame.h
> index b8aed16..d1c24b0 100644
> --- a/gdb/trad-frame.h
> +++ b/gdb/trad-frame.h
> @@ -104,6 +104,7 @@ int trad_frame_realreg_p (struct trad_frame_saved_reg this_saved_regs[],
>
> /* Return a freshly allocated (and initialized) trad_frame array. */
> struct trad_frame_saved_reg *trad_frame_alloc_saved_regs (struct frame_info *);
> +struct trad_frame_saved_reg *trad_frame_alloc_saved_regs (struct gdbarch *);
>
> /* Given the trad_frame info, return the location of the specified
> register. */
>
Otherwise looks good to me.
next prev parent reply other threads:[~2016-11-30 19:30 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-11-29 14:12 Yao Qi
2016-11-29 14:12 ` [PATCH 2/2] [AArch64] Recognize STR instruction in prologue Yao Qi
2016-11-30 18:33 ` Pedro Alves
2016-11-29 14:58 ` [PATCH 1/2] Add unit test to aarch64 prologue analyzer Antoine Tremblay
2016-11-30 11:15 ` Yao Qi
2016-11-30 11:53 ` Antoine Tremblay
2016-11-30 16:35 ` Yao Qi
2016-11-30 16:42 ` Antoine Tremblay
2016-11-30 18:16 ` Pedro Alves
2016-11-30 18:29 ` Pedro Alves
2016-11-30 18:38 ` Pedro Alves
2016-11-30 19:30 ` Luis Machado [this message]
2016-12-01 12:53 ` Pedro Alves
2016-12-01 11:17 ` [PATCH 1/2 v2] " Yao Qi
2016-12-01 11:17 ` [PATCH 2/2 v2] [AArch64] Recognize STR instruction in prologue Yao Qi
2016-12-01 13:07 ` Pedro Alves
2016-12-02 9:42 ` Yao Qi
2016-12-01 12:57 ` [PATCH 1/2 v2] Add unit test to aarch64 prologue analyzer Pedro Alves
2016-12-01 15:21 ` Yao Qi
2016-12-01 16:04 ` Yao Qi
2016-12-01 18:05 ` Pedro Alves
2016-12-02 9:40 ` Yao Qi
2016-12-02 11:11 ` Pedro Alves
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=55ea5ba0-6ea7-686d-1841-48875ed8587c@codesourcery.com \
--to=lgustavo@codesourcery.com \
--cc=gdb-patches@sourceware.org \
--cc=qiyaoltc@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox