1 | /* Low-level I/O routines for BFDs.
|
---|
2 | Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
---|
3 | 2000, 2001, 2002 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
---|
21 |
|
---|
22 | #include "sysdep.h"
|
---|
23 |
|
---|
24 | #include "bfd.h"
|
---|
25 | #include "libbfd.h"
|
---|
26 |
|
---|
27 | #include <limits.h>
|
---|
28 |
|
---|
29 | #ifndef S_IXUSR
|
---|
30 | #define S_IXUSR 0100 /* Execute by owner. */
|
---|
31 | #endif
|
---|
32 | #ifndef S_IXGRP
|
---|
33 | #define S_IXGRP 0010 /* Execute by group. */
|
---|
34 | #endif
|
---|
35 | #ifndef S_IXOTH
|
---|
36 | #define S_IXOTH 0001 /* Execute by others. */
|
---|
37 | #endif
|
---|
38 |
|
---|
39 | /* Note that archive entries don't have streams; they share their parent's.
|
---|
40 | This allows someone to play with the iostream behind BFD's back.
|
---|
41 |
|
---|
42 | Also, note that the origin pointer points to the beginning of a file's
|
---|
43 | contents (0 for non-archive elements). For archive entries this is the
|
---|
44 | first octet in the file, NOT the beginning of the archive header. */
|
---|
45 |
|
---|
46 | static size_t real_read PARAMS ((PTR where, size_t a, size_t b, FILE *file));
|
---|
47 | static size_t
|
---|
48 | real_read (where, a, b, file)
|
---|
49 | PTR where;
|
---|
50 | size_t a;
|
---|
51 | size_t b;
|
---|
52 | FILE *file;
|
---|
53 | {
|
---|
54 | /* FIXME - this looks like an optimization, but it's really to cover
|
---|
55 | up for a feature of some OSs (not solaris - sigh) that
|
---|
56 | ld/pe-dll.c takes advantage of (apparently) when it creates BFDs
|
---|
57 | internally and tries to link against them. BFD seems to be smart
|
---|
58 | enough to realize there are no symbol records in the "file" that
|
---|
59 | doesn't exist but attempts to read them anyway. On Solaris,
|
---|
60 | attempting to read zero bytes from a NULL file results in a core
|
---|
61 | dump, but on other platforms it just returns zero bytes read.
|
---|
62 | This makes it to something reasonable. - DJ */
|
---|
63 | if (a == 0 || b == 0)
|
---|
64 | return 0;
|
---|
65 |
|
---|
66 |
|
---|
67 | #if defined (__VAX) && defined (VMS)
|
---|
68 | /* Apparently fread on Vax VMS does not keep the record length
|
---|
69 | information. */
|
---|
70 | return read (fileno (file), where, a * b);
|
---|
71 | #else
|
---|
72 | return fread (where, a, b, file);
|
---|
73 | #endif
|
---|
74 | }
|
---|
75 |
|
---|
76 | /* Return value is amount read. */
|
---|
77 |
|
---|
78 | bfd_size_type
|
---|
79 | bfd_bread (ptr, size, abfd)
|
---|
80 | PTR ptr;
|
---|
81 | bfd_size_type size;
|
---|
82 | bfd *abfd;
|
---|
83 | {
|
---|
84 | size_t nread;
|
---|
85 |
|
---|
86 | if ((abfd->flags & BFD_IN_MEMORY) != 0)
|
---|
87 | {
|
---|
88 | struct bfd_in_memory *bim;
|
---|
89 | bfd_size_type get;
|
---|
90 |
|
---|
91 | bim = (struct bfd_in_memory *) abfd->iostream;
|
---|
92 | get = size;
|
---|
93 | if (abfd->where + get > bim->size)
|
---|
94 | {
|
---|
95 | if (bim->size < (bfd_size_type) abfd->where)
|
---|
96 | get = 0;
|
---|
97 | else
|
---|
98 | get = bim->size - abfd->where;
|
---|
99 | bfd_set_error (bfd_error_file_truncated);
|
---|
100 | }
|
---|
101 | memcpy (ptr, bim->buffer + abfd->where, (size_t) get);
|
---|
102 | abfd->where += get;
|
---|
103 | return get;
|
---|
104 | }
|
---|
105 |
|
---|
106 | nread = real_read (ptr, 1, (size_t) size, bfd_cache_lookup (abfd));
|
---|
107 | if (nread != (size_t) -1)
|
---|
108 | abfd->where += nread;
|
---|
109 |
|
---|
110 | /* Set bfd_error if we did not read as much data as we expected.
|
---|
111 |
|
---|
112 | If the read failed due to an error set the bfd_error_system_call,
|
---|
113 | else set bfd_error_file_truncated.
|
---|
114 |
|
---|
115 | A BFD backend may wish to override bfd_error_file_truncated to
|
---|
116 | provide something more useful (eg. no_symbols or wrong_format). */
|
---|
117 | if (nread != size)
|
---|
118 | {
|
---|
119 | if (ferror (bfd_cache_lookup (abfd)))
|
---|
120 | bfd_set_error (bfd_error_system_call);
|
---|
121 | else
|
---|
122 | bfd_set_error (bfd_error_file_truncated);
|
---|
123 | }
|
---|
124 |
|
---|
125 | return nread;
|
---|
126 | }
|
---|
127 |
|
---|
128 | bfd_size_type
|
---|
129 | bfd_bwrite (ptr, size, abfd)
|
---|
130 | const PTR ptr;
|
---|
131 | bfd_size_type size;
|
---|
132 | bfd *abfd;
|
---|
133 | {
|
---|
134 | size_t nwrote;
|
---|
135 |
|
---|
136 | if ((abfd->flags & BFD_IN_MEMORY) != 0)
|
---|
137 | {
|
---|
138 | struct bfd_in_memory *bim = (struct bfd_in_memory *) (abfd->iostream);
|
---|
139 | size = (size_t) size;
|
---|
140 | if (abfd->where + size > bim->size)
|
---|
141 | {
|
---|
142 | bfd_size_type newsize, oldsize;
|
---|
143 |
|
---|
144 | oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
|
---|
145 | bim->size = abfd->where + size;
|
---|
146 | /* Round up to cut down on memory fragmentation */
|
---|
147 | newsize = (bim->size + 127) & ~(bfd_size_type) 127;
|
---|
148 | if (newsize > oldsize)
|
---|
149 | {
|
---|
150 | bim->buffer = (bfd_byte *) bfd_realloc (bim->buffer, newsize);
|
---|
151 | if (bim->buffer == 0)
|
---|
152 | {
|
---|
153 | bim->size = 0;
|
---|
154 | return 0;
|
---|
155 | }
|
---|
156 | }
|
---|
157 | }
|
---|
158 | memcpy (bim->buffer + abfd->where, ptr, (size_t) size);
|
---|
159 | abfd->where += size;
|
---|
160 | return size;
|
---|
161 | }
|
---|
162 |
|
---|
163 | nwrote = fwrite (ptr, 1, (size_t) size, bfd_cache_lookup (abfd));
|
---|
164 | if (nwrote != (size_t) -1)
|
---|
165 | abfd->where += nwrote;
|
---|
166 | if (nwrote != size)
|
---|
167 | {
|
---|
168 | #ifdef ENOSPC
|
---|
169 | errno = ENOSPC;
|
---|
170 | #endif
|
---|
171 | bfd_set_error (bfd_error_system_call);
|
---|
172 | }
|
---|
173 | return nwrote;
|
---|
174 | }
|
---|
175 |
|
---|
176 | bfd_vma
|
---|
177 | bfd_tell (abfd)
|
---|
178 | bfd *abfd;
|
---|
179 | {
|
---|
180 | file_ptr ptr;
|
---|
181 |
|
---|
182 | if ((abfd->flags & BFD_IN_MEMORY) != 0)
|
---|
183 | return abfd->where;
|
---|
184 |
|
---|
185 | ptr = ftell (bfd_cache_lookup (abfd));
|
---|
186 |
|
---|
187 | if (abfd->my_archive)
|
---|
188 | ptr -= abfd->origin;
|
---|
189 | abfd->where = ptr;
|
---|
190 | return ptr;
|
---|
191 | }
|
---|
192 |
|
---|
193 | int
|
---|
194 | bfd_flush (abfd)
|
---|
195 | bfd *abfd;
|
---|
196 | {
|
---|
197 | if ((abfd->flags & BFD_IN_MEMORY) != 0)
|
---|
198 | return 0;
|
---|
199 | return fflush (bfd_cache_lookup(abfd));
|
---|
200 | }
|
---|
201 |
|
---|
202 | /* Returns 0 for success, negative value for failure (in which case
|
---|
203 | bfd_get_error can retrieve the error code). */
|
---|
204 | int
|
---|
205 | bfd_stat (abfd, statbuf)
|
---|
206 | bfd *abfd;
|
---|
207 | struct stat *statbuf;
|
---|
208 | {
|
---|
209 | FILE *f;
|
---|
210 | int result;
|
---|
211 |
|
---|
212 | if ((abfd->flags & BFD_IN_MEMORY) != 0)
|
---|
213 | abort ();
|
---|
214 |
|
---|
215 | f = bfd_cache_lookup (abfd);
|
---|
216 | if (f == NULL)
|
---|
217 | {
|
---|
218 | bfd_set_error (bfd_error_system_call);
|
---|
219 | return -1;
|
---|
220 | }
|
---|
221 | result = fstat (fileno (f), statbuf);
|
---|
222 | if (result < 0)
|
---|
223 | bfd_set_error (bfd_error_system_call);
|
---|
224 | return result;
|
---|
225 | }
|
---|
226 |
|
---|
227 | /* Returns 0 for success, nonzero for failure (in which case bfd_get_error
|
---|
228 | can retrieve the error code). */
|
---|
229 |
|
---|
230 | int
|
---|
231 | bfd_seek (abfd, position, direction)
|
---|
232 | bfd *abfd;
|
---|
233 | file_ptr position;
|
---|
234 | int direction;
|
---|
235 | {
|
---|
236 | int result;
|
---|
237 | FILE *f;
|
---|
238 | long file_position;
|
---|
239 | /* For the time being, a BFD may not seek to it's end. The problem
|
---|
240 | is that we don't easily have a way to recognize the end of an
|
---|
241 | element in an archive. */
|
---|
242 |
|
---|
243 | BFD_ASSERT (direction == SEEK_SET || direction == SEEK_CUR);
|
---|
244 |
|
---|
245 | if (direction == SEEK_CUR && position == 0)
|
---|
246 | return 0;
|
---|
247 |
|
---|
248 | if ((abfd->flags & BFD_IN_MEMORY) != 0)
|
---|
249 | {
|
---|
250 | struct bfd_in_memory *bim;
|
---|
251 |
|
---|
252 | bim = (struct bfd_in_memory *) abfd->iostream;
|
---|
253 |
|
---|
254 | if (direction == SEEK_SET)
|
---|
255 | abfd->where = position;
|
---|
256 | else
|
---|
257 | abfd->where += position;
|
---|
258 |
|
---|
259 | if (abfd->where > bim->size)
|
---|
260 | {
|
---|
261 | if ((abfd->direction == write_direction) ||
|
---|
262 | (abfd->direction == both_direction))
|
---|
263 | {
|
---|
264 | bfd_size_type newsize, oldsize;
|
---|
265 | oldsize = (bim->size + 127) & ~(bfd_size_type) 127;
|
---|
266 | bim->size = abfd->where;
|
---|
267 | /* Round up to cut down on memory fragmentation */
|
---|
268 | newsize = (bim->size + 127) & ~(bfd_size_type) 127;
|
---|
269 | if (newsize > oldsize)
|
---|
270 | {
|
---|
271 | bim->buffer = (bfd_byte *) bfd_realloc (bim->buffer, newsize);
|
---|
272 | if (bim->buffer == 0)
|
---|
273 | {
|
---|
274 | bim->size = 0;
|
---|
275 | return -1;
|
---|
276 | }
|
---|
277 | }
|
---|
278 | }
|
---|
279 | else
|
---|
280 | {
|
---|
281 | abfd->where = bim->size;
|
---|
282 | bfd_set_error (bfd_error_file_truncated);
|
---|
283 | return -1;
|
---|
284 | }
|
---|
285 | }
|
---|
286 | return 0;
|
---|
287 | }
|
---|
288 |
|
---|
289 | if (abfd->format != bfd_archive && abfd->my_archive == 0)
|
---|
290 | {
|
---|
291 | #if 0
|
---|
292 | /* Explanation for this code: I'm only about 95+% sure that the above
|
---|
293 | conditions are sufficient and that all i/o calls are properly
|
---|
294 | adjusting the `where' field. So this is sort of an `assert'
|
---|
295 | that the `where' field is correct. If we can go a while without
|
---|
296 | tripping the abort, we can probably safely disable this code,
|
---|
297 | so that the real optimizations happen. */
|
---|
298 | file_ptr where_am_i_now;
|
---|
299 | where_am_i_now = ftell (bfd_cache_lookup (abfd));
|
---|
300 | if (abfd->my_archive)
|
---|
301 | where_am_i_now -= abfd->origin;
|
---|
302 | if (where_am_i_now != abfd->where)
|
---|
303 | abort ();
|
---|
304 | #endif
|
---|
305 | if (direction == SEEK_SET && (bfd_vma) position == abfd->where)
|
---|
306 | return 0;
|
---|
307 | }
|
---|
308 | else
|
---|
309 | {
|
---|
310 | /* We need something smarter to optimize access to archives.
|
---|
311 | Currently, anything inside an archive is read via the file
|
---|
312 | handle for the archive. Which means that a bfd_seek on one
|
---|
313 | component affects the `current position' in the archive, as
|
---|
314 | well as in any other component.
|
---|
315 |
|
---|
316 | It might be sufficient to put a spike through the cache
|
---|
317 | abstraction, and look to the archive for the file position,
|
---|
318 | but I think we should try for something cleaner.
|
---|
319 |
|
---|
320 | In the meantime, no optimization for archives. */
|
---|
321 | }
|
---|
322 |
|
---|
323 | f = bfd_cache_lookup (abfd);
|
---|
324 | file_position = position;
|
---|
325 | if (direction == SEEK_SET && abfd->my_archive != NULL)
|
---|
326 | file_position += abfd->origin;
|
---|
327 |
|
---|
328 | result = fseek (f, file_position, direction);
|
---|
329 | if (result != 0)
|
---|
330 | {
|
---|
331 | int hold_errno = errno;
|
---|
332 |
|
---|
333 | /* Force redetermination of `where' field. */
|
---|
334 | bfd_tell (abfd);
|
---|
335 |
|
---|
336 | /* An EINVAL error probably means that the file offset was
|
---|
337 | absurd. */
|
---|
338 | if (hold_errno == EINVAL)
|
---|
339 | bfd_set_error (bfd_error_file_truncated);
|
---|
340 | else
|
---|
341 | {
|
---|
342 | bfd_set_error (bfd_error_system_call);
|
---|
343 | errno = hold_errno;
|
---|
344 | }
|
---|
345 | }
|
---|
346 | else
|
---|
347 | {
|
---|
348 | /* Adjust `where' field. */
|
---|
349 | if (direction == SEEK_SET)
|
---|
350 | abfd->where = position;
|
---|
351 | else
|
---|
352 | abfd->where += position;
|
---|
353 | }
|
---|
354 | return result;
|
---|
355 | }
|
---|
356 |
|
---|
357 | /*
|
---|
358 | FUNCTION
|
---|
359 | bfd_get_mtime
|
---|
360 |
|
---|
361 | SYNOPSIS
|
---|
362 | long bfd_get_mtime(bfd *abfd);
|
---|
363 |
|
---|
364 | DESCRIPTION
|
---|
365 | Return the file modification time (as read from the file system, or
|
---|
366 | from the archive header for archive members).
|
---|
367 |
|
---|
368 | */
|
---|
369 |
|
---|
370 | long
|
---|
371 | bfd_get_mtime (abfd)
|
---|
372 | bfd *abfd;
|
---|
373 | {
|
---|
374 | FILE *fp;
|
---|
375 | struct stat buf;
|
---|
376 |
|
---|
377 | if (abfd->mtime_set)
|
---|
378 | return abfd->mtime;
|
---|
379 |
|
---|
380 | fp = bfd_cache_lookup (abfd);
|
---|
381 | if (0 != fstat (fileno (fp), &buf))
|
---|
382 | return 0;
|
---|
383 |
|
---|
384 | abfd->mtime = buf.st_mtime; /* Save value in case anyone wants it */
|
---|
385 | return buf.st_mtime;
|
---|
386 | }
|
---|
387 |
|
---|
388 | /*
|
---|
389 | FUNCTION
|
---|
390 | bfd_get_size
|
---|
391 |
|
---|
392 | SYNOPSIS
|
---|
393 | long bfd_get_size(bfd *abfd);
|
---|
394 |
|
---|
395 | DESCRIPTION
|
---|
396 | Return the file size (as read from file system) for the file
|
---|
397 | associated with BFD @var{abfd}.
|
---|
398 |
|
---|
399 | The initial motivation for, and use of, this routine is not
|
---|
400 | so we can get the exact size of the object the BFD applies to, since
|
---|
401 | that might not be generally possible (archive members for example).
|
---|
402 | It would be ideal if someone could eventually modify
|
---|
403 | it so that such results were guaranteed.
|
---|
404 |
|
---|
405 | Instead, we want to ask questions like "is this NNN byte sized
|
---|
406 | object I'm about to try read from file offset YYY reasonable?"
|
---|
407 | As as example of where we might do this, some object formats
|
---|
408 | use string tables for which the first <<sizeof (long)>> bytes of the
|
---|
409 | table contain the size of the table itself, including the size bytes.
|
---|
410 | If an application tries to read what it thinks is one of these
|
---|
411 | string tables, without some way to validate the size, and for
|
---|
412 | some reason the size is wrong (byte swapping error, wrong location
|
---|
413 | for the string table, etc.), the only clue is likely to be a read
|
---|
414 | error when it tries to read the table, or a "virtual memory
|
---|
415 | exhausted" error when it tries to allocate 15 bazillon bytes
|
---|
416 | of space for the 15 bazillon byte table it is about to read.
|
---|
417 | This function at least allows us to answer the quesion, "is the
|
---|
418 | size reasonable?".
|
---|
419 | */
|
---|
420 |
|
---|
421 | long
|
---|
422 | bfd_get_size (abfd)
|
---|
423 | bfd *abfd;
|
---|
424 | {
|
---|
425 | FILE *fp;
|
---|
426 | struct stat buf;
|
---|
427 |
|
---|
428 | if ((abfd->flags & BFD_IN_MEMORY) != 0)
|
---|
429 | return ((struct bfd_in_memory *) abfd->iostream)->size;
|
---|
430 |
|
---|
431 | fp = bfd_cache_lookup (abfd);
|
---|
432 | if (0 != fstat (fileno (fp), & buf))
|
---|
433 | return 0;
|
---|
434 |
|
---|
435 | return buf.st_size;
|
---|
436 | }
|
---|