1 /* opncls.c -- open and close a BFD. 2 Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 1997 3 Free Software Foundation, Inc. 4 5 Written by Cygnus Support. 6 7 This file is part of BFD, the Binary File Descriptor library. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 22 23 #include "bfd.h" 24 #include "sysdep.h" 25 #include "objalloc.h" 26 #include "libbfd.h" 27 28 #ifndef S_IXUSR 29 #define S_IXUSR 0100 /* Execute by owner. */ 30 #endif 31 #ifndef S_IXGRP 32 #define S_IXGRP 0010 /* Execute by group. */ 33 #endif 34 #ifndef S_IXOTH 35 #define S_IXOTH 0001 /* Execute by others. */ 36 #endif 37 38 /* fdopen is a loser -- we should use stdio exclusively. Unfortunately 39 if we do that we can't use fcntl. */ 40 41 /* FIXME: This is no longer used. */ 42 long _bfd_chunksize = -1; 43 44 /* Return a new BFD. All BFD's are allocated through this routine. */ 45 46 bfd * 47 _bfd_new_bfd () 48 { 49 bfd *nbfd; 50 51 nbfd = (bfd *) bfd_zmalloc (sizeof (bfd)); 52 if (nbfd == NULL) 53 return NULL; 54 55 nbfd->memory = (PTR) objalloc_create (); 56 if (nbfd->memory == NULL) 57 { 58 bfd_set_error (bfd_error_no_memory); 59 return NULL; 60 } 61 62 nbfd->arch_info = &bfd_default_arch_struct; 63 64 nbfd->direction = no_direction; 65 nbfd->iostream = NULL; 66 nbfd->where = 0; 67 nbfd->sections = (asection *) NULL; 68 nbfd->format = bfd_unknown; 69 nbfd->my_archive = (bfd *) NULL; 70 nbfd->origin = 0; 71 nbfd->opened_once = false; 72 nbfd->output_has_begun = false; 73 nbfd->section_count = 0; 74 nbfd->usrdata = (PTR) NULL; 75 nbfd->cacheable = false; 76 nbfd->flags = BFD_NO_FLAGS; 77 nbfd->mtime_set = false; 78 79 return nbfd; 80 } 81 82 /* Allocate a new BFD as a member of archive OBFD. */ 83 84 bfd * 85 _bfd_new_bfd_contained_in (obfd) 86 bfd *obfd; 87 { 88 bfd *nbfd; 89 90 nbfd = _bfd_new_bfd (); 91 nbfd->xvec = obfd->xvec; 92 nbfd->my_archive = obfd; 93 nbfd->direction = read_direction; 94 nbfd->target_defaulted = obfd->target_defaulted; 95 return nbfd; 96 } 97 98 /* 99 SECTION 100 Opening and closing BFDs 101 102 */ 103 104 /* 105 FUNCTION 106 bfd_openr 107 108 SYNOPSIS 109 bfd *bfd_openr(CONST char *filename, CONST char *target); 110 111 DESCRIPTION 112 Open the file @var{filename} (using <<fopen>>) with the target 113 @var{target}. Return a pointer to the created BFD. 114 115 Calls <<bfd_find_target>>, so @var{target} is interpreted as by 116 that function. 117 118 If <<NULL>> is returned then an error has occured. Possible errors 119 are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> or <<system_call>> error. 120 */ 121 122 bfd * 123 bfd_openr (filename, target) 124 CONST char *filename; 125 CONST char *target; 126 { 127 bfd *nbfd; 128 const bfd_target *target_vec; 129 130 nbfd = _bfd_new_bfd (); 131 if (nbfd == NULL) 132 return NULL; 133 134 target_vec = bfd_find_target (target, nbfd); 135 if (target_vec == NULL) 136 { 137 objalloc_free ((struct objalloc *) nbfd->memory); 138 free (nbfd); 139 bfd_set_error (bfd_error_invalid_target); 140 return NULL; 141 } 142 143 nbfd->filename = filename; 144 nbfd->direction = read_direction; 145 146 if (bfd_open_file (nbfd) == NULL) 147 { 148 /* File didn't exist, or some such */ 149 bfd_set_error (bfd_error_system_call); 150 objalloc_free ((struct objalloc *) nbfd->memory); 151 free (nbfd); 152 return NULL; 153 } 154 155 return nbfd; 156 } 157 158 /* Don't try to `optimize' this function: 159 160 o - We lock using stack space so that interrupting the locking 161 won't cause a storage leak. 162 o - We open the file stream last, since we don't want to have to 163 close it if anything goes wrong. Closing the stream means closing 164 the file descriptor too, even though we didn't open it. 165 */ 166 /* 167 FUNCTION 168 bfd_fdopenr 169 170 SYNOPSIS 171 bfd *bfd_fdopenr(CONST char *filename, CONST char *target, int fd); 172 173 DESCRIPTION 174 <<bfd_fdopenr>> is to <<bfd_fopenr>> much like <<fdopen>> is to <<fopen>>. 175 It opens a BFD on a file already described by the @var{fd} 176 supplied. 177 178 When the file is later <<bfd_close>>d, the file descriptor will be closed. 179 180 If the caller desires that this file descriptor be cached by BFD 181 (opened as needed, closed as needed to free descriptors for 182 other opens), with the supplied @var{fd} used as an initial 183 file descriptor (but subject to closure at any time), call 184 bfd_set_cacheable(bfd, 1) on the returned BFD. The default is to 185 assume no cacheing; the file descriptor will remain open until 186 <<bfd_close>>, and will not be affected by BFD operations on other 187 files. 188 189 Possible errors are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> and <<bfd_error_system_call>>. 190 */ 191 192 bfd * 193 bfd_fdopenr (filename, target, fd) 194 CONST char *filename; 195 CONST char *target; 196 int fd; 197 { 198 bfd *nbfd; 199 const bfd_target *target_vec; 200 int fdflags; 201 202 bfd_set_error (bfd_error_system_call); 203 #if ! defined(HAVE_FCNTL) || ! defined(F_GETFL) 204 fdflags = O_RDWR; /* Assume full access */ 205 #else 206 fdflags = fcntl (fd, F_GETFL, NULL); 207 #endif 208 if (fdflags == -1) return NULL; 209 210 nbfd = _bfd_new_bfd (); 211 if (nbfd == NULL) 212 return NULL; 213 214 target_vec = bfd_find_target (target, nbfd); 215 if (target_vec == NULL) 216 { 217 bfd_set_error (bfd_error_invalid_target); 218 objalloc_free ((struct objalloc *) nbfd->memory); 219 free (nbfd); 220 return NULL; 221 } 222 223 #ifndef HAVE_FDOPEN 224 nbfd->iostream = (PTR) fopen (filename, FOPEN_RB); 225 #else 226 /* (O_ACCMODE) parens are to avoid Ultrix header file bug */ 227 switch (fdflags & (O_ACCMODE)) 228 { 229 case O_RDONLY: nbfd->iostream = (PTR) fdopen (fd, FOPEN_RB); break; 230 case O_WRONLY: nbfd->iostream = (PTR) fdopen (fd, FOPEN_RUB); break; 231 case O_RDWR: nbfd->iostream = (PTR) fdopen (fd, FOPEN_RUB); break; 232 default: abort (); 233 } 234 #endif 235 236 if (nbfd->iostream == NULL) 237 { 238 objalloc_free ((struct objalloc *) nbfd->memory); 239 free (nbfd); 240 return NULL; 241 } 242 243 /* OK, put everything where it belongs */ 244 245 nbfd->filename = filename; 246 247 /* As a special case we allow a FD open for read/write to 248 be written through, although doing so requires that we end 249 the previous clause with a preposition. */ 250 /* (O_ACCMODE) parens are to avoid Ultrix header file bug */ 251 switch (fdflags & O_ACCMODE) 252 { 253 case O_RDONLY: nbfd->direction = read_direction; break; 254 case O_WRONLY: nbfd->direction = write_direction; break; 255 case O_RDWR: nbfd->direction = both_direction; break; 256 default: abort (); 257 } 258 259 if (! bfd_cache_init (nbfd)) 260 { 261 objalloc_free ((struct objalloc *) nbfd->memory); 262 free (nbfd); 263 return NULL; 264 } 265 nbfd->opened_once = true; 266 267 return nbfd; 268 } 269 270 /* 271 FUNCTION 272 bfd_openstreamr 273 274 SYNOPSIS 275 bfd *bfd_openstreamr(const char *, const char *, PTR); 276 277 DESCRIPTION 278 279 Open a BFD for read access on an existing stdio stream. When 280 the BFD is passed to <<bfd_close>>, the stream will be closed. 281 */ 282 283 bfd * 284 bfd_openstreamr (filename, target, streamarg) 285 const char *filename; 286 const char *target; 287 PTR streamarg; 288 { 289 FILE *stream = (FILE *) streamarg; 290 bfd *nbfd; 291 const bfd_target *target_vec; 292 293 nbfd = _bfd_new_bfd (); 294 if (nbfd == NULL) 295 return NULL; 296 297 target_vec = bfd_find_target (target, nbfd); 298 if (target_vec == NULL) 299 { 300 bfd_set_error (bfd_error_invalid_target); 301 objalloc_free ((struct objalloc *) nbfd->memory); 302 free (nbfd); 303 return NULL; 304 } 305 306 nbfd->iostream = (PTR) stream; 307 nbfd->filename = filename; 308 nbfd->direction = read_direction; 309 310 if (! bfd_cache_init (nbfd)) 311 { 312 objalloc_free ((struct objalloc *) nbfd->memory); 313 free (nbfd); 314 return NULL; 315 } 316 317 return nbfd; 318 } 319 320 /** bfd_openw -- open for writing. 321 Returns a pointer to a freshly-allocated BFD on success, or NULL. 322 323 See comment by bfd_fdopenr before you try to modify this function. */ 324 325 /* 326 FUNCTION 327 bfd_openw 328 329 SYNOPSIS 330 bfd *bfd_openw(CONST char *filename, CONST char *target); 331 332 DESCRIPTION 333 Create a BFD, associated with file @var{filename}, using the 334 file format @var{target}, and return a pointer to it. 335 336 Possible errors are <<bfd_error_system_call>>, <<bfd_error_no_memory>>, 337 <<bfd_error_invalid_target>>. 338 */ 339 340 bfd * 341 bfd_openw (filename, target) 342 CONST char *filename; 343 CONST char *target; 344 { 345 bfd *nbfd; 346 const bfd_target *target_vec; 347 348 bfd_set_error (bfd_error_system_call); 349 350 /* nbfd has to point to head of malloc'ed block so that bfd_close may 351 reclaim it correctly. */ 352 353 nbfd = _bfd_new_bfd (); 354 if (nbfd == NULL) 355 return NULL; 356 357 target_vec = bfd_find_target (target, nbfd); 358 if (target_vec == NULL) 359 { 360 objalloc_free ((struct objalloc *) nbfd->memory); 361 free (nbfd); 362 return NULL; 363 } 364 365 nbfd->filename = filename; 366 nbfd->direction = write_direction; 367 368 if (bfd_open_file (nbfd) == NULL) 369 { 370 bfd_set_error (bfd_error_system_call); /* File not writeable, etc */ 371 objalloc_free ((struct objalloc *) nbfd->memory); 372 free (nbfd); 373 return NULL; 374 } 375 376 return nbfd; 377 } 378 379 /* 380 381 FUNCTION 382 bfd_close 383 384 SYNOPSIS 385 boolean bfd_close(bfd *abfd); 386 387 DESCRIPTION 388 389 Close a BFD. If the BFD was open for writing, 390 then pending operations are completed and the file written out 391 and closed. If the created file is executable, then 392 <<chmod>> is called to mark it as such. 393 394 All memory attached to the BFD is released. 395 396 The file descriptor associated with the BFD is closed (even 397 if it was passed in to BFD by <<bfd_fdopenr>>). 398 399 RETURNS 400 <<true>> is returned if all is ok, otherwise <<false>>. 401 */ 402 403 404 boolean 405 bfd_close (abfd) 406 bfd *abfd; 407 { 408 boolean ret; 409 410 if (!bfd_read_p (abfd)) 411 { 412 if (! BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd))) 413 return false; 414 } 415 416 if (! BFD_SEND (abfd, _close_and_cleanup, (abfd))) 417 return false; 418 419 ret = bfd_cache_close (abfd); 420 421 /* If the file was open for writing and is now executable, 422 make it so */ 423 if (ret 424 && abfd->direction == write_direction 425 && abfd->flags & EXEC_P) 426 { 427 struct stat buf; 428 429 if (stat (abfd->filename, &buf) == 0) 430 { 431 int mask = umask (0); 432 umask (mask); 433 chmod (abfd->filename, 434 (0777 435 & (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask)))); 436 } 437 } 438 439 objalloc_free ((struct objalloc *) abfd->memory); 440 free (abfd); 441 442 return ret; 443 } 444 445 /* 446 FUNCTION 447 bfd_close_all_done 448 449 SYNOPSIS 450 boolean bfd_close_all_done(bfd *); 451 452 DESCRIPTION 453 Close a BFD. Differs from <<bfd_close>> 454 since it does not complete any pending operations. This 455 routine would be used if the application had just used BFD for 456 swapping and didn't want to use any of the writing code. 457 458 If the created file is executable, then <<chmod>> is called 459 to mark it as such. 460 461 All memory attached to the BFD is released. 462 463 RETURNS 464 <<true>> is returned if all is ok, otherwise <<false>>. 465 466 */ 467 468 boolean 469 bfd_close_all_done (abfd) 470 bfd *abfd; 471 { 472 boolean ret; 473 474 ret = bfd_cache_close (abfd); 475 476 /* If the file was open for writing and is now executable, 477 make it so */ 478 if (ret 479 && abfd->direction == write_direction 480 && abfd->flags & EXEC_P) 481 { 482 struct stat buf; 483 484 if (stat (abfd->filename, &buf) == 0) 485 { 486 int mask = umask (0); 487 umask (mask); 488 chmod (abfd->filename, 489 (0777 490 & (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask)))); 491 } 492 } 493 494 objalloc_free ((struct objalloc *) abfd->memory); 495 free (abfd); 496 497 return ret; 498 } 499 500 /* 501 FUNCTION 502 bfd_create 503 504 SYNOPSIS 505 bfd *bfd_create(CONST char *filename, bfd *templ); 506 507 DESCRIPTION 508 Create a new BFD in the manner of 509 <<bfd_openw>>, but without opening a file. The new BFD 510 takes the target from the target used by @var{template}. The 511 format is always set to <<bfd_object>>. 512 513 */ 514 515 bfd * 516 bfd_create (filename, templ) 517 CONST char *filename; 518 bfd *templ; 519 { 520 bfd *nbfd; 521 522 nbfd = _bfd_new_bfd (); 523 if (nbfd == NULL) 524 return NULL; 525 nbfd->filename = filename; 526 if (templ) 527 nbfd->xvec = templ->xvec; 528 nbfd->direction = no_direction; 529 bfd_set_format (nbfd, bfd_object); 530 return nbfd; 531 } 532 533 /* 534 FUNCTION 535 bfd_make_writable 536 537 SYNOPSIS 538 boolean bfd_make_writable(bfd *abfd); 539 540 DESCRIPTION 541 Takes a BFD as created by <<bfd_create>> and converts it 542 into one like as returned by <<bfd_openw>>. It does this 543 by converting the BFD to BFD_IN_MEMORY. It's assumed that 544 you will call <<bfd_make_readable>> on this bfd later. 545 546 RETURNS 547 <<true>> is returned if all is ok, otherwise <<false>>. 548 */ 549 550 boolean 551 bfd_make_writable(abfd) 552 bfd *abfd; 553 { 554 struct bfd_in_memory *bim; 555 556 if (abfd->direction != no_direction) 557 { 558 bfd_set_error (bfd_error_invalid_operation); 559 return false; 560 } 561 562 bim = (struct bfd_in_memory *) bfd_malloc (sizeof (struct bfd_in_memory)); 563 abfd->iostream = (PTR) bim; 564 /* bfd_write will grow these as needed */ 565 bim->size = 0; 566 bim->buffer = 0; 567 568 abfd->flags |= BFD_IN_MEMORY; 569 abfd->direction = write_direction; 570 abfd->where = 0; 571 572 return true; 573 } 574 575 /* 576 FUNCTION 577 bfd_make_readable 578 579 SYNOPSIS 580 boolean bfd_make_readable(bfd *abfd); 581 582 DESCRIPTION 583 Takes a BFD as created by <<bfd_create>> and 584 <<bfd_make_writable>> and converts it into one like as 585 returned by <<bfd_openr>>. It does this by writing the 586 contents out to the memory buffer, then reversing the 587 direction. 588 589 RETURNS 590 <<true>> is returned if all is ok, otherwise <<false>>. */ 591 592 boolean 593 bfd_make_readable(abfd) 594 bfd *abfd; 595 { 596 if (abfd->direction != write_direction || !(abfd->flags & BFD_IN_MEMORY)) 597 { 598 bfd_set_error (bfd_error_invalid_operation); 599 return false; 600 } 601 602 if (! BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd))) 603 return false; 604 605 if (! BFD_SEND (abfd, _close_and_cleanup, (abfd))) 606 return false; 607 608 609 abfd->arch_info = &bfd_default_arch_struct; 610 611 abfd->where = 0; 612 abfd->sections = (asection *) NULL; 613 abfd->format = bfd_unknown; 614 abfd->my_archive = (bfd *) NULL; 615 abfd->origin = 0; 616 abfd->opened_once = false; 617 abfd->output_has_begun = false; 618 abfd->section_count = 0; 619 abfd->usrdata = (PTR) NULL; 620 abfd->cacheable = false; 621 abfd->flags = BFD_IN_MEMORY; 622 abfd->mtime_set = false; 623 624 abfd->target_defaulted = true; 625 abfd->direction = read_direction; 626 abfd->sections = 0; 627 abfd->symcount = 0; 628 abfd->outsymbols = 0; 629 abfd->tdata.any = 0; 630 631 bfd_check_format(abfd, bfd_object); 632 633 return true; 634 } 635 636 /* 637 INTERNAL_FUNCTION 638 bfd_alloc 639 640 SYNOPSIS 641 PTR bfd_alloc (bfd *abfd, size_t wanted); 642 643 DESCRIPTION 644 Allocate a block of @var{wanted} bytes of memory attached to 645 <<abfd>> and return a pointer to it. 646 */ 647 648 649 PTR 650 bfd_alloc (abfd, size) 651 bfd *abfd; 652 size_t size; 653 { 654 PTR ret; 655 656 ret = objalloc_alloc (abfd->memory, (unsigned long) size); 657 if (ret == NULL) 658 bfd_set_error (bfd_error_no_memory); 659 return ret; 660 } 661 662 PTR 663 bfd_zalloc (abfd, size) 664 bfd *abfd; 665 size_t size; 666 { 667 PTR res; 668 669 res = bfd_alloc (abfd, size); 670 if (res) 671 memset (res, 0, size); 672 return res; 673 } 674 675 /* Free a block allocated for a BFD. */ 676 677 void 678 bfd_release (abfd, block) 679 bfd *abfd; 680 PTR block; 681 { 682 objalloc_free_block ((struct objalloc *) abfd->memory, block); 683 } 684