What should a runtime DW_AT_lower_bound be reported as?
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 30/100
Research direction
Start with the two alternatives in the issue: dwarf_subrange_bounds() in dwarf/src/dwarf_subrange.cpp and the parseSubrange() fallback in symtabAPI/src/dwarfWalker.C. Read the linked regression-test context and reproduce the runtime-bound cases under test_binaries/symtabAPI/DWARF/subrange_bounds. Done means the project decides how runtime lower bounds—and the related DW_AT_count cases—are represented without reporting a misleading value; this issue is design work, not a scoped implementation task.
Written by the indexing model from the issue text.
Description
Summary
When a subrange's DW_AT_lower_bound is a runtime value (a DWARF expression or a reference to a DIE, not a constant), it isn't clear what typeSubrange/typeArray should report as the lower bound. This issue is to decide that.
On master this doesn't show up yet, because any non-constant bound makes dwarf_subrange_bounds() return an error and the whole array type is dropped. Once the non-constant forms are parsed (#2418, and a follow-up that also covers the ref* forms and DW_AT_count), the question is live. Both of those currently give a runtime lower bound the language default (1 for Fortran), the same as a missing attribute.
Why the default is questionable
DWARF 5 §5.13 applies the language default only when DW_AT_lower_bound is absent. A present-but-runtime lower bound is a real value that just can't be evaluated statically. Reporting the default gives a wrong value that looks like a known one:
subroutine explicit_dyn(y, lo, hi)
integer :: lo, hi
real :: y(lo:hi) ! DW_AT_lower_bound: ref4 -> artificial DW_TAG_variable
end subroutine
program p
real, allocatable :: z(:)
allocate(z(-2:5)) ! DW_AT_lower_bound: exprloc (DW_OP_push_object_address; DW_OP_plus_uconst 48; DW_OP_deref)
call explicit_dyn(z, -2, 5)
end program
With gfortran -g -O0 (gcc 15.2), both y and z would be reported with lower bound 1; the actual lower bound is -2.
When gfortran knows the lower bound is 1 (e.g. assumed-shape x(:)), it leaves DW_AT_lower_bound out, so the default is correct there.
Options
- Keep the language default. No change from #2418. The value is wrong for allocatables and explicit-shape dummies.
- Report it as unknown, with
LONG_MINas the lower bound, matchingparseSubrange()'s existinglower_bound.value_or(LONG_MIN)and theLONG_MAXused for an unknown upper bound. The only change needed is to apply the default only when!dwarf_hasattr_integrate(die, DW_AT_lower_bound), in bothdwarf_subrange_bounds()and theparseSubrange()fallback. Caveats:- the bounds are stored as
unsigned long; typeArray::updateSize()computeshi_ - low_ + 1, which wraps to 0 for[LONG_MIN:LONG_MAX];BPatch_type::getLow()users would seeLONG_MINwhere they used to see a small number.
- the bounds are stored as
- Keep the runtime description. Store the location expression or referenced DIE (e.g. as a
VariableLocationlist, the way variables are handled) so a consumer with a live process can evaluate it. This is the most complete option but needs an API addition ontypeSubrange/typeArray.
The same question applies to a runtime DW_AT_count with a constant lower bound, and to a constant DW_AT_count counted from a runtime lower bound. Both currently end up as an unknown upper bound (LONG_MAX).
Reproducers
Test binaries covering the exprloc, block1 and ref4 forms of DW_AT_lower_bound, DW_AT_upper_bound and DW_AT_count (gcc/clang C99 VLAs, gfortran assumed-shape/allocatable/explicit-shape), with sources, are being added to test_binaries/symtabAPI/DWARF/subrange_bounds. The accompanying regression test deliberately doesn't check runtime lower bounds until this is settled.
- Dominant language
- C
- Stars
- 836
- Forks
- 177
- Avg merge
- 3d 20h
- Merged PRs (30d)
- 61
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from dyninst/dyninst
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 1 day
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Maintainers usually reply within 1 day
-
SPIDevice selects an active-high device as soon as it is createdPossibly taken @mikeysklar claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 73/100
adafruit/circuitpython#11869 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 78/100
gnif/LookingGlass#1352 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
kovidgoyal/kitty#10862 ·
Maintainers usually reply within 1 day