X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=libctf%2Fctf-open-bfd.c;h=24c04038ad11c17259941fa9e9e56d659b1320b2;hb=7f0ae84c80aae6fe8f7573343fe1ab455d18b5d8;hp=5e34d123699b19e963e99fb030756c0add7205aa;hpb=9698cf9b1c485edbbeabc9f65bfd0fdef92e3854;p=deliverable%2Fbinutils-gdb.git diff --git a/libctf/ctf-open-bfd.c b/libctf/ctf-open-bfd.c index 5e34d12369..24c04038ad 100644 --- a/libctf/ctf-open-bfd.c +++ b/libctf/ctf-open-bfd.c @@ -1,5 +1,5 @@ /* Opening CTF files with BFD. - Copyright (C) 2019 Free Software Foundation, Inc. + Copyright (C) 2019-2020 Free Software Foundation, Inc. This file is part of libctf. @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -26,12 +27,15 @@ #include #include #include +#include "swap.h" +#include "ctf-endian.h" #include "elf-bfd.h" /* Make a new struct ctf_archive_internal wrapper for a ctf_archive or a - ctf_file. Closes ARC and/or FP on error. Arrange to free the SYMSECT and - STRSECT interior on close. */ + ctf_file. Closes ARC and/or FP on error. Arrange to free the SYMSECT or + STRSECT, as needed, on close (though the STRSECT interior is bound to the bfd + * and is not actually freed by this machinery). */ static struct ctf_archive_internal * ctf_new_archive_internal (int is_archive, struct ctf_archive *arc, @@ -62,7 +66,7 @@ ctf_new_archive_internal (int is_archive, struct ctf_archive *arc, return arci; } -/* Free the BFD bits of a CTF file on ctf_file_close(). */ +/* Free the BFD bits of a CTF file on ctf_arc_close(). */ static void ctf_bfdclose (struct ctf_archive_internal *arci) @@ -97,11 +101,8 @@ ctf_bfdopen (struct bfd *abfd, int *errp) } ctfsect.cts_name = _CTF_SECTION; - ctfsect.cts_type = SHT_PROGBITS; - ctfsect.cts_flags = 0; ctfsect.cts_entsize = 1; - ctfsect.cts_offset = 0; - ctfsect.cts_size = bfd_section_size (abfd, ctf_asect); + ctfsect.cts_size = bfd_section_size (ctf_asect); ctfsect.cts_data = contents; if ((arc = ctf_bfdopen_ctfsect (abfd, &ctfsect, errp)) != NULL) @@ -131,54 +132,63 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_, int is_archive; #ifdef HAVE_BFD_ELF - asection *sym_asect; ctf_sect_t symsect, strsect; + Elf_Internal_Shdr *strhdr; + Elf_Internal_Shdr *symhdr = &elf_symtab_hdr (abfd); + size_t symcount = symhdr->sh_size / symhdr->sh_entsize; + Elf_Internal_Sym *isymbuf; + bfd_byte *symtab; + const char *strtab = NULL; /* TODO: handle SYMTAB_SHNDX. */ - if ((sym_asect = bfd_section_from_elf_index (abfd, - elf_onesymtab (abfd))) != NULL) + if ((symtab = malloc (symhdr->sh_size)) == NULL) { - Elf_Internal_Shdr *symhdr = &elf_symtab_hdr (abfd); - asection *str_asect = NULL; - bfd_byte *contents; - - if (symhdr->sh_link != SHN_UNDEF && - symhdr->sh_link <= elf_numsections (abfd)) - str_asect = bfd_section_from_elf_index (abfd, symhdr->sh_link); + bfderrstr = "Cannot malloc symbol table"; + goto err; + } - Elf_Internal_Shdr *strhdr = elf_elfsections (abfd)[symhdr->sh_link]; + isymbuf = bfd_elf_get_elf_syms (abfd, symhdr, symcount, 0, + NULL, symtab, NULL); + free (isymbuf); + if (isymbuf == NULL) + { + bfderrstr = "Cannot read symbol table"; + goto err_free_sym; + } - if (sym_asect && str_asect) + if (elf_elfsections (abfd) != NULL + && symhdr->sh_link < elf_numsections (abfd)) + { + strhdr = elf_elfsections (abfd)[symhdr->sh_link]; + if (strhdr->contents == NULL) { - if (!bfd_malloc_and_get_section (abfd, str_asect, &contents)) + if ((strtab = bfd_elf_get_str_section (abfd, symhdr->sh_link)) == NULL) { - bfderrstr = "Cannot malloc string table"; - free (contents); - goto err; + bfderrstr = "Cannot read string table"; + goto err_free_sym; } - strsect.cts_data = contents; - strsect.cts_name = (char *) strsect.cts_data + strhdr->sh_name; - strsect.cts_type = strhdr->sh_type; - strsect.cts_flags = strhdr->sh_flags; - strsect.cts_entsize = strhdr->sh_size; - strsect.cts_offset = strhdr->sh_offset; - strsectp = &strsect; - - if (!bfd_malloc_and_get_section (abfd, sym_asect, &contents)) - { - bfderrstr = "Cannot malloc symbol table"; - free (contents); - goto err_free_str; - } - - symsect.cts_name = (char *) strsect.cts_data + symhdr->sh_name; - symsect.cts_type = symhdr->sh_type; - symsect.cts_flags = symhdr->sh_flags; - symsect.cts_entsize = symhdr->sh_size; - symsect.cts_data = contents; - symsect.cts_offset = symhdr->sh_offset; - symsectp = &symsect; } + else + strtab = (const char *) strhdr->contents; + } + + if (strtab) + { + /* The names here are more or less arbitrary, but there is no point + thrashing around digging the name out of the shstrtab given that we don't + use it for anything but debugging. */ + + strsect.cts_data = strtab; + strsect.cts_name = ".strtab"; + strsect.cts_size = strhdr->sh_size; + strsectp = &strsect; + + assert (symhdr->sh_entsize == get_elf_backend_data (abfd)->s->sizeof_sym); + symsect.cts_name = ".symtab"; + symsect.cts_entsize = symhdr->sh_entsize; + symsect.cts_size = symhdr->sh_size; + symsect.cts_data = symtab; + symsectp = &symsect; } #endif @@ -188,7 +198,7 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_, is_archive = 1; if ((arc = ctf_arc_bufopen ((void *) ctfsect->cts_data, ctfsect->cts_size, errp)) == NULL) - goto err_free_sym; + goto err_free_str; } else { @@ -197,7 +207,7 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_, { ctf_dprintf ("ctf_internal_open(): cannot open CTF: %s\n", ctf_errmsg (*errp)); - goto err_free_sym; + goto err_free_str; } } arci = ctf_new_archive_internal (is_archive, arc, fp, symsectp, strsectp, @@ -205,11 +215,10 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_, if (arci) return arci; - err_free_sym: + err_free_str: ; #ifdef HAVE_BFD_ELF - free ((void *) symsect.cts_data); -err_free_str: - free ((void *) strsect.cts_data); + err_free_sym: + free (symtab); #endif err: _libctf_unused_; if (bfderrstr) @@ -250,24 +259,27 @@ ctf_fdopen (int fd, const char *filename, const char *target, int *errp) if ((nbytes = ctf_pread (fd, &ctfhdr, sizeof (ctfhdr), 0)) <= 0) return (ctf_set_open_errno (errp, nbytes < 0 ? errno : ECTF_FMT)); - /* If we have read enough bytes to form a CTF header and the magic - string matches, attempt to interpret the file as raw CTF. */ + /* If we have read enough bytes to form a CTF header and the magic string + matches, in either endianness, attempt to interpret the file as raw + CTF. */ - if ((size_t) nbytes >= sizeof (ctf_preamble_t) && - ctfhdr.ctp_magic == CTF_MAGIC) + if ((size_t) nbytes >= sizeof (ctf_preamble_t) + && (ctfhdr.ctp_magic == CTF_MAGIC + || ctfhdr.ctp_magic == bswap_16 (CTF_MAGIC))) { ctf_file_t *fp = NULL; void *data; - if (ctfhdr.ctp_version > CTF_VERSION) - return (ctf_set_open_errno (errp, ECTF_CTFVERS)); - if ((data = ctf_mmap (st.st_size, 0, fd)) == NULL) return (ctf_set_open_errno (errp, errno)); if ((fp = ctf_simple_open (data, (size_t) st.st_size, NULL, 0, 0, NULL, 0, errp)) == NULL) - ctf_munmap (data, (size_t) st.st_size); + { + ctf_munmap (data, (size_t) st.st_size); + return NULL; /* errno is set for us. */ + } + fp->ctf_data_mmapped = data; fp->ctf_data_mmapped_len = (size_t) st.st_size; @@ -277,7 +289,7 @@ ctf_fdopen (int fd, const char *filename, const char *target, int *errp) if ((nbytes = ctf_pread (fd, &arc_magic, sizeof (arc_magic), 0)) <= 0) return (ctf_set_open_errno (errp, nbytes < 0 ? errno : ECTF_FMT)); - if ((size_t) nbytes >= sizeof (uint64_t) && arc_magic == CTFA_MAGIC) + if ((size_t) nbytes >= sizeof (uint64_t) && le64toh (arc_magic) == CTFA_MAGIC) { struct ctf_archive *arc; @@ -300,6 +312,7 @@ ctf_fdopen (int fd, const char *filename, const char *target, int *errp) bfd_errmsg (bfd_get_error())); return (ctf_set_open_errno (errp, ECTF_FMT)); } + bfd_set_cacheable (abfd, 1); if (!bfd_check_format (abfd, bfd_object)) {