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 + -
显示快捷键?