diff options
Diffstat (limited to 'libctf/ctf-open-bfd.c')
-rw-r--r-- | libctf/ctf-open-bfd.c | 98 |
1 files changed, 56 insertions, 42 deletions
diff --git a/libctf/ctf-open-bfd.c b/libctf/ctf-open-bfd.c index 6a0c155..6fbbde8 100644 --- a/libctf/ctf-open-bfd.c +++ b/libctf/ctf-open-bfd.c @@ -19,6 +19,7 @@ #include <ctf-impl.h> #include <stddef.h> +#include <assert.h> #include <sys/types.h> #include <sys/stat.h> #include <errno.h> @@ -32,8 +33,9 @@ #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, @@ -130,50 +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)) - { - bfderrstr = "Cannot malloc string table"; - free (contents); - goto err; - } - strsect.cts_data = contents; - strsect.cts_name = (char *) strsect.cts_data + strhdr->sh_name; - strsect.cts_size = bfd_section_size (str_asect); - strsect.cts_entsize = strhdr->sh_size; - strsectp = &strsect; - - if (!bfd_malloc_and_get_section (abfd, sym_asect, &contents)) + if ((strtab = bfd_elf_get_str_section (abfd, symhdr->sh_link)) == NULL) { - bfderrstr = "Cannot malloc symbol table"; - free (contents); - goto err_free_str; + bfderrstr = "Cannot read string table"; + goto err_free_sym; } - - symsect.cts_name = (char *) strsect.cts_data + symhdr->sh_name; - symsect.cts_entsize = symhdr->sh_size; - symsect.cts_size = bfd_section_size (sym_asect); - symsect.cts_data = contents; - 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 @@ -183,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 { @@ -192,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, @@ -200,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) |