archive.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,234 行 · 第 1/5 页
C
2,234 行
e = memchr (hdr.ar_name, '/', ar_maxnamelen (abfd)); if (e == NULL) e = memchr (hdr.ar_name, ' ', ar_maxnamelen (abfd)); } if (e != NULL) namelen = e - hdr.ar_name; else { /* If we didn't find a termination character, then the name must be the entire field. */ namelen = ar_maxnamelen (abfd); } allocsize += namelen + 1; } if (!allocptr) { allocptr = bfd_zalloc (abfd, allocsize); if (allocptr == NULL) return NULL; } ared = (struct areltdata *) allocptr; ared->arch_header = allocptr + sizeof (struct areltdata); memcpy ((char *) ared->arch_header, (char *) &hdr, sizeof (struct ar_hdr)); ared->parsed_size = parsed_size; if (filename != NULL) ared->filename = filename; else { ared->filename = allocptr + (sizeof (struct areltdata) + sizeof (struct ar_hdr)); if (namelen) memcpy (ared->filename, hdr.ar_name, namelen); ared->filename[namelen] = '\0'; } return (PTR) ared;}/* This is an internal function; it's mainly used when indexing through the archive symbol table, but also used to get the next element, since it handles the bookkeeping so nicely for us. */bfd *_bfd_get_elt_at_filepos (archive, filepos) bfd *archive; file_ptr filepos;{ struct areltdata *new_areldata; bfd *n_nfd; n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos); if (n_nfd) return n_nfd; if (0 > bfd_seek (archive, filepos, SEEK_SET)) return NULL; if ((new_areldata = (struct areltdata *) _bfd_read_ar_hdr (archive)) == NULL) return NULL; n_nfd = _bfd_create_empty_archive_element_shell (archive); if (n_nfd == NULL) { bfd_release (archive, (PTR) new_areldata); return NULL; } n_nfd->origin = bfd_tell (archive); n_nfd->arelt_data = (PTR) new_areldata; n_nfd->filename = new_areldata->filename; if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd)) return n_nfd; /* Huh? */ bfd_release (archive, (PTR) n_nfd); bfd_release (archive, (PTR) new_areldata); return NULL;}/* Return the BFD which is referenced by the symbol in ABFD indexed by INDEX. INDEX should have been returned by bfd_get_next_mapent. */bfd *_bfd_generic_get_elt_at_index (abfd, index) bfd *abfd; symindex index;{ carsym *entry; entry = bfd_ardata (abfd)->symdefs + index; return _bfd_get_elt_at_filepos (abfd, entry->file_offset);}/*FUNCTION bfd_openr_next_archived_fileSYNOPSIS bfd *bfd_openr_next_archived_file(bfd *archive, bfd *previous);DESCRIPTION Provided a BFD, @var{archive}, containing an archive and NULL, open an input BFD on the first contained element and returns that. Subsequent calls should pass the archive and the previous return value to return a created BFD to the next contained element. NULL is returned when there are no more.*/bfd *bfd_openr_next_archived_file (archive, last_file) bfd *archive; bfd *last_file;{ if ((bfd_get_format (archive) != bfd_archive) || (archive->direction == write_direction)) { bfd_set_error (bfd_error_invalid_operation); return NULL; } return BFD_SEND (archive, openr_next_archived_file, (archive, last_file));}bfd *bfd_generic_openr_next_archived_file (archive, last_file) bfd *archive; bfd *last_file;{ file_ptr filestart; if (!last_file) filestart = bfd_ardata (archive)->first_file_filepos; else { unsigned int size = arelt_size (last_file); /* Pad to an even boundary... Note that last_file->origin can be odd in the case of BSD-4.4-style element with a long odd size. */ filestart = last_file->origin + size; filestart += filestart % 2; } return _bfd_get_elt_at_filepos (archive, filestart);}const bfd_target *bfd_generic_archive_p (abfd) bfd *abfd;{ struct artdata *tdata_hold; char armag[SARMAG + 1]; tdata_hold = abfd->tdata.aout_ar_data; if (bfd_read ((PTR) armag, 1, SARMAG, abfd) != SARMAG) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_wrong_format); return NULL; }#ifdef GNU960 if (strncmp (armag, BFD_GNU960_ARMAG (abfd), SARMAG) != 0) return 0;#else if (strncmp (armag, ARMAG, SARMAG) != 0 && strncmp (armag, ARMAGB, SARMAG) != 0) 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) return NULL; bfd_ardata (abfd)->first_file_filepos = SARMAG; bfd_ardata (abfd)->cache = NULL; bfd_ardata (abfd)->archive_head = NULL; bfd_ardata (abfd)->symdefs = NULL; bfd_ardata (abfd)->extended_names = NULL; bfd_ardata (abfd)->tdata = NULL; if (!BFD_SEND (abfd, _bfd_slurp_armap, (abfd))) { bfd_release (abfd, bfd_ardata (abfd)); abfd->tdata.aout_ar_data = tdata_hold; if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_wrong_format); return NULL; } if (!BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd))) { bfd_release (abfd, bfd_ardata (abfd)); abfd->tdata.aout_ar_data = tdata_hold; if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_wrong_format); return NULL; } if (bfd_has_map (abfd)) { bfd *first; /* This archive has a map, so we may presume that the contents are object files. Make sure that if the first file in the archive can be recognized as an object file, it is for this target. If not, assume that this is the wrong format. If the first file is not an object file, somebody is doing something weird, and we permit it so that ar -t will work. This is done because any normal format will recognize any normal archive, regardless of the format of the object files. We do accept an empty archive. */ first = bfd_openr_next_archived_file (abfd, (bfd *) NULL); if (first != NULL) { boolean fail; first->target_defaulted = false; fail = false; if (bfd_check_format (first, bfd_object) && first->xvec != abfd->xvec) { (void) bfd_close (first); bfd_release (abfd, bfd_ardata (abfd)); abfd->tdata.aout_ar_data = tdata_hold; bfd_set_error (bfd_error_wrong_format); return NULL; } /* We ought to close first here, but we can't, because we have no way to remove it from the archive cache. FIXME. */ } } return abfd->xvec;}/* Some constants for a 32 bit BSD archive structure. We do not support 64 bit archives presently; so far as I know, none actually exist. Supporting them would require changing these constants, and changing some bfd_h_get_32 to bfd_h_get_64. *//* The size of an external symdef structure. */#define BSD_SYMDEF_SIZE 8/* The offset from the start of a symdef structure to the file offset. */#define BSD_SYMDEF_OFFSET_SIZE 4/* The size of the symdef count. */#define BSD_SYMDEF_COUNT_SIZE 4/* The size of the string count. */#define BSD_STRING_COUNT_SIZE 4/* Returns false on error, true otherwise */static booleando_slurp_bsd_armap (abfd) bfd *abfd;{ struct areltdata *mapdata; unsigned int counter; bfd_byte *raw_armap, *rbase; struct artdata *ardata = bfd_ardata (abfd); char *stringbase; unsigned int parsed_size; carsym *set; mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd); if (mapdata == NULL) return false; parsed_size = mapdata->parsed_size; bfd_release (abfd, (PTR) mapdata); /* Don't need it any more. */ raw_armap = (bfd_byte *) bfd_zalloc (abfd, parsed_size); if (raw_armap == (bfd_byte *) NULL) return false; if (bfd_read ((PTR) raw_armap, 1, parsed_size, abfd) != parsed_size) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_malformed_archive); byebye: bfd_release (abfd, (PTR) raw_armap); return false; } ardata->symdef_count = bfd_h_get_32 (abfd, raw_armap) / BSD_SYMDEF_SIZE; if (ardata->symdef_count * BSD_SYMDEF_SIZE > parsed_size - BSD_SYMDEF_COUNT_SIZE) { /* Probably we're using the wrong byte ordering. */ bfd_set_error (bfd_error_wrong_format); goto byebye; } ardata->cache = 0; rbase = raw_armap + BSD_SYMDEF_COUNT_SIZE; stringbase = ((char *) rbase + ardata->symdef_count * BSD_SYMDEF_SIZE + BSD_STRING_COUNT_SIZE); ardata->symdefs = (carsym *) bfd_alloc (abfd, (ardata->symdef_count * sizeof (carsym))); if (!ardata->symdefs) return false; for (counter = 0, set = ardata->symdefs; counter < ardata->symdef_count; counter++, set++, rbase += BSD_SYMDEF_SIZE) { set->name = bfd_h_get_32 (abfd, rbase) + stringbase; set->file_offset = bfd_h_get_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE); } 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 objalloc anyway... */ bfd_has_map (abfd) = true; return true;}/* Returns false on error, true otherwise. */static booleando_slurp_coff_armap (abfd) bfd *abfd;{ struct areltdata *mapdata; int *raw_armap, *rawptr; struct artdata *ardata = bfd_ardata (abfd); char *stringbase; unsigned int stringsize; unsigned int parsed_size; carsym *carsyms; unsigned int nsymz; /* Number of symbols in armap. */ bfd_vma (*swap) PARAMS ((const bfd_byte *)); char int_buf[sizeof (long)]; unsigned int carsym_size, ptrsize, i; mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd); if (mapdata == NULL) return false; parsed_size = mapdata->parsed_size; bfd_release (abfd, (PTR) mapdata); /* Don't need it any more. */ if (bfd_read ((PTR) int_buf, 1, 4, abfd) != 4) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_malformed_archive); return false; } /* It seems that all numeric information in a coff archive is always in big endian format, nomatter the host or target. */ swap = bfd_getb32; nsymz = bfd_getb32 ((PTR) int_buf); stringsize = parsed_size - (4 * nsymz) - 4;#if 1 /* ... 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. */ if (stringsize > 0xfffff && bfd_get_arch (abfd) == bfd_arch_i960 && bfd_get_flavour (abfd) == bfd_target_coff_flavour) { /* This looks dangerous, let's do it the other way around. */ nsymz = bfd_getl32 ((PTR) int_buf); stringsize = parsed_size - (4 * nsymz) - 4; swap = bfd_getl32; }#endif /* The coff armap must be read sequentially. So we construct a bsd-style one in core all at once, for simplicity. */ carsym_size = (nsymz * sizeof (carsym)); ptrsize = (4 * nsymz); ardata->symdefs = (carsym *) bfd_zalloc (abfd, carsym_size + stringsize + 1); if (ardata->symdefs == NULL) return false; carsyms = ardata->symdefs; stringbase = ((char *) ardata->symdefs) + carsym_size; /* Allocate and read in the raw offsets. */ raw_armap = (int *) bfd_alloc (abfd, ptrsize); if (raw_armap == NULL) goto release_symdefs; if (bfd_read ((PTR) raw_armap, 1, ptrsize, abfd) != ptrsize || bfd_read ((PTR) stringbase, 1, stringsize, abfd) != stringsize) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_malformed_archive); goto release_raw_armap; } /* OK, build the carsyms. */ for (i = 0; i < nsymz; i++) { rawptr = raw_armap + i; carsyms->file_offset = swap ((PTR) rawptr); carsyms->name = stringbase; stringbase += strlen (stringbase) + 1; carsyms++; } *stringbase = 0; ardata->symdef_count = nsymz; 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; bfd_has_map (abfd) = true; bfd_release (abfd, (PTR) raw_armap); /* Check for a second archive header (as used by PE). */ { struct areltdata *tmp; bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET); tmp = (struct areltdata *) _bfd_read_ar_hdr (abfd); if (tmp != NULL) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?