133965Sjdp/* opncls.c -- open and close a BFD. 278828Sobrien Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 3218822Sdim 2001, 2002, 2003, 2004, 2005, 2006, 2007 433965Sjdp Free Software Foundation, Inc. 533965Sjdp 633965Sjdp Written by Cygnus Support. 733965Sjdp 8104834Sobrien This file is part of BFD, the Binary File Descriptor library. 933965Sjdp 10104834Sobrien This program is free software; you can redistribute it and/or modify 11104834Sobrien it under the terms of the GNU General Public License as published by 12104834Sobrien the Free Software Foundation; either version 2 of the License, or 13104834Sobrien (at your option) any later version. 1433965Sjdp 15104834Sobrien This program is distributed in the hope that it will be useful, 16104834Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 17104834Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18104834Sobrien GNU General Public License for more details. 1933965Sjdp 20104834Sobrien You should have received a copy of the GNU General Public License 21104834Sobrien along with this program; if not, write to the Free Software 22218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 2333965Sjdp 24218822Sdim#include "sysdep.h" 2533965Sjdp#include "bfd.h" 2633965Sjdp#include "objalloc.h" 2733965Sjdp#include "libbfd.h" 28130561Sobrien#include "libiberty.h" 2933965Sjdp 3033965Sjdp#ifndef S_IXUSR 3133965Sjdp#define S_IXUSR 0100 /* Execute by owner. */ 3233965Sjdp#endif 3333965Sjdp#ifndef S_IXGRP 3433965Sjdp#define S_IXGRP 0010 /* Execute by group. */ 3533965Sjdp#endif 3633965Sjdp#ifndef S_IXOTH 3733965Sjdp#define S_IXOTH 0001 /* Execute by others. */ 3833965Sjdp#endif 3933965Sjdp 40130561Sobrien/* Counter used to initialize the bfd identifier. */ 41130561Sobrien 42130561Sobrienstatic unsigned int _bfd_id_counter = 0; 43130561Sobrien 4433965Sjdp/* fdopen is a loser -- we should use stdio exclusively. Unfortunately 4533965Sjdp if we do that we can't use fcntl. */ 4633965Sjdp 4733965Sjdp/* Return a new BFD. All BFD's are allocated through this routine. */ 4833965Sjdp 4933965Sjdpbfd * 50130561Sobrien_bfd_new_bfd (void) 5133965Sjdp{ 5233965Sjdp bfd *nbfd; 5333965Sjdp 54130561Sobrien nbfd = bfd_zmalloc (sizeof (bfd)); 5533965Sjdp if (nbfd == NULL) 5633965Sjdp return NULL; 5733965Sjdp 58130561Sobrien nbfd->id = _bfd_id_counter++; 59130561Sobrien 60130561Sobrien nbfd->memory = objalloc_create (); 6133965Sjdp if (nbfd->memory == NULL) 6233965Sjdp { 6333965Sjdp bfd_set_error (bfd_error_no_memory); 6489857Sobrien free (nbfd); 6533965Sjdp return NULL; 6633965Sjdp } 6733965Sjdp 6833965Sjdp nbfd->arch_info = &bfd_default_arch_struct; 6933965Sjdp 7033965Sjdp nbfd->direction = no_direction; 7133965Sjdp nbfd->iostream = NULL; 7233965Sjdp nbfd->where = 0; 73130561Sobrien if (!bfd_hash_table_init_n (& nbfd->section_htab, bfd_section_hash_newfunc, 74218822Sdim sizeof (struct section_hash_entry), 251)) 7589857Sobrien { 7689857Sobrien free (nbfd); 7789857Sobrien return NULL; 7889857Sobrien } 79130561Sobrien nbfd->sections = NULL; 80218822Sdim nbfd->section_last = NULL; 8133965Sjdp nbfd->format = bfd_unknown; 82130561Sobrien nbfd->my_archive = NULL; 8389857Sobrien nbfd->origin = 0; 84130561Sobrien nbfd->opened_once = FALSE; 85130561Sobrien nbfd->output_has_begun = FALSE; 8633965Sjdp nbfd->section_count = 0; 87130561Sobrien nbfd->usrdata = NULL; 88130561Sobrien nbfd->cacheable = FALSE; 8933965Sjdp nbfd->flags = BFD_NO_FLAGS; 90130561Sobrien nbfd->mtime_set = FALSE; 9133965Sjdp 9233965Sjdp return nbfd; 9333965Sjdp} 9433965Sjdp 9533965Sjdp/* Allocate a new BFD as a member of archive OBFD. */ 9633965Sjdp 9733965Sjdpbfd * 98130561Sobrien_bfd_new_bfd_contained_in (bfd *obfd) 9933965Sjdp{ 10033965Sjdp bfd *nbfd; 10133965Sjdp 10233965Sjdp nbfd = _bfd_new_bfd (); 10399461Sobrien if (nbfd == NULL) 10499461Sobrien return NULL; 10533965Sjdp nbfd->xvec = obfd->xvec; 106218822Sdim nbfd->iovec = obfd->iovec; 10733965Sjdp nbfd->my_archive = obfd; 10833965Sjdp nbfd->direction = read_direction; 10933965Sjdp nbfd->target_defaulted = obfd->target_defaulted; 11033965Sjdp return nbfd; 11133965Sjdp} 11233965Sjdp 11389857Sobrien/* Delete a BFD. */ 11489857Sobrien 11589857Sobrienvoid 116130561Sobrien_bfd_delete_bfd (bfd *abfd) 11789857Sobrien{ 118218822Sdim if (abfd->memory) 119218822Sdim { 120218822Sdim bfd_hash_table_free (&abfd->section_htab); 121218822Sdim objalloc_free ((struct objalloc *) abfd->memory); 122218822Sdim } 12389857Sobrien free (abfd); 12489857Sobrien} 12589857Sobrien 126218822Sdim/* Free objalloc memory. */ 127218822Sdim 128218822Sdimbfd_boolean 129218822Sdim_bfd_free_cached_info (bfd *abfd) 130218822Sdim{ 131218822Sdim if (abfd->memory) 132218822Sdim { 133218822Sdim bfd_hash_table_free (&abfd->section_htab); 134218822Sdim objalloc_free ((struct objalloc *) abfd->memory); 135218822Sdim 136218822Sdim abfd->sections = NULL; 137218822Sdim abfd->section_last = NULL; 138218822Sdim abfd->outsymbols = NULL; 139218822Sdim abfd->tdata.any = NULL; 140218822Sdim abfd->usrdata = NULL; 141218822Sdim abfd->memory = NULL; 142218822Sdim } 143218822Sdim 144218822Sdim return TRUE; 145218822Sdim} 146218822Sdim 14733965Sjdp/* 14833965SjdpSECTION 14933965Sjdp Opening and closing BFDs 15033965Sjdp 151218822SdimSUBSECTION 152218822Sdim Functions for opening and closing 15333965Sjdp*/ 15433965Sjdp 15533965Sjdp/* 15633965SjdpFUNCTION 157218822Sdim bfd_fopen 15833965Sjdp 15933965SjdpSYNOPSIS 160218822Sdim bfd *bfd_fopen (const char *filename, const char *target, 161218822Sdim const char *mode, int fd); 16233965Sjdp 16333965SjdpDESCRIPTION 164218822Sdim Open the file @var{filename} with the target @var{target}. 165218822Sdim Return a pointer to the created BFD. If @var{fd} is not -1, 166218822Sdim then <<fdopen>> is used to open the file; otherwise, <<fopen>> 167218822Sdim is used. @var{mode} is passed directly to <<fopen>> or 168218822Sdim <<fdopen>>. 16933965Sjdp 17033965Sjdp Calls <<bfd_find_target>>, so @var{target} is interpreted as by 17133965Sjdp that function. 17233965Sjdp 173218822Sdim The new BFD is marked as cacheable iff @var{fd} is -1. 174218822Sdim 17533965Sjdp If <<NULL>> is returned then an error has occured. Possible errors 176130561Sobrien are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> or 177130561Sobrien <<system_call>> error. 17833965Sjdp*/ 17933965Sjdp 18033965Sjdpbfd * 181218822Sdimbfd_fopen (const char *filename, const char *target, const char *mode, int fd) 18233965Sjdp{ 18333965Sjdp bfd *nbfd; 18433965Sjdp const bfd_target *target_vec; 18533965Sjdp 18633965Sjdp nbfd = _bfd_new_bfd (); 18733965Sjdp if (nbfd == NULL) 18833965Sjdp return NULL; 18933965Sjdp 19033965Sjdp target_vec = bfd_find_target (target, nbfd); 19133965Sjdp if (target_vec == NULL) 19233965Sjdp { 19389857Sobrien _bfd_delete_bfd (nbfd); 19433965Sjdp return NULL; 19533965Sjdp } 196218822Sdim 197218822Sdim#ifdef HAVE_FDOPEN 198218822Sdim if (fd != -1) 199218822Sdim nbfd->iostream = fdopen (fd, mode); 200218822Sdim else 201218822Sdim#endif 202218822Sdim nbfd->iostream = real_fopen (filename, mode); 203218822Sdim if (nbfd->iostream == NULL) 204218822Sdim { 205218822Sdim bfd_set_error (bfd_error_system_call); 206218822Sdim _bfd_delete_bfd (nbfd); 207218822Sdim return NULL; 208218822Sdim } 20933965Sjdp 210218822Sdim /* OK, put everything where it belongs. */ 21133965Sjdp nbfd->filename = filename; 21233965Sjdp 213218822Sdim /* Figure out whether the user is opening the file for reading, 214218822Sdim writing, or both, by looking at the MODE argument. */ 215218822Sdim if ((mode[0] == 'r' || mode[0] == 'w' || mode[0] == 'a') 216218822Sdim && mode[1] == '+') 217218822Sdim nbfd->direction = both_direction; 218218822Sdim else if (mode[0] == 'r') 219218822Sdim nbfd->direction = read_direction; 220218822Sdim else 221218822Sdim nbfd->direction = write_direction; 222218822Sdim 223218822Sdim if (! bfd_cache_init (nbfd)) 22433965Sjdp { 22589857Sobrien _bfd_delete_bfd (nbfd); 22633965Sjdp return NULL; 22733965Sjdp } 228218822Sdim nbfd->opened_once = TRUE; 229218822Sdim /* If we opened the file by name, mark it cacheable; we can close it 230218822Sdim and reopen it later. However, if a file descriptor was provided, 231218822Sdim then it may have been opened with special flags that make it 232218822Sdim unsafe to close and reopen the file. */ 233218822Sdim if (fd == -1) 234223262Sbenl (void) bfd_set_cacheable (nbfd, TRUE); 23533965Sjdp 23633965Sjdp return nbfd; 23733965Sjdp} 23833965Sjdp 239218822Sdim/* 240218822SdimFUNCTION 241218822Sdim bfd_openr 242218822Sdim 243218822SdimSYNOPSIS 244218822Sdim bfd *bfd_openr (const char *filename, const char *target); 245218822Sdim 246218822SdimDESCRIPTION 247218822Sdim Open the file @var{filename} (using <<fopen>>) with the target 248218822Sdim @var{target}. Return a pointer to the created BFD. 249218822Sdim 250218822Sdim Calls <<bfd_find_target>>, so @var{target} is interpreted as by 251218822Sdim that function. 252218822Sdim 253218822Sdim If <<NULL>> is returned then an error has occured. Possible errors 254218822Sdim are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> or 255218822Sdim <<system_call>> error. 256218822Sdim*/ 257218822Sdim 258218822Sdimbfd * 259218822Sdimbfd_openr (const char *filename, const char *target) 260218822Sdim{ 261218822Sdim return bfd_fopen (filename, target, FOPEN_RB, -1); 262218822Sdim} 263218822Sdim 26433965Sjdp/* Don't try to `optimize' this function: 26533965Sjdp 26633965Sjdp o - We lock using stack space so that interrupting the locking 26733965Sjdp won't cause a storage leak. 26833965Sjdp o - We open the file stream last, since we don't want to have to 26933965Sjdp close it if anything goes wrong. Closing the stream means closing 270104834Sobrien the file descriptor too, even though we didn't open it. */ 27133965Sjdp/* 27233965SjdpFUNCTION 273130561Sobrien bfd_fdopenr 27433965Sjdp 27533965SjdpSYNOPSIS 276130561Sobrien bfd *bfd_fdopenr (const char *filename, const char *target, int fd); 27733965Sjdp 27833965SjdpDESCRIPTION 279130561Sobrien <<bfd_fdopenr>> is to <<bfd_fopenr>> much like <<fdopen>> is to 280130561Sobrien <<fopen>>. It opens a BFD on a file already described by the 281130561Sobrien @var{fd} supplied. 28233965Sjdp 283130561Sobrien When the file is later <<bfd_close>>d, the file descriptor will 284130561Sobrien be closed. If the caller desires that this file descriptor be 285130561Sobrien cached by BFD (opened as needed, closed as needed to free 286130561Sobrien descriptors for other opens), with the supplied @var{fd} used as 287130561Sobrien an initial file descriptor (but subject to closure at any time), 288130561Sobrien call bfd_set_cacheable(bfd, 1) on the returned BFD. The default 289130561Sobrien is to assume no caching; the file descriptor will remain open 290130561Sobrien until <<bfd_close>>, and will not be affected by BFD operations 291130561Sobrien on other files. 29233965Sjdp 293130561Sobrien Possible errors are <<bfd_error_no_memory>>, 294130561Sobrien <<bfd_error_invalid_target>> and <<bfd_error_system_call>>. 29533965Sjdp*/ 29633965Sjdp 29733965Sjdpbfd * 298130561Sobrienbfd_fdopenr (const char *filename, const char *target, int fd) 29933965Sjdp{ 300218822Sdim const char *mode; 301218822Sdim#if defined(HAVE_FCNTL) && defined(F_GETFL) 30233965Sjdp int fdflags; 303218822Sdim#endif 30433965Sjdp 30533965Sjdp#if ! defined(HAVE_FCNTL) || ! defined(F_GETFL) 306218822Sdim mode = FOPEN_RUB; /* Assume full access. */ 30733965Sjdp#else 30833965Sjdp fdflags = fcntl (fd, F_GETFL, NULL); 309104834Sobrien if (fdflags == -1) 31033965Sjdp { 311218822Sdim bfd_set_error (bfd_error_system_call); 31233965Sjdp return NULL; 31333965Sjdp } 31433965Sjdp 315104834Sobrien /* (O_ACCMODE) parens are to avoid Ultrix header file bug. */ 31638889Sjdp switch (fdflags & (O_ACCMODE)) 31738889Sjdp { 318218822Sdim case O_RDONLY: mode = FOPEN_RB; break; 319218822Sdim case O_WRONLY: mode = FOPEN_RUB; break; 320218822Sdim case O_RDWR: mode = FOPEN_RUB; break; 32138889Sjdp default: abort (); 32238889Sjdp } 32333965Sjdp#endif 32433965Sjdp 325218822Sdim return bfd_fopen (filename, target, mode, fd); 326218822Sdim} 327218822Sdim 328218822Sdim/* 329218822SdimFUNCTION 330218822Sdim bfd_openstreamr 331218822Sdim 332218822SdimSYNOPSIS 333218822Sdim bfd *bfd_openstreamr (const char *, const char *, void *); 334218822Sdim 335218822SdimDESCRIPTION 336218822Sdim 337218822Sdim Open a BFD for read access on an existing stdio stream. When 338218822Sdim the BFD is passed to <<bfd_close>>, the stream will be closed. 339218822Sdim*/ 340218822Sdim 341218822Sdimbfd * 342218822Sdimbfd_openstreamr (const char *filename, const char *target, void *streamarg) 343218822Sdim{ 344218822Sdim FILE *stream = streamarg; 345218822Sdim bfd *nbfd; 346218822Sdim const bfd_target *target_vec; 347218822Sdim 348218822Sdim nbfd = _bfd_new_bfd (); 349218822Sdim if (nbfd == NULL) 350218822Sdim return NULL; 351218822Sdim 352218822Sdim target_vec = bfd_find_target (target, nbfd); 353218822Sdim if (target_vec == NULL) 35433965Sjdp { 35589857Sobrien _bfd_delete_bfd (nbfd); 35633965Sjdp return NULL; 35733965Sjdp } 35833965Sjdp 359218822Sdim nbfd->iostream = stream; 36033965Sjdp nbfd->filename = filename; 361218822Sdim nbfd->direction = read_direction; 36233965Sjdp 36333965Sjdp if (! bfd_cache_init (nbfd)) 36433965Sjdp { 36589857Sobrien _bfd_delete_bfd (nbfd); 36633965Sjdp return NULL; 36733965Sjdp } 36833965Sjdp 36933965Sjdp return nbfd; 37033965Sjdp} 37133965Sjdp 37233965Sjdp/* 37333965SjdpFUNCTION 374218822Sdim bfd_openr_iovec 37533965Sjdp 37633965SjdpSYNOPSIS 377218822Sdim bfd *bfd_openr_iovec (const char *filename, const char *target, 378218822Sdim void *(*open) (struct bfd *nbfd, 379218822Sdim void *open_closure), 380218822Sdim void *open_closure, 381218822Sdim file_ptr (*pread) (struct bfd *nbfd, 382218822Sdim void *stream, 383218822Sdim void *buf, 384218822Sdim file_ptr nbytes, 385218822Sdim file_ptr offset), 386218822Sdim int (*close) (struct bfd *nbfd, 387218822Sdim void *stream), 388218822Sdim int (*stat) (struct bfd *abfd, 389218822Sdim void *stream, 390218822Sdim struct stat *sb)); 39133965Sjdp 39233965SjdpDESCRIPTION 39333965Sjdp 394218822Sdim Create and return a BFD backed by a read-only @var{stream}. 395218822Sdim The @var{stream} is created using @var{open}, accessed using 396218822Sdim @var{pread} and destroyed using @var{close}. 397218822Sdim 398218822Sdim Calls <<bfd_find_target>>, so @var{target} is interpreted as by 399218822Sdim that function. 400218822Sdim 401218822Sdim Calls @var{open} (which can call <<bfd_zalloc>> and 402218822Sdim <<bfd_get_filename>>) to obtain the read-only stream backing 403218822Sdim the BFD. @var{open} either succeeds returning the 404218822Sdim non-<<NULL>> @var{stream}, or fails returning <<NULL>> 405218822Sdim (setting <<bfd_error>>). 406218822Sdim 407218822Sdim Calls @var{pread} to request @var{nbytes} of data from 408218822Sdim @var{stream} starting at @var{offset} (e.g., via a call to 409218822Sdim <<bfd_read>>). @var{pread} either succeeds returning the 410218822Sdim number of bytes read (which can be less than @var{nbytes} when 411218822Sdim end-of-file), or fails returning -1 (setting <<bfd_error>>). 412218822Sdim 413218822Sdim Calls @var{close} when the BFD is later closed using 414218822Sdim <<bfd_close>>. @var{close} either succeeds returning 0, or 415218822Sdim fails returning -1 (setting <<bfd_error>>). 416218822Sdim 417218822Sdim Calls @var{stat} to fill in a stat structure for bfd_stat, 418218822Sdim bfd_get_size, and bfd_get_mtime calls. @var{stat} returns 0 419218822Sdim on success, or returns -1 on failure (setting <<bfd_error>>). 420218822Sdim 421218822Sdim If <<bfd_openr_iovec>> returns <<NULL>> then an error has 422218822Sdim occurred. Possible errors are <<bfd_error_no_memory>>, 423218822Sdim <<bfd_error_invalid_target>> and <<bfd_error_system_call>>. 424218822Sdim 42533965Sjdp*/ 42633965Sjdp 427218822Sdimstruct opncls 428218822Sdim{ 429218822Sdim void *stream; 430218822Sdim file_ptr (*pread) (struct bfd *abfd, void *stream, void *buf, 431218822Sdim file_ptr nbytes, file_ptr offset); 432218822Sdim int (*close) (struct bfd *abfd, void *stream); 433218822Sdim int (*stat) (struct bfd *abfd, void *stream, struct stat *sb); 434218822Sdim file_ptr where; 435218822Sdim}; 436218822Sdim 437218822Sdimstatic file_ptr 438218822Sdimopncls_btell (struct bfd *abfd) 439218822Sdim{ 440218822Sdim struct opncls *vec = abfd->iostream; 441218822Sdim return vec->where; 442218822Sdim} 443218822Sdim 444218822Sdimstatic int 445218822Sdimopncls_bseek (struct bfd *abfd, file_ptr offset, int whence) 446218822Sdim{ 447218822Sdim struct opncls *vec = abfd->iostream; 448218822Sdim switch (whence) 449218822Sdim { 450218822Sdim case SEEK_SET: vec->where = offset; break; 451218822Sdim case SEEK_CUR: vec->where += offset; break; 452218822Sdim case SEEK_END: return -1; 453218822Sdim } 454218822Sdim return 0; 455218822Sdim} 456218822Sdim 457218822Sdimstatic file_ptr 458218822Sdimopncls_bread (struct bfd *abfd, void *buf, file_ptr nbytes) 459218822Sdim{ 460218822Sdim struct opncls *vec = abfd->iostream; 461218822Sdim file_ptr nread = (vec->pread) (abfd, vec->stream, buf, nbytes, vec->where); 462218822Sdim if (nread < 0) 463218822Sdim return nread; 464218822Sdim vec->where += nread; 465218822Sdim return nread; 466218822Sdim} 467218822Sdim 468218822Sdimstatic file_ptr 469218822Sdimopncls_bwrite (struct bfd *abfd ATTRIBUTE_UNUSED, 470218822Sdim const void *where ATTRIBUTE_UNUSED, 471218822Sdim file_ptr nbytes ATTRIBUTE_UNUSED) 472218822Sdim{ 473218822Sdim return -1; 474218822Sdim} 475218822Sdim 476218822Sdimstatic int 477218822Sdimopncls_bclose (struct bfd *abfd) 478218822Sdim{ 479218822Sdim struct opncls *vec = abfd->iostream; 480218822Sdim /* Since the VEC's memory is bound to the bfd deleting the bfd will 481218822Sdim free it. */ 482218822Sdim int status = 0; 483218822Sdim if (vec->close != NULL) 484218822Sdim status = (vec->close) (abfd, vec->stream); 485218822Sdim abfd->iostream = NULL; 486218822Sdim return status; 487218822Sdim} 488218822Sdim 489218822Sdimstatic int 490218822Sdimopncls_bflush (struct bfd *abfd ATTRIBUTE_UNUSED) 491218822Sdim{ 492218822Sdim return 0; 493218822Sdim} 494218822Sdim 495218822Sdimstatic int 496218822Sdimopncls_bstat (struct bfd *abfd, struct stat *sb) 497218822Sdim{ 498218822Sdim struct opncls *vec = abfd->iostream; 499218822Sdim 500218822Sdim memset (sb, 0, sizeof (*sb)); 501218822Sdim if (vec->stat == NULL) 502218822Sdim return 0; 503218822Sdim 504218822Sdim return (vec->stat) (abfd, vec->stream, sb); 505218822Sdim} 506218822Sdim 507218822Sdimstatic const struct bfd_iovec opncls_iovec = { 508218822Sdim &opncls_bread, &opncls_bwrite, &opncls_btell, &opncls_bseek, 509218822Sdim &opncls_bclose, &opncls_bflush, &opncls_bstat 510218822Sdim}; 511218822Sdim 51233965Sjdpbfd * 513218822Sdimbfd_openr_iovec (const char *filename, const char *target, 514218822Sdim void *(*open) (struct bfd *nbfd, 515218822Sdim void *open_closure), 516218822Sdim void *open_closure, 517218822Sdim file_ptr (*pread) (struct bfd *abfd, 518218822Sdim void *stream, 519218822Sdim void *buf, 520218822Sdim file_ptr nbytes, 521218822Sdim file_ptr offset), 522218822Sdim int (*close) (struct bfd *nbfd, 523218822Sdim void *stream), 524218822Sdim int (*stat) (struct bfd *abfd, 525218822Sdim void *stream, 526218822Sdim struct stat *sb)) 52733965Sjdp{ 52833965Sjdp bfd *nbfd; 52933965Sjdp const bfd_target *target_vec; 530218822Sdim struct opncls *vec; 531218822Sdim void *stream; 53233965Sjdp 53333965Sjdp nbfd = _bfd_new_bfd (); 53433965Sjdp if (nbfd == NULL) 53533965Sjdp return NULL; 53633965Sjdp 53733965Sjdp target_vec = bfd_find_target (target, nbfd); 53833965Sjdp if (target_vec == NULL) 53933965Sjdp { 54089857Sobrien _bfd_delete_bfd (nbfd); 54133965Sjdp return NULL; 54233965Sjdp } 54333965Sjdp 54433965Sjdp nbfd->filename = filename; 54533965Sjdp nbfd->direction = read_direction; 54689857Sobrien 547218822Sdim stream = open (nbfd, open_closure); 548218822Sdim if (stream == NULL) 54933965Sjdp { 55089857Sobrien _bfd_delete_bfd (nbfd); 55133965Sjdp return NULL; 55233965Sjdp } 55333965Sjdp 554218822Sdim vec = bfd_zalloc (nbfd, sizeof (struct opncls)); 555218822Sdim vec->stream = stream; 556218822Sdim vec->pread = pread; 557218822Sdim vec->close = close; 558218822Sdim vec->stat = stat; 559218822Sdim 560218822Sdim nbfd->iovec = &opncls_iovec; 561218822Sdim nbfd->iostream = vec; 562218822Sdim 56333965Sjdp return nbfd; 56433965Sjdp} 56533965Sjdp 566104834Sobrien/* bfd_openw -- open for writing. 567104834Sobrien Returns a pointer to a freshly-allocated BFD on success, or NULL. 56833965Sjdp 569104834Sobrien See comment by bfd_fdopenr before you try to modify this function. */ 57033965Sjdp 57133965Sjdp/* 57233965SjdpFUNCTION 57333965Sjdp bfd_openw 57433965Sjdp 57533965SjdpSYNOPSIS 576130561Sobrien bfd *bfd_openw (const char *filename, const char *target); 57733965Sjdp 57833965SjdpDESCRIPTION 57933965Sjdp Create a BFD, associated with file @var{filename}, using the 58033965Sjdp file format @var{target}, and return a pointer to it. 58133965Sjdp 58233965Sjdp Possible errors are <<bfd_error_system_call>>, <<bfd_error_no_memory>>, 58333965Sjdp <<bfd_error_invalid_target>>. 58433965Sjdp*/ 58533965Sjdp 58633965Sjdpbfd * 587130561Sobrienbfd_openw (const char *filename, const char *target) 58833965Sjdp{ 58933965Sjdp bfd *nbfd; 59033965Sjdp const bfd_target *target_vec; 59133965Sjdp 59233965Sjdp /* nbfd has to point to head of malloc'ed block so that bfd_close may 593104834Sobrien reclaim it correctly. */ 59433965Sjdp nbfd = _bfd_new_bfd (); 59533965Sjdp if (nbfd == NULL) 59633965Sjdp return NULL; 59733965Sjdp 59833965Sjdp target_vec = bfd_find_target (target, nbfd); 59933965Sjdp if (target_vec == NULL) 60033965Sjdp { 60189857Sobrien _bfd_delete_bfd (nbfd); 60233965Sjdp return NULL; 60333965Sjdp } 60433965Sjdp 60533965Sjdp nbfd->filename = filename; 60633965Sjdp nbfd->direction = write_direction; 60733965Sjdp 60833965Sjdp if (bfd_open_file (nbfd) == NULL) 60933965Sjdp { 610104834Sobrien /* File not writeable, etc. */ 611104834Sobrien bfd_set_error (bfd_error_system_call); 61289857Sobrien _bfd_delete_bfd (nbfd); 61333965Sjdp return NULL; 61433965Sjdp } 61533965Sjdp 61633965Sjdp return nbfd; 61733965Sjdp} 61833965Sjdp 61933965Sjdp/* 62033965Sjdp 62133965SjdpFUNCTION 62233965Sjdp bfd_close 62333965Sjdp 62433965SjdpSYNOPSIS 625130561Sobrien bfd_boolean bfd_close (bfd *abfd); 62633965Sjdp 62733965SjdpDESCRIPTION 62833965Sjdp 629130561Sobrien Close a BFD. If the BFD was open for writing, then pending 630130561Sobrien operations are completed and the file written out and closed. 631130561Sobrien If the created file is executable, then <<chmod>> is called 632130561Sobrien to mark it as such. 63333965Sjdp 63433965Sjdp All memory attached to the BFD is released. 63533965Sjdp 63633965Sjdp The file descriptor associated with the BFD is closed (even 63733965Sjdp if it was passed in to BFD by <<bfd_fdopenr>>). 63833965Sjdp 63933965SjdpRETURNS 640130561Sobrien <<TRUE>> is returned if all is ok, otherwise <<FALSE>>. 64133965Sjdp*/ 64233965Sjdp 64333965Sjdp 644130561Sobrienbfd_boolean 645130561Sobrienbfd_close (bfd *abfd) 64633965Sjdp{ 647130561Sobrien bfd_boolean ret; 64833965Sjdp 649104834Sobrien if (bfd_write_p (abfd)) 65033965Sjdp { 65133965Sjdp if (! BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd))) 652130561Sobrien return FALSE; 65333965Sjdp } 65433965Sjdp 65533965Sjdp if (! BFD_SEND (abfd, _close_and_cleanup, (abfd))) 656130561Sobrien return FALSE; 65733965Sjdp 658218822Sdim /* FIXME: cagney/2004-02-15: Need to implement a BFD_IN_MEMORY io 659218822Sdim vector. */ 660218822Sdim if (!(abfd->flags & BFD_IN_MEMORY)) 661218822Sdim ret = abfd->iovec->bclose (abfd); 662218822Sdim else 663218822Sdim ret = TRUE; 66433965Sjdp 66533965Sjdp /* If the file was open for writing and is now executable, 666104834Sobrien make it so. */ 66733965Sjdp if (ret 66833965Sjdp && abfd->direction == write_direction 66933965Sjdp && abfd->flags & EXEC_P) 67033965Sjdp { 67133965Sjdp struct stat buf; 67233965Sjdp 67333965Sjdp if (stat (abfd->filename, &buf) == 0) 67433965Sjdp { 675130561Sobrien unsigned int mask = umask (0); 676104834Sobrien 67733965Sjdp umask (mask); 67833965Sjdp chmod (abfd->filename, 67933965Sjdp (0777 68033965Sjdp & (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask)))); 68133965Sjdp } 68233965Sjdp } 68333965Sjdp 68489857Sobrien _bfd_delete_bfd (abfd); 68533965Sjdp 68633965Sjdp return ret; 68733965Sjdp} 68833965Sjdp 68933965Sjdp/* 69033965SjdpFUNCTION 69133965Sjdp bfd_close_all_done 69233965Sjdp 69333965SjdpSYNOPSIS 694130561Sobrien bfd_boolean bfd_close_all_done (bfd *); 69533965Sjdp 69633965SjdpDESCRIPTION 697130561Sobrien Close a BFD. Differs from <<bfd_close>> since it does not 698130561Sobrien complete any pending operations. This routine would be used 699130561Sobrien if the application had just used BFD for swapping and didn't 700130561Sobrien want to use any of the writing code. 70133965Sjdp 70233965Sjdp If the created file is executable, then <<chmod>> is called 70333965Sjdp to mark it as such. 70433965Sjdp 70533965Sjdp All memory attached to the BFD is released. 70633965Sjdp 70733965SjdpRETURNS 708130561Sobrien <<TRUE>> is returned if all is ok, otherwise <<FALSE>>. 70933965Sjdp*/ 71033965Sjdp 711130561Sobrienbfd_boolean 712130561Sobrienbfd_close_all_done (bfd *abfd) 71333965Sjdp{ 714130561Sobrien bfd_boolean ret; 71533965Sjdp 71633965Sjdp ret = bfd_cache_close (abfd); 71733965Sjdp 71833965Sjdp /* If the file was open for writing and is now executable, 719104834Sobrien make it so. */ 72033965Sjdp if (ret 72133965Sjdp && abfd->direction == write_direction 72233965Sjdp && abfd->flags & EXEC_P) 72333965Sjdp { 72433965Sjdp struct stat buf; 72533965Sjdp 72633965Sjdp if (stat (abfd->filename, &buf) == 0) 72733965Sjdp { 72889857Sobrien unsigned int mask = umask (0); 729104834Sobrien 73033965Sjdp umask (mask); 73133965Sjdp chmod (abfd->filename, 73261843Sobrien (0777 73333965Sjdp & (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask)))); 73433965Sjdp } 73533965Sjdp } 73633965Sjdp 73789857Sobrien _bfd_delete_bfd (abfd); 73833965Sjdp 73933965Sjdp return ret; 74033965Sjdp} 74133965Sjdp 74233965Sjdp/* 74333965SjdpFUNCTION 74433965Sjdp bfd_create 74533965Sjdp 74633965SjdpSYNOPSIS 747130561Sobrien bfd *bfd_create (const char *filename, bfd *templ); 74833965Sjdp 74933965SjdpDESCRIPTION 750130561Sobrien Create a new BFD in the manner of <<bfd_openw>>, but without 751130561Sobrien opening a file. The new BFD takes the target from the target 752130561Sobrien used by @var{template}. The format is always set to <<bfd_object>>. 75333965Sjdp*/ 75433965Sjdp 75533965Sjdpbfd * 756130561Sobrienbfd_create (const char *filename, bfd *templ) 75733965Sjdp{ 75833965Sjdp bfd *nbfd; 75933965Sjdp 76033965Sjdp nbfd = _bfd_new_bfd (); 76133965Sjdp if (nbfd == NULL) 76233965Sjdp return NULL; 76333965Sjdp nbfd->filename = filename; 76433965Sjdp if (templ) 76533965Sjdp nbfd->xvec = templ->xvec; 76633965Sjdp nbfd->direction = no_direction; 76733965Sjdp bfd_set_format (nbfd, bfd_object); 768104834Sobrien 76933965Sjdp return nbfd; 77033965Sjdp} 77133965Sjdp 77233965Sjdp/* 77360484SobrienFUNCTION 77460484Sobrien bfd_make_writable 77560484Sobrien 77660484SobrienSYNOPSIS 777130561Sobrien bfd_boolean bfd_make_writable (bfd *abfd); 77860484Sobrien 77960484SobrienDESCRIPTION 78060484Sobrien Takes a BFD as created by <<bfd_create>> and converts it 78160484Sobrien into one like as returned by <<bfd_openw>>. It does this 78260484Sobrien by converting the BFD to BFD_IN_MEMORY. It's assumed that 78360484Sobrien you will call <<bfd_make_readable>> on this bfd later. 78460484Sobrien 78560484SobrienRETURNS 786130561Sobrien <<TRUE>> is returned if all is ok, otherwise <<FALSE>>. 78760484Sobrien*/ 78860484Sobrien 789130561Sobrienbfd_boolean 790130561Sobrienbfd_make_writable (bfd *abfd) 79160484Sobrien{ 79260484Sobrien struct bfd_in_memory *bim; 79360484Sobrien 79460484Sobrien if (abfd->direction != no_direction) 79560484Sobrien { 79660484Sobrien bfd_set_error (bfd_error_invalid_operation); 797130561Sobrien return FALSE; 79860484Sobrien } 79960484Sobrien 800130561Sobrien bim = bfd_malloc (sizeof (struct bfd_in_memory)); 801130561Sobrien abfd->iostream = bim; 802104834Sobrien /* bfd_bwrite will grow these as needed. */ 80360484Sobrien bim->size = 0; 80460484Sobrien bim->buffer = 0; 80560484Sobrien 80660484Sobrien abfd->flags |= BFD_IN_MEMORY; 80760484Sobrien abfd->direction = write_direction; 80860484Sobrien abfd->where = 0; 80960484Sobrien 810130561Sobrien return TRUE; 81160484Sobrien} 81260484Sobrien 81360484Sobrien/* 81460484SobrienFUNCTION 81560484Sobrien bfd_make_readable 81660484Sobrien 81760484SobrienSYNOPSIS 818130561Sobrien bfd_boolean bfd_make_readable (bfd *abfd); 81960484Sobrien 82060484SobrienDESCRIPTION 82160484Sobrien Takes a BFD as created by <<bfd_create>> and 82260484Sobrien <<bfd_make_writable>> and converts it into one like as 82360484Sobrien returned by <<bfd_openr>>. It does this by writing the 82460484Sobrien contents out to the memory buffer, then reversing the 82560484Sobrien direction. 82660484Sobrien 82760484SobrienRETURNS 828130561Sobrien <<TRUE>> is returned if all is ok, otherwise <<FALSE>>. */ 82960484Sobrien 830130561Sobrienbfd_boolean 831130561Sobrienbfd_make_readable (bfd *abfd) 83260484Sobrien{ 83360484Sobrien if (abfd->direction != write_direction || !(abfd->flags & BFD_IN_MEMORY)) 83460484Sobrien { 83560484Sobrien bfd_set_error (bfd_error_invalid_operation); 836130561Sobrien return FALSE; 83760484Sobrien } 83860484Sobrien 83960484Sobrien if (! BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd))) 840130561Sobrien return FALSE; 84160484Sobrien 84260484Sobrien if (! BFD_SEND (abfd, _close_and_cleanup, (abfd))) 843130561Sobrien return FALSE; 84460484Sobrien 84560484Sobrien 84660484Sobrien abfd->arch_info = &bfd_default_arch_struct; 84760484Sobrien 84860484Sobrien abfd->where = 0; 84960484Sobrien abfd->format = bfd_unknown; 850130561Sobrien abfd->my_archive = NULL; 85189857Sobrien abfd->origin = 0; 852130561Sobrien abfd->opened_once = FALSE; 853130561Sobrien abfd->output_has_begun = FALSE; 85460484Sobrien abfd->section_count = 0; 855130561Sobrien abfd->usrdata = NULL; 856130561Sobrien abfd->cacheable = FALSE; 85760484Sobrien abfd->flags = BFD_IN_MEMORY; 858130561Sobrien abfd->mtime_set = FALSE; 85960484Sobrien 860130561Sobrien abfd->target_defaulted = TRUE; 86160484Sobrien abfd->direction = read_direction; 86260484Sobrien abfd->sections = 0; 86360484Sobrien abfd->symcount = 0; 86460484Sobrien abfd->outsymbols = 0; 86560484Sobrien abfd->tdata.any = 0; 86660484Sobrien 86799461Sobrien bfd_section_list_clear (abfd); 868104834Sobrien bfd_check_format (abfd, bfd_object); 86960484Sobrien 870130561Sobrien return TRUE; 87160484Sobrien} 87260484Sobrien 87360484Sobrien/* 87433965SjdpINTERNAL_FUNCTION 87533965Sjdp bfd_alloc 87633965Sjdp 87733965SjdpSYNOPSIS 878218822Sdim void *bfd_alloc (bfd *abfd, bfd_size_type wanted); 87933965Sjdp 88033965SjdpDESCRIPTION 88133965Sjdp Allocate a block of @var{wanted} bytes of memory attached to 88233965Sjdp <<abfd>> and return a pointer to it. 88333965Sjdp*/ 88433965Sjdp 885130561Sobrienvoid * 886130561Sobrienbfd_alloc (bfd *abfd, bfd_size_type size) 88733965Sjdp{ 888130561Sobrien void *ret; 88933965Sjdp 89089857Sobrien if (size != (unsigned long) size) 89189857Sobrien { 89289857Sobrien bfd_set_error (bfd_error_no_memory); 89389857Sobrien return NULL; 89489857Sobrien } 89589857Sobrien 89633965Sjdp ret = objalloc_alloc (abfd->memory, (unsigned long) size); 89733965Sjdp if (ret == NULL) 89833965Sjdp bfd_set_error (bfd_error_no_memory); 89933965Sjdp return ret; 90033965Sjdp} 90133965Sjdp 902218822Sdim/* 903218822SdimINTERNAL_FUNCTION 904218822Sdim bfd_alloc2 905218822Sdim 906218822SdimSYNOPSIS 907218822Sdim void *bfd_alloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size); 908218822Sdim 909218822SdimDESCRIPTION 910218822Sdim Allocate a block of @var{nmemb} elements of @var{size} bytes each 911218822Sdim of memory attached to <<abfd>> and return a pointer to it. 912218822Sdim*/ 913218822Sdim 914130561Sobrienvoid * 915218822Sdimbfd_alloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size) 916218822Sdim{ 917218822Sdim void *ret; 918218822Sdim 919218822Sdim if ((nmemb | size) >= HALF_BFD_SIZE_TYPE 920218822Sdim && size != 0 921218822Sdim && nmemb > ~(bfd_size_type) 0 / size) 922218822Sdim { 923218822Sdim bfd_set_error (bfd_error_no_memory); 924218822Sdim return NULL; 925218822Sdim } 926218822Sdim 927218822Sdim size *= nmemb; 928218822Sdim 929218822Sdim if (size != (unsigned long) size) 930218822Sdim { 931218822Sdim bfd_set_error (bfd_error_no_memory); 932218822Sdim return NULL; 933218822Sdim } 934218822Sdim 935218822Sdim ret = objalloc_alloc (abfd->memory, (unsigned long) size); 936218822Sdim if (ret == NULL) 937218822Sdim bfd_set_error (bfd_error_no_memory); 938218822Sdim return ret; 939218822Sdim} 940218822Sdim 941218822Sdim/* 942218822SdimINTERNAL_FUNCTION 943218822Sdim bfd_zalloc 944218822Sdim 945218822SdimSYNOPSIS 946218822Sdim void *bfd_zalloc (bfd *abfd, bfd_size_type wanted); 947218822Sdim 948218822SdimDESCRIPTION 949218822Sdim Allocate a block of @var{wanted} bytes of zeroed memory 950218822Sdim attached to <<abfd>> and return a pointer to it. 951218822Sdim*/ 952218822Sdim 953218822Sdimvoid * 954130561Sobrienbfd_zalloc (bfd *abfd, bfd_size_type size) 95533965Sjdp{ 956130561Sobrien void *res; 95733965Sjdp 95833965Sjdp res = bfd_alloc (abfd, size); 95933965Sjdp if (res) 96089857Sobrien memset (res, 0, (size_t) size); 96133965Sjdp return res; 96233965Sjdp} 96333965Sjdp 964218822Sdim/* 965218822SdimINTERNAL_FUNCTION 966218822Sdim bfd_zalloc2 967218822Sdim 968218822SdimSYNOPSIS 969218822Sdim void *bfd_zalloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size); 970218822Sdim 971218822SdimDESCRIPTION 972218822Sdim Allocate a block of @var{nmemb} elements of @var{size} bytes each 973218822Sdim of zeroed memory attached to <<abfd>> and return a pointer to it. 974218822Sdim*/ 975218822Sdim 976218822Sdimvoid * 977218822Sdimbfd_zalloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size) 978218822Sdim{ 979218822Sdim void *res; 980218822Sdim 981218822Sdim if ((nmemb | size) >= HALF_BFD_SIZE_TYPE 982218822Sdim && size != 0 983218822Sdim && nmemb > ~(bfd_size_type) 0 / size) 984218822Sdim { 985218822Sdim bfd_set_error (bfd_error_no_memory); 986218822Sdim return NULL; 987218822Sdim } 988218822Sdim 989218822Sdim size *= nmemb; 990218822Sdim 991218822Sdim res = bfd_alloc (abfd, size); 992218822Sdim if (res) 993218822Sdim memset (res, 0, (size_t) size); 994218822Sdim return res; 995218822Sdim} 996218822Sdim 99789857Sobrien/* Free a block allocated for a BFD. 99889857Sobrien Note: Also frees all more recently allocated blocks! */ 99933965Sjdp 100033965Sjdpvoid 1001130561Sobrienbfd_release (bfd *abfd, void *block) 100233965Sjdp{ 100333965Sjdp objalloc_free_block ((struct objalloc *) abfd->memory, block); 100433965Sjdp} 1005130561Sobrien 1006130561Sobrien 1007218822Sdim/* 1008218822Sdim GNU Extension: separate debug-info files 1009218822Sdim 1010130561Sobrien The idea here is that a special section called .gnu_debuglink might be 1011130561Sobrien embedded in a binary file, which indicates that some *other* file 1012130561Sobrien contains the real debugging information. This special section contains a 1013130561Sobrien filename and CRC32 checksum, which we read and resolve to another file, 1014130561Sobrien if it exists. 1015130561Sobrien 1016130561Sobrien This facilitates "optional" provision of debugging information, without 1017130561Sobrien having to provide two complete copies of every binary object (with and 1018130561Sobrien without debug symbols). 1019130561Sobrien*/ 1020130561Sobrien 1021130561Sobrien#define GNU_DEBUGLINK ".gnu_debuglink" 1022130561Sobrien/* 1023130561SobrienFUNCTION 1024130561Sobrien bfd_calc_gnu_debuglink_crc32 1025130561Sobrien 1026130561SobrienSYNOPSIS 1027130561Sobrien unsigned long bfd_calc_gnu_debuglink_crc32 1028130561Sobrien (unsigned long crc, const unsigned char *buf, bfd_size_type len); 1029130561Sobrien 1030130561SobrienDESCRIPTION 1031130561Sobrien Computes a CRC value as used in the .gnu_debuglink section. 1032130561Sobrien Advances the previously computed @var{crc} value by computing 1033130561Sobrien and adding in the crc32 for @var{len} bytes of @var{buf}. 1034130561Sobrien 1035130561SobrienRETURNS 1036130561Sobrien Return the updated CRC32 value. 1037218822Sdim*/ 1038130561Sobrien 1039130561Sobrienunsigned long 1040130561Sobrienbfd_calc_gnu_debuglink_crc32 (unsigned long crc, 1041130561Sobrien const unsigned char *buf, 1042130561Sobrien bfd_size_type len) 1043130561Sobrien{ 1044130561Sobrien static const unsigned long crc32_table[256] = 1045130561Sobrien { 1046130561Sobrien 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 1047130561Sobrien 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 1048130561Sobrien 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 1049130561Sobrien 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 1050130561Sobrien 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 1051130561Sobrien 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 1052130561Sobrien 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 1053130561Sobrien 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 1054130561Sobrien 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 1055130561Sobrien 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 1056130561Sobrien 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 1057130561Sobrien 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 1058130561Sobrien 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 1059130561Sobrien 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 1060130561Sobrien 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 1061130561Sobrien 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 1062130561Sobrien 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 1063130561Sobrien 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 1064130561Sobrien 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 1065130561Sobrien 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 1066130561Sobrien 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 1067130561Sobrien 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 1068130561Sobrien 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 1069130561Sobrien 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 1070130561Sobrien 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 1071130561Sobrien 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 1072130561Sobrien 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 1073130561Sobrien 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 1074130561Sobrien 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 1075130561Sobrien 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 1076130561Sobrien 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 1077130561Sobrien 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 1078130561Sobrien 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 1079130561Sobrien 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 1080130561Sobrien 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 1081130561Sobrien 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 1082130561Sobrien 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 1083130561Sobrien 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 1084130561Sobrien 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 1085130561Sobrien 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 1086130561Sobrien 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 1087130561Sobrien 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 1088130561Sobrien 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 1089130561Sobrien 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 1090130561Sobrien 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 1091130561Sobrien 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 1092130561Sobrien 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 1093130561Sobrien 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 1094130561Sobrien 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 1095130561Sobrien 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 1096130561Sobrien 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 1097130561Sobrien 0x2d02ef8d 1098130561Sobrien }; 1099130561Sobrien const unsigned char *end; 1100130561Sobrien 1101130561Sobrien crc = ~crc & 0xffffffff; 1102130561Sobrien for (end = buf + len; buf < end; ++ buf) 1103130561Sobrien crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8); 1104130561Sobrien return ~crc & 0xffffffff;; 1105130561Sobrien} 1106130561Sobrien 1107130561Sobrien 1108130561Sobrien/* 1109130561SobrienINTERNAL_FUNCTION 1110130561Sobrien get_debug_link_info 1111130561Sobrien 1112130561SobrienSYNOPSIS 1113130561Sobrien char *get_debug_link_info (bfd *abfd, unsigned long *crc32_out); 1114130561Sobrien 1115130561SobrienDESCRIPTION 1116130561Sobrien fetch the filename and CRC32 value for any separate debuginfo 1117130561Sobrien associated with @var{abfd}. Return NULL if no such info found, 1118130561Sobrien otherwise return filename and update @var{crc32_out}. 1119130561Sobrien*/ 1120130561Sobrien 1121130561Sobrienstatic char * 1122130561Sobrienget_debug_link_info (bfd *abfd, unsigned long *crc32_out) 1123130561Sobrien{ 1124218822Sdim asection *sect; 1125130561Sobrien unsigned long crc32; 1126218822Sdim bfd_byte *contents; 1127130561Sobrien int crc_offset; 1128218822Sdim char *name; 1129130561Sobrien 1130130561Sobrien BFD_ASSERT (abfd); 1131130561Sobrien BFD_ASSERT (crc32_out); 1132130561Sobrien 1133130561Sobrien sect = bfd_get_section_by_name (abfd, GNU_DEBUGLINK); 1134130561Sobrien 1135130561Sobrien if (sect == NULL) 1136130561Sobrien return NULL; 1137130561Sobrien 1138218822Sdim if (!bfd_malloc_and_get_section (abfd, sect, &contents)) 1139130561Sobrien { 1140218822Sdim if (contents != NULL) 1141218822Sdim free (contents); 1142130561Sobrien return NULL; 1143130561Sobrien } 1144130561Sobrien 1145130561Sobrien /* Crc value is stored after the filename, aligned up to 4 bytes. */ 1146218822Sdim name = (char *) contents; 1147218822Sdim crc_offset = strlen (name) + 1; 1148130561Sobrien crc_offset = (crc_offset + 3) & ~3; 1149130561Sobrien 1150130561Sobrien crc32 = bfd_get_32 (abfd, contents + crc_offset); 1151130561Sobrien 1152130561Sobrien *crc32_out = crc32; 1153218822Sdim return name; 1154130561Sobrien} 1155130561Sobrien 1156130561Sobrien/* 1157130561SobrienINTERNAL_FUNCTION 1158130561Sobrien separate_debug_file_exists 1159130561Sobrien 1160130561SobrienSYNOPSIS 1161130561Sobrien bfd_boolean separate_debug_file_exists 1162130561Sobrien (char *name, unsigned long crc32); 1163130561Sobrien 1164130561SobrienDESCRIPTION 1165130561Sobrien Checks to see if @var{name} is a file and if its contents 1166130561Sobrien match @var{crc32}. 1167130561Sobrien*/ 1168130561Sobrien 1169130561Sobrienstatic bfd_boolean 1170130561Sobrienseparate_debug_file_exists (const char *name, const unsigned long crc) 1171130561Sobrien{ 1172218822Sdim static unsigned char buffer [8 * 1024]; 1173130561Sobrien unsigned long file_crc = 0; 1174130561Sobrien int fd; 1175130561Sobrien bfd_size_type count; 1176130561Sobrien 1177130561Sobrien BFD_ASSERT (name); 1178130561Sobrien 1179130561Sobrien fd = open (name, O_RDONLY); 1180130561Sobrien if (fd < 0) 1181130561Sobrien return FALSE; 1182130561Sobrien 1183130561Sobrien while ((count = read (fd, buffer, sizeof (buffer))) > 0) 1184130561Sobrien file_crc = bfd_calc_gnu_debuglink_crc32 (file_crc, buffer, count); 1185130561Sobrien 1186130561Sobrien close (fd); 1187130561Sobrien 1188130561Sobrien return crc == file_crc; 1189130561Sobrien} 1190130561Sobrien 1191130561Sobrien 1192130561Sobrien/* 1193130561SobrienINTERNAL_FUNCTION 1194130561Sobrien find_separate_debug_file 1195130561Sobrien 1196130561SobrienSYNOPSIS 1197130561Sobrien char *find_separate_debug_file (bfd *abfd); 1198130561Sobrien 1199130561SobrienDESCRIPTION 1200130561Sobrien Searches @var{abfd} for a reference to separate debugging 1201130561Sobrien information, scans various locations in the filesystem, including 1202130561Sobrien the file tree rooted at @var{debug_file_directory}, and returns a 1203130561Sobrien filename of such debugging information if the file is found and has 1204130561Sobrien matching CRC32. Returns NULL if no reference to debugging file 1205130561Sobrien exists, or file cannot be found. 1206130561Sobrien*/ 1207130561Sobrien 1208130561Sobrienstatic char * 1209130561Sobrienfind_separate_debug_file (bfd *abfd, const char *debug_file_directory) 1210130561Sobrien{ 1211130561Sobrien char *basename; 1212130561Sobrien char *dir; 1213130561Sobrien char *debugfile; 1214130561Sobrien unsigned long crc32; 1215130561Sobrien int i; 1216130561Sobrien 1217130561Sobrien BFD_ASSERT (abfd); 1218130561Sobrien if (debug_file_directory == NULL) 1219130561Sobrien debug_file_directory = "."; 1220130561Sobrien 1221130561Sobrien /* BFD may have been opened from a stream. */ 1222130561Sobrien if (! abfd->filename) 1223130561Sobrien return NULL; 1224130561Sobrien 1225130561Sobrien basename = get_debug_link_info (abfd, & crc32); 1226130561Sobrien if (basename == NULL) 1227130561Sobrien return NULL; 1228130561Sobrien 1229130561Sobrien if (strlen (basename) < 1) 1230130561Sobrien { 1231130561Sobrien free (basename); 1232130561Sobrien return NULL; 1233130561Sobrien } 1234130561Sobrien 1235130561Sobrien dir = strdup (abfd->filename); 1236130561Sobrien if (dir == NULL) 1237130561Sobrien { 1238130561Sobrien free (basename); 1239130561Sobrien return NULL; 1240130561Sobrien } 1241130561Sobrien BFD_ASSERT (strlen (dir) != 0); 1242218822Sdim 1243130561Sobrien /* Strip off filename part. */ 1244130561Sobrien for (i = strlen (dir) - 1; i >= 0; i--) 1245130561Sobrien if (IS_DIR_SEPARATOR (dir[i])) 1246130561Sobrien break; 1247130561Sobrien 1248130561Sobrien dir[i + 1] = '\0'; 1249218822Sdim BFD_ASSERT (dir[i] == '/' || dir[0] == '\0'); 1250130561Sobrien 1251130561Sobrien debugfile = malloc (strlen (debug_file_directory) + 1 1252130561Sobrien + strlen (dir) 1253130561Sobrien + strlen (".debug/") 1254218822Sdim + strlen (basename) 1255130561Sobrien + 1); 1256130561Sobrien if (debugfile == NULL) 1257130561Sobrien { 1258130561Sobrien free (basename); 1259130561Sobrien free (dir); 1260130561Sobrien return NULL; 1261130561Sobrien } 1262130561Sobrien 1263130561Sobrien /* First try in the same directory as the original file: */ 1264130561Sobrien strcpy (debugfile, dir); 1265130561Sobrien strcat (debugfile, basename); 1266130561Sobrien 1267130561Sobrien if (separate_debug_file_exists (debugfile, crc32)) 1268130561Sobrien { 1269130561Sobrien free (basename); 1270130561Sobrien free (dir); 1271130561Sobrien return debugfile; 1272130561Sobrien } 1273130561Sobrien 1274130561Sobrien /* Then try in a subdirectory called .debug. */ 1275130561Sobrien strcpy (debugfile, dir); 1276130561Sobrien strcat (debugfile, ".debug/"); 1277130561Sobrien strcat (debugfile, basename); 1278130561Sobrien 1279130561Sobrien if (separate_debug_file_exists (debugfile, crc32)) 1280130561Sobrien { 1281130561Sobrien free (basename); 1282130561Sobrien free (dir); 1283130561Sobrien return debugfile; 1284130561Sobrien } 1285130561Sobrien 1286130561Sobrien /* Then try in the global debugfile directory. */ 1287130561Sobrien strcpy (debugfile, debug_file_directory); 1288130561Sobrien i = strlen (debug_file_directory) - 1; 1289130561Sobrien if (i > 0 1290130561Sobrien && debug_file_directory[i] != '/' 1291130561Sobrien && dir[0] != '/') 1292130561Sobrien strcat (debugfile, "/"); 1293130561Sobrien strcat (debugfile, dir); 1294130561Sobrien strcat (debugfile, basename); 1295130561Sobrien 1296130561Sobrien if (separate_debug_file_exists (debugfile, crc32)) 1297130561Sobrien { 1298130561Sobrien free (basename); 1299130561Sobrien free (dir); 1300130561Sobrien return debugfile; 1301130561Sobrien } 1302130561Sobrien 1303130561Sobrien free (debugfile); 1304130561Sobrien free (basename); 1305130561Sobrien free (dir); 1306130561Sobrien return NULL; 1307130561Sobrien} 1308130561Sobrien 1309130561Sobrien 1310130561Sobrien/* 1311130561SobrienFUNCTION 1312130561Sobrien bfd_follow_gnu_debuglink 1313130561Sobrien 1314130561SobrienSYNOPSIS 1315130561Sobrien char *bfd_follow_gnu_debuglink (bfd *abfd, const char *dir); 1316130561Sobrien 1317130561SobrienDESCRIPTION 1318130561Sobrien 1319130561Sobrien Takes a BFD and searches it for a .gnu_debuglink section. If this 1320130561Sobrien section is found, it examines the section for the name and checksum 1321130561Sobrien of a '.debug' file containing auxiliary debugging information. It 1322130561Sobrien then searches the filesystem for this .debug file in some standard 1323130561Sobrien locations, including the directory tree rooted at @var{dir}, and if 1324130561Sobrien found returns the full filename. 1325130561Sobrien 1326130561Sobrien If @var{dir} is NULL, it will search a default path configured into 1327130561Sobrien libbfd at build time. [XXX this feature is not currently 1328130561Sobrien implemented]. 1329130561Sobrien 1330130561SobrienRETURNS 1331130561Sobrien <<NULL>> on any errors or failure to locate the .debug file, 1332130561Sobrien otherwise a pointer to a heap-allocated string containing the 1333130561Sobrien filename. The caller is responsible for freeing this string. 1334130561Sobrien*/ 1335130561Sobrien 1336130561Sobrienchar * 1337130561Sobrienbfd_follow_gnu_debuglink (bfd *abfd, const char *dir) 1338130561Sobrien{ 1339130561Sobrien return find_separate_debug_file (abfd, dir); 1340130561Sobrien} 1341130561Sobrien 1342130561Sobrien/* 1343130561SobrienFUNCTION 1344130561Sobrien bfd_create_gnu_debuglink_section 1345130561Sobrien 1346130561SobrienSYNOPSIS 1347130561Sobrien struct bfd_section *bfd_create_gnu_debuglink_section 1348130561Sobrien (bfd *abfd, const char *filename); 1349130561Sobrien 1350130561SobrienDESCRIPTION 1351130561Sobrien 1352130561Sobrien Takes a @var{BFD} and adds a .gnu_debuglink section to it. The section is sized 1353130561Sobrien to be big enough to contain a link to the specified @var{filename}. 1354130561Sobrien 1355130561SobrienRETURNS 1356130561Sobrien A pointer to the new section is returned if all is ok. Otherwise <<NULL>> is 1357218822Sdim returned and bfd_error is set. 1358130561Sobrien*/ 1359130561Sobrien 1360130561Sobrienasection * 1361130561Sobrienbfd_create_gnu_debuglink_section (bfd *abfd, const char *filename) 1362130561Sobrien{ 1363130561Sobrien asection *sect; 1364130561Sobrien bfd_size_type debuglink_size; 1365218822Sdim flagword flags; 1366130561Sobrien 1367130561Sobrien if (abfd == NULL || filename == NULL) 1368130561Sobrien { 1369130561Sobrien bfd_set_error (bfd_error_invalid_operation); 1370130561Sobrien return NULL; 1371130561Sobrien } 1372130561Sobrien 1373130561Sobrien /* Strip off any path components in filename. */ 1374130561Sobrien filename = lbasename (filename); 1375218822Sdim 1376130561Sobrien sect = bfd_get_section_by_name (abfd, GNU_DEBUGLINK); 1377130561Sobrien if (sect) 1378130561Sobrien { 1379130561Sobrien /* Section already exists. */ 1380130561Sobrien bfd_set_error (bfd_error_invalid_operation); 1381130561Sobrien return NULL; 1382130561Sobrien } 1383130561Sobrien 1384218822Sdim flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING; 1385218822Sdim sect = bfd_make_section_with_flags (abfd, GNU_DEBUGLINK, flags); 1386130561Sobrien if (sect == NULL) 1387130561Sobrien return NULL; 1388130561Sobrien 1389130561Sobrien debuglink_size = strlen (filename) + 1; 1390130561Sobrien debuglink_size += 3; 1391130561Sobrien debuglink_size &= ~3; 1392130561Sobrien debuglink_size += 4; 1393130561Sobrien 1394130561Sobrien if (! bfd_set_section_size (abfd, sect, debuglink_size)) 1395130561Sobrien /* XXX Should we delete the section from the bfd ? */ 1396130561Sobrien return NULL; 1397218822Sdim 1398130561Sobrien return sect; 1399130561Sobrien} 1400130561Sobrien 1401130561Sobrien 1402130561Sobrien/* 1403130561SobrienFUNCTION 1404130561Sobrien bfd_fill_in_gnu_debuglink_section 1405130561Sobrien 1406130561SobrienSYNOPSIS 1407130561Sobrien bfd_boolean bfd_fill_in_gnu_debuglink_section 1408130561Sobrien (bfd *abfd, struct bfd_section *sect, const char *filename); 1409130561Sobrien 1410130561SobrienDESCRIPTION 1411130561Sobrien 1412130561Sobrien Takes a @var{BFD} and containing a .gnu_debuglink section @var{SECT} 1413130561Sobrien and fills in the contents of the section to contain a link to the 1414130561Sobrien specified @var{filename}. The filename should be relative to the 1415130561Sobrien current directory. 1416130561Sobrien 1417130561SobrienRETURNS 1418130561Sobrien <<TRUE>> is returned if all is ok. Otherwise <<FALSE>> is returned 1419218822Sdim and bfd_error is set. 1420130561Sobrien*/ 1421130561Sobrien 1422130561Sobrienbfd_boolean 1423130561Sobrienbfd_fill_in_gnu_debuglink_section (bfd *abfd, 1424130561Sobrien struct bfd_section *sect, 1425130561Sobrien const char *filename) 1426130561Sobrien{ 1427130561Sobrien bfd_size_type debuglink_size; 1428130561Sobrien unsigned long crc32; 1429130561Sobrien char * contents; 1430130561Sobrien bfd_size_type crc_offset; 1431130561Sobrien FILE * handle; 1432218822Sdim static unsigned char buffer[8 * 1024]; 1433130561Sobrien size_t count; 1434130561Sobrien 1435130561Sobrien if (abfd == NULL || sect == NULL || filename == NULL) 1436130561Sobrien { 1437130561Sobrien bfd_set_error (bfd_error_invalid_operation); 1438130561Sobrien return FALSE; 1439130561Sobrien } 1440130561Sobrien 1441130561Sobrien /* Make sure that we can read the file. 1442130561Sobrien XXX - Should we attempt to locate the debug info file using the same 1443130561Sobrien algorithm as gdb ? At the moment, since we are creating the 1444130561Sobrien .gnu_debuglink section, we insist upon the user providing us with a 1445130561Sobrien correct-for-section-creation-time path, but this need not conform to 1446130561Sobrien the gdb location algorithm. */ 1447218822Sdim handle = real_fopen (filename, FOPEN_RB); 1448130561Sobrien if (handle == NULL) 1449130561Sobrien { 1450130561Sobrien bfd_set_error (bfd_error_system_call); 1451130561Sobrien return FALSE; 1452130561Sobrien } 1453130561Sobrien 1454130561Sobrien crc32 = 0; 1455130561Sobrien while ((count = fread (buffer, 1, sizeof buffer, handle)) > 0) 1456130561Sobrien crc32 = bfd_calc_gnu_debuglink_crc32 (crc32, buffer, count); 1457130561Sobrien fclose (handle); 1458130561Sobrien 1459130561Sobrien /* Strip off any path components in filename, 1460130561Sobrien now that we no longer need them. */ 1461130561Sobrien filename = lbasename (filename); 1462218822Sdim 1463130561Sobrien debuglink_size = strlen (filename) + 1; 1464130561Sobrien debuglink_size += 3; 1465130561Sobrien debuglink_size &= ~3; 1466130561Sobrien debuglink_size += 4; 1467130561Sobrien 1468215105Scperciva contents = bfd_zmalloc (debuglink_size); 1469130561Sobrien if (contents == NULL) 1470130561Sobrien { 1471130561Sobrien /* XXX Should we delete the section from the bfd ? */ 1472130561Sobrien bfd_set_error (bfd_error_no_memory); 1473130561Sobrien return FALSE; 1474130561Sobrien } 1475130561Sobrien 1476130561Sobrien strcpy (contents, filename); 1477130561Sobrien crc_offset = debuglink_size - 4; 1478130561Sobrien 1479130561Sobrien bfd_put_32 (abfd, crc32, contents + crc_offset); 1480130561Sobrien 1481130561Sobrien if (! bfd_set_section_contents (abfd, sect, contents, 0, debuglink_size)) 1482130561Sobrien { 1483130561Sobrien /* XXX Should we delete the section from the bfd ? */ 1484130561Sobrien free (contents); 1485130561Sobrien return FALSE; 1486130561Sobrien } 1487130561Sobrien 1488130561Sobrien return TRUE; 1489130561Sobrien} 1490