xref: /openbsd/gnu/usr.bin/binutils/bfd/opncls.c (revision 78b63d65)
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