📄 archive.c
字号:
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 + -