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

📄 solib.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Handle SunOS and SVR4 shared libraries for GDB, the GNU Debugger.   Copyright 1990, 1991, 1992 Free Software Foundation, Inc.   This file is part of GDB.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */#include "defs.h"#include <sys/types.h>#include <signal.h>#include <string.h>#include <link.h>#include <sys/param.h>#include <fcntl.h>#ifndef SVR4_SHARED_LIBS /* SunOS shared libs need the nlist structure.  */#include <a.out.h> #endif#include "symtab.h"#include "bfd.h"#include "symfile.h"#include "objfiles.h"#include "gdbcore.h"#include "command.h"#include "target.h"#include "frame.h"#include "regex.h"#include "inferior.h"#define MAX_PATH_SIZE 256		/* FIXME: Should be dynamic *//* On SVR4 systems, for the initial implementation, use main() as the   "startup mapping complete" breakpoint address.  The models for SunOS   and SVR4 dynamic linking debugger support are different in that SunOS   hits one breakpoint when all mapping is complete while using the SVR4   debugger support takes two breakpoint hits for each file mapped, and   there is no way to know when the "last" one is hit.  Both these   mechanisms should be tied to a "breakpoint service routine" that   gets automatically executed whenever one of the breakpoints indicating   a change in mapping is hit.  This is a future enhancement.  (FIXME) */#define BKPT_AT_MAIN 1/* local data declarations */#ifndef SVR4_SHARED_LIBS#define DEBUG_BASE "_DYNAMIC"#define LM_ADDR(so) ((so) -> lm.lm_addr)#define LM_NEXT(so) ((so) -> lm.lm_next)#define LM_NAME(so) ((so) -> lm.lm_name)static struct link_dynamic dynamic_copy;static struct link_dynamic_2 ld_2_copy;static struct ld_debug debug_copy;static CORE_ADDR debug_addr;static CORE_ADDR flag_addr;#else	/* SVR4_SHARED_LIBS */#define DEBUG_BASE "_r_debug"#define LM_ADDR(so) ((so) -> lm.l_addr)#define LM_NEXT(so) ((so) -> lm.l_next)#define LM_NAME(so) ((so) -> lm.l_name)static struct r_debug debug_copy;char shadow_contents[BREAKPOINT_MAX];	/* Stash old bkpt addr contents */#endif	/* !SVR4_SHARED_LIBS */struct so_list {  struct so_list *next;			/* next structure in linked list */  struct link_map lm;			/* copy of link map from inferior */  struct link_map *lmaddr;		/* addr in inferior lm was read from */  CORE_ADDR lmend;			/* upper addr bound of mapped object */  char so_name[MAX_PATH_SIZE];		/* shared object lib name (FIXME) */  char symbols_loaded;			/* flag: symbols read in yet? */  char from_tty;			/* flag: print msgs? */  bfd *so_bfd;				/* bfd for so_name */  struct objfile *objfile;		/* objfile for loaded lib */  struct section_table *sections;  struct section_table *sections_end;  struct section_table *textsection;};static struct so_list *so_list_head;	/* List of known shared objects */static CORE_ADDR debug_base;		/* Base of dynamic linker structures */static CORE_ADDR breakpoint_addr;	/* Address where end bkpt is set */extern intfdmatch PARAMS ((int, int));		/* In libiberty *//* Local function prototypes */static voidspecial_symbol_handling PARAMS ((struct so_list *));static voidsharedlibrary_command PARAMS ((char *, int));static intenable_break PARAMS ((void));static intdisable_break PARAMS ((void));static voidinfo_sharedlibrary_command PARAMS ((char *, int));static intsymbol_add_stub PARAMS ((char *));static struct so_list *find_solib PARAMS ((struct so_list *));static struct link_map *first_link_map_member PARAMS ((void));static CORE_ADDRlocate_base PARAMS ((void));static voidsolib_map_sections PARAMS ((struct so_list *));#ifdef SVR4_SHARED_LIBSstatic intlook_for_base PARAMS ((int, CORE_ADDR));static CORE_ADDRbfd_lookup_symbol PARAMS ((bfd *, char *));#elsestatic voidsolib_add_common_symbols PARAMS ((struct rtc_symb *, struct objfile *));#endif/*LOCAL FUNCTION	solib_map_sections -- open bfd and build sections for shared libSYNOPSIS	static void solib_map_sections (struct so_list *so)DESCRIPTION	Given a pointer to one of the shared objects in our list	of mapped objects, use the recorded name to open a bfd	descriptor for the object, build a section table, and then	relocate all the section addresses by the base address at	which the shared object was mapped.FIXMES	In most (all?) cases the shared object file name recorded in the	dynamic linkage tables will be a fully qualified pathname.  For	cases where it isn't, do we really mimic the systems search	mechanism correctly in the below code (particularly the tilde	expansion stuff?). */static voidsolib_map_sections (so)     struct so_list *so;{  char *filename;  char *scratch_pathname;  int scratch_chan;  struct section_table *p;    filename = tilde_expand (so -> so_name);  make_cleanup (free, filename);    scratch_chan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,			&scratch_pathname);  if (scratch_chan < 0)    {      scratch_chan = openp (getenv ("LD_LIBRARY_PATH"), 1, filename,			    O_RDONLY, 0, &scratch_pathname);    }  if (scratch_chan < 0)    {      perror_with_name (filename);    }    so -> so_bfd = bfd_fdopenr (scratch_pathname, NULL, scratch_chan);  if (!so -> so_bfd)    {      error ("Could not open `%s' as an executable file: %s",	     scratch_pathname, bfd_errmsg (bfd_error));    }  if (!bfd_check_format (so -> so_bfd, bfd_object))    {      error ("\"%s\": not in executable format: %s.",	     scratch_pathname, bfd_errmsg (bfd_error));    }  if (build_section_table (so -> so_bfd, &so -> sections, &so -> sections_end))    {      error ("Can't find the file sections in `%s': %s", 	     exec_bfd -> filename, bfd_errmsg (bfd_error));    }  for (p = so -> sections; p < so -> sections_end; p++)    {      /* Relocate the section binding addresses as recorded in the shared	 object's file by the base address to which the object was actually	 mapped. */      p -> addr += (CORE_ADDR) LM_ADDR (so);      p -> endaddr += (CORE_ADDR) LM_ADDR (so);      so -> lmend = (CORE_ADDR) max (p -> endaddr, so -> lmend);      if (strcmp (p -> sec_ptr -> name, ".text") == 0)	{	  so -> textsection = p;	}    }}/* Read all dynamically loaded common symbol definitions from the inferior   and add them to the minimal symbol table for the shared library objfile.  */#ifndef SVR4_SHARED_LIBSstatic voidsolib_add_common_symbols (rtc_symp, objfile)    struct rtc_symb *rtc_symp;    struct objfile *objfile;{  struct rtc_symb inferior_rtc_symb;  struct nlist inferior_rtc_nlist;  int len;  char *name;  char *origname;  init_minimal_symbol_collection ();  make_cleanup (discard_minimal_symbols, 0);  while (rtc_symp)    {      read_memory ((CORE_ADDR) rtc_symp,		   (char *) &inferior_rtc_symb,		   sizeof (inferior_rtc_symb));      read_memory ((CORE_ADDR) inferior_rtc_symb.rtc_sp,		   (char *) &inferior_rtc_nlist,		   sizeof(inferior_rtc_nlist));      if (inferior_rtc_nlist.n_type == N_COMM)	{	  /* FIXME: The length of the symbol name is not available, but in the	     current implementation the common symbol is allocated immediately	     behind the name of the symbol. */	  len = inferior_rtc_nlist.n_value - inferior_rtc_nlist.n_un.n_strx;	  origname = name = xmalloc (len);	  read_memory ((CORE_ADDR) inferior_rtc_nlist.n_un.n_name, name, len);	  /* Don't enter the symbol twice if the target is re-run. */#ifdef NAMES_HAVE_UNDERSCORE	  if (*name == '_')	    {	      name++;	    }#endif	  /* FIXME:  Do we really want to exclude symbols which happen	     to match symbols for other locations in the inferior's	     address space, even when they are in different linkage units? */	  if (lookup_minimal_symbol (name, (struct objfile *) NULL) == NULL)	    {	      name = obsavestring (name, strlen (name),				   &objfile -> symbol_obstack);	      prim_record_minimal_symbol (name, inferior_rtc_nlist.n_value,					  mst_bss);	    }	  free (origname);	}      rtc_symp = inferior_rtc_symb.rtc_next;    }  /* Install any minimal symbols that have been collected as the current     minimal symbols for this objfile. */  install_minimal_symbols (objfile);}#endif	/* SVR4_SHARED_LIBS */#ifdef SVR4_SHARED_LIBS/*LOCAL FUNCTION	bfd_lookup_symbol -- lookup the value for a specific symbolSYNOPSIS	CORE_ADDR bfd_lookup_symbol (bfd *abfd, char *symname)DESCRIPTION	An expensive way to lookup the value of a single symbol for	bfd's that are only temporary anyway.  This is used by the	shared library support to find the address of the debugger	interface structures in the shared library.	Note that 0 is specifically allowed as an error return (no	such symbol).	FIXME:  See if there is a less "expensive" way of doing this.	Also see if there is already another bfd or gdb function	that specifically does this, and if so, use it.*/static CORE_ADDRbfd_lookup_symbol (abfd, symname)     bfd *abfd;     char *symname;{  unsigned int storage_needed;  asymbol *sym;  asymbol **symbol_table;  unsigned int number_of_symbols;  unsigned int i;  struct cleanup *back_to;  CORE_ADDR symaddr = 0;    storage_needed = get_symtab_upper_bound (abfd);  if (storage_needed > 0)    {      symbol_table = (asymbol **) xmalloc (storage_needed);      back_to = make_cleanup (free, (PTR)symbol_table);      number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);         for (i = 0; i < number_of_symbols; i++)	{	  sym = *symbol_table++;	  if (strcmp (sym -> name, symname) == 0)	    {	      symaddr = sym -> value;	      break;	    }	}      do_cleanups (back_to);    }  return (symaddr);}/*LOCAL FUNCTION	look_for_base -- examine file for each mapped address segmentSYNOPSYS	static int look_for_base (int fd, CORE_ADDR baseaddr)DESCRIPTION	This function is passed to proc_iterate_over_mappings, which	causes it to get called once for each mapped address space, with	an open file descriptor for the file mapped to that space, and the	base address of that mapped space.	Our job is to find the symbol DEBUG_BASE in the file that this	fd is open on, if it exists, and if so, initialize the dynamic	linker structure base address debug_base.	Note that this is a computationally expensive proposition, since	we basically have to open a bfd on every call, so we specifically	avoid opening the exec file. */static intlook_for_base (fd, baseaddr)     int fd;     CORE_ADDR baseaddr;{  bfd *interp_bfd;  CORE_ADDR address;  /* If the fd is -1, then there is no file that corresponds to this     mapped memory segment, so skip it.  Also, if the fd corresponds     to the exec file, skip it as well. */  if ((fd == -1) || fdmatch (fileno ((FILE *)(exec_bfd -> iostream)), fd))    {      return (0);    }  /* Try to open whatever random file this fd corresponds to.  Note that     we have no way currently to find the filename.  Don't gripe about     any problems we might have, just fail. */  if ((interp_bfd = bfd_fdopenr ("unnamed", NULL, fd)) == NULL)    {      return (0);    }  if (!bfd_check_format (interp_bfd, bfd_object))    {      bfd_close (interp_bfd);      return (0);    }  /* Now try to find our DEBUG_BASE symbol in this file, which we at     least know to be a valid ELF executable or shared library. */  if ((address = bfd_lookup_symbol (interp_bfd, DEBUG_BASE)) == 0)

⌨️ 快捷键说明

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