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

📄 linux-low.c

📁 这个是LINUX下的GDB调度工具的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
      p_sig = malloc (sizeof (*p_sig));      p_sig->prev = process->pending_signals;      p_sig->signal = process->resume->sig;      process->pending_signals = p_sig;    }  process->resume = NULL;}/* Set DUMMY if this process has an interesting status pending.  */static intresume_status_pending_p (struct inferior_list_entry *entry, void *flag_p){  struct process_info *process = (struct process_info *) entry;  /* Processes which will not be resumed are not interesting, because     we might not wait for them next time through linux_wait.  */  if (process->resume->leave_stopped)    return 0;  /* If this thread has a removed breakpoint, we won't have any     events to report later, so check now.  check_removed_breakpoint     may clear status_pending_p.  We avoid calling check_removed_breakpoint     for any thread that we are not otherwise going to resume - this     lets us preserve stopped status when two threads hit a breakpoint.     GDB removes the breakpoint to single-step a particular thread     past it, then re-inserts it and resumes all threads.  We want     to report the second thread without resuming it in the interim.  */  if (process->status_pending_p)    check_removed_breakpoint (process);  if (process->status_pending_p)    * (int *) flag_p = 1;  return 0;}static voidlinux_resume (struct thread_resume *resume_info){  int pending_flag;  /* Yes, the use of a global here is rather ugly.  */  resume_ptr = resume_info;  for_each_inferior (&all_threads, linux_set_resume_request);  /* If there is a thread which would otherwise be resumed, which     has a pending status, then don't resume any threads - we can just     report the pending status.  Make sure to queue any signals     that would otherwise be sent.  */  pending_flag = 0;  find_inferior (&all_processes, resume_status_pending_p, &pending_flag);  if (debug_threads)    {      if (pending_flag)	fprintf (stderr, "Not resuming, pending status\n");      else	fprintf (stderr, "Resuming, no pending status\n");    }  if (pending_flag)    for_each_inferior (&all_threads, linux_queue_one_thread);  else    {      block_async_io ();      enable_async_io ();      for_each_inferior (&all_threads, linux_continue_one_thread);    }}#ifdef HAVE_LINUX_USRREGSintregister_addr (int regnum){  int addr;  if (regnum < 0 || regnum >= the_low_target.num_regs)    error ("Invalid register number %d.", regnum);  addr = the_low_target.regmap[regnum];  return addr;}/* Fetch one register.  */static voidfetch_register (int regno){  CORE_ADDR regaddr;  register int i;  char *buf;  if (regno >= the_low_target.num_regs)    return;  if ((*the_low_target.cannot_fetch_register) (regno))    return;  regaddr = register_addr (regno);  if (regaddr == -1)    return;  buf = alloca (register_size (regno));  for (i = 0; i < register_size (regno); i += sizeof (PTRACE_XFER_TYPE))    {      errno = 0;      *(PTRACE_XFER_TYPE *) (buf + i) =	ptrace (PTRACE_PEEKUSER, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, 0);      regaddr += sizeof (PTRACE_XFER_TYPE);      if (errno != 0)	{	  /* Warning, not error, in case we are attached; sometimes the	     kernel doesn't let us at the registers.  */	  char *err = strerror (errno);	  char *msg = alloca (strlen (err) + 128);	  sprintf (msg, "reading register %d: %s", regno, err);	  error (msg);	  goto error_exit;	}    }  supply_register (regno, buf);error_exit:;}/* Fetch all registers, or just one, from the child process.  */static voidusr_fetch_inferior_registers (int regno){  if (regno == -1 || regno == 0)    for (regno = 0; regno < the_low_target.num_regs; regno++)      fetch_register (regno);  else    fetch_register (regno);}/* Store our register values back into the inferior.   If REGNO is -1, do this for all registers.   Otherwise, REGNO specifies which register (so we can save time).  */static voidusr_store_inferior_registers (int regno){  CORE_ADDR regaddr;  int i;  char *buf;  if (regno >= 0)    {      if (regno >= the_low_target.num_regs)	return;      if ((*the_low_target.cannot_store_register) (regno) == 1)	return;      regaddr = register_addr (regno);      if (regaddr == -1)	return;      errno = 0;      buf = alloca (register_size (regno));      collect_register (regno, buf);      for (i = 0; i < register_size (regno); i += sizeof (PTRACE_XFER_TYPE))	{	  errno = 0;	  ptrace (PTRACE_POKEUSER, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,		  *(PTRACE_XFER_TYPE *) (buf + i));	  if (errno != 0)	    {	      if ((*the_low_target.cannot_store_register) (regno) == 0)		{		  char *err = strerror (errno);		  char *msg = alloca (strlen (err) + 128);		  sprintf (msg, "writing register %d: %s",			   regno, err);		  error (msg);		  return;		}	    }	  regaddr += sizeof (PTRACE_XFER_TYPE);	}    }  else    for (regno = 0; regno < the_low_target.num_regs; regno++)      usr_store_inferior_registers (regno);}#endif /* HAVE_LINUX_USRREGS */#ifdef HAVE_LINUX_REGSETSstatic intregsets_fetch_inferior_registers (){  struct regset_info *regset;  regset = target_regsets;  while (regset->size >= 0)    {      void *buf;      int res;      if (regset->size == 0)	{	  regset ++;	  continue;	}      buf = malloc (regset->size);      res = ptrace (regset->get_request, inferior_pid, 0, buf);      if (res < 0)	{	  if (errno == EIO)	    {	      /* If we get EIO on the first regset, do not try regsets again.		 If we get EIO on a later regset, disable that regset.  */	      if (regset == target_regsets)		{		  use_regsets_p = 0;		  return -1;		}	      else		{		  regset->size = 0;		  continue;		}	    }	  else	    {	      char s[256];	      sprintf (s, "ptrace(regsets_fetch_inferior_registers) PID=%d",		       inferior_pid);	      perror (s);	    }	}      regset->store_function (buf);      regset ++;    }  return 0;}static intregsets_store_inferior_registers (){  struct regset_info *regset;  regset = target_regsets;  while (regset->size >= 0)    {      void *buf;      int res;      if (regset->size == 0)	{	  regset ++;	  continue;	}      buf = malloc (regset->size);      regset->fill_function (buf);      res = ptrace (regset->set_request, inferior_pid, 0, buf);      if (res < 0)	{	  if (errno == EIO)	    {	      /* If we get EIO on the first regset, do not try regsets again.		 If we get EIO on a later regset, disable that regset.  */	      if (regset == target_regsets)		{		  use_regsets_p = 0;		  return -1;		}	      else		{		  regset->size = 0;		  continue;		}	    }	  else	    {	      perror ("Warning: ptrace(regsets_store_inferior_registers)");	    }	}      regset ++;      free (buf);    }  return 0;}#endif /* HAVE_LINUX_REGSETS */voidlinux_fetch_registers (int regno){#ifdef HAVE_LINUX_REGSETS  if (use_regsets_p)    {      if (regsets_fetch_inferior_registers () == 0)	return;    }#endif#ifdef HAVE_LINUX_USRREGS  usr_fetch_inferior_registers (regno);#endif}voidlinux_store_registers (int regno){#ifdef HAVE_LINUX_REGSETS  if (use_regsets_p)    {      if (regsets_store_inferior_registers () == 0)	return;    }#endif#ifdef HAVE_LINUX_USRREGS  usr_store_inferior_registers (regno);#endif}/* Copy LEN bytes from inferior's memory starting at MEMADDR   to debugger memory starting at MYADDR.  */static intlinux_read_memory (CORE_ADDR memaddr, char *myaddr, int len){  register int i;  /* Round starting address down to longword boundary.  */  register CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE);  /* Round ending address up; get number of longwords that makes.  */  register int count    = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1)      / sizeof (PTRACE_XFER_TYPE);  /* Allocate buffer of that many longwords.  */  register PTRACE_XFER_TYPE *buffer    = (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE));  /* Read all the longwords */  for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))    {      errno = 0;      buffer[i] = ptrace (PTRACE_PEEKTEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr, 0);      if (errno)	return errno;    }  /* Copy appropriate bytes out of the buffer.  */  memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)), len);  return 0;}/* Copy LEN bytes of data from debugger memory at MYADDR   to inferior's memory at MEMADDR.   On failure (cannot write the inferior)   returns the value of errno.  */static intlinux_write_memory (CORE_ADDR memaddr, const char *myaddr, int len){  register int i;  /* Round starting address down to longword boundary.  */  register CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE);  /* Round ending address up; get number of longwords that makes.  */  register int count  = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1) / sizeof (PTRACE_XFER_TYPE);  /* Allocate buffer of that many longwords.  */  register PTRACE_XFER_TYPE *buffer = (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE));  extern int errno;  if (debug_threads)    {      fprintf (stderr, "Writing %02x to %08lx\n", (unsigned)myaddr[0], (long)memaddr);    }  /* Fill start and end extra bytes of buffer with existing memory data.  */  buffer[0] = ptrace (PTRACE_PEEKTEXT, inferior_pid,		      (PTRACE_ARG3_TYPE) addr, 0);  if (count > 1)    {      buffer[count - 1]	= ptrace (PTRACE_PEEKTEXT, inferior_pid,		  (PTRACE_ARG3_TYPE) (addr + (count - 1)				      * sizeof (PTRACE_XFER_TYPE)),		  0);    }  /* Copy data to be written over corresponding part of buffer */  memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)), myaddr, len);  /* Write the entire buffer.  */  for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))    {      errno = 0;      ptrace (PTRACE_POKETEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr, buffer[i]);      if (errno)	return errno;    }  return 0;}static voidlinux_look_up_symbols (void){#ifdef USE_THREAD_DB  if (using_threads)    return;  using_threads = thread_db_init ();#endif}static voidlinux_send_signal (int signum){  extern int signal_pid;  if (cont_thread > 0)    {      struct process_info *process;      process = get_thread_process (current_inferior);      kill_lwp (process->lwpid, signum);    }  else    kill_lwp (signal_pid, signum);}/* Copy LEN bytes from inferior's auxiliary vector starting at OFFSET   to debugger memory starting at MYADDR.  */static intlinux_read_auxv (CORE_ADDR offset, char *myaddr, unsigned int len){  char filename[PATH_MAX];  int fd, n;  snprintf (filename, sizeof filename, "/proc/%d/auxv", inferior_pid);  fd = open (filename, O_RDONLY);  if (fd < 0)    return -1;  if (offset != (CORE_ADDR) 0      && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)    n = -1;  else    n = read (fd, myaddr, len);  close (fd);  return n;}static struct target_ops linux_target_ops = {  linux_create_inferior,  linux_attach,  linux_kill,  linux_detach,  linux_thread_alive,  linux_resume,  linux_wait,  linux_fetch_registers,  linux_store_registers,  linux_read_memory,  linux_write_memory,  linux_look_up_symbols,  linux_send_signal,  linux_read_auxv,};static voidlinux_init_signals (){  /* FIXME drow/2002-06-09: As above, we should check with LinuxThreads     to find what the cancel signal actually is.  */  signal (__SIGRTMIN+1, SIG_IGN);}voidinitialize_low (void){  using_threads = 0;  set_target_ops (&linux_target_ops);  set_breakpoint_data (the_low_target.breakpoint,		       the_low_target.breakpoint_len);  init_registers ();  linux_init_signals ();}

⌨️ 快捷键说明

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