1 |
/* opncls.c -- open and close a BFD. |
/* opncls.c -- open and close a BFD. |
2 |
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, |
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, |
3 |
2001, 2002 |
2001, 2002, 2003, 2004, 2005 |
4 |
Free Software Foundation, Inc. |
Free Software Foundation, Inc. |
5 |
|
|
6 |
Written by Cygnus Support. |
Written by Cygnus Support. |
25 |
#include "sysdep.h" |
#include "sysdep.h" |
26 |
#include "objalloc.h" |
#include "objalloc.h" |
27 |
#include "libbfd.h" |
#include "libbfd.h" |
28 |
|
#include "libiberty.h" |
29 |
|
|
30 |
#ifndef S_IXUSR |
#ifndef S_IXUSR |
31 |
#define S_IXUSR 0100 /* Execute by owner. */ |
#define S_IXUSR 0100 /* Execute by owner. */ |
37 |
#define S_IXOTH 0001 /* Execute by others. */ |
#define S_IXOTH 0001 /* Execute by others. */ |
38 |
#endif |
#endif |
39 |
|
|
40 |
|
/* Counter used to initialize the bfd identifier. */ |
41 |
|
|
42 |
|
static unsigned int _bfd_id_counter = 0; |
43 |
|
|
44 |
/* fdopen is a loser -- we should use stdio exclusively. Unfortunately |
/* fdopen is a loser -- we should use stdio exclusively. Unfortunately |
45 |
if we do that we can't use fcntl. */ |
if we do that we can't use fcntl. */ |
46 |
|
|
47 |
/* Return a new BFD. All BFD's are allocated through this routine. */ |
/* Return a new BFD. All BFD's are allocated through this routine. */ |
48 |
|
|
49 |
bfd * |
bfd * |
50 |
_bfd_new_bfd () |
_bfd_new_bfd (void) |
51 |
{ |
{ |
52 |
bfd *nbfd; |
bfd *nbfd; |
53 |
|
|
54 |
nbfd = (bfd *) bfd_zmalloc ((bfd_size_type) sizeof (bfd)); |
nbfd = bfd_zmalloc (sizeof (bfd)); |
55 |
if (nbfd == NULL) |
if (nbfd == NULL) |
56 |
return NULL; |
return NULL; |
57 |
|
|
58 |
nbfd->memory = (PTR) objalloc_create (); |
nbfd->id = _bfd_id_counter++; |
59 |
|
|
60 |
|
nbfd->memory = objalloc_create (); |
61 |
if (nbfd->memory == NULL) |
if (nbfd->memory == NULL) |
62 |
{ |
{ |
63 |
bfd_set_error (bfd_error_no_memory); |
bfd_set_error (bfd_error_no_memory); |
70 |
nbfd->direction = no_direction; |
nbfd->direction = no_direction; |
71 |
nbfd->iostream = NULL; |
nbfd->iostream = NULL; |
72 |
nbfd->where = 0; |
nbfd->where = 0; |
73 |
if (!bfd_hash_table_init (&nbfd->section_htab, bfd_section_hash_newfunc)) |
if (!bfd_hash_table_init_n (& nbfd->section_htab, bfd_section_hash_newfunc, |
74 |
|
251)) |
75 |
{ |
{ |
76 |
free (nbfd); |
free (nbfd); |
77 |
return NULL; |
return NULL; |
78 |
} |
} |
79 |
nbfd->sections = (asection *) NULL; |
nbfd->sections = NULL; |
80 |
nbfd->section_tail = &nbfd->sections; |
nbfd->section_tail = &nbfd->sections; |
81 |
nbfd->format = bfd_unknown; |
nbfd->format = bfd_unknown; |
82 |
nbfd->my_archive = (bfd *) NULL; |
nbfd->my_archive = NULL; |
83 |
nbfd->origin = 0; |
nbfd->origin = 0; |
84 |
nbfd->opened_once = false; |
nbfd->opened_once = FALSE; |
85 |
nbfd->output_has_begun = false; |
nbfd->output_has_begun = FALSE; |
86 |
nbfd->section_count = 0; |
nbfd->section_count = 0; |
87 |
nbfd->usrdata = (PTR) NULL; |
nbfd->usrdata = NULL; |
88 |
nbfd->cacheable = false; |
nbfd->cacheable = FALSE; |
89 |
nbfd->flags = BFD_NO_FLAGS; |
nbfd->flags = BFD_NO_FLAGS; |
90 |
nbfd->mtime_set = false; |
nbfd->mtime_set = FALSE; |
91 |
|
|
92 |
return nbfd; |
return nbfd; |
93 |
} |
} |
95 |
/* Allocate a new BFD as a member of archive OBFD. */ |
/* Allocate a new BFD as a member of archive OBFD. */ |
96 |
|
|
97 |
bfd * |
bfd * |
98 |
_bfd_new_bfd_contained_in (obfd) |
_bfd_new_bfd_contained_in (bfd *obfd) |
|
bfd *obfd; |
|
99 |
{ |
{ |
100 |
bfd *nbfd; |
bfd *nbfd; |
101 |
|
|
103 |
if (nbfd == NULL) |
if (nbfd == NULL) |
104 |
return NULL; |
return NULL; |
105 |
nbfd->xvec = obfd->xvec; |
nbfd->xvec = obfd->xvec; |
106 |
|
nbfd->iovec = obfd->iovec; |
107 |
nbfd->my_archive = obfd; |
nbfd->my_archive = obfd; |
108 |
nbfd->direction = read_direction; |
nbfd->direction = read_direction; |
109 |
nbfd->target_defaulted = obfd->target_defaulted; |
nbfd->target_defaulted = obfd->target_defaulted; |
113 |
/* Delete a BFD. */ |
/* Delete a BFD. */ |
114 |
|
|
115 |
void |
void |
116 |
_bfd_delete_bfd (abfd) |
_bfd_delete_bfd (bfd *abfd) |
|
bfd *abfd; |
|
117 |
{ |
{ |
118 |
bfd_hash_table_free (&abfd->section_htab); |
bfd_hash_table_free (&abfd->section_htab); |
119 |
objalloc_free ((struct objalloc *) abfd->memory); |
objalloc_free ((struct objalloc *) abfd->memory); |
131 |
bfd_openr |
bfd_openr |
132 |
|
|
133 |
SYNOPSIS |
SYNOPSIS |
134 |
bfd *bfd_openr(const char *filename, const char *target); |
bfd *bfd_openr (const char *filename, const char *target); |
135 |
|
|
136 |
DESCRIPTION |
DESCRIPTION |
137 |
Open the file @var{filename} (using <<fopen>>) with the target |
Open the file @var{filename} (using <<fopen>>) with the target |
141 |
that function. |
that function. |
142 |
|
|
143 |
If <<NULL>> is returned then an error has occured. Possible errors |
If <<NULL>> is returned then an error has occured. Possible errors |
144 |
are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> or <<system_call>> error. |
are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> or |
145 |
|
<<system_call>> error. |
146 |
*/ |
*/ |
147 |
|
|
148 |
bfd * |
bfd * |
149 |
bfd_openr (filename, target) |
bfd_openr (const char *filename, const char *target) |
|
const char *filename; |
|
|
const char *target; |
|
150 |
{ |
{ |
151 |
bfd *nbfd; |
bfd *nbfd; |
152 |
const bfd_target *target_vec; |
const bfd_target *target_vec; |
185 |
the file descriptor too, even though we didn't open it. */ |
the file descriptor too, even though we didn't open it. */ |
186 |
/* |
/* |
187 |
FUNCTION |
FUNCTION |
188 |
bfd_fdopenr |
bfd_fdopenr |
189 |
|
|
190 |
SYNOPSIS |
SYNOPSIS |
191 |
bfd *bfd_fdopenr(const char *filename, const char *target, int fd); |
bfd *bfd_fdopenr (const char *filename, const char *target, int fd); |
192 |
|
|
193 |
DESCRIPTION |
DESCRIPTION |
194 |
<<bfd_fdopenr>> is to <<bfd_fopenr>> much like <<fdopen>> is to <<fopen>>. |
<<bfd_fdopenr>> is to <<bfd_fopenr>> much like <<fdopen>> is to |
195 |
It opens a BFD on a file already described by the @var{fd} |
<<fopen>>. It opens a BFD on a file already described by the |
196 |
supplied. |
@var{fd} supplied. |
197 |
|
|
198 |
When the file is later <<bfd_close>>d, the file descriptor will be closed. |
When the file is later <<bfd_close>>d, the file descriptor will |
199 |
|
be closed. If the caller desires that this file descriptor be |
200 |
If the caller desires that this file descriptor be cached by BFD |
cached by BFD (opened as needed, closed as needed to free |
201 |
(opened as needed, closed as needed to free descriptors for |
descriptors for other opens), with the supplied @var{fd} used as |
202 |
other opens), with the supplied @var{fd} used as an initial |
an initial file descriptor (but subject to closure at any time), |
203 |
file descriptor (but subject to closure at any time), call |
call bfd_set_cacheable(bfd, 1) on the returned BFD. The default |
204 |
bfd_set_cacheable(bfd, 1) on the returned BFD. The default is to |
is to assume no caching; the file descriptor will remain open |
205 |
assume no cacheing; the file descriptor will remain open until |
until <<bfd_close>>, and will not be affected by BFD operations |
206 |
<<bfd_close>>, and will not be affected by BFD operations on other |
on other files. |
|
files. |
|
207 |
|
|
208 |
Possible errors are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> and <<bfd_error_system_call>>. |
Possible errors are <<bfd_error_no_memory>>, |
209 |
|
<<bfd_error_invalid_target>> and <<bfd_error_system_call>>. |
210 |
*/ |
*/ |
211 |
|
|
212 |
bfd * |
bfd * |
213 |
bfd_fdopenr (filename, target, fd) |
bfd_fdopenr (const char *filename, const char *target, int fd) |
|
const char *filename; |
|
|
const char *target; |
|
|
int fd; |
|
214 |
{ |
{ |
215 |
bfd *nbfd; |
bfd *nbfd; |
216 |
const bfd_target *target_vec; |
const bfd_target *target_vec; |
237 |
} |
} |
238 |
|
|
239 |
#ifndef HAVE_FDOPEN |
#ifndef HAVE_FDOPEN |
240 |
nbfd->iostream = (PTR) fopen (filename, FOPEN_RB); |
nbfd->iostream = fopen (filename, FOPEN_RB); |
241 |
#else |
#else |
242 |
/* (O_ACCMODE) parens are to avoid Ultrix header file bug. */ |
/* (O_ACCMODE) parens are to avoid Ultrix header file bug. */ |
243 |
switch (fdflags & (O_ACCMODE)) |
switch (fdflags & (O_ACCMODE)) |
244 |
{ |
{ |
245 |
case O_RDONLY: nbfd->iostream = (PTR) fdopen (fd, FOPEN_RB); break; |
case O_RDONLY: nbfd->iostream = fdopen (fd, FOPEN_RB); break; |
246 |
case O_WRONLY: nbfd->iostream = (PTR) fdopen (fd, FOPEN_RUB); break; |
case O_WRONLY: nbfd->iostream = fdopen (fd, FOPEN_RUB); break; |
247 |
case O_RDWR: nbfd->iostream = (PTR) fdopen (fd, FOPEN_RUB); break; |
case O_RDWR: nbfd->iostream = fdopen (fd, FOPEN_RUB); break; |
248 |
default: abort (); |
default: abort (); |
249 |
} |
} |
250 |
#endif |
#endif |
275 |
_bfd_delete_bfd (nbfd); |
_bfd_delete_bfd (nbfd); |
276 |
return NULL; |
return NULL; |
277 |
} |
} |
278 |
nbfd->opened_once = true; |
nbfd->opened_once = TRUE; |
279 |
|
|
280 |
return nbfd; |
return nbfd; |
281 |
} |
} |
285 |
bfd_openstreamr |
bfd_openstreamr |
286 |
|
|
287 |
SYNOPSIS |
SYNOPSIS |
288 |
bfd *bfd_openstreamr(const char *, const char *, PTR); |
bfd *bfd_openstreamr (const char *, const char *, void *); |
289 |
|
|
290 |
DESCRIPTION |
DESCRIPTION |
291 |
|
|
294 |
*/ |
*/ |
295 |
|
|
296 |
bfd * |
bfd * |
297 |
bfd_openstreamr (filename, target, streamarg) |
bfd_openstreamr (const char *filename, const char *target, void *streamarg) |
|
const char *filename; |
|
|
const char *target; |
|
|
PTR streamarg; |
|
298 |
{ |
{ |
299 |
FILE *stream = (FILE *) streamarg; |
FILE *stream = streamarg; |
300 |
bfd *nbfd; |
bfd *nbfd; |
301 |
const bfd_target *target_vec; |
const bfd_target *target_vec; |
302 |
|
|
311 |
return NULL; |
return NULL; |
312 |
} |
} |
313 |
|
|
314 |
nbfd->iostream = (PTR) stream; |
nbfd->iostream = stream; |
315 |
nbfd->filename = filename; |
nbfd->filename = filename; |
316 |
nbfd->direction = read_direction; |
nbfd->direction = read_direction; |
317 |
|
|
323 |
|
|
324 |
return nbfd; |
return nbfd; |
325 |
} |
} |
326 |
|
|
327 |
|
/* |
328 |
|
FUNCTION |
329 |
|
bfd_openr_iovec |
330 |
|
|
331 |
|
SYNOPSIS |
332 |
|
bfd *bfd_openr_iovec (const char *filename, const char *target, |
333 |
|
void *(*open) (struct bfd *nbfd, |
334 |
|
void *open_closure), |
335 |
|
void *open_closure, |
336 |
|
file_ptr (*pread) (struct bfd *nbfd, |
337 |
|
void *stream, |
338 |
|
void *buf, |
339 |
|
file_ptr nbytes, |
340 |
|
file_ptr offset), |
341 |
|
int (*close) (struct bfd *nbfd, |
342 |
|
void *stream)); |
343 |
|
|
344 |
|
DESCRIPTION |
345 |
|
|
346 |
|
Create and return a BFD backed by a read-only @var{stream}. |
347 |
|
The @var{stream} is created using @var{open}, accessed using |
348 |
|
@var{pread} and destroyed using @var{close}. |
349 |
|
|
350 |
|
Calls <<bfd_find_target>>, so @var{target} is interpreted as by |
351 |
|
that function. |
352 |
|
|
353 |
|
Calls @var{open} (which can call <<bfd_zalloc>> and |
354 |
|
<<bfd_get_filename>>) to obtain the read-only stream backing |
355 |
|
the BFD. @var{open} either succeeds returning the |
356 |
|
non-<<NULL>> @var{stream}, or fails returning <<NULL>> |
357 |
|
(setting <<bfd_error>>). |
358 |
|
|
359 |
|
Calls @var{pread} to request @var{nbytes} of data from |
360 |
|
@var{stream} starting at @var{offset} (e.g., via a call to |
361 |
|
<<bfd_read>>). @var{pread} either succeeds returning the |
362 |
|
number of bytes read (which can be less than @var{nbytes} when |
363 |
|
end-of-file), or fails returning -1 (setting <<bfd_error>>). |
364 |
|
|
365 |
|
Calls @var{close} when the BFD is later closed using |
366 |
|
<<bfd_close>>. @var{close} either succeeds returning 0, or |
367 |
|
fails returning -1 (setting <<bfd_error>>). |
368 |
|
|
369 |
|
If <<bfd_openr_iovec>> returns <<NULL>> then an error has |
370 |
|
occurred. Possible errors are <<bfd_error_no_memory>>, |
371 |
|
<<bfd_error_invalid_target>> and <<bfd_error_system_call>>. |
372 |
|
|
373 |
|
*/ |
374 |
|
|
375 |
|
struct opncls |
376 |
|
{ |
377 |
|
void *stream; |
378 |
|
file_ptr (*pread) (struct bfd *abfd, void *stream, void *buf, |
379 |
|
file_ptr nbytes, file_ptr offset); |
380 |
|
int (*close) (struct bfd *abfd, void *stream); |
381 |
|
file_ptr where; |
382 |
|
}; |
383 |
|
|
384 |
|
static file_ptr |
385 |
|
opncls_btell (struct bfd *abfd) |
386 |
|
{ |
387 |
|
struct opncls *vec = abfd->iostream; |
388 |
|
return vec->where; |
389 |
|
} |
390 |
|
|
391 |
|
static int |
392 |
|
opncls_bseek (struct bfd *abfd, file_ptr offset, int whence) |
393 |
|
{ |
394 |
|
struct opncls *vec = abfd->iostream; |
395 |
|
switch (whence) |
396 |
|
{ |
397 |
|
case SEEK_SET: vec->where = offset; break; |
398 |
|
case SEEK_CUR: vec->where += offset; break; |
399 |
|
case SEEK_END: return -1; |
400 |
|
} |
401 |
|
return 0; |
402 |
|
} |
403 |
|
|
404 |
|
static file_ptr |
405 |
|
opncls_bread (struct bfd *abfd, void *buf, file_ptr nbytes) |
406 |
|
{ |
407 |
|
struct opncls *vec = abfd->iostream; |
408 |
|
file_ptr nread = (vec->pread) (abfd, vec->stream, buf, nbytes, vec->where); |
409 |
|
if (nread < 0) |
410 |
|
return nread; |
411 |
|
vec->where += nread; |
412 |
|
return nread; |
413 |
|
} |
414 |
|
|
415 |
|
static file_ptr |
416 |
|
opncls_bwrite (struct bfd *abfd ATTRIBUTE_UNUSED, |
417 |
|
const void *where ATTRIBUTE_UNUSED, |
418 |
|
file_ptr nbytes ATTRIBUTE_UNUSED) |
419 |
|
{ |
420 |
|
return -1; |
421 |
|
} |
422 |
|
|
423 |
|
static int |
424 |
|
opncls_bclose (struct bfd *abfd) |
425 |
|
{ |
426 |
|
struct opncls *vec = abfd->iostream; |
427 |
|
/* Since the VEC's memory is bound to the bfd deleting the bfd will |
428 |
|
free it. */ |
429 |
|
int status = 0; |
430 |
|
if (vec->close != NULL) |
431 |
|
status = (vec->close) (abfd, vec->stream); |
432 |
|
abfd->iostream = NULL; |
433 |
|
return status; |
434 |
|
} |
435 |
|
|
436 |
|
static int |
437 |
|
opncls_bflush (struct bfd *abfd ATTRIBUTE_UNUSED) |
438 |
|
{ |
439 |
|
return 0; |
440 |
|
} |
441 |
|
|
442 |
|
static int |
443 |
|
opncls_bstat (struct bfd *abfd ATTRIBUTE_UNUSED, struct stat *sb) |
444 |
|
{ |
445 |
|
memset (sb, 0, sizeof (*sb)); |
446 |
|
return 0; |
447 |
|
} |
448 |
|
|
449 |
|
static const struct bfd_iovec opncls_iovec = { |
450 |
|
&opncls_bread, &opncls_bwrite, &opncls_btell, &opncls_bseek, |
451 |
|
&opncls_bclose, &opncls_bflush, &opncls_bstat |
452 |
|
}; |
453 |
|
|
454 |
|
bfd * |
455 |
|
bfd_openr_iovec (const char *filename, const char *target, |
456 |
|
void *(*open) (struct bfd *nbfd, |
457 |
|
void *open_closure), |
458 |
|
void *open_closure, |
459 |
|
file_ptr (*pread) (struct bfd *abfd, |
460 |
|
void *stream, |
461 |
|
void *buf, |
462 |
|
file_ptr nbytes, |
463 |
|
file_ptr offset), |
464 |
|
int (*close) (struct bfd *nbfd, |
465 |
|
void *stream)) |
466 |
|
{ |
467 |
|
bfd *nbfd; |
468 |
|
const bfd_target *target_vec; |
469 |
|
struct opncls *vec; |
470 |
|
void *stream; |
471 |
|
|
472 |
|
nbfd = _bfd_new_bfd (); |
473 |
|
if (nbfd == NULL) |
474 |
|
return NULL; |
475 |
|
|
476 |
|
target_vec = bfd_find_target (target, nbfd); |
477 |
|
if (target_vec == NULL) |
478 |
|
{ |
479 |
|
_bfd_delete_bfd (nbfd); |
480 |
|
return NULL; |
481 |
|
} |
482 |
|
|
483 |
|
nbfd->filename = filename; |
484 |
|
nbfd->direction = read_direction; |
485 |
|
|
486 |
|
stream = open (nbfd, open_closure); |
487 |
|
if (stream == NULL) |
488 |
|
{ |
489 |
|
_bfd_delete_bfd (nbfd); |
490 |
|
return NULL; |
491 |
|
} |
492 |
|
|
493 |
|
vec = bfd_zalloc (nbfd, sizeof (struct opncls)); |
494 |
|
vec->stream = stream; |
495 |
|
vec->pread = pread; |
496 |
|
vec->close = close; |
497 |
|
|
498 |
|
nbfd->iovec = &opncls_iovec; |
499 |
|
nbfd->iostream = vec; |
500 |
|
|
501 |
|
return nbfd; |
502 |
|
} |
503 |
|
|
504 |
/* bfd_openw -- open for writing. |
/* bfd_openw -- open for writing. |
505 |
Returns a pointer to a freshly-allocated BFD on success, or NULL. |
Returns a pointer to a freshly-allocated BFD on success, or NULL. |
511 |
bfd_openw |
bfd_openw |
512 |
|
|
513 |
SYNOPSIS |
SYNOPSIS |
514 |
bfd *bfd_openw(const char *filename, const char *target); |
bfd *bfd_openw (const char *filename, const char *target); |
515 |
|
|
516 |
DESCRIPTION |
DESCRIPTION |
517 |
Create a BFD, associated with file @var{filename}, using the |
Create a BFD, associated with file @var{filename}, using the |
522 |
*/ |
*/ |
523 |
|
|
524 |
bfd * |
bfd * |
525 |
bfd_openw (filename, target) |
bfd_openw (const char *filename, const char *target) |
|
const char *filename; |
|
|
const char *target; |
|
526 |
{ |
{ |
527 |
bfd *nbfd; |
bfd *nbfd; |
528 |
const bfd_target *target_vec; |
const bfd_target *target_vec; |
560 |
bfd_close |
bfd_close |
561 |
|
|
562 |
SYNOPSIS |
SYNOPSIS |
563 |
boolean bfd_close(bfd *abfd); |
bfd_boolean bfd_close (bfd *abfd); |
564 |
|
|
565 |
DESCRIPTION |
DESCRIPTION |
566 |
|
|
567 |
Close a BFD. If the BFD was open for writing, |
Close a BFD. If the BFD was open for writing, then pending |
568 |
then pending operations are completed and the file written out |
operations are completed and the file written out and closed. |
569 |
and closed. If the created file is executable, then |
If the created file is executable, then <<chmod>> is called |
570 |
<<chmod>> is called to mark it as such. |
to mark it as such. |
571 |
|
|
572 |
All memory attached to the BFD is released. |
All memory attached to the BFD is released. |
573 |
|
|
575 |
if it was passed in to BFD by <<bfd_fdopenr>>). |
if it was passed in to BFD by <<bfd_fdopenr>>). |
576 |
|
|
577 |
RETURNS |
RETURNS |
578 |
<<true>> is returned if all is ok, otherwise <<false>>. |
<<TRUE>> is returned if all is ok, otherwise <<FALSE>>. |
579 |
*/ |
*/ |
580 |
|
|
581 |
|
|
582 |
boolean |
bfd_boolean |
583 |
bfd_close (abfd) |
bfd_close (bfd *abfd) |
|
bfd *abfd; |
|
584 |
{ |
{ |
585 |
boolean ret; |
bfd_boolean ret; |
586 |
|
|
587 |
if (bfd_write_p (abfd)) |
if (bfd_write_p (abfd)) |
588 |
{ |
{ |
589 |
if (! BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd))) |
if (! BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd))) |
590 |
return false; |
return FALSE; |
591 |
} |
} |
592 |
|
|
593 |
if (! BFD_SEND (abfd, _close_and_cleanup, (abfd))) |
if (! BFD_SEND (abfd, _close_and_cleanup, (abfd))) |
594 |
return false; |
return FALSE; |
595 |
|
|
596 |
ret = bfd_cache_close (abfd); |
/* FIXME: cagney/2004-02-15: Need to implement a BFD_IN_MEMORY io |
597 |
|
vector. */ |
598 |
|
if (!(abfd->flags & BFD_IN_MEMORY)) |
599 |
|
ret = abfd->iovec->bclose (abfd); |
600 |
|
else |
601 |
|
ret = TRUE; |
602 |
|
|
603 |
/* If the file was open for writing and is now executable, |
/* If the file was open for writing and is now executable, |
604 |
make it so. */ |
make it so. */ |
610 |
|
|
611 |
if (stat (abfd->filename, &buf) == 0) |
if (stat (abfd->filename, &buf) == 0) |
612 |
{ |
{ |
613 |
unsigned int mask = umask (0); |
unsigned int mask = umask (0); |
614 |
|
|
615 |
umask (mask); |
umask (mask); |
616 |
chmod (abfd->filename, |
chmod (abfd->filename, |
629 |
bfd_close_all_done |
bfd_close_all_done |
630 |
|
|
631 |
SYNOPSIS |
SYNOPSIS |
632 |
boolean bfd_close_all_done(bfd *); |
bfd_boolean bfd_close_all_done (bfd *); |
633 |
|
|
634 |
DESCRIPTION |
DESCRIPTION |
635 |
Close a BFD. Differs from <<bfd_close>> |
Close a BFD. Differs from <<bfd_close>> since it does not |
636 |
since it does not complete any pending operations. This |
complete any pending operations. This routine would be used |
637 |
routine would be used if the application had just used BFD for |
if the application had just used BFD for swapping and didn't |
638 |
swapping and didn't want to use any of the writing code. |
want to use any of the writing code. |
639 |
|
|
640 |
If the created file is executable, then <<chmod>> is called |
If the created file is executable, then <<chmod>> is called |
641 |
to mark it as such. |
to mark it as such. |
643 |
All memory attached to the BFD is released. |
All memory attached to the BFD is released. |
644 |
|
|
645 |
RETURNS |
RETURNS |
646 |
<<true>> is returned if all is ok, otherwise <<false>>. |
<<TRUE>> is returned if all is ok, otherwise <<FALSE>>. |
647 |
*/ |
*/ |
648 |
|
|
649 |
boolean |
bfd_boolean |
650 |
bfd_close_all_done (abfd) |
bfd_close_all_done (bfd *abfd) |
|
bfd *abfd; |
|
651 |
{ |
{ |
652 |
boolean ret; |
bfd_boolean ret; |
653 |
|
|
654 |
ret = bfd_cache_close (abfd); |
ret = bfd_cache_close (abfd); |
655 |
|
|
682 |
bfd_create |
bfd_create |
683 |
|
|
684 |
SYNOPSIS |
SYNOPSIS |
685 |
bfd *bfd_create(const char *filename, bfd *templ); |
bfd *bfd_create (const char *filename, bfd *templ); |
686 |
|
|
687 |
DESCRIPTION |
DESCRIPTION |
688 |
Create a new BFD in the manner of |
Create a new BFD in the manner of <<bfd_openw>>, but without |
689 |
<<bfd_openw>>, but without opening a file. The new BFD |
opening a file. The new BFD takes the target from the target |
690 |
takes the target from the target used by @var{template}. The |
used by @var{template}. The format is always set to <<bfd_object>>. |
|
format is always set to <<bfd_object>>. |
|
691 |
*/ |
*/ |
692 |
|
|
693 |
bfd * |
bfd * |
694 |
bfd_create (filename, templ) |
bfd_create (const char *filename, bfd *templ) |
|
const char *filename; |
|
|
bfd *templ; |
|
695 |
{ |
{ |
696 |
bfd *nbfd; |
bfd *nbfd; |
697 |
|
|
712 |
bfd_make_writable |
bfd_make_writable |
713 |
|
|
714 |
SYNOPSIS |
SYNOPSIS |
715 |
boolean bfd_make_writable(bfd *abfd); |
bfd_boolean bfd_make_writable (bfd *abfd); |
716 |
|
|
717 |
DESCRIPTION |
DESCRIPTION |
718 |
Takes a BFD as created by <<bfd_create>> and converts it |
Takes a BFD as created by <<bfd_create>> and converts it |
721 |
you will call <<bfd_make_readable>> on this bfd later. |
you will call <<bfd_make_readable>> on this bfd later. |
722 |
|
|
723 |
RETURNS |
RETURNS |
724 |
<<true>> is returned if all is ok, otherwise <<false>>. |
<<TRUE>> is returned if all is ok, otherwise <<FALSE>>. |
725 |
*/ |
*/ |
726 |
|
|
727 |
boolean |
bfd_boolean |
728 |
bfd_make_writable(abfd) |
bfd_make_writable (bfd *abfd) |
|
bfd *abfd; |
|
729 |
{ |
{ |
730 |
struct bfd_in_memory *bim; |
struct bfd_in_memory *bim; |
731 |
|
|
732 |
if (abfd->direction != no_direction) |
if (abfd->direction != no_direction) |
733 |
{ |
{ |
734 |
bfd_set_error (bfd_error_invalid_operation); |
bfd_set_error (bfd_error_invalid_operation); |
735 |
return false; |
return FALSE; |
736 |
} |
} |
737 |
|
|
738 |
bim = ((struct bfd_in_memory *) |
bim = bfd_malloc (sizeof (struct bfd_in_memory)); |
739 |
bfd_malloc ((bfd_size_type) sizeof (struct bfd_in_memory))); |
abfd->iostream = bim; |
|
abfd->iostream = (PTR) bim; |
|
740 |
/* bfd_bwrite will grow these as needed. */ |
/* bfd_bwrite will grow these as needed. */ |
741 |
bim->size = 0; |
bim->size = 0; |
742 |
bim->buffer = 0; |
bim->buffer = 0; |
745 |
abfd->direction = write_direction; |
abfd->direction = write_direction; |
746 |
abfd->where = 0; |
abfd->where = 0; |
747 |
|
|
748 |
return true; |
return TRUE; |
749 |
} |
} |
750 |
|
|
751 |
/* |
/* |
753 |
bfd_make_readable |
bfd_make_readable |
754 |
|
|
755 |
SYNOPSIS |
SYNOPSIS |
756 |
boolean bfd_make_readable(bfd *abfd); |
bfd_boolean bfd_make_readable (bfd *abfd); |
757 |
|
|
758 |
DESCRIPTION |
DESCRIPTION |
759 |
Takes a BFD as created by <<bfd_create>> and |
Takes a BFD as created by <<bfd_create>> and |
763 |
direction. |
direction. |
764 |
|
|
765 |
RETURNS |
RETURNS |
766 |
<<true>> is returned if all is ok, otherwise <<false>>. */ |
<<TRUE>> is returned if all is ok, otherwise <<FALSE>>. */ |
767 |
|
|
768 |
boolean |
bfd_boolean |
769 |
bfd_make_readable(abfd) |
bfd_make_readable (bfd *abfd) |
|
bfd *abfd; |
|
770 |
{ |
{ |
771 |
if (abfd->direction != write_direction || !(abfd->flags & BFD_IN_MEMORY)) |
if (abfd->direction != write_direction || !(abfd->flags & BFD_IN_MEMORY)) |
772 |
{ |
{ |
773 |
bfd_set_error (bfd_error_invalid_operation); |
bfd_set_error (bfd_error_invalid_operation); |
774 |
return false; |
return FALSE; |
775 |
} |
} |
776 |
|
|
777 |
if (! BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd))) |
if (! BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd))) |
778 |
return false; |
return FALSE; |
779 |
|
|
780 |
if (! BFD_SEND (abfd, _close_and_cleanup, (abfd))) |
if (! BFD_SEND (abfd, _close_and_cleanup, (abfd))) |
781 |
return false; |
return FALSE; |
782 |
|
|
783 |
|
|
784 |
abfd->arch_info = &bfd_default_arch_struct; |
abfd->arch_info = &bfd_default_arch_struct; |
785 |
|
|
786 |
abfd->where = 0; |
abfd->where = 0; |
787 |
abfd->format = bfd_unknown; |
abfd->format = bfd_unknown; |
788 |
abfd->my_archive = (bfd *) NULL; |
abfd->my_archive = NULL; |
789 |
abfd->origin = 0; |
abfd->origin = 0; |
790 |
abfd->opened_once = false; |
abfd->opened_once = FALSE; |
791 |
abfd->output_has_begun = false; |
abfd->output_has_begun = FALSE; |
792 |
abfd->section_count = 0; |
abfd->section_count = 0; |
793 |
abfd->usrdata = (PTR) NULL; |
abfd->usrdata = NULL; |
794 |
abfd->cacheable = false; |
abfd->cacheable = FALSE; |
795 |
abfd->flags = BFD_IN_MEMORY; |
abfd->flags = BFD_IN_MEMORY; |
796 |
abfd->mtime_set = false; |
abfd->mtime_set = FALSE; |
797 |
|
|
798 |
abfd->target_defaulted = true; |
abfd->target_defaulted = TRUE; |
799 |
abfd->direction = read_direction; |
abfd->direction = read_direction; |
800 |
abfd->sections = 0; |
abfd->sections = 0; |
801 |
abfd->symcount = 0; |
abfd->symcount = 0; |
805 |
bfd_section_list_clear (abfd); |
bfd_section_list_clear (abfd); |
806 |
bfd_check_format (abfd, bfd_object); |
bfd_check_format (abfd, bfd_object); |
807 |
|
|
808 |
return true; |
return TRUE; |
809 |
} |
} |
810 |
|
|
811 |
/* |
/* |
813 |
bfd_alloc |
bfd_alloc |
814 |
|
|
815 |
SYNOPSIS |
SYNOPSIS |
816 |
PTR bfd_alloc (bfd *abfd, size_t wanted); |
void *bfd_alloc (bfd *abfd, bfd_size_type wanted); |
817 |
|
|
818 |
DESCRIPTION |
DESCRIPTION |
819 |
Allocate a block of @var{wanted} bytes of memory attached to |
Allocate a block of @var{wanted} bytes of memory attached to |
820 |
<<abfd>> and return a pointer to it. |
<<abfd>> and return a pointer to it. |
821 |
*/ |
*/ |
822 |
|
|
823 |
|
void * |
824 |
PTR |
bfd_alloc (bfd *abfd, bfd_size_type size) |
|
bfd_alloc (abfd, size) |
|
|
bfd *abfd; |
|
|
bfd_size_type size; |
|
825 |
{ |
{ |
826 |
PTR ret; |
void *ret; |
827 |
|
|
828 |
if (size != (unsigned long) size) |
if (size != (unsigned long) size) |
829 |
{ |
{ |
837 |
return ret; |
return ret; |
838 |
} |
} |
839 |
|
|
840 |
PTR |
/* |
841 |
bfd_zalloc (abfd, size) |
INTERNAL_FUNCTION |
842 |
bfd *abfd; |
bfd_zalloc |
843 |
bfd_size_type size; |
|
844 |
|
SYNOPSIS |
845 |
|
void *bfd_zalloc (bfd *abfd, bfd_size_type wanted); |
846 |
|
|
847 |
|
DESCRIPTION |
848 |
|
Allocate a block of @var{wanted} bytes of zeroed memory |
849 |
|
attached to <<abfd>> and return a pointer to it. |
850 |
|
*/ |
851 |
|
|
852 |
|
void * |
853 |
|
bfd_zalloc (bfd *abfd, bfd_size_type size) |
854 |
{ |
{ |
855 |
PTR res; |
void *res; |
856 |
|
|
857 |
res = bfd_alloc (abfd, size); |
res = bfd_alloc (abfd, size); |
858 |
if (res) |
if (res) |
864 |
Note: Also frees all more recently allocated blocks! */ |
Note: Also frees all more recently allocated blocks! */ |
865 |
|
|
866 |
void |
void |
867 |
bfd_release (abfd, block) |
bfd_release (bfd *abfd, void *block) |
|
bfd *abfd; |
|
|
PTR block; |
|
868 |
{ |
{ |
869 |
objalloc_free_block ((struct objalloc *) abfd->memory, block); |
objalloc_free_block ((struct objalloc *) abfd->memory, block); |
870 |
} |
} |
871 |
|
|
872 |
|
|
873 |
|
/* |
874 |
|
GNU Extension: separate debug-info files |
875 |
|
|
876 |
|
The idea here is that a special section called .gnu_debuglink might be |
877 |
|
embedded in a binary file, which indicates that some *other* file |
878 |
|
contains the real debugging information. This special section contains a |
879 |
|
filename and CRC32 checksum, which we read and resolve to another file, |
880 |
|
if it exists. |
881 |
|
|
882 |
|
This facilitates "optional" provision of debugging information, without |
883 |
|
having to provide two complete copies of every binary object (with and |
884 |
|
without debug symbols). |
885 |
|
*/ |
886 |
|
|
887 |
|
#define GNU_DEBUGLINK ".gnu_debuglink" |
888 |
|
/* |
889 |
|
FUNCTION |
890 |
|
bfd_calc_gnu_debuglink_crc32 |
891 |
|
|
892 |
|
SYNOPSIS |
893 |
|
unsigned long bfd_calc_gnu_debuglink_crc32 |
894 |
|
(unsigned long crc, const unsigned char *buf, bfd_size_type len); |
895 |
|
|
896 |
|
DESCRIPTION |
897 |
|
Computes a CRC value as used in the .gnu_debuglink section. |
898 |
|
Advances the previously computed @var{crc} value by computing |
899 |
|
and adding in the crc32 for @var{len} bytes of @var{buf}. |
900 |
|
|
901 |
|
RETURNS |
902 |
|
Return the updated CRC32 value. |
903 |
|
*/ |
904 |
|
|
905 |
|
unsigned long |
906 |
|
bfd_calc_gnu_debuglink_crc32 (unsigned long crc, |
907 |
|
const unsigned char *buf, |
908 |
|
bfd_size_type len) |
909 |
|
{ |
910 |
|
static const unsigned long crc32_table[256] = |
911 |
|
{ |
912 |
|
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, |
913 |
|
0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, |
914 |
|
0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, |
915 |
|
0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, |
916 |
|
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, |
917 |
|
0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, |
918 |
|
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, |
919 |
|
0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, |
920 |
|
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, |
921 |
|
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, |
922 |
|
0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, |
923 |
|
0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, |
924 |
|
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, |
925 |
|
0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, |
926 |
|
0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, |
927 |
|
0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, |
928 |
|
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, |
929 |
|
0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, |
930 |
|
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, |
931 |
|
0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, |
932 |
|
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, |
933 |
|
0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, |
934 |
|
0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, |
935 |
|
0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, |
936 |
|
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, |
937 |
|
0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, |
938 |
|
0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, |
939 |
|
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, |
940 |
|
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, |
941 |
|
0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, |
942 |
|
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, |
943 |
|
0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, |
944 |
|
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, |
945 |
|
0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, |
946 |
|
0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, |
947 |
|
0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, |
948 |
|
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, |
949 |
|
0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, |
950 |
|
0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, |
951 |
|
0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, |
952 |
|
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, |
953 |
|
0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, |
954 |
|
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, |
955 |
|
0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, |
956 |
|
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, |
957 |
|
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, |
958 |
|
0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, |
959 |
|
0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, |
960 |
|
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, |
961 |
|
0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, |
962 |
|
0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, |
963 |
|
0x2d02ef8d |
964 |
|
}; |
965 |
|
const unsigned char *end; |
966 |
|
|
967 |
|
crc = ~crc & 0xffffffff; |
968 |
|
for (end = buf + len; buf < end; ++ buf) |
969 |
|
crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8); |
970 |
|
return ~crc & 0xffffffff;; |
971 |
|
} |
972 |
|
|
973 |
|
|
974 |
|
/* |
975 |
|
INTERNAL_FUNCTION |
976 |
|
get_debug_link_info |
977 |
|
|
978 |
|
SYNOPSIS |
979 |
|
char *get_debug_link_info (bfd *abfd, unsigned long *crc32_out); |
980 |
|
|
981 |
|
DESCRIPTION |
982 |
|
fetch the filename and CRC32 value for any separate debuginfo |
983 |
|
associated with @var{abfd}. Return NULL if no such info found, |
984 |
|
otherwise return filename and update @var{crc32_out}. |
985 |
|
*/ |
986 |
|
|
987 |
|
static char * |
988 |
|
get_debug_link_info (bfd *abfd, unsigned long *crc32_out) |
989 |
|
{ |
990 |
|
asection *sect; |
991 |
|
unsigned long crc32; |
992 |
|
bfd_byte *contents; |
993 |
|
int crc_offset; |
994 |
|
char *name; |
995 |
|
|
996 |
|
BFD_ASSERT (abfd); |
997 |
|
BFD_ASSERT (crc32_out); |
998 |
|
|
999 |
|
sect = bfd_get_section_by_name (abfd, GNU_DEBUGLINK); |
1000 |
|
|
1001 |
|
if (sect == NULL) |
1002 |
|
return NULL; |
1003 |
|
|
1004 |
|
if (!bfd_malloc_and_get_section (abfd, sect, &contents)) |
1005 |
|
{ |
1006 |
|
if (contents != NULL) |
1007 |
|
free (contents); |
1008 |
|
return NULL; |
1009 |
|
} |
1010 |
|
|
1011 |
|
/* Crc value is stored after the filename, aligned up to 4 bytes. */ |
1012 |
|
name = (char *) contents; |
1013 |
|
crc_offset = strlen (name) + 1; |
1014 |
|
crc_offset = (crc_offset + 3) & ~3; |
1015 |
|
|
1016 |
|
crc32 = bfd_get_32 (abfd, contents + crc_offset); |
1017 |
|
|
1018 |
|
*crc32_out = crc32; |
1019 |
|
return name; |
1020 |
|
} |
1021 |
|
|
1022 |
|
/* |
1023 |
|
INTERNAL_FUNCTION |
1024 |
|
separate_debug_file_exists |
1025 |
|
|
1026 |
|
SYNOPSIS |
1027 |
|
bfd_boolean separate_debug_file_exists |
1028 |
|
(char *name, unsigned long crc32); |
1029 |
|
|
1030 |
|
DESCRIPTION |
1031 |
|
Checks to see if @var{name} is a file and if its contents |
1032 |
|
match @var{crc32}. |
1033 |
|
*/ |
1034 |
|
|
1035 |
|
static bfd_boolean |
1036 |
|
separate_debug_file_exists (const char *name, const unsigned long crc) |
1037 |
|
{ |
1038 |
|
static unsigned char buffer [8 * 1024]; |
1039 |
|
unsigned long file_crc = 0; |
1040 |
|
int fd; |
1041 |
|
bfd_size_type count; |
1042 |
|
|
1043 |
|
BFD_ASSERT (name); |
1044 |
|
|
1045 |
|
fd = open (name, O_RDONLY); |
1046 |
|
if (fd < 0) |
1047 |
|
return FALSE; |
1048 |
|
|
1049 |
|
while ((count = read (fd, buffer, sizeof (buffer))) > 0) |
1050 |
|
file_crc = bfd_calc_gnu_debuglink_crc32 (file_crc, buffer, count); |
1051 |
|
|
1052 |
|
close (fd); |
1053 |
|
|
1054 |
|
return crc == file_crc; |
1055 |
|
} |
1056 |
|
|
1057 |
|
|
1058 |
|
/* |
1059 |
|
INTERNAL_FUNCTION |
1060 |
|
find_separate_debug_file |
1061 |
|
|
1062 |
|
SYNOPSIS |
1063 |
|
char *find_separate_debug_file (bfd *abfd); |
1064 |
|
|
1065 |
|
DESCRIPTION |
1066 |
|
Searches @var{abfd} for a reference to separate debugging |
1067 |
|
information, scans various locations in the filesystem, including |
1068 |
|
the file tree rooted at @var{debug_file_directory}, and returns a |
1069 |
|
filename of such debugging information if the file is found and has |
1070 |
|
matching CRC32. Returns NULL if no reference to debugging file |
1071 |
|
exists, or file cannot be found. |
1072 |
|
*/ |
1073 |
|
|
1074 |
|
static char * |
1075 |
|
find_separate_debug_file (bfd *abfd, const char *debug_file_directory) |
1076 |
|
{ |
1077 |
|
char *basename; |
1078 |
|
char *dir; |
1079 |
|
char *debugfile; |
1080 |
|
unsigned long crc32; |
1081 |
|
int i; |
1082 |
|
|
1083 |
|
BFD_ASSERT (abfd); |
1084 |
|
if (debug_file_directory == NULL) |
1085 |
|
debug_file_directory = "."; |
1086 |
|
|
1087 |
|
/* BFD may have been opened from a stream. */ |
1088 |
|
if (! abfd->filename) |
1089 |
|
return NULL; |
1090 |
|
|
1091 |
|
basename = get_debug_link_info (abfd, & crc32); |
1092 |
|
if (basename == NULL) |
1093 |
|
return NULL; |
1094 |
|
|
1095 |
|
if (strlen (basename) < 1) |
1096 |
|
{ |
1097 |
|
free (basename); |
1098 |
|
return NULL; |
1099 |
|
} |
1100 |
|
|
1101 |
|
dir = strdup (abfd->filename); |
1102 |
|
if (dir == NULL) |
1103 |
|
{ |
1104 |
|
free (basename); |
1105 |
|
return NULL; |
1106 |
|
} |
1107 |
|
BFD_ASSERT (strlen (dir) != 0); |
1108 |
|
|
1109 |
|
/* Strip off filename part. */ |
1110 |
|
for (i = strlen (dir) - 1; i >= 0; i--) |
1111 |
|
if (IS_DIR_SEPARATOR (dir[i])) |
1112 |
|
break; |
1113 |
|
|
1114 |
|
dir[i + 1] = '\0'; |
1115 |
|
BFD_ASSERT (dir[i] == '/' || dir[0] == '\0'); |
1116 |
|
|
1117 |
|
debugfile = malloc (strlen (debug_file_directory) + 1 |
1118 |
|
+ strlen (dir) |
1119 |
|
+ strlen (".debug/") |
1120 |
|
+ strlen (basename) |
1121 |
|
+ 1); |
1122 |
|
if (debugfile == NULL) |
1123 |
|
{ |
1124 |
|
free (basename); |
1125 |
|
free (dir); |
1126 |
|
return NULL; |
1127 |
|
} |
1128 |
|
|
1129 |
|
/* First try in the same directory as the original file: */ |
1130 |
|
strcpy (debugfile, dir); |
1131 |
|
strcat (debugfile, basename); |
1132 |
|
|
1133 |
|
if (separate_debug_file_exists (debugfile, crc32)) |
1134 |
|
{ |
1135 |
|
free (basename); |
1136 |
|
free (dir); |
1137 |
|
return debugfile; |
1138 |
|
} |
1139 |
|
|
1140 |
|
/* Then try in a subdirectory called .debug. */ |
1141 |
|
strcpy (debugfile, dir); |
1142 |
|
strcat (debugfile, ".debug/"); |
1143 |
|
strcat (debugfile, basename); |
1144 |
|
|
1145 |
|
if (separate_debug_file_exists (debugfile, crc32)) |
1146 |
|
{ |
1147 |
|
free (basename); |
1148 |
|
free (dir); |
1149 |
|
return debugfile; |
1150 |
|
} |
1151 |
|
|
1152 |
|
/* Then try in the global debugfile directory. */ |
1153 |
|
strcpy (debugfile, debug_file_directory); |
1154 |
|
i = strlen (debug_file_directory) - 1; |
1155 |
|
if (i > 0 |
1156 |
|
&& debug_file_directory[i] != '/' |
1157 |
|
&& dir[0] != '/') |
1158 |
|
strcat (debugfile, "/"); |
1159 |
|
strcat (debugfile, dir); |
1160 |
|
strcat (debugfile, basename); |
1161 |
|
|
1162 |
|
if (separate_debug_file_exists (debugfile, crc32)) |
1163 |
|
{ |
1164 |
|
free (basename); |
1165 |
|
free (dir); |
1166 |
|
return debugfile; |
1167 |
|
} |
1168 |
|
|
1169 |
|
free (debugfile); |
1170 |
|
free (basename); |
1171 |
|
free (dir); |
1172 |
|
return NULL; |
1173 |
|
} |
1174 |
|
|
1175 |
|
|
1176 |
|
/* |
1177 |
|
FUNCTION |
1178 |
|
bfd_follow_gnu_debuglink |
1179 |
|
|
1180 |
|
SYNOPSIS |
1181 |
|
char *bfd_follow_gnu_debuglink (bfd *abfd, const char *dir); |
1182 |
|
|
1183 |
|
DESCRIPTION |
1184 |
|
|
1185 |
|
Takes a BFD and searches it for a .gnu_debuglink section. If this |
1186 |
|
section is found, it examines the section for the name and checksum |
1187 |
|
of a '.debug' file containing auxiliary debugging information. It |
1188 |
|
then searches the filesystem for this .debug file in some standard |
1189 |
|
locations, including the directory tree rooted at @var{dir}, and if |
1190 |
|
found returns the full filename. |
1191 |
|
|
1192 |
|
If @var{dir} is NULL, it will search a default path configured into |
1193 |
|
libbfd at build time. [XXX this feature is not currently |
1194 |
|
implemented]. |
1195 |
|
|
1196 |
|
RETURNS |
1197 |
|
<<NULL>> on any errors or failure to locate the .debug file, |
1198 |
|
otherwise a pointer to a heap-allocated string containing the |
1199 |
|
filename. The caller is responsible for freeing this string. |
1200 |
|
*/ |
1201 |
|
|
1202 |
|
char * |
1203 |
|
bfd_follow_gnu_debuglink (bfd *abfd, const char *dir) |
1204 |
|
{ |
1205 |
|
return find_separate_debug_file (abfd, dir); |
1206 |
|
} |
1207 |
|
|
1208 |
|
/* |
1209 |
|
FUNCTION |
1210 |
|
bfd_create_gnu_debuglink_section |
1211 |
|
|
1212 |
|
SYNOPSIS |
1213 |
|
struct bfd_section *bfd_create_gnu_debuglink_section |
1214 |
|
(bfd *abfd, const char *filename); |
1215 |
|
|
1216 |
|
DESCRIPTION |
1217 |
|
|
1218 |
|
Takes a @var{BFD} and adds a .gnu_debuglink section to it. The section is sized |
1219 |
|
to be big enough to contain a link to the specified @var{filename}. |
1220 |
|
|
1221 |
|
RETURNS |
1222 |
|
A pointer to the new section is returned if all is ok. Otherwise <<NULL>> is |
1223 |
|
returned and bfd_error is set. |
1224 |
|
*/ |
1225 |
|
|
1226 |
|
asection * |
1227 |
|
bfd_create_gnu_debuglink_section (bfd *abfd, const char *filename) |
1228 |
|
{ |
1229 |
|
asection *sect; |
1230 |
|
bfd_size_type debuglink_size; |
1231 |
|
|
1232 |
|
if (abfd == NULL || filename == NULL) |
1233 |
|
{ |
1234 |
|
bfd_set_error (bfd_error_invalid_operation); |
1235 |
|
return NULL; |
1236 |
|
} |
1237 |
|
|
1238 |
|
/* Strip off any path components in filename. */ |
1239 |
|
filename = lbasename (filename); |
1240 |
|
|
1241 |
|
sect = bfd_get_section_by_name (abfd, GNU_DEBUGLINK); |
1242 |
|
if (sect) |
1243 |
|
{ |
1244 |
|
/* Section already exists. */ |
1245 |
|
bfd_set_error (bfd_error_invalid_operation); |
1246 |
|
return NULL; |
1247 |
|
} |
1248 |
|
|
1249 |
|
sect = bfd_make_section (abfd, GNU_DEBUGLINK); |
1250 |
|
if (sect == NULL) |
1251 |
|
return NULL; |
1252 |
|
|
1253 |
|
if (! bfd_set_section_flags (abfd, sect, |
1254 |
|
SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING)) |
1255 |
|
/* XXX Should we delete the section from the bfd ? */ |
1256 |
|
return NULL; |
1257 |
|
|
1258 |
|
|
1259 |
|
debuglink_size = strlen (filename) + 1; |
1260 |
|
debuglink_size += 3; |
1261 |
|
debuglink_size &= ~3; |
1262 |
|
debuglink_size += 4; |
1263 |
|
|
1264 |
|
if (! bfd_set_section_size (abfd, sect, debuglink_size)) |
1265 |
|
/* XXX Should we delete the section from the bfd ? */ |
1266 |
|
return NULL; |
1267 |
|
|
1268 |
|
return sect; |
1269 |
|
} |
1270 |
|
|
1271 |
|
|
1272 |
|
/* |
1273 |
|
FUNCTION |
1274 |
|
bfd_fill_in_gnu_debuglink_section |
1275 |
|
|
1276 |
|
SYNOPSIS |
1277 |
|
bfd_boolean bfd_fill_in_gnu_debuglink_section |
1278 |
|
(bfd *abfd, struct bfd_section *sect, const char *filename); |
1279 |
|
|
1280 |
|
DESCRIPTION |
1281 |
|
|
1282 |
|
Takes a @var{BFD} and containing a .gnu_debuglink section @var{SECT} |
1283 |
|
and fills in the contents of the section to contain a link to the |
1284 |
|
specified @var{filename}. The filename should be relative to the |
1285 |
|
current directory. |
1286 |
|
|
1287 |
|
RETURNS |
1288 |
|
<<TRUE>> is returned if all is ok. Otherwise <<FALSE>> is returned |
1289 |
|
and bfd_error is set. |
1290 |
|
*/ |
1291 |
|
|
1292 |
|
bfd_boolean |
1293 |
|
bfd_fill_in_gnu_debuglink_section (bfd *abfd, |
1294 |
|
struct bfd_section *sect, |
1295 |
|
const char *filename) |
1296 |
|
{ |
1297 |
|
bfd_size_type debuglink_size; |
1298 |
|
unsigned long crc32; |
1299 |
|
char * contents; |
1300 |
|
bfd_size_type crc_offset; |
1301 |
|
FILE * handle; |
1302 |
|
static unsigned char buffer[8 * 1024]; |
1303 |
|
size_t count; |
1304 |
|
|
1305 |
|
if (abfd == NULL || sect == NULL || filename == NULL) |
1306 |
|
{ |
1307 |
|
bfd_set_error (bfd_error_invalid_operation); |
1308 |
|
return FALSE; |
1309 |
|
} |
1310 |
|
|
1311 |
|
/* Make sure that we can read the file. |
1312 |
|
XXX - Should we attempt to locate the debug info file using the same |
1313 |
|
algorithm as gdb ? At the moment, since we are creating the |
1314 |
|
.gnu_debuglink section, we insist upon the user providing us with a |
1315 |
|
correct-for-section-creation-time path, but this need not conform to |
1316 |
|
the gdb location algorithm. */ |
1317 |
|
handle = fopen (filename, FOPEN_RB); |
1318 |
|
if (handle == NULL) |
1319 |
|
{ |
1320 |
|
bfd_set_error (bfd_error_system_call); |
1321 |
|
return FALSE; |
1322 |
|
} |
1323 |
|
|
1324 |
|
crc32 = 0; |
1325 |
|
while ((count = fread (buffer, 1, sizeof buffer, handle)) > 0) |
1326 |
|
crc32 = bfd_calc_gnu_debuglink_crc32 (crc32, buffer, count); |
1327 |
|
fclose (handle); |
1328 |
|
|
1329 |
|
/* Strip off any path components in filename, |
1330 |
|
now that we no longer need them. */ |
1331 |
|
filename = lbasename (filename); |
1332 |
|
|
1333 |
|
debuglink_size = strlen (filename) + 1; |
1334 |
|
debuglink_size += 3; |
1335 |
|
debuglink_size &= ~3; |
1336 |
|
debuglink_size += 4; |
1337 |
|
|
1338 |
|
contents = malloc (debuglink_size); |
1339 |
|
if (contents == NULL) |
1340 |
|
{ |
1341 |
|
/* XXX Should we delete the section from the bfd ? */ |
1342 |
|
bfd_set_error (bfd_error_no_memory); |
1343 |
|
return FALSE; |
1344 |
|
} |
1345 |
|
|
1346 |
|
strcpy (contents, filename); |
1347 |
|
crc_offset = debuglink_size - 4; |
1348 |
|
|
1349 |
|
bfd_put_32 (abfd, crc32, contents + crc_offset); |
1350 |
|
|
1351 |
|
if (! bfd_set_section_contents (abfd, sect, contents, 0, debuglink_size)) |
1352 |
|
{ |
1353 |
|
/* XXX Should we delete the section from the bfd ? */ |
1354 |
|
free (contents); |
1355 |
|
return FALSE; |
1356 |
|
} |
1357 |
|
|
1358 |
|
return TRUE; |
1359 |
|
} |