⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dwarfread.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
DESCRIPTION	Translate the DWARF line number information to gdb form.	The ".line" section contains one or more line number tables, one for	each ".line" section from the objects that were linked.	The AT_stmt_list attribute for each TAG_source_file entry in the	".debug" section contains the offset into the ".line" section for the	start of the table for that file.	The table itself has the following structure:	<table length><base address><source statement entry>	4 bytes       4 bytes       10 bytes	The table length is the total size of the table, including the 4 bytes	for the length information.	The base address is the address of the first instruction generated	for the source file.	Each source statement entry has the following structure:	<line number><statement position><address delta>	4 bytes      2 bytes             4 bytes	The line number is relative to the start of the file, starting with	line 1.	The statement position either -1 (0xFFFF) or the number of characters	from the beginning of the line to the beginning of the statement.	The address delta is the difference between the base address and	the address of the first instruction for the statement.	Note that we must copy the bytes from the packed table to our local	variables before attempting to use them, to avoid alignment problems	on some machines, particularly RISC processors.BUGS	Does gdb expect the line numbers to be sorted?  They are now by	chance/luck, but are not required to be.  (FIXME)	The line with number 0 is unused, gdb apparently can discover the	span of the last line some other way. How?  (FIXME) */static voiddecode_line_numbers (linetable)     char *linetable;{  char *tblscan;  char *tblend;  unsigned long length;  unsigned long base;  unsigned long line;  unsigned long pc;    if (linetable != NULL)    {      tblscan = tblend = linetable;      length = target_to_host (tblscan, SIZEOF_LINETBL_LENGTH, GET_UNSIGNED,			       current_objfile);      tblscan += SIZEOF_LINETBL_LENGTH;      tblend += length;      base = target_to_host (tblscan, TARGET_FT_POINTER_SIZE (objfile),			     GET_UNSIGNED, current_objfile);      tblscan += TARGET_FT_POINTER_SIZE (objfile);      base += baseaddr;      while (tblscan < tblend)	{	  line = target_to_host (tblscan, SIZEOF_LINETBL_LINENO, GET_UNSIGNED,				 current_objfile);	  tblscan += SIZEOF_LINETBL_LINENO + SIZEOF_LINETBL_STMT;	  pc = target_to_host (tblscan, SIZEOF_LINETBL_DELTA, GET_UNSIGNED,			       current_objfile);	  tblscan += SIZEOF_LINETBL_DELTA;	  pc += base;	  if (line != 0)	    {	      record_line (current_subfile, line, pc);	    }	}    }}/*LOCAL FUNCTION	locval -- compute the value of a location attributeSYNOPSIS	static int locval (char *loc)DESCRIPTION	Given pointer to a string of bytes that define a location, compute	the location and return the value.	When computing values involving the current value of the frame pointer,	the value zero is used, which results in a value relative to the frame	pointer, rather than the absolute value.  This is what GDB wants	anyway.    	When the result is a register number, the global isreg flag is set,	otherwise it is cleared.  This is a kludge until we figure out a better	way to handle the problem.  Gdb's design does not mesh well with the	DWARF notion of a location computing interpreter, which is a shame	because the flexibility goes unused.NOTES	Note that stack[0] is unused except as a default error return.	Note that stack overflow is not yet handled. */static intlocval (loc)     char *loc;{  unsigned short nbytes;  unsigned short locsize;  auto long stack[64];  int stacki;  char *end;  long regno;  int loc_atom_code;  int loc_value_size;    nbytes = attribute_size (AT_location);  locsize = target_to_host (loc, nbytes, GET_UNSIGNED, current_objfile);  loc += nbytes;  end = loc + locsize;  stacki = 0;  stack[stacki] = 0;  isreg = 0;  offreg = 0;  loc_value_size = TARGET_FT_LONG_SIZE (current_objfile);  while (loc < end)    {      loc_atom_code = target_to_host (loc, SIZEOF_LOC_ATOM_CODE, GET_UNSIGNED,				      current_objfile);      loc += SIZEOF_LOC_ATOM_CODE;      switch (loc_atom_code)	{	  case 0:	    /* error */	    loc = end;	    break;	  case OP_REG:	    /* push register (number) */	    stack[++stacki] = target_to_host (loc, loc_value_size,					      GET_UNSIGNED, current_objfile);	    loc += loc_value_size;	    isreg = 1;	    break;	  case OP_BASEREG:	    /* push value of register (number) */	    /* Actually, we compute the value as if register has 0 */	    offreg = 1;	    regno = target_to_host (loc, loc_value_size, GET_UNSIGNED,				    current_objfile);	    loc += loc_value_size;	    if (regno == R_FP)	      {		stack[++stacki] = 0;	      }	    else	      {		stack[++stacki] = 0;		SQUAWK (("BASEREG %d not handled!", regno));	      }	    break;	  case OP_ADDR:	    /* push address (relocated address) */	    stack[++stacki] = target_to_host (loc, loc_value_size,					      GET_UNSIGNED, current_objfile);	    loc += loc_value_size;	    break;	  case OP_CONST:	    /* push constant (number)   FIXME: signed or unsigned! */	    stack[++stacki] = target_to_host (loc, loc_value_size,					      GET_SIGNED, current_objfile);	    loc += loc_value_size;	    break;	  case OP_DEREF2:	    /* pop, deref and push 2 bytes (as a long) */	    SQUAWK (("OP_DEREF2 address 0x%x not handled", stack[stacki]));	    break;	  case OP_DEREF4:	/* pop, deref and push 4 bytes (as a long) */	    SQUAWK (("OP_DEREF4 address 0x%x not handled", stack[stacki]));	    break;	  case OP_ADD:	/* pop top 2 items, add, push result */	    stack[stacki - 1] += stack[stacki];	    stacki--;	    break;	}    }  return (stack[stacki]);}/*LOCAL FUNCTION	read_ofile_symtab -- build a full symtab entry from chunk of DIE'sSYNOPSIS	static struct symtab *read_ofile_symtab (struct partial_symtab *pst)DESCRIPTION	When expanding a partial symbol table entry to a full symbol table	entry, this is the function that gets called to read in the symbols	for the compilation unit.	Returns a pointer to the newly constructed symtab (which is now	the new first one on the objfile's symtab list). */static struct symtab *read_ofile_symtab (pst)     struct partial_symtab *pst;{  struct cleanup *back_to;  unsigned long lnsize;  file_ptr foffset;  bfd *abfd;  char lnsizedata[SIZEOF_LINETBL_LENGTH];  abfd = pst -> objfile -> obfd;  current_objfile = pst -> objfile;  /* Allocate a buffer for the entire chunk of DIE's for this compilation     unit, seek to the location in the file, and read in all the DIE's. */  diecount = 0;  dbsize = DBLENGTH (pst);  dbbase = xmalloc (dbsize);  dbroff = DBROFF(pst);  foffset = DBFOFF(pst) + dbroff;  base_section_offsets = pst->section_offsets;  baseaddr = ANOFFSET (pst->section_offsets, 0);  if (bfd_seek (abfd, foffset, L_SET) ||      (bfd_read (dbbase, dbsize, 1, abfd) != dbsize))    {      free (dbbase);      error ("can't read DWARF data");    }  back_to = make_cleanup (free, dbbase);  /* If there is a line number table associated with this compilation unit     then read the size of this fragment in bytes, from the fragment itself.     Allocate a buffer for the fragment and read it in for future      processing. */  lnbase = NULL;  if (LNFOFF (pst))    {      if (bfd_seek (abfd, LNFOFF (pst), L_SET) ||	  (bfd_read ((PTR) lnsizedata, sizeof (lnsizedata), 1, abfd) !=	   sizeof (lnsizedata)))	{	  error ("can't read DWARF line number table size");	}      lnsize = target_to_host (lnsizedata, SIZEOF_LINETBL_LENGTH,			       GET_UNSIGNED, pst -> objfile);      lnbase = xmalloc (lnsize);      if (bfd_seek (abfd, LNFOFF (pst), L_SET) ||	  (bfd_read (lnbase, lnsize, 1, abfd) != lnsize))	{	  free (lnbase);	  error ("can't read DWARF line numbers");	}      make_cleanup (free, lnbase);    }  process_dies (dbbase, dbbase + dbsize, pst -> objfile);  do_cleanups (back_to);  current_objfile = NULL;  return (pst -> objfile -> symtabs);}/*LOCAL FUNCTION	psymtab_to_symtab_1 -- do grunt work for building a full symtab entrySYNOPSIS	static void psymtab_to_symtab_1 (struct partial_symtab *pst)DESCRIPTION	Called once for each partial symbol table entry that needs to be	expanded into a full symbol table entry.*/static voidpsymtab_to_symtab_1 (pst)     struct partial_symtab *pst;{  int i;  struct cleanup *old_chain;    if (pst != NULL)    {      if (pst->readin)	{	  warning ("psymtab for %s already read in.  Shouldn't happen.",		   pst -> filename);	}      else	{	  /* Read in all partial symtabs on which this one is dependent */	  for (i = 0; i < pst -> number_of_dependencies; i++)	    {	      if (!pst -> dependencies[i] -> readin)		{		  /* Inform about additional files that need to be read in. */		  if (info_verbose)		    {		      fputs_filtered (" ", stdout);		      wrap_here ("");		      fputs_filtered ("and ", stdout);		      wrap_here ("");		      printf_filtered ("%s...",				       pst -> dependencies[i] -> filename);		      wrap_here ("");		      fflush (stdout);		/* Flush output */		    }		  psymtab_to_symtab_1 (pst -> dependencies[i]);		}	    }	  	  if (DBLENGTH (pst))		/* Otherwise it's a dummy */	    {	      buildsym_init ();	      old_chain = make_cleanup (really_free_pendings, 0);	      pst -> symtab = read_ofile_symtab (pst);	      if (info_verbose)		{		  printf_filtered ("%d DIE's, sorting...", diecount);		  wrap_here ("");		  fflush (stdout);		}	      sort_symtab_syms (pst -> symtab);	      do_cleanups (old_chain);	    }	  pst -> readin = 1;	}    }}/*LOCAL FUNCTION	dwarf_psymtab_to_symtab -- build a full symtab entry from partial oneSYNOPSIS	static void dwarf_psymtab_to_symtab (struct partial_symtab *pst)DESCRIPTION	This is the DWARF support entry point for building a full symbol	table entry from a partial symbol table entry.  We are passed a	pointer to the partial symbol table entry that needs to be expanded.*/static voiddwarf_psymtab_to_symtab (pst)     struct partial_symtab *pst;{  if (pst != NULL)    {      if (pst -> readin)	{	  warning ("psymtab for %s already read in.  Shouldn't happen.",		   pst -> filename);	}      else	{	  if (DBLENGTH (pst) || pst -> number_of_dependencies)	    {	      /* Print the message now, before starting serious work, to avoid		 disconcerting pauses.  */	      if (info_verbose)		{		  printf_filtered ("Reading in symbols for %s...",				   pst -> filename);		  fflush (stdout);		}	      	      psymtab_to_symtab_1 (pst);	      #if 0	      /* FIXME:  Check to see what dbxread is doing here and see if		 we need to do an equivalent or is this something peculiar to		 stabs/a.out format.		 Match with global symbols.  This only needs to be done once,		 after all of the symtabs and dependencies have been read in.		 */	      scan_file_globals (pst -> objfile);#endif	      	      /* Finish up the verbose info message.  */	      if (info_verbose)		{		  printf_filtered ("done.\n");		  fflush (stdout);		}	    }	}    }}/*LOCAL FUNCTION	init_psymbol_list -- initialize storage for partial symbolsSYNOPSIS	static void init_psymbol_list (struct objfile *objfile, int total_symbols)DESCRIPTION	Initializes storage for all of the partial symbols that will be	created by dwarf_build_psymtabs and subsidiaries. */static voidinit_psymbol_list (objfile, total_symbols)     struct objfile *objfile;     int total_symbols;{  /* Free any previously allocated psymbol lists.  */    if (objfile -> global_psymbols.list)    {      mfree (objfile -> md, (PTR)objfile -> global_psymbols.list);    }  if (objfile -> static_psymbols.list)    {      mfree (objfile -> md, (PTR)objfile -> static_psymbols.list);    }    /* Current best guess is that there are approximately a twentieth     of the total symbols (in a debugging file) are global or static     oriented symbols */    objfile -> global_psymbols.size = total_symbols / 10;  objfile -> static_psymbols.size = total_symbols / 10;  objfile -> global_psymbols.next =    objfile -> global_psymbols.list = (stru

⌨️ 快捷键说明

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