archive.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,234 行 · 第 1/5 页
C
2,234 行
errno = 0; if (bfd_read (buffer, amt, 1, current) != amt) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_malformed_archive); return false; } if (bfd_write (buffer, amt, 1, arch) != amt) return false; remaining -= amt; } if ((arelt_size (current) % 2) == 1) { if (bfd_write ("\012", 1, 1, arch) != 1) return false; } } if (makemap && hasobjects) { /* Verify the timestamp in the archive file. If it would not be accepted by the linker, rewrite it until it would be. If anything odd happens, break out and just return. (The Berkeley linker checks the timestamp and refuses to read the table-of-contents if it is >60 seconds less than the file's modified-time. That painful hack requires this painful hack. */ tries = 1; do { if (bfd_update_armap_timestamp (arch)) break; (*_bfd_error_handler) (_("Warning: writing archive was slow: rewriting timestamp\n")); } while (++tries < 6); } return true;}/* Note that the namidx for the first symbol is 0. */boolean_bfd_compute_and_write_armap (arch, elength) bfd *arch; unsigned int elength;{ char *first_name = NULL; bfd *current; file_ptr elt_no = 0; struct orl *map = NULL; int orl_max = 1024; /* fine initial default */ int orl_count = 0; int stridx = 0; /* string index */ asymbol **syms = NULL; long syms_max = 0; boolean ret; /* 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_malloc (orl_max * sizeof (struct orl)); if (map == NULL) goto error_return; /* We put the symbol names on the arch objalloc, and then discard them when done. */ first_name = bfd_alloc (arch, 1); if (first_name == NULL) goto error_return; /* 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))) { long storage; long symcount; long src_count; storage = bfd_get_symtab_upper_bound (current); if (storage < 0) goto error_return; if (storage != 0) { if (storage > syms_max) { if (syms_max > 0) free (syms); syms_max = storage; syms = (asymbol **) bfd_malloc ((size_t) syms_max); if (syms == NULL) goto error_return; } symcount = bfd_canonicalize_symtab (current, syms); if (symcount < 0) goto error_return; /* 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_WEAK || flags & BSF_INDIRECT || bfd_is_com_section (sec)) && ! bfd_is_und_section (sec)) { size_t namelen; struct orl *new_map; /* This symbol will go into the archive header. */ if (orl_count == orl_max) { orl_max *= 2; new_map = ((struct orl *) bfd_realloc (map, orl_max * sizeof (struct orl))); if (new_map == (struct orl *) NULL) goto error_return; map = new_map; } namelen = strlen (syms[src_count]->name); map[orl_count].name = ((char **) bfd_alloc (arch, sizeof (char *))); if (map[orl_count].name == NULL) goto error_return; *(map[orl_count].name) = bfd_alloc (arch, namelen + 1); if (*(map[orl_count].name) == NULL) goto error_return; strcpy (*(map[orl_count].name), syms[src_count]->name); (map[orl_count]).pos = (file_ptr) current; (map[orl_count]).namidx = stridx; stridx += namelen + 1; ++orl_count; } } } /* Now ask the BFD to free up any cached information, so we don't fill all of memory with symbol tables. */ if (! bfd_free_cached_info (current)) goto error_return; } } /* OK, now we have collected all the data, let's write them out. */ ret = BFD_SEND (arch, write_armap, (arch, elength, map, orl_count, stridx)); if (syms_max > 0) free (syms); if (map != NULL) free (map); if (first_name != NULL) bfd_release (arch, first_name); return ret; error_return: if (syms_max > 0) free (syms); if (map != NULL) free (map); if (first_name != NULL) bfd_release (arch, first_name); return false;}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 * BSD_SYMDEF_SIZE; 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 */ bfd_byte temp[4]; unsigned 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); /* Remember the timestamp, to keep it holy. But fudge it a little. */ bfd_ardata (arch)->armap_timestamp = statbuf.st_mtime + ARMAP_TIME_OFFSET; bfd_ardata (arch)->armap_datepos = (SARMAG + offsetof (struct ar_hdr, ar_date[0])); sprintf (hdr.ar_date, "%ld", bfd_ardata (arch)->armap_timestamp); sprintf (hdr.ar_uid, "%ld", (long) getuid ()); sprintf (hdr.ar_gid, "%ld", (long) getgid ()); sprintf (hdr.ar_size, "%-10d", (int) mapsize); strncpy (hdr.ar_fmag, ARFMAG, 2); for (i = 0; i < sizeof (struct ar_hdr); i++) if (((char *) (&hdr))[i] == '\0') (((char *) (&hdr))[i]) = ' '; if (bfd_write ((char *) &hdr, 1, sizeof (struct ar_hdr), arch) != sizeof (struct ar_hdr)) return false; bfd_h_put_32 (arch, (bfd_vma) ranlibsize, temp); if (bfd_write (temp, 1, sizeof (temp), arch) != sizeof (temp)) return false; for (count = 0; count < orl_count; count++) { bfd_byte buf[BSD_SYMDEF_SIZE]; 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, buf); bfd_h_put_32 (arch, firstreal, buf + BSD_SYMDEF_OFFSET_SIZE); if (bfd_write (buf, BSD_SYMDEF_SIZE, 1, arch) != BSD_SYMDEF_SIZE) return false; } /* Now write the strings themselves. */ bfd_h_put_32 (arch, stringsize, temp); if (bfd_write (temp, 1, sizeof (temp), arch) != sizeof (temp)) return false; for (count = 0; count < orl_count; count++) { size_t len = strlen (*map[count].name) + 1; if (bfd_write (*map[count].name, 1, len, arch) != len) return false; } /* 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) { if (bfd_write ("", 1, 1, arch) != 1) return false; } return true;}/* At the end of archive file handling, update the timestamp in the file, so the linker will accept it. Return true if the timestamp was OK, or an unusual problem happened. Return false if we updated the timestamp. */boolean_bfd_archive_bsd_update_armap_timestamp (arch) bfd *arch;{ struct stat archstat; struct ar_hdr hdr; unsigned int i; /* Flush writes, get last-write timestamp from file, and compare it to the timestamp IN the file. */ bfd_flush (arch); if (bfd_stat (arch, &archstat) == -1) { perror (_("Reading archive file mod timestamp")); /* Can't read mod time for some reason. */ return true; } if (archstat.st_mtime <= bfd_ardata (arch)->armap_timestamp) /* OK by the linker's rules. */ return true; /* Update the timestamp. */ bfd_ardata (arch)->armap_timestamp = archstat.st_mtime + ARMAP_TIME_OFFSET; /* Prepare an ASCII version suitable for writing. */ memset (hdr.ar_date, 0, sizeof (hdr.ar_date)); sprintf (hdr.ar_date, "%ld", bfd_ardata (arch)->armap_timestamp); for (i = 0; i < sizeof (hdr.ar_date); i++) if (hdr.ar_date[i] == '\0') (hdr.ar_date)[i] = ' '; /* Write it into the file. */ bfd_ardata (arch)->armap_datepos = (SARMAG + offsetof (struct ar_hdr, ar_date[0])); if (bfd_seek (arch, bfd_ardata (arch)->armap_datepos, SEEK_SET) != 0 || (bfd_write (hdr.ar_date, sizeof (hdr.ar_date), 1, arch) != sizeof (hdr.ar_date))) { /* FIXME: bfd can't call perror. */ perror (_("Writing updated armap timestamp")); /* Some error while writing. */ return true; } /* We updated the timestamp successfully. */ return false;}/* 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; unsigned 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); strncpy (hdr.ar_fmag, ARFMAG, 2); 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. */ if (bfd_write ((PTR) &hdr, 1, sizeof (struct ar_hdr), arch) != sizeof (struct ar_hdr)) return false; 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 (count < symbol_count && ((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++) { size_t len = strlen (*map[count].name) + 1; if (bfd_write (*map[count].name, 1, len, arch) != len) return false; } /* The spec sez this should be a newline. But in order to be bug-compatible for arc960 we use a null. */ if (padit) { if (bfd_write ("", 1, 1, arch) != 1) return false; } return true;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?