dwarf2.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 1,670 行 · 第 1/3 页

C
1,670
字号
    case DW_FORM_data4:      DW_UNSND (attr) = read_4_bytes (abfd, info_ptr);      info_ptr += 4;      break;    case DW_FORM_data8:      DW_UNSND (attr) = read_8_bytes (abfd, info_ptr);      info_ptr += 8;      break;    case DW_FORM_string:      DW_STRING (attr) = read_string (abfd, info_ptr, &bytes_read);      info_ptr += bytes_read;      break;    case DW_FORM_block:      blk = (struct dwarf_block *) bfd_alloc (abfd, sizeof (struct dwarf_block));      blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);      info_ptr += bytes_read;      blk->data = read_n_bytes (abfd, info_ptr, blk->size);      info_ptr += blk->size;      DW_BLOCK (attr) = blk;      break;    case DW_FORM_block1:      blk = (struct dwarf_block *) bfd_alloc (abfd, sizeof (struct dwarf_block));      blk->size = read_1_byte (abfd, info_ptr);      info_ptr += 1;      blk->data = read_n_bytes (abfd, info_ptr, blk->size);      info_ptr += blk->size;      DW_BLOCK (attr) = blk;      break;    case DW_FORM_data1:      DW_UNSND (attr) = read_1_byte (abfd, info_ptr);      info_ptr += 1;      break;    case DW_FORM_flag:      DW_UNSND (attr) = read_1_byte (abfd, info_ptr);      info_ptr += 1;      break;    case DW_FORM_sdata:      DW_SND (attr) = read_signed_leb128 (abfd, info_ptr, &bytes_read);      info_ptr += bytes_read;      break;    case DW_FORM_udata:      DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);      info_ptr += bytes_read;      break;    case DW_FORM_ref1:      DW_UNSND (attr) = read_1_byte (abfd, info_ptr);      info_ptr += 1;      break;    case DW_FORM_ref2:      DW_UNSND (attr) = read_2_bytes (abfd, info_ptr);      info_ptr += 2;      break;    case DW_FORM_ref4:      DW_UNSND (attr) = read_4_bytes (abfd, info_ptr);      info_ptr += 4;      break;    case DW_FORM_ref8:      DW_UNSND (attr) = read_8_bytes (abfd, info_ptr);      info_ptr += 8;      break;    case DW_FORM_ref_udata:      DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);      info_ptr += bytes_read;      break;    case DW_FORM_strp:    case DW_FORM_indirect:    default:      (*_bfd_error_handler) (_("Dwarf Error: Invalid or unhandled FORM value: %d."),			     abbrev->form);      bfd_set_error (bfd_error_bad_value);    }  return info_ptr;}/* Source line information table routines.  */#define FILE_ALLOC_CHUNK 5#define DIR_ALLOC_CHUNK 5struct line_info{  struct line_info* prev_line;  bfd_vma address;  char* filename;  unsigned int line;  unsigned int column;  int end_sequence;		/* End of (sequential) code sequence.  */};struct fileinfo{  char *name;  unsigned int dir;  unsigned int time;  unsigned int size;};struct line_info_table{  bfd* abfd;  unsigned int num_files;  unsigned int num_dirs;  char* comp_dir;  char** dirs;  struct fileinfo* files;  struct line_info* last_line;};static voidadd_line_info (table, address, filename, line, column, end_sequence)     struct line_info_table* table;     bfd_vma address;     char* filename;     unsigned int line;     unsigned int column;     int end_sequence;{  struct line_info* info = (struct line_info*)    bfd_alloc (table->abfd, sizeof (struct line_info));  info->prev_line = table->last_line;  table->last_line = info;  info->address = address;  info->filename = filename;  info->line = line;  info->column = column;  info->end_sequence = end_sequence;}static char *concat_filename (table, file)     struct line_info_table* table;     unsigned int file;{  char* filename;  if (file - 1 >= table->num_files)    {      (*_bfd_error_handler)	(_("Dwarf Error: mangled line number section (bad file number)."));      return "<unknown>";    }  filename = table->files[file - 1].name;  if (IS_ABSOLUTE_PATH(filename))    return filename;  else    {      char* dirname = (table->files[file - 1].dir		       ? table->dirs[table->files[file - 1].dir - 1]		       : table->comp_dir);      return (char*) concat (dirname, "/", filename, NULL);    }}static voidarange_add (unit, low_pc, high_pc)     struct comp_unit *unit;     bfd_vma low_pc;     bfd_vma high_pc;{  struct arange *arange;  /* First see if we can cheaply extend an existing range.  */  arange = &unit->arange;  do    {      if (low_pc == arange->high)	{	  arange->high = high_pc;	  return;	}      if (high_pc == arange->low)	{	  arange->low = low_pc;	  return;	}      arange = arange->next;    }  while (arange);  if (unit->arange.high == 0)    {      /* This is the first address range: store it in unit->arange.  */      unit->arange.next = 0;      unit->arange.low = low_pc;      unit->arange.high = high_pc;      return;    }  /* Need to allocate a new arange and insert it into the arange list.  */  arange = bfd_zalloc (unit->abfd, sizeof (*arange));  arange->low = low_pc;  arange->high = high_pc;  arange->next = unit->arange.next;  unit->arange.next = arange;}/* Decode the line number information for UNIT.  */static struct line_info_table*decode_line_info (unit, stash)     struct comp_unit *unit;     struct dwarf2_debug *stash;{  bfd *abfd = unit->abfd;  struct line_info_table* table;  char *line_ptr;  char *line_end;  struct line_head lh;  unsigned int i, bytes_read;  char *cur_file, *cur_dir;  unsigned char op_code, extended_op, adj_opcode;  if (! stash->dwarf_line_buffer)    {      asection *msec;      msec = bfd_get_section_by_name (abfd, ".debug_line");      if (! msec)	{	  (*_bfd_error_handler) (_("Dwarf Error: Can't find .debug_line section."));	  bfd_set_error (bfd_error_bad_value);	  return 0;	}      stash->dwarf_line_size = msec->_raw_size;      stash->dwarf_line_buffer = (char *) bfd_alloc (abfd, stash->dwarf_line_size);      if (! stash->dwarf_line_buffer)	return 0;      if (! bfd_get_section_contents (abfd, msec,				      stash->dwarf_line_buffer, 0,				      stash->dwarf_line_size))	return 0;      /* FIXME: We ought to apply the relocs against this section before	 we process it...  */    }  /* Since we are using un-relocated data, it is possible to get a bad value     for the line_offset.  Validate it here so that we won't get a segfault     below.  */  if (unit->line_offset >= stash->dwarf_line_size)    {      (*_bfd_error_handler) (_("Dwarf Error: Line offset (%u) greater than or equal to line size (%u)."),			     unit->line_offset, stash->dwarf_line_size);      bfd_set_error (bfd_error_bad_value);      return 0;    }  table = (struct line_info_table*) bfd_alloc (abfd,					       sizeof (struct line_info_table));  table->abfd = abfd;  table->comp_dir = unit->comp_dir;  table->num_files = 0;  table->files = NULL;  table->num_dirs = 0;  table->dirs = NULL;  table->files = NULL;  table->last_line = NULL;  line_ptr = stash->dwarf_line_buffer + unit->line_offset;  /* Read in the prologue.  */  lh.total_length = read_4_bytes (abfd, line_ptr);  line_ptr += 4;  line_end = line_ptr + lh.total_length;  lh.version = read_2_bytes (abfd, line_ptr);  line_ptr += 2;  lh.prologue_length = read_4_bytes (abfd, line_ptr);  line_ptr += 4;  lh.minimum_instruction_length = read_1_byte (abfd, line_ptr);  line_ptr += 1;  lh.default_is_stmt = read_1_byte (abfd, line_ptr);  line_ptr += 1;  lh.line_base = read_1_signed_byte (abfd, line_ptr);  line_ptr += 1;  lh.line_range = read_1_byte (abfd, line_ptr);  line_ptr += 1;  lh.opcode_base = read_1_byte (abfd, line_ptr);  line_ptr += 1;  lh.standard_opcode_lengths = (unsigned char *)    bfd_alloc (abfd, lh.opcode_base * sizeof (unsigned char));  lh.standard_opcode_lengths[0] = 1;  for (i = 1; i < lh.opcode_base; ++i)    {      lh.standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);      line_ptr += 1;    }  /* Read directory table.  */  while ((cur_dir = read_string (abfd, line_ptr, &bytes_read)) != NULL)    {      line_ptr += bytes_read;      if ((table->num_dirs % DIR_ALLOC_CHUNK) == 0)	{	  table->dirs = (char **)	    bfd_realloc (table->dirs,			 (table->num_dirs + DIR_ALLOC_CHUNK) * sizeof (char *));	  if (! table->dirs)	    return 0;	}      table->dirs[table->num_dirs++] = cur_dir;    }  line_ptr += bytes_read;  /* Read file name table.  */  while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL)    {      line_ptr += bytes_read;      if ((table->num_files % FILE_ALLOC_CHUNK) == 0)	{	  table->files = (struct fileinfo *)	    bfd_realloc (table->files,			 (table->num_files + FILE_ALLOC_CHUNK)			 * sizeof (struct fileinfo));	  if (! table->files)	    return 0;	}      table->files[table->num_files].name = cur_file;      table->files[table->num_files].dir =	read_unsigned_leb128 (abfd, line_ptr, &bytes_read);      line_ptr += bytes_read;      table->files[table->num_files].time =	read_unsigned_leb128 (abfd, line_ptr, &bytes_read);      line_ptr += bytes_read;      table->files[table->num_files].size =	read_unsigned_leb128 (abfd, line_ptr, &bytes_read);      line_ptr += bytes_read;      table->num_files++;    }  line_ptr += bytes_read;  /* Read the statement sequences until there's nothing left.  */  while (line_ptr < line_end)    {      /* State machine registers.  */      bfd_vma address = 0;      char* filename = concat_filename (table, 1);      unsigned int line = 1;      unsigned int column = 0;      int is_stmt = lh.default_is_stmt;      int basic_block = 0;      int end_sequence = 0, need_low_pc = 1;      bfd_vma low_pc = 0;      /* Decode the table.  */      while (! end_sequence)	{	  op_code = read_1_byte (abfd, line_ptr);	  line_ptr += 1;	  switch (op_code)	    {	    case DW_LNS_extended_op:	      line_ptr += 1;	/* Ignore length.  */	      extended_op = read_1_byte (abfd, line_ptr);	      line_ptr += 1;	      switch (extended_op)		{		case DW_LNE_end_sequence:		  end_sequence = 1;		  add_line_info (table, address, filename, line, column,				 end_sequence);		  if (need_low_pc)		    {		      need_low_pc = 0;		      low_pc = address;		    }		  arange_add (unit, low_pc, address);		  break;		case DW_LNE_set_address:		  address = read_address (unit, line_ptr);		  line_ptr += unit->addr_size;		  break;		case DW_LNE_define_file:		  cur_file = read_string (abfd, line_ptr, &bytes_read);		  line_ptr += bytes_read;		  if ((table->num_files % FILE_ALLOC_CHUNK) == 0)		    {		      table->files = (struct fileinfo *)			bfd_realloc (table->files,				     (table->num_files + FILE_ALLOC_CHUNK)				     * sizeof (struct fileinfo));		      if (! table->files)			return 0;		    }		  table->files[table->num_files].name = cur_file;		  table->files[table->num_files].dir =		    read_unsigned_leb128 (abfd, line_ptr, &bytes_read);		  line_ptr += bytes_read;		  table->files[table->num_files].time =		    read_unsigned_leb128 (abfd, line_ptr, &bytes_read);		  line_ptr += bytes_read;		  table->files[table->num_files].size =		    read_unsigned_leb128 (abfd, line_ptr, &bytes_read);		  line_ptr += bytes_read;		  table->num_files++;		  break;		default:		  (*_bfd_error_handler) (_("Dwarf Error: mangled line number section."));		  bfd_set_error (bfd_error_bad_value);		  return 0;		}	      break;	    case DW_LNS_copy:	      add_line_info (table, address, filename, line, column, 0);	      basic_block = 0;	      if (need_low_pc)		{		  need_low_pc = 0;		  low_pc = address;		}	      break;	    case DW_LNS_advance_pc:	      address += lh.minimum_instruction_length		* read_unsigned_leb128 (abfd, line_ptr, &bytes_read);	      line_ptr += bytes_read;	      break;	    case DW_LNS_advance_line:	      line += read_signed_leb128 (abfd, line_ptr, &bytes_read);	      line_ptr += bytes_read;	      break;	    case DW_LNS_set_file:	      {		unsigned int file;		/* The file and directory tables are 0 based, the references		   are 1 based.  */		file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);		line_ptr += bytes_read;		filename = concat_filename (table, file);		break;	      }	    case DW_LNS_set_column:	      column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);	      line_ptr += bytes_read;	      break;	    case DW_LNS_negate_stmt:	      is_stmt = (!is_stmt);	      break;	    case DW_LNS_set_basic_block:	      basic_block = 1;	      break;	    case DW_LNS_const_add_pc:	      address += lh.minimum_instruction_length		      * ((255 - lh.opcode_base) / lh.line_range);	      break;	    case DW_LNS_fixed_advance_pc:	      address += read_2_bytes (abfd, line_ptr);	      line_ptr += 2;	      break;	    default:		/* Special operand.  */	      adj_opcode = op_code - lh.opcode_base;	      address += (adj_opcode / lh.line_range)		* lh.minimum_instruction_length;	      line += lh.line_base + (adj_opcode % lh.line_range);	      /* Append row to matrix using current values.  */	      add_line_info (table, address, filename, line, column, 0);	      basic_block = 1;	      if (need_low_pc)		{		  need_low_pc = 0;		  low_pc = address;		}	    }	}    }  return table;}/* If ADDR is within TABLE set the output parameters and return true,   otherwise return false.  The output parameters, FILENAME_PTR and   LINENUMBER_PTR, are pointers to the objects to be filled in.  */static booleanlookup_address_in_line_info_table (table,				   addr,				   filename_ptr,				   linenumber_ptr)     struct line_info_table* table;     bfd_vma addr;     const char **filename_ptr;     unsigned int *linenumber_ptr;{  struct line_info* next_line = table->last_line;  struct line_info* each_line;  if (!next_line)    return false;  each_line = next_line->prev_line;  while (each_line && next_line)    {      if (!each_line->end_sequence	  && addr >= each_line->address && addr < next_line->address)	{	  *filename_ptr = each_line->filename;	  *linenumber_ptr = each_line->line;	  return true;	}      next_line = each_line;      each_line = each_line->prev_line;    }  return false;}/* Function table functions.  */struct funcinfo{  struct funcinfo *prev_func;  char* name;  bfd_vma low;  bfd_vma high;};/* If ADDR is within TABLE, set FUNCTIONNAME_PTR, and return true.  */static booleanlookup_address_in_function_table (table,				  addr,				  functionname_ptr)     struct funcinfo* table;     bfd_vma addr;     const char **functionname_ptr;{  struct funcinfo* each_func;  for (each_func = table;       each_func;       each_func = each_func->prev_func)    {      if (addr >= each_func->low && addr < each_func->high)	{	  *functionname_ptr = each_func->name;	  return true;	}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?