From patchwork Tue Jul 15 14:48:03 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pierre Langlois X-Patchwork-Id: 2059 Received: (qmail 3455 invoked by alias); 15 Jul 2014 14:48:19 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 3384 invoked by uid 89); 15 Jul 2014 14:48:15 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.4 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 X-HELO: mail-wg0-f50.google.com Received: from mail-wg0-f50.google.com (HELO mail-wg0-f50.google.com) (74.125.82.50) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Tue, 15 Jul 2014 14:48:12 +0000 Received: by mail-wg0-f50.google.com with SMTP id n12so5756517wgh.9 for ; Tue, 15 Jul 2014 07:48:09 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=BlS46nXga423L386jzxWB1GBkMg/rEYxx/vo9AX/9Qk=; b=RdVE4Q82bLyyaFkkNdV7fgFPDF57EriQOQ+XjS0GB9VHzoOcKvYbzcDcLofSp9K312 Nf6nYV6tUt7NFUd65B0ixaVhUHlNVQWF8VpUQ4Yu9EAXvjzsYSLarI7DdvFwWKnLzDJo qpZEf47/Al3JEXdUO3UY9FvoSbKrhEDOJ40+BnP9grCvikJdpAexxU1OveUNKwAlNyzT xro1Rc39kC98I0N/XzHv3xY56dmEjYPbeH6I9Xb+EjT2W6FCQLtzFOF5VJvBRCPQP5xG ETjKlAn9o46v0nMIOb8U/khmPNIgQJ4K/OEmD3tO+mcDN3/c17NrNg2aveYZG84MD9Ay 8ToQ== X-Gm-Message-State: ALoCoQlHoz4Z7CjFlEnxTnQ96VT+U2kP9p1/Awq2t3D7CfhSoIYxO828umCAA3iFrfihJPiZxDGA X-Received: by 10.194.71.132 with SMTP id v4mr13263463wju.102.1405435689850; Tue, 15 Jul 2014 07:48:09 -0700 (PDT) Received: from localhost.localdomain (cust64-dsl91-135-5.idnet.net. [91.135.5.64]) by mx.google.com with ESMTPSA id s14sm11592898wij.1.2014.07.15.07.48.08 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 15 Jul 2014 07:48:09 -0700 (PDT) From: Pierre Langlois To: gdb-patches@sourceware.org Cc: Pierre Langlois Subject: [PATCH v2] Add support for the __flash qualifier on AVR Date: Tue, 15 Jul 2014 15:48:03 +0100 Message-Id: <1405435683-10535-1-git-send-email-pierre.langlois@embecosm.com> In-Reply-To: <1404816844-1639-1-git-send-email-pierre.langlois@embecosm.com> References: <1404816844-1639-1-git-send-email-pierre.langlois@embecosm.com> X-IsSubscribed: yes 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 "\253" (gdb) print/x *pointer_to_flash $2 = 0xab (gdb) x/x pointer_to_flash 0x1e8 : 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 "" ~~~ [1] https://gcc.gnu.org/onlinedocs/gcc/Named-Address-Spaces.html 2014-07-08 Pierre Langlois 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 | 85 ++++++++++++++++++++++++-- gdb/testsuite/gdb.arch/avr-flash-qualifier.c | 32 ++++++++++ gdb/testsuite/gdb.arch/avr-flash-qualifier.exp | 52 ++++++++++++++++ 3 files changed, 164 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..d3a0e87 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,53 @@ avr_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg) return -1; } +/* Implementation of `address_class_type_flags' gdbarch method. + + This method maps DW_AT_address_class attributes to a + type_instance_flag_value. */ + +static int +avr_address_class_type_flags (int byte_size, int dwarf2_addr_class) +{ + /* The value 1 of the DW_AT_address_class attribute corresponds to the __flash + qualifier. 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. */ + if (dwarf2_addr_class == 1 && byte_size == 2) + return AVR_TYPE_INSTANCE_FLAG_ADDRESS_CLASS_FLASH; + return 0; +} + +/* Implementation of `address_class_type_flags_to_name' gdbarch method. + + Convert a type_instance_flag_value to an address space qualifier. */ + +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; +} + +/* Implementation of `address_class_name_to_type_flags' gdbarch method. + + Convert an address space qualifier to a type_instance_flag_value. */ + +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 +1521,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 . */ + +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 . +# +# This file is part of the gdb testsuite. +# +# Contributed by Pierre Langlois +# 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 .*" + +gdb_breakpoint "pass_to_function" +gdb_continue_to_breakpoint "pass_to_function" + +gdb_test "print p" \ + " = $hex .*" + +gdb_test "backtrace 1" \ + "\#0 pass_to_function \\(p=$hex .*\\).*"