xref: /dflybsd-src/contrib/gdb-7/gdb/gdb_bfd.c (revision de8e141f24382815c10a4012d209bbbf7abf1112)
1*ef5ccd6cSJohn Marino /* Definitions for BFD wrappers used by GDB.
2*ef5ccd6cSJohn Marino 
3*ef5ccd6cSJohn Marino    Copyright (C) 2011-2013 Free Software Foundation, Inc.
4*ef5ccd6cSJohn Marino 
5*ef5ccd6cSJohn Marino    This file is part of GDB.
6*ef5ccd6cSJohn Marino 
7*ef5ccd6cSJohn Marino    This program is free software; you can redistribute it and/or modify
8*ef5ccd6cSJohn Marino    it under the terms of the GNU General Public License as published by
9*ef5ccd6cSJohn Marino    the Free Software Foundation; either version 3 of the License, or
10*ef5ccd6cSJohn Marino    (at your option) any later version.
11*ef5ccd6cSJohn Marino 
12*ef5ccd6cSJohn Marino    This program is distributed in the hope that it will be useful,
13*ef5ccd6cSJohn Marino    but WITHOUT ANY WARRANTY; without even the implied warranty of
14*ef5ccd6cSJohn Marino    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*ef5ccd6cSJohn Marino    GNU General Public License for more details.
16*ef5ccd6cSJohn Marino 
17*ef5ccd6cSJohn Marino    You should have received a copy of the GNU General Public License
18*ef5ccd6cSJohn Marino    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19*ef5ccd6cSJohn Marino 
20*ef5ccd6cSJohn Marino #include "defs.h"
21*ef5ccd6cSJohn Marino #include "gdb_bfd.h"
22*ef5ccd6cSJohn Marino #include "gdb_assert.h"
23*ef5ccd6cSJohn Marino #include "gdb_string.h"
24*ef5ccd6cSJohn Marino #include "ui-out.h"
25*ef5ccd6cSJohn Marino #include "gdbcmd.h"
26*ef5ccd6cSJohn Marino #include "hashtab.h"
27*ef5ccd6cSJohn Marino #ifdef HAVE_ZLIB_H
28*ef5ccd6cSJohn Marino #include <zlib.h>
29*ef5ccd6cSJohn Marino #endif
30*ef5ccd6cSJohn Marino #ifdef HAVE_MMAP
31*ef5ccd6cSJohn Marino #include <sys/mman.h>
32*ef5ccd6cSJohn Marino #ifndef MAP_FAILED
33*ef5ccd6cSJohn Marino #define MAP_FAILED ((void *) -1)
34*ef5ccd6cSJohn Marino #endif
35*ef5ccd6cSJohn Marino #endif
36*ef5ccd6cSJohn Marino 
37*ef5ccd6cSJohn Marino /* An object of this type is stored in the section's user data when
38*ef5ccd6cSJohn Marino    mapping a section.  */
39*ef5ccd6cSJohn Marino 
40*ef5ccd6cSJohn Marino struct gdb_bfd_section_data
41*ef5ccd6cSJohn Marino {
42*ef5ccd6cSJohn Marino   /* Size of the data.  */
43*ef5ccd6cSJohn Marino   bfd_size_type size;
44*ef5ccd6cSJohn Marino   /* If the data was mmapped, this is the length of the map.  */
45*ef5ccd6cSJohn Marino   bfd_size_type map_len;
46*ef5ccd6cSJohn Marino   /* The data.  If NULL, the section data has not been read.  */
47*ef5ccd6cSJohn Marino   void *data;
48*ef5ccd6cSJohn Marino   /* If the data was mmapped, this is the map address.  */
49*ef5ccd6cSJohn Marino   void *map_addr;
50*ef5ccd6cSJohn Marino };
51*ef5ccd6cSJohn Marino 
52*ef5ccd6cSJohn Marino /* A hash table holding every BFD that gdb knows about.  This is not
53*ef5ccd6cSJohn Marino    to be confused with 'gdb_bfd_cache', which is used for sharing
54*ef5ccd6cSJohn Marino    BFDs; in contrast, this hash is used just to implement
55*ef5ccd6cSJohn Marino    "maint info bfd".  */
56*ef5ccd6cSJohn Marino 
57*ef5ccd6cSJohn Marino static htab_t all_bfds;
58*ef5ccd6cSJohn Marino 
59*ef5ccd6cSJohn Marino /* See gdb_bfd.h.  */
60*ef5ccd6cSJohn Marino 
61*ef5ccd6cSJohn Marino void
gdb_bfd_stash_filename(struct bfd * abfd)62*ef5ccd6cSJohn Marino gdb_bfd_stash_filename (struct bfd *abfd)
63*ef5ccd6cSJohn Marino {
64*ef5ccd6cSJohn Marino   char *name = bfd_get_filename (abfd);
65*ef5ccd6cSJohn Marino   char *data;
66*ef5ccd6cSJohn Marino 
67*ef5ccd6cSJohn Marino   data = bfd_alloc (abfd, strlen (name) + 1);
68*ef5ccd6cSJohn Marino   strcpy (data, name);
69*ef5ccd6cSJohn Marino 
70*ef5ccd6cSJohn Marino   /* Unwarranted chumminess with BFD.  */
71*ef5ccd6cSJohn Marino   abfd->filename = data;
72*ef5ccd6cSJohn Marino }
73*ef5ccd6cSJohn Marino 
74*ef5ccd6cSJohn Marino /* An object of this type is stored in each BFD's user data.  */
75*ef5ccd6cSJohn Marino 
76*ef5ccd6cSJohn Marino struct gdb_bfd_data
77*ef5ccd6cSJohn Marino {
78*ef5ccd6cSJohn Marino   /* The reference count.  */
79*ef5ccd6cSJohn Marino   int refc;
80*ef5ccd6cSJohn Marino 
81*ef5ccd6cSJohn Marino   /* The mtime of the BFD at the point the cache entry was made.  */
82*ef5ccd6cSJohn Marino   time_t mtime;
83*ef5ccd6cSJohn Marino 
84*ef5ccd6cSJohn Marino   /* If the BFD comes from an archive, this points to the archive's
85*ef5ccd6cSJohn Marino      BFD.  Otherwise, this is NULL.  */
86*ef5ccd6cSJohn Marino   bfd *archive_bfd;
87*ef5ccd6cSJohn Marino 
88*ef5ccd6cSJohn Marino   /* The registry.  */
89*ef5ccd6cSJohn Marino   REGISTRY_FIELDS;
90*ef5ccd6cSJohn Marino };
91*ef5ccd6cSJohn Marino 
92*ef5ccd6cSJohn Marino #define GDB_BFD_DATA_ACCESSOR(ABFD) \
93*ef5ccd6cSJohn Marino   ((struct gdb_bfd_data *) bfd_usrdata (ABFD))
94*ef5ccd6cSJohn Marino 
DEFINE_REGISTRY(bfd,GDB_BFD_DATA_ACCESSOR)95*ef5ccd6cSJohn Marino DEFINE_REGISTRY (bfd, GDB_BFD_DATA_ACCESSOR)
96*ef5ccd6cSJohn Marino 
97*ef5ccd6cSJohn Marino /* A hash table storing all the BFDs maintained in the cache.  */
98*ef5ccd6cSJohn Marino 
99*ef5ccd6cSJohn Marino static htab_t gdb_bfd_cache;
100*ef5ccd6cSJohn Marino 
101*ef5ccd6cSJohn Marino /* The type of an object being looked up in gdb_bfd_cache.  We use
102*ef5ccd6cSJohn Marino    htab's capability of storing one kind of object (BFD in this case)
103*ef5ccd6cSJohn Marino    and using a different sort of object for searching.  */
104*ef5ccd6cSJohn Marino 
105*ef5ccd6cSJohn Marino struct gdb_bfd_cache_search
106*ef5ccd6cSJohn Marino {
107*ef5ccd6cSJohn Marino   /* The filename.  */
108*ef5ccd6cSJohn Marino   const char *filename;
109*ef5ccd6cSJohn Marino   /* The mtime.  */
110*ef5ccd6cSJohn Marino   time_t mtime;
111*ef5ccd6cSJohn Marino };
112*ef5ccd6cSJohn Marino 
113*ef5ccd6cSJohn Marino /* A hash function for BFDs.  */
114*ef5ccd6cSJohn Marino 
115*ef5ccd6cSJohn Marino static hashval_t
hash_bfd(const void * b)116*ef5ccd6cSJohn Marino hash_bfd (const void *b)
117*ef5ccd6cSJohn Marino {
118*ef5ccd6cSJohn Marino   const bfd *abfd = b;
119*ef5ccd6cSJohn Marino 
120*ef5ccd6cSJohn Marino   /* It is simplest to just hash the filename.  */
121*ef5ccd6cSJohn Marino   return htab_hash_string (bfd_get_filename (abfd));
122*ef5ccd6cSJohn Marino }
123*ef5ccd6cSJohn Marino 
124*ef5ccd6cSJohn Marino /* An equality function for BFDs.  Note that this expects the caller
125*ef5ccd6cSJohn Marino    to search using struct gdb_bfd_cache_search only, not BFDs.  */
126*ef5ccd6cSJohn Marino 
127*ef5ccd6cSJohn Marino static int
eq_bfd(const void * a,const void * b)128*ef5ccd6cSJohn Marino eq_bfd (const void *a, const void *b)
129*ef5ccd6cSJohn Marino {
130*ef5ccd6cSJohn Marino   const bfd *abfd = a;
131*ef5ccd6cSJohn Marino   const struct gdb_bfd_cache_search *s = b;
132*ef5ccd6cSJohn Marino   struct gdb_bfd_data *gdata = bfd_usrdata (abfd);
133*ef5ccd6cSJohn Marino 
134*ef5ccd6cSJohn Marino   return (gdata->mtime == s->mtime
135*ef5ccd6cSJohn Marino 	  && strcmp (bfd_get_filename (abfd), s->filename) == 0);
136*ef5ccd6cSJohn Marino }
137*ef5ccd6cSJohn Marino 
138*ef5ccd6cSJohn Marino /* See gdb_bfd.h.  */
139*ef5ccd6cSJohn Marino 
140*ef5ccd6cSJohn Marino struct bfd *
gdb_bfd_open(const char * name,const char * target,int fd)141*ef5ccd6cSJohn Marino gdb_bfd_open (const char *name, const char *target, int fd)
142*ef5ccd6cSJohn Marino {
143*ef5ccd6cSJohn Marino   hashval_t hash;
144*ef5ccd6cSJohn Marino   void **slot;
145*ef5ccd6cSJohn Marino   bfd *abfd;
146*ef5ccd6cSJohn Marino   struct gdb_bfd_cache_search search;
147*ef5ccd6cSJohn Marino   struct stat st;
148*ef5ccd6cSJohn Marino 
149*ef5ccd6cSJohn Marino   if (gdb_bfd_cache == NULL)
150*ef5ccd6cSJohn Marino     gdb_bfd_cache = htab_create_alloc (1, hash_bfd, eq_bfd, NULL,
151*ef5ccd6cSJohn Marino 				       xcalloc, xfree);
152*ef5ccd6cSJohn Marino 
153*ef5ccd6cSJohn Marino   if (fd == -1)
154*ef5ccd6cSJohn Marino     {
155*ef5ccd6cSJohn Marino       fd = open (name, O_RDONLY | O_BINARY);
156*ef5ccd6cSJohn Marino       if (fd == -1)
157*ef5ccd6cSJohn Marino 	{
158*ef5ccd6cSJohn Marino 	  bfd_set_error (bfd_error_system_call);
159*ef5ccd6cSJohn Marino 	  return NULL;
160*ef5ccd6cSJohn Marino 	}
161*ef5ccd6cSJohn Marino     }
162*ef5ccd6cSJohn Marino 
163*ef5ccd6cSJohn Marino   search.filename = name;
164*ef5ccd6cSJohn Marino   if (fstat (fd, &st) < 0)
165*ef5ccd6cSJohn Marino     {
166*ef5ccd6cSJohn Marino       /* Weird situation here.  */
167*ef5ccd6cSJohn Marino       search.mtime = 0;
168*ef5ccd6cSJohn Marino     }
169*ef5ccd6cSJohn Marino   else
170*ef5ccd6cSJohn Marino     search.mtime = st.st_mtime;
171*ef5ccd6cSJohn Marino 
172*ef5ccd6cSJohn Marino   /* Note that this must compute the same result as hash_bfd.  */
173*ef5ccd6cSJohn Marino   hash = htab_hash_string (name);
174*ef5ccd6cSJohn Marino   /* Note that we cannot use htab_find_slot_with_hash here, because
175*ef5ccd6cSJohn Marino      opening the BFD may fail; and this would violate hashtab
176*ef5ccd6cSJohn Marino      invariants.  */
177*ef5ccd6cSJohn Marino   abfd = htab_find_with_hash (gdb_bfd_cache, &search, hash);
178*ef5ccd6cSJohn Marino   if (abfd != NULL)
179*ef5ccd6cSJohn Marino     {
180*ef5ccd6cSJohn Marino       close (fd);
181*ef5ccd6cSJohn Marino       gdb_bfd_ref (abfd);
182*ef5ccd6cSJohn Marino       return abfd;
183*ef5ccd6cSJohn Marino     }
184*ef5ccd6cSJohn Marino 
185*ef5ccd6cSJohn Marino   abfd = bfd_fopen (name, target, FOPEN_RB, fd);
186*ef5ccd6cSJohn Marino   if (abfd == NULL)
187*ef5ccd6cSJohn Marino     return NULL;
188*ef5ccd6cSJohn Marino 
189*ef5ccd6cSJohn Marino   slot = htab_find_slot_with_hash (gdb_bfd_cache, &search, hash, INSERT);
190*ef5ccd6cSJohn Marino   gdb_assert (!*slot);
191*ef5ccd6cSJohn Marino   *slot = abfd;
192*ef5ccd6cSJohn Marino 
193*ef5ccd6cSJohn Marino   gdb_bfd_stash_filename (abfd);
194*ef5ccd6cSJohn Marino   gdb_bfd_ref (abfd);
195*ef5ccd6cSJohn Marino   return abfd;
196*ef5ccd6cSJohn Marino }
197*ef5ccd6cSJohn Marino 
198*ef5ccd6cSJohn Marino /* A helper function that releases any section data attached to the
199*ef5ccd6cSJohn Marino    BFD.  */
200*ef5ccd6cSJohn Marino 
201*ef5ccd6cSJohn Marino static void
free_one_bfd_section(bfd * abfd,asection * sectp,void * ignore)202*ef5ccd6cSJohn Marino free_one_bfd_section (bfd *abfd, asection *sectp, void *ignore)
203*ef5ccd6cSJohn Marino {
204*ef5ccd6cSJohn Marino   struct gdb_bfd_section_data *sect = bfd_get_section_userdata (abfd, sectp);
205*ef5ccd6cSJohn Marino 
206*ef5ccd6cSJohn Marino   if (sect != NULL && sect->data != NULL)
207*ef5ccd6cSJohn Marino     {
208*ef5ccd6cSJohn Marino #ifdef HAVE_MMAP
209*ef5ccd6cSJohn Marino       if (sect->map_addr != NULL)
210*ef5ccd6cSJohn Marino 	{
211*ef5ccd6cSJohn Marino 	  int res;
212*ef5ccd6cSJohn Marino 
213*ef5ccd6cSJohn Marino 	  res = munmap (sect->map_addr, sect->map_len);
214*ef5ccd6cSJohn Marino 	  gdb_assert (res == 0);
215*ef5ccd6cSJohn Marino 	}
216*ef5ccd6cSJohn Marino       else
217*ef5ccd6cSJohn Marino #endif
218*ef5ccd6cSJohn Marino 	xfree (sect->data);
219*ef5ccd6cSJohn Marino     }
220*ef5ccd6cSJohn Marino }
221*ef5ccd6cSJohn Marino 
222*ef5ccd6cSJohn Marino /* Close ABFD, and warn if that fails.  */
223*ef5ccd6cSJohn Marino 
224*ef5ccd6cSJohn Marino static int
gdb_bfd_close_or_warn(struct bfd * abfd)225*ef5ccd6cSJohn Marino gdb_bfd_close_or_warn (struct bfd *abfd)
226*ef5ccd6cSJohn Marino {
227*ef5ccd6cSJohn Marino   int ret;
228*ef5ccd6cSJohn Marino   char *name = bfd_get_filename (abfd);
229*ef5ccd6cSJohn Marino 
230*ef5ccd6cSJohn Marino   bfd_map_over_sections (abfd, free_one_bfd_section, NULL);
231*ef5ccd6cSJohn Marino 
232*ef5ccd6cSJohn Marino   ret = bfd_close (abfd);
233*ef5ccd6cSJohn Marino 
234*ef5ccd6cSJohn Marino   if (!ret)
235*ef5ccd6cSJohn Marino     warning (_("cannot close \"%s\": %s"),
236*ef5ccd6cSJohn Marino 	     name, bfd_errmsg (bfd_get_error ()));
237*ef5ccd6cSJohn Marino 
238*ef5ccd6cSJohn Marino   return ret;
239*ef5ccd6cSJohn Marino }
240*ef5ccd6cSJohn Marino 
241*ef5ccd6cSJohn Marino /* See gdb_bfd.h.  */
242*ef5ccd6cSJohn Marino 
243*ef5ccd6cSJohn Marino void
gdb_bfd_ref(struct bfd * abfd)244*ef5ccd6cSJohn Marino gdb_bfd_ref (struct bfd *abfd)
245*ef5ccd6cSJohn Marino {
246*ef5ccd6cSJohn Marino   struct gdb_bfd_data *gdata;
247*ef5ccd6cSJohn Marino   void **slot;
248*ef5ccd6cSJohn Marino 
249*ef5ccd6cSJohn Marino   if (abfd == NULL)
250*ef5ccd6cSJohn Marino     return;
251*ef5ccd6cSJohn Marino 
252*ef5ccd6cSJohn Marino   gdata = bfd_usrdata (abfd);
253*ef5ccd6cSJohn Marino 
254*ef5ccd6cSJohn Marino   if (gdata != NULL)
255*ef5ccd6cSJohn Marino     {
256*ef5ccd6cSJohn Marino       gdata->refc += 1;
257*ef5ccd6cSJohn Marino       return;
258*ef5ccd6cSJohn Marino     }
259*ef5ccd6cSJohn Marino 
260*ef5ccd6cSJohn Marino   /* Ask BFD to decompress sections in bfd_get_full_section_contents.  */
261*ef5ccd6cSJohn Marino   abfd->flags |= BFD_DECOMPRESS;
262*ef5ccd6cSJohn Marino 
263*ef5ccd6cSJohn Marino   gdata = bfd_zalloc (abfd, sizeof (struct gdb_bfd_data));
264*ef5ccd6cSJohn Marino   gdata->refc = 1;
265*ef5ccd6cSJohn Marino   gdata->mtime = bfd_get_mtime (abfd);
266*ef5ccd6cSJohn Marino   gdata->archive_bfd = NULL;
267*ef5ccd6cSJohn Marino   bfd_usrdata (abfd) = gdata;
268*ef5ccd6cSJohn Marino 
269*ef5ccd6cSJohn Marino   bfd_alloc_data (abfd);
270*ef5ccd6cSJohn Marino 
271*ef5ccd6cSJohn Marino   /* This is the first we've seen it, so add it to the hash table.  */
272*ef5ccd6cSJohn Marino   slot = htab_find_slot (all_bfds, abfd, INSERT);
273*ef5ccd6cSJohn Marino   gdb_assert (slot && !*slot);
274*ef5ccd6cSJohn Marino   *slot = abfd;
275*ef5ccd6cSJohn Marino }
276*ef5ccd6cSJohn Marino 
277*ef5ccd6cSJohn Marino /* See gdb_bfd.h.  */
278*ef5ccd6cSJohn Marino 
279*ef5ccd6cSJohn Marino void
gdb_bfd_unref(struct bfd * abfd)280*ef5ccd6cSJohn Marino gdb_bfd_unref (struct bfd *abfd)
281*ef5ccd6cSJohn Marino {
282*ef5ccd6cSJohn Marino   struct gdb_bfd_data *gdata;
283*ef5ccd6cSJohn Marino   struct gdb_bfd_cache_search search;
284*ef5ccd6cSJohn Marino   bfd *archive_bfd;
285*ef5ccd6cSJohn Marino 
286*ef5ccd6cSJohn Marino   if (abfd == NULL)
287*ef5ccd6cSJohn Marino     return;
288*ef5ccd6cSJohn Marino 
289*ef5ccd6cSJohn Marino   gdata = bfd_usrdata (abfd);
290*ef5ccd6cSJohn Marino   gdb_assert (gdata->refc >= 1);
291*ef5ccd6cSJohn Marino 
292*ef5ccd6cSJohn Marino   gdata->refc -= 1;
293*ef5ccd6cSJohn Marino   if (gdata->refc > 0)
294*ef5ccd6cSJohn Marino     return;
295*ef5ccd6cSJohn Marino 
296*ef5ccd6cSJohn Marino   archive_bfd = gdata->archive_bfd;
297*ef5ccd6cSJohn Marino   search.filename = bfd_get_filename (abfd);
298*ef5ccd6cSJohn Marino 
299*ef5ccd6cSJohn Marino   if (gdb_bfd_cache && search.filename)
300*ef5ccd6cSJohn Marino     {
301*ef5ccd6cSJohn Marino       hashval_t hash = htab_hash_string (search.filename);
302*ef5ccd6cSJohn Marino       void **slot;
303*ef5ccd6cSJohn Marino 
304*ef5ccd6cSJohn Marino       search.mtime = gdata->mtime;
305*ef5ccd6cSJohn Marino       slot = htab_find_slot_with_hash (gdb_bfd_cache, &search, hash,
306*ef5ccd6cSJohn Marino 				       NO_INSERT);
307*ef5ccd6cSJohn Marino 
308*ef5ccd6cSJohn Marino       if (slot && *slot)
309*ef5ccd6cSJohn Marino 	htab_clear_slot (gdb_bfd_cache, slot);
310*ef5ccd6cSJohn Marino     }
311*ef5ccd6cSJohn Marino 
312*ef5ccd6cSJohn Marino   bfd_free_data (abfd);
313*ef5ccd6cSJohn Marino   bfd_usrdata (abfd) = NULL;  /* Paranoia.  */
314*ef5ccd6cSJohn Marino 
315*ef5ccd6cSJohn Marino   htab_remove_elt (all_bfds, abfd);
316*ef5ccd6cSJohn Marino 
317*ef5ccd6cSJohn Marino   gdb_bfd_close_or_warn (abfd);
318*ef5ccd6cSJohn Marino 
319*ef5ccd6cSJohn Marino   gdb_bfd_unref (archive_bfd);
320*ef5ccd6cSJohn Marino }
321*ef5ccd6cSJohn Marino 
322*ef5ccd6cSJohn Marino /* A helper function that returns the section data descriptor
323*ef5ccd6cSJohn Marino    associated with SECTION.  If no such descriptor exists, a new one
324*ef5ccd6cSJohn Marino    is allocated and cleared.  */
325*ef5ccd6cSJohn Marino 
326*ef5ccd6cSJohn Marino static struct gdb_bfd_section_data *
get_section_descriptor(asection * section)327*ef5ccd6cSJohn Marino get_section_descriptor (asection *section)
328*ef5ccd6cSJohn Marino {
329*ef5ccd6cSJohn Marino   struct gdb_bfd_section_data *result;
330*ef5ccd6cSJohn Marino 
331*ef5ccd6cSJohn Marino   result = bfd_get_section_userdata (section->owner, section);
332*ef5ccd6cSJohn Marino 
333*ef5ccd6cSJohn Marino   if (result == NULL)
334*ef5ccd6cSJohn Marino     {
335*ef5ccd6cSJohn Marino       result = bfd_zalloc (section->owner, sizeof (*result));
336*ef5ccd6cSJohn Marino       bfd_set_section_userdata (section->owner, section, result);
337*ef5ccd6cSJohn Marino     }
338*ef5ccd6cSJohn Marino 
339*ef5ccd6cSJohn Marino   return result;
340*ef5ccd6cSJohn Marino }
341*ef5ccd6cSJohn Marino 
342*ef5ccd6cSJohn Marino /* See gdb_bfd.h.  */
343*ef5ccd6cSJohn Marino 
344*ef5ccd6cSJohn Marino const gdb_byte *
gdb_bfd_map_section(asection * sectp,bfd_size_type * size)345*ef5ccd6cSJohn Marino gdb_bfd_map_section (asection *sectp, bfd_size_type *size)
346*ef5ccd6cSJohn Marino {
347*ef5ccd6cSJohn Marino   bfd *abfd;
348*ef5ccd6cSJohn Marino   struct gdb_bfd_section_data *descriptor;
349*ef5ccd6cSJohn Marino   bfd_byte *data;
350*ef5ccd6cSJohn Marino 
351*ef5ccd6cSJohn Marino   gdb_assert ((sectp->flags & SEC_RELOC) == 0);
352*ef5ccd6cSJohn Marino   gdb_assert (size != NULL);
353*ef5ccd6cSJohn Marino 
354*ef5ccd6cSJohn Marino   abfd = sectp->owner;
355*ef5ccd6cSJohn Marino 
356*ef5ccd6cSJohn Marino   descriptor = get_section_descriptor (sectp);
357*ef5ccd6cSJohn Marino 
358*ef5ccd6cSJohn Marino   /* If the data was already read for this BFD, just reuse it.  */
359*ef5ccd6cSJohn Marino   if (descriptor->data != NULL)
360*ef5ccd6cSJohn Marino     goto done;
361*ef5ccd6cSJohn Marino 
362*ef5ccd6cSJohn Marino #ifdef HAVE_MMAP
363*ef5ccd6cSJohn Marino   if (!bfd_is_section_compressed (abfd, sectp))
364*ef5ccd6cSJohn Marino     {
365*ef5ccd6cSJohn Marino       /* The page size, used when mmapping.  */
366*ef5ccd6cSJohn Marino       static int pagesize;
367*ef5ccd6cSJohn Marino 
368*ef5ccd6cSJohn Marino       if (pagesize == 0)
369*ef5ccd6cSJohn Marino 	pagesize = getpagesize ();
370*ef5ccd6cSJohn Marino 
371*ef5ccd6cSJohn Marino       /* Only try to mmap sections which are large enough: we don't want
372*ef5ccd6cSJohn Marino 	 to waste space due to fragmentation.  */
373*ef5ccd6cSJohn Marino 
374*ef5ccd6cSJohn Marino       if (bfd_get_section_size (sectp) > 4 * pagesize)
375*ef5ccd6cSJohn Marino 	{
376*ef5ccd6cSJohn Marino 	  descriptor->size = bfd_get_section_size (sectp);
377*ef5ccd6cSJohn Marino 	  descriptor->data = bfd_mmap (abfd, 0, descriptor->size, PROT_READ,
378*ef5ccd6cSJohn Marino 				       MAP_PRIVATE, sectp->filepos,
379*ef5ccd6cSJohn Marino 				       &descriptor->map_addr,
380*ef5ccd6cSJohn Marino 				       &descriptor->map_len);
381*ef5ccd6cSJohn Marino 
382*ef5ccd6cSJohn Marino 	  if ((caddr_t)descriptor->data != MAP_FAILED)
383*ef5ccd6cSJohn Marino 	    {
384*ef5ccd6cSJohn Marino #if HAVE_POSIX_MADVISE
385*ef5ccd6cSJohn Marino 	      posix_madvise (descriptor->map_addr, descriptor->map_len,
386*ef5ccd6cSJohn Marino 			     POSIX_MADV_WILLNEED);
387*ef5ccd6cSJohn Marino #endif
388*ef5ccd6cSJohn Marino 	      goto done;
389*ef5ccd6cSJohn Marino 	    }
390*ef5ccd6cSJohn Marino 
391*ef5ccd6cSJohn Marino 	  /* On failure, clear out the section data and try again.  */
392*ef5ccd6cSJohn Marino 	  memset (descriptor, 0, sizeof (*descriptor));
393*ef5ccd6cSJohn Marino 	}
394*ef5ccd6cSJohn Marino     }
395*ef5ccd6cSJohn Marino #endif /* HAVE_MMAP */
396*ef5ccd6cSJohn Marino 
397*ef5ccd6cSJohn Marino   /* Handle compressed sections, or ordinary uncompressed sections in
398*ef5ccd6cSJohn Marino      the no-mmap case.  */
399*ef5ccd6cSJohn Marino 
400*ef5ccd6cSJohn Marino   descriptor->size = bfd_get_section_size (sectp);
401*ef5ccd6cSJohn Marino   descriptor->data = NULL;
402*ef5ccd6cSJohn Marino 
403*ef5ccd6cSJohn Marino   data = NULL;
404*ef5ccd6cSJohn Marino   if (!bfd_get_full_section_contents (abfd, sectp, &data))
405*ef5ccd6cSJohn Marino     error (_("Can't read data for section '%s' in file '%s'"),
406*ef5ccd6cSJohn Marino 	   bfd_get_section_name (abfd, sectp),
407*ef5ccd6cSJohn Marino 	   bfd_get_filename (abfd));
408*ef5ccd6cSJohn Marino   descriptor->data = data;
409*ef5ccd6cSJohn Marino 
410*ef5ccd6cSJohn Marino  done:
411*ef5ccd6cSJohn Marino   gdb_assert (descriptor->data != NULL);
412*ef5ccd6cSJohn Marino   *size = descriptor->size;
413*ef5ccd6cSJohn Marino   return descriptor->data;
414*ef5ccd6cSJohn Marino }
415*ef5ccd6cSJohn Marino 
416*ef5ccd6cSJohn Marino 
417*ef5ccd6cSJohn Marino 
418*ef5ccd6cSJohn Marino /* See gdb_bfd.h.  */
419*ef5ccd6cSJohn Marino 
420*ef5ccd6cSJohn Marino bfd *
gdb_bfd_fopen(const char * filename,const char * target,const char * mode,int fd)421*ef5ccd6cSJohn Marino gdb_bfd_fopen (const char *filename, const char *target, const char *mode,
422*ef5ccd6cSJohn Marino 	       int fd)
423*ef5ccd6cSJohn Marino {
424*ef5ccd6cSJohn Marino   bfd *result = bfd_fopen (filename, target, mode, fd);
425*ef5ccd6cSJohn Marino 
426*ef5ccd6cSJohn Marino   if (result)
427*ef5ccd6cSJohn Marino     {
428*ef5ccd6cSJohn Marino       gdb_bfd_stash_filename (result);
429*ef5ccd6cSJohn Marino       gdb_bfd_ref (result);
430*ef5ccd6cSJohn Marino     }
431*ef5ccd6cSJohn Marino 
432*ef5ccd6cSJohn Marino   return result;
433*ef5ccd6cSJohn Marino }
434*ef5ccd6cSJohn Marino 
435*ef5ccd6cSJohn Marino /* See gdb_bfd.h.  */
436*ef5ccd6cSJohn Marino 
437*ef5ccd6cSJohn Marino bfd *
gdb_bfd_openr(const char * filename,const char * target)438*ef5ccd6cSJohn Marino gdb_bfd_openr (const char *filename, const char *target)
439*ef5ccd6cSJohn Marino {
440*ef5ccd6cSJohn Marino   bfd *result = bfd_openr (filename, target);
441*ef5ccd6cSJohn Marino 
442*ef5ccd6cSJohn Marino   if (result)
443*ef5ccd6cSJohn Marino     {
444*ef5ccd6cSJohn Marino       gdb_bfd_stash_filename (result);
445*ef5ccd6cSJohn Marino       gdb_bfd_ref (result);
446*ef5ccd6cSJohn Marino     }
447*ef5ccd6cSJohn Marino 
448*ef5ccd6cSJohn Marino   return result;
449*ef5ccd6cSJohn Marino }
450*ef5ccd6cSJohn Marino 
451*ef5ccd6cSJohn Marino /* See gdb_bfd.h.  */
452*ef5ccd6cSJohn Marino 
453*ef5ccd6cSJohn Marino bfd *
gdb_bfd_openw(const char * filename,const char * target)454*ef5ccd6cSJohn Marino gdb_bfd_openw (const char *filename, const char *target)
455*ef5ccd6cSJohn Marino {
456*ef5ccd6cSJohn Marino   bfd *result = bfd_openw (filename, target);
457*ef5ccd6cSJohn Marino 
458*ef5ccd6cSJohn Marino   if (result)
459*ef5ccd6cSJohn Marino     {
460*ef5ccd6cSJohn Marino       gdb_bfd_stash_filename (result);
461*ef5ccd6cSJohn Marino       gdb_bfd_ref (result);
462*ef5ccd6cSJohn Marino     }
463*ef5ccd6cSJohn Marino 
464*ef5ccd6cSJohn Marino   return result;
465*ef5ccd6cSJohn Marino }
466*ef5ccd6cSJohn Marino 
467*ef5ccd6cSJohn Marino /* See gdb_bfd.h.  */
468*ef5ccd6cSJohn Marino 
469*ef5ccd6cSJohn Marino bfd *
gdb_bfd_openr_iovec(const char * filename,const char * target,void * (* open_func)(struct bfd * nbfd,void * open_closure),void * open_closure,file_ptr (* pread_func)(struct bfd * nbfd,void * stream,void * buf,file_ptr nbytes,file_ptr offset),int (* close_func)(struct bfd * nbfd,void * stream),int (* stat_func)(struct bfd * abfd,void * stream,struct stat * sb))470*ef5ccd6cSJohn Marino gdb_bfd_openr_iovec (const char *filename, const char *target,
471*ef5ccd6cSJohn Marino 		     void *(*open_func) (struct bfd *nbfd,
472*ef5ccd6cSJohn Marino 					 void *open_closure),
473*ef5ccd6cSJohn Marino 		     void *open_closure,
474*ef5ccd6cSJohn Marino 		     file_ptr (*pread_func) (struct bfd *nbfd,
475*ef5ccd6cSJohn Marino 					     void *stream,
476*ef5ccd6cSJohn Marino 					     void *buf,
477*ef5ccd6cSJohn Marino 					     file_ptr nbytes,
478*ef5ccd6cSJohn Marino 					     file_ptr offset),
479*ef5ccd6cSJohn Marino 		     int (*close_func) (struct bfd *nbfd,
480*ef5ccd6cSJohn Marino 					void *stream),
481*ef5ccd6cSJohn Marino 		     int (*stat_func) (struct bfd *abfd,
482*ef5ccd6cSJohn Marino 				       void *stream,
483*ef5ccd6cSJohn Marino 				       struct stat *sb))
484*ef5ccd6cSJohn Marino {
485*ef5ccd6cSJohn Marino   bfd *result = bfd_openr_iovec (filename, target,
486*ef5ccd6cSJohn Marino 				 open_func, open_closure,
487*ef5ccd6cSJohn Marino 				 pread_func, close_func, stat_func);
488*ef5ccd6cSJohn Marino 
489*ef5ccd6cSJohn Marino   if (result)
490*ef5ccd6cSJohn Marino     {
491*ef5ccd6cSJohn Marino       gdb_bfd_ref (result);
492*ef5ccd6cSJohn Marino       gdb_bfd_stash_filename (result);
493*ef5ccd6cSJohn Marino     }
494*ef5ccd6cSJohn Marino 
495*ef5ccd6cSJohn Marino   return result;
496*ef5ccd6cSJohn Marino }
497*ef5ccd6cSJohn Marino 
498*ef5ccd6cSJohn Marino /* See gdb_bfd.h.  */
499*ef5ccd6cSJohn Marino 
500*ef5ccd6cSJohn Marino void
gdb_bfd_mark_parent(bfd * child,bfd * parent)501*ef5ccd6cSJohn Marino gdb_bfd_mark_parent (bfd *child, bfd *parent)
502*ef5ccd6cSJohn Marino {
503*ef5ccd6cSJohn Marino   struct gdb_bfd_data *gdata;
504*ef5ccd6cSJohn Marino 
505*ef5ccd6cSJohn Marino   gdb_bfd_ref (child);
506*ef5ccd6cSJohn Marino   /* No need to stash the filename here, because we also keep a
507*ef5ccd6cSJohn Marino      reference on the parent archive.  */
508*ef5ccd6cSJohn Marino 
509*ef5ccd6cSJohn Marino   gdata = bfd_usrdata (child);
510*ef5ccd6cSJohn Marino   if (gdata->archive_bfd == NULL)
511*ef5ccd6cSJohn Marino     {
512*ef5ccd6cSJohn Marino       gdata->archive_bfd = parent;
513*ef5ccd6cSJohn Marino       gdb_bfd_ref (parent);
514*ef5ccd6cSJohn Marino     }
515*ef5ccd6cSJohn Marino   else
516*ef5ccd6cSJohn Marino     gdb_assert (gdata->archive_bfd == parent);
517*ef5ccd6cSJohn Marino }
518*ef5ccd6cSJohn Marino 
519*ef5ccd6cSJohn Marino /* See gdb_bfd.h.  */
520*ef5ccd6cSJohn Marino 
521*ef5ccd6cSJohn Marino bfd *
gdb_bfd_openr_next_archived_file(bfd * archive,bfd * previous)522*ef5ccd6cSJohn Marino gdb_bfd_openr_next_archived_file (bfd *archive, bfd *previous)
523*ef5ccd6cSJohn Marino {
524*ef5ccd6cSJohn Marino   bfd *result = bfd_openr_next_archived_file (archive, previous);
525*ef5ccd6cSJohn Marino 
526*ef5ccd6cSJohn Marino   if (result)
527*ef5ccd6cSJohn Marino     gdb_bfd_mark_parent (result, archive);
528*ef5ccd6cSJohn Marino 
529*ef5ccd6cSJohn Marino   return result;
530*ef5ccd6cSJohn Marino }
531*ef5ccd6cSJohn Marino 
532*ef5ccd6cSJohn Marino /* See gdb_bfd.h.  */
533*ef5ccd6cSJohn Marino 
534*ef5ccd6cSJohn Marino bfd *
gdb_bfd_fdopenr(const char * filename,const char * target,int fd)535*ef5ccd6cSJohn Marino gdb_bfd_fdopenr (const char *filename, const char *target, int fd)
536*ef5ccd6cSJohn Marino {
537*ef5ccd6cSJohn Marino   bfd *result = bfd_fdopenr (filename, target, fd);
538*ef5ccd6cSJohn Marino 
539*ef5ccd6cSJohn Marino   if (result)
540*ef5ccd6cSJohn Marino     {
541*ef5ccd6cSJohn Marino       gdb_bfd_ref (result);
542*ef5ccd6cSJohn Marino       gdb_bfd_stash_filename (result);
543*ef5ccd6cSJohn Marino     }
544*ef5ccd6cSJohn Marino 
545*ef5ccd6cSJohn Marino   return result;
546*ef5ccd6cSJohn Marino }
547*ef5ccd6cSJohn Marino 
548*ef5ccd6cSJohn Marino 
549*ef5ccd6cSJohn Marino 
550*ef5ccd6cSJohn Marino /* A callback for htab_traverse that prints a single BFD.  */
551*ef5ccd6cSJohn Marino 
552*ef5ccd6cSJohn Marino static int
print_one_bfd(void ** slot,void * data)553*ef5ccd6cSJohn Marino print_one_bfd (void **slot, void *data)
554*ef5ccd6cSJohn Marino {
555*ef5ccd6cSJohn Marino   bfd *abfd = *slot;
556*ef5ccd6cSJohn Marino   struct gdb_bfd_data *gdata = bfd_usrdata (abfd);
557*ef5ccd6cSJohn Marino   struct ui_out *uiout = data;
558*ef5ccd6cSJohn Marino   struct cleanup *inner;
559*ef5ccd6cSJohn Marino 
560*ef5ccd6cSJohn Marino   inner = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
561*ef5ccd6cSJohn Marino   ui_out_field_int (uiout, "refcount", gdata->refc);
562*ef5ccd6cSJohn Marino   ui_out_field_string (uiout, "addr", host_address_to_string (abfd));
563*ef5ccd6cSJohn Marino   ui_out_field_string (uiout, "filename", bfd_get_filename (abfd));
564*ef5ccd6cSJohn Marino   ui_out_text (uiout, "\n");
565*ef5ccd6cSJohn Marino   do_cleanups (inner);
566*ef5ccd6cSJohn Marino 
567*ef5ccd6cSJohn Marino   return 1;
568*ef5ccd6cSJohn Marino }
569*ef5ccd6cSJohn Marino 
570*ef5ccd6cSJohn Marino /* Implement the 'maint info bfd' command.  */
571*ef5ccd6cSJohn Marino 
572*ef5ccd6cSJohn Marino static void
maintenance_info_bfds(char * arg,int from_tty)573*ef5ccd6cSJohn Marino maintenance_info_bfds (char *arg, int from_tty)
574*ef5ccd6cSJohn Marino {
575*ef5ccd6cSJohn Marino   struct cleanup *cleanup;
576*ef5ccd6cSJohn Marino   struct ui_out *uiout = current_uiout;
577*ef5ccd6cSJohn Marino 
578*ef5ccd6cSJohn Marino   cleanup = make_cleanup_ui_out_table_begin_end (uiout, 3, -1, "bfds");
579*ef5ccd6cSJohn Marino   ui_out_table_header (uiout, 10, ui_left, "refcount", "Refcount");
580*ef5ccd6cSJohn Marino   ui_out_table_header (uiout, 18, ui_left, "addr", "Address");
581*ef5ccd6cSJohn Marino   ui_out_table_header (uiout, 40, ui_left, "filename", "Filename");
582*ef5ccd6cSJohn Marino 
583*ef5ccd6cSJohn Marino   ui_out_table_body (uiout);
584*ef5ccd6cSJohn Marino   htab_traverse (all_bfds, print_one_bfd, uiout);
585*ef5ccd6cSJohn Marino 
586*ef5ccd6cSJohn Marino   do_cleanups (cleanup);
587*ef5ccd6cSJohn Marino }
588*ef5ccd6cSJohn Marino 
589*ef5ccd6cSJohn Marino /* -Wmissing-prototypes */
590*ef5ccd6cSJohn Marino extern initialize_file_ftype _initialize_gdb_bfd;
591*ef5ccd6cSJohn Marino 
592*ef5ccd6cSJohn Marino void
_initialize_gdb_bfd(void)593*ef5ccd6cSJohn Marino _initialize_gdb_bfd (void)
594*ef5ccd6cSJohn Marino {
595*ef5ccd6cSJohn Marino   all_bfds = htab_create_alloc (10, htab_hash_pointer, htab_eq_pointer,
596*ef5ccd6cSJohn Marino 				NULL, xcalloc, xfree);
597*ef5ccd6cSJohn Marino 
598*ef5ccd6cSJohn Marino   add_cmd ("bfds", class_maintenance, maintenance_info_bfds, _("\
599*ef5ccd6cSJohn Marino List the BFDs that are currently open."),
600*ef5ccd6cSJohn Marino 	   &maintenanceinfolist);
601*ef5ccd6cSJohn Marino }
602