libbfd.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 1,383 行 · 第 1/3 页
C
1,383 行
fprintf (stderr, "\n\tmapped %ld at %p, offset is %ld\n", (long) real_size, i->data, (long) offset2); i->size = real_size; windowp->data = (PTR) ((bfd_byte *) i->data + offset2); windowp->size = size; i->mapped = 1; return true; } else if (debug_windows) { if (ok_to_map) fprintf (stderr, _("not mapping: data=%lx mapped=%d\n"), (unsigned long) i->data, (int) i->mapped); else fprintf (stderr, _("not mapping: env var not set\n")); }#else ok_to_map = 0;#endif#ifdef HAVE_MPROTECT if (!writable) { size_to_alloc += pagesize - 1; size_to_alloc -= size_to_alloc % pagesize; }#endif if (debug_windows) fprintf (stderr, "\n\t%s(%6ld)", i->data ? "realloc" : " malloc", (long) size_to_alloc); i->data = (PTR) bfd_realloc (i->data, size_to_alloc); if (debug_windows) fprintf (stderr, "\t-> %p\n", i->data); i->refcount = 1; if (i->data == NULL) { if (size_to_alloc == 0) return true; bfd_set_error (bfd_error_no_memory); return false; } if (bfd_seek (abfd, offset, SEEK_SET) != 0) return false; i->size = bfd_read (i->data, size, 1, abfd); if (i->size != size) return false; i->mapped = 0;#ifdef HAVE_MPROTECT if (!writable) { if (debug_windows) fprintf (stderr, "\tmprotect (%p, %ld, PROT_READ)\n", i->data, (long) i->size); mprotect (i->data, i->size, PROT_READ); }#endif windowp->data = i->data; windowp->size = i->size; return true;}#endif /* USE_MMAP */bfd_size_typebfd_write (ptr, size, nitems, abfd) CONST PTR ptr; bfd_size_type size; bfd_size_type nitems; bfd *abfd;{ long nwrote; if ((abfd->flags & BFD_IN_MEMORY) != 0) { struct bfd_in_memory *bim = (struct bfd_in_memory *) (abfd->iostream); size *= nitems; if (abfd->where + size > bim->size) { long newsize, oldsize = (bim->size + 127) & ~127; bim->size = abfd->where + size; /* Round up to cut down on memory fragmentation */ newsize = (bim->size + 127) & ~127; if (newsize > oldsize) { bim->buffer = bfd_realloc (bim->buffer, newsize); if (bim->buffer == 0) { bim->size = 0; return 0; } } } memcpy (bim->buffer + abfd->where, ptr, size); abfd->where += size; return size; } nwrote = fwrite (ptr, 1, (size_t) (size * nitems), bfd_cache_lookup (abfd)); if (nwrote > 0) abfd->where += nwrote; if ((bfd_size_type) nwrote != size * nitems) {#ifdef ENOSPC if (nwrote >= 0) errno = ENOSPC;#endif bfd_set_error (bfd_error_system_call); } return nwrote;}/*INTERNAL_FUNCTION bfd_write_bigendian_4byte_intSYNOPSIS void bfd_write_bigendian_4byte_int(bfd *abfd, int i);DESCRIPTION Write a 4 byte integer @var{i} to the output BFD @var{abfd}, in big endian order regardless of what else is going on. This is useful in archives.*/voidbfd_write_bigendian_4byte_int (abfd, i) bfd *abfd; int i;{ bfd_byte buffer[4]; bfd_putb32(i, buffer); if (bfd_write((PTR)buffer, 4, 1, abfd) != 4) abort ();}longbfd_tell (abfd) bfd *abfd;{ file_ptr ptr; if ((abfd->flags & BFD_IN_MEMORY) != 0) return abfd->where; ptr = ftell (bfd_cache_lookup(abfd)); if (abfd->my_archive) ptr -= abfd->origin; abfd->where = ptr; return ptr;}intbfd_flush (abfd) bfd *abfd;{ if ((abfd->flags & BFD_IN_MEMORY) != 0) return 0; return fflush (bfd_cache_lookup(abfd));}/* Returns 0 for success, negative value for failure (in which case bfd_get_error can retrieve the error code). */intbfd_stat (abfd, statbuf) bfd *abfd; struct stat *statbuf;{ FILE *f; int result; if ((abfd->flags & BFD_IN_MEMORY) != 0) abort (); f = bfd_cache_lookup (abfd); if (f == NULL) { bfd_set_error (bfd_error_system_call); return -1; } result = fstat (fileno (f), statbuf); if (result < 0) bfd_set_error (bfd_error_system_call); return result;}/* Returns 0 for success, nonzero for failure (in which case bfd_get_error can retrieve the error code). */intbfd_seek (abfd, position, direction) bfd *abfd; file_ptr position; int direction;{ int result; FILE *f; file_ptr file_position; /* For the time being, a BFD may not seek to it's end. The problem is that we don't easily have a way to recognize the end of an element in an archive. */ BFD_ASSERT (direction == SEEK_SET || direction == SEEK_CUR); if (direction == SEEK_CUR && position == 0) return 0; if ((abfd->flags & BFD_IN_MEMORY) != 0) { struct bfd_in_memory *bim; bim = (struct bfd_in_memory *) abfd->iostream; if (direction == SEEK_SET) abfd->where = position; else abfd->where += position; if ((bfd_size_type) abfd->where > bim->size) { if ((abfd->direction == write_direction) || (abfd->direction == both_direction)) { long newsize, oldsize = (bim->size + 127) & ~127; bim->size = abfd->where; /* Round up to cut down on memory fragmentation */ newsize = (bim->size + 127) & ~127; if (newsize > oldsize) { bim->buffer = bfd_realloc (bim->buffer, newsize); if (bim->buffer == 0) { bim->size = 0; bfd_set_error (bfd_error_no_memory); return -1; } } } else { abfd->where = bim->size; bfd_set_error (bfd_error_file_truncated); return -1; } } return 0; } if (abfd->format != bfd_archive && abfd->my_archive == 0) {#if 0 /* Explanation for this code: I'm only about 95+% sure that the above conditions are sufficient and that all i/o calls are properly adjusting the `where' field. So this is sort of an `assert' that the `where' field is correct. If we can go a while without tripping the abort, we can probably safely disable this code, so that the real optimizations happen. */ file_ptr where_am_i_now; where_am_i_now = ftell (bfd_cache_lookup (abfd)); if (abfd->my_archive) where_am_i_now -= abfd->origin; if (where_am_i_now != abfd->where) abort ();#endif if (direction == SEEK_SET && position == abfd->where) return 0; } else { /* We need something smarter to optimize access to archives. Currently, anything inside an archive is read via the file handle for the archive. Which means that a bfd_seek on one component affects the `current position' in the archive, as well as in any other component. It might be sufficient to put a spike through the cache abstraction, and look to the archive for the file position, but I think we should try for something cleaner. In the meantime, no optimization for archives. */ } f = bfd_cache_lookup (abfd); file_position = position; if (direction == SEEK_SET && abfd->my_archive != NULL) file_position += abfd->origin; result = fseek (f, file_position, direction); if (result != 0) { int hold_errno = errno; /* Force redetermination of `where' field. */ bfd_tell (abfd); /* An EINVAL error probably means that the file offset was absurd. */ if (hold_errno == EINVAL) bfd_set_error (bfd_error_file_truncated); else { bfd_set_error (bfd_error_system_call); errno = hold_errno; } } else { /* Adjust `where' field. */ if (direction == SEEK_SET) abfd->where = position; else abfd->where += position; } return result;}/** The do-it-yourself (byte) sex-change kit *//* The middle letter e.g. get<b>short indicates Big or Little endian target machine. It doesn't matter what the byte order of the host machine is; these routines work for either. *//* FIXME: Should these take a count argument? Answer (gnu@cygnus.com): No, but perhaps they should be inline functions in swap.h #ifdef __GNUC__. Gprof them later and find out. *//*FUNCTION bfd_put_sizeFUNCTION bfd_get_sizeDESCRIPTION These macros as used for reading and writing raw data in sections; each access (except for bytes) is vectored through the target format of the BFD and mangled accordingly. The mangling performs any necessary endian translations and removes alignment restrictions. Note that types accepted and returned by these macros are identical so they can be swapped around in macros---for example, @file{libaout.h} defines <<GET_WORD>> to either <<bfd_get_32>> or <<bfd_get_64>>. In the put routines, @var{val} must be a <<bfd_vma>>. If we are on a system without prototypes, the caller is responsible for making sure that is true, with a cast if necessary. We don't cast them in the macro definitions because that would prevent <<lint>> or <<gcc -Wall>> from detecting sins such as passing a pointer. To detect calling these with less than a <<bfd_vma>>, use <<gcc -Wconversion>> on a host with 64 bit <<bfd_vma>>'s...{* Byte swapping macros for user section data. *}..#define bfd_put_8(abfd, val, ptr) \. ((void) (*((unsigned char *) (ptr)) = (unsigned char) (val))).#define bfd_put_signed_8 \. bfd_put_8.#define bfd_get_8(abfd, ptr) \. (*(unsigned char *) (ptr)).#define bfd_get_signed_8(abfd, ptr) \. ((*(unsigned char *) (ptr) ^ 0x80) - 0x80)..#define bfd_put_16(abfd, val, ptr) \. BFD_SEND(abfd, bfd_putx16, ((val),(ptr))).#define bfd_put_signed_16 \. bfd_put_16.#define bfd_get_16(abfd, ptr) \. BFD_SEND(abfd, bfd_getx16, (ptr)).#define bfd_get_signed_16(abfd, ptr) \. BFD_SEND (abfd, bfd_getx_signed_16, (ptr))..#define bfd_put_32(abfd, val, ptr) \. BFD_SEND(abfd, bfd_putx32, ((val),(ptr))).#define bfd_put_signed_32 \. bfd_put_32.#define bfd_get_32(abfd, ptr) \. BFD_SEND(abfd, bfd_getx32, (ptr)).#define bfd_get_signed_32(abfd, ptr) \. BFD_SEND(abfd, bfd_getx_signed_32, (ptr))..#define bfd_put_64(abfd, val, ptr) \. BFD_SEND(abfd, bfd_putx64, ((val), (ptr))).#define bfd_put_signed_64 \. bfd_put_64.#define bfd_get_64(abfd, ptr) \. BFD_SEND(abfd, bfd_getx64, (ptr)).#define bfd_get_signed_64(abfd, ptr) \. BFD_SEND(abfd, bfd_getx_signed_64, (ptr))..#define bfd_get(bits, abfd, ptr) \. ((bits) == 8 ? bfd_get_8 (abfd, ptr) \. : (bits) == 16 ? bfd_get_16 (abfd, ptr) \. : (bits) == 32 ? bfd_get_32 (abfd, ptr) \. : (bits) == 64 ? bfd_get_64 (abfd, ptr) \. : (abort (), (bfd_vma) - 1))..#define bfd_put(bits, abfd, val, ptr) \. ((bits) == 8 ? bfd_put_8 (abfd, val, ptr) \. : (bits) == 16 ? bfd_put_16 (abfd, val, ptr) \. : (bits) == 32 ? bfd_put_32 (abfd, val, ptr) \. : (bits) == 64 ? bfd_put_64 (abfd, val, ptr) \. : (abort (), (void) 0)).*//*FUNCTION bfd_h_put_size bfd_h_get_sizeDESCRIPTION These macros have the same function as their <<bfd_get_x>> bretheren, except that they are used for removing information for the header records of object files. Believe it or not, some object files keep their header records in big endian order and their data in little endian order...{* Byte swapping macros for file header data. *}..#define bfd_h_put_8(abfd, val, ptr) \. bfd_put_8 (abfd, val, ptr).#define bfd_h_put_signed_8(abfd, val, ptr) \. bfd_put_8 (abfd, val, ptr).#define bfd_h_get_8(abfd, ptr) \. bfd_get_8 (abfd, ptr).#define bfd_h_get_signed_8(abfd, ptr) \. bfd_get_signed_8 (abfd, ptr)..#define bfd_h_put_16(abfd, val, ptr) \. BFD_SEND(abfd, bfd_h_putx16,(val,ptr)).#define bfd_h_put_signed_16 \. bfd_h_put_16.#define bfd_h_get_16(abfd, ptr) \. BFD_SEND(abfd, bfd_h_getx16,(ptr)).#define bfd_h_get_signed_16(abfd, ptr) \. BFD_SEND(abfd, bfd_h_getx_signed_16, (ptr))..#define bfd_h_put_32(abfd, val, ptr) \. BFD_SEND(abfd, bfd_h_putx32,(val,ptr)).#define bfd_h_put_signed_32 \. bfd_h_put_32.#define bfd_h_get_32(abfd, ptr) \. BFD_SEND(abfd, bfd_h_getx32,(ptr)).#define bfd_h_get_signed_32(abfd, ptr) \. BFD_SEND(abfd, bfd_h_getx_signed_32, (ptr))..#define bfd_h_put_64(abfd, val, ptr) \. BFD_SEND(abfd, bfd_h_putx64,(val, ptr)).#define bfd_h_put_signed_64 \. bfd_h_put_64.#define bfd_h_get_64(abfd, ptr) \. BFD_SEND(abfd, bfd_h_getx64,(ptr)).#define bfd_h_get_signed_64(abfd, ptr) \. BFD_SEND(abfd, bfd_h_getx_signed_64, (ptr)).*//* Sign extension to bfd_signed_vma. */#define COERCE16(x) (((bfd_signed_vma) (x) ^ 0x8000) - 0x8000)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?