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_type
= SHT_PROGBITS
;
101 ctfsect
.cts_flags
= 0;
102 ctfsect
.cts_entsize
= 1;
103 ctfsect
.cts_offset
= 0;
104 ctfsect
.cts_size
= bfd_section_size (abfd
, ctf_asect
);
105 ctfsect
.cts_data
= contents
;
107 if ((arc
= ctf_bfdopen_ctfsect (abfd
, &ctfsect
, errp
)) != NULL
)
109 arc
->ctfi_data
= (void *) ctfsect
.cts_data
;
114 return NULL
; /* errno is set for us. */
117 /* Open a CTF file given the specified BFD and CTF section (which may contain a
118 CTF archive or a file). Takes ownership of the ctfsect, and frees it
122 ctf_bfdopen_ctfsect (struct bfd
*abfd
, const ctf_sect_t
*ctfsect
, int *errp
)
124 struct ctf_archive
*arc
= NULL
;
126 ctf_file_t
*fp
= NULL
;
127 ctf_sect_t
*symsectp
= NULL
;
128 ctf_sect_t
*strsectp
= NULL
;
129 const char *bfderrstr
= NULL
;
133 ctf_sect_t symsect
, strsect
;
134 /* TODO: handle SYMTAB_SHNDX. */
136 if ((sym_asect
= bfd_section_from_elf_index (abfd
,
137 elf_onesymtab (abfd
))) != NULL
)
139 Elf_Internal_Shdr
*symhdr
= &elf_symtab_hdr (abfd
);
140 asection
*str_asect
= NULL
;
143 if (symhdr
->sh_link
!= SHN_UNDEF
&&
144 symhdr
->sh_link
<= elf_numsections (abfd
))
145 str_asect
= bfd_section_from_elf_index (abfd
, symhdr
->sh_link
);
147 Elf_Internal_Shdr
*strhdr
= elf_elfsections (abfd
)[symhdr
->sh_link
];
149 if (sym_asect
&& str_asect
)
151 if (!bfd_malloc_and_get_section (abfd
, str_asect
, &contents
))
153 bfderrstr
= "Cannot malloc string table";
157 strsect
.cts_data
= contents
;
158 strsect
.cts_name
= (char *) strsect
.cts_data
+ strhdr
->sh_name
;
159 strsect
.cts_type
= strhdr
->sh_type
;
160 strsect
.cts_flags
= strhdr
->sh_flags
;
161 strsect
.cts_entsize
= strhdr
->sh_size
;
162 strsect
.cts_offset
= strhdr
->sh_offset
;
165 if (!bfd_malloc_and_get_section (abfd
, sym_asect
, &contents
))
167 bfderrstr
= "Cannot malloc symbol table";
172 symsect
.cts_name
= (char *) strsect
.cts_data
+ symhdr
->sh_name
;
173 symsect
.cts_type
= symhdr
->sh_type
;
174 symsect
.cts_flags
= symhdr
->sh_flags
;
175 symsect
.cts_entsize
= symhdr
->sh_size
;
176 symsect
.cts_data
= contents
;
177 symsect
.cts_offset
= symhdr
->sh_offset
;
182 if (ctfsect
->cts_size
> sizeof (uint64_t) &&
183 ((*(uint64_t *) ctfsect
->cts_data
) == CTFA_MAGIC
))
186 if ((arc
= ctf_arc_bufopen ((void *) ctfsect
->cts_data
,
187 ctfsect
->cts_size
, errp
)) == NULL
)
193 if ((fp
= ctf_bufopen (ctfsect
, symsectp
, strsectp
, errp
)) == NULL
)
195 ctf_dprintf ("ctf_internal_open(): cannot open CTF: %s\n",
200 arci
= ctf_new_archive_internal (is_archive
, arc
, fp
, symsectp
, strsectp
,
206 free ((void *) symsect
.cts_data
);
208 free ((void *) strsect
.cts_data
);
209 err
: _libctf_unused_
;
212 ctf_dprintf ("ctf_bfdopen(): %s: %s\n", bfderrstr
,
213 bfd_errmsg (bfd_get_error()));
214 ctf_set_open_errno (errp
, ECTF_FMT
);
219 /* Open the specified file descriptor and return a pointer to a CTF archive that
220 contains one or more CTF containers. The file can be an ELF file, a raw CTF
221 file, or a CTF archive. The caller is responsible for closing the file
222 descriptor when it is no longer needed. If this is an ELF file, TARGET, if
223 non-NULL, should be the name of a suitable BFD target. */
226 ctf_fdopen (int fd
, const char *filename
, const char *target
, int *errp
)
235 ctf_preamble_t ctfhdr
;
238 memset (&ctfhdr
, 0, sizeof (ctfhdr
));
242 if (fstat (fd
, &st
) == -1)
243 return (ctf_set_open_errno (errp
, errno
));
245 if ((nbytes
= ctf_pread (fd
, &ctfhdr
, sizeof (ctfhdr
), 0)) <= 0)
246 return (ctf_set_open_errno (errp
, nbytes
< 0 ? errno
: ECTF_FMT
));
248 /* If we have read enough bytes to form a CTF header and the magic
249 string matches, attempt to interpret the file as raw CTF. */
251 if ((size_t) nbytes
>= sizeof (ctf_preamble_t
) &&
252 ctfhdr
.ctp_magic
== CTF_MAGIC
)
254 ctf_file_t
*fp
= NULL
;
257 if (ctfhdr
.ctp_version
> CTF_VERSION
)
258 return (ctf_set_open_errno (errp
, ECTF_CTFVERS
));
260 if ((data
= ctf_mmap (st
.st_size
, 0, fd
)) == NULL
)
261 return (ctf_set_open_errno (errp
, errno
));
263 if ((fp
= ctf_simple_open (data
, (size_t) st
.st_size
, NULL
, 0, 0,
264 NULL
, 0, errp
)) == NULL
)
265 ctf_munmap (data
, (size_t) st
.st_size
);
266 fp
->ctf_data_mmapped
= data
;
267 fp
->ctf_data_mmapped_len
= (size_t) st
.st_size
;
269 return ctf_new_archive_internal (0, NULL
, fp
, NULL
, NULL
, errp
);
272 if ((nbytes
= ctf_pread (fd
, &arc_magic
, sizeof (arc_magic
), 0)) <= 0)
273 return (ctf_set_open_errno (errp
, nbytes
< 0 ? errno
: ECTF_FMT
));
275 if ((size_t) nbytes
>= sizeof (uint64_t) && arc_magic
== CTFA_MAGIC
)
277 struct ctf_archive
*arc
;
279 if ((arc
= ctf_arc_open_internal (filename
, errp
)) == NULL
)
280 return NULL
; /* errno is set for us. */
282 return ctf_new_archive_internal (1, arc
, NULL
, NULL
, NULL
, errp
);
285 /* Attempt to open the file with BFD. We must dup the fd first, since bfd
286 takes ownership of the passed fd. */
288 if ((nfd
= dup (fd
)) < 0)
289 return (ctf_set_open_errno (errp
, errno
));
291 if ((abfd
= bfd_fdopenr (filename
, target
, nfd
)) == NULL
)
293 ctf_dprintf ("Cannot open BFD from %s: %s\n",
294 filename
? filename
: "(unknown file)",
295 bfd_errmsg (bfd_get_error()));
296 return (ctf_set_open_errno (errp
, ECTF_FMT
));
299 if (!bfd_check_format (abfd
, bfd_object
))
301 ctf_dprintf ("BFD format problem in %s: %s\n",
302 filename
? filename
: "(unknown file)",
303 bfd_errmsg (bfd_get_error()));
304 if (bfd_get_error() == bfd_error_file_ambiguously_recognized
)
305 return (ctf_set_open_errno (errp
, ECTF_BFD_AMBIGUOUS
));
307 return (ctf_set_open_errno (errp
, ECTF_FMT
));
310 if ((arci
= ctf_bfdopen (abfd
, errp
)) == NULL
)
312 if (!bfd_close_all_done (abfd
))
313 ctf_dprintf ("Cannot close BFD: %s\n", bfd_errmsg (bfd_get_error()));
314 return NULL
; /* errno is set for us. */
316 arci
->ctfi_bfd_close
= ctf_bfdclose
;
317 arci
->ctfi_abfd
= abfd
;
322 /* Open the specified file and return a pointer to a CTF container. The file
323 can be either an ELF file or raw CTF file. This is just a convenient
324 wrapper around ctf_fdopen() for callers. */
327 ctf_open (const char *filename
, const char *target
, int *errp
)
332 if ((fd
= open (filename
, O_RDONLY
)) == -1)
339 arc
= ctf_fdopen (fd
, filename
, target
, errp
);
344 /* Public entry point: open a CTF archive, or CTF file. Returns the archive, or
345 NULL and an error in *err. Despite the fact that this uses CTF archives, it
346 must be in this file to avoid dragging in BFD into non-BFD-using programs. */
348 ctf_arc_open (const char *filename
, int *errp
)
350 return ctf_open (filename
, NULL
, errp
);