Message ID | 1404816844-1639-1-git-send-email-pierre.langlois@embecosm.com |
---|---|
State | New |
Headers | show |
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> .*\\).*" >
Hello, > 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. Sorry about the delay in reviewing this. Some comments below. > +/* 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. */ Can you start the comment by saying that this function implements the address_class_name_to_type_flags gdbarch method? You can then add the comment above as a second paragraph, or perhaps as an implementation comment inside the function body itself. > +static int > +avr_address_class_type_flags (int byte_size, int dwarf2_addr_class) > +{ Please add a comment saying that this function implements the address_class_type_flags gdbarch method. Generally speaking, all new functions without exception should have an introductory comment. > + // __flash qualifier Please do not use C++-style comments for the moment. > + 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) Same as above regarding the function's introductory comment. And also, I'd prefer it if we avoided two functions being documented with the same comment, as this opens the door for a function becoming undocumented if the two functions somehow get separated. > +{ > + 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) Missing introductory comment ("Implements the ...").
Hello Joel, > > Sorry about the delay in reviewing this. Some comments below. > That's OK, thank you very much for the review! >> + // __flash qualifier > > Please do not use C++-style comments for the moment. > Oh dear, I'm sorry about this. Thanks, Pierre
Hi Pierre, On 07/08/2014 11:54 AM, 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). > Thanks. This looks good to me, with a couple nits pointed out below addressed. > +/* Address space flags */ > + > +/* We are assigning the TYPE_INSTANCE_FLAG_ADDRESS_CLASS_1 to the flash address > + space. */ > /* 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. */ FYI, the "or the program counter" reference here looks a bit confusion-inducing to me. TYPE_CODE_FUNC -> function. TYPE_CODE_METHOD -> C++ class member functions (methods). I think you've added that, because the $pc register is of function pointer type? I'd suggest just not bringing that up, as it was before. > /* 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))) Particularly since this bit didn't get that comment? BTW, interesting/curious that TYPE_CODE_SPACE is handled here but not in avr_address_to_pointer. Offhand, looks like a bug, though off topic for this patch. > 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 Please use /**/-style comments, and write full sentences. > + if (dwarf2_addr_class == 1 && byte_size == 2) > + return AVR_TYPE_INSTANCE_FLAG_ADDRESS_CLASS_FLASH; > + return 0; > +} > + Thanks,
Hi Pedro, On 21/07/14 16:45, Pedro Alves wrote: > Hi Pierre, > > On 07/08/2014 11:54 AM, 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). >> > > Thanks. This looks good to me, with a couple nits pointed out > below addressed. > Thanks for looking at this. I have committed a better version of this patch last week after review. So I just submitted another patch improving the comments as suggested. >> +/* Address space flags */ >> + >> +/* We are assigning the TYPE_INSTANCE_FLAG_ADDRESS_CLASS_1 to the flash address >> + space. */ >> /* 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. */ > > FYI, the "or the program counter" reference here looks a bit > confusion-inducing to me. > > TYPE_CODE_FUNC -> function. > TYPE_CODE_METHOD -> C++ class member functions (methods). > > I think you've added that, because the $pc register is of function > pointer type? I'd suggest just not bringing that up, as it was before. > Yes you're right, I mentioned the $pc register because of its type. I understand it's confusing now. > >> /* 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))) > > Particularly since this bit didn't get that comment? > > BTW, interesting/curious that TYPE_CODE_SPACE is handled > here but not in avr_address_to_pointer. Offhand, looks like a > bug, though off topic for this patch. > I am bit puzzled here but I suspect this was done on purpose. I'll submit a patch so we can discuss it. Thanks, Pierre
On 07/23/2014 05:52 PM, Pierre Langlois wrote: > Hi Pedro, > > On 21/07/14 16:45, Pedro Alves wrote: >> Hi Pierre, >> >> On 07/08/2014 11:54 AM, 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). >>> >> >> Thanks. This looks good to me, with a couple nits pointed out >> below addressed. >> > > Thanks for looking at this. I have committed a better version of this patch > last week after review. So I just submitted another patch improving the > comments as suggested. > Whoops, I completely missed that. Sorry about that. > Yes you're right, I mentioned the $pc register because of its type. I > understand it's confusing now. > >> >>> /* 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))) >> >> Particularly since this bit didn't get that comment? >> >> BTW, interesting/curious that TYPE_CODE_SPACE is handled >> here but not in avr_address_to_pointer. Offhand, looks like a >> bug, though off topic for this patch. >> > > I am bit puzzled here but I suspect this was done on purpose. I'll submit a > patch so we can discuss it. > Thanks!
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> .*\\).*"