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