lief-project / LIEF

LIEF - Library to Instrument Executable Formats (C++, Python, Rust)
https://lief.re
Apache License 2.0
4.46k stars 622 forks source link

Everything breaks when disabling most CMake options enabled by default #599

Closed leycec closed 3 years ago

leycec commented 3 years ago

Hi! I'm @leycec, the stalwart volunteer currently packaging the most recent stable release of LIEF (...so, LIEF 0.11.5) for Gentoo Linux. LIEF is a mandatory build-time dependency for CadQuery, which is what I'm really trying to package and which imports LIEF's Python API to dump symbols for Open Cascade.

Who cares! On with the ugly parade of bugs.

A Tale of Two Terrible Bugs

Okay. Let's admit that packaging LIEF hasn't gone well.

LIEF's CMake-based build system is surprisingly fragile, constantly falling down and refusing to get up in common use scenarios. Various options described by cmake/LIEFOptions.cmake appear to mostly be untested, as disabling those options induces fatal compilation errors – but only after ten to twenty minutes of successful compilation, which only complicates an already overcomplicated build system.

The most egregious of these is the -DLIEF_DEX option governing DEX instrumentation. This option is thankfully enabled by default, because disabling this option destroys everything. What's mystifying is that the exact compilation error raised by disabling this option contextually changes based on which other CMake options are concurrently enabled or disabled.

I'll list the two prominent errors I hit here, but there are likely more.

DEX Must Die

Let's first disable DEX and only DEX by passing -DLIEF_DEX=OFF. Okay, we technically also disable ccache, because ccache is ostensibly insane and we're trying to maximize sanity here:

$ cmake -G Ninja -DCMAKE_INSTALL_PREFIX=/usr -DLIEF_USE_CCACHE=OFF -DLIEF_DEX=OFF /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5
...
[66/679] /usr/bin/x86_64-pc-linux-gnu-g++ -DLIB_LIEF_EXPORTS -DLIEF_EXPORTS -DMBEDTLS_MD2_C -DMBEDTLS_MD4_C -DMBEDTLS_PEM_PARSE_C -DMBEDTLS_PEM_WRITE_C -DMBEDTLS_PKCS1_V15 -DMBEDTLS_PKCS1_V21 -DMBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION -DMBEDTLS_X509_CRT_PARSE_C -DSPDLOG_DISABLE_DEFAULT_LOGGER -DSPDLOG_FUNCTION="" -D_GLIBCXX_USE_CXX11_ABI=1 -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/api/c/include -Iinclude -Ilief_frozen-prefix/src/lief_frozen/include -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/src -I. -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF -isystem lief_spdlog-prefix/src/lief_spdlog/include -isystem mbed_tls/src/lief_mbed_tls/include  -march=native -O2 -pipe -fPIC -fvisibility=hidden -Wall -Wextra -Wpedantic -fno-stack-protector -fomit-frame-pointer -fno-strict-aliasing -fexceptions -fvisibility=hidden -Wno-expansion-to-defined -fdiagnostics-color=always -std=gnu++14 -MD -MT CMakeFiles/LIB_LIEF.dir/src/visitors/hash.cpp.o -MF CMakeFiles/LIB_LIEF.dir/src/visitors/hash.cpp.o.d -o CMakeFiles/LIB_LIEF.dir/src/visitors/hash.cpp.o -c /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/src/visitors/hash.cpp
FAILED: CMakeFiles/LIB_LIEF.dir/src/visitors/hash.cpp.o 
/usr/bin/x86_64-pc-linux-gnu-g++ -DLIB_LIEF_EXPORTS -DLIEF_EXPORTS -DMBEDTLS_MD2_C -DMBEDTLS_MD4_C -DMBEDTLS_PEM_PARSE_C -DMBEDTLS_PEM_WRITE_C -DMBEDTLS_PKCS1_V15 -DMBEDTLS_PKCS1_V21 -DMBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION -DMBEDTLS_X509_CRT_PARSE_C -DSPDLOG_DISABLE_DEFAULT_LOGGER -DSPDLOG_FUNCTION="" -D_GLIBCXX_USE_CXX11_ABI=1 -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/api/c/include -Iinclude -Ilief_frozen-prefix/src/lief_frozen/include -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/src -I. -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF -isystem lief_spdlog-prefix/src/lief_spdlog/include -isystem mbed_tls/src/lief_mbed_tls/include  -march=native -O2 -pipe -fPIC -fvisibility=hidden -Wall -Wextra -Wpedantic -fno-stack-protector -fomit-frame-pointer -fno-strict-aliasing -fexceptions -fvisibility=hidden -Wno-expansion-to-defined -fdiagnostics-color=always -std=gnu++14 -MD -MT CMakeFiles/LIB_LIEF.dir/src/visitors/hash.cpp.o -MF CMakeFiles/LIB_LIEF.dir/src/visitors/hash.cpp.o.d -o CMakeFiles/LIB_LIEF.dir/src/visitors/hash.cpp.o -c /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/src/visitors/hash.cpp
In file included from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Binary.hpp:26,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Parser.hpp:30,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT.hpp:22,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/hash.hpp:21,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/src/visitors/hash.cpp:37:
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/type_traits.hpp:48:36: error: ‘DEX’ was not declared in this scope; did you mean ‘VDEX’?
   48 | using dex2dex_info_t    = std::map<DEX::File*, DEX::dex2dex_info_t>;
      |                                    ^~~
      |                                    VDEX
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/type_traits.hpp:48:67: error: wrong number of template arguments (1, should be at least 2)
   48 | using dex2dex_info_t    = std::map<DEX::File*, DEX::dex2dex_info_t>;
      |                                                                   ^
In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/10.3.0/include/g++-v10/map:61,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/ELF/Relocation.hpp:20,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/ELF.hpp:32,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Parser.hpp:28,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT.hpp:22,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/hash.hpp:21,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/src/visitors/hash.cpp:37:
/usr/lib/gcc/x86_64-pc-linux-gnu/10.3.0/include/g++-v10/bits/stl_map.h:100:11: note: provided for ‘template<class _Key, class _Tp, class _Compare, class _Alloc> class std::map’
  100 |     class map
      |           ^~~
In file included from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Binary.hpp:28,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Parser.hpp:30,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT.hpp:22,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/hash.hpp:21,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/src/visitors/hash.cpp:37:
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/DexFile.hpp:46:9: error: ‘DEX’ does not name a type; did you mean ‘VDEX’?
   46 |   const DEX::File& dex_file(void) const;
      |         ^~~
      |         VDEX
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/DexFile.hpp:47:3: error: ‘DEX’ does not name a type; did you mean ‘VDEX’?
   47 |   DEX::File& dex_file(void);
      |   ^~~
      |   VDEX
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/DexFile.hpp:77:3: error: ‘DEX’ does not name a type; did you mean ‘VDEX’?
   77 |   DEX::File* dex_file_{nullptr};
      |   ^~~
      |   VDEX
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/DexFile.hpp:77:32: warning: extra ‘;’ [-Wpedantic]
   77 |   DEX::File* dex_file_{nullptr};
      |                                ^
      |                                -
In file included from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Binary.hpp:29,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Parser.hpp:30,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT.hpp:22,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/hash.hpp:21,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/src/visitors/hash.cpp:37:
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Class.hpp:39:7: error: ‘DEX’ has not been declared
   39 |       DEX::Class* dex_class, const std::vector<uint32_t>& bitmap = {});
      |       ^~~
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Class.hpp:39:17: error: expected ‘,’ or ‘...’ before ‘ ’ token
   39 |       DEX::Class* dex_class, const std::vector<uint32_t>& bitmap = {});
      |                 ^
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Class.hpp:45:9: error: ‘DEX’ does not name a type; did you mean ‘VDEX’?
   45 |   const DEX::Class& dex_class(void) const;
      |         ^~~
      |         VDEX
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Class.hpp:46:3: error: ‘DEX’ does not name a type; did you mean ‘VDEX’?
   46 |   DEX::Class& dex_class(void);
      |   ^~~
      |   VDEX
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Class.hpp:59:27: error: ‘DEX’ does not name a type; did you mean ‘VDEX’?
   59 |   bool is_quickened(const DEX::Method& m) const;
      |                           ^~~
      |                           VDEX
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Class.hpp:59:38: error: expected unqualified-id before ‘&’ token
   59 |   bool is_quickened(const DEX::Method& m) const;
      |                                      ^
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Class.hpp:59:38: error: expected ‘)’ before ‘&’ token
   59 |   bool is_quickened(const DEX::Method& m) const;
      |                    ~                 ^
      |                                      )
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Class.hpp:59:38: error: expected ‘;’ at end of member declaration
   59 |   bool is_quickened(const DEX::Method& m) const;
      |                                      ^
      |                                       ;
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Class.hpp:59:40: error: ‘m’ does not name a type; did you mean ‘tm’?
   59 |   bool is_quickened(const DEX::Method& m) const;
      |                                        ^
      |                                        tm
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Class.hpp:62:39: error: ‘DEX’ does not name a type; did you mean ‘VDEX’?
   62 |   uint32_t method_offsets_index(const DEX::Method& m) const;
      |                                       ^~~
      |                                       VDEX
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Class.hpp:62:50: error: expected unqualified-id before ‘&’ token
   62 |   uint32_t method_offsets_index(const DEX::Method& m) const;
      |                                                  ^
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Class.hpp:62:50: error: expected ‘)’ before ‘&’ token
   62 |   uint32_t method_offsets_index(const DEX::Method& m) const;
      |                                ~                 ^
      |                                                  )
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Class.hpp:62:50: error: expected ‘;’ at end of member declaration
   62 |   uint32_t method_offsets_index(const DEX::Method& m) const;
      |                                                  ^
      |                                                   ;
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Class.hpp:62:52: error: ‘m’ does not name a type; did you mean ‘tm’?
   62 |   uint32_t method_offsets_index(const DEX::Method& m) const;
      |                                                    ^
      |                                                    tm
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Class.hpp:65:33: error: ‘DEX’ does not name a type; did you mean ‘VDEX’?
   65 |   uint32_t relative_index(const DEX::Method& m) const;
      |                                 ^~~
      |                                 VDEX
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Class.hpp:65:44: error: expected unqualified-id before ‘&’ token
   65 |   uint32_t relative_index(const DEX::Method& m) const;
      |                                            ^
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Class.hpp:65:44: error: expected ‘)’ before ‘&’ token
   65 |   uint32_t relative_index(const DEX::Method& m) const;
      |                          ~                 ^
      |                                            )
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Class.hpp:65:44: error: expected ‘;’ at end of member declaration
   65 |   uint32_t relative_index(const DEX::Method& m) const;
      |                                            ^
      |                                             ;
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Class.hpp:65:46: error: ‘m’ does not name a type; did you mean ‘tm’?
   65 |   uint32_t relative_index(const DEX::Method& m) const;
      |                                              ^
      |                                              tm
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Class.hpp:68:3: error: ‘DEX’ does not name a type; did you mean ‘VDEX’?
   68 |   DEX::dex2dex_class_info_t dex2dex_info(void) const;
      |   ^~~
      |   VDEX
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Class.hpp:80:3: error: ‘DEX’ does not name a type; did you mean ‘VDEX’?
   80 |   DEX::Class* dex_class_{nullptr};
      |   ^~~
      |   VDEX
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Class.hpp:80:34: warning: extra ‘;’ [-Wpedantic]
   80 |   DEX::Class* dex_class_{nullptr};
      |                                  ^
      |                                  -
In file included from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Binary.hpp:30,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Parser.hpp:30,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT.hpp:22,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/hash.hpp:21,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/src/visitors/hash.cpp:37:
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Method.hpp:41:10: error: ‘DEX’ has not been declared
   41 |   Method(DEX::Method* method, Class* oat_class, const std::vector<uint8_t>& code = {});
      |          ^~~
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Method.hpp:41:21: error: expected ‘)’ before ‘*’ token
   41 |   Method(DEX::Method* method, Class* oat_class, const std::vector<uint8_t>& code = {});
      |         ~           ^
      |                     )
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Method.hpp:41:86: error: expected unqualified-id before ‘)’ token
   41 |   Method(DEX::Method* method, Class* oat_class, const std::vector<uint8_t>& code = {});
      |                                                                                      ^
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Method.hpp:58:9: error: ‘DEX’ does not name a type; did you mean ‘VDEX’?
   58 |   const DEX::Method& dex_method(void) const;
      |         ^~~
      |         VDEX
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Method.hpp:59:3: error: ‘DEX’ does not name a type; did you mean ‘VDEX’?
   59 |   DEX::Method& dex_method(void);
      |   ^~~
      |   VDEX
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Method.hpp:67:9: error: ‘DEX’ does not name a type; did you mean ‘VDEX’?
   67 |   const DEX::dex2dex_method_info_t& dex2dex_info(void) const;
      |         ^~~
      |         VDEX
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Method.hpp:83:3: error: ‘DEX’ does not name a type; did you mean ‘VDEX’?
   83 |   DEX::Method* dex_method_{nullptr};
      |   ^~~
      |   VDEX
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Method.hpp:83:36: warning: extra ‘;’ [-Wpedantic]
   83 |   DEX::Method* dex_method_{nullptr};
      |                                    ^
      |                                    -
In file included from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Parser.hpp:30,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT.hpp:22,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/hash.hpp:21,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/src/visitors/hash.cpp:37:
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Binary.hpp:51:3: error: ‘DEX’ does not name a type; did you mean ‘VDEX’?
   51 |   DEX::it_dex_files dex_files(void);
      |   ^~~
      |   VDEX
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Binary.hpp:52:3: error: ‘DEX’ does not name a type; did you mean ‘VDEX’?
   52 |   DEX::it_const_dex_files dex_files(void) const;
      |   ^~~
      |   VDEX
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Binary.hpp:80:3: error: ‘dex2dex_info_t’ does not name a type
   80 |   dex2dex_info_t dex2dex_info(void) const;
      |   ^~~~~~~~~~~~~~
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Binary.hpp:97:3: error: ‘DEX’ does not name a type; did you mean ‘VDEX’?
   97 |   DEX::dex_files_t dex_files_;
      |   ^~~
      |   VDEX
In file included from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT.hpp:22,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/hash.hpp:21,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/src/visitors/hash.cpp:37:
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Parser.hpp:81:74: error: ‘DEX’ does not name a type; did you mean ‘VDEX’?
   81 |     void parse_oat_methods(uint64_t methods_offsets, Class* clazz, const DEX::Class& dex_class);
      |                                                                          ^~~
      |                                                                          VDEX
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Parser.hpp:81:84: error: expected unqualified-id before ‘&’ token
   81 |     void parse_oat_methods(uint64_t methods_offsets, Class* clazz, const DEX::Class& dex_class);
      |                                                                                    ^
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Parser.hpp:81:84: error: expected ‘)’ before ‘&’ token
   81 |     void parse_oat_methods(uint64_t methods_offsets, Class* clazz, const DEX::Class& dex_class);
      |                           ~                                                        ^
      |                                                                                    )
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/OAT/Parser.hpp:81:86: error: expected initializer before ‘dex_class’
   81 |     void parse_oat_methods(uint64_t methods_offsets, Class* clazz, const DEX::Class& dex_class);
      |                                                                                      ^~~~~~~~~
In file included from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/VDEX/Header.hpp:19,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/VDEX/File.hpp:20,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/VDEX/Parser.hpp:26,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/VDEX.hpp:22,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/VDEX/hash.hpp:21,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/src/visitors/hash.cpp:49:
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/VDEX/type_traits.hpp:26:35: error: ‘dex2dex_info_t’ in namespace ‘LIEF::OAT’ does not name a type
   26 | using dex2dex_info_t = LIEF::OAT::dex2dex_info_t;
      |                                   ^~~~~~~~~~~~~~
In file included from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/VDEX/Parser.hpp:26,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/VDEX.hpp:22,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/VDEX/hash.hpp:21,
                 from /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/src/visitors/hash.cpp:49:
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/VDEX/File.hpp:44:3: error: ‘DEX’ does not name a type; did you mean ‘VDEX’?
   44 |   DEX::it_dex_files       dex_files(void);
      |   ^~~
      |   VDEX
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/VDEX/File.hpp:45:3: error: ‘DEX’ does not name a type; did you mean ‘VDEX’?
   45 |   DEX::it_const_dex_files dex_files(void) const;
      |   ^~~
      |   VDEX
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/VDEX/File.hpp:47:3: error: ‘dex2dex_info_t’ does not name a type
   47 |   dex2dex_info_t dex2dex_info(void) const;
      |   ^~~~~~~~~~~~~~
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include/LIEF/VDEX/File.hpp:64:3: error: ‘DEX’ does not name a type; did you mean ‘VDEX’?
   64 |   DEX::dex_files_t dex_files_;
      |   ^~~
      |   VDEX
ninja: build stopped: subcommand failed.

That's... not great. On the bright side, this failure erupts after only a minute or so of compilation; on the dark side, the endless litany of non-human-readable errors is somewhat less than ideal.

DEX, OAT, and VDEX Must Also Die

Let's next disable DEX, OAT, and VDEX altogether to circumvent the above error by passing -DLIEF_DEX=OFF -DLIEF_OAT=OFF -DLIEF_VDEX=OFF.

$ cmake -G Ninja -DCMAKE_INSTALL_PREFIX=/usr -DLIEF_USE_CCACHE=OFF  -DLIEF_DEX=OFF -DLIEF_OAT=OFF -DLIEF_VDEX=OFF /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5
...
Success!

And... that actually works! The raccoons currently eating all of the tomatoes on our front deck rejoice. :raccoon: :tomato: :raccoon:

PE, ART, DEX, OAT, and VDEX Must All Die

Great. So, let's just go ahead and disable all format-specific instrumentation except for the two most popular POSIX-friendly formats (i.e., ELF and Macho-O) by passing -DLIEF_PE=OFF -DLIEF_ART=OFF -DLIEF_DEX=OFF -DLIEF_OAT=OFF -DLIEF_VDEX=OFF.

Because bugs breed like flies in the muggy Canadian heat, we now receive a completely different compilation error on a completely different compilation unit:

$ cmake -G Ninja -DCMAKE_INSTALL_PREFIX=/usr -DLIEF_USE_CCACHE=OFF  -DLIEF_PE=OFF -DLIEF_ART=OFF -DLIEF_DEX=OFF -DLIEF_OAT=OFF -DLIEF_VDEX=OFF /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5
...
[218/471] /usr/bin/x86_64-pc-linux-gnu-g++ -DMBEDTLS_MD2_C -DMBEDTLS_MD4_C -DMBEDTLS_PEM_PARSE_C -DMBEDTLS_PEM_WRITE_C -DMBEDTLS_PKCS1_V15 -DMBEDTLS_PKCS1_V21 -DMBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION -DMBEDTLS_X509_CRT_PARSE_C -D_GLIBCXX_USE_CXX11_ABI=1 -DpyLIEF_EXPORTS -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/api/python -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/api/python/Abstract -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/api/python/ELF -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/api/python/MachO -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/api/python/platforms/android -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/api/python/platforms/android/../.. -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/api/c/include -Iinclude -isystem /usr/include/python3.9 -isystem api/python/lief_pybind11-prefix/src/lief_pybind11/include  -march=native -O2 -pipe -fPIC -fvisibility=hidden -Wno-macro-redefined -Wno-deprecated-declarations -std=gnu++14 -MD -MT api/python/CMakeFiles/pyLIEF.dir/Abstract/objects/pyBinary.cpp.o -MF api/python/CMakeFiles/pyLIEF.dir/Abstract/objects/pyBinary.cpp.o.d -o api/python/CMakeFiles/pyLIEF.dir/Abstract/objects/pyBinary.cpp.o -c /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/api/python/Abstract/objects/pyBinary.cpp
FAILED: api/python/CMakeFiles/pyLIEF.dir/Abstract/objects/pyBinary.cpp.o 
/usr/bin/x86_64-pc-linux-gnu-g++ -DMBEDTLS_MD2_C -DMBEDTLS_MD4_C -DMBEDTLS_PEM_PARSE_C -DMBEDTLS_PEM_WRITE_C -DMBEDTLS_PKCS1_V15 -DMBEDTLS_PKCS1_V21 -DMBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION -DMBEDTLS_X509_CRT_PARSE_C -D_GLIBCXX_USE_CXX11_ABI=1 -DpyLIEF_EXPORTS -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/api/python -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/api/python/Abstract -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/api/python/ELF -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/api/python/MachO -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/api/python/platforms/android -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/api/python/platforms/android/../.. -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/include -I/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/api/c/include -Iinclude -isystem /usr/include/python3.9 -isystem api/python/lief_pybind11-prefix/src/lief_pybind11/include  -march=native -O2 -pipe -fPIC -fvisibility=hidden -Wno-macro-redefined -Wno-deprecated-declarations -std=gnu++14 -MD -MT api/python/CMakeFiles/pyLIEF.dir/Abstract/objects/pyBinary.cpp.o -MF api/python/CMakeFiles/pyLIEF.dir/Abstract/objects/pyBinary.cpp.o.d -o api/python/CMakeFiles/pyLIEF.dir/Abstract/objects/pyBinary.cpp.o -c /var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/api/python/Abstract/objects/pyBinary.cpp
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/api/python/Abstract/objects/pyBinary.cpp: In lambda function:
/var/tmp/portage/dev-libs/lief-0.11.5/work/LIEF-0.11.5/api/python/Abstract/objects/pyBinary.cpp:190:30: error: aggregate ‘std::ostringstream stream’ has incomplete type and cannot be defined
  190 |           std::ostringstream stream;
      |                              ^~~~~~
At global scope:
cc1plus: note: unrecognized command-line option ‘-Wno-macro-redefined’ may have been intended to silence earlier diagnostics
ninja: build stopped: subcommand failed

That's even worse. On the bright side, there's only a single prominent error; on the dark side, that error only erupts after ten to twenty minutes of compilation and (much more importantly) has no obvious relation to the underlying CMake options causing this error.

The superficial "error: aggregate ‘std::ostringstream stream’ has incomplete type and cannot be defined" message just means there's a missing #include <sstring> in pyBinary.cpp, presumably due to some perfidious nesting of conditional includes. Debugging that error back to its root cause, however, took me the better part of several days.

In reflection, that wasn't necessarily time well-spent.

Another Rotten Leaf Falls

Gentoo's LIEF package currently circumvents everything above by unconditionally enabling all format-specific CMake options (e.g., by internally forcing -DLIEF_ELF=ON -DLIEF_PE=ON -DLIEF_MACHO=ON -DLIEF_ART=ON -DLIEF_DEX=ON -DLIEF_OAT=ON -DLIEF_VDEX=ON). That's really non-ideal for us, because the whole point of using Gentoo in the first place is fine-grained control over compilation. Still, working but non-configurable >>>>>>>> non-working but configurable.

While debugging everything above, I slowly received the uncontrollable urge to break keyboards. It'd be great if these issues could be resolved to prevent any future hardship to keyboards.

As scarce volunteer time permits, it'd also be great if LIEF's continuous integration suite could be updated to test these problematic permutations of CMake options. Since I'll be packaging LIEF for the foreseeable future on Gentoo, I'm really hoping to avoid painful regressions in the future. Please help me help you.

And thanks for your tireless attention, LEIF developers. Maintaining a code behemoth of this magnitude cannot be easy. I salute your bravery and integrity in the face of ongoing development pain.

leycec commented 3 years ago

Relatedly, the LIEF_INSTALL_PYTHON CMake option declared by cmake/LIEFOptions.cmake silently reduces to a noop. It isn't actually used anywhere, but should be; ideally, enabling that option should instruct the api/python/CMakeLists.txt file to install the generated pyLIEF C extension into the site-packages/ subdirectory of the target Python interpreter.

Of course, setup.py exists – but that's really just a thin wrapper around cmake and ninja lacking most of the configurability of the top-level CMakeLists.txt file. Gentoo currently ignores LIEF's setup.py in lieu of directly invoking cmake and ninja, because patching setup.py to respect our CMake toolchain mostly seems like an exercise in futility. </sigh>

romainthomas commented 3 years ago

Hello @leycec,

Thanks for having taken time to write this ~tale~ issue!

I slowly received the uncontrollable urge to break keyboards

Sorry to hear that and if it can help, I can send you a LIEF's sticker to put on you keyboard (It was helpful for me :blush:)

Actually (and I take the point), there is no documentation on these options and I'll address this problem. For the (missing) context, DEX, ART, OAT and VDEX are formats related to Android and they depend each other. This is why disabling DEX fails but disabling DEX, OAT and VDEX works.

And thanks for your tireless attention, LEIF developers

My pleasure!

Maintaining a code behemoth of this magnitude cannot be easy. I salute your bravery and integrity in the face of ongoing development pain.

I return the compliment for being a package manager for Gentoo, sincerely!

leycec commented 3 years ago

Sorry to hear that and if it can help, I can send you a LIEF's sticker to put on you keyboard (It was helpful for me :blush:)

Yes! Yes! Smiling LIEF stickers plastered all over my keyboard is exactly what I've been missing all this time – only I never knew it!

But... seriously. Thanks for accommodating my obvious frustration with genuinely funny humour. As a fellow package maintainer, this is the way you convert grumpy gripers into satisfied smilers.

You win @leycec's Gold Star for Customer Service today, Romain. :star2:

leycec commented 3 years ago

Yikes. Gentoo is issuing an automated QA notice concerning an insecure RUNPATH in LIEF's api/python/lief.so shared library:

 * QA Notice: The following files contain insecure RUNPATHs
 *  Please file a bug about this at https://bugs.gentoo.org/
 *  with the maintainer of the package.
 *   /var/tmp/portage/dev-libs/lief-0.11.5/image/usr/lib/python3.9/site-packages/lief.so
 *     RPATH: /var/tmp/portage/dev-libs/lief-0.11.5/work/lief-0.11.5_build

That's a potential CVE in the making. Insecure RPATHS like this enable malicious black hats to inject arbitrary code at LIEF runtime by adding arbitrary shared libraries to that RPATH.

Of course, this assumes black hats have write permissions to that RPATH. That isn't likely in Gentoo's case, as /var/tmp/portage isn't world-writeable. All bets are off on other platforms – especially platforms that build CMake-based packages in /tmp, which typically is world-writeable.

The underlying issue is that LIEF makefiles are erroneously passing -rpath when generating this library: e.g.,

... -Wl,-rpath,/var/tmp/portage/dev-libs/lief-0.11.5/work/lief-0.11.5_build libLIEF.so

I've traced this to line 5559 (on my machine, of course – YMMV) of the generated build.ninja makefile, which resembles:

  LINK_LIBRARIES = -Wl,-rpath,/var/tmp/portage/dev-libs/lief-0.11.5/work/lief-0.11.5_build  libLIEF.so

I'm not as conversant in cmake and ninja as I'd like, so I'm afraid that's as far down the black hat rabbit hole as my expertise goes. But... yeah. This is super-bad, especially because LIEF is often leveraged by security consultants. It doesn't look good, you know? This would probably be a great time to define a project-wide security policy.

I'd escalate resolving that insecurity with all haste before the other shoe drops. You really do not want that shoe to drop, Romain. :warning: :skull: :skull_and_crossbones: :radioactive:

leycec commented 3 years ago

Fascinating. Because this is so horrible, I couldn't help but dig deeper. It's like an abscessed molar. You just want to keep poking it.

The scary insecurity detailed by my prior comment shouldn't be happening. ninja install already strips insecure RPATHS from installed libraries – which should also include the the api/python/lief.so shared library.

ninja install isn't doing that, though. Why? Because api/python/CMakeLists.txt isn't actually installing the library it generates. It obviously should be, because not doing that gives you this scary insecurity. That's the real underlying issue here and the ultimate cause of this insanity.

Fortunately, fixing this should be trivial. You just need to respect rather than ignore the LIEF_INSTALL_PYTHON CMake option declared by cmake/LIEFOptions.cmake. Specifically, you need to add something resembling the following to the end of api/python/CMakeLists.txt:

IF(LIEF_INSTALL_PYTHON)
  INSTALL(
    FILES ${PROJECT_BINARY_DIR}/api/python/lief.so
    DESTINATION ${CMAKE_INSTALL_LIBDIR}
    COMPONENT Application
  )
ENDIF()

Untested, of course, but probably not too far from the mark. Phew! I can finally rest in peace knowing that LIEF might actually be packageable after several nightmarish days of mud-wrestling with LIEF's "unique" build system.

romainthomas commented 3 years ago

Phew! I can finally rest in peace knowing that LIEF might actually be packageable

Well done! You passed the first challenge!

The next step is to learn cmake (you can start with: RPATH handling) :kissing_heart:

leycec commented 3 years ago

...wut? None of these breaking installation issues were resolved, so this shouldn't have been closed. Denial is not a river in Egypt.

I'm getting the firm impression here that LIEF has a troubled development history, questionable goals, and toxic management – which means I'm outta here. Ain't nobody got scarce volunteer time for shenanigans.

On Gentoo's side, we'll sanitize LIEF's broken build process by (A) not disabling CMake options enabled by default and (B) manually patching api/python/CMakeLists.txt to properly install RPATH-less Python bindings.

Have a good dev cycle, I guess? </sigh>

blshkv commented 3 years ago

@leycec I'm curious, did they fix it?

romainthomas commented 3 years ago

@blshkv which ones?