Files @ e0ea6762c78c
Branch filter:

Location: libtransport.git/include/boost/dll/detail/elf_info.hpp - annotation

Jan Kaluza
Rename SlackInstallation to SlackSession. Allow SlackUser to move SlackSession from SlackUserManager once the SlackUser is created.
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
15e16d709e79
// Copyright 2014 Renato Tegon Forti, Antony Polukhin.
// Copyright 2015 Antony Polukhin.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_DLL_DETAIL_POSIX_ELF_INFO_HPP
#define BOOST_DLL_DETAIL_POSIX_ELF_INFO_HPP

#include <boost/config.hpp>

#ifdef BOOST_HAS_PRAGMA_ONCE
# pragma once
#endif

#include <cstring>
#include <boost/filesystem/fstream.hpp>
#include <boost/dll/detail/x_info_interface.hpp>

namespace boost { namespace dll { namespace detail {

template <class AddressOffsetT>
struct Elf_Ehdr_template {
  unsigned char     e_ident[16];    /* Magic number and other info */
  boost::uint16_t   e_type;         /* Object file type */
  boost::uint16_t   e_machine;      /* Architecture */
  boost::uint32_t   e_version;      /* Object file version */
  AddressOffsetT    e_entry;        /* Entry point virtual address */
  AddressOffsetT    e_phoff;        /* Program header table file offset */
  AddressOffsetT    e_shoff;        /* Section header table file offset */
  boost::uint32_t   e_flags;        /* Processor-specific flags */
  boost::uint16_t   e_ehsize;       /* ELF header size in bytes */
  boost::uint16_t   e_phentsize;    /* Program header table entry size */
  boost::uint16_t   e_phnum;        /* Program header table entry count */
  boost::uint16_t   e_shentsize;    /* Section header table entry size */
  boost::uint16_t   e_shnum;        /* Section header table entry count */
  boost::uint16_t   e_shstrndx;     /* Section header string table index */
};

typedef Elf_Ehdr_template<boost::uint32_t> Elf32_Ehdr_;
typedef Elf_Ehdr_template<boost::uint64_t> Elf64_Ehdr_;

template <class AddressOffsetT>
struct Elf_Shdr_template {
  boost::uint32_t   sh_name;        /* Section name (string tbl index) */
  boost::uint32_t   sh_type;        /* Section type */
  AddressOffsetT    sh_flags;       /* Section flags */
  AddressOffsetT    sh_addr;        /* Section virtual addr at execution */
  AddressOffsetT    sh_offset;      /* Section file offset */
  AddressOffsetT    sh_size;        /* Section size in bytes */
  boost::uint32_t   sh_link;        /* Link to another section */
  boost::uint32_t   sh_info;        /* Additional section information */
  AddressOffsetT    sh_addralign;   /* Section alignment */
  AddressOffsetT    sh_entsize;     /* Entry size if section holds table */
};

typedef Elf_Shdr_template<boost::uint32_t> Elf32_Shdr_;
typedef Elf_Shdr_template<boost::uint64_t> Elf64_Shdr_;

template <class AddressOffsetT>
struct Elf_Sym_template;

template <>
struct Elf_Sym_template<boost::uint32_t> {
  typedef boost::uint32_t AddressOffsetT;

  boost::uint32_t   st_name;    /* Symbol name (string tbl index) */
  AddressOffsetT    st_value;   /* Symbol value */
  AddressOffsetT    st_size;    /* Symbol size */
  unsigned char     st_info;    /* Symbol type and binding */
  unsigned char     st_other;   /* Symbol visibility */
  boost::uint16_t   st_shndx;   /* Section index */
};

template <>
struct Elf_Sym_template<boost::uint64_t> {
  typedef boost::uint64_t AddressOffsetT;

  boost::uint32_t   st_name;    /* Symbol name (string tbl index) */
  unsigned char     st_info;    /* Symbol type and binding */
  unsigned char     st_other;   /* Symbol visibility */
  boost::uint16_t   st_shndx;   /* Section index */
  AddressOffsetT    st_value;   /* Symbol value */
  AddressOffsetT    st_size;    /* Symbol size */
};


typedef Elf_Sym_template<boost::uint32_t> Elf32_Sym_;
typedef Elf_Sym_template<boost::uint64_t> Elf64_Sym_;

template <class AddressOffsetT>
class elf_info: public x_info_interface {
    boost::filesystem::ifstream& f_;

    typedef boost::dll::detail::Elf_Ehdr_template<AddressOffsetT>  header_t;
    typedef boost::dll::detail::Elf_Shdr_template<AddressOffsetT>  section_t;
    typedef boost::dll::detail::Elf_Sym_template<AddressOffsetT>   symbol_t;

    BOOST_STATIC_CONSTANT(boost::uint32_t, SHT_SYMTAB_ = 2);
    BOOST_STATIC_CONSTANT(boost::uint32_t, SHT_STRTAB_ = 3);

    BOOST_STATIC_CONSTANT(unsigned char, STB_LOCAL_ = 0);   /* Local symbol */
    BOOST_STATIC_CONSTANT(unsigned char, STB_GLOBAL_ = 1);  /* Global symbol */
    BOOST_STATIC_CONSTANT(unsigned char, STB_WEAK_ = 2);    /* Weak symbol */

    /* Symbol visibility specification encoded in the st_other field.  */
    BOOST_STATIC_CONSTANT(unsigned char, STV_DEFAULT_ = 0);      /* Default symbol visibility rules */
    BOOST_STATIC_CONSTANT(unsigned char, STV_INTERNAL_ = 1);     /* Processor specific hidden class */
    BOOST_STATIC_CONSTANT(unsigned char, STV_HIDDEN_ = 2);       /* Sym unavailable in other modules */
    BOOST_STATIC_CONSTANT(unsigned char, STV_PROTECTED_ = 3);    /* Not preemptible, not exported */

public:
    static bool parsing_supported(boost::filesystem::ifstream& f) {
        const unsigned char magic_bytes[5] = { 
            0x7f, 'E', 'L', 'F', sizeof(boost::uint32_t) == sizeof(AddressOffsetT) ? 1 : 2
        };

        unsigned char ch;
        f.seekg(0);
        for (std::size_t i = 0; i < sizeof(magic_bytes); ++i) {
            f >> ch;
            if (ch != magic_bytes[i]) {
                return false;
            }
        }

        return true;
    }

    explicit elf_info(boost::filesystem::ifstream& f) BOOST_NOEXCEPT
        : f_(f)
    {}

    std::vector<std::string> sections() {
        std::vector<std::string> ret;
        std::vector<char> names;
        sections_names_raw(names);
        
        const char* name_begin = &names[0];
        const char* const name_end = name_begin + names.size();
        ret.reserve(header().e_shnum);
        do {
            ret.push_back(name_begin);
            name_begin += ret.back().size() + 1;
        } while (name_begin != name_end);

        return ret;
    }

private:
    template <class T>
    inline void read_raw(T& value, std::size_t size = sizeof(T)) const {
        f_.read(reinterpret_cast<char*>(&value), size);
    }

    inline header_t header() {
        header_t elf;

        f_.seekg(0);
        read_raw(elf);

        return elf;
    }

    void sections_names_raw(std::vector<char>& sections) {
        const header_t elf = header();

        section_t section_names_section;
        f_.seekg(elf.e_shoff + elf.e_shstrndx * sizeof(section_t));
        read_raw(section_names_section);

        sections.resize(static_cast<std::size_t>(section_names_section.sh_size));
        f_.seekg(section_names_section.sh_offset);
        read_raw(sections[0], static_cast<std::size_t>(section_names_section.sh_size));
    }

    void symbols_text(std::vector<symbol_t>& symbols, std::vector<char>& text) {
        const header_t elf = header();
        f_.seekg(elf.e_shoff);

        for (std::size_t i = 0; i < elf.e_shnum; ++i) {
            section_t section;
            read_raw(section);

            if (section.sh_type == SHT_SYMTAB_) {
                symbols.resize(static_cast<std::size_t>(section.sh_size / sizeof(symbol_t)));

                const boost::filesystem::ifstream::pos_type pos = f_.tellg();
                f_.seekg(section.sh_offset);
                read_raw(symbols[0], static_cast<std::size_t>(section.sh_size - (section.sh_size % sizeof(symbol_t))) );
                f_.seekg(pos);
            } else if (section.sh_type == SHT_STRTAB_) {
                text.resize(static_cast<std::size_t>(section.sh_size));

                const boost::filesystem::ifstream::pos_type pos = f_.tellg();
                f_.seekg(section.sh_offset);
                read_raw(text[0], static_cast<std::size_t>(section.sh_size));
                f_.seekg(pos);
            }
        }
    }

    static bool is_visible(const symbol_t& sym) BOOST_NOEXCEPT {
        // `(sym.st_info >> 4) != STB_LOCAL_ && !!sym.st_size` check also workarounds the
        // GCC's issue https://sourceware.org/bugzilla/show_bug.cgi?id=13621
        return (sym.st_other & 0x03) == STV_DEFAULT_ && (sym.st_info >> 4) != STB_LOCAL_ && !!sym.st_size;
    }

public:
    std::vector<std::string> symbols() {
        std::vector<std::string> ret;

        std::vector<symbol_t> symbols;
        std::vector<char>   text;
        symbols_text(symbols, text);

        ret.reserve(symbols.size());
        for (std::size_t i = 0; i < symbols.size(); ++i) {
            if (is_visible(symbols[i])) {
                ret.push_back(&text[0] + symbols[i].st_name);
                if (ret.back().empty()) {
                    ret.pop_back(); // Do not show empty names
                }
            }
        }

        return ret;
    }

    std::vector<std::string> symbols(const char* section_name) {
        std::vector<std::string> ret;
        
        std::size_t index = 0;
        std::size_t ptrs_in_section_count = 0;
        {
            std::vector<char> names;
            sections_names_raw(names);

            const header_t elf = header();

            for (; index < elf.e_shnum; ++index) {
                section_t section;
                f_.seekg(elf.e_shoff + index * sizeof(section_t));
                read_raw(section);
            
                if (!std::strcmp(&names[0] + section.sh_name, section_name)) {
                    if (!section.sh_entsize) {
                        section.sh_entsize = 1;
                    }
                    ptrs_in_section_count = static_cast<std::size_t>(section.sh_size / section.sh_entsize);
                    break;
                }
            }                        
        }

        std::vector<symbol_t> symbols;
        std::vector<char>   text;
        symbols_text(symbols, text);
    
        if (ptrs_in_section_count < symbols.size()) {
            ret.reserve(ptrs_in_section_count);
        } else {
            ret.reserve(symbols.size());
        }

        for (std::size_t i = 0; i < symbols.size(); ++i) {
            if (symbols[i].st_shndx == index && is_visible(symbols[i])) {
                ret.push_back(&text[0] + symbols[i].st_name);
                if (ret.back().empty()) {
                    ret.pop_back(); // Do not show empty names
                }
            }
        }

        return ret;
    }
};

typedef elf_info<boost::uint32_t> elf_info32;
typedef elf_info<boost::uint64_t> elf_info64;

}}} // namespace boost::dll::detail

#endif // BOOST_DLL_DETAIL_POSIX_ELF_INFO_HPP