dwarf2dbg.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 1,313 行 · 第 1/3 页
C
1,313 行
/* dwarf2dbg.c - DWARF2 debug support Copyright 1999, 2000, 2001 Free Software Foundation, Inc. Contributed by David Mosberger-Tang <davidm@hpl.hp.com> This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* Logical line numbers can be controlled by the compiler via the following two directives: .file FILENO "file.c" .loc FILENO LINENO [COLUMN] FILENO is the filenumber. */#include "ansidecl.h"#include "as.h"#ifdef HAVE_LIMITS_H#include <limits.h>#else#ifdef HAVE_SYS_PARAM_H#include <sys/param.h>#endif#ifndef INT_MAX#define INT_MAX (int) (((unsigned) (-1)) >> 1)#endif#endif#ifdef BFD_ASSEMBLER#include "dwarf2dbg.h"#include "subsegs.h"#include "elf/dwarf2.h"/* Since we can't generate the prolog until the body is complete, we use three different subsegments for .debug_line: one holding the prolog, one for the directory and filename info, and one for the body ("statement program"). */#define DL_PROLOG 0#define DL_FILES 1#define DL_BODY 2/* First special line opcde - leave room for the standard opcodes. Note: If you want to change this, you'll have to update the "standard_opcode_lengths" table that is emitted below in dwarf2_finish(). */#define DWARF2_LINE_OPCODE_BASE 10#ifndef DWARF2_LINE_BASE /* Minimum line offset in a special line info. opcode. This value was chosen to give a reasonable range of values. */# define DWARF2_LINE_BASE -5#endif/* Range of line offsets in a special line info. opcode. */#ifndef DWARF2_LINE_RANGE# define DWARF2_LINE_RANGE 14#endif#ifndef DWARF2_LINE_MIN_INSN_LENGTH /* Define the architecture-dependent minimum instruction length (in bytes). This value should be rather too small than too big. */# define DWARF2_LINE_MIN_INSN_LENGTH 1#endif/* Flag that indicates the initial value of the is_stmt_start flag. In the present implementation, we do not mark any lines as the beginning of a source statement, because that information is not made available by the GCC front-end. */#define DWARF2_LINE_DEFAULT_IS_STMT 1/* Given a special op, return the line skip amount. */#define SPECIAL_LINE(op) \ (((op) - DWARF2_LINE_OPCODE_BASE)%DWARF2_LINE_RANGE + DWARF2_LINE_BASE)/* Given a special op, return the address skip amount (in units of DWARF2_LINE_MIN_INSN_LENGTH. */#define SPECIAL_ADDR(op) (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE)/* The maximum address skip amount that can be encoded with a special op. */#define MAX_SPECIAL_ADDR_DELTA SPECIAL_ADDR(255)struct line_entry { struct line_entry *next; fragS *frag; addressT frag_ofs; struct dwarf2_line_info loc;};struct line_subseg { struct line_subseg *next; subsegT subseg; struct line_entry *head; struct line_entry **ptail;};struct line_seg { struct line_seg *next; segT seg; struct line_subseg *head; symbolS *text_start; symbolS *text_end;};/* Collects data for all line table entries during assembly. */static struct line_seg *all_segs;struct file_entry { char *filename; unsigned int dir;};/* Table of files used by .debug_line. */static struct file_entry *files;static unsigned int files_in_use;static unsigned int files_allocated;/* True when we've seen a .loc directive recently. Used to avoid doing work when there's nothing to do. */static boolean loc_directive_seen;/* Current location as indicated by the most recent .loc directive. */static struct dwarf2_line_info current;/* Fake label name. */static char const fake_label_name[] = ".L0\001";/* The size of an address on the target. */static unsigned int sizeof_address;static struct line_subseg *get_line_subseg PARAMS ((segT, subsegT));static unsigned int get_filenum PARAMS ((const char *));static struct frag *first_frag_for_seg PARAMS ((segT));static struct frag *last_frag_for_seg PARAMS ((segT));static void out_byte PARAMS ((int));static void out_opcode PARAMS ((int));static void out_two PARAMS ((int));static void out_four PARAMS ((int));static void out_abbrev PARAMS ((int, int));static void out_uleb128 PARAMS ((addressT));static symbolS *symbol_new_now PARAMS ((void));static void set_symbol_value_now PARAMS ((symbolS *));static offsetT get_frag_fix PARAMS ((fragS *));static void out_set_addr PARAMS ((segT, fragS *, addressT));static int size_inc_line_addr PARAMS ((int, addressT));static void emit_inc_line_addr PARAMS ((int, addressT, char *, int));static void out_inc_line_addr PARAMS ((int, addressT));static void relax_inc_line_addr PARAMS ((int, segT, fragS *, addressT, fragS *, addressT));static void process_entries PARAMS ((segT, struct line_entry *));static void out_file_list PARAMS ((void));static void out_debug_line PARAMS ((segT));static void out_debug_aranges PARAMS ((segT, segT));static void out_debug_abbrev PARAMS ((segT));static void out_debug_info PARAMS ((segT, segT, segT));/* Find or create an entry for SEG+SUBSEG in ALL_SEGS. */static struct line_subseg *get_line_subseg (seg, subseg) segT seg; subsegT subseg;{ static segT last_seg; static subsegT last_subseg; static struct line_subseg *last_line_subseg; struct line_seg *s; struct line_subseg **pss, *ss; if (seg == last_seg && subseg == last_subseg) return last_line_subseg; for (s = all_segs; s; s = s->next) if (s->seg == seg) goto found_seg; s = (struct line_seg *) xmalloc (sizeof (*s)); s->next = all_segs; s->seg = seg; s->head = NULL; all_segs = s; found_seg: for (pss = &s->head; (ss = *pss) != NULL ; pss = &ss->next) { if (ss->subseg == subseg) goto found_subseg; if (ss->subseg > subseg) break; } ss = (struct line_subseg *) xmalloc (sizeof (*ss)); ss->next = *pss; ss->subseg = subseg; ss->head = NULL; ss->ptail = &ss->head; *pss = ss; found_subseg: last_seg = seg; last_subseg = subseg; last_line_subseg = ss; return ss;}/* Record an entry for LOC ocurring at OFS within the current fragment. */voiddwarf2_gen_line_info (ofs, loc) addressT ofs; struct dwarf2_line_info *loc;{ struct line_subseg *ss; struct line_entry *e; /* Early out for as-yet incomplete location information. */ if (loc->filenum == 0 || loc->line == 0) return; e = (struct line_entry *) xmalloc (sizeof (*e)); e->next = NULL; e->frag = frag_now; e->frag_ofs = ofs; e->loc = *loc; ss = get_line_subseg (now_seg, now_subseg); *ss->ptail = e; ss->ptail = &e->next;}voiddwarf2_where (line) struct dwarf2_line_info *line;{ if (debug_type == DEBUG_DWARF2) { char *filename; as_where (&filename, &line->line); line->filenum = get_filenum (filename); line->column = 0; line->flags = DWARF2_FLAG_BEGIN_STMT; } else *line = current;}/* Called for each machine instruction, or relatively atomic group of machine instructions (ie built-in macro). The instruction or group is SIZE bytes in length. If dwarf2 line number generation is called for, emit a line statement appropriately. */voiddwarf2_emit_insn (size) int size;{ struct dwarf2_line_info loc; if (debug_type != DEBUG_DWARF2 && ! loc_directive_seen) return; loc_directive_seen = false; dwarf2_where (&loc); dwarf2_gen_line_info (frag_now_fix () - size, &loc);}/* Get a .debug_line file number for FILENAME. */static unsigned intget_filenum (filename) const char *filename;{ static unsigned int last_used; unsigned int i; if (last_used) if (strcmp (filename, files[last_used].filename) == 0) return last_used; for (i = 1; i < files_in_use; ++i) if (strcmp (filename, files[i].filename) == 0) return i; if (i >= files_allocated) { unsigned int old = files_allocated; files_allocated = i + 32; files = (struct file_entry *) xrealloc (files, (i + 32) * sizeof (struct file_entry)); memset (files + old, 0, (i + 32 - old) * sizeof (struct file_entry)); } files[i].filename = xstrdup (filename); files[i].dir = 0; files_in_use = i + 1; last_used = i; return i;}/* Handle the .file directive. */voiddwarf2_directive_file (dummy) int dummy ATTRIBUTE_UNUSED;{ offsetT num; char *filename; int filename_len; /* Continue to accept a bare string and pass it off. */ SKIP_WHITESPACE (); if (*input_line_pointer == '"') { s_app_file (0); return; } num = get_absolute_expression (); filename = demand_copy_C_string (&filename_len); demand_empty_rest_of_line (); if (num < 1) { as_bad (_("File number less than one")); return; } if (num < files_in_use && files[num].filename != 0) { as_bad (_("File number %ld already allocated"), (long) num); return; } if (num >= (int) files_allocated) { unsigned int old = files_allocated; files_allocated = num + 16; files = (struct file_entry *) xrealloc (files, (num + 16) * sizeof (struct file_entry)); /* Zero the new memory. */ memset (files + old, 0, (num + 16 - old) * sizeof (struct file_entry)); } files[num].filename = filename; files[num].dir = 0; files_in_use = num + 1;}voiddwarf2_directive_loc (dummy) int dummy ATTRIBUTE_UNUSED;{ offsetT filenum, line, column; filenum = get_absolute_expression (); SKIP_WHITESPACE (); line = get_absolute_expression (); SKIP_WHITESPACE (); column = get_absolute_expression (); demand_empty_rest_of_line (); if (filenum < 1) { as_bad (_("File number less than one")); return; } if (filenum >= (int) files_in_use || files[filenum].filename == 0) { as_bad (_("Unassigned file number %ld"), (long) filenum); return; } current.filenum = filenum; current.line = line; current.column = column; current.flags = DWARF2_FLAG_BEGIN_STMT; loc_directive_seen = true;#ifndef NO_LISTING if (listing) listing_source_line (line);#endif}static struct frag *first_frag_for_seg (seg) segT seg;{ frchainS *f, *first = NULL; for (f = frchain_root; f; f = f->frch_next) if (f->frch_seg == seg && (! first || first->frch_subseg > f->frch_subseg)) first = f; return first ? first->frch_root : NULL;}static struct frag *last_frag_for_seg (seg) segT seg;{ frchainS *f, *last = NULL; for (f = frchain_root; f; f = f->frch_next) if (f->frch_seg == seg && (! last || last->frch_subseg < f->frch_subseg)) last= f; return last ? last->frch_last : NULL;}/* Emit a single byte into the current segment. */static inline void
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?