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

📄 unexaix.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
      if (f_thdr == 0)	{	  ERROR1 ("unexec: couldn't find \"%s\" section", _TEXT);	}      if (f_dhdr == 0)	{	  ERROR1 ("unexec: couldn't find \"%s\" section", _DATA);	}      if (f_bhdr == 0)	{	  ERROR1 ("unexec: couldn't find \"%s\" section", _BSS);	}    }  else    {      ERROR0 ("can't build a COFF file from scratch yet");    }  orig_data_scnptr = f_dhdr->s_scnptr;  orig_load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0;  /* Now we alter the contents of all the f_*hdr variables     to correspond to what we want to dump.  */  f_hdr.f_flags |= (F_RELFLG | F_EXEC);		/* Why? */#ifdef EXEC_MAGIC  f_ohdr.magic = EXEC_MAGIC;#endif#ifndef NO_REMAP  f_ohdr.tsize = data_start - f_ohdr.text_start;  f_ohdr.text_start = (long) start_of_text ();#endif  f_ohdr.dsize = bss_start - ((unsigned) &_data);  f_ohdr.bsize = bss_end - bss_start;  f_dhdr->s_size = f_ohdr.dsize;  f_bhdr->s_size = f_ohdr.bsize;  f_bhdr->s_paddr = f_ohdr.dsize;  f_bhdr->s_vaddr = f_ohdr.dsize;  /* fix scnptr's */  {    long ptr;    for (scns = 0; scns < f_hdr.f_nscns; scns++) {      struct scnhdr *s = &section[scns];      if (scns == 0)	ptr = s->s_scnptr;      if (s->s_scnptr != 0)	{	  s->s_scnptr = ptr;	}      if ((s->s_flags & 0xffff) == STYP_PAD)	{	  /*	   * the text_start should probably be o_algntext but that doesn't	   * seem to change	   */	  if (f_ohdr.text_start != 0) /* && scns != 0 */	    {	      s->s_size = 512 - (s->s_scnptr % 512);	      if (s->s_size == 512)		s->s_size = 0;	    }	}      ptr = ptr + s->s_size;    }    bias = ptr - block_copy_start;  }  /* fix other pointers */  for (scns = 0; scns < f_hdr.f_nscns; scns++) {    struct scnhdr *s = &section[scns];    if (s->s_relptr != 0)      {	s->s_relptr += bias;      }    if (s->s_lnnoptr != 0)      {	if (lnnoptr == 0) lnnoptr = s->s_lnnoptr;	s->s_lnnoptr += bias;      }  }  if (f_hdr.f_symptr > 0L)    {      f_hdr.f_symptr += bias;    }  data_st = data_start;  text_scnptr = f_thdr->s_scnptr;  data_scnptr = f_dhdr->s_scnptr;  load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0;  block_copy_start = orig_load_scnptr;#ifdef ADJUST_EXEC_HEADER  ADJUST_EXEC_HEADER#endif /* ADJUST_EXEC_HEADER */  if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))    {      PERROR (new_name);    }  if (f_hdr.f_opthdr > 0)    {      if (write (new, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))	{	  PERROR (new_name);	}    }  for (scns = 0; scns < f_hdr.f_nscns; scns++) {    struct scnhdr *s = &section[scns];    if (write (new, s, sizeof (*s)) != sizeof (*s))      {	PERROR (new_name);      }  }  return (0);#endif /* COFF */}/* ****************************************************************  * * Copy the text and data segments from memory to the new a.out */static intcopy_text_and_data (new)     int new;{  register char *end;  register char *ptr;  lseek (new, (long) text_scnptr, 0);  ptr = start_of_text () + text_scnptr;  end = ptr + f_ohdr.tsize;  write_segment (new, ptr, end);  lseek (new, (long) data_scnptr, 0);  ptr = (char *) &_data;  end = ptr + f_ohdr.dsize;  write_segment (new, ptr, end);  return 0;}write_segment (new, ptr, end)     int new;     register char *ptr, *end;{  register int i, nwrite, ret;  char buf[80];  extern int errno;  char zeros[128];  bzero (zeros, sizeof zeros);  for (i = 0; ptr < end;)    {      /* distance to next multiple of 128.  */      nwrite = (((int) ptr + 128) & -128) - (int) ptr;      /* But not beyond specified end.  */      if (nwrite > end - ptr) nwrite = end - ptr;      ret = write (new, ptr, nwrite);      /* If write gets a page fault, it means we reached	 a gap between the old text segment and the old data segment.	 This gap has probably been remapped into part of the text segment.	 So write zeros for it.  */      if (ret == -1 && errno == EFAULT)	{	write (new, zeros, nwrite);	}      else if (nwrite != ret)	{	  sprintf (buf,		   "unexec write failure: addr 0x%x, fileno %d, size 0x%x, wrote 0x%x, errno %d",		   ptr, new, nwrite, ret, errno);	  PERROR (buf);	}      i += nwrite;      ptr += nwrite;    }}/* **************************************************************** * copy_sym * * Copy the relocation information and symbol table from the a.out to the new */static intcopy_sym (new, a_out, a_name, new_name)     int new, a_out;     char *a_name, *new_name;{  char page[1024];  int n;  if (a_out < 0)    return 0;  if (SYMS_START == 0L)    return 0;  if (lnnoptr && lnnoptr < SYMS_START)	/* if there is line number info */    lseek (a_out, lnnoptr, 0);		/* start copying from there */  else    lseek (a_out, SYMS_START, 0);	/* Position a.out to symtab. */  while ((n = read (a_out, page, sizeof page)) > 0)    {      if (write (new, page, n) != n)	{	  PERROR (new_name);	}    }  if (n < 0)    {      PERROR (a_name);    }  return 0;}/* **************************************************************** * mark_x * * After succesfully building the new a.out, mark it executable */staticmark_x (name)     char *name;{  struct stat sbuf;  int um;  int new = 0;  /* for PERROR */  um = umask (777);  umask (um);  if (stat (name, &sbuf) == -1)    {      PERROR (name);    }  sbuf.st_mode |= 0111 & ~um;  if (chmod (name, sbuf.st_mode) == -1)    PERROR (name);}/* *	If the COFF file contains a symbol table and a line number section, *	then any auxiliary entries that have values for x_lnnoptr must *	be adjusted by the amount that the line number section has moved *	in the file (bias computed in make_hdr).  The #@$%&* designers of *	the auxiliary entry structures used the absolute file offsets for *	the line number entry rather than an offset from the start of the *	line number section! * *	When I figure out how to scan through the symbol table and pick out *	the auxiliary entries that need adjustment, this routine will *	be fixed.  As it is now, all such entries are wrong and sdb *	will complain.   Fred Fish, UniSoft Systems Inc. */#ifdef COFF/* This function is probably very slow.  Instead of reopening the new   file for input and output it should copy from the old to the new   using the two descriptors already open (WRITEDESC and READDESC).   Instead of reading one small structure at a time it should use   a reasonable size buffer.  But I don't have time to work on such   things, so I am installing it as submitted to me.  -- RMS.  */adjust_lnnoptrs (writedesc, readdesc, new_name)     int writedesc;     int readdesc;     char *new_name;{  register int nsyms;  register int new;#ifdef amdahl_uts  SYMENT symentry;  AUXENT auxentry;#else  struct syment symentry;  union auxent auxentry;#endif  if (!lnnoptr || !f_hdr.f_symptr)    return 0;  if ((new = open (new_name, 2)) < 0)    {      PERROR (new_name);      return -1;    }  lseek (new, f_hdr.f_symptr, 0);  for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++)    {      read (new, &symentry, SYMESZ);      if (symentry.n_numaux)	{	  read (new, &auxentry, AUXESZ);	  nsyms++;	  if (ISFCN (symentry.n_type)) {	    auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias;	    lseek (new, -AUXESZ, 1);	    write (new, &auxentry, AUXESZ);	  }	}    }  close (new);}#endif /* COFF */#ifdef XCOFF/* It is probably a false economy to optimise this routine (it used to   read one LDREL and do do two lseeks per iteration) but the wrath of   RMS (see above :-) would be too much to bear */unrelocate_symbols (new, a_out, a_name, new_name)     int new, a_out;     char *a_name, *new_name;{  register int i;  register int l;  register LDREL *ldrel;  LDHDR ldhdr;  LDREL ldrel_buf [20];  ulong t_start = &_text;  ulong d_start = &_data;  int * p;  int dirty;  if (load_scnptr == 0)    return 0;  lseek (a_out, orig_load_scnptr, 0);  if (read (a_out, &ldhdr, sizeof (ldhdr)) != sizeof (ldhdr))    {      PERROR (new_name);    }#define SYMNDX_TEXT	0#define SYMNDX_DATA	1#define SYMNDX_BSS	2  l = 0;  for (i = 0; i < ldhdr.l_nreloc; i++, l--, ldrel++)    {      if (l == 0) {	lseek (a_out,	       orig_load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i,	       0);	l = ldhdr.l_nreloc - i;	if (l > sizeof (ldrel_buf) / LDRELSZ)	  l = sizeof (ldrel_buf) / LDRELSZ;	if (read (a_out, ldrel_buf, l * LDRELSZ) != l * LDRELSZ)	  {	    PERROR (a_name);	  }	ldrel = ldrel_buf;      }      dirty = 0;      /* this code may not be necessary */      /* I originally had == in the "assignment" and it still unrelocated */      /* move the BSS loader symbols to the DATA segment */      if (ldrel->l_rsecnm == f_ohdr.o_snbss)	ldrel->l_rsecnm = f_ohdr.o_sndata, dirty++;      if (ldrel->l_symndx == SYMNDX_BSS)	ldrel->l_symndx = SYMNDX_DATA, dirty++;      if (dirty)	{	  lseek (new,		 load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i,		 0);	  if (write (new, ldrel, LDRELSZ) != LDRELSZ)	    {	      PERROR (new_name);	    }	}      if (ldrel->l_rsecnm == f_ohdr.o_sndata)	{	  int orig_int;	  lseek (a_out, orig_data_scnptr + ldrel->l_vaddr, 0);	  if (read (a_out, (void *) &orig_int, sizeof (orig_int)) != sizeof (orig_int))	    {	      PERROR (a_name);	    }	  switch (ldrel->l_symndx) {	  case SYMNDX_TEXT:	    p = (int *) (d_start + ldrel->l_vaddr);	    orig_int = * p - (t_start - f_ohdr.text_start);	    break;	  case SYMNDX_DATA:	  case SYMNDX_BSS:	    p = (int *) (d_start + ldrel->l_vaddr);	    orig_int = * p - (d_start - f_ohdr.data_start);	    break;	  }	  lseek (new, data_scnptr + ldrel->l_vaddr, 0);	  if (write (new, (void *) &orig_int, sizeof (orig_int)) != sizeof (orig_int))	    {	      PERROR (new_name);	    }	}    }}#endif /* XCOFF */#endif /* not CANNOT_UNEXEC */#endif /* not CANNOT_DUMP */

⌨️ 快捷键说明

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