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 + -
显示快捷键?