deps/libdwarf+src/dwarfparser: remove, not needed anymore.

This commit is contained in:
Matula Peter 2020-01-17 22:30:47 +01:00
parent def84a63ae
commit 65b8503f33
32 changed files with 18 additions and 8615 deletions

File diff suppressed because it is too large Load Diff

View File

@ -242,7 +242,7 @@ You can pass the following additional parameters to `cmake`:
* `-DRETDEC_COMPILE_YARA=OFF` to disable YARA rules compilation at installation step (enabled by default).
* `-DCMAKE_BUILD_TYPE=Debug` to build with debugging information, which is useful during development. By default, the project is built in the `Release` mode. This has no effect on Windows, but the same thing can be achieved by running `cmake --build .` with the `--config Debug` parameter.
* `-DCMAKE_PROGRAM_PATH=<path>` to use Perl at `<path>` (probably useful only on Windows).
* `-D<dep>_LOCAL_DIR=<path>` where `<dep>` is from `{CAPSTONE, GOOGLETEST, KEYSTONE, LIBDWARF, LLVM, YARA, YARAMOD}` (e.g. `-DCAPSTONE_LOCAL_DIR=<path>`), to use the local repository clone at `<path>` for RetDec dependency instead of downloading a fresh copy at build time. Multiple such options may be used at the same time.
* `-D<dep>_LOCAL_DIR=<path>` where `<dep>` is from `{CAPSTONE, GOOGLETEST, KEYSTONE, LLVM, YARA, YARAMOD}` (e.g. `-DCAPSTONE_LOCAL_DIR=<path>`), to use the local repository clone at `<path>` for RetDec dependency instead of downloading a fresh copy at build time. Multiple such options may be used at the same time.
* `-DRETDEC_ENABLE_<component>=ON` to build only the specified component(s) (multiple such options can be used at once), and its (theirs) dependencies. By default, all the components are built. If at least one component is enabled via this mechanism, all the other components that were not explicitly enabled (and are not needed as dependencies of enabled components) are not built. See [cmake/options.cmake](https://github.com/avast/retdec/blob/master/cmake/options.cmake) for all the available component options.
* `-DRETDEC_ENABLE_ALL=ON` can be used to (re-)enable all the components.
* Alternatively, `-DRETDEC_ENABLE=<comma-separated component list>` can be used instead of `-DRETDEC_ENABLE_<component>=ON` (e.g. `-DRETDEC_ENABLE=fileformat,loader,ctypesparser` is equivalent to `-DRETDEC_ENABLE_FILEFORMAT=ON -DRETDEC_ENABLE_LOADER=ON -DRETDEC_ENABLE_CTYPESPARSER=ON`).
@ -301,7 +301,6 @@ This repository contains the following libraries:
* `ctypes` - C++ library for representing C function data types.
* `debugformat` - library for uniform representation of DWARF and PDB debugging information.
* `demangler` - demangling library capable to handle names generated by the GCC/Clang, Microsoft Visual C++, and Borland C++ compilers.
* `dwarfparser` - library for high-level representation of DWARF debugging information.
* `fileformat` - library for parsing and uniform representation of various object file formats. Currently supporting the following formats: COFF, ELF, Intel HEX, Mach-O, PE, raw data.
* `llvm-support` - set of LLVM related utility functions.
* `llvmir-emul` - LLVM IR emulation library used for unit testing.

View File

@ -26,7 +26,6 @@ option(RETDEC_ENABLE_CTYPESPARSER "" OFF)
option(RETDEC_ENABLE_DEBUGFORMAT "" OFF)
option(RETDEC_ENABLE_DEMANGLER "" OFF)
option(RETDEC_ENABLE_DEMANGLERTOOL "" OFF)
option(RETDEC_ENABLE_DWARFPARSER "" OFF)
option(RETDEC_ENABLE_FILEFORMAT "" OFF)
option(RETDEC_ENABLE_FILEINFO "" OFF)
option(RETDEC_ENABLE_GETSIG "" OFF)
@ -83,7 +82,6 @@ foreach(t ${RETDEC_ENABLE})
set_if_equal(${t} "debugformat" RETDEC_ENABLE_DEBUGFORMAT)
set_if_equal(${t} "demangler" RETDEC_ENABLE_DEMANGLER)
set_if_equal(${t} "demanglertool" RETDEC_ENABLE_DEMANGLERTOOL)
set_if_equal(${t} "dwarfparser" RETDEC_ENABLE_DWARFPARSER)
set_if_equal(${t} "fileformat" RETDEC_ENABLE_FILEFORMAT)
set_if_equal(${t} "fileinfo" RETDEC_ENABLE_FILEINFO)
set_if_equal(${t} "getsig" RETDEC_ENABLE_GETSIG)
@ -130,7 +128,6 @@ if (RETDEC_ENABLE_AR_EXTRACTOR
OR RETDEC_ENABLE_DEBUGFORMAT
OR RETDEC_ENABLE_DEMANGLER
OR RETDEC_ENABLE_DEMANGLERTOOL
OR RETDEC_ENABLE_DWARFPARSER
OR RETDEC_ENABLE_FILEFORMAT
OR RETDEC_ENABLE_FILEINFO
OR RETDEC_ENABLE_GETSIG
@ -319,10 +316,6 @@ set_if_at_least_one_set(RETDEC_ENABLE_CTYPES
RETDEC_ENABLE_ALL
RETDEC_ENABLE_CTYPESPARSER)
set_if_at_least_one_set(RETDEC_ENABLE_DWARFPARSER
RETDEC_ENABLE_ALL
RETDEC_ENABLE_DEBUGFORMAT)
set_if_at_least_one_set(RETDEC_ENABLE_PDBPARSER
RETDEC_ENABLE_CPDETECT
RETDEC_ENABLE_DEBUGFORMAT)
@ -341,7 +334,6 @@ set_if_at_least_one_set(RETDEC_ENABLE_FILEFORMAT
RETDEC_ENABLE_ALL
RETDEC_ENABLE_BIN2LLVMIR
RETDEC_ENABLE_CPDETECT
RETDEC_ENABLE_DWARFPARSER
RETDEC_ENABLE_FILEINFO
RETDEC_ENABLE_GETSIG
RETDEC_ENABLE_LOADER
@ -397,7 +389,6 @@ set_if_at_least_one_set(RETDEC_ENABLE_UTILS
RETDEC_ENABLE_CRYPTO
RETDEC_ENABLE_CTYPES
RETDEC_ENABLE_CTYPESPARSER
RETDEC_ENABLE_DWARFPARSER
RETDEC_ENABLE_FILEFORMAT
RETDEC_ENABLE_FILEINFO
RETDEC_ENABLE_IDR2PAT
@ -494,10 +485,6 @@ set_if_at_least_one_set(RETDEC_ENABLE_KEYSTONE
RETDEC_ENABLE_CAPSTONE2LLVMIRTOOL
RETDEC_ENABLE_CAPSTONE2LLVMIR_TESTS)
set_if_at_least_one_set(RETDEC_ENABLE_LIBDWARF
RETDEC_ENABLE_CPDETECT
RETDEC_ENABLE_DWARFPARSER)
set_if_at_least_one_set(RETDEC_ENABLE_LLVM
RETDEC_ENABLE_AR_EXTRACTOR
RETDEC_ENABLE_BIN2LLVMIR
@ -507,7 +494,9 @@ set_if_at_least_one_set(RETDEC_ENABLE_LLVM
RETDEC_ENABLE_LLVM_SUPPORT
RETDEC_ENABLE_LLVMIR_EMUL
RETDEC_ENABLE_LLVMIR2HLL
RETDEC_ENABLE_MACHO_EXTRACTOR)
RETDEC_ENABLE_MACHO_EXTRACTOR
RETDEC_ENABLE_CPDETECT
RETDEC_ENABLE_DEBUGFORMAT)
set_if_at_least_one_set(RETDEC_ENABLE_OPENSLL
RETDEC_ENABLE_CRYPTO)

1
deps/CMakeLists.txt vendored
View File

@ -7,7 +7,6 @@ cond_add_subdirectory(capstone RETDEC_ENABLE_CAPSTONE)
cond_add_subdirectory(elfio RETDEC_ENABLE_ELFIO)
cond_add_subdirectory(googletest RETDEC_ENABLE_GOOGLETEST)
cond_add_subdirectory(keystone RETDEC_ENABLE_KEYSTONE)
cond_add_subdirectory(libdwarf RETDEC_ENABLE_LIBDWARF)
cond_add_subdirectory(llvm RETDEC_ENABLE_LLVM)
cond_add_subdirectory(openssl RETDEC_ENABLE_OPENSLL)
cond_add_subdirectory(rapidjson RETDEC_ENABLE_RAPIDJSON)

View File

@ -1,88 +0,0 @@
include(ExternalProject)
if(CMAKE_C_COMPILER)
set(CMAKE_C_COMPILER_OPTION "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}")
endif()
if(CMAKE_CXX_COMPILER)
set(CMAKE_CXX_COMPILER_OPTION "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}")
endif()
set(LIBDWARF_INSTALL_DIR "${PROJECT_BINARY_DIR}/external/src/libdwarf-project-install")
if(LIBDWARF_LOCAL_DIR)
message(STATUS "LibDwarf: using local LibDwarf directory.")
ExternalProject_Add(libdwarf-project
DOWNLOAD_COMMAND ""
SOURCE_DIR "${LIBDWARF_LOCAL_DIR}"
CMAKE_ARGS
# This does not work on MSVC, but may be useful on Linux.
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_INSTALL_PREFIX=${LIBDWARF_INSTALL_DIR}
# Force the use of the same compiler as used to build the top-level
# project. Otherwise, the external project may pick up a different
# compiler, which may result in link errors.
"${CMAKE_C_COMPILER_OPTION}"
"${CMAKE_CXX_COMPILER_OPTION}"
# Disable the update step.
UPDATE_COMMAND ""
)
force_configure_step(libdwarf-project)
else()
message(STATUS "LibDwarf: using remote LibDwarf revision.")
ExternalProject_Add(libdwarf-project
URL https://github.com/avast/libdwarf/archive/85465d5e235cc2d2f90d04016d6aca1a452d0e73.zip
URL_HASH SHA256=2864aa7b46529778476190e90359669eb35799ad273233c4df2203bec7db0738
DOWNLOAD_NAME libdwarf.zip
CMAKE_ARGS
# This does not work on MSVC, but may be useful on Linux.
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_INSTALL_PREFIX=${LIBDWARF_INSTALL_DIR}
# Force the use of the same compiler as used to build the top-level
# project. Otherwise, the external project may pick up a different
# compiler, which may result in link errors.
"${CMAKE_C_COMPILER_OPTION}"
"${CMAKE_CXX_COMPILER_OPTION}"
# Disable the update step.
UPDATE_COMMAND ""
LOG_DOWNLOAD ON
LOG_CONFIGURE ON
LOG_BUILD ON
)
endif()
check_if_variable_changed(LIBDWARF_LOCAL_DIR CHANGED)
if(CHANGED)
ExternalProject_Get_Property(libdwarf-project binary_dir)
message(STATUS "LibDwarf: path to LibDwarf directory changed -> cleaning CMake files in ${binary_dir}.")
clean_cmake_files(${binary_dir})
endif()
ExternalProject_Get_Property(libdwarf-project source_dir)
ExternalProject_Get_Property(libdwarf-project binary_dir)
# Add libraries.
add_library(libdwarf INTERFACE)
add_dependencies(libdwarf libdwarf-project)
target_include_directories(libdwarf SYSTEM INTERFACE ${source_dir}/libdwarf)
if(MSVC)
target_link_libraries(libdwarf INTERFACE ${binary_dir}/libdwarf/libdwarf/$<CONFIGURATION>/${CMAKE_STATIC_LIBRARY_PREFIX}retdec-libdwarf.lib)
target_link_libraries(libdwarf INTERFACE ${binary_dir}/libelf/lib/$<CONFIGURATION>/${CMAKE_STATIC_LIBRARY_PREFIX}retdec-libelf.lib)
elseif(MSYS)
target_link_libraries(libdwarf INTERFACE ${LIBDWARF_INSTALL_DIR}/bin/${CMAKE_STATIC_LIBRARY_PREFIX}retdec-libdwarf${CMAKE_SHARED_LIBRARY_SUFFIX})
target_link_libraries(libdwarf INTERFACE ${LIBDWARF_INSTALL_DIR}/bin/${CMAKE_STATIC_LIBRARY_PREFIX}retdec-libelf${CMAKE_SHARED_LIBRARY_SUFFIX})
else() # Linux
target_link_libraries(libdwarf INTERFACE ${LIBDWARF_INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}retdec-libdwarf${CMAKE_SHARED_LIBRARY_SUFFIX})
target_link_libraries(libdwarf INTERFACE ${LIBDWARF_INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}retdec-libelf${CMAKE_SHARED_LIBRARY_SUFFIX})
endif()
if(MSVC)
install(DIRECTORY "${LIBDWARF_INSTALL_DIR}/bin" DESTINATION "${CMAKE_INSTALL_PREFIX}")
elseif(MSYS)
install(DIRECTORY "${LIBDWARF_INSTALL_DIR}/bin" DESTINATION "${CMAKE_INSTALL_PREFIX}")
else() # Linux
install(DIRECTORY "${LIBDWARF_INSTALL_DIR}/lib" DESTINATION "${CMAKE_INSTALL_PREFIX}")
endif()

View File

@ -1,177 +0,0 @@
/**
* @file include/retdec/dwarfparser/dwarf_base.h
* @brief Declaration of base classes used in dwarfparser.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#ifndef RETDEC_DWARFPARSER_DWARF_BASE_H
#define RETDEC_DWARFPARSER_DWARF_BASE_H
#include <list>
#include <map>
#include <string>
#include <vector>
#include <libdwarf/dwarf.h>
#include <libdwarf/libdwarf.h>
namespace retdec {
namespace dwarfparser {
// Extern forward declarations.
class DwarfFile;
class DwarfCU;
// Locale forward declarations.
template <class T>
class DwarfBaseContainer;
class DwarfBaseElement;
/**
* @class DwarfBaseContainer.
* @brief Base container class for all container objects used by dwarfparser.
*/
template <class T>
class DwarfBaseContainer
{
//
// Type aliases
//
public:
using iterator = typename std::vector<T*>::iterator;
using const_iterator = typename std::vector<T*>::const_iterator;
//
// Non-virtual functions.
//
public:
DwarfBaseContainer(DwarfFile *file, DwarfBaseElement *elem = nullptr) :
m_res(0),
m_error(nullptr),
m_parentFile(file),
m_parentElem(elem)
{
}
std::size_t size() const { return m_data.size(); }
void push_back(T *n) { m_data.push_back(n); }
bool empty() const { return m_data.empty(); }
iterator begin() { return m_data.begin(); }
const_iterator begin() const { return m_data.begin(); }
iterator end() { return m_data.end(); }
const_iterator end() const { return m_data.end(); }
DwarfBaseElement *getParentElem() const { return m_parentElem; }
DwarfFile *getParentFile() const { return m_parentFile; }
// TODO: get element by DIE?
DwarfBaseElement *getElemByOffset(Dwarf_Off o);
//
// Virtual functions.
//
public:
virtual ~DwarfBaseContainer()
{
for (iterator it=begin(); it!=end(); ++it)
delete (*it);
m_data.clear();
}
virtual void dump() const
{
for (const_iterator cit=begin(); cit!=end(); ++cit)
(*cit)->dump();
}
//
// Pure virtual functions.
//
public:
virtual T* loadAndGetDie(Dwarf_Die die, unsigned lvl) = 0;
//
// Data.
//
protected:
std::vector<T*> m_data; ///< Object container.
int m_res; ///< Global return value.
Dwarf_Error m_error; ///< Global error code.
DwarfFile *m_parentFile; ///< Pointer to DWARF file representation.
DwarfBaseElement *m_parentElem; ///< Pointer to parent element, if nullptr then parent is DWARF file.
public:
/**
* DIE offset to element mapping.
* One element may have multiple offsets -- multiple mappings.
* ==> *DO NOT* iterate through this container, use 'm_data'.
*/
std::map<Dwarf_Off, T*> off2data;
};
/**
* @class DwarfBaseElement
* @brief Base element class for all objects used by dwarfparser.
*/
class DwarfBaseElement
{
public:
/**
* @brief Types element
*/
enum type_t
{
CU,
FUNCTION,
LINE,
TYPE,
VAR
};
DwarfBaseElement(type_t type, DwarfBaseContainer<DwarfBaseElement> *prnt, Dwarf_Off d);
virtual ~DwarfBaseElement() = default;
virtual void dump() const = 0;
public:
virtual const std::string& getName() const {return name;}
type_t getType() const {return m_type;}
DwarfBaseContainer<DwarfBaseElement> *getPrntCont() const {return m_parent;}
DwarfFile *getParentFile() const {return getPrntCont()->getParentFile();}
DwarfCU *getCuParent() const {return m_cuParent;}
Dwarf_Debug &getLibdwarfDebug() const;
void addOffset(Dwarf_Off o);
std::string getDwarfdump2OffsetString() const;
public:
std::string name;
protected:
type_t m_type;
DwarfBaseContainer<DwarfBaseElement> *m_parent; ///< Pointer to parent container that contains this element.
DwarfCU *m_cuParent; ///< Pointer to parent CU element that contains this element.
};
/**
* @brief Get container's element with provided offset.
* @param o Offset.
* @return Element with offset.
*/
template <class T>
DwarfBaseElement* DwarfBaseContainer<T>::getElemByOffset(Dwarf_Off o)
{
auto it = off2data.find(o);
if (it != off2data.end())
return it->second;
else
return nullptr;
}
} // namespace dwarfparser
} // namespace retdec
#endif

View File

@ -1,68 +0,0 @@
/**
* @file include/retdec/dwarfparser/dwarf_cu.h
* @brief Declaration of classes representing Compilation Units.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#ifndef RETDEC_DWARFPARSER_DWARF_CU_H
#define RETDEC_DWARFPARSER_DWARF_CU_H
#include <cstdlib>
#include <list>
#include "retdec/dwarfparser/dwarf_base.h"
namespace retdec {
namespace dwarfparser {
// Extern forward declarations.
class DwarfFile;
// Locale forward declarations.
class DwarfCU;
class DwarfCUContainer;
/**
* @class DwarfCU
* @brief Compilation unit object.
*/
class DwarfCU : public DwarfBaseElement
{
public:
DwarfCU(DwarfCUContainer *prnt, Dwarf_Off o);
virtual void dump() const override;
std::size_t srcFilesCount();
void addSrcFile(std::string f);
std::string *getSrcFile(unsigned idx);
int findSrcFile(std::string f, const std::string **ret);
bool IsLanguageC() const;
bool IsLanguageCpp() const;
public:
std::string compDir; ///< Name of compilation directory.
std::string producer; ///< Name of compiler used to create CU.
Dwarf_Addr lowAddr; ///< Lowest address of active range, base for loclists.
Dwarf_Addr highAddr; ///< Highest address of active range.
Dwarf_Unsigned language; ///< A code indicating the source language.
private:
std::list<std::string> m_srcFiles; ///< List of source file of this compilation unit.
};
/**
* @class DwarfCUContainer
* @brief Compilation unit container.
*/
class DwarfCUContainer : public DwarfBaseContainer<DwarfCU>
{
public:
DwarfCUContainer(DwarfFile *file, DwarfBaseElement *elem = nullptr);
virtual DwarfCU *loadAndGetDie(Dwarf_Die cuDie, unsigned lvl) override;
virtual void dump() const override;
};
} // namespace dwarfparser
} // namespace retdec
#endif

View File

@ -1,143 +0,0 @@
/**
* @file include/retdec/dwarfparser/dwarf_file.h
* @brief Declarations of DwarfFile class which provides high-level access
* to DWARF debugging informations.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
/*
* TODO:
* - Multiple CUs -> CUs should own other info that are inside them.
* At the moment each object contains pointer to its CU.
* It would be better designed if CU elements would contain all the different
* containers (lines, functions, types, ...).
* Problem is that there would be many containers for each element type, and
* it is much easier for user of this library to have all functions, types, etc.
* in single container -- methods getFunctions(), etc.
* Possible solution would be to create new container when get*() method is called,
* this container would contain all element from all CU containers of the type.
* But I'm not sure that this is the best solution.
* - add some method that enables printing debug info in all classes.
* - class holding and managing active context, accessible from other classes.
* - DW_AT_abstract_origin problem -- associate object with original DIE.
* - void data type - is it the best solution ???
*/
#ifndef RETDEC_DWARFPARSER_DWARF_FILE_H
#define RETDEC_DWARFPARSER_DWARF_FILE_H
#include <string>
#include <libdwarf/dwarf.h>
#include <libdwarf/libdwarf.h>
#include "retdec/fileformat-libdwarf-interface/bin_interface.h"
#include "retdec/dwarfparser/dwarf_cu.h"
#include "retdec/dwarfparser/dwarf_functions.h"
#include "retdec/dwarfparser/dwarf_linenumbers.h"
#include "retdec/dwarfparser/dwarf_locations.h"
#include "retdec/dwarfparser/dwarf_parserdefs.h"
#include "retdec/dwarfparser/dwarf_resources.h"
#include "retdec/dwarfparser/dwarf_types.h"
#include "retdec/dwarfparser/dwarf_utils.h"
#include "retdec/dwarfparser/dwarf_vars.h"
namespace retdec {
namespace dwarfparser {
// Extern forward declarations.
// Locale forward declarations.
class DwarfFile;
/**
* @class DwarfFile
* @brief Main class containing all DWARF information.
*/
class DwarfFile
{
//
// Public methods.
//
public:
DwarfFile(std::string fileName, retdec::fileformat::FileFormat *fileParser = nullptr);
~DwarfFile();
bool hasDwarfInfo();
//
// Functions getting particular DWARF records.
//
public:
DwarfCUContainer *getCUs();
DwarfLineContainer *getLines();
DwarfFunctionContainer *getFunctions();
DwarfTypeContainer *getTypes();
DwarfVarContainer *getGlobalVars();
Dwarf_Debug &getDwarfDebug();
//
// Private methods.
//
private:
bool loadFile(std::string fileName, retdec::fileformat::FileFormat *fileParser);
void loadFileCUs();
void loadCUtree(Dwarf_Die die, DwarfBaseElement* parent, int lvl);
void loadDIE(Dwarf_Die die, DwarfBaseElement* &parent, int lvl);
void makeStructTypesUnique();
//
// Containers storing high-level representation of DWARF data.
//
private:
DwarfCUContainer m_CUs; ///< Compilation units.
DwarfLineContainer m_lines; ///< Line numbers.
DwarfFunctionContainer m_functions; ///< Functions.
DwarfTypeContainer m_types; ///< Data types.
DwarfVarContainer m_globalVars; ///< Global variables.
//
// Some auxiliary variables.
//
private:
bool m_hasDwarf; ///< Loaded file contains some DWARF information.
int m_res; ///< Global return value.
Dwarf_Debug m_dbg; ///< Libdwarf structure representing DWARF file.
int m_fd; ///< File descriptor used in dwarf_init().
Dwarf_Error m_error; ///< Global libdwarf error code.
//
// Variables keep track of the context of DWARF tree.
//
private:
DwarfCU *m_activeCU;
//
// Resources.
//
public:
void initMapping(eDefaultMap m);
DwarfResources resources; ///< Class representing resources.
//
// These classes need to access DWARF context tree.
//
template <class T> friend class DwarfBaseContainer;
friend class DwarfCUContainer;
friend class DwarfLineContainer;
friend class DwarfFunctionContainer;
friend class DwarfVarContainer;
friend class DwarfTypeContainer;
friend class DwarfBaseElement;
friend class DwarfCU;
friend class DwarfArrayType;
friend class DwarfEnumType;
friend class DwarfStructType;
friend class DwarfLocationDesc;
friend class AttrProcessor;
};
} // namespace dwarfparser
} // namespace retdec
#endif

View File

@ -1,79 +0,0 @@
/**
* @file include/retdec/dwarfparser/dwarf_functions.h
* @brief Declaration of classes representing functions.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#ifndef RETDEC_DWARFPARSER_DWARF_FUNCTIONS_H
#define RETDEC_DWARFPARSER_DWARF_FUNCTIONS_H
#include <cstdlib>
#include "retdec/dwarfparser/dwarf_base.h"
#include "retdec/dwarfparser/dwarf_vars.h"
namespace retdec {
namespace dwarfparser {
// Extern forward declarations.
class DwarfFile;
// Locale forward declarations.
class DwarfFunction;
class DwarfFunctionContainer;
/**
* @class DwarfFunction
* @brief Function object.
*/
class DwarfFunction : public DwarfVar
{
public:
DwarfFunction(DwarfFunctionContainer *prnt, Dwarf_Off o, const std::string &n);
virtual ~DwarfFunction() override;
virtual void dump() const override;
bool hasVars() const;
bool hasParams() const;
DwarfVarContainer *getVars();
DwarfVarContainer *getParams();
std::size_t getParamCount() const;
bool hasFrameBase() const;
DwarfLocationDesc::cLocType getFrameBase(std::string *n, Dwarf_Addr *a, Dwarf_Addr pc = 0);
public:
std::string linkageName; ///< Mangled name, sometimes only this one is in DWARF, then use it as name as well.
Dwarf_Addr lowAddr; ///< Lowest address of active range.
Dwarf_Addr highAddr; ///< Highest address of active range.
Dwarf_Unsigned line; ///< Function declaration line number.
const std::string &file; ///< Source file name where function is declared.
DwarfLocationDesc *frameBase; ///< Frame base location descriptor.
bool isVariadic; ///< If true, function has variadic argument following arguments stored in m_params.
bool isDeclaration; ///<
bool isTemplateInstance;
bool isVariadicTemplateInstance;
bool isTemplateTemplateInstance;
private:
DwarfVarContainer m_vars; ///< Container with local variables of this function.
DwarfVarContainer m_params; ///< Container with parameters of this function.
};
/**
* @class DwarfFunctionContainer
* @brief Function container.
*/
class DwarfFunctionContainer : public DwarfBaseContainer<DwarfFunction>
{
public:
DwarfFunctionContainer(DwarfFile *file, DwarfBaseElement *elem = nullptr);
virtual void dump() const override;
virtual DwarfFunction *loadAndGetDie(Dwarf_Die die, unsigned lvl) override;
DwarfFunction *getFunctionByName(std::string n);
};
} // namespace dwarfparser
} // namespace retdec
#endif

View File

@ -1,88 +0,0 @@
/**
* @file include/retdec/dwarfparser/dwarf_linenumbers.h
* @brief Declaration of classes representing linenumbers.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#ifndef RETDEC_DWARFPARSER_DWARF_LINENUMBERS_H
#define RETDEC_DWARFPARSER_DWARF_LINENUMBERS_H
#include <cstdlib>
#include <list>
#include <vector>
#include "retdec/dwarfparser/dwarf_base.h"
namespace retdec {
namespace dwarfparser {
// Extern forward declarations.
class DwarfFile;
// Locale forward declarations.
class DwarfLine;
class DwarfLineContainer;
/**
* @class DwarfLine
* @brief Line number object.
*/
class DwarfLine : public DwarfBaseElement
{
public:
/**
* @brief Flags of line number.
*/
enum eFlags
{
EMPTY = 0, ///< Empty.
STAT_BEG = 1 << 1, ///< Line number entry marked as beginning a statment.
SEQ_END = 1 << 2, ///< Line number entry marked as ending a text sequence.
BASE_BLOCK_BEG = 1 << 3, ///< Line number entry marked as beginning a basic block.
PROLOGUE_END = 1 << 4, ///< Line number entry marked as end of prologue.
EPILOGUE_BEGIN = 1 << 5 ///< Line number entry marked as begin of epilogue.
};
public:
DwarfLine(DwarfLineContainer *prnt, const std::string &n);
virtual void dump() const override;
virtual const std::string& getName() const override {return name;}
bool isStatmentBeg() const;
bool isSequenceEnd() const;
bool isBasicBlockBeg() const;
public:
Dwarf_Unsigned lineNum; ///< Source statement line number.
Dwarf_Addr addr; ///< Address associated with line.
Dwarf_Unsigned col; ///< Column number at which statement represented by line begins.
int flags; ///< Line number record flags.
const std::string &name; ///< Name of source file where line occurs.
};
/**
* @class DwarfLineContainer
* @brief Line number container.
*/
class DwarfLineContainer : public DwarfBaseContainer<DwarfLine>
{
public:
DwarfLineContainer(DwarfFile *file, DwarfBaseElement *elem = nullptr);
virtual DwarfLine *loadAndGetDie(Dwarf_Die cu_die, unsigned lvl) override;
virtual void dump() const override;
std::vector<Dwarf_Addr> getAddrByLine(std::string file, Dwarf_Unsigned line);
DwarfLine *getLineByAddr(Dwarf_Addr addr);
private:
void loadLine(Dwarf_Line line);
std::string *findSrcFile(std::string f);
private:
std::list<std::string> m_srcFiles; ///< List of all source file names used in lines.
};
} // namespace dwarfparser
} // namespace retdec
#endif

View File

@ -1,115 +0,0 @@
/**
* @file include/retdec/dwarfparser/dwarf_locations.h
* @brief Declaration of classes representing locations.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#ifndef RETDEC_DWARFPARSER_DWARF_LOCATIONS_H
#define RETDEC_DWARFPARSER_DWARF_LOCATIONS_H
#include <cstdlib>
#include <vector>
#include "retdec/dwarfparser/dwarf_base.h"
#include "retdec/dwarfparser/dwarf_resources.h"
namespace retdec {
namespace dwarfparser {
// Extern forward declarations.
class DwarfFunction;
// Locale forward declarations.
class DwarfLocationDesc;
/**
* @class DwarfLocationDesc
* @brief Class represents location description used by DWARF.
*/
class DwarfLocationDesc
{
public:
/**
* @brief Type of location.
*/
enum eLocType
{
REGISTER = 0, ///< Register.
ADDRESS = 1 << 1, ///< Address.
VALUE = 1 << 2, ///< Actual value of the object.
FAIL = 1 << 3 ///< Invalid.
};
/**
* @class cLocType.
* @brief Class representing location type.
*/
class cLocType
{
public:
cLocType(eLocType tt);
bool isRegister();
bool isAddress();
bool isValue();
bool failed();
private:
eLocType t; ///< Location type.
};
/**
* @brief Basic unit of location description.
*/
struct Atom
{
Dwarf_Small opcode; ///< Operation code.
Dwarf_Unsigned op1; ///< Operand #1.
Dwarf_Unsigned op2; ///< Operand #2.
Dwarf_Unsigned off; ///< Offset in locexpr used in OP_BRA.
};
/**
* @brief DWARF expression.
*/
class Expression
{
public:
Dwarf_Addr lowAddr; ///< Lowest address of active range.
Dwarf_Addr highAddr; ///< Highest address of active range.
std::vector<Atom> atoms; ///< Vector of expression's atoms.
std::size_t count() const {return atoms.size();}
};
public:
DwarfLocationDesc();
cLocType computeLocation(std::string *n, Dwarf_Addr *a, Dwarf_Addr pc = 0,
Dwarf_Addr base = 0, bool hasBase = false);
void addExpr(Expression e);
void setBaseFunc(DwarfFunction *f);
DwarfLocationDesc *getBaseLoc();
void setParent(DwarfBaseElement *p);
DwarfCU *getCuParent();
std::string getParentName();
DwarfResources *getResources();
std::size_t count() const;
bool isEmpty();
bool isNormal() const;
bool isList();
bool isOnStack(Dwarf_Signed *off, bool *deref, Dwarf_Addr pc = 0, int *regNum=nullptr);
void dump();
private:
cLocType evaluateExpression(Expression &expr, std::string *retN, Dwarf_Addr *retA,
Dwarf_Addr pc = 0, Dwarf_Addr base = 0, bool hasBase = false);
private:
std::vector<Expression> m_exprs; ///< Vector of expressions of this location.
DwarfFunction *m_baseFunc; ///< Pointer to base function containing frame base location.
DwarfBaseElement *m_parent; ///< Pointer to object which owns this location.
};
} // namespace dwarfparser
} // namespace retdec
#endif

View File

@ -1,118 +0,0 @@
/**
* @file include/retdec/dwarfparser/dwarf_parserdefs.h
* @brief Definitions globally used in dwarfparser library.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#ifndef RETDEC_DWARFPARSER_DWARF_PARSERDEFS_H
#define RETDEC_DWARFPARSER_DWARF_PARSERDEFS_H
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <limits>
#include <libdwarf/dwarf.h>
#include <libdwarf/libdwarf.h>
#include "retdec/utils/os.h"
#ifdef OS_WINDOWS
#include <windows.h>
#endif
/**
* These constants represents empty values of used data types.
*/
const std::string EMPTY_STR = "";
const Dwarf_Unsigned EMPTY_UNSIGNED = std::numeric_limits<Dwarf_Unsigned>::max();
const Dwarf_Signed EMPTY_SIGNED = std::numeric_limits<Dwarf_Signed>::max();
const Dwarf_Addr EMPTY_ADDR = EMPTY_UNSIGNED;
const Dwarf_Off EMPTY_OFF = EMPTY_UNSIGNED;
/**
* TODO:
* this is used to determine source section of DWARF info in some new
* libdwarf functions
* at the moment '.debug_info' is always used
* implement possible use of '.debug_types' as in dwarfdump2
*/
const Dwarf_Bool is_info = true;
/**
*
*/
const unsigned short BITS_IN_BYTE = 8;
/**
* @brief Variants of default DWARF registers numbers mapping initialization.
*/
enum eDefaultMap
{
MIPS, ///<
ARM, ///<
X86 ///<
};
/*
* Debug msg printing.
*/
//#define DWARF_PARSER_RECOVERY_DEBUG
#undef DWARF_PARSER_RECOVERY_DEBUG
#ifndef OS_WINDOWS /* OS_WINDOWS */
const std::string DWARF_CYAN = "\33[22;36m";
const std::string DWARF_RED = "\33[22;31m";
const std::string DWARF_NOCOLOR = "\33[0m";
#ifdef DWARF_PARSER_RECOVERY_DEBUG /* DWARF_PARSER_RECOVERY_DEBUG */
#define DWARF_ERROR(X) \
std::cout << DWARF_RED << "Dwarfparserl Error: " << X << " -> (" << __FILE__ << ":" << std::dec << __LINE__ << ")" << DWARF_NOCOLOR << std::endl;
#define DWARF_WARNING(X) \
std::cout << DWARF_CYAN << "Dwarfparserl Warning: " << X << " -> (" << __FILE__ << ":" << std::dec << __LINE__ << ")" << DWARF_NOCOLOR << std::endl;
#endif /* DWARF_PARSER_RECOVERY_DEBUG */
#ifndef DWARF_PARSER_RECOVERY_DEBUG /* DWARF_PARSER_RECOVERY_DEBUG */
#define DWARF_ERROR(X) {}
#define DWARF_WARNING(X) {}
#endif /* DWARF_PARSER_RECOVERY_DEBUG */
#else /* OS_WINDOWS */
#ifdef DWARF_PARSER_RECOVERY_DEBUG /* DWARF_PARSER_RECOVERY_DEBUG */
#define DWARF_ERROR(X) \
{ \
int wOldColorAttrs; \
CONSOLE_SCREEN_BUFFER_INFO csbiInfo; \
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbiInfo); \
wOldColorAttrs = csbiInfo.wAttributes; \
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_DWARF_RED | FOREGROUND_INTENSITY); \
std::cout << "Dwarfparserl Error: " << X << " -> (" << __FILE__ << ":" << std::dec << __LINE__ << ")" << std::endl; \
SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), wOldColorAttrs);\
}
#define DWARF_WARNING(X) \
{ \
int wOldColorAttrs; \
CONSOLE_SCREEN_BUFFER_INFO csbiInfo; \
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbiInfo); \
wOldColorAttrs = csbiInfo.wAttributes; \
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE | FOREGROUND_INTENSITY); \
std::cout << "Dwarfparserl Warning: " << X << " -> (" << __FILE__ << ":" << std::dec << __LINE__ << ")" << std::endl; \
SetConsoleTextAttribute (GetStdHandle (STD_OUTPUT_HANDLE), wOldColorAttrs); \
}
#endif /* DWARF_PARSER_RECOVERY_DEBUG */
#ifndef DWARF_PARSER_RECOVERY_DEBUG /* DWARF_PARSER_RECOVERY_DEBUG */
#define DWARF_ERROR(X) {}
#define DWARF_WARNING(X) {}
#endif /* DWARF_PARSER_RECOVERY_DEBUG */
#endif /* OS_WINDOWS */
#endif

View File

@ -1,61 +0,0 @@
/**
* @file include/retdec/dwarfparser/dwarf_resources.h
* @brief Declaration of classes representing resources.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#ifndef RETDEC_DWARFPARSER_DWARF_RESOURCES_H
#define RETDEC_DWARFPARSER_DWARF_RESOURCES_H
#include <map>
#include <vector>
#include "retdec/dwarfparser/dwarf_parserdefs.h"
namespace retdec {
namespace dwarfparser {
// Extern forward declarations.
// Locale forward declarations.
class DwarfResources;
/**
* @class DwarfResources
* @brief Provide access to local resources.
* Must be initialized before use.
* To initialize use initAccess() and initPcReg().
*/
class DwarfResources
{
public:
/**
* @brief Representation of real architecture register.
*/
struct RealReg
{
RealReg() : arrayNum(0) {}
RealReg(std::string s, unsigned n) : name(s), arrayNum(n) {}
std::string name; ///< Name of register array which contains this register.
unsigned arrayNum; ///< Index number of this register in register array.
};
public:
void initMappingDefault(eDefaultMap m = MIPS);
void dump();
Dwarf_Signed getReg(Dwarf_Half n);
Dwarf_Signed getReg(std::string name, Dwarf_Addr number);
Dwarf_Signed getAddr(Dwarf_Addr a);
Dwarf_Addr getPcReg();
void setReg(Dwarf_Half reg, std::string *n, Dwarf_Addr *a);
private:
std::map<Dwarf_Half, RealReg> m_regMaps; ///< Mapping of DWARF register numbers to
///< architecture registers.
};
} // namespace dwarfparser
} // namespace retdec
#endif

View File

@ -1,454 +0,0 @@
/**
* @file include/retdec/dwarfparser/dwarf_types.h
* @brief Declaration of classes representing data types.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#ifndef RETDEC_DWARFPARSER_DWARF_TYPES_H
#define RETDEC_DWARFPARSER_DWARF_TYPES_H
#include <cstdlib>
#include <map>
#include <vector>
#include <libdwarf/libdwarf.h>
#include "retdec/dwarfparser/dwarf_base.h"
#include "retdec/dwarfparser/dwarf_locations.h"
#include "retdec/dwarfparser/dwarf_utils.h"
namespace retdec {
namespace dwarfparser {
// Extern forward declarations.
class DwarfFile;
class DwarfVarContainer;
// Locale forward declarations.
class DwarfType;
class DwarfArrayType;
class DwarfEnumType;
class DwarfStructType;
class DwarfUnionType;
class DwarfTypedefType;
class DwarfFunctionType;
class DwarfTypeContainer;
class DwarfModifierType;
class DwarfConstType;
class DwarfPackedType;
class DwarfPointerType;
class DwarfReferenceType;
class DwarfRestrictType;
class DwarfRValReferenceType;
class DwarfSharedType;
class DwarfVolatileType;
// Macros for type identification.
#define DEC_DWARF_TYPE_TID static const DwarfType::eDataType TID
#define DEF_DWARF_TYPE_TID(CL, ID) const DwarfType::eDataType CL::TID = ID
/**
* @class DwarfType
* @brief Base data type, others are derived from it.
*/
class DwarfType : public DwarfBaseElement
{
public:
/**
* @brief Types of data types.
*/
enum eDataType
{
BASE, ///< Basic data type.
// Composite types.
ARRAY, ///< Data type is an array.
ENUMERATION, ///< Data type is an enumeration.
FUNCTION, ///< Data type is a function.
STRUCTURE, ///< Data type is a structure.
TYPEDEF, ///< Data type is a typedef.
UNION, ///< Data type is an union.
CLASS, ///< Data type is a class.
// Modifier types.
CONSTANT, ///< C or C++ const qualified type.
PACKED, ///< Pascal or Ada packed type.
POINTER, ///< Pointer to an object of the type being modified.
REFERENCE, ///< C++ (lvalue) reference to an object ot the type being modified.
RESTRICT, ///< C restrict qualified type.
RVAL_REFERENCE, ///< C++ rvalue to an object ot the type being modified.
SHARED, ///< UPC shared qualified type.
VOLATILE ///< C or C++ volatile qualified type.
};
/**
* @brief Mapping of eDataType enum to strings.
* Entries must be in the same order as in eDataType.
*/
static const char * eDataTypeString[];
public:
DwarfType(DwarfTypeContainer *prnt, Dwarf_Off o);
virtual void load(AttrProcessor &ap);
virtual void dump() const override;
virtual std::string toLLVMString() const;
virtual std::string toLLVMStringIdentified() const;
Dwarf_Unsigned getBitSize() const;
Dwarf_Unsigned getByteSize() const;
DwarfType *getUnderlyingType();
std::string dumpNameAndOffset() const;
//
// All data types are referenced as pointers to this base class.
// TODO: not sure about these, i might be dangerous to use strict T::TID.
//
template<typename T> bool constructed_as()
{
return (dynamic_cast<T*>(this) != nullptr ? true : false);
}
template<typename T> T* leaf_cast()
{
return dynamic_cast<T*>(this);
}
public:
DEC_DWARF_TYPE_TID;
Dwarf_Unsigned bitSize; ///< Bit size of data type.
Dwarf_Unsigned encoding; ///< DWARF Encoding of base type (valid only for base types).
eDataType dataType; ///< Type of data type.
};
/**
* @class DwarfArrayType
* @brief Array data type.
*/
class DwarfArrayType : public DwarfType
{
public:
using dimension_it = std::vector<Dwarf_Unsigned>::iterator;
using const_dimension_it = std::vector<Dwarf_Unsigned>::const_iterator;
public:
DwarfArrayType(DwarfTypeContainer *prnt, Dwarf_Off o);
virtual void load(AttrProcessor &ap) override;
virtual void dump() const override;
virtual std::string toLLVMString() const override;
virtual std::string toLLVMStringIdentified() const override;
void addDimension(Dwarf_Unsigned d);
void updateSize();
std::size_t dimensionCount();
DEC_DWARF_TYPE_TID;
DwarfType *baseType; ///< Pointer to data type object of array elements.
std::vector<Dwarf_Unsigned> dimensionBounds; ///< Array bounds. bound(int[3]) = 2.
};
/**
* @class DwarfEnumType
* @brief Enumeration data type.
*/
class DwarfEnumType : public DwarfType
{
public:
/**
* @brief Structure representing single enumeration member.
*/
struct EnumMember
{
std::string name; ///< Name of member.
Dwarf_Signed constVal; ///< Constant value of member.
};
using member_t = std::vector<EnumMember> ;
using member_const_it_t = member_t::const_iterator ;
public:
DwarfEnumType(DwarfTypeContainer *prnt, Dwarf_Off o);
virtual void load(AttrProcessor &ap) override;
virtual void dump() const override;
virtual std::string toLLVMString() const override;
virtual std::string toLLVMStringIdentified() const override;
void addMember(EnumMember m);
std::size_t memberCount();
DEC_DWARF_TYPE_TID;
DwarfType *baseType; ///< Pointer to data type of elements. C is not using it.
member_t members; ///< Vector of enumeration members.
};
/**
* @class DwarfStructType
* @brief Structure data type.
*/
class DwarfStructType : public DwarfType
{
public:
/**
* @brief Structure representing single structure member.
*/
class StructMember
{
public:
StructMember() :
type(nullptr), location(nullptr), bitSize(EMPTY_UNSIGNED), bitOffset(EMPTY_UNSIGNED), access(DW_ACCESS_public)
{}
void setAccess(Dwarf_Unsigned a)
{ access = (a==DW_ACCESS_public || a==DW_ACCESS_protected || a==DW_ACCESS_private) ? a : DW_ACCESS_public; }
Dwarf_Unsigned getAccess() const
{ return access; }
std::string name; ///< Name of this member.
DwarfType *type; ///< Pointer to data type of this member.
DwarfLocationDesc* location; ///< Location of the member.
Dwarf_Unsigned bitSize; ///< Bit size of bit field.
Dwarf_Unsigned bitOffset; ///< Bit offset of bit field.
private:
Dwarf_Unsigned access; ///< Member accessibility.
};
public:
DwarfStructType(DwarfTypeContainer *prnt, Dwarf_Off o);
~DwarfStructType();
virtual void load(AttrProcessor &ap) override;
virtual void dump() const override;
virtual std::string toLLVMString() const override;
virtual std::string toLLVMStringIdentified() const override;
void addMember(StructMember m);
void addStaticMember(StructMember m);
std::size_t memberCount();
DEC_DWARF_TYPE_TID;
std::vector<StructMember> members; ///< Vector of structure members.
std::vector<StructMember> staticMembers;
};
/**
* @class DwarfStructType
* @brief Structure data type.
*/
class DwarfUnionType : public DwarfStructType
{
public:
DwarfUnionType(DwarfTypeContainer *prnt, Dwarf_Off o);
DEC_DWARF_TYPE_TID;
};
/**
* @class DwarfClassType
*/
class DwarfClassType : public DwarfStructType
{
public:
/**
* @brief Class represents inheritance relationship.
*/
class InheritanceMember
{
public:
InheritanceMember(DwarfClassType *b, Dwarf_Unsigned a) :
base(b),
access((a==DW_ACCESS_public || a==DW_ACCESS_protected || a==DW_ACCESS_private) ? a : DW_ACCESS_public)
{
}
DwarfClassType *getBase() const { return base; }
Dwarf_Unsigned getAccess() const { return access; }
private:
DwarfClassType *base;
Dwarf_Unsigned access;
};
public:
DwarfClassType(DwarfTypeContainer *prnt, Dwarf_Off o);
virtual void load(AttrProcessor &ap) override;
virtual void dump() const override;
DEC_DWARF_TYPE_TID;
std::vector<DwarfFunction*> memberFunctions;
std::vector<InheritanceMember> baseClasses;
};
/**
* @class DwarfTypedefType
* @brief Typedef data type.
*/
class DwarfTypedefType : public DwarfType
{
public:
DwarfTypedefType(DwarfTypeContainer *prnt, Dwarf_Off o);
virtual void load(AttrProcessor &ap) override;
virtual void dump() const override;
virtual std::string toLLVMString() const override;
virtual std::string toLLVMStringIdentified() const override;
DEC_DWARF_TYPE_TID;
DwarfType *baseType; ///< Pointer to original data type od this typedef.
};
/**
* @class DwarfFunctionType
* @brief Function (subroutine) data type.
*/
class DwarfFunctionType : public DwarfType
{
public:
DwarfFunctionType(DwarfTypeContainer *prnt, Dwarf_Off o);
~DwarfFunctionType();
virtual void load(AttrProcessor &ap) override;
virtual void dump() const override;
virtual std::string toLLVMString() const override;
virtual std::string toLLVMStringIdentified() const override;
bool hasParams();
DwarfVarContainer *getParams();
const DwarfVarContainer *getParams() const;
std::size_t getParamCount() const;
DEC_DWARF_TYPE_TID;
DwarfType *type; ///< Data type of function.
DwarfFunction *func; ///< Real function of this type. This may be filled using name of the type.
///< Name is usually not set, and this is not used at the moment.
bool isVariadic; ///< If true, function has variadic argument following arguments stored in m_params.
private:
DwarfVarContainer *m_params; ///< Container with parameters of this function.
};
/**
* @class DwarfModifierType
* @brief Base class for all data type modifier classes.
*/
class DwarfModifierType : public DwarfType
{
public:
DwarfModifierType(DwarfTypeContainer *prnt, Dwarf_Off o);
virtual void load(AttrProcessor &ap) override;
virtual void dump() const override;
virtual std::string toLLVMString() const override;
virtual std::string toLLVMStringIdentified() const override;
DwarfType *baseType; ///< Pointer to data type this pointer is pointing to.
};
/**
* @class DwarfConstType
* @brief Constant data type modifier.
*/
class DwarfConstType : public DwarfModifierType
{
public:
DwarfConstType(DwarfTypeContainer *prnt, Dwarf_Off o);
DEC_DWARF_TYPE_TID;
};
/**
* @class DwarfPackedType
* @brief Packed data type modifier.
*/
class DwarfPackedType : public DwarfModifierType
{
public:
DwarfPackedType(DwarfTypeContainer *prnt, Dwarf_Off o);
DEC_DWARF_TYPE_TID;
};
/**
* @class DwarfPointerType
* @brief Pointer data type modifier.
*/
class DwarfPointerType : public DwarfModifierType
{
public:
DwarfPointerType(DwarfTypeContainer *prnt, Dwarf_Off o);
virtual std::string toLLVMString() const override;
unsigned getPointerLevel();
DEC_DWARF_TYPE_TID;
};
/**
* @class DwarfReferenceType
* @brief Reference data type modifier.
*/
class DwarfReferenceType : public DwarfModifierType
{
public:
DwarfReferenceType(DwarfTypeContainer *prnt, Dwarf_Off o);
DEC_DWARF_TYPE_TID;
};
/**
* @class DwarfRestrictType
* @brief Restrict data type modifier.
*/
class DwarfRestrictType : public DwarfModifierType
{
public:
DwarfRestrictType(DwarfTypeContainer *prnt, Dwarf_Off o);
DEC_DWARF_TYPE_TID;
};
/**
* @class DwarfRValReferenceType
* @brief Rvalue reference data type modifier.
*/
class DwarfRValReferenceType : public DwarfModifierType
{
public:
DwarfRValReferenceType(DwarfTypeContainer *prnt, Dwarf_Off o);
DEC_DWARF_TYPE_TID;
};
/**
* @class DwarfSharedType
* @brief Shared data type modifier.
*/
class DwarfSharedType : public DwarfModifierType
{
public:
DwarfSharedType(DwarfTypeContainer *prnt, Dwarf_Off o);
DEC_DWARF_TYPE_TID;
};
/**
* @class DwarfVolatileType
* @brief Volatile data type modifier.
*/
class DwarfVolatileType : public DwarfModifierType
{
public:
DwarfVolatileType(DwarfTypeContainer *prnt, Dwarf_Off o);
DEC_DWARF_TYPE_TID;
};
/**
* @class DwarfTypeContainer
* @brief Data type container.
*/
class DwarfTypeContainer : public DwarfBaseContainer<DwarfType>
{
public:
DwarfTypeContainer(DwarfFile *file, DwarfBaseElement *elem = nullptr);
virtual void dump() const override;
DwarfType *checkIfLoaded(Dwarf_Off off);
virtual DwarfType *loadAndGetDie(Dwarf_Die die, unsigned lvl) override;
DwarfType *getTypeByName(std::string n);
DwarfType *getVoid();
int getDieFlags(Dwarf_Die die, unsigned lvl);
private:
DwarfType m_void; ///< Void data type.
std::map<Dwarf_Off, DwarfType*> m_typeCache; ///< Cache for fast type search based on die offset.
};
} // namespace dwarfparser
} // namespace retdec
#endif

View File

@ -1,77 +0,0 @@
/**
* @file include/retdec/dwarfparser/dwarf_utils.h
* @brief Declaration of utility functions and classes.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#ifndef RETDEC_DWARFPARSER_DWARF_UTILS_H
#define RETDEC_DWARFPARSER_DWARF_UTILS_H
#include <string>
#include <libdwarf/dwarf.h>
#include <libdwarf/libdwarf.h>
namespace retdec {
namespace dwarfparser {
class DwarfType;
class DwarfLocationDesc;
// Extern forward declarations.
// Locale forward declarations.
class AttrProcessor;
/**
* Safe encapsulation of libdwarf functions that are getting
* data from attributes.
*/
Dwarf_Addr getAttrAddr(Dwarf_Attribute attr);
Dwarf_Unsigned getAttrNumb(Dwarf_Attribute attr);
std::string getAttrStr(Dwarf_Attribute attr);
Dwarf_Off getAttrRef(Dwarf_Attribute attr);
Dwarf_Off getAttrGlobalRef(Dwarf_Attribute attr);
Dwarf_Bool getAttrFlag(Dwarf_Attribute attr);
Dwarf_Block *getAttrBlock(Dwarf_Attribute attr);
Dwarf_Sig8 getAttrSig(Dwarf_Attribute attr);
void getAttrExprLoc(Dwarf_Attribute attr, Dwarf_Unsigned *exprlen, Dwarf_Ptr *ptr);
std::string getDwarfError(Dwarf_Error &error);
bool getDieFromOffset(Dwarf_Debug dbg, Dwarf_Off off, Dwarf_Die &die);
/**
* @class AttrProcessor
* @brief Helper class providing access to DIE's attributes.
* Class is initialized with DIE which attributes will be processed.
*/
class AttrProcessor
{
public:
AttrProcessor(Dwarf_Debug dbg, Dwarf_Die die, DwarfFile *parent);
bool get(Dwarf_Half attrCode, std::string& ret);
bool get(Dwarf_Half attrCode, const std::string* &ret);
bool get(Dwarf_Half attrCode, Dwarf_Unsigned& ret);
bool get(Dwarf_Half attrCode, Dwarf_Signed& ret);
bool get(Dwarf_Half attrCode, Dwarf_Bool& ret);
bool get(Dwarf_Half attrCode, DwarfLocationDesc* &ret);
bool get(Dwarf_Half attrCode, DwarfType* &ret);
bool geti(Dwarf_Half attrCode, int& ret);
Dwarf_Off getDieOff();
private:
Dwarf_Debug m_dbg; ///< Libdwarf structure representing DWARF file.
Dwarf_Die m_die; ///< Source DIE which atributes will be processed.
DwarfFile *m_parent; ///< Parent dwarfparser representation of DWARF file.
int m_res; ///< Global return value.
Dwarf_Error m_error; ///< Global error code.
};
} // namespace dwarfparser
} // namespace retdec
#endif

View File

@ -1,85 +0,0 @@
/**
* @file include/retdec/dwarfparser/dwarf_vars.h
* @brief Declaration of classes representing variables.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#ifndef RETDEC_DWARFPARSER_DWARF_VARS_H
#define RETDEC_DWARFPARSER_DWARF_VARS_H
#include <cstdlib>
#include "retdec/dwarfparser/dwarf_base.h"
#include "retdec/dwarfparser/dwarf_locations.h"
#include "retdec/dwarfparser/dwarf_types.h"
namespace retdec {
namespace dwarfparser {
// Extern forward declarations.
class DwarfFile;
// Locale forward declarations.
class DwarfVar;
class DwarfVarContainer;
/**
* @class DwarfVar
* @brief Variable object.
*/
class DwarfVar : public DwarfBaseElement
{
public:
/**
* @brief Variable flags.
*/
enum eFlags
{
EMPTY = 0, ///< Empty.
CONSTANT = 1 << 1, ///< This is constant, not variable.
POINTER = 1 << 2, ///< Variable is a pointer.
RESTRICT = 1 << 3, ///< Variable is restrict.
VOLATILE = 1 << 4 ///< Variable is volatile.
};
public:
DwarfVar(DwarfVarContainer *prnt, Dwarf_Off off, DwarfBaseElement::type_t t = DwarfBaseElement::VAR);
virtual ~DwarfVar() override;
virtual void dump() const override;
bool hasLocation();
void mergeWith(DwarfVar *o);
DwarfLocationDesc::cLocType getLocation(std::string *n, Dwarf_Addr *a, Dwarf_Addr pc=0);
bool isOnStack(Dwarf_Signed *a, bool *deref, Dwarf_Addr pc = 0, int *regNum=nullptr);
bool isConstant() const;
bool isPointer() const;
bool isRestrict() const;
bool isVolatile() const;
public:
int flags; ///< Flags of variable.
DwarfType *type; ///< Data type of variable.
DwarfLocationDesc *location; ///< Location descriptor of variable.
};
/**
* @class DwarfVarContainer
* @brief Variable container.
*/
class DwarfVarContainer : public DwarfBaseContainer<DwarfVar>
{
public:
DwarfVarContainer(DwarfFile *file, DwarfBaseElement *elem = nullptr);
virtual void dump() const override;
virtual DwarfVar *loadAndGetDie(Dwarf_Die die, unsigned lvl) override;
DwarfVar *getVarByName(std::string n);
DwarfVar *addParameter(DwarfVar *n);
};
} // namespace dwarfparser
} // namespace retdec
#endif

View File

@ -1,11 +0,0 @@
##########################################
#
# Makefile
#
##########################################
#
# !!! THIS IS NOT USED, ONLY SOURCES ARE ADDED TO APPLICATION COMPILATION.
# !!! WHEN I TRIED TO CREATE .a FROM INTERFACE THE SAME CODE THAT WORKED
# !!! BEFORE CAUSED SEG FAULT.
#

View File

@ -1,326 +0,0 @@
/**
* @file include/retdec/fileformat-libdwarf-interface/bin_interface.h
* @brief Definition of binary interface working with input files.
* Based on declarations of interface in libdwarf.h
* and definition of ELF interface in dwarf_elf_access.cpp.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#ifndef BININT_H_
#define BININT_H_
#include <list>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include <libdwarf/dwarf.h>
#include <libdwarf/libdwarf.h>
#include "retdec/fileformat/format_factory.h"
#include "retdec/fileformat/file_format/file_format.h"
/**
* @class BinInt.
* @brief This class creates binary interface to access input files.
*/
class BinInt
{
//
// Public class methods.
//
public:
/**
* @brief Initialize class and dwarf object access method structure.
* @param fileName Name of input file to load.
* @param fileParser Parser of input file (optional).
* @note Function which relocate a section is not used at the moment.
*/
BinInt(std::string fileName, retdec::fileformat::FileFormat *fileParser = nullptr) :
m_fileName(fileName),
m_fileParser(fileParser),
m_parserInsteadOfPath(m_fileParser && m_fileParser->isInValidState()),
m_success(true),
m_binInt(nullptr),
dwarf_binint_object_access_methods()
{
dwarf_binint_object_access_init();
struct Dwarf_Obj_Access_Methods_s p = {
dwarf_binint_object_access_get_section_info,
dwarf_binint_object_access_get_byte_order,
dwarf_binint_object_access_get_length_size,
dwarf_binint_object_access_get_pointer_size,
dwarf_binint_object_access_get_section_count,
dwarf_binint_object_access_load_section,
nullptr //dwarf_binint_object_relocate_a_section
};
dwarf_binint_object_access_methods = p;
}
/**
* @brief Clean up input file object access interface.
*/
~BinInt()
{
delete m_binInt;
}
/**
* @brief Return input file binary interface.
* @return Input file binary interface.
*/
Dwarf_Obj_Access_Interface *getInt()
{
return m_binInt;
}
/**
* @brief Tells caller if input file file was loaded successfully or not.
* @return True if success, false otherwise.
*/
bool success()
{
return m_success;
}
//
// TODO: maybe relocate this to ctor.
//
private:
/**
* @brief Initialize input file binary interface.
*/
void dwarf_binint_object_access_init()
{
// Open input object file.
retdec::fileformat::FileFormat *objFile = nullptr;
if(m_parserInsteadOfPath)
{
objFile = m_fileParser;
}
else
{
m_newParserPtr = retdec::fileformat::createFileFormat(m_fileName);
if(m_newParserPtr)
{
objFile = m_newParserPtr.get();
}
}
// Alloc interface descriptor.
m_binInt = new Dwarf_Obj_Access_Interface;
if (!m_binInt || !objFile)
{
m_success = false;
return;
}
// Initialize the interface struct.
m_binInt->object = objFile;
m_binInt->methods = &dwarf_binint_object_access_methods;
m_success = objFile->isInValidState();
return;
}
//
// Access functions as defined in libdwarf.h.
//
private:
/**
* @brief Get address, size, and name info about a section.
* @param obj_in Object file structure.
* @param section_index Section index.
* @param ret_scn Structure where section info will be placed.
* @param error A pointer to an integer in which an error code may be stored.
* @return Return code.
*/
static int dwarf_binint_object_access_get_section_info(
void* obj_in,
Dwarf_Half section_index,
Dwarf_Obj_Access_Section* ret_scn,
int* error)
{
auto *obj = static_cast<retdec::fileformat::FileFormat*>(obj_in);
const auto *sec = obj->getSection(section_index);
if (!sec)
{
*error = DW_DLE_MDE;
return DW_DLV_ERROR;
}
ret_scn->size = sec->getSizeInFile();
ret_scn->addr = sec->getAddress();
ret_scn->name = sec->getNameAsCStr();
ret_scn->link = 0; // TODO: meaningless?
return DW_DLV_OK;
}
/**
* @brief Find out if file is big-endian or little endian.
* @param obj_in Object file structure.
* @return Endianness of object.
*/
static Dwarf_Endianness dwarf_binint_object_access_get_byte_order(
void* obj_in)
{
auto *obj = static_cast<retdec::fileformat::FileFormat*>(obj_in);
if (obj->isLittleEndian())
{
return DW_OBJECT_LSB;
}
else if (obj->isBigEndian())
{
return DW_OBJECT_MSB;
}
else
{
// This may happen in input file (undefined) but there is no
// dwarflib option for it.
return DW_OBJECT_LSB;
}
}
/**
* @brief Get the size of a length field in the underlying object file.
* @param obj_in Object file structure.
* @return Size of length.
*
* TODO: what is length size??? is it same as word length???
*/
static Dwarf_Small dwarf_binint_object_access_get_length_size(
void* obj_in)
{
auto *obj = static_cast<retdec::fileformat::FileFormat*>(obj_in);
return static_cast<Dwarf_Small>(obj->getBytesPerWord());
}
/**
* @brief Get the size of a pointer field in the underlying object file.
* @param obj_in Object file structure.
* @return Size of pointer.
*/
static Dwarf_Small dwarf_binint_object_access_get_pointer_size(
void* obj_in)
{
auto *obj = static_cast<retdec::fileformat::FileFormat*>(obj_in);
return static_cast<Dwarf_Small>(obj->getBytesPerWord());
}
/**
* @brief Get the number of sections in the object file.
* @param obj_in Object file structure.
* @return Number of sections.
*/
static Dwarf_Unsigned dwarf_binint_object_access_get_section_count(
void * obj_in)
{
auto *obj = static_cast<retdec::fileformat::FileFormat*>(obj_in);
return obj->getNumberOfSections();
}
/**
* @brief Get a pointer to an array of bytes that represent the section.
* @param obj_in Object file structure.
* @param section_index Index of section which data to get.
* @param section_data The address of a pointer where sec data will be placed.
* @param error Pointer to integer for returning libdwarf-defined error numbers.
* @return Return code.
*/
static int dwarf_binint_object_access_load_section(
void* obj_in,
Dwarf_Half section_index,
Dwarf_Small** section_data,
int* error)
{
std::map<Dwarf_Half, std::vector<unsigned char>>::iterator fIt = BinInt::secBytes().find(section_index);
if (fIt != BinInt::secBytes().end())
{
*section_data = fIt->second.data();
return DW_DLV_OK;
}
else
{
auto *obj = static_cast<retdec::fileformat::FileFormat*>(obj_in);
if (!obj || !section_data)
{
*error = DW_DLE_MDE;
return DW_DLV_ERROR;
}
const auto *fSec = obj->getSection(section_index);
std::vector<unsigned char> bytes;
if (!fSec || !fSec->getBytes(bytes))
{
*error = DW_DLE_MDE;
return DW_DLV_ERROR;
}
BinInt::secBytes()[section_index] = bytes;
*section_data = BinInt::secBytes()[section_index].data();
if (*section_data == NULL)
{
*error = DW_DLE_MDE;
return DW_DLV_ERROR;
}
return DW_DLV_OK;
}
}
/**
* @brief Relocate a section.
* @param obj_in Object file structure.
* @param section_index Index of section to relocate.
* @param dbg Libdwarf representation of file.
* @param error Pointer to integer for returning libdwarf-defined error numbers.
* @return Return code.
*/
static int dwarf_binint_object_relocate_a_section(
void* obj_in,
Dwarf_Half section_index,
Dwarf_Debug dbg,
int* error)
{
return DW_DLV_OK;
}
//
// When this module had both header and source file, we declared static variable
// secBytes here in header and defined it in source.
// However, it is easier to use this module when it is header only.
// The problem is that static member variables can not be defined in header files.
// Therefore, we hack it by using static member getter method which contains
// static local variable in its body.
//
// Matula: I have no idea why there is (must be?) a static member variable in the
// first place, but it seems to work, so be it.
//
private:
static std::map<Dwarf_Half, std::vector<unsigned char>>& secBytes()
{
static std::map<Dwarf_Half, std::vector<unsigned char>> secBytes;
return secBytes;
}
//
// Class data.
//
private:
std::string m_fileName;
std::unique_ptr<retdec::fileformat::FileFormat> m_newParserPtr;
retdec::fileformat::FileFormat *m_fileParser;
bool m_parserInsteadOfPath;
bool m_success;
Dwarf_Obj_Access_Interface *m_binInt;
struct Dwarf_Obj_Access_Methods_s dwarf_binint_object_access_methods;
};
#endif

View File

@ -1,54 +0,0 @@
#
# This file contains code that needs to be added to dwarfdump2
# to enable inputs in our format.
# It needs to be modified manually because new versions might change
# original dawrfdump.cc and automatic patch may screw it up.
#
// Add include.
// Simple or with more complex path -- depends on make settings.
//
#include "bin_interface.h"
// Make sure input files will be further processed in main().
//
// replace
/* not a 64-bit obj either! */
/* dwarfdump is quiet when not an object */
// with
process_one_file(elf, file_name, archive, &config_file_data);
// or just always call process_one_file.
// Add bin-interface to process_one_file().
//
// add
Dwarf_Handler errHand = 0;
Dwarf_Ptr errArg = 0;
BinInt *binInt = new BinInt(file_name);
if (binInt->success())
{
dres = dwarf_object_init(binInt->getInt(),
errHand, errArg, &dbg, &err);
// Input file has no DWARF information.
if (dres == DW_DLV_NO_ENTRY)
{
cout <<"No DWARF information present in " << file_name <<endl;
return 0;
}
// Something went wrong.
else if(dres != DW_DLV_OK)
{
delete binInt;
print_error(dbg, "dwarf_object_init", dres, err);
}
}
else
{ ... }
// before
dres = dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dbg, &err);
// and make sure whole ELF loading is in the else { ... } branch.

View File

@ -15,7 +15,6 @@ cond_add_subdirectory(ctypesparser RETDEC_ENABLE_CTYPESPARSER)
cond_add_subdirectory(debugformat RETDEC_ENABLE_DEBUGFORMAT)
cond_add_subdirectory(demangler RETDEC_ENABLE_DEMANGLER)
cond_add_subdirectory(demanglertool RETDEC_ENABLE_DEMANGLERTOOL)
cond_add_subdirectory(dwarfparser RETDEC_ENABLE_DWARFPARSER)
cond_add_subdirectory(fileformat RETDEC_ENABLE_FILEFORMAT)
cond_add_subdirectory(fileinfo RETDEC_ENABLE_FILEINFO)
cond_add_subdirectory(getsig RETDEC_ENABLE_GETSIG)

View File

@ -1,16 +0,0 @@
set(DWARFPARSER_SOURCES
dwarf_base.cpp
dwarf_cu.cpp
dwarf_file.cpp
dwarf_functions.cpp
dwarf_linenumbers.cpp
dwarf_locations.cpp
dwarf_resources.cpp
dwarf_types.cpp
dwarf_utils.cpp
dwarf_vars.cpp
)
add_library(retdec-dwarfparser STATIC ${DWARFPARSER_SOURCES})
target_link_libraries(retdec-dwarfparser retdec-fileformat retdec-utils libdwarf)
target_include_directories(retdec-dwarfparser PUBLIC ${PROJECT_SOURCE_DIR}/include/)

View File

@ -1,11 +0,0 @@
/**
* @file src/dwarfparser/doxygen.h
* @brief Doxygen documentation of the dwarfparser namespace.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
// As there is no better place to comment this namespace, we do this in the
// present file.
/// @namespace dwarfparser A library for parsing a processing
/// files with DWARF debugging information.

View File

@ -1,64 +0,0 @@
/**
* @file src/dwarfparser/dwarf_base.cpp
* @brief Implementation of base classes used in dwarfparser.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#include <algorithm>
#include <cstdlib>
#include <sstream>
#include "retdec/dwarfparser/dwarf_base.h"
#include "retdec/dwarfparser/dwarf_file.h"
#include "retdec/dwarfparser/dwarf_functions.h"
using namespace std;
namespace retdec {
namespace dwarfparser {
/**
* @brief ctor.
* @param type Type of the base element.
* @param prnt Pointer to parent container that contains this element.
* @param off Offset associated with this element in DWARF file - unique ID.
*/
DwarfBaseElement::DwarfBaseElement(type_t type, DwarfBaseContainer<DwarfBaseElement> *prnt, Dwarf_Off off) :
m_type(type),
m_parent(prnt),
m_cuParent(m_parent->getParentFile()->m_activeCU)
{
if (m_parent)
m_parent->off2data[off] = this;
}
/**
*
*/
void DwarfBaseElement::addOffset(Dwarf_Off o)
{
if (m_parent)
m_parent->off2data[o] = this;
}
/**
*
*/
string DwarfBaseElement::getDwarfdump2OffsetString() const
{
stringstream ret;
ret << "(";
ret << ")";
return ret.str();
}
/**
* @brief Get libdwarf's debug file.
*/
Dwarf_Debug &DwarfBaseElement::getLibdwarfDebug() const
{
return getParentFile()->getDwarfDebug();
}
} // namespace dwarfparser
} // namespace retdec

View File

@ -1,206 +0,0 @@
/**
* @file src/dwarfparser/dwarf_cu.cpp
* @brief Implementaion of classes representing Compilation Units.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#include <iostream>
#include <libdwarf/dwarf.h>
#include <libdwarf/libdwarf.h>
#include "retdec/dwarfparser/dwarf_cu.h"
#include "retdec/dwarfparser/dwarf_file.h"
using namespace std;
namespace retdec {
namespace dwarfparser {
/**
* @brief ctor.
* @param file Pointer to dwarfparser representation of DWARF file which owns this container.
* @param elem Pointer to parent element that owns this container.
*/
DwarfCUContainer::DwarfCUContainer(DwarfFile *file, DwarfBaseElement *elem) :
DwarfBaseContainer<DwarfCU>(file, elem)
{
}
/**
* @brief Get all data from compilation unit DIE.
* @param cuDie Compilation unit DIE.
* @param lvl Level (depth) of this die.
* @return Pointer to newly created CU object or nullptr if failed.
*/
DwarfCU *DwarfCUContainer::loadAndGetDie(Dwarf_Die cuDie, unsigned)
{
// Get source files.
char **srcFiles;
Dwarf_Signed fileCnt;
m_res = dwarf_srcfiles(cuDie, &srcFiles, &fileCnt, &m_error);
if (m_res == DW_DLV_ERROR)
{
DWARF_WARNING("dwarf_srcfiles() in loadDie() failed.\n"
"Libdwarf error: " << getDwarfError(m_error));
}
AttrProcessor ap(m_parentFile->m_dbg, cuDie, m_parentFile);
DwarfCU *newCU = new DwarfCU(this, ap.getDieOff());
// Copy source files to new CU.
if (m_res == DW_DLV_OK)
{
for (int i=0; i<fileCnt; i++)
{
newCU->addSrcFile(srcFiles[i]);
dwarf_dealloc(m_parentFile->m_dbg, srcFiles[i], DW_DLA_STRING);
}
dwarf_dealloc(m_parentFile->m_dbg, srcFiles, DW_DLA_LIST);
}
// Use special class to get attributes that we want.
ap.get(DW_AT_comp_dir, newCU->compDir);
ap.get(DW_AT_name, newCU->name);
ap.get(DW_AT_producer, newCU->producer);
ap.get(DW_AT_low_pc, newCU->lowAddr);
ap.get(DW_AT_high_pc, newCU->highAddr);
ap.get(DW_AT_language, newCU->language);
// Add new CU to container and set as active.
m_data.push_back(newCU);
m_parentFile->m_activeCU = newCU;
return newCU;
}
/**
* @brief Print contents of this container.
*/
void DwarfCUContainer::dump() const
{
cout << endl;
cout << "==================== CUs ====================" << endl;
DwarfBaseContainer<DwarfCU>::dump();
cout << endl;
}
/**
* @brief ctor.
* @param prnt Pointer to parent container owning this element.
* @param o Original libdwarf DIE offset.
*/
DwarfCU::DwarfCU(DwarfCUContainer *prnt, Dwarf_Off o) :
DwarfBaseElement(DwarfBaseElement::CU, reinterpret_cast<DwarfBaseContainer<DwarfBaseElement>*>(prnt), o),
lowAddr(0),
highAddr(0),
language(0)
{
}
/**
* @brief Get number of source file of this compilation unit.
* @return Number of source files.
*/
std::size_t DwarfCU::srcFilesCount()
{
return m_srcFiles.size();
}
/**
* @brief Add source file to compilation unit.
* @param f Name of source file.
*/
void DwarfCU::addSrcFile(string f)
{
m_srcFiles.push_back(f);
}
/**
* @brief Get source file by its index.
* @param idx Index of source file to get.
* @return Pointer to source file name or nullptr if index out of range.
*/
string *DwarfCU::getSrcFile(unsigned idx)
{
if (idx < srcFilesCount())
{
list<string>::iterator srcFileIt = m_srcFiles.begin();
advance(srcFileIt, idx);
return &(*srcFileIt);
}
else
{
DWARF_ERROR("getSrcFile(idx): index out of range.");
return nullptr;
}
}
/**
* @brief This method finds record in list of source files with
* the same name as parameter and returns pointer to it.
* @param f Name of source file to find.
* @param ret Address of pointer where result will be saved.
* @return DW_DLV_OK if record was found, DW_DLV_NO_ENTRY if not.
*/
int DwarfCU::findSrcFile(string f, const string **ret)
{
list<string>::const_iterator srcFileIt = m_srcFiles.begin();
while (srcFileIt != m_srcFiles.end())
{
if (*srcFileIt == f)
{
*ret = &(*srcFileIt);
return DW_DLV_OK;
}
++srcFileIt;
}
// If it gets here, no record was found.
return DW_DLV_NO_ENTRY;
}
bool DwarfCU::IsLanguageC() const
{
return
language == DW_LANG_C89 ||
language == DW_LANG_C ||
language == DW_LANG_C99;
}
bool DwarfCU::IsLanguageCpp() const
{
return
language == DW_LANG_C_plus_plus;
}
/**
* @brief Print contents of this class.
*/
void DwarfCU::dump() const
{
cout << "CU : " << name << endl;
cout << "CU DIR : " << compDir << endl;
cout << "CU lowpc : " << hex << lowAddr << endl;
cout << "CU highpc : " << hex << highAddr << endl;
list<string>::const_iterator srcFileIt = m_srcFiles.begin();
while (srcFileIt != m_srcFiles.end())
{
cout << "\t" << *(srcFileIt) << endl;
++srcFileIt;
}
cout << endl;
}
} // namespace dwarfparser
} // namespace retdec

View File

@ -1,713 +0,0 @@
/**
* @file src/dwarfparser/dwarf_file.cpp
* @brief Implementaion of DwarfFile class which provides high-level access
* to DWARF debugging informations.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#include <cstdlib>
#include <fcntl.h>
#include "retdec/utils/os.h"
#include "retdec/dwarfparser/dwarf_file.h"
#ifdef OS_WINDOWS
#include <io.h>
#else
#include <unistd.h>
#endif
using namespace std;
namespace retdec {
namespace dwarfparser {
/**
* @brief ctor -- create containers and load data from input file.
* @param fileName Name of file to open.
* @param fileParser Parser of input file (optional)
*/
DwarfFile::DwarfFile(string fileName, retdec::fileformat::FileFormat *fileParser) :
m_CUs(this),
m_lines(this),
m_functions(this),
m_types(this),
m_globalVars(this),
m_hasDwarf(false),
m_res(0),
m_dbg(nullptr),
m_fd(0),
m_error(nullptr),
m_activeCU(nullptr)
{
loadFile(fileName, fileParser);
}
/**
* @brief dctor -- destroy containers.
*/
DwarfFile::~DwarfFile()
{
if (m_fd && m_dbg)
{
dwarf_finish(m_dbg, &m_error);
#ifdef OS_WINDOWS
_close(m_fd);
#else
close(m_fd);
#endif
}
else
{
dwarf_object_finish(m_dbg, &m_error);
}
}
/**
* @brief Open file and get DWARF info.
* @param fileName Name of file to open.
* @param fileParser Parser of input file (optional)
* @return True if input file contains DWARF information, false otherwise.
*
* Binary interface is used to access input file at first.
* If it fails standard ELF interface provided by libdwarf is used.
*/
bool DwarfFile::loadFile(string fileName, retdec::fileformat::FileFormat *fileParser)
{
Dwarf_Handler errHand = nullptr;
Dwarf_Ptr errArg = nullptr;
// It is possible to load input file with our backend.
BinInt binInt(fileName, fileParser);
if (binInt.success())
{
m_res = dwarf_object_init(binInt.getInt(),
errHand, errArg, &m_dbg, &m_error);
// Input file has no DWARF information.
if (m_res == DW_DLV_NO_ENTRY)
{
DWARF_WARNING("File: \"" << fileName << "\" has no DWARF information.");
return false;
}
// Something went wrong.
else if (m_res != DW_DLV_OK)
{
DWARF_ERROR("Libdwarf error: " << getDwarfError(m_error));
return false;
}
resources.initMappingDefault();
loadFileCUs();
m_hasDwarf = true;
}
// Our binary backend can not be used
// --> try to use ELF interface.
else
{
DWARF_WARNING("Using ELF interface.");
#ifdef OS_WINDOWS
if ((m_fd = _open(fileName.c_str(), _O_RDONLY, 0)) < 0)
#else
if ((m_fd = open(fileName.c_str(), O_RDONLY, 0)) < 0)
#endif
{
DWARF_ERROR("File: \"" << fileName << "\" can not be opened.");
return false;
}
m_res = dwarf_init(m_fd, DW_DLC_READ, errHand, errArg, &m_dbg, &m_error);
if (m_res == DW_DLV_NO_ENTRY)
{
DWARF_WARNING("File: \"" << fileName << "\" has no DWARF information.");
return false;
}
else if(m_res != DW_DLV_OK)
{
DWARF_ERROR("Libdwarf error: " << getDwarfError(m_error));
return false;
}
// Init register mapping by default values.
resources.initMappingDefault();
loadFileCUs();
m_hasDwarf = true;
}
makeStructTypesUnique();
return m_hasDwarf;
}
/**
* Same-named structures may exist. We need to rename them -> make them unique,
* otherwise, string based (LLVM) type representation can not be used.
* Several same named structures would be generated and it would not be possible
* to distinguish their uses from one another.
*/
void DwarfFile::makeStructTypesUnique()
{
std::map<std::string, unsigned> typeMap;
for (auto& t : m_types)
{
if (t->constructed_as<DwarfStructType>())
{
auto fIt = typeMap.find(t->name);
if (fIt == typeMap.end())
{
typeMap[t->name] = 1;
}
else
{
t->name = t->name + "_" + std::to_string(fIt->second);
++fIt->second;
}
}
}
}
/**
* @brief Find out if input file contains DWARF information.
* @return True if input file contains DWARF information, false otherwise.
*/
bool DwarfFile::hasDwarfInfo()
{
return m_hasDwarf;
}
/**
* @brief Iterate over DWARF file's CUs.
*/
void DwarfFile::loadFileCUs()
{
Dwarf_Unsigned cu_header_length = 0;
Dwarf_Half version_stamp = 0;
Dwarf_Unsigned abbrev_offset = 0;
Dwarf_Half address_size = 0;
Dwarf_Half offset_size = 0;
Dwarf_Half extension_size = 0;
Dwarf_Sig8 signature;
Dwarf_Unsigned typeoffset = 0;
Dwarf_Unsigned next_cu_header = 0;
// Iterate over CU headers.
while (dwarf_next_cu_header_c(
m_dbg,
is_info,
&cu_header_length,
&version_stamp,
&abbrev_offset,
&address_size,
&offset_size,
&extension_size,
&signature,
&typeoffset,
&next_cu_header,
&m_error) == DW_DLV_OK)
{
Dwarf_Die cuDie = nullptr;
// CU have single sibling - CU DIE.
// nullptr - descriptor of first die in CU.
m_res = dwarf_siblingof_b(m_dbg, nullptr, is_info, &cuDie, &m_error);
if (m_res == DW_DLV_ERROR)
{
DWARF_ERROR("Libdwarf error: " << getDwarfError(m_error));
return;
}
else if (m_res == DW_DLV_NO_ENTRY)
{
return;
}
int lvl = 0;
loadCUtree(cuDie, nullptr, lvl);
dwarf_dealloc(m_dbg, cuDie, DW_DLA_DIE);
}
}
/**
* @brief Gets a CU DIE at first and recursively load all DIEs in tree.
* @param inDie Input die
* @param parent Parent element or nullptr.
* @param lvl Level (depth) of this die.
*/
void DwarfFile::loadCUtree(Dwarf_Die inDie, DwarfBaseElement* parent, int lvl)
{
Dwarf_Die curDie = inDie;
DwarfBaseElement* siblingElement = parent;
loadDIE(curDie, siblingElement, lvl);
// Siblings and childs.
while (1)
{
// Get child.
Dwarf_Die child = nullptr;
m_res = dwarf_child(curDie, &child, &m_error);
if(m_res == DW_DLV_ERROR)
{
DWARF_ERROR("Libdwarf error: " << getDwarfError(m_error));
return;
}
// Has child -> recursion.
if(m_res == DW_DLV_OK)
{
loadCUtree(child, siblingElement, lvl+1);
}
// No entry -> no child.
Dwarf_Die sib_die = nullptr;
m_res = dwarf_siblingof_b(m_dbg, curDie, is_info, &sib_die, &m_error);
if(m_res == DW_DLV_ERROR)
{
DWARF_ERROR("Libdwarf error: " << getDwarfError(m_error));
return;
}
// Done at this level.
if(m_res == DW_DLV_NO_ENTRY)
{
break;
}
// res == DW_DLV_OK
if(curDie != inDie)
{
dwarf_dealloc(m_dbg, curDie, DW_DLA_DIE);
}
curDie = sib_die;
siblingElement = parent;
loadDIE(curDie, siblingElement, lvl);
}
}
/**
* @brief Get DIE and load all its contents to dwarfparser representation.
* @param die DIE to load.
* @param parent Input parent element. Output newly loaded element or nullptr.
* @param lvl Level (depth) of this die.
*/
void DwarfFile::loadDIE(Dwarf_Die die, DwarfBaseElement* &parent, int lvl)
{
DwarfBaseElement* parentElement = parent;
parent = nullptr;
// DIE name -- unused, but without it there is a SEG FAULT for some reason.
//
char *dieName = nullptr;
bool localname = false;
m_res = dwarf_diename(die, &dieName, &m_error);
if(m_res == DW_DLV_ERROR)
{
DWARF_ERROR("Libdwarf error: " << getDwarfError(m_error));
return;
}
if(m_res == DW_DLV_NO_ENTRY)
{
localname = true;
}
// DIE TAG.
Dwarf_Half tag = 0;
if (dwarf_tag(die, &tag, &m_error) != DW_DLV_OK)
{
DWARF_ERROR("Libdwarf error: " << getDwarfError(m_error));
return;
}
AttrProcessor ap(m_dbg, die, this);
// Decide what to do based on tag type.
switch (tag)
{
//
// Compilation unit.
//
case DW_TAG_compile_unit:
{
parent = m_CUs.loadAndGetDie(die, lvl);
m_lines.loadAndGetDie(die, lvl);
break;
}
//
// Subprogram name == DIE name.
//
case DW_TAG_subprogram:
{
DwarfFunction *tmp = m_functions.loadAndGetDie(die, lvl);
parent = tmp;
DwarfClassType *activeClass = dynamic_cast<DwarfClassType*>(parentElement);
if (tmp && activeClass)
{
activeClass->memberFunctions.push_back(tmp); // TODO: nejak obojsmerne nastavit.
}
break;
}
//
// Class inheritance.
//
case DW_TAG_inheritance:
{
DwarfType *type = nullptr;
Dwarf_Unsigned access;
ap.get(DW_AT_type, type);
ap.get(DW_AT_accessibility, access);
DwarfClassType *activeClass = dynamic_cast<DwarfClassType*>(parentElement);
DwarfClassType *base = dynamic_cast<DwarfClassType*>(type);
if (base && activeClass)
{
DwarfClassType::InheritanceMember inh(base, access);
activeClass->baseClasses.push_back(inh);
}
break;
}
//
// Send all type related DIEs to type class.
//
case DW_TAG_array_type:
case DW_TAG_base_type:
case DW_TAG_class_type:
case DW_TAG_const_type:
case DW_TAG_enumeration_type: // May be used as DW_TAG_subrange_type
case DW_TAG_file_type:
case DW_TAG_interface_type:
case DW_TAG_packed_type:
case DW_TAG_pointer_type:
case DW_TAG_ptr_to_member_type:
case DW_TAG_reference_type:
case DW_TAG_restrict_type:
case DW_TAG_rvalue_reference_type:
case DW_TAG_set_type:
case DW_TAG_shared_type:
case DW_TAG_string_type:
case DW_TAG_structure_type:
case DW_TAG_subroutine_type:
case DW_TAG_thrown_type:
case DW_TAG_typedef:
case DW_TAG_union_type:
case DW_TAG_unspecified_type:
case DW_TAG_volatile_type:
{
auto p = m_types.loadAndGetDie(die, lvl);
Dwarf_Die child = nullptr;
if (dwarf_child(die, &child, &m_error) == DW_DLV_OK)
{
parent = p;
}
break;
}
//
// Belongs to active array.
//
case DW_TAG_subrange_type:
{
DwarfArrayType *activeArray = dynamic_cast<DwarfArrayType *>(parentElement);
if (activeArray != nullptr)
{
Dwarf_Unsigned bound;
ap.get(DW_AT_upper_bound, bound);
activeArray->addDimension(bound);
}
break;
}
//
// Belongs to active enumeration.
//
case DW_TAG_enumerator:
{
DwarfEnumType *activeEnum = dynamic_cast<DwarfEnumType *>(parentElement);
if (activeEnum != nullptr)
{
DwarfEnumType::EnumMember m;
ap.get(DW_AT_name, m.name);
ap.get(DW_AT_const_value, m.constVal);
activeEnum->addMember(m);
}
break;
}
//
// Belongs to active structure.
//
case DW_TAG_member:
{
DwarfStructType *activeStruct = dynamic_cast<DwarfStructType *>(parentElement);
if (activeStruct != nullptr)
{
DwarfStructType::StructMember m;
m.type = nullptr;
m.location = nullptr;
m.bitSize = EMPTY_UNSIGNED;
m.bitOffset = EMPTY_UNSIGNED;
ap.get(DW_AT_name, m.name);
ap.get(DW_AT_type, m.type);
ap.get(DW_AT_data_member_location, m.location);
ap.get(DW_AT_bit_size, m.bitSize);
ap.get(DW_AT_bit_offset, m.bitOffset);
Dwarf_Bool isStatic;
ap.get(DW_AT_external, isStatic);
Dwarf_Unsigned a;
ap.get(DW_AT_accessibility, a);
m.setAccess(a);
if (m.location != nullptr)
{
m.location->setParent(activeStruct);
}
if (isStatic)
activeStruct->addStaticMember(m);
else
activeStruct->addMember(m);
}
break;
}
//
// Variables and constants.
//
case DW_TAG_variable:
{
// Global variable.
if (dynamic_cast<DwarfCU*>(parentElement)) //DwarfCU *activeCu
{
m_globalVars.loadAndGetDie(die, lvl);
}
// Variable belongs to some function.
else if (DwarfFunction *activeFunc = dynamic_cast<DwarfFunction *>(parentElement))
{
activeFunc->getVars()->loadAndGetDie(die, lvl);
}
break;
}
//
// Function parameters -- belong to active function or function type.
//
case DW_TAG_formal_parameter:
{
DwarfFunction *activeFunc = dynamic_cast<DwarfFunction *>(parentElement);
if (activeFunc != nullptr && !activeFunc->isDeclaration)
{
activeFunc->getParams()->loadAndGetDie(die, lvl);
}
else
{
DwarfFunctionType *activeFuncType = dynamic_cast<DwarfFunctionType *>(parentElement);
if (activeFuncType != nullptr)
{
activeFuncType->getParams()->loadAndGetDie(die, lvl);
}
}
break;
}
//
// Variadic parameters.
//
case DW_TAG_unspecified_parameters:
{
DwarfFunction *activeFunc =
dynamic_cast<DwarfFunction *>(parentElement);
if (activeFunc != nullptr)
{
activeFunc->isVariadic = true;
}
else
{
DwarfFunctionType *activeFuncType =
dynamic_cast<DwarfFunctionType *>(parentElement);
if (activeFuncType != nullptr)
{
activeFuncType->isVariadic = true;
}
}
break;
}
//
// Block -- not processed at the moment, but we want to keep old parent
// so that DIEs on lower level connect with parents even if block DIEs
// in the middle are not processed.
//
case DW_TAG_catch_block:
case DW_TAG_common_block:
case DW_TAG_label:
case DW_TAG_lexical_block:
case DW_TAG_module:
case DW_TAG_namespace:
case DW_TAG_partial_unit:
case DW_TAG_try_block:
{
parent = parentElement;
break;
}
//
// DW_TAG_template_type_parameter is in standard.
//
case DW_TAG_template_type_parameter:
{
DwarfFunction *activeFunc = dynamic_cast<DwarfFunction *>(parentElement);
if (activeFunc != nullptr && !activeFunc->isDeclaration)
{
activeFunc->isTemplateInstance = true;
}
break;
}
//
// GNU extension for variadic templates.
//
case DW_TAG_GNU_template_parameter_pack:
case DW_TAG_GNU_formal_parameter_pack:
{
DwarfFunction *activeFunc = dynamic_cast<DwarfFunction *>(parentElement);
if (activeFunc != nullptr && !activeFunc->isDeclaration)
{
activeFunc->isVariadicTemplateInstance = true;
}
break;
}
//
// GNU extension for template template arguments.
//
case DW_TAG_GNU_template_template_parameter:
{
DwarfFunction *activeFunc = dynamic_cast<DwarfFunction *>(parentElement);
if (activeFunc != nullptr && !activeFunc->isDeclaration)
{
activeFunc->isTemplateTemplateInstance = true;
}
break;
}
//
// Unprocessed tags.
//
case DW_TAG_access_declaration:
case DW_TAG_common_inclusion:
case DW_TAG_condition:
case DW_TAG_constant: // in languages with true named constants
case DW_TAG_dwarf_procedure:
case DW_TAG_entry_point:
case DW_TAG_friend:
case DW_TAG_imported_declaration:
case DW_TAG_imported_module:
case DW_TAG_imported_unit:
case DW_TAG_inlined_subroutine:
case DW_TAG_namelist:
case DW_TAG_namelist_item:
case DW_TAG_template_alias:
case DW_TAG_template_value_parameter:
case DW_TAG_type_unit:
case DW_TAG_variant:
case DW_TAG_variant_part:
case DW_TAG_with_stmt:
default:
{
break;
}
}
// Free DIE dieName.
if(!localname)
{
dwarf_dealloc(m_dbg, dieName, DW_DLA_STRING);
}
}
/**
* @brief Get reference to Libdwarf representation.
* @return reference to Libdwarf representation.
*/
Dwarf_Debug &DwarfFile::getDwarfDebug()
{
return m_dbg;
}
/**
* @brief Get all compilation units.
* @return Compilation units.
*/
DwarfCUContainer *DwarfFile::getCUs()
{
return &m_CUs;
}
/**
* @brief Get lines information.
* @return Lines.
*/
DwarfLineContainer *DwarfFile::getLines()
{
return &m_lines;
}
/**
* @brief Get all functions.
* @return Functions.
*/
DwarfFunctionContainer *DwarfFile::getFunctions()
{
return &m_functions;
}
/**
* @brief Get all data types.
* @return Data types.
*/
DwarfTypeContainer *DwarfFile::getTypes()
{
return &m_types;
}
/**
* @brief Get all global variables.
* @return Global variables.
*/
DwarfVarContainer *DwarfFile::getGlobalVars()
{
return &m_globalVars;
}
/**
* @brief Init mapping of DWARF register numbers to names using
* default -- well known mapping for architectures.
* @param m Architecture which default mapping will be used.
* @note Use this method if mappingSecPresent() returns false -> input file
* doesn't contain section with DWARF register numbers mapping.
*/
void DwarfFile::initMapping(eDefaultMap m)
{
resources.initMappingDefault(m);
}
} // namespace dwarfparser
} // namespace retdec

View File

@ -1,314 +0,0 @@
/**
* @file src/dwarfparser/dwarf_functions.cpp
* @brief Implementation of classes representing functions.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#include <iostream>
#include "retdec/dwarfparser/dwarf_base.h"
#include "retdec/dwarfparser/dwarf_file.h"
#include "retdec/dwarfparser/dwarf_functions.h"
using namespace std;
namespace retdec {
namespace dwarfparser {
/**
* @brief ctor.
* @param file Pointer to dwarfparser representation of DWARF file which owns this container.
* @param elem Pointer to parent element that owns this container.
*/
DwarfFunctionContainer::DwarfFunctionContainer(DwarfFile *file, DwarfBaseElement *elem) :
DwarfBaseContainer<DwarfFunction>(file, elem)
{
}
/**
* @brief Get all data from function DIE.
* @param die Function DIE.
* @param lvl Level (depth) of this die.
* @return Pointer to newly created data type object or nullptr if failed.
*/
DwarfFunction *DwarfFunctionContainer::loadAndGetDie(Dwarf_Die die, unsigned)
{
// Use special class to get attributes that we want.
AttrProcessor ap(m_parentFile->m_dbg, die, m_parentFile);
DwarfFunction *f = nullptr;
// If this has DW_AT_abstract_origin, then this is second part of some other declaration.
// Find first one and just actualize it. Otherwise create new function declaration.
// TODO: This expects that the first part without DW_AT_abstract_origin was already
// processed. I'm not sure if it is possible/common that second part is before first one.
Dwarf_Off ref = EMPTY_UNSIGNED;
ap.get(DW_AT_abstract_origin, ref);
if (ref == EMPTY_UNSIGNED)
ap.get(DW_AT_specification, ref);
if (ref != EMPTY_UNSIGNED)
{
f = static_cast<DwarfFunction*>( this->getElemByOffset(ref) );
if (f)
{
f->addOffset( ap.getDieOff() );
}
}
else if ( (f = static_cast<DwarfFunction*>( this->getElemByOffset( ap.getDieOff() )) ) )
{
// if (f)
// f->addOffset( ap.getDieOff() ); // adds the same offset for the second time?
// This will probably get function info for the second time, but it is not big problem.
}
else
{
const string *fileName = nullptr;
ap.get(DW_AT_decl_file, fileName);
f = new DwarfFunction(this, ap.getDieOff(), *fileName);
if (f != nullptr)
m_data.push_back(f);
}
if (f == nullptr)
{
DWARF_ERROR("Function was not found/created.");
return nullptr;
}
// We can not load directly to f->*, because if may overwrite already loaded values.
string name;
string linkName;
Dwarf_Addr low, high;
Dwarf_Unsigned line;
DwarfType *type;
DwarfLocationDesc *frame;
ap.get(DW_AT_name, name);
ap.get(DW_AT_linkage_name, linkName);
if (linkName.empty())
ap.get(DW_AT_MIPS_linkage_name, linkName);
if (linkName.empty())
ap.get(DW_AT_HP_linkage_name, linkName);
ap.get(DW_AT_low_pc, low);
ap.get(DW_AT_high_pc, high);
ap.get(DW_AT_decl_line, line);
ap.get(DW_AT_type, type);
ap.get(DW_AT_frame_base, frame);
if (name != EMPTY_STR) f->name = name;
if (linkName != EMPTY_STR)
{
f->linkageName = linkName;
if (f->name.empty())
f->name = linkName;
}
if (low != EMPTY_ADDR) f->lowAddr = low;
if (high != EMPTY_ADDR) f->highAddr = high;
if (line != EMPTY_UNSIGNED) f->line = line;
if (type != nullptr) f->type = type;
else f->type = m_parentFile->getTypes()->getVoid();
if (f->frameBase == nullptr && frame != nullptr)
{
f->frameBase = frame;
f->frameBase->setParent(f);
}
// Offset from low address.
if (f->highAddr < f->lowAddr)
f->highAddr += f->lowAddr;
// Set function as active.
// TODO: Functions with DW_AT_declaration attribute are skipped at the moment.
// For each such DIE there should be another one that defines function.
Dwarf_Bool isDeclr;
ap.get(DW_AT_declaration, isDeclr);
if (!isDeclr)
f->isDeclaration = false;
return f;
}
/**
* @brief Print contents of this container.
*/
void DwarfFunctionContainer::dump() const
{
cout << endl;
cout << "==================== Functions ====================" << endl;
DwarfBaseContainer<DwarfFunction>::dump();
cout << endl;
}
/**
* @brief Get function by its name.
* @param n Name of function to get.
* @return Pointer to function object if found, nullptr otherwise.
*/
DwarfFunction *DwarfFunctionContainer::getFunctionByName(string n)
{
for (iterator it=begin(); it!=end(); ++it)
{
if ((*it)->name == n)
return (*it);
}
return nullptr;
}
/**
* @brief ctor -- create local containers.
* @param prnt Pointer to parent container owning this element.
* @param o Original libdwarf DIE offset.
* @param n Reference to source file name where function is declared.
*/
DwarfFunction::DwarfFunction(DwarfFunctionContainer *prnt, Dwarf_Off o, const string &n) :
DwarfVar(reinterpret_cast<DwarfVarContainer*>(prnt), o, DwarfBaseElement::FUNCTION),
lowAddr(0),
highAddr(0),
line(0),
file(n),
frameBase(nullptr),
isVariadic(false),
isDeclaration(true),
isTemplateInstance(false),
isVariadicTemplateInstance(false),
isTemplateTemplateInstance(false),
m_vars(getParentFile(), this),
m_params(getParentFile(), this)
{
}
/**
* @brief dctor -- destroy local containers.
*/
DwarfFunction::~DwarfFunction()
{
delete frameBase;
}
/**
* @brief Print contents of this class.
*/
void DwarfFunction::dump() const
{
cout << "Function: \"" << name << "\" " << getDwarfdump2OffsetString() << endl;
cout << "\tLink name : " << linkageName << endl;
cout << "\tType : " << type->name << endl;
cout << "\tLine : " << dec << line << endl;
cout << "\tAddr. range : " << hex << lowAddr
<< " - " << highAddr << endl;
cout << "\tSrc. file : " << file << endl;
cout << endl;
cout << "\tParams cnt. : " << dec << m_params.size() << endl;
DwarfVarContainer::const_iterator iter = m_params.begin();
while (iter != m_params.end())
{
cout << "\t ";
(*iter)->dump();
++iter;
}
if (isVariadic)
cout << "\t ... variadic argument" << endl;
cout << endl;
cout << "\tVars cnt. : " << dec << m_vars.size() << endl;
iter = m_vars.begin();
while (iter != m_vars.end())
{
cout << "\t ";
(*iter)->dump();
++iter;
}
cout << endl;
}
/**
* @brief Test if function has local variables.
* @return True if function has local variables, false otherwise.
*/
bool DwarfFunction::hasVars() const
{
return (m_vars.size() != 0);
}
/**
* @brief Test if function has parameters.
* @return True if function has parameters, false otherwise.
*/
bool DwarfFunction::hasParams() const
{
return (m_params.size() != 0);
}
/**
* @brief Get local variables.
* @return Pointer to container of local variables.
*/
DwarfVarContainer *DwarfFunction::getVars()
{
return &m_vars;
}
/**
* @brief Get parameters.
* @return Pointer to container of parameters.
*/
DwarfVarContainer *DwarfFunction::getParams()
{
return &m_params;
}
/**
* @brief Get number of function's parameters.
* @return Number of functions parameters.
*/
std::size_t DwarfFunction::getParamCount() const
{
return m_params.size();
}
/**
* @brief Find out if this function has frame base.
* @return True if function has frame base, false otherwise.
*/
bool DwarfFunction::hasFrameBase() const
{
return (frameBase != nullptr);
}
/**
* @brief Compute and return value of function's frame base.
* @param n Pointer to string that will be filled by method.
* If location is address this is a name of address space.
* If location is register this is a name of register array.
* @param a Pointer to value that will be filled by method.
* If location is address this is an address in address space.
* If location is register this is a number in register array.
* @param pc Program counter value.
* @return Type of location - address or register.
* @note Frame base should be always address.
*/
DwarfLocationDesc::cLocType DwarfFunction::getFrameBase(string *n, Dwarf_Addr *a, Dwarf_Addr pc)
{
if (frameBase)
return (frameBase->computeLocation(n, a, pc));
else
return DwarfLocationDesc::FAIL;
}
} // namespace dwarfparser
} // namespace retdec

View File

@ -1,347 +0,0 @@
/**
* @file src/dwarfparser/dwarf_linenumbers.cpp
* @brief Implementation of classes representing linenumbers.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#include <iomanip>
#include <iostream>
#include <sstream>
#include "retdec/dwarfparser/dwarf_file.h"
#include "retdec/dwarfparser/dwarf_linenumbers.h"
using namespace std;
namespace retdec {
namespace dwarfparser {
/**
* @brief ctor.
* @param file Pointer to dwarfparser representation of DWARF file which owns this container.
* @param elem Pointer to parent element that owns this container.
*/
DwarfLineContainer::DwarfLineContainer(DwarfFile *file, DwarfBaseElement *elem) :
DwarfBaseContainer<DwarfLine>(file, elem)
{
m_srcFiles.push_back(EMPTY_STR);
}
/**
* @brief Get line number information from compilation unit DIE.
* @param cu_die Compilation unit DIE.
* @param lvl Level (depth) of this die.
* @return Loaded line element pointer or nullptr if some problem.
*/
DwarfLine *DwarfLineContainer::loadAndGetDie(Dwarf_Die cu_die, unsigned)
{
// Get all lines to buffer.
Dwarf_Signed lineCnt = 0;
Dwarf_Line *lineBuf = nullptr;
m_res = dwarf_srclines(cu_die, &lineBuf, &lineCnt, &m_error);
if (m_res == DW_DLV_NO_ENTRY)
{
return nullptr;
}
else if (m_res != DW_DLV_OK)
{
DWARF_ERROR(getDwarfError(m_error));
return nullptr;
}
// Iterate through lines and load each one of them.
for (int i=0; i<lineCnt; i++)
{
loadLine(lineBuf[i]);
}
dwarf_srclines_dealloc(m_parentFile->m_dbg, lineBuf, lineCnt);
return nullptr;
}
/**
* @brief Process one line number record.
* @param line Line to process.
*/
void DwarfLineContainer::loadLine(Dwarf_Line line)
{
// Address associated with line.
Dwarf_Addr addr = 0;
m_res = dwarf_lineaddr(line, &addr, &m_error);
if (m_res == DW_DLV_ERROR)
{
DWARF_ERROR(getDwarfError(m_error));
return;
}
if (m_res == DW_DLV_NO_ENTRY)
{
addr = EMPTY_ADDR;
}
// Source statement line number.
Dwarf_Unsigned lineno;
m_res = dwarf_lineno(line, &lineno, &m_error);
if (m_res == DW_DLV_ERROR)
{
DWARF_ERROR(getDwarfError(m_error));
return;
}
if (m_res == DW_DLV_NO_ENTRY)
{
lineno = EMPTY_UNSIGNED;
}
// Column number at which statement represented by line begins.
Dwarf_Unsigned column;
m_res = dwarf_lineoff_b(line, &column, &m_error);
if (m_res == DW_DLV_ERROR)
{
DWARF_ERROR(getDwarfError(m_error));
return;
}
if (m_res == DW_DLV_NO_ENTRY)
{
column = EMPTY_UNSIGNED;
}
// Name of src file where line occurs.
char *s = nullptr;
string f;
m_res = dwarf_linesrc(line, &s, &m_error);
if (m_res == DW_DLV_ERROR)
{
DWARF_ERROR(getDwarfError(m_error));
return;
}
if (m_res == DW_DLV_NO_ENTRY || s==nullptr)
f = EMPTY_STR;
else
f = s;
dwarf_dealloc(m_parentFile->m_dbg, s, DW_DLA_STRING);
// Is line marked as beginning of the statement?
Dwarf_Bool statBeg;
m_res = dwarf_linebeginstatement(line, &statBeg, &m_error);
if (m_res != DW_DLV_OK)
{
DWARF_ERROR(getDwarfError(m_error));
return;
}
// Is line marked as ending a text sequence?
Dwarf_Bool seqEnd;
m_res = dwarf_lineendsequence(line, &seqEnd, &m_error);
if (m_res != DW_DLV_OK)
{
DWARF_ERROR(getDwarfError(m_error));
return;
}
// Is line marked as not beginning basic block?
Dwarf_Bool basicBlockBeg;
m_res = dwarf_lineblock(line, &basicBlockBeg, &m_error);
if (m_res != DW_DLV_OK)
{
DWARF_ERROR(getDwarfError(m_error));
return;
}
Dwarf_Bool prologueEnd, epilogueBegin;
Dwarf_Unsigned isa, discriminator;
m_res = dwarf_prologue_end_etc(line, &prologueEnd, &epilogueBegin,
&isa, &discriminator, &m_error);
if (m_res != DW_DLV_OK)
{
DWARF_ERROR(getDwarfError(m_error));
return;
}
// Create line record.
DwarfLine *l = new DwarfLine(this, *findSrcFile(f));
l->lineNum = lineno;
l->addr = addr;
l->col = column;
if (statBeg) l->flags += DwarfLine::STAT_BEG;
if (seqEnd) l->flags += DwarfLine::SEQ_END;
if (basicBlockBeg) l->flags += DwarfLine::BASE_BLOCK_BEG;
if (prologueEnd) l->flags += DwarfLine::PROLOGUE_END;
if (epilogueBegin) l->flags += DwarfLine::EPILOGUE_BEGIN;
m_data.push_back(l);
}
/**
* @brief Find source file name and return pointer to it.
* If specified name is not in list yet, add it.
* @param f Source file name to find.
* @return Pointer to file name in list.
*/
string *DwarfLineContainer::findSrcFile(string f)
{
list<string>::iterator srcFilesIter = m_srcFiles.begin();
while (srcFilesIter != m_srcFiles.end())
{
if (*srcFilesIter == f)
{
return &(*srcFilesIter);
}
++srcFilesIter;
}
// If it gets here, no record was found.
m_srcFiles.push_back(f);
return &(m_srcFiles.back());
}
/**
* @brief Gets all addresses associated with particular line.
* @param file Name of source file where line occurs.
* @param line Source statement line number.
* @return Vector of addresses.
*/
vector <Dwarf_Addr> DwarfLineContainer::getAddrByLine(string file, Dwarf_Unsigned line)
{
vector <Dwarf_Addr> ret;
for (iterator it=begin(); it!=end(); ++it)
{
if (((*it)->name == file) &&
((*it)->lineNum == line))
{
ret.push_back((*it)->addr);
}
}
return ret;
}
/**
* @brief Gets line associated with particular addresses.
* @return Dwarfparser representation of line.
*/
DwarfLine *DwarfLineContainer::getLineByAddr(Dwarf_Addr addr)
{
for (iterator it=begin(); it!=end(); ++it)
{
if ((*it)->addr == addr)
return (*it);
}
return nullptr;
}
/**
* @brief Prints content of line number container.
* @note Debugging purposes.
*/
void DwarfLineContainer::dump() const
{
cout << endl;
cout << "==================== Lines ====================" << endl;
// Is empty?
if (m_data.empty())
{
cout << "NO line number information." << endl;
return;
}
// Header.
cout << setw(10) << right << "Line num";
cout << setw(12) << right << "Address";
cout << setw(10) << right << "Column";
cout << setw(8) << right << "Marks";
cout << " " << "Filename" << endl;
// Lines.
DwarfBaseContainer<DwarfLine>::dump();
// Explanation of marks meaning.
cout << endl << "Marks meaning:" << endl;
cout << "\tB - Line is marked as beginning of the statement." << endl;
cout << "\tE - Line is marked as ending a text sequence." << endl;
cout << "\tK - Line is marked as not beginning basic block." << endl;
cout << endl;
}
/**
* @brief ctor.
* @param prnt Pointer to parent container owning this element.
* @param n Reference to bame of source file where line occurs.
* @note There is no DIE offset for lines, this value is set to zero.
*/
DwarfLine::DwarfLine(DwarfLineContainer *prnt, const string &n) :
DwarfBaseElement(DwarfBaseElement::LINE, reinterpret_cast<DwarfBaseContainer<DwarfBaseElement>*>(prnt), 0),
lineNum(0),
addr(0),
col(0),
flags(EMPTY),
name(n)
{
}
/**
* @brief Print contents of this class.
*/
void DwarfLine::dump() const
{
string marks = " ";
if (isStatmentBeg())
marks[0] = 'B';
if (isSequenceEnd())
marks[1] = 'E';
if (isBasicBlockBeg())
marks[2] = 'K';
cout << setw(10) << right << dec << lineNum;
cout << setw(12) << right << hex << addr;
cout << setw(10) << right << dec << col;
cout << setw(8) << right << marks;
cout << " " << name << endl;
}
/**
* @brief Test if line is beginning a statment.
* @return True if line is beginning a statment, false otherwise.
*/
bool DwarfLine::isStatmentBeg() const
{
return (flags & STAT_BEG);
}
/**
* @brief Test if line is ending a text sequence.
* @return True if line is ending a text sequence, false otherwise.
*/
bool DwarfLine::isSequenceEnd() const
{
return (flags & SEQ_END);
}
/**
* @brief Test if line is beginning a basic block.
* @return True if line is beginning a basic block, false otherwise.
*/
bool DwarfLine::isBasicBlockBeg() const
{
return (flags & BASE_BLOCK_BEG); // TODO - reverse ?
}
} // namespace dwarfparser
} // namespace retdec

File diff suppressed because it is too large Load Diff

View File

@ -1,201 +0,0 @@
/**
* @file src/dwarfparser/dwarf_resources.cpp
* @brief Implementation of classes representing resources.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#include <iostream>
#include "retdec/dwarfparser/dwarf_resources.h"
using namespace std;
namespace retdec {
namespace dwarfparser {
/**
* @brief Print contents of this class.
*/
void DwarfResources::dump()
{
cout << endl;
cout << "==================== Resources ====================" << endl;
cout << endl;
cout << "Register mapping:" << endl;
const char *s0 = "Idx";
const char *s1 = "Dwarf num.";
const char *s2 = "Array num.";
const char *s3 = "Name";
printf("\t%4s %10s %10s %-30s\n", s0, s1, s2, s3);
unsigned idx = 0;
map<Dwarf_Half, RealReg>::iterator mIter;
for(mIter=m_regMaps.begin(); mIter!=m_regMaps.end(); ++mIter)
{
printf("\t%4d %10d %10d %-30s\n",
idx,
(*mIter).first,
(*mIter).second.arrayNum,
(*mIter).second.name.c_str()
);
idx++;
}
cout << endl;
}
/**
* @brief Gets DWARF register number and returns its content.
* @param n DWARF register number.
* @return value of the given register.
*/
Dwarf_Signed DwarfResources::getReg(Dwarf_Half n)
{
(void) n;
return EMPTY_SIGNED;
}
/**
* @brief Gets name of register array and number in register array and returns content of that register.
* @param name is a name of register array.
* @param number is a number in register array.
* @return value of the given register.
*/
Dwarf_Signed DwarfResources::getReg(std::string name, Dwarf_Addr number)
{
(void) name;
(void) number;
return EMPTY_SIGNED;
}
/**
* @brief Gets address and returns its content.
* @param a Address to get.
* @return Value on the given address.
* @note It use only one (always the first) address name space at the moment.
*/
Dwarf_Signed DwarfResources::getAddr(Dwarf_Addr a)
{
(void) a;
return EMPTY_SIGNED;
}
/**
* @brief Gets content of program counter register.
* @return Value of program counter.
*/
Dwarf_Addr DwarfResources::getPcReg()
{
return EMPTY_SIGNED;
}
/**
* @brief Gets DWARF register number and sets name of register array and
* its index number used in architecture.
* @param reg Register number used by DWARF.
* @param n Name of register array in architecture to set.
* @param a Index number of register in register array to set.
*/
void DwarfResources::setReg(Dwarf_Half reg, string *n, Dwarf_Addr *a)
{
map<Dwarf_Half, RealReg>::iterator iter;
iter = m_regMaps.find(reg);
if (iter == m_regMaps.end())
{
DWARF_ERROR("DwarfResources::setReg(): DWARF register num is not mapped to a register.");
}
else
{
RealReg rr = (*iter).second;
*n = rr.name;
*a = rr.arrayNum;
}
}
/**
* @brief Init mapping of DWARF register numbers to names using
* default -- well known mapping for architectures.
* @param m Architecture which default mapping will be used.
*/
void DwarfResources::initMappingDefault(eDefaultMap m)
{
switch (m)
{
//
// Mapping is the same as the one generated by compiler.
// MIPS-32.
//
case MIPS:
{
unsigned i = 0;
string general = "gpregs";
for (unsigned j=0; j<32; j++, i++)
m_regMaps[i] = RealReg(general, j);
// Mapping same as in files from compiler.
// But according to tests, fpu registers begin on number 32.
// Single precision.
string fpu_s = "fpuregs_s";
for (unsigned j=0; j<32; j++, i++)
m_regMaps[i] = RealReg(fpu_s, j);
// Double precision - on MIPS 32.
string fpu_d = "fpuregs_d";
i = 32;
for (unsigned j=0; j<16; j++, i=i+2)
{
m_regMaps[i+i+1] = RealReg(fpu_d, i-32);
}
break;
}
//
// Only first 16 general registers are mapped.
// Name of register array was taken from ARM semantics specification (resource_name record).
//
case ARM:
{
unsigned i;
string general = "regs";
for (i=0; i<16; i++)
m_regMaps[i] = RealReg(general, i);
m_regMaps[128] = RealReg("spsr", 0);
break;
}
//
// Only 8 general registers (32-bit) are mapped.
// Name of register array was taken from x86 semantics specification (resource_name record).
//
case X86:
{
unsigned i;
string general = "gp32";
for (i=0; i<8; i++)
m_regMaps[i] = RealReg(general, i);
break;
}
//
// Default.
//
default:
{
DWARF_ERROR("DwarfResources::initMappingDefault: unrecognized type of default mapping used.");
initMappingDefault(MIPS);
break;
}
}
}
} // namespace dwarfparser
} // namespace retdec

File diff suppressed because it is too large Load Diff

View File

@ -1,856 +0,0 @@
/**
* @file src/dwarfparser/dwarf_utils.cpp
* @brief Implementation of utility functions and classes.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#include <cstdlib>
#include "retdec/dwarfparser/dwarf_file.h"
#include "retdec/dwarfparser/dwarf_utils.h"
using namespace std;
namespace retdec {
namespace dwarfparser {
//
// Taken from dwarfdump2/print_die.cpp
//
static int get_form_values(Dwarf_Attribute attrib, Dwarf_Half & theform, Dwarf_Half & directform)
{
Dwarf_Error err = nullptr;
int res = dwarf_whatform(attrib, &theform, &err);
dwarf_whatform_direct(attrib, &directform, &err);
return res;
}
//
// Taken from dwarfdump2/print_die.cpp
//
/*
* This is a slightly simplistic rendering of the FORM
* issue, it is not precise. However it is really only
* here so we can detect and report an error (producing
* incorrect DWARF) by a particular compiler (a quite unusual error,
* noticed in April 2010).
* So this simplistic form suffices. See the libdwarf get_loclist_n()
* function source for the precise test.
*/
static bool is_location_form(int form)
{
if(form == DW_FORM_block1 ||
form == DW_FORM_block2 ||
form == DW_FORM_block4 ||
form == DW_FORM_block ||
form == DW_FORM_data4 ||
form == DW_FORM_data8 ||
form == DW_FORM_sec_offset) {
return true;
}
return false;
}
/**
* @brief Get address from attribute.
* @param attr Address class attribute.
* @return Address represented by the attribute.
*/
Dwarf_Addr getAttrAddr(Dwarf_Attribute attr)
{
Dwarf_Error error = nullptr;
Dwarf_Addr retVal = 0;
if (dwarf_formaddr(attr, &retVal, &error) == DW_DLV_OK)
{
return retVal;
}
else
{
DWARF_ERROR(getDwarfError(error));
return EMPTY_ADDR;
}
}
/**
* @brief Get value of the attribute.
* @param attr Constant class attribute.
* @return Value of the attrinute.
*/
Dwarf_Unsigned getAttrNumb(Dwarf_Attribute attr)
{
Dwarf_Error error = nullptr;
Dwarf_Unsigned uRetVal = 0;
if (dwarf_formudata(attr, &uRetVal, &error) == DW_DLV_OK)
{
return uRetVal;
}
Dwarf_Signed sRetVal = 0;
if (dwarf_formsdata(attr, &sRetVal, &error) == DW_DLV_OK)
{
return sRetVal;
}
DWARF_ERROR(getDwarfError(error));
return EMPTY_UNSIGNED;
}
/**
* @brief Get string from the attribute.
* @param attr String class attribute.
* @return String containing the value of the attribute.
*/
string getAttrStr(Dwarf_Attribute attr)
{
Dwarf_Error error = nullptr;
char *name = nullptr;
if (dwarf_formstring(attr, &name, &error) == DW_DLV_OK)
{
return string(name);
}
else
{
DWARF_ERROR(getDwarfError(error));
return EMPTY_STR;
}
}
/**
* @brief Get reference from the attribute.
* @param attr Reference class attribute.
* @return Offset represented by the attribute.
*/
Dwarf_Off getAttrRef(Dwarf_Attribute attr)
{
Dwarf_Error error = nullptr;
Dwarf_Off retVal;
if (dwarf_formref(attr, &retVal, &error) == DW_DLV_OK)
{
return retVal;
}
else
{
DWARF_ERROR(getDwarfError(error));
return EMPTY_OFF;
}
}
/**
* @brief Get global reference from the attribute.
* @param attr Reference or other section-references class
* attribute.
* @return Global offset represented by the attribute.
*/
Dwarf_Off getAttrGlobalRef(Dwarf_Attribute attr)
{
Dwarf_Error error = nullptr;
Dwarf_Off retVal;
if (dwarf_global_formref(attr, &retVal, &error) == DW_DLV_OK)
{
return retVal;
}
else
{
DWARF_ERROR(getDwarfError(error));
return EMPTY_OFF;
}
}
/**
* @brief Get flag from the attribute.
* @param attr Attribute.
* @return True if attribute has a non-zero value, else false.
*/
Dwarf_Bool getAttrFlag(Dwarf_Attribute attr)
{
Dwarf_Error error = nullptr;
Dwarf_Bool retVal;
if (dwarf_formflag(attr, &retVal, &error) == DW_DLV_OK)
{
return retVal;
}
else
{
DWARF_ERROR(getDwarfError(error));
return false;
}
}
/**
* @brief Get block from the attribute.
* @param attr Block class attribute.
* @return Pointer to block structure represented by the attribute,
*/
Dwarf_Block *getAttrBlock(Dwarf_Attribute attr)
{
Dwarf_Error error = nullptr;
Dwarf_Block *retVal = nullptr;
if (dwarf_formblock(attr, &retVal, &error) == DW_DLV_OK)
{
return retVal;
}
else
{
DWARF_ERROR(getDwarfError(error));
return nullptr;
}
}
/**
* @brief Get 8 byte signature from the attribute.
* @param attr Attribute of DW_FORM_ref_sig8 form.
* @return 8 byte signature represented by the attribute.
*/
Dwarf_Sig8 getAttrSig(Dwarf_Attribute attr)
{
Dwarf_Error error = nullptr;
Dwarf_Sig8 retVal;
if (dwarf_formsig8(attr, &retVal, &error) == DW_DLV_OK)
{
return retVal;
}
else
{
DWARF_ERROR(getDwarfError(error));
return Dwarf_Sig8();
}
}
/**
* @brief Gets length of the location expression and pointer to
* the bytes of the location expression from the attribute.
* @param attr Attribute of DW_FORM_exprloc form.
* @param exprlen Pointer to location expression length to set.
* @param ptr Pointer to location expression pointer to set.
*/
void getAttrExprLoc(Dwarf_Attribute attr, Dwarf_Unsigned *exprlen,
Dwarf_Ptr *ptr)
{
Dwarf_Error error = nullptr;
if (dwarf_formexprloc(attr, exprlen, ptr, &error) != DW_DLV_OK)
{
DWARF_ERROR(getDwarfError(error));
// non-recoverable -- exit(1) ???
}
}
/**
* @brief Gets libdwarf error message to provided error code.
* @param error Error code.
* @return Error message as strings.
*/
string getDwarfError(Dwarf_Error &error)
{
return string(dwarf_errmsg(error));
}
/**
* @brief Gets DIE from provided offset.
* @param dbg Debug file.
* @param off Offset.
* @param die Found die.
* @return True if success, false otherwise.
*/
bool getDieFromOffset(Dwarf_Debug dbg, Dwarf_Off off, Dwarf_Die &die)
{
bool is_info = true;
Dwarf_Error error;
int res = dwarf_offdie_b(dbg, off, is_info, &die, &error);
if (res == DW_DLV_ERROR)
{
DWARF_ERROR(getDwarfError(error));
return false;
}
if (res == DW_DLV_NO_ENTRY)
{
return false;
}
return true;
}
/**
* @brief ctor -- initialize class with DIE which attributes will be processed.
* @param dbg Libdwarf structure representing DWARF file.
* @param die Source DIE which atributes will be processed.
* @param parent Parent dwarfparser representation of DWARF file.
*/
AttrProcessor::AttrProcessor(Dwarf_Debug dbg, Dwarf_Die die, DwarfFile *parent) :
m_dbg(dbg),
m_die(die),
m_parent(parent),
m_res(DW_DLV_OK),
m_error(nullptr)
{
}
/**
* @brief Get offset of source DIE.
* @return DIE offset.
*/
Dwarf_Off AttrProcessor::getDieOff()
{
Dwarf_Off offset;
if (dwarf_dieoffset(m_die, &offset, &m_error) != DW_DLV_OK)
{
DWARF_ERROR(getDwarfError(m_error));
return EMPTY_OFF;
}
return offset;
}
/**
* @brief Get attribute value from source DIE and return it in.
* @param attrCode Attribute code to get.
* @param ret Pointer to return value which will be filled with result.
* Caller must provide pointer to expected data type.
* @return True if specified attribute was found, false otherwise.
* @note
* AttrCodes in switch are not in alphabetical order,
* codes are grouped based on mechanism of getting attr values.
* But codes inside one group should by ordered alphabetically,
* so if you are adding some, place it in correct place here and
* in getEmpty() method as well.
*
* TODO: because it may be called at already initialized member of some object, it
* will rewrite (getEmpty) this member if attr not found for the second time:
* DW_AT_abstract_origin in functions, DW_AT_specification in types, ...
* It would be better to refactorize all work with this function, all ret must by initialized
* to empty value before call and there will be no getEmpty() function, if attr not found,
* ret wont be changed -- default empty value if not processed yet, previous value if already
* found and processed.
*/
bool AttrProcessor::get(Dwarf_Half attrCode, std::string& ret)
{
ret = EMPTY_STR;
Dwarf_Attribute attr;
m_res = dwarf_attr(m_die, attrCode, &attr, &m_error);
if (m_res != DW_DLV_OK)
{
if (m_res == DW_DLV_ERROR)
DWARF_ERROR(getDwarfError(m_error));
return false;
}
bool r = true;
switch (attrCode)
{
case DW_AT_comp_dir:
case DW_AT_linkage_name:
case DW_AT_MIPS_linkage_name:
case DW_AT_HP_linkage_name:
case DW_AT_name:
case DW_AT_producer:
{
ret = getAttrStr(attr);
break;
}
default:
{
r = false;
}
}
dwarf_dealloc(m_dbg, attr, DW_DLA_ATTR);
return r;
}
bool AttrProcessor::get(Dwarf_Half attrCode, const std::string* &ret)
{
ret = &EMPTY_STR;
Dwarf_Attribute attr;
m_res = dwarf_attr(m_die, attrCode, &attr, &m_error);
if (m_res != DW_DLV_OK)
{
if (m_res == DW_DLV_ERROR)
DWARF_ERROR(getDwarfError(m_error));
return false;
}
bool r = true;
switch (attrCode)
{
case DW_AT_decl_file:
{
Dwarf_Unsigned fileNum = getAttrNumb(attr);
DwarfCU *lastCU = m_parent->m_activeCU;
if(lastCU &&
(fileNum > 0) &&
(lastCU->srcFilesCount() > (fileNum-1)))
{
ret = lastCU->getSrcFile(fileNum-1);
}
else
{
r = false;
}
break;
}
default:
{
r = false;
}
}
dwarf_dealloc(m_dbg, attr, DW_DLA_ATTR);
return r;
}
bool AttrProcessor::get(Dwarf_Half attrCode, Dwarf_Signed& ret)
{
ret = EMPTY_SIGNED;
Dwarf_Attribute attr;
m_res = dwarf_attr(m_die, attrCode, &attr, &m_error);
if (m_res != DW_DLV_OK)
{
if (m_res == DW_DLV_ERROR)
DWARF_ERROR(getDwarfError(m_error));
return false;
}
bool r = true;
switch (attrCode)
{
case DW_AT_const_value: // !!! block, constant, string
{
ret = getAttrNumb(attr);
break;
}
default:
{
r = false;
}
}
dwarf_dealloc(m_dbg, attr, DW_DLA_ATTR);
return r;
}
bool AttrProcessor::get(Dwarf_Half attrCode, Dwarf_Unsigned& ret)
{
ret = EMPTY_UNSIGNED;
Dwarf_Attribute attr;
m_res = dwarf_attr(m_die, attrCode, &attr, &m_error);
if (m_res != DW_DLV_OK)
{
if (m_res == DW_DLV_ERROR)
DWARF_ERROR(getDwarfError(m_error));
return false;
}
bool r = true;
switch (attrCode)
{
case DW_AT_low_pc:
{
ret = getAttrAddr(attr);
break;
}
case DW_AT_high_pc:
{
Dwarf_Half theform;
dwarf_whatform(attr,&theform,&m_error);
if (theform == DW_FORM_addr)
ret = getAttrAddr(attr); // address class
else
ret = getAttrNumb(attr); // constant class - offset from low
break;
}
case DW_AT_abstract_origin:
case DW_AT_sibling:
case DW_AT_specification:
{
ret = getAttrGlobalRef(attr);
break;
}
case DW_AT_ordering:
case DW_AT_byte_size: // !!! constant, exprloc, reference
case DW_AT_bit_offset: // !!! constant, exprloc, reference
case DW_AT_bit_size: // !!! constant, exprloc, reference
case DW_AT_language:
case DW_AT_discr_value:
case DW_AT_visibility:
case DW_AT_const_value: // !!! block, constant, string
case DW_AT_inline:
case DW_AT_upper_bound: // !!! constant, exprloc, reference
case DW_AT_accessibility:
case DW_AT_address_class:
case DW_AT_calling_convention:
case DW_AT_decl_column:
//case DW_AT_decl_file: // !!! implemented below
case DW_AT_decl_line:
case DW_AT_encoding:
case DW_AT_identifier_case:
case DW_AT_virtuality:
case DW_AT_call_column:
case DW_AT_call_file:
case DW_AT_call_line:
case DW_AT_binary_scale:
case DW_AT_decimal_scale:
case DW_AT_decimal_sign:
case DW_AT_digit_count:
case DW_AT_endianity:
case DW_AT_data_bit_offset:
{
ret = getAttrNumb(attr);
break;
}
default:
{
r = false;
}
}
dwarf_dealloc(m_dbg, attr, DW_DLA_ATTR);
return r;
}
bool AttrProcessor::get(Dwarf_Half attrCode, Dwarf_Bool& ret)
{
ret = false;
Dwarf_Attribute attr;
m_res = dwarf_attr(m_die, attrCode, &attr, &m_error);
if (m_res != DW_DLV_OK)
{
if (m_res == DW_DLV_ERROR)
DWARF_ERROR(getDwarfError(m_error));
return false;
}
bool r = true;
switch (attrCode)
{
case DW_AT_is_optional:
case DW_AT_prototyped:
case DW_AT_artificial:
case DW_AT_declaration:
case DW_AT_external:
case DW_AT_variable_parameter:
case DW_AT_use_UTF8:
case DW_AT_mutable:
case DW_AT_threads_scaled:
case DW_AT_explicit:
case DW_AT_elemental:
case DW_AT_pure:
case DW_AT_recursive:
case DW_AT_main_subprogram:
case DW_AT_const_expr:
case DW_AT_enum_class:
{
ret = getAttrFlag(attr);
break;
}
default:
{
r = false;
}
}
dwarf_dealloc(m_dbg, attr, DW_DLA_ATTR);
return r;
}
bool AttrProcessor::get(Dwarf_Half attrCode, DwarfLocationDesc* &ret)
{
ret = nullptr;
Dwarf_Attribute attr;
m_res = dwarf_attr(m_die, attrCode, &attr, &m_error);
if (m_res != DW_DLV_OK)
{
if (m_res == DW_DLV_ERROR)
DWARF_ERROR(getDwarfError(m_error));
return false;
}
bool r = true;
switch (attrCode)
{
case DW_AT_location:
case DW_AT_data_member_location:
case DW_AT_frame_base:
{
ret = new DwarfLocationDesc();
Dwarf_Half theform = 0;
Dwarf_Half directform = 0;
get_form_values(attr, theform, directform);
// Location form - original form working on ARM, MIPS.
if (is_location_form(theform))
{
Dwarf_Locdesc **locs; // list of location descriptions
Dwarf_Signed cnt; // number of list records
m_res = dwarf_loclist_n(attr, &locs, &cnt, &m_error);
if (m_res != DW_DLV_OK)
{
delete ret;
ret = nullptr;
return false;
}
// List of expressions.
for (int i=0; i<cnt; i++)
{
DwarfLocationDesc::Expression e;
e.lowAddr = locs[i]->ld_lopc;
e.highAddr = locs[i]->ld_hipc;
// List of atoms in one expression.
for (int j=0; j<locs[i]->ld_cents;j++)
{
Dwarf_Loc *atom = &(locs[i]->ld_s[j]);
DwarfLocationDesc::Atom a;
a.opcode = atom->lr_atom;
a.op1 = atom->lr_number;
a.op2 = atom->lr_number2;
a.off = atom->lr_offset;
e.atoms.push_back(a);
}
ret->addExpr(e);
dwarf_dealloc(m_dbg, locs[i]->ld_s, DW_DLA_LOC_BLOCK);
dwarf_dealloc(m_dbg, locs[i], DW_DLA_LOCDESC);
}
dwarf_dealloc(m_dbg, locs, DW_DLA_LIST);
}
// Expression location - occured on x86.
else if (theform == DW_FORM_exprloc)
{
// Get expression location pointer.
Dwarf_Unsigned retExprLen; // Length of location expression.
Dwarf_Ptr blockPtr = nullptr; // Pointer to location expression.
m_res = dwarf_formexprloc(attr, &retExprLen, &blockPtr, &m_error);
if (m_res != DW_DLV_OK)
{
if (m_res == DW_DLV_ERROR)
{
DWARF_ERROR("dwarf_formexprloc() error.");
}
delete ret;
ret = nullptr;
return false;
}
// Get address size.
Dwarf_Half addrSize = 0;
m_res = dwarf_get_die_address_size(m_die, &addrSize, &m_error);
if (m_res != DW_DLV_OK)
{
delete ret;
ret = nullptr;
return false;
}
// Get list of location descriptors -- only one location expression.
Dwarf_Locdesc *loc = nullptr;
Dwarf_Signed cnt;
m_res = dwarf_loclist_from_expr_a(m_dbg,
blockPtr,
retExprLen,
addrSize,
&loc,
&cnt, // should be set to 1.
&m_error);
if (m_res != DW_DLV_OK) {
delete ret;
ret = nullptr;
return false;
}
// Copy single location to higher representation.
DwarfLocationDesc::Expression e;
e.lowAddr = loc->ld_lopc;
e.highAddr = loc->ld_hipc;
// List of atoms in one expression.
for (int j=0; j<loc->ld_cents;j++)
{
Dwarf_Loc *atom = &(loc->ld_s[j]);
DwarfLocationDesc::Atom a;
a.opcode = atom->lr_atom;
a.op1 = atom->lr_number;
a.op2 = atom->lr_number2;
a.off = atom->lr_offset;
e.atoms.push_back(a);
}
ret->addExpr(e);
dwarf_dealloc(m_dbg, loc->ld_s, DW_DLA_LOC_BLOCK);
dwarf_dealloc(m_dbg, loc, DW_DLA_LOCDESC);
}
//
else if (theform == DW_FORM_data1 ||
theform == DW_FORM_data2 ||
theform == DW_FORM_data4 ||
theform == DW_FORM_data8)
{
// TODO: dwarf-cpp-test: DW_AT_data_member_location:
// tu by to chcelo vratit konstantu a nie location,
// data member su vacsinou aj tak hodnoty a nie vyrazy.
//
//Dwarf_Unsigned *num = (Dwarf_Unsigned*) ret
//*num = getAttrNumb(attr)
break;
}
// Bad attribute form.
else
{
DWARF_ERROR("Attribute form error: " << hex << attrCode << " : " << theform);
delete ret;
ret = nullptr;
return false;
}
break;
}
default:
{
r = false;
}
}
dwarf_dealloc(m_dbg, attr, DW_DLA_ATTR);
return r;
}
bool AttrProcessor::get(Dwarf_Half attrCode, DwarfType* &ret)
{
ret = m_parent->getTypes()->getVoid();
Dwarf_Attribute attr;
m_res = dwarf_attr(m_die, attrCode, &attr, &m_error);
if (m_res != DW_DLV_OK)
{
if (m_res == DW_DLV_ERROR)
DWARF_ERROR(getDwarfError(m_error));
return false;
}
bool r = true;
switch (attrCode)
{
case DW_AT_type:
{
Dwarf_Off typeRef = getAttrGlobalRef(attr);
Dwarf_Die typeDie;
m_res = dwarf_offdie_b(m_dbg, typeRef, is_info, &typeDie, &m_error);
if (m_res == DW_DLV_ERROR)
{
DWARF_ERROR(getDwarfError(m_error));
return false;
}
if (m_res == DW_DLV_NO_ENTRY)
{
return false;
}
ret = m_parent->getTypes()->loadAndGetDie(typeDie, 0);
if (ret == nullptr)
{
ret = m_parent->getTypes()->getVoid();
return false;
}
break;
}
default:
{
r = false;
}
}
dwarf_dealloc(m_dbg, attr, DW_DLA_ATTR);
return r;
}
bool AttrProcessor::geti(Dwarf_Half attrCode, int& ret)
{
ret = 0;
Dwarf_Attribute attr;
m_res = dwarf_attr(m_die, attrCode, &attr, &m_error);
if (m_res != DW_DLV_OK)
{
if (m_res == DW_DLV_ERROR)
DWARF_ERROR(getDwarfError(m_error));
return false;
}
bool r = true;
switch (attrCode)
{
case DW_AT_type:
{
Dwarf_Off typeRef = getAttrGlobalRef(attr);
Dwarf_Die typeDie;
m_res = dwarf_offdie_b(m_dbg, typeRef, is_info, &typeDie, &m_error);
if (m_res == DW_DLV_ERROR)
{
DWARF_ERROR(getDwarfError(m_error));
return false;
}
if (m_res == DW_DLV_NO_ENTRY)
{
return false;
}
ret = m_parent->getTypes()->getDieFlags(typeDie, 0);
break;
}
default:
{
r = false;
}
}
dwarf_dealloc(m_dbg, attr, DW_DLA_ATTR);
return r;
}
} // namespace dwarfparser
} // namespace retdec

View File

@ -1,326 +0,0 @@
/**
* @file src/dwarfparser/dwarf_vars.cpp
* @brief Implementataion of classes representing variables.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/
#include <iomanip>
#include <iostream>
#include "retdec/dwarfparser/dwarf_file.h"
#include "retdec/dwarfparser/dwarf_functions.h"
#include "retdec/dwarfparser/dwarf_vars.h"
using namespace std;
namespace retdec {
namespace dwarfparser {
/**
* @brief ctor.
* @param file Pointer to dwarfparser representation of DWARF file which owns this container.
* @param elem Pointer to parent element that owns this container.
*/
DwarfVarContainer::DwarfVarContainer(DwarfFile *file, DwarfBaseElement *elem) :
DwarfBaseContainer<DwarfVar>(file, elem)
{
}
/**
* @brief Print contents of this container.
*/
void DwarfVarContainer::dump() const
{
cout << endl;
cout << "==================== Variables ====================" << endl;
// Is Empty?
if (m_data.empty())
{
cout << "NO variable information." << endl;
return;
}
// Header.
cout << setw(30) << left << "Variable name";
cout << setw(25) << left << "Variable type name";
cout << setw(20) << left << "Flags" << endl;
// Variables.
DwarfBaseContainer<DwarfVar>::dump();
cout << endl;
}
/**
* @brief Get all data from function DIE.
* @param die Function DIE.
* @param lvl Level (depth) of this die.
* @return Pointer to variable object if found, nullptr otherwise.
*/
DwarfVar *DwarfVarContainer::loadAndGetDie(Dwarf_Die die, unsigned)
{
// Use special class to get attributes that we want.
AttrProcessor ap(m_parentFile->m_dbg, die, m_parentFile);
// TODO: Variables with DW_AT_declaration attribute are skipped at the moment.
// These DIEs do not contain DW_AT_location attribute.
// For each such DIE there should be another one that defines variable and
// contains location.
Dwarf_Bool isDeclr;
ap.get(DW_AT_declaration, isDeclr);
if (isDeclr)
return nullptr;
// TODO: Variables with DW_AT_abstract_origin are skipped at them moment.
// They are inline instances of inline subprograms.
// They mess-up subprogram parameters.
Dwarf_Off ref = EMPTY_UNSIGNED;
ap.get(DW_AT_abstract_origin, ref);
if (ref != EMPTY_UNSIGNED)
return nullptr;
DwarfVar *v = new DwarfVar(this, ap.getDieOff());
ap.get(DW_AT_name, v->name);
ap.get(DW_AT_type, v->type);
ap.geti(DW_AT_type, v->flags);
ap.get(DW_AT_location, v->location);
if (v->location)
{
v->location->setParent(v);
if (m_parentElem != nullptr)
{
if (dynamic_cast<DwarfFunctionType*>(m_parentElem))
{
// no frame base
}
else if (DwarfFunction *f = dynamic_cast<DwarfFunction*>(m_parentElem))
{
v->location->setBaseFunc(f);
}
else
{
DWARF_WARNING("loadDie(): Unable to set frame base for variable: \"" << v->name << "\".");
}
}
}
Dwarf_Half tag = 0;
dwarf_tag(die, &tag, &m_error);
if (tag == DW_TAG_variable)
{
m_data.push_back(v);
return v;
}
else if (tag == DW_TAG_formal_parameter)
{
return addParameter(v);
}
else
{
DWARF_ERROR("Unexpected tag.");
return nullptr;
}
}
/**
* @brief Get variable by its name.
* @param n Name of variable to get.
* @return Pointer to variable object if found, nullptr otherwise.
*/
DwarfVar *DwarfVarContainer::getVarByName(string n)
{
for (iterator it=begin(); it!=end(); ++it)
{
if ((*it)->name == n)
{
return (*it);
}
}
return nullptr;
}
/**
* @brief Add parameter co container. Check if it has unique name.
* @param n Parameter to add.
* @return Added parameter or existing one.
*
* TODO: podla mena to nie je 100%, v jednom DIE nemusi byt meno nastavene.
* V jednom samplu sa dali unikatne prepojit podla DW_AT_decl_file + DW_AT_decl_line.
* neviem ale ci je toto nastaven vzdy, ideal by bolo kontextove nacitanie, ktore by vedelo
* ku ktorej funkcii parameter partri, ktory v poradi je a ak by na tom indexe uz nieco
* existovalo tak by sa to len aktualizovalo a nevytvaralo nove.
*/
DwarfVar *DwarfVarContainer::addParameter(DwarfVar *n)
{
if (n == nullptr)
return n;
for (iterator it=begin(); it!=end(); ++it)
{
// not empty -> params for DW_TAG_subroutine_type do not have names,
// this may cause some other problems.
//
if (!n->name.empty() && (*it)->name == n->name)
{
(*it)->mergeWith(n);
delete n;
return (*it);
}
}
m_data.push_back(n);
return n;
}
/**
* @brief ctor.
* @param prnt Pointer to parent container owning this element.
* @param off Offset associated with this element in DWARF file - unique ID.
* @param t Type of DwarfBaseElement object.
*/
DwarfVar::DwarfVar(DwarfVarContainer *prnt, Dwarf_Off off,
DwarfBaseElement::type_t t) :
DwarfBaseElement(t, reinterpret_cast<DwarfBaseContainer<DwarfBaseElement>*>(prnt), off),
flags(EMPTY),
type(nullptr),
location(nullptr)
{
}
/**
* @brief dctor.
*/
DwarfVar::~DwarfVar()
{
delete location;
}
/**
* @brief Print contents of this class.
*/
void DwarfVar::dump() const
{
string f;
if (isConstant())
f += " Const. ";
if (isPointer())
f += " Ptr. ";
if (isRestrict())
f += " Rest. ";
if (isVolatile())
f += " Volat. ";
cout << setw(30) << left << name;
cout << setw(25) << left << type->name;
cout << setw(20) << left << f;
cout << getDwarfdump2OffsetString() << endl;
}
/**
* @brief Merge this variable with the provided one.
* Members that are not set in this are set from other.
* @param o Other variable.
*/
void DwarfVar::mergeWith(DwarfVar *o)
{
if (name.empty()) name = o->name;
if (flags == EMPTY) flags = o->flags;
if (type == nullptr) type = o->type;
if (location == nullptr) { location = o->location; o->location = nullptr; }
}
/**
* @brief Some variables may not have locations.
* @return True if this variable has location, false otherwise.
*/
bool DwarfVar::hasLocation()
{
return (location != nullptr);
}
/**
* @brief Compute location of variable.
* @param n Pointer to string that will be filled by method.
* If variable location is address this is a name of address space.
* If variable location is register this is a name of register array.
* @param a Pointer to value that will be filled by method.
* If variable location is address this is an address in address space.
* If variable location is register this is a number in register array.
* @param pc Program counter value. Does not need to be specified if resources was
* initialized.
* @return Type of variable location - address or register.
*/
DwarfLocationDesc::cLocType DwarfVar::getLocation(string *n, Dwarf_Addr *a, Dwarf_Addr pc)
{
if (location)
return (location->computeLocation(n, a, pc));
else
return DwarfLocationDesc::FAIL;
}
/**
* @brief If variable is on stack, get its offset from stack pointer;
* @param a Pointer to offset that will be filled by method.
* If variable is not on stack it will be set to zero.
* @param deref Pointer to boolean value that will be filled by method.
* If true then on address counted using returned offset is an
* address of variable data.
* If false then there are actual data on counted address.
* If variable is not on stack it will be set to false.
* @param pc Actual program counter.
* @param regNum Register number.
* @return True if variable on stack, false otherwise.
*/
bool DwarfVar::isOnStack(Dwarf_Signed *a, bool *deref, Dwarf_Addr pc, int *regNum)
{
if (location)
return location->isOnStack(a, deref, pc, regNum);
else
return false;
}
/**
* @brief Test if variable is a constant.
* @return True if variable is a constant, false otherwise.
*/
bool DwarfVar::isConstant() const
{
return (flags & CONSTANT);
}
/**
* @brief Test if variable is a pointer.
* @return True if variable is a pointer, false otherwise.
*/
bool DwarfVar::isPointer() const
{
return (flags & POINTER);
}
/**
* @brief Test if variable is restrict.
* @return True if variable is restrict, false otherwise.
*/
bool DwarfVar::isRestrict() const
{
return (flags & RESTRICT);
}
/**
* @brief Test if variable is volatile.
* @return True if variable is volatile, false otherwise.
*/
bool DwarfVar::isVolatile() const
{
return (flags & VOLATILE);
}
} // namespace dwarfparser
} // namespace retdec