libbfd.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 1,383 行 · 第 1/3 页
C
1,383 行
/* Assorted BFD support routines, only used internally. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. Written by Cygnus Support.This file is part of BFD, the Binary File Descriptor library.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "bfd.h"#include "sysdep.h"#include "libbfd.h"#ifndef HAVE_GETPAGESIZE#define getpagesize() 2048#endifstatic int real_read PARAMS ((PTR, size_t, size_t, FILE *));/*SECTION Internal functionsDESCRIPTION These routines are used within BFD. They are not intended for export, but are documented here for completeness.*//* A routine which is used in target vectors for unsupported operations. */booleanbfd_false (ignore) bfd *ignore ATTRIBUTE_UNUSED;{ bfd_set_error (bfd_error_invalid_operation); return false;}/* A routine which is used in target vectors for supported operations which do not actually do anything. */booleanbfd_true (ignore) bfd *ignore ATTRIBUTE_UNUSED;{ return true;}/* A routine which is used in target vectors for unsupported operations which return a pointer value. */PTRbfd_nullvoidptr (ignore) bfd *ignore ATTRIBUTE_UNUSED;{ bfd_set_error (bfd_error_invalid_operation); return NULL;}intbfd_0 (ignore) bfd *ignore ATTRIBUTE_UNUSED;{ return 0;}unsigned intbfd_0u (ignore) bfd *ignore ATTRIBUTE_UNUSED;{ return 0;}longbfd_0l (ignore) bfd *ignore ATTRIBUTE_UNUSED;{ return 0;}/* A routine which is used in target vectors for unsupported operations which return -1 on error. */long_bfd_n1 (ignore_abfd) bfd *ignore_abfd ATTRIBUTE_UNUSED;{ bfd_set_error (bfd_error_invalid_operation); return -1;}voidbfd_void (ignore) bfd *ignore ATTRIBUTE_UNUSED;{}boolean_bfd_nocore_core_file_matches_executable_p (ignore_core_bfd, ignore_exec_bfd) bfd *ignore_core_bfd ATTRIBUTE_UNUSED; bfd *ignore_exec_bfd ATTRIBUTE_UNUSED;{ bfd_set_error (bfd_error_invalid_operation); return false;}/* Routine to handle core_file_failing_command entry point for targets without core file support. */char *_bfd_nocore_core_file_failing_command (ignore_abfd) bfd *ignore_abfd ATTRIBUTE_UNUSED;{ bfd_set_error (bfd_error_invalid_operation); return (char *)NULL;}/* Routine to handle core_file_failing_signal entry point for targets without core file support. */int_bfd_nocore_core_file_failing_signal (ignore_abfd) bfd *ignore_abfd ATTRIBUTE_UNUSED;{ bfd_set_error (bfd_error_invalid_operation); return 0;}const bfd_target *_bfd_dummy_target (ignore_abfd) bfd *ignore_abfd ATTRIBUTE_UNUSED;{ bfd_set_error (bfd_error_wrong_format); return 0;}/* Allocate memory using malloc. */PTRbfd_malloc (size) size_t size;{ PTR ptr; ptr = (PTR) malloc (size); if (ptr == NULL && size != 0) bfd_set_error (bfd_error_no_memory); return ptr;}/* Reallocate memory using realloc. */PTRbfd_realloc (ptr, size) PTR ptr; size_t size;{ PTR ret; if (ptr == NULL) ret = malloc (size); else ret = realloc (ptr, size); if (ret == NULL) bfd_set_error (bfd_error_no_memory); return ret;}/* Allocate memory using malloc and clear it. */PTRbfd_zmalloc (size) size_t size;{ PTR ptr; ptr = (PTR) malloc (size); if (size != 0) { if (ptr == NULL) bfd_set_error (bfd_error_no_memory); else memset (ptr, 0, size); } return ptr;}/* Some IO code *//* Note that archive entries don't have streams; they share their parent's. This allows someone to play with the iostream behind BFD's back. Also, note that the origin pointer points to the beginning of a file's contents (0 for non-archive elements). For archive entries this is the first octet in the file, NOT the beginning of the archive header. */static intreal_read (where, a,b, file) PTR where; size_t a; size_t b; FILE *file;{ /* FIXME - this looks like an optimization, but it's really to cover up for a feature of some OSs (not solaris - sigh) that ld/pe-dll.c takes advantage of (apparently) when it creates BFDs internally and tries to link against them. BFD seems to be smart enough to realize there are no symbol records in the "file" that doesn't exist but attempts to read them anyway. On Solaris, attempting to read zero bytes from a NULL file results in a core dump, but on other platforms it just returns zero bytes read. This makes it to something reasonable. - DJ */ if (a == 0 || b == 0) return 0;#if defined (__VAX) && defined (VMS) /* Apparently fread on Vax VMS does not keep the record length information. */ return read (fileno (file), where, a * b);#else return fread (where, a, b, file);#endif}/* Return value is amount read (FIXME: how are errors and end of file dealt with? We never call bfd_set_error, which is probably a mistake). */bfd_size_typebfd_read (ptr, size, nitems, abfd) PTR ptr; bfd_size_type size; bfd_size_type nitems; bfd *abfd;{ int nread; if ((abfd->flags & BFD_IN_MEMORY) != 0) { struct bfd_in_memory *bim; bfd_size_type get; bim = (struct bfd_in_memory *) abfd->iostream; get = size * nitems; if (abfd->where + get > bim->size) { if (bim->size < (bfd_size_type) abfd->where) get = 0; else get = bim->size - abfd->where; bfd_set_error (bfd_error_file_truncated); } memcpy (ptr, bim->buffer + abfd->where, get); abfd->where += get; return get; } nread = real_read (ptr, 1, (size_t) (size*nitems), bfd_cache_lookup(abfd)); if (nread > 0) abfd->where += nread; /* Set bfd_error if we did not read as much data as we expected. If the read failed due to an error set the bfd_error_system_call, else set bfd_error_file_truncated. A BFD backend may wish to override bfd_error_file_truncated to provide something more useful (eg. no_symbols or wrong_format). */ if (nread != (int) (size * nitems)) { if (ferror (bfd_cache_lookup (abfd))) bfd_set_error (bfd_error_system_call); else bfd_set_error (bfd_error_file_truncated); } return nread;}/* The window support stuff should probably be broken out into another file.... *//* The idea behind the next and refcount fields is that one mapped region can suffice for multiple read-only windows or multiple non-overlapping read-write windows. It's not implemented yet though. */struct _bfd_window_internal { struct _bfd_window_internal *next; PTR data; bfd_size_type size; int refcount : 31; /* should be enough... */ unsigned mapped : 1; /* 1 = mmap, 0 = malloc */};voidbfd_init_window (windowp) bfd_window *windowp;{ windowp->data = 0; windowp->i = 0; windowp->size = 0;}/* Currently, if USE_MMAP is undefined, none if the window stuff is used. Okay, so it's mis-named. At least the command-line option "--without-mmap" is more obvious than "--without-windows" or some such. */#ifdef USE_MMAP#undef HAVE_MPROTECT /* code's not tested yet */#if HAVE_MMAP || HAVE_MPROTECT || HAVE_MADVISE#include <sys/mman.h>#endif#ifndef MAP_FILE#define MAP_FILE 0#endifstatic int debug_windows;voidbfd_free_window (windowp) bfd_window *windowp;{ bfd_window_internal *i = windowp->i; windowp->i = 0; windowp->data = 0; if (i == 0) return; i->refcount--; if (debug_windows) fprintf (stderr, "freeing window @%p<%p,%lx,%p>\n", windowp, windowp->data, windowp->size, windowp->i); if (i->refcount != 0) return; if (i->mapped) {#ifdef HAVE_MMAP munmap (i->data, i->size); goto no_free;#else abort ();#endif }#ifdef HAVE_MPROTECT mprotect (i->data, i->size, PROT_READ | PROT_WRITE);#endif free (i->data);#ifdef HAVE_MMAP no_free:#endif i->data = 0; /* There should be no more references to i at this point. */ free (i);}static int ok_to_map = 1;booleanbfd_get_file_window (abfd, offset, size, windowp, writable) bfd *abfd; file_ptr offset; bfd_size_type size; bfd_window *windowp; boolean writable;{ static size_t pagesize; bfd_window_internal *i = windowp->i; size_t size_to_alloc = size; if (debug_windows) fprintf (stderr, "bfd_get_file_window (%p, %6ld, %6ld, %p<%p,%lx,%p>, %d)", abfd, (long) offset, (long) size, windowp, windowp->data, (unsigned long) windowp->size, windowp->i, writable); /* Make sure we know the page size, so we can be friendly to mmap. */ if (pagesize == 0) pagesize = getpagesize (); if (pagesize == 0) abort (); if (i == 0) { windowp->i = i = (bfd_window_internal *) bfd_zmalloc (sizeof (bfd_window_internal)); if (i == 0) return false; i->data = 0; }#ifdef HAVE_MMAP if (ok_to_map && (i->data == 0 || i->mapped == 1) && (abfd->flags & BFD_IN_MEMORY) == 0) { file_ptr file_offset, offset2; size_t real_size; int fd; FILE *f; /* Find the real file and the real offset into it. */ while (abfd->my_archive != NULL) { offset += abfd->origin; abfd = abfd->my_archive; } f = bfd_cache_lookup (abfd); fd = fileno (f); /* Compute offsets and size for mmap and for the user's data. */ offset2 = offset % pagesize; if (offset2 < 0) abort (); file_offset = offset - offset2; real_size = offset + size - file_offset; real_size = real_size + pagesize - 1; real_size -= real_size % pagesize; /* If we're re-using a memory region, make sure it's big enough. */ if (i->data && i->size < size) { munmap (i->data, i->size); i->data = 0; } i->data = mmap (i->data, real_size, writable ? PROT_WRITE | PROT_READ : PROT_READ, (writable ? MAP_FILE | MAP_PRIVATE : MAP_FILE | MAP_SHARED), fd, file_offset); if (i->data == (PTR) -1) { /* An error happened. Report it, or try using malloc, or something. */ bfd_set_error (bfd_error_system_call); i->data = 0; windowp->data = 0; if (debug_windows) fprintf (stderr, "\t\tmmap failed!\n"); return false; } if (debug_windows)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?