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 _libctf_unused_
,
123 const ctf_sect_t
*ctfsect
, int *errp
)
125 struct ctf_archive
*arc
= NULL
;
127 ctf_file_t
*fp
= NULL
;
128 ctf_sect_t
*symsectp
= NULL
;
129 ctf_sect_t
*strsectp
= NULL
;
130 const char *bfderrstr
= NULL
;
135 ctf_sect_t symsect
, strsect
;
136 /* TODO: handle SYMTAB_SHNDX. */
138 if ((sym_asect
= bfd_section_from_elf_index (abfd
,
139 elf_onesymtab (abfd
))) != NULL
)
141 Elf_Internal_Shdr
*symhdr
= &elf_symtab_hdr (abfd
);
142 asection
*str_asect
= NULL
;
145 if (symhdr
->sh_link
!= SHN_UNDEF
&&
146 symhdr
->sh_link
<= elf_numsections (abfd
))
147 str_asect
= bfd_section_from_elf_index (abfd
, symhdr
->sh_link
);
149 Elf_Internal_Shdr
*strhdr
= elf_elfsections (abfd
)[symhdr
->sh_link
];
151 if (sym_asect
&& str_asect
)
153 if (!bfd_malloc_and_get_section (abfd
, str_asect
, &contents
))
155 bfderrstr
= "Cannot malloc string table";
159 strsect
.cts_data
= contents
;
160 strsect
.cts_name
= (char *) strsect
.cts_data
+ strhdr
->sh_name
;
161 strsect
.cts_type
= strhdr
->sh_type
;
162 strsect
.cts_flags
= strhdr
->sh_flags
;
163 strsect
.cts_entsize
= strhdr
->sh_size
;
164 strsect
.cts_offset
= strhdr
->sh_offset
;
167 if (!bfd_malloc_and_get_section (abfd
, sym_asect
, &contents
))
169 bfderrstr
= "Cannot malloc symbol table";
174 symsect
.cts_name
= (char *) strsect
.cts_data
+ symhdr
->sh_name
;
175 symsect
.cts_type
= symhdr
->sh_type
;
176 symsect
.cts_flags
= symhdr
->sh_flags
;
177 symsect
.cts_entsize
= symhdr
->sh_size
;
178 symsect
.cts_data
= contents
;
179 symsect
.cts_offset
= symhdr
->sh_offset
;
185 if (ctfsect
->cts_size
> sizeof (uint64_t) &&
186 ((*(uint64_t *) ctfsect
->cts_data
) == CTFA_MAGIC
))
189 if ((arc
= ctf_arc_bufopen ((void *) ctfsect
->cts_data
,
190 ctfsect
->cts_size
, errp
)) == NULL
)
196 if ((fp
= ctf_bufopen (ctfsect
, symsectp
, strsectp
, errp
)) == NULL
)
198 ctf_dprintf ("ctf_internal_open(): cannot open CTF: %s\n",
203 arci
= ctf_new_archive_internal (is_archive
, arc
, fp
, symsectp
, strsectp
,
210 free ((void *) symsect
.cts_data
);
212 free ((void *) strsect
.cts_data
);
214 err
: _libctf_unused_
;
217 ctf_dprintf ("ctf_bfdopen(): %s: %s\n", bfderrstr
,
218 bfd_errmsg (bfd_get_error()));
219 ctf_set_open_errno (errp
, ECTF_FMT
);
224 /* Open the specified file descriptor and return a pointer to a CTF archive that
225 contains one or more CTF containers. The file can be an ELF file, a raw CTF
226 file, or a CTF archive. The caller is responsible for closing the file
227 descriptor when it is no longer needed. If this is an ELF file, TARGET, if
228 non-NULL, should be the name of a suitable BFD target. */
231 ctf_fdopen (int fd
, const char *filename
, const char *target
, int *errp
)
240 ctf_preamble_t ctfhdr
;
243 memset (&ctfhdr
, 0, sizeof (ctfhdr
));
247 if (fstat (fd
, &st
) == -1)
248 return (ctf_set_open_errno (errp
, errno
));
250 if ((nbytes
= ctf_pread (fd
, &ctfhdr
, sizeof (ctfhdr
), 0)) <= 0)
251 return (ctf_set_open_errno (errp
, nbytes
< 0 ? errno
: ECTF_FMT
));
253 /* If we have read enough bytes to form a CTF header and the magic
254 string matches, attempt to interpret the file as raw CTF. */
256 if ((size_t) nbytes
>= sizeof (ctf_preamble_t
) &&
257 ctfhdr
.ctp_magic
== CTF_MAGIC
)
259 ctf_file_t
*fp
= NULL
;
262 if (ctfhdr
.ctp_version
> CTF_VERSION
)
263 return (ctf_set_open_errno (errp
, ECTF_CTFVERS
));
265 if ((data
= ctf_mmap (st
.st_size
, 0, fd
)) == NULL
)
266 return (ctf_set_open_errno (errp
, errno
));
268 if ((fp
= ctf_simple_open (data
, (size_t) st
.st_size
, NULL
, 0, 0,
269 NULL
, 0, errp
)) == NULL
)
270 ctf_munmap (data
, (size_t) st
.st_size
);
271 fp
->ctf_data_mmapped
= data
;
272 fp
->ctf_data_mmapped_len
= (size_t) st
.st_size
;
274 return ctf_new_archive_internal (0, NULL
, fp
, NULL
, NULL
, errp
);
277 if ((nbytes
= ctf_pread (fd
, &arc_magic
, sizeof (arc_magic
), 0)) <= 0)
278 return (ctf_set_open_errno (errp
, nbytes
< 0 ? errno
: ECTF_FMT
));
280 if ((size_t) nbytes
>= sizeof (uint64_t) && arc_magic
== CTFA_MAGIC
)
282 struct ctf_archive
*arc
;
284 if ((arc
= ctf_arc_open_internal (filename
, errp
)) == NULL
)
285 return NULL
; /* errno is set for us. */
287 return ctf_new_archive_internal (1, arc
, NULL
, NULL
, NULL
, errp
);
290 /* Attempt to open the file with BFD. We must dup the fd first, since bfd
291 takes ownership of the passed fd. */
293 if ((nfd
= dup (fd
)) < 0)
294 return (ctf_set_open_errno (errp
, errno
));
296 if ((abfd
= bfd_fdopenr (filename
, target
, nfd
)) == NULL
)
298 ctf_dprintf ("Cannot open BFD from %s: %s\n",
299 filename
? filename
: "(unknown file)",
300 bfd_errmsg (bfd_get_error()));
301 return (ctf_set_open_errno (errp
, ECTF_FMT
));
304 if (!bfd_check_format (abfd
, bfd_object
))
306 ctf_dprintf ("BFD format problem in %s: %s\n",
307 filename
? filename
: "(unknown file)",
308 bfd_errmsg (bfd_get_error()));
309 if (bfd_get_error() == bfd_error_file_ambiguously_recognized
)
310 return (ctf_set_open_errno (errp
, ECTF_BFD_AMBIGUOUS
));
312 return (ctf_set_open_errno (errp
, ECTF_FMT
));
315 if ((arci
= ctf_bfdopen (abfd
, errp
)) == NULL
)
317 if (!bfd_close_all_done (abfd
))
318 ctf_dprintf ("Cannot close BFD: %s\n", bfd_errmsg (bfd_get_error()));
319 return NULL
; /* errno is set for us. */
321 arci
->ctfi_bfd_close
= ctf_bfdclose
;
322 arci
->ctfi_abfd
= abfd
;
327 /* Open the specified file and return a pointer to a CTF container. The file
328 can be either an ELF file or raw CTF file. This is just a convenient
329 wrapper around ctf_fdopen() for callers. */
332 ctf_open (const char *filename
, const char *target
, int *errp
)
337 if ((fd
= open (filename
, O_RDONLY
)) == -1)
344 arc
= ctf_fdopen (fd
, filename
, target
, errp
);
349 /* Public entry point: open a CTF archive, or CTF file. Returns the archive, or
350 NULL and an error in *err. Despite the fact that this uses CTF archives, it
351 must be in this file to avoid dragging in BFD into non-BFD-using programs. */
353 ctf_arc_open (const char *filename
, int *errp
)
355 return ctf_open (filename
, NULL
, errp
);