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

📄 archive.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
    bfd_error = invalid_operation;    return -1;  }      hdr = arch_hdr (abfd);#define foo(arelt, stelt, size)  \  buf->stelt = strtol (hdr->arelt, &aloser, size); \  if (aloser == hdr->arelt) return -1;    foo (ar_date, st_mtime, 10);  foo (ar_uid, st_uid, 10);  foo (ar_gid, st_gid, 10);  foo (ar_mode, st_mode, 8);  foo (ar_size, st_size, 10);  return 0;}voidbfd_dont_truncate_arname (abfd, pathname, arhdr)     bfd *abfd;     CONST char *pathname;     char *arhdr;{  /* FIXME: This interacts unpleasantly with ar's quick-append option.     Fortunately ic960 users will never use that option.  Fixing this     is very hard; fortunately I know how to do it and will do so once     intel's release is out the door. */     struct ar_hdr *hdr = (struct ar_hdr *) arhdr;  int length;  CONST char *filename = normalize(pathname);  int maxlen = ar_maxnamelen (abfd);  length = strlen (filename);  if (length <= maxlen)    memcpy (hdr->ar_name, filename, length);  if (length < maxlen) (hdr->ar_name)[length] = ar_padchar (abfd);  return;}voidbfd_bsd_truncate_arname (abfd, pathname, arhdr)     bfd *abfd;     CONST char *pathname;     char *arhdr;{  struct ar_hdr *hdr = (struct ar_hdr *) arhdr;  int length;  CONST char *filename = strrchr (pathname, '/');  int maxlen = ar_maxnamelen (abfd);  if (filename == NULL)    filename = pathname;  else    ++filename;  length = strlen (filename);  if (length <= maxlen)    memcpy (hdr->ar_name, filename, length);  else {    /* pathname: meet procrustes */    memcpy (hdr->ar_name, filename, maxlen);    length = maxlen;  }  if (length < maxlen) (hdr->ar_name)[length] = ar_padchar (abfd);}/* Store name into ar header.  Truncates the name to fit.   1> strip pathname to be just the basename.   2> if it's short enuf to fit, stuff it in.   3> If it doesn't end with .o, truncate it to fit   4> truncate it before the .o, append .o, stuff THAT in.*//* This is what gnu ar does.  It's better but incompatible with the bsd ar. */voidbfd_gnu_truncate_arname (abfd, pathname, arhdr)     bfd *abfd;     CONST char *pathname;     char *arhdr;{  struct ar_hdr *hdr = (struct ar_hdr *) arhdr;  int length;  CONST char *filename = strrchr (pathname, '/');  int maxlen = ar_maxnamelen (abfd);	  if (filename == NULL)    filename = pathname;  else    ++filename;  length = strlen (filename);  if (length <= maxlen)    memcpy (hdr->ar_name, filename, length);  else {			/* pathname: meet procrustes */    memcpy (hdr->ar_name, filename, maxlen);    if ((filename[length - 2] == '.') && (filename[length - 1] == 'o')) {      hdr->ar_name[maxlen - 2] = '.';      hdr->ar_name[maxlen - 1] = 'o';    }    length = maxlen;  }  if (length < 16) (hdr->ar_name)[length] = ar_padchar (abfd);}PROTO (boolean, compute_and_write_armap, (bfd *arch, unsigned int elength));/* The BFD is open for write and has its format set to bfd_archive */boolean_bfd_write_archive_contents (arch)     bfd *arch;{  bfd *current;  char *etable = NULL;  unsigned int elength = 0;  boolean makemap = bfd_has_map (arch);  boolean hasobjects = false;	/* if no .o's, don't bother to make a map */  unsigned int i;  /* Verify the viability of all entries; if any of them live in the     filesystem (as opposed to living in an archive open for input)     then construct a fresh ar_hdr for them.     */  for (current = arch->archive_head; current; current = current->next) {    if (bfd_write_p (current)) {      bfd_error = invalid_operation;      return false;    }    if (!current->arelt_data) {      current->arelt_data =	  (PTR) bfd_ar_hdr_from_filesystem (arch, current->filename);      if (!current->arelt_data) return false;      /* Put in the file name */        BFD_SEND (arch, _bfd_truncate_arname,(arch, 					  current->filename,					 (char *) arch_hdr(current)));          }    if (makemap) {		/* don't bother if we won't make a map! */      if ((bfd_check_format (current, bfd_object))#if 0				/* FIXME -- these are not set correctly */	  && ((bfd_get_file_flags (current) & HAS_SYMS))#endif	  )	hasobjects = true;    }  }  if (!bfd_construct_extended_name_table (arch, &etable, &elength))    return false;  bfd_seek (arch, (file_ptr) 0, SEEK_SET);#ifdef GNU960  bfd_write (BFD_GNU960_ARMAG(arch), 1, SARMAG, arch);#else  bfd_write (ARMAG, 1, SARMAG, arch);#endif  if (makemap && hasobjects) {    if (compute_and_write_armap (arch, elength) != true) {      return false;    }  }  if (elength != 0) {    struct ar_hdr hdr;    memset ((char *)(&hdr), 0, sizeof (struct ar_hdr));    sprintf (&(hdr.ar_name[0]), "ARFILENAMES/");    sprintf (&(hdr.ar_size[0]), "%-10d", (int) elength);    hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n';    for (i = 0; i < sizeof (struct ar_hdr); i++)      if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';    bfd_write ((char *)&hdr, 1, sizeof (struct ar_hdr), arch);    bfd_write (etable, 1, elength, arch);    if ((elength % 2) == 1) bfd_write ("\n", 1, 1, arch);  }  for (current = arch->archive_head; current; current = current->next) {    char buffer[DEFAULT_BUFFERSIZE];    unsigned int remaining = arelt_size (current);    struct ar_hdr *hdr = arch_hdr(current);    /* write ar header */    if (bfd_write ((char *)hdr, 1, sizeof(*hdr), arch) != sizeof(*hdr)) {    syserr:	bfd_error = system_call_error;	return false;      }    if (bfd_seek (current, (file_ptr) 0, SEEK_SET) != 0) goto syserr;    while (remaining) 	{	  unsigned int amt = DEFAULT_BUFFERSIZE;	  if (amt > remaining) {	    amt = remaining;	  }	  errno = 0;	  if (bfd_read (buffer, amt, 1, current) != amt) {	      if (errno) goto syserr;	      /* Looks like a truncated archive. */	      bfd_error = malformed_archive;	      return false;	  }	  if (bfd_write (buffer, amt, 1, arch)   != amt) goto syserr;	  remaining -= amt;	}    if ((arelt_size (current) % 2) == 1) bfd_write ("\n", 1, 1, arch);  }return true;}/* Note that the namidx for the first symbol is 0 */booleancompute_and_write_armap (arch, elength)     bfd *arch;     unsigned int elength;{    bfd *current;    file_ptr elt_no = 0;    struct orl *map;    int orl_max = 15000;	/* fine initial default */    int orl_count = 0;    int stridx = 0;		/* string index */    /* Dunno if this is the best place for this info... */    if (elength != 0) elength += sizeof (struct ar_hdr);    elength += elength %2 ;    map = (struct orl *) bfd_zalloc (arch,orl_max * sizeof (struct orl));    if (map == NULL) {	    bfd_error = no_memory;	    return false;	}    /* Drop all the files called __.SYMDEF, we're going to make our       own */    while (arch->archive_head   &&	   strcmp(arch->archive_head->filename,"__.SYMDEF") == 0)     {	arch->archive_head = arch->archive_head->next;    }    /* Map over each element */    for (current = arch->archive_head;	 current != (bfd *)NULL;	 current = current->next, elt_no++)     {	if ((bfd_check_format (current, bfd_object) == true)	    && ((bfd_get_file_flags (current) & HAS_SYMS))) {		asymbol **syms;		unsigned int storage;		unsigned int symcount;		unsigned int src_count;		storage = get_symtab_upper_bound (current);		if (storage != 0) {			syms = (asymbol **) bfd_zalloc (arch,storage);			if (syms == NULL) {				bfd_error = no_memory; /* FIXME -- memory leak */				return false;			    }			symcount = bfd_canonicalize_symtab (current, syms);			/* Now map over all the symbols, picking out the ones we want */			for (src_count = 0; src_count <symcount; src_count++) {				flagword flags =				 (syms[src_count])->flags;				asection  *sec =				 syms[src_count]->section;								if ((flags & BSF_GLOBAL) ||				    (flags & BSF_INDIRECT) ||				    (sec == &bfd_com_section)) {					/* This symbol will go into the archive header */					if (orl_count == orl_max) 					{					    orl_max *= 2;					    map = (struct orl *) bfd_realloc (arch, (char *) map,									      orl_max * sizeof (struct orl));					}					(map[orl_count]).name = (char **) &((syms[src_count])->name);					(map[orl_count]).pos = (file_ptr) current;					(map[orl_count]).namidx = stridx;					stridx += strlen ((syms[src_count])->name) + 1;					++orl_count;				    }			    }		    }	    }    }    /* OK, now we have collected all the data, let's write them out */    if (!BFD_SEND (arch, write_armap,		   (arch, elength, map, orl_count, stridx))) {	    return false;	}    return true;}booleanbsd_write_armap (arch, elength, map, orl_count, stridx)     bfd *arch;     unsigned int elength;     struct orl *map;     unsigned int orl_count;     int stridx;{  int padit = stridx & 1;  unsigned int ranlibsize = orl_count * sizeof (struct ranlib);  unsigned int stringsize = stridx + padit;  /* Include 8 bytes to store ranlibsize and stringsize in output. */  unsigned int mapsize = ranlibsize + stringsize + 8;  file_ptr firstreal;  bfd *current = arch->archive_head;  bfd *last_elt = current;	/* last element arch seen */  int temp;  int count;  struct ar_hdr hdr;  struct stat statbuf;  unsigned int i;  firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG;  stat (arch->filename, &statbuf);  memset ((char *)(&hdr), 0, sizeof (struct ar_hdr));  sprintf (hdr.ar_name, RANLIBMAG);  /* write the timestamp of the archive header to be just a little bit     later than the timestamp of the file, otherwise the linker will     complain that the index is out of date.     */  sprintf (hdr.ar_date, "%ld", statbuf.st_mtime + 60);    sprintf (hdr.ar_uid, "%d", getuid());  sprintf (hdr.ar_gid, "%d", getgid());  sprintf (hdr.ar_size, "%-10d", (int) mapsize);  hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n';  for (i = 0; i < sizeof (struct ar_hdr); i++)   if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';  bfd_write ((char *)&hdr, 1, sizeof (struct ar_hdr), arch);  bfd_h_put_32(arch, ranlibsize, (PTR)&temp);  bfd_write (&temp, 1, sizeof (temp), arch);    for (count = 0; count < orl_count; count++) {    struct symdef outs;    struct symdef *outp = &outs;        if (((bfd *)(map[count]).pos) != last_elt) {      do {	firstreal += arelt_size (current) + sizeof (struct ar_hdr);	firstreal += firstreal % 2;	current = current->next;      } while (current != (bfd *)(map[count]).pos);    }				/* if new archive element */    last_elt = current;    bfd_h_put_32(arch, ((map[count]).namidx),(PTR) &outs.s.string_offset);    bfd_h_put_32(arch, firstreal,(PTR) &outs.file_offset);    bfd_write ((char *)outp, 1, sizeof (outs), arch);  }  /* now write the strings themselves */  bfd_h_put_32(arch, stringsize, (PTR)&temp);  bfd_write ((PTR)&temp, 1, sizeof (temp), arch);  for (count = 0; count < orl_count; count++)   bfd_write (*((map[count]).name), 1, strlen (*((map[count]).name))+1, arch);  /* The spec sez this should be a newline.  But in order to be     bug-compatible for sun's ar we use a null. */  if (padit)   bfd_write("\0",1,1,arch);  return true;}/* A coff armap looks like : lARMAG struct ar_hdr with name = '/'  number of symbols offset of file for symbol 0 offset of file for symbol 1 offset of file for symbol n-1 symbol name 0 symbol name 1	  symbol name n-1*/booleancoff_write_armap (arch, elength, map, symbol_count, stridx)     bfd *arch;     unsigned int elength;     struct orl *map;     unsigned int symbol_count;     int stridx;{    /* The size of the ranlib is the number of exported symbols in the       archive * the number of bytes in a int, + an int for the count */    unsigned int ranlibsize = (symbol_count * 4) + 4;    unsigned int stringsize = stridx;    unsigned int mapsize = stringsize + ranlibsize;    file_ptr archive_member_file_ptr;    bfd *current = arch->archive_head;    int count;    struct ar_hdr hdr;    unsigned int i;    int padit = mapsize & 1;      if (padit) mapsize ++;    /* work out where the first object file will go in the archive */    archive_member_file_ptr =   mapsize + elength + sizeof (struct ar_hdr) + SARMAG;    memset ((char *)(&hdr), 0, sizeof (struct ar_hdr));    hdr.ar_name[0] = '/';    sprintf (hdr.ar_size, "%-10d", (int) mapsize);    sprintf (hdr.ar_date, "%ld", (long)time (NULL));    /* This, at least, is what Intel coff sets the values to.: */    sprintf ((hdr.ar_uid), "%d", 0);    sprintf ((hdr.ar_gid), "%d", 0);    sprintf ((hdr.ar_mode), "%-7o",(unsigned ) 0);    hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n';    for (i = 0; i < sizeof (struct ar_hdr); i++)     if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';    /* Write the ar header for this item and the number of symbols */      bfd_write ((PTR)&hdr, 1, sizeof (struct ar_hdr), arch);    bfd_write_bigendian_4byte_int(arch, symbol_count);    /* Two passes, first write the file offsets for each symbol -       remembering that each offset is on a two byte boundary.  */    /* Write out the file offset for the file associated with each       symbol, and remember to keep the offsets padded out.  */    current = arch->archive_head;    count = 0;    while (current != (bfd *)NULL && count < symbol_count) {	/* For each symbol which is used defined in this object, write out	   the object file's address in the archive */    	while (((bfd *)(map[count]).pos) == current) {	    bfd_write_bigendian_4byte_int(arch, archive_member_file_ptr);	    count++;	}	/* Add size of this archive entry */	archive_member_file_ptr += arelt_size (current) + sizeof (struct								  ar_hdr);	/* remember aboout the even alignment */	archive_member_file_ptr += archive_member_file_ptr % 2;	current = current->next;    }      /* now write the strings themselves */    for (count = 0; count < symbol_count; count++) {	bfd_write ((PTR)*((map[count]).name),		   1,		   strlen (*((map[count]).name))+1, arch);    }    /* The spec sez this should be a newline.  But in order to be       bug-compatible for arc960 we use a null. */    if (padit)     bfd_write("\0",1,1,arch);    return true;}

⌨️ 快捷键说明

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