mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-10-18 13:23:10 +08:00
fort_dyn_array: Enable dynamic member types inside a structure.
Fortran supports dynamic types for which bounds, size and location can vary during their lifetime. As a result of the dynamic behaviour, they have to be resolved at every query. This patch will resolve the type of a structure field when it is dynamic. 2016-04-26 Bernhard Heckel <bernhard.heckel@intel.com> 2016-04-26 Keven Boell <keven.boell@intel.com> Before: (gdb) print threev%ivla(1) Cannot access memory at address 0x3 (gdb) print threev%ivla(5) no such vector element After: (gdb) print threev%ivla(1) $9 = 1 (gdb) print threev%ivla(5) $10 = 42 gdb/Changelog: * NEWS: Add new supported features for fortran. * gdbtypes.c (remove_dyn_prop): New. (resolve_dynamic_struct): Keep type length for fortran structs. * gdbtypes.h: Forward declaration of new function. * value.c (value_address): Return dynamic resolved location of a value. (set_value_component_location): Adjust the value address for single value prints. (value_primitive_field): Support value types with a dynamic location. (set_internalvar): Remove dynamic location property of internal variables. gdb/testsuite/Changelog: * gdb.fortran/vla-type.f90: New file. * gdb.fortran/vla-type.exp: New file.
This commit is contained in:
@ -1,3 +1,17 @@
|
|||||||
|
2016-04-26 Bernhard Heckel <bernhard.heckel@intel.com>
|
||||||
|
Keven Boell <kevel.boell@intel.com>
|
||||||
|
|
||||||
|
* NEWS: Add new supported features for fortran.
|
||||||
|
* gdbtypes.c (remove_dyn_prop): New.
|
||||||
|
(resolve_dynamic_struct): Keep type length for fortran structs.
|
||||||
|
* gdbtypes.h: Forward declaration of new function.
|
||||||
|
* value.c (value_address): Return dynamic resolved location of a value.
|
||||||
|
(set_value_component_location): Adjust the value address
|
||||||
|
for single value prints.
|
||||||
|
(value_primitive_field): Support value types with a dynamic location.
|
||||||
|
(set_internalvar): Remove dynamic location property of
|
||||||
|
internal variables.
|
||||||
|
|
||||||
2016-04-25 Pedro Alves <palves@redhat.com>
|
2016-04-25 Pedro Alves <palves@redhat.com>
|
||||||
Yao Qi <yao.qi@linaro.org>
|
Yao Qi <yao.qi@linaro.org>
|
||||||
|
|
||||||
|
3
gdb/NEWS
3
gdb/NEWS
@ -3,6 +3,9 @@
|
|||||||
|
|
||||||
*** Changes since GDB 7.11
|
*** Changes since GDB 7.11
|
||||||
|
|
||||||
|
* Fortran: Support structures with fields of dynamic types and
|
||||||
|
arrays of dynamic types.
|
||||||
|
|
||||||
* GDB now supports multibit bitfields and enums in target register
|
* GDB now supports multibit bitfields and enums in target register
|
||||||
descriptions.
|
descriptions.
|
||||||
|
|
||||||
|
@ -2064,7 +2064,9 @@ resolve_dynamic_struct (struct type *type,
|
|||||||
|
|
||||||
pinfo.type = check_typedef (TYPE_FIELD_TYPE (type, i));
|
pinfo.type = check_typedef (TYPE_FIELD_TYPE (type, i));
|
||||||
pinfo.valaddr = addr_stack->valaddr;
|
pinfo.valaddr = addr_stack->valaddr;
|
||||||
pinfo.addr = addr_stack->addr;
|
pinfo.addr
|
||||||
|
= (addr_stack->addr
|
||||||
|
+ (TYPE_FIELD_BITPOS (resolved_type, i) / TARGET_CHAR_BIT));
|
||||||
pinfo.next = addr_stack;
|
pinfo.next = addr_stack;
|
||||||
|
|
||||||
TYPE_FIELD_TYPE (resolved_type, i)
|
TYPE_FIELD_TYPE (resolved_type, i)
|
||||||
@ -2090,8 +2092,13 @@ resolve_dynamic_struct (struct type *type,
|
|||||||
resolved_type_bit_length = new_bit_length;
|
resolved_type_bit_length = new_bit_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPE_LENGTH (resolved_type)
|
/* The length of a type won't change for fortran, but it does for C and Ada.
|
||||||
= (resolved_type_bit_length + TARGET_CHAR_BIT - 1) / TARGET_CHAR_BIT;
|
For fortran the size of dynamic fields might change over time but not the
|
||||||
|
type length of the structure. If we adapt it, we run into problems
|
||||||
|
when calculating the element offset for arrays of structs. */
|
||||||
|
if (current_language->la_language != language_fortran)
|
||||||
|
TYPE_LENGTH (resolved_type)
|
||||||
|
= (resolved_type_bit_length + TARGET_CHAR_BIT - 1) / TARGET_CHAR_BIT;
|
||||||
|
|
||||||
/* The Ada language uses this field as a cache for static fixed types: reset
|
/* The Ada language uses this field as a cache for static fixed types: reset
|
||||||
it as RESOLVED_TYPE must have its own static fixed type. */
|
it as RESOLVED_TYPE must have its own static fixed type. */
|
||||||
@ -2224,6 +2231,37 @@ add_dyn_prop (enum dynamic_prop_node_kind prop_kind, struct dynamic_prop prop,
|
|||||||
TYPE_DYN_PROP_LIST (type) = temp;
|
TYPE_DYN_PROP_LIST (type) = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove dynamic property from TYPE in case it exists. */
|
||||||
|
|
||||||
|
void
|
||||||
|
remove_dyn_prop (enum dynamic_prop_node_kind prop_kind,
|
||||||
|
struct type *type)
|
||||||
|
{
|
||||||
|
struct dynamic_prop_list *prev_node, *curr_node;
|
||||||
|
|
||||||
|
curr_node = TYPE_DYN_PROP_LIST (type);
|
||||||
|
prev_node = NULL;
|
||||||
|
|
||||||
|
while (NULL != curr_node)
|
||||||
|
{
|
||||||
|
if (curr_node->prop_kind == prop_kind)
|
||||||
|
{
|
||||||
|
/* Update the linked list but don't free anything.
|
||||||
|
The property was allocated on objstack and it is not known
|
||||||
|
if we are on top of it. Nevertheless, everything is released
|
||||||
|
when the complete objstack is freed. */
|
||||||
|
if (NULL == prev_node)
|
||||||
|
TYPE_DYN_PROP_LIST (type) = curr_node->next;
|
||||||
|
else
|
||||||
|
prev_node->next = curr_node->next;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_node = curr_node;
|
||||||
|
curr_node = curr_node->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Find the real type of TYPE. This function returns the real type,
|
/* Find the real type of TYPE. This function returns the real type,
|
||||||
after removing all layers of typedefs, and completing opaque or stub
|
after removing all layers of typedefs, and completing opaque or stub
|
||||||
|
@ -1826,6 +1826,9 @@ extern void add_dyn_prop
|
|||||||
(enum dynamic_prop_node_kind kind, struct dynamic_prop prop,
|
(enum dynamic_prop_node_kind kind, struct dynamic_prop prop,
|
||||||
struct type *type, struct objfile *objfile);
|
struct type *type, struct objfile *objfile);
|
||||||
|
|
||||||
|
extern void remove_dyn_prop (enum dynamic_prop_node_kind prop_kind,
|
||||||
|
struct type *type);
|
||||||
|
|
||||||
extern struct type *check_typedef (struct type *);
|
extern struct type *check_typedef (struct type *);
|
||||||
|
|
||||||
extern void check_stub_method_group (struct type *, int);
|
extern void check_stub_method_group (struct type *, int);
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2016-04-26 Bernhard Heckel <bernhard.heckel@intel.com>
|
||||||
|
|
||||||
|
* gdb.fortran/vla-type.f90: New file.
|
||||||
|
* gdb.fortran/vla-type.exp: New file.
|
||||||
|
|
||||||
2016-04-25 Yao Qi <yao.qi@linaro.org>
|
2016-04-25 Yao Qi <yao.qi@linaro.org>
|
||||||
|
|
||||||
* gdb.base/branch-to-self.c: New file.
|
* gdb.base/branch-to-self.c: New file.
|
||||||
|
102
gdb/testsuite/gdb.fortran/vla-type.exp
Executable file
102
gdb/testsuite/gdb.fortran/vla-type.exp
Executable file
@ -0,0 +1,102 @@
|
|||||||
|
# Copyright 2016 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/>.
|
||||||
|
|
||||||
|
standard_testfile ".f90"
|
||||||
|
load_lib "fortran.exp"
|
||||||
|
|
||||||
|
if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} \
|
||||||
|
{debug f90 quiet}] } {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if ![runto_main] {
|
||||||
|
untested "could not run to main"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Depending on the compiler being used, the type names can be printed differently.
|
||||||
|
set int [fortran_int4]
|
||||||
|
|
||||||
|
# Check if not allocated VLA in type does not break
|
||||||
|
# the debugger when accessing it.
|
||||||
|
gdb_breakpoint [gdb_get_line_number "before-allocated"]
|
||||||
|
gdb_continue_to_breakpoint "before-allocated"
|
||||||
|
gdb_test "print twov" " = \\\( <not allocated>, <not allocated> \\\)" \
|
||||||
|
"print twov before allocated"
|
||||||
|
gdb_test "print twov%ivla1" " = <not allocated>" \
|
||||||
|
"print twov%ivla1 before allocated"
|
||||||
|
|
||||||
|
# Check type with one VLA's inside
|
||||||
|
gdb_breakpoint [gdb_get_line_number "onev-filled"]
|
||||||
|
gdb_continue_to_breakpoint "onev-filled"
|
||||||
|
gdb_test "print onev%ivla(5, 11, 23)" " = 1"
|
||||||
|
gdb_test "print onev%ivla(1, 2, 3)" " = 123"
|
||||||
|
gdb_test "print onev%ivla(3, 2, 1)" " = 321"
|
||||||
|
gdb_test "ptype onev" \
|
||||||
|
[multi_line "type = Type one" \
|
||||||
|
"\\s+$int :: ivla\\\(11,22,33\\\)" \
|
||||||
|
"End Type one" ]
|
||||||
|
|
||||||
|
# Check type with two VLA's inside
|
||||||
|
gdb_breakpoint [gdb_get_line_number "twov-filled"]
|
||||||
|
gdb_continue_to_breakpoint "twov-filled"
|
||||||
|
gdb_test "print twov%ivla1(5, 11, 23)" " = 1"
|
||||||
|
gdb_test "print twov%ivla1(1, 2, 3)" " = 123"
|
||||||
|
gdb_test "print twov%ivla1(3, 2, 1)" " = 321"
|
||||||
|
gdb_test "ptype twov" \
|
||||||
|
[multi_line "type = Type two" \
|
||||||
|
"\\s+$int :: ivla1\\\(5,12,99\\\)" \
|
||||||
|
"\\s+$int :: ivla2\\\(9,12\\\)" \
|
||||||
|
"End Type two" ]
|
||||||
|
|
||||||
|
# Check type with attribute at beginn of type
|
||||||
|
gdb_breakpoint [gdb_get_line_number "threev-filled"]
|
||||||
|
gdb_continue_to_breakpoint "threev-filled"
|
||||||
|
gdb_test "print threev%ivla(1)" " = 1"
|
||||||
|
gdb_test "print threev%ivla(5)" " = 42"
|
||||||
|
gdb_test "print threev%ivla(14)" " = 24"
|
||||||
|
gdb_test "print threev%ivar" " = 3"
|
||||||
|
gdb_test "ptype threev" \
|
||||||
|
[multi_line "type = Type three" \
|
||||||
|
"\\s+$int :: ivar" \
|
||||||
|
"\\s+$int :: ivla\\\(20\\\)" \
|
||||||
|
"End Type three" ]
|
||||||
|
|
||||||
|
# Check type with attribute at end of type
|
||||||
|
gdb_breakpoint [gdb_get_line_number "fourv-filled"]
|
||||||
|
gdb_continue_to_breakpoint "fourv-filled"
|
||||||
|
gdb_test "print fourv%ivla(1)" " = 1"
|
||||||
|
gdb_test "print fourv%ivla(2)" " = 2"
|
||||||
|
gdb_test "print fourv%ivla(7)" " = 7"
|
||||||
|
gdb_test "print fourv%ivla(12)" "no such vector element"
|
||||||
|
gdb_test "print fourv%ivar" " = 3"
|
||||||
|
gdb_test "ptype fourv" \
|
||||||
|
[multi_line "type = Type four" \
|
||||||
|
"\\s+$int :: ivla\\\(10\\\)" \
|
||||||
|
"\\s+$int :: ivar" \
|
||||||
|
"End Type four" ]
|
||||||
|
|
||||||
|
# Check nested types containing a VLA
|
||||||
|
gdb_breakpoint [gdb_get_line_number "fivev-filled"]
|
||||||
|
gdb_continue_to_breakpoint "fivev-filled"
|
||||||
|
gdb_test "print fivev%tone%ivla(5, 5, 1)" " = 1"
|
||||||
|
gdb_test "print fivev%tone%ivla(1, 2, 3)" " = 123"
|
||||||
|
gdb_test "print fivev%tone%ivla(3, 2, 1)" " = 321"
|
||||||
|
gdb_test "ptype fivev" \
|
||||||
|
[multi_line "type = Type five" \
|
||||||
|
"\\s+Type one" \
|
||||||
|
"\\s+$int :: ivla\\\(10,10,10\\\)" \
|
||||||
|
"\\s+End Type one :: tone" \
|
||||||
|
"End Type five" ]
|
88
gdb/testsuite/gdb.fortran/vla-type.f90
Executable file
88
gdb/testsuite/gdb.fortran/vla-type.f90
Executable file
@ -0,0 +1,88 @@
|
|||||||
|
! Copyright 2016 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/>.
|
||||||
|
|
||||||
|
program vla_struct
|
||||||
|
type :: one
|
||||||
|
integer, allocatable :: ivla (:, :, :)
|
||||||
|
end type one
|
||||||
|
type :: two
|
||||||
|
integer, allocatable :: ivla1 (:, :, :)
|
||||||
|
integer, allocatable :: ivla2 (:, :)
|
||||||
|
end type two
|
||||||
|
type :: three
|
||||||
|
integer :: ivar
|
||||||
|
integer, allocatable :: ivla (:)
|
||||||
|
end type three
|
||||||
|
type :: four
|
||||||
|
integer, allocatable :: ivla (:)
|
||||||
|
integer :: ivar
|
||||||
|
end type four
|
||||||
|
type :: five
|
||||||
|
type(one) :: tone
|
||||||
|
end type five
|
||||||
|
|
||||||
|
type(one), target :: onev
|
||||||
|
type(two) :: twov
|
||||||
|
type(three) :: threev
|
||||||
|
type(four) :: fourv
|
||||||
|
type(five) :: fivev
|
||||||
|
logical :: l
|
||||||
|
integer :: i, j
|
||||||
|
|
||||||
|
allocate (onev%ivla (11,22,33)) ! before-allocated
|
||||||
|
l = allocated(onev%ivla)
|
||||||
|
|
||||||
|
onev%ivla(:, :, :) = 1
|
||||||
|
onev%ivla(1, 2, 3) = 123
|
||||||
|
onev%ivla(3, 2, 1) = 321
|
||||||
|
|
||||||
|
allocate (twov%ivla1 (5,12,99)) ! onev-filled
|
||||||
|
l = allocated(twov%ivla1)
|
||||||
|
allocate (twov%ivla2 (9,12))
|
||||||
|
l = allocated(twov%ivla2)
|
||||||
|
|
||||||
|
twov%ivla1(:, :, :) = 1
|
||||||
|
twov%ivla1(1, 2, 3) = 123
|
||||||
|
twov%ivla1(3, 2, 1) = 321
|
||||||
|
|
||||||
|
twov%ivla2(:, :) = 1
|
||||||
|
twov%ivla2(1, 2) = 12
|
||||||
|
twov%ivla2(2, 1) = 21
|
||||||
|
|
||||||
|
threev%ivar = 3 ! twov-filled
|
||||||
|
allocate (threev%ivla (20))
|
||||||
|
l = allocated(threev%ivla)
|
||||||
|
|
||||||
|
threev%ivla(:) = 1
|
||||||
|
threev%ivla(5) = 42
|
||||||
|
threev%ivla(14) = 24
|
||||||
|
|
||||||
|
allocate (fourv%ivla (10)) ! threev-filled
|
||||||
|
l = allocated(fourv%ivla)
|
||||||
|
|
||||||
|
fourv%ivar = 3
|
||||||
|
fourv%ivla(:) = 1
|
||||||
|
fourv%ivla(2) = 2
|
||||||
|
fourv%ivla(7) = 7
|
||||||
|
|
||||||
|
allocate (fivev%tone%ivla (10, 10, 10)) ! fourv-filled
|
||||||
|
l = allocated(fivev%tone%ivla)
|
||||||
|
fivev%tone%ivla(:, :, :) = 1
|
||||||
|
fivev%tone%ivla(1, 2, 3) = 123
|
||||||
|
fivev%tone%ivla(3, 2, 1) = 321
|
||||||
|
|
||||||
|
! dummy statement for bp
|
||||||
|
l = allocated(fivev%tone%ivla) ! fivev-filled
|
||||||
|
end program vla_struct
|
39
gdb/value.c
39
gdb/value.c
@ -1541,8 +1541,13 @@ value_address (const struct value *value)
|
|||||||
return 0;
|
return 0;
|
||||||
if (value->parent != NULL)
|
if (value->parent != NULL)
|
||||||
return value_address (value->parent) + value->offset;
|
return value_address (value->parent) + value->offset;
|
||||||
else
|
if (NULL != TYPE_DATA_LOCATION (value_type (value)))
|
||||||
return value->location.address + value->offset;
|
{
|
||||||
|
gdb_assert (PROP_CONST == TYPE_DATA_LOCATION_KIND (value_type (value)));
|
||||||
|
return TYPE_DATA_LOCATION_ADDR (value_type (value));
|
||||||
|
}
|
||||||
|
|
||||||
|
return value->location.address + value->offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
CORE_ADDR
|
CORE_ADDR
|
||||||
@ -1857,6 +1862,8 @@ void
|
|||||||
set_value_component_location (struct value *component,
|
set_value_component_location (struct value *component,
|
||||||
const struct value *whole)
|
const struct value *whole)
|
||||||
{
|
{
|
||||||
|
struct type *type;
|
||||||
|
|
||||||
gdb_assert (whole->lval != lval_xcallable);
|
gdb_assert (whole->lval != lval_xcallable);
|
||||||
|
|
||||||
if (whole->lval == lval_internalvar)
|
if (whole->lval == lval_internalvar)
|
||||||
@ -1872,9 +1879,15 @@ set_value_component_location (struct value *component,
|
|||||||
if (funcs->copy_closure)
|
if (funcs->copy_closure)
|
||||||
component->location.computed.closure = funcs->copy_closure (whole);
|
component->location.computed.closure = funcs->copy_closure (whole);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If type has a dynamic resolved location property
|
||||||
|
update it's value address. */
|
||||||
|
type = value_type (whole);
|
||||||
|
if (NULL != TYPE_DATA_LOCATION (type)
|
||||||
|
&& TYPE_DATA_LOCATION_KIND (type) == PROP_CONST)
|
||||||
|
set_value_address (component, TYPE_DATA_LOCATION_ADDR (type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Access to the value history. */
|
/* Access to the value history. */
|
||||||
|
|
||||||
/* Record a new value in the value history.
|
/* Record a new value in the value history.
|
||||||
@ -2427,6 +2440,15 @@ set_internalvar (struct internalvar *var, struct value *val)
|
|||||||
call error () until new_data is installed into the var->u to avoid
|
call error () until new_data is installed into the var->u to avoid
|
||||||
leaking memory. */
|
leaking memory. */
|
||||||
release_value (new_data.value);
|
release_value (new_data.value);
|
||||||
|
|
||||||
|
/* Internal variables which are created from values with a dynamic
|
||||||
|
location don't need the location property of the origin anymore.
|
||||||
|
The resolved dynamic location is used prior then any other address
|
||||||
|
when accessing the value.
|
||||||
|
If we keep it, we would still refer to the origin value.
|
||||||
|
Remove the location property in case it exist. */
|
||||||
|
remove_dyn_prop (DYN_PROP_DATA_LOCATION, value_type (new_data.value));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3168,6 +3190,17 @@ value_primitive_field (struct value *arg1, int offset,
|
|||||||
v->offset = value_offset (arg1);
|
v->offset = value_offset (arg1);
|
||||||
v->embedded_offset = offset + value_embedded_offset (arg1) + boffset;
|
v->embedded_offset = offset + value_embedded_offset (arg1) + boffset;
|
||||||
}
|
}
|
||||||
|
else if (NULL != TYPE_DATA_LOCATION (type))
|
||||||
|
{
|
||||||
|
/* Field is a dynamic data member. */
|
||||||
|
|
||||||
|
gdb_assert (0 == offset);
|
||||||
|
/* We expect an already resolved data location. */
|
||||||
|
gdb_assert (PROP_CONST == TYPE_DATA_LOCATION_KIND (type));
|
||||||
|
/* For dynamic data types defer memory allocation
|
||||||
|
until we actual access the value. */
|
||||||
|
v = allocate_value_lazy (type);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Plain old data member */
|
/* Plain old data member */
|
||||||
|
Reference in New Issue
Block a user