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