From 62e6b7b3b3c6f2fffe9f5863ddebf430533b79f0 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Sun, 5 May 2019 23:07:20 -0300 Subject: [LVu] base subseg head view on prev subseg's tail Location views at borders between subsegments/subsections in the same segment/section are computed as if each new subsegment/subsection started with a forced view reset to zero, but the line number program does not introduce resets that are not explicitly requested, so if a subsegment ends at the same address another starts, the line number program will have a continuity of views at the border address, whereas the initial view number label in the latter subsegment will be miscomputed as zero. This patch delays the assignment of view expressions at subsegment heads to the time of chaining the frags of subsegments into a single segment, so that they are set based on the view at the end of the previous subsegment in the same segment. The line number program created for the test program had an unnecessary DW_LNS_advance_pc at the end. This patch also arranges for us not to emit it. for gas/ChangeLog * dwarf2dbg.c (set_or_check_view): Skip heads when assigning views of prior locs. (dwarf2_gen_line_info_1): Skip heads. (size_inc_line_addr, emit_inc_line_addr): Drop DW_LNS_advance_pc for zero addr delta. (dwarf2_finish): Assign views for heads of segments. * testsuite/gas/elf/dwarf2-19.d: New. * testsuite/gas/elf/dwarf2-19.s: New. * testsuite/gas/elf/elf.exp: Test it. --- gas/dwarf2dbg.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) (limited to 'gas/dwarf2dbg.c') diff --git a/gas/dwarf2dbg.c b/gas/dwarf2dbg.c index 2d316dd..b77751d 100644 --- a/gas/dwarf2dbg.c +++ b/gas/dwarf2dbg.c @@ -442,7 +442,16 @@ set_or_check_view (struct line_entry *e, struct line_entry *p, gas_assert (r == p); /* Set or check views until we find a defined or absent view. */ do - set_or_check_view (r, r->next, NULL); + { + /* Do not define the head of a (sub?)segment view while + handling others. It would be defined too early, without + regard to the last view of other subsegments. + set_or_check_view will be called for every head segment + that needs it. */ + if (r == h) + break; + set_or_check_view (r, r->next, NULL); + } while (r->next && r->next->loc.view && !S_IS_DEFINED (r->next->loc.view) && (r = r->next)); @@ -454,6 +463,11 @@ set_or_check_view (struct line_entry *e, struct line_entry *p, simplify the view expressions, until we do so to P. */ do { + /* The head view of a subsegment may remain undefined while + handling other elements, before it is linked to the last + view of the previous subsegment. */ + if (r == h) + continue; gas_assert (S_IS_DEFINED (r->loc.view)); resolve_expression (symbol_get_value_expression (r->loc.view)); } @@ -480,9 +494,11 @@ dwarf2_gen_line_info_1 (symbolS *label, struct dwarf2_line_info *loc) lss = get_line_subseg (now_seg, now_subseg, TRUE); - if (loc->view) + /* Subseg heads are chained to previous subsegs in + dwarf2_finish. */ + if (loc->view && lss->head) set_or_check_view (e, - !lss->head ? NULL : (struct line_entry *)lss->ptail, + (struct line_entry *)lss->ptail, lss->head); *lss->ptail = e; @@ -1176,7 +1192,7 @@ size_inc_line_addr (int line_delta, addressT addr_delta) { if (addr_delta == MAX_SPECIAL_ADDR_DELTA) len = 1; - else + else if (addr_delta) len = 1 + sizeof_leb128 (addr_delta, 0); return len + 3; } @@ -1240,7 +1256,7 @@ emit_inc_line_addr (int line_delta, addressT addr_delta, char *p, int len) { if (addr_delta == MAX_SPECIAL_ADDR_DELTA) *p++ = DW_LNS_const_add_pc; - else + else if (addr_delta) { *p++ = DW_LNS_advance_pc; p += output_leb128 (p, addr_delta, 0); @@ -2218,8 +2234,19 @@ dwarf2_finish (void) struct line_subseg *lss = s->head; struct line_entry **ptail = lss->ptail; + /* Reset the initial view of the first subsection of the + section. */ + if (lss->head && lss->head->loc.view) + set_or_check_view (lss->head, NULL, NULL); + while ((lss = lss->next) != NULL) { + /* Link the first view of subsequent subsections to the + previous view. */ + if (lss->head && lss->head->loc.view) + set_or_check_view (lss->head, + !s->head ? NULL : (struct line_entry *)ptail, + s->head ? s->head->head : NULL); *ptail = lss->head; ptail = lss->ptail; } -- cgit v1.1