1 /* Opening CTF files with BFD.
2 Copyright (C) 2019 Free Software Foundation, Inc.
4 This file is part of libctf.
6 libctf is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 See the GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; see the file COPYING. If not see
18 <http://www.gnu.org/licenses/>. */
22 #include <sys/types.h>
32 /* Make a new struct ctf_archive_internal wrapper for a ctf_archive or a
33 ctf_file. Closes ARC and/or FP on error. Arrange to free the SYMSECT and
34 STRSECT interior on close. */
36 static struct ctf_archive_internal
*
37 ctf_new_archive_internal (int is_archive
, struct ctf_archive
*arc
,
38 ctf_file_t
*fp
, const ctf_sect_t
*symsect
,
39 const ctf_sect_t
*strsect
,
42 struct ctf_archive_internal
*arci
;
44 if ((arci
= calloc (1, sizeof (struct ctf_archive_internal
))) == NULL
)
47 ctf_arc_close_internal (arc
);
50 return (ctf_set_open_errno (errp
, errno
));
52 arci
->ctfi_is_archive
= is_archive
;
54 arci
->ctfi_archive
= arc
;
58 memcpy (&arci
->ctfi_symsect
, symsect
, sizeof (struct ctf_sect
));
60 memcpy (&arci
->ctfi_strsect
, strsect
, sizeof (struct ctf_sect
));
65 /* Free the BFD bits of a CTF file on ctf_file_close(). */
68 ctf_bfdclose (struct ctf_archive_internal
*arci
)
70 if (arci
->ctfi_abfd
!= NULL
)
71 if (!bfd_close_all_done (arci
->ctfi_abfd
))
72 ctf_dprintf ("Cannot close BFD: %s\n", bfd_errmsg (bfd_get_error()));
75 /* Open a CTF file given the specified BFD. */
78 ctf_bfdopen (struct bfd
*abfd
, int *errp
)
87 if ((ctf_asect
= bfd_get_section_by_name (abfd
, _CTF_SECTION
)) == NULL
)
89 return (ctf_set_open_errno (errp
, ECTF_NOCTFDATA
));
92 if (!bfd_malloc_and_get_section (abfd
, ctf_asect
, &contents
))
94 ctf_dprintf ("ctf_bfdopen(): cannot malloc CTF section: %s\n",
95 bfd_errmsg (bfd_get_error()));
96 return (ctf_set_open_errno (errp
, ECTF_FMT
));
99 ctfsect
.cts_name
= _CTF_SECTION
;
100 ctfsect
.cts_entsize
= 1;
101 ctfsect
.cts_size
= bfd_section_size (abfd
, ctf_asect
);
102 ctfsect
.cts_data
= contents
;
104 if ((arc
= ctf_bfdopen_ctfsect (abfd
, &ctfsect
, errp
)) != NULL
)
106 arc
->ctfi_data
= (void *) ctfsect
.cts_data
;
111 return NULL
; /* errno is set for us. */
114 /* Open a CTF file given the specified BFD and CTF section (which may contain a
115 CTF archive or a file). Takes ownership of the ctfsect, and frees it
119 ctf_bfdopen_ctfsect (struct bfd
*abfd _libctf_unused_
,
120 const ctf_sect_t
*ctfsect
, int *errp
)
122 struct ctf_archive
*arc
= NULL
;
124 ctf_file_t
*fp
= NULL
;
125 ctf_sect_t
*symsectp
= NULL
;
126 ctf_sect_t
*strsectp
= NULL
;
127 const char *bfderrstr
= NULL
;
132 ctf_sect_t symsect
, strsect
;
133 /* TODO: handle SYMTAB_SHNDX. */
135 if ((sym_asect
= bfd_section_from_elf_index (abfd
,
136 elf_onesymtab (abfd
))) != NULL
)
138 Elf_Internal_Shdr
*symhdr
= &elf_symtab_hdr (abfd
);
139 asection
*str_asect
= NULL
;
142 if (symhdr
->sh_link
!= SHN_UNDEF
&&
143 symhdr
->sh_link
<= elf_numsections (abfd
))
144 str_asect
= bfd_section_from_elf_index (abfd
, symhdr
->sh_link
);
146 Elf_Internal_Shdr
*strhdr
= elf_elfsections (abfd
)[symhdr
->sh_link
];
148 if (sym_asect
&& str_asect
)
150 if (!bfd_malloc_and_get_section (abfd
, str_asect
, &contents
))
152 bfderrstr
= "Cannot malloc string table";
156 strsect
.cts_data
= contents
;
157 strsect
.cts_name
= (char *) strsect
.cts_data
+ strhdr
->sh_name
;
158 strsect
.cts_size
= bfd_section_size (abfd
, str_asect
);
159 strsect
.cts_entsize
= strhdr
->sh_size
;
162 if (!bfd_malloc_and_get_section (abfd
, sym_asect
, &contents
))
164 bfderrstr
= "Cannot malloc symbol table";
169 symsect
.cts_name
= (char *) strsect
.cts_data
+ symhdr
->sh_name
;
170 symsect
.cts_entsize
= symhdr
->sh_size
;
171 symsect
.cts_size
= bfd_section_size (abfd
, sym_asect
);
172 symsect
.cts_data
= contents
;
178 if (ctfsect
->cts_size
> sizeof (uint64_t) &&
179 ((*(uint64_t *) ctfsect
->cts_data
) == CTFA_MAGIC
))
182 if ((arc
= ctf_arc_bufopen ((void *) ctfsect
->cts_data
,
183 ctfsect
->cts_size
, errp
)) == NULL
)
189 if ((fp
= ctf_bufopen (ctfsect
, symsectp
, strsectp
, errp
)) == NULL
)
191 ctf_dprintf ("ctf_internal_open(): cannot open CTF: %s\n",
196 arci
= ctf_new_archive_internal (is_archive
, arc
, fp
, symsectp
, strsectp
,
203 free ((void *) symsect
.cts_data
);
205 free ((void *) strsect
.cts_data
);
207 err
: _libctf_unused_
;
210 ctf_dprintf ("ctf_bfdopen(): %s: %s\n", bfderrstr
,
211 bfd_errmsg (bfd_get_error()));
212 ctf_set_open_errno (errp
, ECTF_FMT
);
217 /* Open the specified file descriptor and return a pointer to a CTF archive that
218 contains one or more CTF containers. The file can be an ELF file, a raw CTF
219 file, or a CTF archive. The caller is responsible for closing the file
220 descriptor when it is no longer needed. If this is an ELF file, TARGET, if
221 non-NULL, should be the name of a suitable BFD target. */
224 ctf_fdopen (int fd
, const char *filename
, const char *target
, int *errp
)
233 ctf_preamble_t ctfhdr
;
236 memset (&ctfhdr
, 0, sizeof (ctfhdr
));
240 if (fstat (fd
, &st
) == -1)
241 return (ctf_set_open_errno (errp
, errno
));
243 if ((nbytes
= ctf_pread (fd
, &ctfhdr
, sizeof (ctfhdr
), 0)) <= 0)
244 return (ctf_set_open_errno (errp
, nbytes
< 0 ? errno
: ECTF_FMT
));
246 /* If we have read enough bytes to form a CTF header and the magic
247 string matches, attempt to interpret the file as raw CTF. */
249 if ((size_t) nbytes
>= sizeof (ctf_preamble_t
) &&
250 ctfhdr
.ctp_magic
== CTF_MAGIC
)
252 ctf_file_t
*fp
= NULL
;
255 if (ctfhdr
.ctp_version
> CTF_VERSION
)
256 return (ctf_set_open_errno (errp
, ECTF_CTFVERS
));
258 if ((data
= ctf_mmap (st
.st_size
, 0, fd
)) == NULL
)
259 return (ctf_set_open_errno (errp
, errno
));
261 if ((fp
= ctf_simple_open (data
, (size_t) st
.st_size
, NULL
, 0, 0,
262 NULL
, 0, errp
)) == NULL
)
263 ctf_munmap (data
, (size_t) st
.st_size
);
264 fp
->ctf_data_mmapped
= data
;
265 fp
->ctf_data_mmapped_len
= (size_t) st
.st_size
;
267 return ctf_new_archive_internal (0, NULL
, fp
, NULL
, NULL
, errp
);
270 if ((nbytes
= ctf_pread (fd
, &arc_magic
, sizeof (arc_magic
), 0)) <= 0)
271 return (ctf_set_open_errno (errp
, nbytes
< 0 ? errno
: ECTF_FMT
));
273 if ((size_t) nbytes
>= sizeof (uint64_t) && arc_magic
== CTFA_MAGIC
)
275 struct ctf_archive
*arc
;
277 if ((arc
= ctf_arc_open_internal (filename
, errp
)) == NULL
)
278 return NULL
; /* errno is set for us. */
280 return ctf_new_archive_internal (1, arc
, NULL
, NULL
, NULL
, errp
);
283 /* Attempt to open the file with BFD. We must dup the fd first, since bfd
284 takes ownership of the passed fd. */
286 if ((nfd
= dup (fd
)) < 0)
287 return (ctf_set_open_errno (errp
, errno
));
289 if ((abfd
= bfd_fdopenr (filename
, target
, nfd
)) == NULL
)
291 ctf_dprintf ("Cannot open BFD from %s: %s\n",
292 filename
? filename
: "(unknown file)",
293 bfd_errmsg (bfd_get_error()));
294 return (ctf_set_open_errno (errp
, ECTF_FMT
));
297 if (!bfd_check_format (abfd
, bfd_object
))
299 ctf_dprintf ("BFD format problem in %s: %s\n",
300 filename
? filename
: "(unknown file)",
301 bfd_errmsg (bfd_get_error()));
302 if (bfd_get_error() == bfd_error_file_ambiguously_recognized
)
303 return (ctf_set_open_errno (errp
, ECTF_BFD_AMBIGUOUS
));
305 return (ctf_set_open_errno (errp
, ECTF_FMT
));
308 if ((arci
= ctf_bfdopen (abfd
, errp
)) == NULL
)
310 if (!bfd_close_all_done (abfd
))
311 ctf_dprintf ("Cannot close BFD: %s\n", bfd_errmsg (bfd_get_error()));
312 return NULL
; /* errno is set for us. */
314 arci
->ctfi_bfd_close
= ctf_bfdclose
;
315 arci
->ctfi_abfd
= abfd
;
320 /* Open the specified file and return a pointer to a CTF container. The file
321 can be either an ELF file or raw CTF file. This is just a convenient
322 wrapper around ctf_fdopen() for callers. */
325 ctf_open (const char *filename
, const char *target
, int *errp
)
330 if ((fd
= open (filename
, O_RDONLY
)) == -1)
337 arc
= ctf_fdopen (fd
, filename
, target
, errp
);
342 /* Public entry point: open a CTF archive, or CTF file. Returns the archive, or
343 NULL and an error in *err. Despite the fact that this uses CTF archives, it
344 must be in this file to avoid dragging in BFD into non-BFD-using programs. */
346 ctf_arc_open (const char *filename
, int *errp
)
348 return ctf_open (filename
, NULL
, errp
);