[PATCH] Prune useless .debug_loc entries (PR debug/43442)
Jakub Jelinek
jakub@redhat.com
Mon Mar 22 17:51:00 GMT 2010
On Mon, Mar 22, 2010 at 02:27:08PM +0100, Jan Kratochvil wrote:
> Your patch keeps .debug_loc the same as the range 0x43..0x89 is used by
> .debug_ranges at least in some of its parts. But when I change it to:
>
> 00000160 000000000000003b 0000000000000043 (DW_OP_breg0: 0; DW_OP_lit30; DW_OP_mul; DW_OP_stack_value)
> 00000160 0000000000000043 0000000000000046 (DW_OP_breg13: 0; DW_OP_lit30; DW_OP_mul; DW_OP_stack_value)
> 00000160 0000000000000049 0000000000000089 (DW_OP_breg13: 0; DW_OP_lit30; DW_OP_mul; DW_OP_stack_value)
> 00000160 <End of list>
>
> to reduce it just to the valid ranges of .debug_ranges I get a debugging
> regression:
>
> 12 int d1 = j (x) * 40;
> (gdb) set can-use-hw-watchpoints 0
> (gdb) watch c1
> Watchpoint 2: c1
> (gdb) stepi
> 19 g (a, b, c, d);
> (gdb) info watchpoints
> Num Type Disp Enb Address What
> 1 breakpoint keep y 0x00000000004004c4 in f at frag.c:12
> breakpoint already hit 1 time
> 2 watchpoint keep y c1
> (gdb) info locals
> c = 30
> d = 40
> (gdb) stepi
> 17 h ();
> (gdb) _
>
> a regression to:
If gdb doesn't consider variable to die when it goes out of scope
and still relies on .debug_loc as its location when it is not in scope,
that would be quite unfortunate. Either gdb could/should mask
.debug_loc ranges with containing DW_AT_ranges to get places where
the variable is really considered to be live (i.e. when it would get
out of scope temporarily, it would be considered <not in scope> resp.
<optimized out>, when returning back, it would be known again).
Or I have following incremental patch, which means all the whole
patch does (in addition to sorting .debug_ranges entries) is
drop completely .debug_loc ranges that don't overlap with DW_AT_ranges,
but not merge any ranges.
To show better what I mean, consider variable live in DW_AT_ranges
10..20 30..40 50..60
With vanilla trunk, one would get location list
12..22 reg1
23..25 reg2
25..28 reg3
28..35 reg1
48..65 reg2
68..95 reg4 - 16
With the patch I've posted earlier, we'd have
12..35 reg1
48..65 reg2
location list. While var doesn't live in reg1 from 22 to 28,
as it is not in scope in that case, we would keep compact location list.
With the following incremental patch we'd get:
12..22 reg1
28..35 reg1
48..65 reg2
(i.e. gcc wouldn't claim the var is live in reg1 between 22 and 28, but
wouldn't tell the debugger that when it stops being available in reg1,
it might look at reg2 resp. reg3 afterwards, when those ranges never overlap
with the var block's DW_AT_ranges).
My preference would be that gdb would be happy even with the more compact
ranges (as can be seen in the following data, it is still considerably
smaller), but even if just the incremental patch would be what gdb would be
happy about we'd still save on .debug_loc size.
Always first cc1plus is one with in_scope_var_loc_node always returning node immediately,
the second is unmodified patch I've posted earlier today, third is with the following
incremental patch:
filesize: 65568300
[28] .debug_info PROGBITS 00000000 1002ada 139b6cd 00 0 0 1
[33] .debug_loc PROGBITS 00000000 2905694 f6b1b1 00 0 0 1
[35] .debug_ranges PROGBITS 00000000 39d3741 3c1400 00 0 0 1
filesize: 59548797
[28] .debug_info PROGBITS 00000000 1002ada 1397d82 00 0 0 1
[33] .debug_loc PROGBITS 00000000 2901ed0 9b0f44 00 0 0 1
[35] .debug_ranges PROGBITS 00000000 3415d10 3c1438 00 0 0 1
filesize: 61354047
[28] .debug_info PROGBITS 00000000 1002ada 1397ab8 00 0 0 1
[33] .debug_loc PROGBITS 00000000 2901b96 b69f17 00 0 0 1
[35] .debug_ranges PROGBITS 00000000 35ce9a9 3c12f0 00 0 0 1
filesize: 86921679
[28] .debug_info PROGBITS 0000000000000000 10eb517 149eab7 00 0 0 1
[32] .debug_loc PROGBITS 0000000000000000 2a6ace7 1e300ab 00 0 0 1
[34] .debug_ranges PROGBITS 0000000000000000 49fcab8 7b8020 00 0 0 1
filesize: 75274552
[28] .debug_info PROGBITS 0000000000000000 10eb517 149af57 00 0 0 1
[32] .debug_loc PROGBITS 0000000000000000 2a672c4 1318257 00 0 0 1
[34] .debug_ranges PROGBITS 0000000000000000 3ee1241 7b7fa0 00 0 0 1
filesize: 78526419
[28] .debug_info PROGBITS 0000000000000000 10eb517 149aec3 00 0 0 1
[32] .debug_loc PROGBITS 0000000000000000 2a67268 163214f 00 0 0 1
[34] .debug_ranges PROGBITS 0000000000000000 41fb0dd 7b7f90 00 0 0 1
--- gcc/dwarf2out.c 2010-03-22 18:02:51.909630679 +0100
+++ gcc/dwarf2out.c 2010-03-22 17:09:55.000000000 +0100
@@ -14137,7 +14137,7 @@ dw_loc_list (var_loc_list *loc_list, tre
const char *endname, *secname;
rtx varloc;
enum var_init_status initialized;
- struct var_loc_node *node, *next;
+ struct var_loc_node *node;
dw_loc_descr_ref descr;
char label_id[MAX_ARTIFICIAL_LABEL_BYTES];
dw_loc_list_ref list = NULL;
@@ -14158,22 +14158,9 @@ dw_loc_list (var_loc_list *loc_list, tre
secname = secname_for_decl (decl);
for (node = in_scope_var_loc_node (loc_list->first, &block);
- node; node = next)
+ node;
+ node = in_scope_var_loc_node (node->next, &block))
{
- next = node;
- while ((next = in_scope_var_loc_node (next->next, &block)) != NULL)
- {
- rtx loc1 = NOTE_VAR_LOCATION_LOC (node->var_loc_note);
- rtx loc2 = NOTE_VAR_LOCATION_LOC (next->var_loc_note);
- if (!rtx_equal_p (loc1, loc2)
- || (NOTE_VAR_LOCATION_STATUS (node->var_loc_note)
- != NOTE_VAR_LOCATION_STATUS (next->var_loc_note)
- && ((NOTE_VAR_LOCATION_STATUS (node->var_loc_note)
- == VAR_INIT_STATUS_UNINITIALIZED)
- || (NOTE_VAR_LOCATION_STATUS (next->var_loc_note)
- == VAR_INIT_STATUS_UNINITIALIZED))))
- break;
- }
if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
{
/* The variable has a location between NODE->LABEL and
@@ -14183,8 +14170,8 @@ dw_loc_list (var_loc_list *loc_list, tre
descr = dw_loc_list_1 (decl, varloc, want_address, initialized);
if (descr)
{
- if (next)
- endname = next->label;
+ if (node->next)
+ endname = node->next->label;
else if (!current_function_decl)
endname = text_end_label;
else
Jakub
More information about the Gcc-patches
mailing list