diff --git a/src/core/util/CMakeLists.txt b/src/core/util/CMakeLists.txt index 92de758d..5e93916a 100644 --- a/src/core/util/CMakeLists.txt +++ b/src/core/util/CMakeLists.txt @@ -1,6 +1,8 @@ set(SRCS ElfReader.cc ElfReader.hpp + Demangler.hpp + Demangler.cc elfinfo/elfinfo.cc elfinfo/elfinfo.h gzstream/gzstream.C @@ -28,5 +30,8 @@ find_package(Boost 1.42 COMPONENTS thread REQUIRED) include_directories(${Boost_INCLUDE_DIRS}) link_directories(${Boost_LIBRARY_DIRS}) +# libiberty required by Demangler.cc: +find_library(LIB_IBERTY iberty) + add_library(fail-util ${SRCS}) -target_link_libraries(fail-util ${PROTOBUF_LIBRARY} ${Boost_THREAD_LIBRARY}) +target_link_libraries(fail-util ${PROTOBUF_LIBRARY} ${Boost_THREAD_LIBRARY} ${LIB_IBERTY}) diff --git a/src/core/util/Demangler.cc b/src/core/util/Demangler.cc new file mode 100644 index 00000000..e469d4d5 --- /dev/null +++ b/src/core/util/Demangler.cc @@ -0,0 +1,20 @@ +#include "Demangler.hpp" + +#define HAVE_DECL_BASENAME 1 +#include +#include + +namespace fail { + + const std::string Demangler::DEMANGLE_FAILED = "[Demangler] Demangle failed."; + + std::string Demangler::demangle(const std::string& name){ + const char* res = cplus_demangle(name.c_str(), 0); + if(res != NULL){ + return std::string(res); + }else{ + return DEMANGLE_FAILED; + } + } + +} // end of namespace diff --git a/src/core/util/Demangler.hpp b/src/core/util/Demangler.hpp new file mode 100644 index 00000000..e5644df8 --- /dev/null +++ b/src/core/util/Demangler.hpp @@ -0,0 +1,24 @@ +#ifndef __DEMANGLER_HPP +#define __DEMANGLER_HPP + +#include + +namespace fail { + + class Demangler { + public: + + /** + * Get the demangled symbol name of a mangled string. + * @param name The mangled symbol + * @return The according demangled name if found, else Demangler:::DEMANGLE_FAILED + */ + static std::string demangle(const std::string & name); + + //! Inform about failed demangling. + static const std::string DEMANGLE_FAILED; + }; + +} // end of namespace + +#endif // DEMANGLER_HPP diff --git a/src/core/util/ElfReader.cc b/src/core/util/ElfReader.cc index 8a7b8fa8..b18ce290 100644 --- a/src/core/util/ElfReader.cc +++ b/src/core/util/ElfReader.cc @@ -4,8 +4,12 @@ #include #include +#include "Demangler.hpp" + namespace fail { +const std::string ElfReader::NOTFOUND = "[ELFReader] Function not found."; + ElfReader::ElfReader(const char* path) : m_log("Fail*Elfinfo", false){ // Try to open the ELF file FILE * fp = fopen(path, "r"); @@ -31,7 +35,7 @@ namespace fail { } else { - if((sec_hdr.sh_type==SHT_SYMTAB)||(sec_hdr.sh_type==SHT_DYNSYM)) + if((sec_hdr.sh_type==SHT_SYMTAB)||(sec_hdr.sh_type==SHT_DYNSYM)) { process_symboltable(i,fp); @@ -80,7 +84,6 @@ namespace fail { //so we have the namebuf now seek to symtab data fseek(fp,sym_data_offset,SEEK_SET); - //m_log << "[section " << sect_num << "] contains " << num_sym << " symbols." << std::endl; for(i=0;isecond; +#ifndef __puma + guest_address_t ElfReader::getAddress(const bimap_t& map, const std::string& name){ + typedef bimap_t::left_map::const_iterator const_iterator_t; + + const_iterator_t iterator = map.left.find(name); + if(iterator == map.left.end()){ + return ADDR_INV; + }else{ + return iterator->second; + } } #endif + +#ifndef __puma + std::string ElfReader::getName(const bimap_t& map, guest_address_t address){ + // .right switches key/value + typedef bimap_t::right_map::const_iterator const_iterator_t; + + const_iterator_t iterator = map.right.find(address); + if(iterator != map.right.end()){ + return iterator->second; + } + return NOTFOUND; } std::string ElfReader::getNameByAddress(guest_address_t address) { -#ifndef __puma - // .right switches key/value - typedef bimap_t::right_map::const_iterator const_iterator_t; + std::string res = getName(m_bimap_demangled, address); + if(res == NOTFOUND){ + return getName(m_bimap_mangled, address); + } + return res; + } - const_iterator_t iterator = m_bimap.right.find(address); - if(iterator == m_bimap.right.end()){ - return "[ElfReader] FUNCTION NOT FOUND"; - }else{ - return iterator->second; + std::string ElfReader::getMangledNameByAddress(guest_address_t address) { + return getName(m_bimap_mangled, address); + } + + std::string ElfReader::getDemangledNameByAddress(guest_address_t address) { + return getName(m_bimap_demangled, address); + } + + void ElfReader::printDemangled(){ + print_map(m_bimap_demangled.right); // print Address as first element + } + + void ElfReader::printMangled(){ + print_map(m_bimap_mangled.right); // print Address as first element } #endif - } + } // end-of-namespace fail diff --git a/src/core/util/ElfReader.hpp b/src/core/util/ElfReader.hpp index 0c9e9374..7846be0d 100644 --- a/src/core/util/ElfReader.hpp +++ b/src/core/util/ElfReader.hpp @@ -2,24 +2,14 @@ #define __ELFREADER_HPP__ #include + #ifndef __puma #include #endif -#include "sal/SALConfig.hpp" +#include "sal/SALConfig.hpp" // for ADDR_INV #include "Logger.hpp" -template< class MapType > -void print_map(const MapType & map) -{ - typedef typename MapType::const_iterator const_iterator; - - for( const_iterator i = map.begin(), iend = map.end(); i != iend; ++i ) - { - std::cout << i->first << " -- " << i->second << std::endl; - } -} - namespace fail { /** @@ -39,34 +29,76 @@ namespace fail { ElfReader(const char* path); /** - * Get guest address by symbol name + * Get guest address by symbol name. + * Both mangled an demangled symbols are searched. * @param name The symbol name as string - * @return The according addres if found, else -1 + * @return The according address if found, else ADDR_INV */ guest_address_t getAddressByName(const std::string& name) ; - /** - * Get symbol name associated to an address + * Get demangled symbol name associated to an address * This is interesting when checking instruction pointers. * @param name The address of a symbol (or around a symbol -> instruction pointer) - * @return The according address if found, else -1 - * - * \todo multimap sorted by addresses - * Name is at first key <= address + * @return The according address if found, else ElfReader::NOTFOUND */ std::string getNameByAddress(guest_address_t address) ; + /** + * Get the mangled symbol name associated to an address + + * @param name The address of a symbol (or around a symbol -> instruction pointer) + * @return The according address if found, else ElfReader::NOTFOUND + */ + std::string getMangledNameByAddress(guest_address_t address) ; + + /** + * Get the demangled symbol name associated to an address + * Note the the demangled name is simplified, not showing any types! + * @param name The address of a symbol (or around a symbol -> instruction pointer) + * @return The according address if found, else ElfReader::NOTFOUND + */ + std::string getDemangledNameByAddress(guest_address_t address) ; + + /** + * Print the list of available mangled symbols + * @note This includes both C and C++ symbols + */ + void printMangled(); + + /** + * Print the list of all available demangled symbols + * @note These are only C++ symbols. + */ + void printDemangled(); + + //! Default string, if symbol is not found + static const std::string NOTFOUND; private: Logger m_log; + + int process_symboltable(int sect_num, FILE* fp); #ifndef __puma typedef boost::bimap< std::string, guest_address_t > bimap_t; typedef bimap_t::value_type entry; - bimap_t m_bimap; + + bimap_t m_bimap_mangled; + bimap_t m_bimap_demangled; + + template < typename MapType > + void print_map(const MapType & m){ + typedef typename MapType::const_iterator const_iterator; + for( const_iterator iter = m.begin(), iend = m.end(); iter != iend; ++iter ) + { + m_log << std::hex << iter->first << " - "<< std::hex << iter->second << std::endl; + } + } + + guest_address_t getAddress(const bimap_t& map, const std::string& name); + std::string getName(const bimap_t& map, guest_address_t address); #endif - int process_symboltable(int sect_num, FILE* fp); }; } // end-of-namespace fail diff --git a/src/experiments/vezs-example/experiment.cc b/src/experiments/vezs-example/experiment.cc index 0d6bf07e..5f058c6c 100644 --- a/src/experiments/vezs-example/experiment.cc +++ b/src/experiments/vezs-example/experiment.cc @@ -34,6 +34,8 @@ bool VEZSExperiment::run() ElfReader elf("./x86_bare_test"); log << "STARTING EXPERIMENT" << endl; log << "main() address: " << elf.getAddressByName("main") << endl; + elf.printMangled(); + elf.printDemangled(); BPSingleListener bp; #if 0 @@ -57,23 +59,22 @@ bool VEZSExperiment::run() simulator.restore("vezs.state"); log << " current EIP = " << simulator.getCPU(0).getInstructionPointer() << endl; - log << " Task0 start: " << elf.getAddressByName("_ZN5Alpha17functionTaskTask0Ev") << endl; BPSingleListener bpt0; BPSingleListener bpt1; - bpt0.setWatchInstructionPointer(elf.getAddressByName("_ZN5Alpha17functionTaskTask0Ev")); - bpt1.setWatchInstructionPointer(elf.getAddressByName("_ZN4Beta17functionTaskTask1Ev")); + bpt0.setWatchInstructionPointer(elf.getAddressByName("Alpha::functionTaskTask0")); + bpt1.setWatchInstructionPointer(elf.getAddressByName("_ZN4Beta17functionTaskTask1Ev")); // both mangled and demangled name a working. simulator.addListener(&bpt1); simulator.addListenerAndResume(&bpt0); - log << "EIP = " << simulator.getCPU(0).getInstructionPointer() <<" "<