X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gas%2Fdwarf2dbg.c;h=40a44355423c10b10df0a43d8a6f037fa6941e2f;hb=57d87c09a33acdce280f4c9ae4f55b885a5cee99;hp=2d316ddcb9ca18da799302d28ca2c42f36dce80d;hpb=204f543cae7a5dc908264b49d558191d0ceb989c;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/dwarf2dbg.c b/gas/dwarf2dbg.c index 2d316ddcb9..40a4435542 100644 --- a/gas/dwarf2dbg.c +++ b/gas/dwarf2dbg.c @@ -1,5 +1,5 @@ /* dwarf2dbg.c - DWARF2 debug support - Copyright (C) 1999-2019 Free Software Foundation, Inc. + Copyright (C) 1999-2020 Free Software Foundation, Inc. Contributed by David Mosberger-Tang This file is part of GAS, the GNU Assembler. @@ -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; @@ -641,7 +657,7 @@ dwarf2_emit_label (symbolS *label) return; if (S_GET_SEGMENT (label) != now_seg) return; - if (!(bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE)) + if (!(bfd_section_flags (now_seg) & SEC_CODE)) return; if (files_in_use == 0 && debug_type != DEBUG_DWARF2) return; @@ -735,12 +751,18 @@ get_filenum (const char *filename, unsigned int num) unsigned int old = files_allocated; files_allocated = i + 32; - files = XRESIZEVEC (struct file_entry, files, files_allocated); + /* Catch wraparound. */ + if (files_allocated <= old) + { + as_bad (_("file number %lu is too big"), (unsigned long) i); + return 0; + } + files = XRESIZEVEC (struct file_entry, files, files_allocated); memset (files + old, 0, (i + 32 - old) * sizeof (struct file_entry)); } - files[i].filename = num ? file : xstrdup (file); + files[i].filename = file; files[i].dir = dir; if (files_in_use < i + 1) files_in_use = i + 1; @@ -759,7 +781,7 @@ get_filenum (const char *filename, unsigned int num) char * dwarf2_directive_filename (void) { - offsetT num; + valueT num; char *filename; int filename_len; @@ -777,7 +799,7 @@ dwarf2_directive_filename (void) return NULL; demand_empty_rest_of_line (); - if (num < 1) + if ((offsetT) num < 1) { as_bad (_("file number less than one")); return NULL; @@ -787,13 +809,19 @@ dwarf2_directive_filename (void) being supplied. Turn off gas generated debug info. */ debug_type = DEBUG_NONE; - if (num < (int) files_in_use && files[num].filename != 0) + if (num != (unsigned int) num + || num >= (size_t) -1 / sizeof (struct file_entry) - 32) { - as_bad (_("file number %ld already allocated"), (long) num); + as_bad (_("file number %lu is too big"), (unsigned long) num); + return NULL; + } + if (num < files_in_use && files[num].filename != 0) + { + as_bad (_("file number %u already allocated"), (unsigned int) num); return NULL; } - get_filenum (filename, num); + get_filenum (filename, (unsigned int) num); return filename; } @@ -1108,28 +1136,16 @@ 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); - /* 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 */ + out_opcode (DW_LNE_set_address); exp.X_op = O_symbol; exp.X_add_symbol = sym; exp.X_add_number = 0; @@ -1145,10 +1161,10 @@ scale_addr_delta (addressT *addr_delta) if (DWARF2_LINE_MIN_INSN_LENGTH > 1) { if (*addr_delta % DWARF2_LINE_MIN_INSN_LENGTH != 0 && !printed_this) - { + { as_bad("unaligned opcodes detected in executable segment"); - printed_this = 1; - } + printed_this = 1; + } *addr_delta /= DWARF2_LINE_MIN_INSN_LENGTH; } } @@ -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); @@ -1566,7 +1582,7 @@ process_entries (segT seg, struct line_entry *e) that all of the sub-sections are merged into a proper .debug_line section before a debugger sees them. */ - sec_name = bfd_get_section_name (stdoutput, seg); + sec_name = bfd_section_name (seg); if (strcmp (sec_name, ".text") != 0) { name = concat (".debug_line", sec_name, (char *) NULL); @@ -1723,10 +1739,10 @@ out_file_list (void) out_uleb128 (files[i].dir); /* directory number */ /* Output the last modification timestamp. */ out_uleb128 (DWARF2_FILE_TIME_NAME (files[i].filename, - files[i].dir ? dirs [files [i].dir] : "")); + files[i].dir ? dirs [files [i].dir] : "")); /* Output the filesize. */ out_uleb128 (DWARF2_FILE_SIZE_NAME (files[i].filename, - files[i].dir ? dirs [files [i].dir] : "")); + files[i].dir ? dirs [files [i].dir] : "")); } /* Terminate filename list. */ @@ -1799,7 +1815,6 @@ 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); @@ -1816,7 +1831,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_octets (prologue_start); + symbol_set_value_now (prologue_start); /* Parameters of the state machine. */ out_byte (DWARF2_LINE_MIN_INSN_LENGTH); @@ -1841,7 +1856,7 @@ out_debug_line (segT line_seg) out_file_list (); - symbol_set_value_now_octets (prologue_end); + symbol_set_value_now (prologue_end); /* For each section, emit a statement program. */ for (s = all_segs; s; s = s->next) @@ -1861,17 +1876,7 @@ out_debug_line (segT line_seg) in the DWARF Line Number header. */ subseg_set (subseg_get (".debug_line_end", FALSE), 0); - /* 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); + symbol_set_value_now (line_end); } static void @@ -1990,7 +1995,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_octets (aranges_end); + symbol_set_value_now (aranges_end); } /* Emit data for .debug_abbrev. Note that this must be kept in @@ -2105,7 +2110,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_octets (info_end); + symbol_set_value_now (info_end); } /* Emit the three debug strings needed in .debug_str and setup symbols @@ -2166,6 +2171,17 @@ void dwarf2_init (void) { last_seg_ptr = &all_segs; + + /* Select the default CIE version to produce here. The global + starts with a value of -1 and will be modified to a valid value + either by the user providing a command line option, or some + targets will select their own default in md_after_parse_args. If + we get here and the global still contains -1 then it is up to us + to pick a sane default. The default we choose is 1, this is the + CIE version gas has produced for a long time, and there seems no + reason to change it yet. */ + if (flag_dwarf_cie_version == -1) + flag_dwarf_cie_version = 1; } @@ -2210,7 +2226,7 @@ dwarf2_finish (void) /* Create and switch to the line number section. */ line_seg = subseg_new (".debug_line", 0); - bfd_set_section_flags (stdoutput, line_seg, SEC_READONLY | SEC_DEBUGGING); + bfd_set_section_flags (line_seg, SEC_READONLY | SEC_DEBUGGING | SEC_OCTETS); /* For each subsection, chain the debug entries together. */ for (s = all_segs; s; s = s->next) @@ -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; } @@ -2245,15 +2272,15 @@ dwarf2_finish (void) aranges_seg = subseg_new (".debug_aranges", 0); str_seg = subseg_new (".debug_str", 0); - bfd_set_section_flags (stdoutput, info_seg, - SEC_READONLY | SEC_DEBUGGING); - bfd_set_section_flags (stdoutput, abbrev_seg, - SEC_READONLY | SEC_DEBUGGING); - bfd_set_section_flags (stdoutput, aranges_seg, - SEC_READONLY | SEC_DEBUGGING); - bfd_set_section_flags (stdoutput, str_seg, - (SEC_READONLY | SEC_DEBUGGING - | SEC_MERGE | SEC_STRINGS)); + bfd_set_section_flags (info_seg, + SEC_READONLY | SEC_DEBUGGING | SEC_OCTETS); + bfd_set_section_flags (abbrev_seg, + SEC_READONLY | SEC_DEBUGGING | SEC_OCTETS); + bfd_set_section_flags (aranges_seg, + SEC_READONLY | SEC_DEBUGGING | SEC_OCTETS); + bfd_set_section_flags (str_seg, + SEC_READONLY | SEC_DEBUGGING | SEC_OCTETS + | SEC_MERGE | SEC_STRINGS); str_seg->entsize = 1; record_alignment (aranges_seg, ffs (2 * sizeof_address) - 1); @@ -2263,8 +2290,8 @@ dwarf2_finish (void) else { ranges_seg = subseg_new (".debug_ranges", 0); - bfd_set_section_flags (stdoutput, ranges_seg, - SEC_READONLY | SEC_DEBUGGING); + bfd_set_section_flags (ranges_seg, + SEC_READONLY | SEC_DEBUGGING | SEC_OCTETS); record_alignment (ranges_seg, ffs (2 * sizeof_address) - 1); out_debug_ranges (ranges_seg); }