OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.18.50/] [bfd/] [bfdwin.c] - Blame information for rev 297

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
/* Support for memory-mapped windows into a BFD.
2
   Copyright 1995, 1996, 2001, 2002, 2003, 2005, 2007, 2008
3
   Free Software Foundation, Inc.
4
   Written by Cygnus Support.
5
 
6
   This file is part of BFD, the Binary File Descriptor library.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program; if not, write to the Free Software
20
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21
   MA 02110-1301, USA.  */
22
 
23
#include "sysdep.h"
24
 
25
#include "bfd.h"
26
#include "libbfd.h"
27
 
28
/* Currently, if USE_MMAP is undefined, none if the window stuff is
29
   used.  Okay, so it's mis-named.  At least the command-line option
30
   "--without-mmap" is more obvious than "--without-windows" or some
31
   such.  */
32
 
33
#ifdef USE_MMAP
34
 
35
#undef HAVE_MPROTECT /* code's not tested yet */
36
 
37
#if HAVE_MMAP || HAVE_MPROTECT || HAVE_MADVISE
38
#include <sys/mman.h>
39
#endif
40
 
41
#ifndef MAP_FILE
42
#define MAP_FILE 0
43
#endif
44
 
45
static int debug_windows;
46
 
47
/* The idea behind the next and refcount fields is that one mapped
48
   region can suffice for multiple read-only windows or multiple
49
   non-overlapping read-write windows.  It's not implemented yet
50
   though.  */
51
 
52
/*
53
INTERNAL_DEFINITION
54
 
55
.struct _bfd_window_internal {
56
.  struct _bfd_window_internal *next;
57
.  void *data;
58
.  bfd_size_type size;
59
.  int refcount : 31;           {* should be enough...  *}
60
.  unsigned mapped : 1;         {* 1 = mmap, 0 = malloc *}
61
.};
62
*/
63
 
64
void
65
bfd_init_window (bfd_window *windowp)
66
{
67
  windowp->data = 0;
68
  windowp->i = 0;
69
  windowp->size = 0;
70
}
71
 
72
void
73
bfd_free_window (bfd_window *windowp)
74
{
75
  bfd_window_internal *i = windowp->i;
76
  windowp->i = 0;
77
  windowp->data = 0;
78
  if (i == 0)
79
    return;
80
  i->refcount--;
81
  if (debug_windows)
82
    fprintf (stderr, "freeing window @%p<%p,%lx,%p>\n",
83
             windowp, windowp->data, windowp->size, windowp->i);
84
  if (i->refcount != 0)
85
    return;
86
 
87
  if (i->mapped)
88
    {
89
#ifdef HAVE_MMAP
90
      munmap (i->data, i->size);
91
      goto no_free;
92
#else
93
      abort ();
94
#endif
95
    }
96
#ifdef HAVE_MPROTECT
97
  mprotect (i->data, i->size, PROT_READ | PROT_WRITE);
98
#endif
99
  free (i->data);
100
#ifdef HAVE_MMAP
101
 no_free:
102
#endif
103
  i->data = 0;
104
  /* There should be no more references to i at this point.  */
105
  free (i);
106
}
107
 
108
static int ok_to_map = 1;
109
 
110
bfd_boolean
111
bfd_get_file_window (bfd *abfd,
112
                     file_ptr offset,
113
                     bfd_size_type size,
114
                     bfd_window *windowp,
115
                     bfd_boolean writable)
116
{
117
  static size_t pagesize;
118
  bfd_window_internal *i = windowp->i;
119
  bfd_size_type size_to_alloc = size;
120
 
121
  if (debug_windows)
122
    fprintf (stderr, "bfd_get_file_window (%p, %6ld, %6ld, %p<%p,%lx,%p>, %d)",
123
             abfd, (long) offset, (long) size,
124
             windowp, windowp->data, (unsigned long) windowp->size,
125
             windowp->i, writable);
126
 
127
  /* Make sure we know the page size, so we can be friendly to mmap.  */
128
  if (pagesize == 0)
129
    pagesize = getpagesize ();
130
  if (pagesize == 0)
131
    abort ();
132
 
133
  if (i == 0)
134
    {
135
      i = bfd_zmalloc (sizeof (bfd_window_internal));
136
      windowp->i = i;
137
      if (i == 0)
138
        return FALSE;
139
      i->data = 0;
140
    }
141
#ifdef HAVE_MMAP
142
  if (ok_to_map
143
      && (i->data == 0 || i->mapped == 1)
144
      && (abfd->flags & BFD_IN_MEMORY) == 0)
145
    {
146
      file_ptr file_offset, offset2;
147
      size_t real_size;
148
      int fd;
149
 
150
      /* Find the real file and the real offset into it.  */
151
      while (abfd->my_archive != NULL)
152
        {
153
          offset += abfd->origin;
154
          abfd = abfd->my_archive;
155
        }
156
 
157
      /* Seek into the file, to ensure it is open if cacheable.  */
158
      if (abfd->iostream == NULL
159
          && (abfd->iovec == NULL
160
              || abfd->iovec->bseek (abfd, offset, SEEK_SET) != 0))
161
        return FALSE;
162
      fd = fileno ((FILE *) abfd->iostream);
163
 
164
      /* Compute offsets and size for mmap and for the user's data.  */
165
      offset2 = offset % pagesize;
166
      if (offset2 < 0)
167
        abort ();
168
      file_offset = offset - offset2;
169
      real_size = offset + size - file_offset;
170
      real_size = real_size + pagesize - 1;
171
      real_size -= real_size % pagesize;
172
 
173
      /* If we're re-using a memory region, make sure it's big enough.  */
174
      if (i->data && i->size < size)
175
        {
176
          munmap (i->data, i->size);
177
          i->data = 0;
178
        }
179
      i->data = mmap (i->data, real_size,
180
                      writable ? PROT_WRITE | PROT_READ : PROT_READ,
181
                      (writable
182
                       ? MAP_FILE | MAP_PRIVATE
183
                       : MAP_FILE | MAP_SHARED),
184
                      fd, file_offset);
185
      if (i->data == (void *) -1)
186
        {
187
          /* An error happened.  Report it, or try using malloc, or
188
             something.  */
189
          bfd_set_error (bfd_error_system_call);
190
          i->data = 0;
191
          windowp->data = 0;
192
          if (debug_windows)
193
            fprintf (stderr, "\t\tmmap failed!\n");
194
          return FALSE;
195
        }
196
      if (debug_windows)
197
        fprintf (stderr, "\n\tmapped %ld at %p, offset is %ld\n",
198
                 (long) real_size, i->data, (long) offset2);
199
      i->size = real_size;
200
      windowp->data = (bfd_byte *) i->data + offset2;
201
      windowp->size = size;
202
      i->mapped = 1;
203
      return TRUE;
204
    }
205
  else if (debug_windows)
206
    {
207
      if (ok_to_map)
208
        fprintf (stderr, _("not mapping: data=%lx mapped=%d\n"),
209
                 (unsigned long) i->data, (int) i->mapped);
210
      else
211
        fprintf (stderr, _("not mapping: env var not set\n"));
212
    }
213
#else
214
  ok_to_map = 0;
215
#endif
216
 
217
#ifdef HAVE_MPROTECT
218
  if (!writable)
219
    {
220
      size_to_alloc += pagesize - 1;
221
      size_to_alloc -= size_to_alloc % pagesize;
222
    }
223
#endif
224
  if (debug_windows)
225
    fprintf (stderr, "\n\t%s(%6ld)",
226
             i->data ? "realloc" : " malloc", (long) size_to_alloc);
227
  i->data = bfd_realloc_or_free (i->data, size_to_alloc);
228
  if (debug_windows)
229
    fprintf (stderr, "\t-> %p\n", i->data);
230
  if (i->data == NULL)
231
    {
232
      if (size_to_alloc == 0)
233
        return TRUE;
234
      return FALSE;
235
    }
236
  i->refcount = 1;
237
  if (bfd_seek (abfd, offset, SEEK_SET) != 0)
238
    return FALSE;
239
  i->size = bfd_bread (i->data, size, abfd);
240
  if (i->size != size)
241
    return FALSE;
242
  i->mapped = 0;
243
#ifdef HAVE_MPROTECT
244
  if (!writable)
245
    {
246
      if (debug_windows)
247
        fprintf (stderr, "\tmprotect (%p, %ld, PROT_READ)\n", i->data,
248
                 (long) i->size);
249
      mprotect (i->data, i->size, PROT_READ);
250
    }
251
#endif
252
  windowp->data = i->data;
253
  windowp->size = i->size;
254
  return TRUE;
255
}
256
 
257
#endif /* USE_MMAP */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.