[PING][PATCH] Add support for the __flash qualifier on AVR
Pierre Langlois
pierre.langlois@embecosm.com
Tue Jul 15 10:36:00 GMT 2014
Ping.
On 08/07/14 11:54, Pierre Langlois wrote:
> The __flash qualifier is part of the named address spaces for AVR [1]. It allows
> putting read-only data in the flash memory, normally reserved for code.
>
> When used together with a pointer, the DW_AT_address_class attribute is set to 1
> and allows GDB to detect that when it will be dereferenced, the data will be
> loaded from the flash memory (with the LPM instruction).
>
> We can now properly debug the following code:
>
> ~~~
> const __flash char data_in_flash = 0xab;
>
> int
> main (void)
> {
> const __flash char *pointer_to_flash = &data_in_flash;
> }
> ~~~
>
> ~~~
> (gdb) print pointer_to_flash
> $1 = 0x1e8 <data_in_flash> "\253"
> (gdb) print/x *pointer_to_flash
> $2 = 0xab
> (gdb) x/x pointer_to_flash
> 0x1e8 <data_in_flash>: 0xXXXXXXab
> ~~~
>
> Whereas previously, GDB would revert to the default address space which is RAM
> and mapped in higher memory:
>
> ~~~
> (gdb) print pointer_to_flash
> $1 = 0x8001e8 ""
> ~~~
>
> Thanks,
>
> Pierre
>
> [1] https://gcc.gnu.org/onlinedocs/gcc/Named-Address-Spaces.html
>
> 2014-07-08 Pierre Langlois <pierre.langlois@embecosm.com>
>
> gdb/
> * avr-tdep.c (AVR_TYPE_ADDRESS_CLASS_FLASH): New macro.
> (AVR_TYPE_INSTANCE_FLAG_ADDRESS_CLASS_FLASH): Likewise.
> (avr_address_to_pointer): Check for AVR_TYPE_ADDRESS_CLASS_FLASH.
> (avr_pointer_to_address): Likewise.
> (avr_address_class_type_flags): New function.
> (avr_address_class_type_flags_to_name): Likewise.
> (avr_address_class_name_to_type_flags): Likewise.
> (avr_gdbarch_init): Set address_class_type_flags,
> address_class_type_flags_to_name and
> address_class_name_to_type_flags.
>
> gdb/testsuite/
> * gdb.arch/avr-flash-qualifer.c: New.
> * gdb.arch/avr-flash-qualifer.exp: New.
> ---
> gdb/avr-tdep.c | 77 ++++++++++++++++++++++++--
> gdb/testsuite/gdb.arch/avr-flash-qualifier.c | 32 +++++++++++
> gdb/testsuite/gdb.arch/avr-flash-qualifier.exp | 52 +++++++++++++++++
> 3 files changed, 156 insertions(+), 5 deletions(-)
> create mode 100644 gdb/testsuite/gdb.arch/avr-flash-qualifier.c
> create mode 100644 gdb/testsuite/gdb.arch/avr-flash-qualifier.exp
>
> diff --git a/gdb/avr-tdep.c b/gdb/avr-tdep.c
> index 9b0bfaf..eb99748 100644
> --- a/gdb/avr-tdep.c
> +++ b/gdb/avr-tdep.c
> @@ -71,6 +71,16 @@
>
> /* Constants: prefixed with AVR_ to avoid name space clashes */
>
> +/* Address space flags */
> +
> +/* We are assigning the TYPE_INSTANCE_FLAG_ADDRESS_CLASS_1 to the flash address
> + space. */
> +
> +#define AVR_TYPE_ADDRESS_CLASS_FLASH TYPE_ADDRESS_CLASS_1
> +#define AVR_TYPE_INSTANCE_FLAG_ADDRESS_CLASS_FLASH \
> + TYPE_INSTANCE_FLAG_ADDRESS_CLASS_1
> +
> +
> enum
> {
> AVR_REG_W = 24,
> @@ -295,10 +305,19 @@ avr_address_to_pointer (struct gdbarch *gdbarch,
> {
> enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
>
> + /* Is it a data address in flash? */
> + if (AVR_TYPE_ADDRESS_CLASS_FLASH (type))
> + {
> + /* A data address in flash is always byte addressed. */
> + store_unsigned_integer (buf, TYPE_LENGTH (type), byte_order,
> + avr_convert_iaddr_to_raw (addr));
> + }
> /* Is it a code address? */
> - if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC
> - || TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD)
> + else if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC
> + || TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD)
> {
> + /* A code address, either a function pointer or the program counter, is
> + word (16 bits) addressed. */
> store_unsigned_integer (buf, TYPE_LENGTH (type), byte_order,
> avr_convert_iaddr_to_raw (addr >> 1));
> }
> @@ -318,10 +337,13 @@ avr_pointer_to_address (struct gdbarch *gdbarch,
> CORE_ADDR addr
> = extract_unsigned_integer (buf, TYPE_LENGTH (type), byte_order);
>
> + /* Is it a data address in flash? */
> + if (AVR_TYPE_ADDRESS_CLASS_FLASH (type))
> + return avr_make_iaddr (addr);
> /* Is it a code address? */
> - if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC
> - || TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD
> - || TYPE_CODE_SPACE (TYPE_TARGET_TYPE (type)))
> + else if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC
> + || TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD
> + || TYPE_CODE_SPACE (TYPE_TARGET_TYPE (type)))
> return avr_make_iaddr (addr << 1);
> else
> return avr_make_saddr (addr);
> @@ -1342,6 +1364,45 @@ avr_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg)
> return -1;
> }
>
> +/* Map DW_AT_address_class attributes to a type_instance_flag_value. Note that
> + this attribute is only valid with pointer types and therefore the flag is set
> + to the pointer type and not its target type. */
> +
> +static int
> +avr_address_class_type_flags (int byte_size, int dwarf2_addr_class)
> +{
> + // __flash qualifier
> + if (dwarf2_addr_class == 1 && byte_size == 2)
> + return AVR_TYPE_INSTANCE_FLAG_ADDRESS_CLASS_FLASH;
> + return 0;
> +}
> +
> +/* Convert a type_instance_flag_value to an address space qualifier and
> + vice-versa. */
> +
> +static const char*
> +avr_address_class_type_flags_to_name (struct gdbarch *gdbarch, int type_flags)
> +{
> + if (type_flags & AVR_TYPE_INSTANCE_FLAG_ADDRESS_CLASS_FLASH)
> + return "flash";
> + else
> + return NULL;
> +}
> +
> +static int
> +avr_address_class_name_to_type_flags (struct gdbarch *gdbarch,
> + const char* name,
> + int *type_flags_ptr)
> +{
> + if (strcmp (name, "flash") == 0)
> + {
> + *type_flags_ptr = AVR_TYPE_INSTANCE_FLAG_ADDRESS_CLASS_FLASH;
> + return 1;
> + }
> + else
> + return 0;
> +}
> +
> /* Initialize the gdbarch structure for the AVR's. */
>
> static struct gdbarch *
> @@ -1452,6 +1513,12 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
> set_gdbarch_unwind_pc (gdbarch, avr_unwind_pc);
> set_gdbarch_unwind_sp (gdbarch, avr_unwind_sp);
>
> + set_gdbarch_address_class_type_flags (gdbarch, avr_address_class_type_flags);
> + set_gdbarch_address_class_name_to_type_flags
> + (gdbarch, avr_address_class_name_to_type_flags);
> + set_gdbarch_address_class_type_flags_to_name
> + (gdbarch, avr_address_class_type_flags_to_name);
> +
> return gdbarch;
> }
>
> diff --git a/gdb/testsuite/gdb.arch/avr-flash-qualifier.c b/gdb/testsuite/gdb.arch/avr-flash-qualifier.c
> new file mode 100644
> index 0000000..4e5b451
> --- /dev/null
> +++ b/gdb/testsuite/gdb.arch/avr-flash-qualifier.c
> @@ -0,0 +1,32 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> + Copyright 2014 Free Software Foundation, Inc.
> +
> + This program is free software; you can redistribute it and/or modify
> + it under the terms of the GNU General Public License as published by
> + the Free Software Foundation; either version 3 of the License, or
> + (at your option) any later version.
> +
> + This program is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + GNU General Public License for more details.
> +
> + You should have received a copy of the GNU General Public License
> + along with this program. If not, see <http://www.gnu.org/licenses/>. */
> +
> +const __flash char data_in_flash = 0xab;
> +
> +static void
> +pass_to_function (const __flash char *p)
> +{
> +}
> +
> +int
> +main (void)
> +{
> + const __flash char *pointer_to_flash = &data_in_flash;
> + /* break here. */
> + pass_to_function (&data_in_flash);
> + return 0;
> +}
> diff --git a/gdb/testsuite/gdb.arch/avr-flash-qualifier.exp b/gdb/testsuite/gdb.arch/avr-flash-qualifier.exp
> new file mode 100644
> index 0000000..e9ccb4f
> --- /dev/null
> +++ b/gdb/testsuite/gdb.arch/avr-flash-qualifier.exp
> @@ -0,0 +1,52 @@
> +# Copyright 2014 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program. If not, see <http://www.gnu.org/licenses/>.
> +#
> +# This file is part of the gdb testsuite.
> +#
> +# Contributed by Pierre Langlois <pierre.langlois@embecosm.com>
> +# Tests for the AVR __flash named address space qualifier.
> +
> +if {![istarget "avr*"]} {
> + verbose "Skipping ${gdb_test_file_name}."
> + return
> +}
> +
> +# The __flash qualifier was added in GCC 4.7.
> +if {[test_compiler_info {gcc-[0-4]-[0-6]}]} {
> + verbose "Skipping ${gdb_test_file_name}."
> + return
> +}
> +
> +standard_testfile
> +if {[prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}]} {
> + return -1
> +}
> +
> +if ![runto [gdb_get_line_number "break here."]] {
> + untested "could not run to \"break here.\""
> + return -1
> +}
> +
> +gdb_test "print pointer_to_flash" \
> + " = $hex <data_in_flash> .*"
> +
> +gdb_breakpoint "pass_to_function"
> +gdb_continue_to_breakpoint "pass_to_function"
> +
> +gdb_test "print p" \
> + " = $hex <data_in_flash> .*"
> +
> +gdb_test "backtrace 1" \
> + "\#0 pass_to_function \\(p=$hex <data_in_flash> .*\\).*"
>
More information about the Gdb-patches
mailing list