diff --git a/recipes/libelfin/all/CMakeLists.txt b/recipes/libelfin/all/CMakeLists.txt new file mode 100644 index 0000000000000..eb2aa34b81ac8 --- /dev/null +++ b/recipes/libelfin/all/CMakeLists.txt @@ -0,0 +1,77 @@ +cmake_minimum_required(VERSION 3.1) +project(libelfin CXX) + +include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) +conan_basic_setup() + +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 11) +endif() +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(PythonInterp 3 REQUIRED) + +file(GLOB_RECURSE elf_sources source_subfolder/elf/*.cc) +set(elf_headers + source_subfolder/elf/common.hh + source_subfolder/elf/data.hh + source_subfolder/elf/elf++.hh) +file(GLOB_RECURSE dwarf_sources source_subfolder/dwarf/*.cc) +set(dwarf_headers + source_subfolder/dwarf/data.hh + source_subfolder/dwarf/dwarf++.hh + source_subfolder/dwarf/small_vector.hh) + +add_custom_command( + OUTPUT source_subfolder/elf/to_string.cc + COMMAND ${CMAKE_COMMAND} -E echo '// Automatically generated' > to_string.cc + COMMAND ${CMAKE_COMMAND} -E echo '// DO NOT EDIT' >> to_string.cc + COMMAND ${CMAKE_COMMAND} -E echo >> to_string.cc + COMMAND ${CMAKE_COMMAND} -E echo '\#include \"data.hh\"' >> to_string.cc + COMMAND ${CMAKE_COMMAND} -E echo '\#include \"to_hex.hh\"' >> to_string.cc + COMMAND ${CMAKE_COMMAND} -E echo >> to_string.cc + COMMAND ${CMAKE_COMMAND} -E echo 'ELFPP_BEGIN_NAMESPACE' >> to_string.cc + COMMAND ${CMAKE_COMMAND} -E echo >> to_string.cc + COMMAND ${PYTHON_EXECUTABLE} enum-print.py -u --hex --no-type --mask shf --mask pf -x loos -x hios -x loproc -x hiproc < data.hh >> to_string.cc + COMMAND ${CMAKE_COMMAND} -E echo 'ELFPP_END_NAMESPACE' >> to_string.cc + DEPENDS source_subfolder/elf/enum-print.py source_subfolder/elf/data.hh + WORKING_DIRECTORY source_subfolder/elf) + +add_custom_command( + OUTPUT source_subfolder/dwarf/to_string.cc + COMMAND ${CMAKE_COMMAND} -E echo '// Automatically generated' > to_string.cc + COMMAND ${CMAKE_COMMAND} -E echo '// DO NOT EDIT' >> to_string.cc + COMMAND ${CMAKE_COMMAND} -E echo >> to_string.cc + COMMAND ${CMAKE_COMMAND} -E echo '\#include \"internal.hh\"' >> to_string.cc + COMMAND ${CMAKE_COMMAND} -E echo >> to_string.cc + COMMAND ${CMAKE_COMMAND} -E echo 'DWARFPP_BEGIN_NAMESPACE' >> to_string.cc + COMMAND ${CMAKE_COMMAND} -E echo >> to_string.cc + COMMAND ${PYTHON_EXECUTABLE} ../elf/enum-print.py < dwarf++.hh >> to_string.cc + COMMAND ${PYTHON_EXECUTABLE} ../elf/enum-print.py -s _ -u --hex -x hi_user -x lo_user < data.hh >> to_string.cc + COMMAND ${CMAKE_COMMAND} -E echo 'DWARFPP_END_NAMESPACE' >> to_string.cc + DEPENDS source_subfolder/elf/enum-print.py source_subfolder/dwarf/data.hh + WORKING_DIRECTORY source_subfolder/dwarf) + +add_library(elf++ ${elf_sources} source_subfolder/elf/to_string.cc) +set_target_properties(elf++ PROPERTIES + PUBLIC_HEADER "${elf_headers}" + VERSION ${CONAN_PACKAGE_VERSION}) + +add_library(dwarf++ ${dwarf_sources} source_subfolder/dwarf/to_string.cc) +set_target_properties(dwarf++ PROPERTIES + PUBLIC_HEADER "${dwarf_headers}" + VERSION ${CONAN_PACKAGE_VERSION}) + +include(GNUInstallDirs) +install(TARGETS elf++ + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libelfin/elf) +install(TARGETS dwarf++ + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libelfin/dwarf) + +install(FILES source_subfolder/LICENSE DESTINATION licenses) diff --git a/recipes/libelfin/all/conandata.yml b/recipes/libelfin/all/conandata.yml new file mode 100644 index 0000000000000..147f188cac1b2 --- /dev/null +++ b/recipes/libelfin/all/conandata.yml @@ -0,0 +1,8 @@ +sources: + "0.3": + url: "https://github.com/aclements/libelfin/archive/v0.3.tar.gz" + sha256: "c338942b967582922b3514b54b93175ca9051a9668db92dd8ef619824d443ac7" +patches: + "0.3": + - patch_file: "patches/commit-9d0db16d0a0b3c4f8aaa60a3e4dab295df34b6b2.patch" + base_path: "source_subfolder" diff --git a/recipes/libelfin/all/conanfile.py b/recipes/libelfin/all/conanfile.py new file mode 100644 index 0000000000000..d53acbbfd0abe --- /dev/null +++ b/recipes/libelfin/all/conanfile.py @@ -0,0 +1,64 @@ +import os +from conans import ConanFile, CMake, tools +from conans.errors import ConanInvalidConfiguration + + +class LibelfinConan(ConanFile): + name = "libelfin" + description = "C++11 library for reading ELF binaries and DWARFv4 debug information" + url = "https://github.com/conan-io/conan-center-index" + homepage = "https://github.com/aclements/libelfin" + license = "MIT" + topics = ("conan", "elf", "dwarf", "libelfin") + + settings = "os", "arch", "compiler", "build_type" + options = {"shared": [True, False], "fPIC": [True, False]} + default_options = {"shared": False, "fPIC": True} + + exports_sources = "CMakeLists.txt", "patches/*" + generators = "cmake" + + _cmake = None + _source_subfolder = "source_subfolder" + + def config_options(self): + if self.settings.os == "Windows": + del self.options.fPIC + + def configure(self): + if self.settings.compiler == "Visual Studio": + raise ConanInvalidConfiguration("libelfin doesn't support compiler: {} on OS: {}.". + format(self.settings.compiler, self.settings.os)) + if self.options.shared: + del self.options.fPIC + if self.settings.compiler.cppstd: + tools.check_min_cppstd(self, "11") + + def source(self): + tools.get(**self.conan_data["sources"][self.version]) + extracted_dir = self.name + "-" + self.version + os.rename(extracted_dir, self._source_subfolder) + + def _configure_cmake(self): + if self._cmake: + return self._cmake + self._cmake = CMake(self) + self._cmake.configure() + return self._cmake + + def build(self): + for patch in self.conan_data.get("patches", {}).get(self.version, []): + tools.patch(**patch) + cmake = self._configure_cmake() + cmake.build() + + def package(self): + cmake = self._configure_cmake() + cmake.install() + + def package_info(self): + self.cpp_info.components["libelf++"].names["pkg_config"] = "libelf++" + self.cpp_info.components["libelf++"].libs = ["elf++"] + self.cpp_info.components["libdwarf++"].names["pkg_config"] = "libdwarf++" + self.cpp_info.components["libdwarf++"].libs = ["dwarf++"] + self.cpp_info.components["libdwarf++"].requires = ["libelf++"] diff --git a/recipes/libelfin/all/patches/commit-9d0db16d0a0b3c4f8aaa60a3e4dab295df34b6b2.patch b/recipes/libelfin/all/patches/commit-9d0db16d0a0b3c4f8aaa60a3e4dab295df34b6b2.patch new file mode 100644 index 0000000000000..5a53079e6b0a6 --- /dev/null +++ b/recipes/libelfin/all/patches/commit-9d0db16d0a0b3c4f8aaa60a3e4dab295df34b6b2.patch @@ -0,0 +1,173 @@ +# +# Updates v0.3 to the commit 9d0db16d0a0b3c4f8aaa60a3e4dab295df34b6b2: +# 9d0db16 fix data initialization of elf segment +# 74f1116 ignore dwarf extensions of gcc in the line table +# ac45a09 Added #include to files that use errno. +# 4a678c7 Don't mandate that compilation units need a DW_AT_comp_dir for line table parsing +# 85812f6 Fix typos +# +diff --git a/dwarf/abbrev.cc b/dwarf/abbrev.cc +index c780b8e..f77dc0c 100644 +--- a/dwarf/abbrev.cc ++++ b/dwarf/abbrev.cc +@@ -133,6 +133,10 @@ resolve_type(DW_AT name, DW_FORM form) + case DW_AT::ranges: + return value::type::rangelist; + ++ case DW_AT::lo_user...DW_AT::hi_user: ++ //HACK: ignore vendor extensions ++ return value::type::invalid; ++ + default: + throw format_error("DW_FORM_sec_offset not expected for attribute " + + to_string(name)); +diff --git a/dwarf/dwarf.cc b/dwarf/dwarf.cc +index fe9b947..2465eef 100644 +--- a/dwarf/dwarf.cc ++++ b/dwarf/dwarf.cc +@@ -289,8 +289,7 @@ compilation_unit::get_line_table() const + { + if (!m->lt.valid()) { + const die &d = root(); +- if (!d.has(DW_AT::stmt_list) || !d.has(DW_AT::name) || +- !d.has(DW_AT::comp_dir)) ++ if (!d.has(DW_AT::stmt_list) || !d.has(DW_AT::name)) + goto done; + + shared_ptr
sec; +@@ -300,8 +299,10 @@ compilation_unit::get_line_table() const + goto done; + } + ++ auto comp_dir = d.has(DW_AT::comp_dir) ? at_comp_dir(d) : ""; ++ + m->lt = line_table(sec, d[DW_AT::stmt_list].as_sec_offset(), +- m->subsec->addr_size, at_comp_dir(d), ++ m->subsec->addr_size, comp_dir, + at_name(d)); + } + done: +diff --git a/elf/elf++.hh b/elf/elf++.hh +index 562d1de..ee59ed0 100644 +--- a/elf/elf++.hh ++++ b/elf/elf++.hh +@@ -48,7 +48,7 @@ public: + * section data. Hence, callers must ensure that the loader passed to + * this file remains live as long as any such pointer is in use. + * Keeping any object that can return such a pointer live is +- * sufficieint to keep the loader live. ++ * sufficient to keep the loader live. + */ + class elf + { +@@ -204,7 +204,7 @@ public: + + /** + * Return the in-memory size of this segment in bytes. +- * Bytes between file_size() and mem_size() are implicity zeroes. ++ * Bytes between file_size() and mem_size() are implicitly zeroes. + */ + size_t mem_size() const; + +diff --git a/elf/elf.cc b/elf/elf.cc +index 587329f..61172ac 100644 +--- a/elf/elf.cc ++++ b/elf/elf.cc +@@ -167,12 +167,10 @@ elf::get_segment(unsigned index) const + + struct segment::impl { + impl(const elf &f) +- : f(f) { } ++ : f(f), data(nullptr) { } + + const elf f; + Phdr<> hdr; +- // const char *name; +- // size_t name_len; + const void *data; + }; + +diff --git a/elf/mmap_loader.cc b/elf/mmap_loader.cc +index 69d8acb..875d7bd 100644 +--- a/elf/mmap_loader.cc ++++ b/elf/mmap_loader.cc +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include + +diff --git a/examples/dump-lines.cc b/examples/dump-lines.cc +index ec58be1..9fed1fa 100644 +--- a/examples/dump-lines.cc ++++ b/examples/dump-lines.cc +@@ -1,6 +1,7 @@ + #include "elf++.hh" + #include "dwarf++.hh" + ++#include + #include + #include + +diff --git a/examples/dump-sections.cc b/examples/dump-sections.cc +index 12e7569..22526ec 100644 +--- a/examples/dump-sections.cc ++++ b/examples/dump-sections.cc +@@ -2,6 +2,7 @@ + + #include + #include ++#include + #include + #include + +diff --git a/examples/dump-segments.cc b/examples/dump-segments.cc +index f9e07d3..4c6319f 100644 +--- a/examples/dump-segments.cc ++++ b/examples/dump-segments.cc +@@ -2,6 +2,7 @@ + + #include + #include ++#include + #include + #include + +diff --git a/examples/dump-syms.cc b/examples/dump-syms.cc +index e7c2c3b..af7f484 100644 +--- a/examples/dump-syms.cc ++++ b/examples/dump-syms.cc +@@ -2,6 +2,7 @@ + + #include + #include ++#include + #include + #include + +diff --git a/examples/dump-tree.cc b/examples/dump-tree.cc +index 57d2b70..8bf2a63 100644 +--- a/examples/dump-tree.cc ++++ b/examples/dump-tree.cc +@@ -1,6 +1,7 @@ + #include "elf++.hh" + #include "dwarf++.hh" + ++#include + #include + #include + +diff --git a/examples/find-pc.cc b/examples/find-pc.cc +index dc40b85..2e324fc 100644 +--- a/examples/find-pc.cc ++++ b/examples/find-pc.cc +@@ -1,6 +1,7 @@ + #include "elf++.hh" + #include "dwarf++.hh" + ++#include + #include + #include + #include diff --git a/recipes/libelfin/all/test_package/CMakeLists.txt b/recipes/libelfin/all/test_package/CMakeLists.txt new file mode 100644 index 0000000000000..36df85d833b7f --- /dev/null +++ b/recipes/libelfin/all/test_package/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.1) +project(test_package CXX) + +include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) +conan_basic_setup() + +add_executable(${PROJECT_NAME} test_package.cpp) +target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS}) +set_target_properties(${PROJECT_NAME} PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED ON) diff --git a/recipes/libelfin/all/test_package/Makefile b/recipes/libelfin/all/test_package/Makefile new file mode 100644 index 0000000000000..ccf962b53e8bc --- /dev/null +++ b/recipes/libelfin/all/test_package/Makefile @@ -0,0 +1,5 @@ +# From http://timelessname.com/elfbin/ + +hello: hello.asm + nasm -f elf hello.asm + gcc -m32 -s -o hello hello.o -nostartfiles -nostdlib -nodefaultlibs diff --git a/recipes/libelfin/all/test_package/conanfile.py b/recipes/libelfin/all/test_package/conanfile.py new file mode 100644 index 0000000000000..e2a48eb337ec0 --- /dev/null +++ b/recipes/libelfin/all/test_package/conanfile.py @@ -0,0 +1,19 @@ +from conans import ConanFile, CMake, tools +import os + + +class TestPackageConan(ConanFile): + settings = "os", "compiler", "build_type", "arch" + generators = "cmake" + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def test(self): + if tools.cross_building(self.settings): + return + bin_path = os.path.join("bin", "test_package") + elf_path = os.path.join(self.source_folder, "hello") + self.run("{} {}".format(bin_path, elf_path), run_environment=True) diff --git a/recipes/libelfin/all/test_package/hello b/recipes/libelfin/all/test_package/hello new file mode 100644 index 0000000000000..7202f6f7d512e Binary files /dev/null and b/recipes/libelfin/all/test_package/hello differ diff --git a/recipes/libelfin/all/test_package/hello.asm b/recipes/libelfin/all/test_package/hello.asm new file mode 100644 index 0000000000000..0cc26b9d3a4a8 --- /dev/null +++ b/recipes/libelfin/all/test_package/hello.asm @@ -0,0 +1,16 @@ + SECTION .data +msg: db "Hi World",10 +len: equ $-msg + + SECTION .text + global main +main: + mov edx,len + mov ecx,msg + mov ebx,1 + mov eax,4 + int 0x80 + mov ebx,0 + mov eax,1 + int 0x80 + diff --git a/recipes/libelfin/all/test_package/test_package.cpp b/recipes/libelfin/all/test_package/test_package.cpp new file mode 100644 index 0000000000000..41843df23299f --- /dev/null +++ b/recipes/libelfin/all/test_package/test_package.cpp @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include + +int +main(int argc, char** argv) +{ + using elf::to_string; + + int fd = open(argv[1], O_RDONLY); + elf::elf f(elf::create_mmap_loader(fd)); + + auto& hdr = f.get_hdr(); + std::cout << "ELF Header:\n"; + std::cout << " Magic: " << std::hex; + for (auto c : hdr.ei_magic) + std::cout << ' ' << static_cast(c); + std::cout << '\n'; + std::cout << " Class: " << to_string(hdr.ei_class) << '\n'; + std::cout << " Data: " << to_string(hdr.ei_data) << '\n'; + std::cout << " Version: " << static_cast(hdr.ei_version) << '\n'; + std::cout << " OS/ABI: " << to_string(hdr.ei_osabi) << '\n'; + std::cout << " ABI Version: " << static_cast(hdr.ei_abiversion) << '\n'; + std::cout << " Type: " << to_string(hdr.type) << '\n'; + + return 0; +} diff --git a/recipes/libelfin/config.yml b/recipes/libelfin/config.yml new file mode 100644 index 0000000000000..1d91bf4e0169c --- /dev/null +++ b/recipes/libelfin/config.yml @@ -0,0 +1,3 @@ +versions: + "0.3": + folder: all