X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fdwarf2dbg.c;h=b77751d8af3d922a7648d4525a775e26727644f5;hb=a6d0f2490c0c7969eb60038f01c0ee0f46e4d5fd;hp=e42c561927fb3642ce00aec22cd00077bca8c251;hpb=031e33500e82fb8ef525595ea684473774dfc669;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/dwarf2dbg.c b/gas/dwarf2dbg.c index e42c561927..b77751d8af 100644 --- a/gas/dwarf2dbg.c +++ b/gas/dwarf2dbg.c @@ -1,5 +1,5 @@ /* dwarf2dbg.c - DWARF2 debug support - Copyright (C) 1999-2018 Free Software Foundation, Inc. + Copyright (C) 1999-2019 Free Software Foundation, Inc. Contributed by David Mosberger-Tang This file is part of GAS, the GNU Assembler. @@ -97,9 +97,9 @@ #define DWARF2_ARANGES_VERSION 2 #endif -/* This implementation output version 2 .debug_line information. */ +/* This implementation outputs version 3 .debug_line information. */ #ifndef DWARF2_LINE_VERSION -#define DWARF2_LINE_VERSION 2 +#define DWARF2_LINE_VERSION 3 #endif #include "subsegs.h" @@ -426,7 +426,7 @@ set_or_check_view (struct line_entry *e, struct line_entry *p, if (!S_IS_DEFINED (e->loc.view)) { symbol_set_value_expression (e->loc.view, &viewx); - S_SET_SEGMENT (e->loc.view, absolute_section); + S_SET_SEGMENT (e->loc.view, expr_section); symbol_set_frag (e->loc.view, &zero_address_frag); } @@ -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; @@ -579,7 +595,7 @@ dwarf2_emit_insn (int size) dwarf2_where (&loc); - dwarf2_gen_line_info (frag_now_fix () - size, &loc); + dwarf2_gen_line_info ((frag_now_fix_octets () - size) / OCTETS_PER_BYTE, &loc); dwarf2_consume_line_info (); } @@ -960,16 +976,19 @@ dwarf2_directive_loc (int dummy ATTRIBUTE_UNUSED) if (!name) return; sym = symbol_find_or_make (name); - if (S_IS_DEFINED (sym)) + if (S_IS_DEFINED (sym) || symbol_equated_p (sym)) { - if (!S_CAN_BE_REDEFINED (sym)) - as_bad (_("symbol `%s' is already defined"), name); - else + if (S_IS_VOLATILE (sym)) sym = symbol_clone (sym, 1); - S_SET_SEGMENT (sym, undefined_section); - S_SET_VALUE (sym, 0); - symbol_set_frag (sym, &zero_address_frag); + else if (!S_CAN_BE_REDEFINED (sym)) + { + as_bad (_("symbol `%s' is already defined"), name); + return; + } } + S_SET_SEGMENT (sym, undefined_section); + S_SET_VALUE (sym, 0); + symbol_set_frag (sym, &zero_address_frag); } current.view = sym; } @@ -1105,16 +1124,28 @@ get_frag_fix (fragS *frag, segT seg) /* Set an absolute address (may result in a relocation entry). */ +static void +out_inc_line_addr (int line_delta, addressT addr_delta); + static void out_set_addr (symbolS *sym) { expressionS exp; + addressT expr_addr, expr_addr_aligned; memset (&exp, 0, sizeof exp); - out_opcode (DW_LNS_extended_op); - out_uleb128 (sizeof_address + 1); - out_opcode (DW_LNE_set_address); + /* The expression at the bottom must be aligned to OCTETS_PER_BYTE. The + statements after the for loop will contribute 3 more octets. */ + expr_addr = frag_now_fix_octets () + 3; + expr_addr_aligned = (expr_addr + OCTETS_PER_BYTE - 1) & -OCTETS_PER_BYTE; + for ( ; expr_addr != expr_addr_aligned; expr_addr++) + out_inc_line_addr (0, 0); /* NOP */ + + out_opcode (DW_LNS_extended_op); /* 1 octet */ + out_uleb128 (sizeof_address + 1); /* 1 octet */ + + out_opcode (DW_LNE_set_address); /* 1 octet */ exp.X_op = O_symbol; exp.X_add_symbol = sym; exp.X_add_number = 0; @@ -1161,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; } @@ -1225,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); @@ -1742,7 +1773,7 @@ out_header (asection *sec, expressionS *exp) } else { - start_sym = symbol_temp_new_now (); + start_sym = symbol_temp_new_now_octets (); end_sym = symbol_temp_make (); } @@ -1784,6 +1815,7 @@ out_debug_line (segT line_seg) symbolS *line_end; struct line_seg *s; int sizeof_offset; + addressT section_end, section_end_aligned; memset (&exp, 0, sizeof exp); sizeof_offset = out_header (line_seg, &exp); @@ -1800,7 +1832,7 @@ out_debug_line (segT line_seg) exp.X_op_symbol = prologue_start; exp.X_add_number = 0; emit_expr (&exp, sizeof_offset); - symbol_set_value_now (prologue_start); + symbol_set_value_now_octets (prologue_start); /* Parameters of the state machine. */ out_byte (DWARF2_LINE_MIN_INSN_LENGTH); @@ -1825,7 +1857,7 @@ out_debug_line (segT line_seg) out_file_list (); - symbol_set_value_now (prologue_end); + symbol_set_value_now_octets (prologue_end); /* For each section, emit a statement program. */ for (s = all_segs; s; s = s->next) @@ -1845,7 +1877,17 @@ out_debug_line (segT line_seg) in the DWARF Line Number header. */ subseg_set (subseg_get (".debug_line_end", FALSE), 0); - symbol_set_value_now (line_end); + /* Pad size of .debug_line section to a multiple of OCTETS_PER_BYTE. + Simply sizing the section in md_section_align() is not sufficient, + also the size field in the .debug_line header must be a multiple + of OCTETS_PER_BYTE. Not doing so will introduce gaps within the + .debug_line sections after linking. */ + section_end = frag_now_fix_octets (); + section_end_aligned = (section_end + OCTETS_PER_BYTE - 1) & -OCTETS_PER_BYTE; + for ( ; section_end != section_end_aligned; section_end++) + out_inc_line_addr (0, 0); /* NOP */ + + symbol_set_value_now_octets (line_end); } static void @@ -1964,7 +2006,7 @@ out_debug_aranges (segT aranges_seg, segT info_seg) md_number_to_chars (p, 0, addr_size); md_number_to_chars (p + addr_size, 0, addr_size); - symbol_set_value_now (aranges_end); + symbol_set_value_now_octets (aranges_end); } /* Emit data for .debug_abbrev. Note that this must be kept in @@ -2079,7 +2121,7 @@ out_debug_info (segT info_seg, segT abbrev_seg, segT line_seg, segT ranges_seg, dwarf2 draft has no standard code for assembler. */ out_two (DW_LANG_Mips_Assembler); - symbol_set_value_now (info_end); + symbol_set_value_now_octets (info_end); } /* Emit the three debug strings needed in .debug_str and setup symbols @@ -2100,7 +2142,7 @@ out_debug_str (segT str_seg, symbolS **name_sym, symbolS **comp_dir_sym, on the command line, so assume files[1] is the main input file. We're not supposed to get called unless at least one line number entry was emitted, so this should always be defined. */ - *name_sym = symbol_temp_new_now (); + *name_sym = symbol_temp_new_now_octets (); if (files_in_use == 0) abort (); if (files[1].dir) @@ -2122,14 +2164,14 @@ out_debug_str (segT str_seg, symbolS **name_sym, symbolS **comp_dir_sym, memcpy (p, files[1].filename, len); /* DW_AT_comp_dir */ - *comp_dir_sym = symbol_temp_new_now (); + *comp_dir_sym = symbol_temp_new_now_octets (); comp_dir = remap_debug_filename (getpwd ()); len = strlen (comp_dir) + 1; p = frag_more (len); memcpy (p, comp_dir, len); /* DW_AT_producer */ - *producer_sym = symbol_temp_new_now (); + *producer_sym = symbol_temp_new_now_octets (); sprintf (producer, "GNU AS %s", VERSION); len = strlen (producer) + 1; p = frag_more (len); @@ -2192,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; }