?? archive.c
字號(hào):
char armag[SARMAG+1]; if (bfd_read ((PTR)armag, 1, SARMAG, abfd) != SARMAG) { bfd_error = wrong_format; return 0; }#ifdef GNU960 if (strncmp (armag, BFD_GNU960_ARMAG(abfd), SARMAG)) return 0;#else if (strncmp (armag, ARMAG, SARMAG) && strncmp (armag, ARMAGB, SARMAG)) return 0;#endif /* We are setting bfd_ardata(abfd) here, but since bfd_ardata involves a cast, we can't do it as the left operand of assignment. */ abfd->tdata.aout_ar_data = (struct artdata *) bfd_zalloc(abfd,sizeof (struct artdata)); if (bfd_ardata (abfd) == NULL) { bfd_error = no_memory; return 0; } bfd_ardata (abfd)->first_file_filepos = SARMAG; if (!BFD_SEND (abfd, _bfd_slurp_armap, (abfd))) { bfd_release(abfd, bfd_ardata (abfd)); abfd->tdata.aout_ar_data = NULL; return 0; } if (!BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd))) { bfd_release(abfd, bfd_ardata (abfd)); abfd->tdata.aout_ar_data = NULL; return 0; } return abfd->xvec;}/* Returns false on error, true otherwise */booleanbfd_slurp_bsd_armap (abfd) bfd *abfd;{ struct areltdata *mapdata; char nextname[17]; unsigned int counter = 0; int *raw_armap, *rbase; struct artdata *ardata = bfd_ardata (abfd); char *stringbase; /* FIXME, if the read fails, this routine quietly returns "true"!! It should probably do that if the read gives 0 bytes (empty archive), but fail for any other size... */ if (bfd_read ((PTR)nextname, 1, 16, abfd) == 16) { /* The archive has at least 16 bytes in it */ bfd_seek (abfd, (file_ptr) -16, SEEK_CUR); /* This should be using RANLIBMAG, but at least it can be grepped for in this comment. */ if (strncmp (nextname, "__.SYMDEF ", 16)) { bfd_has_map (abfd) = false; return true; } mapdata = snarf_ar_hdr (abfd); if (mapdata == NULL) return false; raw_armap = (int *) bfd_zalloc(abfd,mapdata->parsed_size); if (raw_armap == NULL) { bfd_error = no_memory; byebye: bfd_release (abfd, (PTR)mapdata); return false; } if (bfd_read ((PTR)raw_armap, 1, mapdata->parsed_size, abfd) != mapdata->parsed_size) { bfd_error = malformed_archive; byebyebye: bfd_release (abfd, (PTR)raw_armap); goto byebye; } ardata->symdef_count = bfd_h_get_32(abfd, (PTR)raw_armap) / sizeof (struct symdef); if (ardata->symdef_count * sizeof (struct symdef) > mapdata->parsed_size - sizeof (*raw_armap)) { /* Probably we're using the wrong byte ordering. */ bfd_error = wrong_format; goto byebyebye; } ardata->cache = 0; rbase = raw_armap+1; ardata->symdefs = (carsym *) rbase; stringbase = ((char *) (ardata->symdefs + ardata->symdef_count)) + 4; for (;counter < ardata->symdef_count; counter++) { struct symdef *sym = ((struct symdef *) rbase) + counter; sym->s.name = bfd_h_get_32(abfd, (PTR)(&(sym->s.string_offset))) + stringbase; sym->file_offset = bfd_h_get_32(abfd, (PTR)( &(sym->file_offset))); } ardata->first_file_filepos = bfd_tell (abfd); /* Pad to an even boundary if you have to */ ardata->first_file_filepos += (ardata-> first_file_filepos) %2; /* FIXME, we should provide some way to free raw_ardata when we are done using the strings from it. For now, it seems to be allocated on an obstack anyway... */ bfd_has_map (abfd) = true; } return true;}/* Returns false on error, true otherwise */booleanbfd_slurp_coff_armap (abfd) bfd *abfd;{ struct areltdata *mapdata; char nextname; int *raw_armap, *rawptr; struct artdata *ardata = bfd_ardata (abfd); char *stringbase; unsigned int stringsize; carsym *carsyms; int result; bfd_vma (*swap)(); result = bfd_read ((PTR)&nextname, 1, 1, abfd); bfd_seek (abfd, (file_ptr) -1, SEEK_CUR); if (result != 1 || nextname != '/') { /* Actually I think this is an error for a COFF archive */ bfd_has_map (abfd) = false; return true; } mapdata = snarf_ar_hdr (abfd); if (mapdata == NULL) return false; raw_armap = (int *) bfd_alloc(abfd,mapdata->parsed_size); if (raw_armap == NULL) { bfd_error = no_memory; byebye: bfd_release (abfd, (PTR)mapdata); return false; } /* read in the raw map */ if (bfd_read ((PTR)raw_armap, 1, mapdata->parsed_size, abfd) != mapdata->parsed_size) { bfd_error = malformed_archive; oops: bfd_release (abfd, (PTR)raw_armap); goto byebye; } /* The coff armap must be read sequentially. So we construct a bsd-style one in core all at once, for simplicity. It seems that all numeric information in a coff archive is always in big endian format, nomatter the host or target. */ stringsize = mapdata->parsed_size - (4 * (_do_getb32((PTR)raw_armap))) - 4; /* Except that some archive formats are broken, and it may be our fault - the i960 little endian coff sometimes has big and sometimes little, because our tools changed. Here's a horrible hack to clean up the crap */ swap = _do_getb32; if (stringsize > 0xfffff) { /* This looks dangerous, let's do it the other way around */ stringsize = mapdata->parsed_size - (4 * (_do_getl32((PTR)raw_armap))) - 4; swap = _do_getl32; } { unsigned int nsymz = swap( (PTR)raw_armap); unsigned int carsym_size = (nsymz * sizeof (carsym)); unsigned int ptrsize = (4 * nsymz); unsigned int i; ardata->symdefs = (carsym *) bfd_zalloc(abfd,carsym_size + stringsize + 1); if (ardata->symdefs == NULL) { bfd_error = no_memory; goto oops; } carsyms = ardata->symdefs; stringbase = ((char *) ardata->symdefs) + carsym_size; memcpy (stringbase, (char*)raw_armap + ptrsize + 4, stringsize); /* OK, build the carsyms */ for (i = 0; i < nsymz; i++) { rawptr = raw_armap + i + 1; carsyms->file_offset = swap((PTR)rawptr); carsyms->name = stringbase; for (; *(stringbase++);); carsyms++; } *stringbase = 0; } ardata->symdef_count = swap((PTR)raw_armap); ardata->first_file_filepos = bfd_tell (abfd); /* Pad to an even boundary if you have to */ ardata->first_file_filepos += (ardata->first_file_filepos) %2; /* We'd like to release these allocations, but we have allocated stuff since then (using the same obstack, if bfd_release is obstack based). So they will stick around until the BFD is closed. */ /* bfd_release (abfd, (PTR)raw_armap); bfd_release (abfd, (PTR)mapdata); */ bfd_has_map (abfd) = true; return true;}/** Extended name table. Normally archives support only 14-character filenames. Intel has extended the format: longer names are stored in a special element (the first in the archive, or second if there is an armap); the name in the ar_hdr is replaced by <space><index into filename element>. Index is the P.R. of an int (decimal). Data General have extended the format by using the prefix // for the special element *//* Returns false on error, true otherwise */boolean_bfd_slurp_extended_name_table (abfd) bfd *abfd;{ char nextname[17]; struct areltdata *namedata; /* FIXME: Formatting sucks here, and in case of failure of BFD_READ, we probably don't want to return true. */ if (bfd_read ((PTR)nextname, 1, 16, abfd) == 16) { bfd_seek (abfd, (file_ptr) -16, SEEK_CUR); if (strncmp (nextname, "ARFILENAMES/ ", 16) != 0 && strncmp (nextname, "// ", 16) != 0) { bfd_ardata (abfd)->extended_names = NULL; return true; } namedata = snarf_ar_hdr (abfd); if (namedata == NULL) return false; bfd_ardata (abfd)->extended_names = bfd_zalloc(abfd,namedata->parsed_size); if (bfd_ardata (abfd)->extended_names == NULL) { bfd_error = no_memory; byebye: bfd_release (abfd, (PTR)namedata); return false; } if (bfd_read ((PTR)bfd_ardata (abfd)->extended_names, 1, namedata->parsed_size, abfd) != namedata->parsed_size) { bfd_error = malformed_archive; bfd_release (abfd, (PTR)(bfd_ardata (abfd)->extended_names)); bfd_ardata (abfd)->extended_names = NULL; goto byebye; } /* Since the archive is supposed to be printable if it contains text, the entries in the list are newline-padded, not null padded. We'll fix that there.. */ { char *temp = bfd_ardata (abfd)->extended_names; for (; *temp != '\0'; ++temp) if (*temp == '\n') *temp = '\0'; } /* Pad to an even boundary if you have to */ bfd_ardata (abfd)->first_file_filepos = bfd_tell (abfd); bfd_ardata (abfd)->first_file_filepos += (bfd_ardata (abfd)->first_file_filepos) %2; /* FIXME, we can't release namedata here because it was allocated below extended_names on the obstack... */ /* bfd_release (abfd, namedata); */ } return true;}#ifdef VMS/* Return a copy of the stuff in the filename between any :]> and a semicolon */static CONST char *DEFUN(normalize,(file), CONST char *file){ CONST char *first; CONST char *last; char *copy; first = file + strlen(file)-1; last = first+1; while (first != file) { if (*first == ';') last = first; if (*first == ':' || *first == ']' ||*first == '>') { first++; break; } first --; } copy = malloc(last - first + 1); memcpy(copy, first, last-first); copy[last-first] = 0; return copy;}#elsestaticCONST char *normalize(file)CONST char *file;{ CONST char * filename = strrchr(file, '/'); if (filename != (char *)NULL) { filename ++; } else { filename = file; } return filename;}#endif/* Follows archive_head and produces an extended name table if necessary. Returns (in tabloc) a pointer to an extended name table, and in tablen the length of the table. If it makes an entry it clobbers the filename so that the element may be written without further massage. Returns true if it ran successfully, false if something went wrong. A successful return may still involve a zero-length tablen! */booleanbfd_construct_extended_name_table (abfd, tabloc, tablen) bfd *abfd; char **tabloc; unsigned int *tablen;{ unsigned int maxname = abfd->xvec->ar_max_namelen; unsigned int total_namelen = 0; bfd *current; char *strptr; *tablen = 0; /* Figure out how long the table should be */ for (current = abfd->archive_head; current != NULL; current = current->next){ unsigned int thislen = strlen (normalize(current->filename)); if (thislen > maxname) total_namelen += thislen + 1; /* leave room for \n */ } if (total_namelen == 0) return true; *tabloc = bfd_zalloc (abfd,total_namelen); if (*tabloc == NULL) { bfd_error = no_memory; return false; } *tablen = total_namelen; strptr = *tabloc; for (current = abfd->archive_head; current != NULL; current = current->next) { CONST char *normal =normalize( current->filename); unsigned int thislen = strlen (normal); if (thislen > maxname) { /* Works for now; may need to be re-engineered if we encounter an oddball archive format and want to generalise this hack. */ struct ar_hdr *hdr = arch_hdr(current); strcpy (strptr, normal); strptr[thislen] = '\n'; hdr->ar_name[0] = ' '; /* We know there will always be enough room (one of the few cases where you may safely use sprintf). */ sprintf ((hdr->ar_name) + 1, "%-d", (unsigned) (strptr - *tabloc)); /* Kinda Kludgy. We should just use the returned value of sprintf but not all implementations get this right */ { char *temp = hdr->ar_name +2; for (; temp < hdr->ar_name + maxname; temp++) if (*temp == '\0') *temp = ' '; } strptr += thislen + 1; } } return true;}/** A couple of functions for creating ar_hdrs *//* Takes a filename, returns an arelt_data for it, or NULL if it can't make one. The filename must refer to a filename in the filesystem. The filename field of the ar_hdr will NOT be initialized*/struct areltdata *DEFUN(bfd_ar_hdr_from_filesystem, (abfd,filename), bfd* abfd AND CONST char *filename){ struct stat status; struct areltdata *ared; struct ar_hdr *hdr; char *temp, *temp1; if (stat (filename, &status) != 0) { bfd_error = system_call_error; return NULL; } ared = (struct areltdata *) bfd_zalloc(abfd, sizeof (struct ar_hdr) + sizeof (struct areltdata)); if (ared == NULL) { bfd_error = no_memory; return NULL; } hdr = (struct ar_hdr *) (((char *) ared) + sizeof (struct areltdata)); /* ar headers are space padded, not null padded! */ temp = (char *) hdr; temp1 = temp + sizeof (struct ar_hdr) - 2; for (; temp < temp1; *(temp++) = ' '); strncpy (hdr->ar_fmag, ARFMAG, 2); /* Goddamned sprintf doesn't permit MAXIMUM field lengths */ sprintf ((hdr->ar_date), "%-12ld", status.st_mtime); sprintf ((hdr->ar_uid), "%d", status.st_uid); sprintf ((hdr->ar_gid), "%d", status.st_gid); sprintf ((hdr->ar_mode), "%-8o", (unsigned) status.st_mode); sprintf ((hdr->ar_size), "%-10ld", status.st_size); /* Correct for a lossage in sprintf whereby it null-terminates. I cannot understand how these C losers could design such a ramshackle bunch of IO operations */ temp = (char *) hdr; temp1 = temp + sizeof (struct ar_hdr) - 2; for (; temp < temp1; temp++) { if (*temp == '\0') *temp = ' '; } strncpy (hdr->ar_fmag, ARFMAG, 2); ared->parsed_size = status.st_size; ared->arch_header = (char *) hdr; return ared;}/* This is magic required by the "ar" program. Since it's undocumented, it's undocumented. You may think that it would take a strong stomach to write this, and it does, but it takes even a stronger stomach to try to code around such a thing!*/struct ar_hdr *DEFUN(bfd_special_undocumented_glue, (abfd, filename), bfd *abfd AND char *filename){ struct areltdata *ar_elt = bfd_ar_hdr_from_filesystem (abfd, filename); if (ar_elt == NULL) return NULL; return (struct ar_hdr *) ar_elt->arch_header;}/* Analogous to stat call */intbfd_generic_stat_arch_elt (abfd, buf) bfd *abfd; struct stat *buf;{ struct ar_hdr *hdr; char *aloser; if (abfd->arelt_data == NULL) {
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -