aboutsummaryrefslogtreecommitdiff
path: root/gdb/f-lang.c
diff options
context:
space:
mode:
authorAndrew Burgess <andrew.burgess@embecosm.com>2020-12-18 11:59:54 +0000
committerAndrew Burgess <andrew.burgess@embecosm.com>2020-12-24 16:45:40 +0000
commitb7874836c331d13e5478c775477b12abf7c481a0 (patch)
treec2bd2f017919f0f581d7dc16facbb558a75241d0 /gdb/f-lang.c
parent5ba3b20ec23816e07ecc5ce58bc7585f371e2f8c (diff)
downloadbinutils-b7874836c331d13e5478c775477b12abf7c481a0.zip
binutils-b7874836c331d13e5478c775477b12abf7c481a0.tar.gz
binutils-b7874836c331d13e5478c775477b12abf7c481a0.tar.bz2
gdb: avoid resolving dynamic properties for non-allocated arrays
In PR gdb/27059 an issue was discovered where GDB would sometimes trigger undefined behaviour in the form of signed integer overflow. The problem here is that GDB was reading random garbage from the inferior memory space, assuming this data was valid, and performing arithmetic on it. This bug raises an interesting general problem with GDB's DWARF expression evaluator, which is this: We currently assume that the DWARF expressions being evaluated are well formed, and well behaving. As an example, this is the expression that the bug was running into problems on, this was used as the expression for a DW_AT_byte_stride of a DW_TAG_subrange_type: DW_OP_push_object_address; DW_OP_plus_uconst: 88; DW_OP_deref; DW_OP_push_object_address; DW_OP_plus_uconst: 32; DW_OP_deref; DW_OP_mul Two values are read from the inferior and multiplied together. GDB should not assume that any value read from the inferior is in any way sane, as such the implementation of DW_OP_mul should be guarding against overflow and doing something semi-sane here. However, it turns out that the original bug PR gdb/27059, is hitting a more specific case, which doesn't require changes to the DWARF expression evaluator, so I'm going to leave the above issue for another day. In the test mentioned in the bug GDB is actually trying to resolve the dynamic type of a Fortran array that is NOT allocated. A non-allocated Fortran array is one that does not have any data allocated for it yet, and even the upper and lower bounds of the array are not yet known. It turns out that, at least for gfortran compiled code, the data fields that describe the byte-stride are not initialised until the array is allocated. This leads me to the following conclusion: GDB should not try to resolve the bounds, or stride information for an array that is not allocated (or not associated, a similar, but slightly different Fortran feature). Instead, each of these properties should be set to undefined if the array is not allocated (or associated). That is what this commit does. There's a new flag that is passed around during the dynamic array resolution. When this flag is true the dynamic properties are resolved using the DWARF expressions as they currently are, but when this flag is false the expressions are not evaluated, and instead the properties are set to undefined. gdb/ChangeLog: PR gdb/27059 * eval.c (evaluate_subexp_for_sizeof): Handle not allocated and not associated arrays. * f-lang.c (fortran_adjust_dynamic_array_base_address_hack): Don't adjust arrays that are not allocated/associated. * gdbtypes.c (resolve_dynamic_range): Update header comment. Add new parameter which is used to sometimes set dynamic properties to undefined. (resolve_dynamic_array_or_string): Update header comment. Add new parameter which is used to guard evaluating dynamic properties. Resolve allocated/associated properties first. gdb/testsuite/ChangeLog: PR gdb/27059 * gdb.dwarf2/dyn-type-unallocated.c: New file. * gdb.dwarf2/dyn-type-unallocated.exp: New file.
Diffstat (limited to 'gdb/f-lang.c')
-rw-r--r--gdb/f-lang.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
index 28a66fd..e06bbb4 100644
--- a/gdb/f-lang.c
+++ b/gdb/f-lang.c
@@ -1391,6 +1391,10 @@ fortran_adjust_dynamic_array_base_address_hack (struct type *type,
{
gdb_assert (type->code () == TYPE_CODE_ARRAY);
+ /* We can't adjust the base address for arrays that have no content. */
+ if (type_not_allocated (type) || type_not_associated (type))
+ return address;
+
int ndimensions = calc_f77_array_dims (type);
LONGEST total_offset = 0;