From 7c3b4a3f9fe3dd44bdbcd4ceaf6f5e2baff0c470 Mon Sep 17 00:00:00 2001 From: Romain Thomas Date: Sat, 17 Aug 2024 05:30:57 +0200 Subject: [PATCH] Add `demangle` utility (resolve: #1054) --- api/python/lief/__init__.pyi | 1 + api/python/src/pyLIEF.cpp | 17 ++++++++++++++++- api/rust/autocxx_ffi.rs | 1 + api/rust/cargo/lief/src/lib.rs | 11 +++++++++++ api/rust/include/LIEF/rust/utils.hpp | 6 ++++++ doc/sphinx/changelog.rst | 7 +++++++ include/LIEF/utils.hpp | 5 +++++ src/messages.hpp | 6 ++++++ src/utils.cpp | 9 +++++++++ tests/api/test_demangle.py | 14 ++++++++++++++ 10 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 tests/api/test_demangle.py diff --git a/api/python/lief/__init__.pyi b/api/python/lief/__init__.pyi index faa10d2854..6133fb8d0e 100644 --- a/api/python/lief/__init__.pyi +++ b/api/python/lief/__init__.pyi @@ -380,6 +380,7 @@ class range_t: def size(self) -> int: ... def current_platform() -> lief.PLATFORMS: ... +def demangle(mangled: str) -> Optional[str]: ... def disable_leak_warning() -> None: ... @overload def hash(arg: lief.Object, /) -> int: ... diff --git a/api/python/src/pyLIEF.cpp b/api/python/src/pyLIEF.cpp index ab49b68884..b7d8c0d918 100644 --- a/api/python/src/pyLIEF.cpp +++ b/api/python/src/pyLIEF.cpp @@ -22,6 +22,7 @@ #include #include +#include "LIEF/utils.hpp" #include "LIEF/hash.hpp" #include "LIEF/Object.hpp" #include "LIEF/range.hpp" @@ -208,7 +209,21 @@ void init(nb::module_& m) { - leaked function "export_symbol" - ... skipped remainder nanobind: this is likely caused by a reference counting issue in the binding code. - )doc"); + )doc"_doc); + + m.def("demangle", + [] (const std::string& mangled) { + return LIEF::py::value_or_none(&LIEF::demangle, mangled); + }, + R"doc( + Demangle the given input. + + .. warnings:: + + This function only works with the extended version of LIEF + )doc"_doc, + "mangled"_a + ); LIEF::py::init_extension(m); diff --git a/api/rust/autocxx_ffi.rs b/api/rust/autocxx_ffi.rs index 5965039184..bd5ddbc8b4 100644 --- a/api/rust/autocxx_ffi.rs +++ b/api/rust/autocxx_ffi.rs @@ -7,6 +7,7 @@ include_cpp! { name!(autocxx_ffi) generate!("is_extended") + generate!("demangle") generate_pod!("Span") block_constructors!("Span") diff --git a/api/rust/cargo/lief/src/lib.rs b/api/rust/cargo/lief/src/lib.rs index 5371281c01..08cee994ff 100644 --- a/api/rust/cargo/lief/src/lib.rs +++ b/api/rust/cargo/lief/src/lib.rs @@ -106,3 +106,14 @@ pub use debug_location::DebugLocation; pub fn is_extended() -> bool { lief_ffi::is_extended() } + +/// Try to demangle the given input. +/// +/// This function requires the extended version of LIEF +pub fn demangle(mangled: &str) -> Result { + to_conv_result!( + lief_ffi::demangle, + *mangled, + |e: cxx::UniquePtr| { e.to_string() } + ); +} diff --git a/api/rust/include/LIEF/rust/utils.hpp b/api/rust/include/LIEF/rust/utils.hpp index 48949a1baf..4d0b409c02 100644 --- a/api/rust/include/LIEF/rust/utils.hpp +++ b/api/rust/include/LIEF/rust/utils.hpp @@ -14,7 +14,13 @@ */ #pragma once #include "LIEF/utils.hpp" +#include "LIEF/rust/error.hpp" inline bool is_extended() { return LIEF::is_extended(); } + +inline std::string demangle(std::string mangled, uint32_t& err) { + return details::make_error(LIEF::demangle(mangled), err); +} + diff --git a/doc/sphinx/changelog.rst b/doc/sphinx/changelog.rst index aea77b391e..14137fa510 100644 --- a/doc/sphinx/changelog.rst +++ b/doc/sphinx/changelog.rst @@ -13,6 +13,13 @@ Changelog * Add support for RISC-V architecture + +:Extended: + + * Add :func:`lief.demangle` / :cpp:func:`LIEF::demangle` to demangle symbols + (c.f. :issue:`1054`) + + 0.15.1 - July 23th, 2024 ------------------------ diff --git a/include/LIEF/utils.hpp b/include/LIEF/utils.hpp index 9ca961dd89..1cf799ac7e 100644 --- a/include/LIEF/utils.hpp +++ b/include/LIEF/utils.hpp @@ -78,6 +78,11 @@ LIEF_API result u8tou16(const std::string& string); //! Whether this version of LIEF includes extended features LIEF_API bool is_extended(); + +//! Demangle the given input. +//! +//! This function only works with the extended version of LIEF +LIEF_API result demangle(const std::string& mangled); } diff --git a/src/messages.hpp b/src/messages.hpp index 63fa31a298..a083851ce1 100644 --- a/src/messages.hpp +++ b/src/messages.hpp @@ -36,5 +36,11 @@ "Please checkout " LIEF_DOC_PREFIX "/latest/extended/intro.html for the details" #endif +#if !defined(NEEDS_EXTENDED_MSG) +#define NEEDS_EXTENDED_MSG \ + "This function requires the extended version of LIEF.\n" \ + "Please checkout " LIEF_DOC_PREFIX "/latest/extended/intro.html for the details" +#endif + #endif diff --git a/src/utils.cpp b/src/utils.cpp index 6fcc2fa975..30c3db9af9 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -25,6 +25,8 @@ #include "third-party/utfcpp.hpp" #include "LIEF/config.h" +#include "logging.hpp" +#include "messages.hpp" namespace LIEF { @@ -90,5 +92,12 @@ bool is_extended() { return lief_extended; } +#if !defined(LIEF_EXTENDED) +result demangle(const std::string&/*mangled*/) { + LIEF_WARN(NEEDS_EXTENDED_MSG); + return make_error_code(lief_errors::not_implemented); +} +#endif + } // namespace LIEF diff --git a/tests/api/test_demangle.py b/tests/api/test_demangle.py new file mode 100644 index 0000000000..c766773109 --- /dev/null +++ b/tests/api/test_demangle.py @@ -0,0 +1,14 @@ +import lief +import pytest + +if not lief.__extended__: + pytest.skip("skipping: extended version only", allow_module_level=True) + +def test_itanium(): + assert lief.demangle("_ZN8nanobind6detail16type_caster_baseIN4LIEF3DEX6HeaderEEcvRS4_Ev") == "nanobind::detail::type_caster_base::operator LIEF::DEX::Header&()" + +def test_rust(): + assert lief.demangle("_RNvCskwGfYPst2Cb_3foo16example_function") == "foo::example_function" + +def test_ms(): + assert lief.demangle("??_C@_0CC@KGNKJKHE@heap_failure_listentry_corruptio@FNODOBFM@") == '"heap_failure_listentry_corruptio"...'