diff options
| author | Glenn Smith <glenn@vector35.com> | 2023-11-07 18:55:32 -0500 |
|---|---|---|
| committer | Glenn Smith <glenn@vector35.com> | 2023-11-13 17:22:16 -0500 |
| commit | 1716451033063812056349156332128984540962 (patch) | |
| tree | 7a12ab7cdb9c15ffadfaa42651e7fe044ff7befa | |
| parent | 0cc0b1ce9f7e1bcf4b8fac581ab4e5a354906ba4 (diff) | |
Add fmt library to api
| -rw-r--r-- | .gitmodules | 3 | ||||
| -rw-r--r-- | CMakeLists.txt | 3 | ||||
| -rw-r--r-- | architecture.cpp | 28 | ||||
| -rw-r--r-- | binaryninjaapi.cpp | 154 | ||||
| -rw-r--r-- | binaryninjaapi.h | 363 | ||||
| -rw-r--r-- | binaryninjacore.h | 3 | ||||
| -rw-r--r-- | docs/about/open-source.md | 3 | ||||
| -rw-r--r-- | log.cpp | 98 | ||||
| -rw-r--r-- | metadata.cpp | 4 | ||||
| -rw-r--r-- | type.cpp | 5 | ||||
| -rw-r--r-- | ui/util.h | 12 | ||||
| m--------- | vendor/fmt | 0 |
12 files changed, 644 insertions, 32 deletions
diff --git a/.gitmodules b/.gitmodules index f3489ad4..30817521 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "suite/binaries"] path = suite/binaries url = https://github.com/Vector35/BinaryTestCases.git +[submodule "vendor/fmt"] + path = vendor/fmt + url = https://github.com/fmtlib/fmt.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d918a23..7f4c62e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,9 @@ target_link_libraries(binaryninjaapi PUBLIC ${BinaryNinjaCore_LIBRARIES}) target_link_directories(binaryninjaapi PUBLIC ${BinaryNinjaCore_LIBRARY_DIRS}) target_compile_definitions(binaryninjaapi PUBLIC ${BinaryNinjaCore_DEFINITIONS}) +add_subdirectory(vendor/fmt) +target_link_libraries(binaryninjaapi PUBLIC fmt::fmt) + set_target_properties(binaryninjaapi PROPERTIES CXX_STANDARD 17 CXX_VISIBILITY_PRESET hidden diff --git a/architecture.cpp b/architecture.cpp index d0147dc0..0e09230a 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -899,25 +899,19 @@ bool Architecture::GetInstructionLowLevelIL(const uint8_t*, uint64_t, size_t&, L string Architecture::GetRegisterName(uint32_t reg) { - char regStr[32]; - snprintf(regStr, sizeof(regStr), "r%" PRIu32, reg); - return regStr; + return fmt::format("r{}", reg); } string Architecture::GetFlagName(uint32_t flag) { - char flagStr[32]; - snprintf(flagStr, sizeof(flagStr), "flag%" PRIu32, flag); - return flagStr; + return fmt::format("flag{}", flag); } string Architecture::GetFlagWriteTypeName(uint32_t flags) { - char flagStr[32]; - snprintf(flagStr, sizeof(flagStr), "update%" PRIu32, flags); - return flagStr; + return fmt::format("update{}", flags); } @@ -925,17 +919,13 @@ string Architecture::GetSemanticFlagClassName(uint32_t semClass) { if (semClass == 0) return ""; - char flagStr[32]; - snprintf(flagStr, sizeof(flagStr), "semantic%" PRIu32, semClass); - return flagStr; + return fmt::format("semantic{}", semClass); } string Architecture::GetSemanticFlagGroupName(uint32_t semGroup) { - char flagStr[32]; - snprintf(flagStr, sizeof(flagStr), "group%" PRIu32, semGroup); - return flagStr; + return fmt::format("group{}", semGroup); } @@ -1097,9 +1087,7 @@ bool Architecture::IsSystemRegister(uint32_t reg) string Architecture::GetRegisterStackName(uint32_t regStack) { - char regStr[32]; - snprintf(regStr, sizeof(regStr), "reg_stack_%" PRIu32, regStack); - return regStr; + return fmt::format("reg_stack_{}", regStack); } @@ -1129,9 +1117,7 @@ uint32_t Architecture::GetRegisterStackForRegister(uint32_t reg) string Architecture::GetIntrinsicName(uint32_t intrinsic) { - char intrinsicStr[32]; - snprintf(intrinsicStr, sizeof(intrinsicStr), "intrinsic_%" PRIu32, intrinsic); - return intrinsicStr; + return fmt::format("intrinsic_{}", intrinsic); } diff --git a/binaryninjaapi.cpp b/binaryninjaapi.cpp index a456f8c2..89827c73 100644 --- a/binaryninjaapi.cpp +++ b/binaryninjaapi.cpp @@ -431,3 +431,157 @@ bool BinaryNinja::ProgressCallback(void* ctxt, size_t current, size_t total) return true; return pctxt->callback(current, total); } + + +fmt::format_context::iterator fmtByteString(const std::vector<uint8_t>& string, fmt::format_context& ctx) +{ + *ctx.out()++ = 'b'; + *ctx.out()++ = '\"'; + for (uint8_t ch: string) + { + if (ch == '\n') + { + *ctx.out()++ = '\\'; + *ctx.out()++ = 'n'; + } + else if (ch == '\r') + { + *ctx.out()++ = '\\'; + *ctx.out()++ = 'r'; + } + else if (ch == '\t') + { + *ctx.out()++ = '\\'; + *ctx.out()++ = 't'; + } + else if (ch == '\"') + { + *ctx.out()++ = '\\'; + *ctx.out()++ = '\"'; + } + else if (ch == '\\') + { + *ctx.out()++ = '\\'; + *ctx.out()++ = '\\'; + } + else if (ch < 0x20 || ch >= 0x7f) + { + fmt::format_to(ctx.out(), "\\x{:02x}", ch); + } + else + { + *ctx.out()++ = ch; + } + } + *ctx.out()++ = '\"'; + return ctx.out(); +} + + +fmt::format_context::iterator fmtQuotedString(const std::string& string, fmt::format_context& ctx) +{ + *ctx.out()++ = '\"'; + for (char ch: string) + { + if (ch == '\n') + { + *ctx.out()++ = '\\'; + *ctx.out()++ = 'n'; + } + else if (ch == '\r') + { + *ctx.out()++ = '\\'; + *ctx.out()++ = 'r'; + } + else if (ch == '\t') + { + *ctx.out()++ = '\\'; + *ctx.out()++ = 't'; + } + else if (ch == '\"') + { + *ctx.out()++ = '\\'; + *ctx.out()++ = '\"'; + } + else if (ch == '\\') + { + *ctx.out()++ = '\\'; + *ctx.out()++ = '\\'; + } + else if (ch < 0x20 || ch >= 0x7f) + { + fmt::format_to(ctx.out(), "\\x{:02x}", ch); + } + else + { + *ctx.out()++ = ch; + } + } + *ctx.out()++ = '\"'; + return ctx.out(); +} + + +fmt::format_context::iterator fmt::formatter<BinaryNinja::Metadata>::format(const BinaryNinja::Metadata& obj, format_context& ctx) const +{ + switch (obj.GetType()) + { + default: + case InvalidDataType: + return fmt::format_to(ctx.out(), "(invalid)"); + case BooleanDataType: + return fmt::format_to(ctx.out(), "{}", obj.GetBoolean()); + case StringDataType: + return fmt::format_to(ctx.out(), "{}", obj.GetString()); + case UnsignedIntegerDataType: + return fmt::format_to(ctx.out(), "{}", obj.GetUnsignedInteger()); + case SignedIntegerDataType: + return fmt::format_to(ctx.out(), "{}", obj.GetSignedInteger()); + case DoubleDataType: + return fmt::format_to(ctx.out(), "{}", obj.GetDouble()); + case RawDataType: + return fmtByteString(obj.GetRaw(), ctx); + case KeyValueDataType: + { + *ctx.out()++ = '{'; + bool first = true; + for (auto& [name, value]: obj.GetKeyValueStore()) + { + if (!first) + { + *ctx.out()++ = ','; + *ctx.out()++ = ' '; + } + first = false; + + fmtQuotedString(name, ctx); + *ctx.out()++ = ':'; + *ctx.out()++ = ' '; + fmt::format_to(ctx.out(), "{}", value); + } + *ctx.out()++ = '}'; + return ctx.out(); + } + case ArrayDataType: + *ctx.out()++ = '['; + bool first = true; + for (auto& value: obj.GetArray()) + { + if (!first) + { + *ctx.out()++ = ','; + *ctx.out()++ = ' '; + } + first = false; + fmt::format_to(ctx.out(), "{}", value); + } + *ctx.out()++ = ']'; + return ctx.out(); + } +} + + +fmt::format_context::iterator fmt::formatter<BinaryNinja::NameList>::format(const BinaryNinja::NameList& obj, format_context& ctx) const +{ + return fmt::format_to(ctx.out(), "{}", obj.GetString()); +} diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 485a01d6..32db3582 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -38,6 +38,7 @@ #include <atomic> #include <memory> #include <cstdint> +#include <typeinfo> #include <type_traits> #include <variant> #include <optional> @@ -45,6 +46,9 @@ #include "binaryninjacore.h" #include "exceptions.h" #include "json/json.h" +#include <fmt/format.h> +#include <fmt/ranges.h> +#include <fmt/core.h> #ifdef _MSC_VER #define NOEXCEPT @@ -638,7 +642,7 @@ namespace BinaryNinja { BN_PRINTF_ATTRIBUTE(1, 2) void LogWarn(const char* fmt, ...); - /*! LogError writes text to the error console and pops up the error console. Additionall, + /*! LogError writes text to the error console and pops up the error console. Additionally, Errors in the console log include a error icon. LogError corresponds to the log level: ErrorLog. @threadsafe @@ -664,6 +668,127 @@ namespace BinaryNinja { BN_PRINTF_ATTRIBUTE(1, 2) void LogAlert(const char* fmt, ...); + // Implementation detail + void LogFV(BNLogLevel level, fmt::string_view format, fmt::format_args args); + void LogTraceFV(fmt::string_view format, fmt::format_args args); + void LogDebugFV(fmt::string_view format, fmt::format_args args); + void LogInfoFV(fmt::string_view format, fmt::format_args args); + void LogWarnFV(fmt::string_view format, fmt::format_args args); + void LogErrorFV(fmt::string_view format, fmt::format_args args); + void LogAlertFV(fmt::string_view format, fmt::format_args args); + + /*! Logs to the error console with the given BNLogLevel. + + @threadsafe + + \ingroup logging + + \param level BNLogLevel debug log level + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template<typename... T> + void LogF(BNLogLevel level, fmt::format_string<T...> format, T&&... args) + { + LogFV(level, format, fmt::make_format_args(args...)); + } + + /*! LogTrace only writes text to the error console if the console is set to log level: DebugLog + Log level and the build is not a DEBUG build (i.e. the preprocessor directive _DEBUG is defined) + + @threadsafe + + \ingroup logging + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template<typename... T> + void LogTraceF(fmt::format_string<T...> format, T&&... args) + { + LogTraceFV(format, fmt::make_format_args(args...)); + } + + /*! LogDebug only writes text to the error console if the console is set to log level: DebugLog + Log level DebugLog is the most verbose logging level in release builds. + + @threadsafe + + \ingroup logging + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template<typename... T> + void LogDebugF(fmt::format_string<T...> format, T&&... args) + { + LogDebugFV(format, fmt::make_format_args(args...)); + } + + /*! LogInfo always writes text to the error console, and corresponds to the log level: InfoLog. + Log level InfoLog is the second most verbose logging level. + + @threadsafe + + \ingroup logging + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template<typename... T> + void LogInfoF(fmt::format_string<T...> format, T&&... args) + { + LogInfoFV(format, fmt::make_format_args(args...)); + } + + /*! LogWarn writes text to the error console including a warning icon, + and also shows a warning icon in the bottom pane. LogWarn corresponds to the log level: WarningLog. + + @threadsafe + + \ingroup logging + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template<typename... T> + void LogWarnF(fmt::format_string<T...> format, T&&... args) + { + LogWarnFV(format, fmt::make_format_args(args...)); + } + + /*! LogError writes text to the error console and pops up the error console. Additionally, + Errors in the console log include a error icon. LogError corresponds to the log level: ErrorLog. + + @threadsafe + + \ingroup logging + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template<typename... T> + void LogErrorF(fmt::format_string<T...> format, T&&... args) + { + LogErrorFV(format, fmt::make_format_args(args...)); + } + + /*! LogAlert pops up a message box displaying the alert message and logs to the error console. + LogAlert corresponds to the log level: AlertLog. + + @threadsafe + + \ingroup logging + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template<typename... T> + void LogAlertF(fmt::format_string<T...> format, T&&... args) + { + LogAlertFV(format, fmt::make_format_args(args...)); + } + /*! Redirects the minimum level passed to standard out @threadsafe @@ -711,6 +836,17 @@ namespace BinaryNinja { class Logger: public CoreRefCountObject<BNLogger, BNNewLoggerReference, BNFreeLogger> { size_t GetThreadId() const; + std::unordered_map<BNLogLevel, std::string> m_iterBuffer; + friend struct Iterator; + + void LogFV(BNLogLevel level, fmt::string_view format, fmt::format_args args); + void LogTraceFV(fmt::string_view format, fmt::format_args args); + void LogDebugFV(fmt::string_view format, fmt::format_args args); + void LogInfoFV(fmt::string_view format, fmt::format_args args); + void LogWarnFV(fmt::string_view format, fmt::format_args args); + void LogErrorFV(fmt::string_view format, fmt::format_args args); + void LogAlertFV(fmt::string_view format, fmt::format_args args); + public: Logger(BNLogger* logger); @@ -804,6 +940,104 @@ namespace BinaryNinja { */ void LogAlert(const char* fmt, ...); + /*! Logs to the error console with the given BNLogLevel. + + @threadsafe + + \param level BNLogLevel debug log level + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template<typename... T> + void LogF(BNLogLevel level, fmt::format_string<T...> format, T&&... args) + { + LogFV(level, format, fmt::make_format_args(args...)); + } + + /*! LogTrace only writes text to the error console if the console is set to log level: DebugLog + Log level and the build is not a DEBUG build (i.e. the preprocessor directive _DEBUG is defined) + + @threadsafe + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template<typename... T> + void LogTraceF(fmt::format_string<T...> format, T&&... args) + { + LogTraceFV(format, fmt::make_format_args(args...)); + } + + /*! LogDebug only writes text to the error console if the console is set to log level: DebugLog + Log level DebugLog is the most verbose logging level in release builds. + + @threadsafe + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template<typename... T> + void LogDebugF(fmt::format_string<T...> format, T&&... args) + { + LogDebugFV(format, fmt::make_format_args(args...)); + } + + /*! LogInfo always writes text to the error console, and corresponds to the log level: InfoLog. + Log level InfoLog is the second most verbose logging level. + + @threadsafe + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template<typename... T> + void LogInfoF(fmt::format_string<T...> format, T&&... args) + { + LogInfoFV(format, fmt::make_format_args(args...)); + } + + /*! LogWarn writes text to the error console including a warning icon, + and also shows a warning icon in the bottom pane. LogWarn corresponds to the log level: WarningLog. + + @threadsafe + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template<typename... T> + void LogWarnF(fmt::format_string<T...> format, T&&... args) + { + LogWarnFV(format, fmt::make_format_args(args...)); + } + + /*! LogError writes text to the error console and pops up the error console. Additionally, + Errors in the console log include a error icon. LogError corresponds to the log level: ErrorLog. + + @threadsafe + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template<typename... T> + void LogErrorF(fmt::format_string<T...> format, T&&... args) + { + LogErrorFV(format, fmt::make_format_args(args...)); + } + + /*! LogAlert pops up a message box displaying the alert message and logs to the error console. + LogAlert corresponds to the log level: AlertLog. + + @threadsafe + + \param format fmt-style format string. + \param ... Variable arguments corresponding to the format string. + */ + template<typename... T> + void LogAlertF(fmt::format_string<T...> format, T&&... args) + { + LogAlertFV(format, fmt::make_format_args(args...)); + } + /*! Get the name registered for this Logger @threadsafe @@ -938,6 +1172,47 @@ namespace BinaryNinja { void SetCurrentPluginLoadOrder(BNPluginLoadOrder order); void AddRequiredPluginDependency(const std::string& name); void AddOptionalPluginDependency(const std::string& name); + + template<typename T> + std::string CoreEnumName() + { + // Extremely implementation-defined. Best-effort is made for our relevant platforms +#ifdef WIN32 + // "enum TestEnum" + return std::string(typeid(T).name()).substr(5); +#else + // "19BNWhateverItsCalled" + auto name = std::string(typeid(T).name()); + while (std::isdigit(name[0])) + { + name.erase(0, 1); + } + return name; +#endif + } + + template<typename T> + std::optional<std::string> CoreEnumToString(T value) + { + auto name = CoreEnumName<T>(); + char* result; + if (!BNCoreEnumToString(name.c_str(), (size_t)value, &result)) + return std::nullopt; + auto cppResult = std::string(result); + BNFreeString(result); + return cppResult; + } + + template<typename T> + std::optional<T> CoreEnumFromString(const std::string& value) + { + auto name = CoreEnumName<T>(); + size_t result; + if (!BNCoreEnumFromString(name.c_str(), value.c_str(), &result)) + return std::nullopt; + return result; + } + /*! @} */ @@ -1087,8 +1362,8 @@ namespace BinaryNinja { std::vector<int64_t> GetSignedIntegerList() const; std::vector<double> GetDoubleList() const; std::vector<uint8_t> GetRaw() const; - std::vector<Ref<Metadata>> GetArray(); - std::map<std::string, Ref<Metadata>> GetKeyValueStore(); + std::vector<Ref<Metadata>> GetArray() const; + std::map<std::string, Ref<Metadata>> GetKeyValueStore() const; // For key-value data only /*! Get a Metadata object by key. Only for if IsKeyValueStore == true @@ -2897,7 +3172,7 @@ namespace BinaryNinja { public: NameList(const BNQualifiedName* name); - NameList(const std::string& join, size_t size = 0); + explicit NameList(const std::string& join, size_t size = 0); NameList(const std::string& name, const std::string& join); NameList(const std::vector<std::string>& name, const std::string& join); NameList(const NameList& name, const std::string& join); @@ -16034,3 +16309,83 @@ namespace std } }; } // namespace std + + +template<typename T> struct fmt::formatter<BinaryNinja::Ref<T>> +{ + format_context::iterator format(const BinaryNinja::Ref<T>& obj, format_context& ctx) const + { + return fmt::formatter<T>().format(*obj.GetPtr(), ctx); + } + constexpr auto parse(format_parse_context& ctx) -> format_parse_context::iterator { return ctx.begin(); } +}; + +template<typename T> struct fmt::formatter<BinaryNinja::Confidence<T>> +{ + format_context::iterator format(const BinaryNinja::Confidence<T>& obj, format_context& ctx) const + { + fmt::formatter<T>().format(obj.GetValue(), ctx); + return fmt::format_to(ctx.out(), " ({} confidence)", ctx); + } + constexpr auto parse(format_parse_context& ctx) -> format_parse_context::iterator { return ctx.begin(); } +}; + +template<typename T> struct fmt::formatter<BinaryNinja::Confidence<BinaryNinja::Ref<T>>> +{ + format_context::iterator format(const BinaryNinja::Confidence<BinaryNinja::Ref<T>>& obj, format_context& ctx) const + { + fmt::formatter<T>().format(*obj.GetValue().GetPtr(), ctx); + return fmt::format_to(ctx.out(), " ({} confidence)", ctx); + } + constexpr auto parse(format_parse_context& ctx) -> format_parse_context::iterator { return ctx.begin(); } +}; + +template<> struct fmt::formatter<BinaryNinja::Metadata> +{ + format_context::iterator format(const BinaryNinja::Metadata& obj, format_context& ctx) const; + constexpr auto parse(format_parse_context& ctx) -> format_parse_context::iterator { return ctx.begin(); } +}; + +template<> struct fmt::formatter<BinaryNinja::NameList> +{ + format_context::iterator format(const BinaryNinja::NameList& obj, format_context& ctx) const; + constexpr auto parse(format_parse_context& ctx) -> format_parse_context::iterator { return ctx.begin(); } +}; + +template<typename T> +struct fmt::formatter<T, char, std::enable_if_t<std::is_enum_v<T>, void>> +{ + // s -> name, S -> scoped::name, d -> int, x -> hex + char presentation = 's'; + format_context::iterator format(const T& obj, format_context& ctx) const + { + auto stringed = BinaryNinja::CoreEnumToString<T>(obj); + if (stringed.has_value()) + { + switch (presentation) + { + default: + case 's': + return fmt::format_to(ctx.out(), "{}", *stringed); + case 'S': + return fmt::format_to(ctx.out(), "{}::{}", BinaryNinja::CoreEnumName<T>(), *stringed); + case 'd': + return fmt::format_to(ctx.out(), "{}", (size_t)obj); + case 'x': + return fmt::format_to(ctx.out(), "{:#x}", (size_t)obj); + } + } + else + { + return fmt::format_to(ctx.out(), "{}", (size_t)obj); + } + } + + constexpr auto parse(format_parse_context& ctx) -> format_parse_context::iterator + { + auto it = ctx.begin(), end = ctx.end(); + if (it != end && (*it == 's' || *it == 'S' || *it == 'd' || *it == 'x')) presentation = *it++; + if (it != end && *it != '}') detail::throw_format_error("invalid format"); + return it; + } +}; diff --git a/binaryninjacore.h b/binaryninjacore.h index 30e34b81..57ee5eb6 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -6634,6 +6634,9 @@ extern "C" void (*add)(void* ctxt, BNSymbol* symbol, BNType* type), void* addContext); BINARYNINJACOREAPI void BNProcessSymbolQueue(BNSymbolQueue* queue); + BINARYNINJACOREAPI bool BNCoreEnumToString(const char* enumName, size_t value, char** result); + BINARYNINJACOREAPI bool BNCoreEnumFromString(const char* enumName, const char* value, size_t* result); + #ifdef __cplusplus } #endif diff --git a/docs/about/open-source.md b/docs/about/open-source.md index 9f9f70e3..65780aec 100644 --- a/docs/about/open-source.md +++ b/docs/about/open-source.md @@ -37,6 +37,7 @@ The previous tools are used in the generation of our documentation, but are not - [curl] ([curl license] - MIT) - [xxHash] ([xxHash License] - 2-clause BSD) - [botan] ([botan license] - 2-clause BSD) + - [fmt] ([fmt license] - MIT) * Core (Rust) - [Rust] ([Rust license] - Apache 2.0 / MIT) @@ -423,6 +424,8 @@ Please note that we offer no support for running Binary Ninja with modified Qt l [fallible-iterator license]: https://github.com/sfackler/rust-fallible-iterator/blob/master/LICENSE-MIT [flate2]: https://github.com/rust-lang/flate2-rs [flate2 license]: https://github.com/rust-lang/flate2-rs/blob/main/LICENSE-MIT +[fmt]: https://github.com/fmtlib/fmt +[fmt license]: https://github.com/fmtlib/fmt/blob/master/LICENSE [fnv]: https://github.com/servo/rust-fnv [fnv license]: https://github.com/servo/rust-fnv/blob/master/LICENSE-MIT [form_urlencoded]: https://github.com/servo/rust-url @@ -162,6 +162,55 @@ void BinaryNinja::LogAlert(const char* fmt, ...) } +void BinaryNinja::LogFV(BNLogLevel level, fmt::string_view format, fmt::format_args args) +{ + std::string value = fmt::vformat(format, args); + Log(level, "%s", value.c_str()); +} + + +void BinaryNinja::LogTraceFV(fmt::string_view format, fmt::format_args args) +{ + std::string value = fmt::vformat(format, args); + LogTrace("%s", value.c_str()); +} + + +void BinaryNinja::LogDebugFV(fmt::string_view format, fmt::format_args args) +{ + std::string value = fmt::vformat(format, args); + LogDebug("%s", value.c_str()); +} + + +void BinaryNinja::LogInfoFV(fmt::string_view format, fmt::format_args args) +{ + std::string value = fmt::vformat(format, args); + LogInfo("%s", value.c_str()); +} + + +void BinaryNinja::LogWarnFV(fmt::string_view format, fmt::format_args args) +{ + std::string value = fmt::vformat(format, args); + LogWarn("%s", value.c_str()); +} + + +void BinaryNinja::LogErrorFV(fmt::string_view format, fmt::format_args args) +{ + std::string value = fmt::vformat(format, args); + LogError("%s", value.c_str()); +} + + +void BinaryNinja::LogAlertFV(fmt::string_view format, fmt::format_args args) +{ + std::string value = fmt::vformat(format, args); + LogAlert("%s", value.c_str()); +} + + void BinaryNinja::LogToStdout(BNLogLevel minimumLevel) { BNLogToStdout(minimumLevel); @@ -267,6 +316,55 @@ void Logger::LogAlert(const char* fmt, ...) } +void Logger::LogFV(BNLogLevel level, fmt::string_view format, fmt::format_args args) +{ + std::string value = fmt::vformat(format, args); + Log(level, "%s", value.c_str()); +} + + +void Logger::LogTraceFV(fmt::string_view format, fmt::format_args args) +{ + std::string value = fmt::vformat(format, args); + LogTrace("%s", value.c_str()); +} + + +void Logger::LogDebugFV(fmt::string_view format, fmt::format_args args) +{ + std::string value = fmt::vformat(format, args); + LogDebug("%s", value.c_str()); +} + + +void Logger::LogInfoFV(fmt::string_view format, fmt::format_args args) +{ + std::string value = fmt::vformat(format, args); + LogInfo("%s", value.c_str()); +} + + +void Logger::LogWarnFV(fmt::string_view format, fmt::format_args args) +{ + std::string value = fmt::vformat(format, args); + LogWarn("%s", value.c_str()); +} + + +void Logger::LogErrorFV(fmt::string_view format, fmt::format_args args) +{ + std::string value = fmt::vformat(format, args); + LogError("%s", value.c_str()); +} + + +void Logger::LogAlertFV(fmt::string_view format, fmt::format_args args) +{ + std::string value = fmt::vformat(format, args); + LogAlert("%s", value.c_str()); +} + + string Logger::GetName() { char* name = BNLoggerGetName(m_object); diff --git a/metadata.cpp b/metadata.cpp index 253d03de..c1ba34a3 100644 --- a/metadata.cpp +++ b/metadata.cpp @@ -299,7 +299,7 @@ vector<uint8_t> Metadata::GetRaw() const return result; } -vector<Ref<Metadata>> Metadata::GetArray() +vector<Ref<Metadata>> Metadata::GetArray() const { size_t size = 0; BNMetadata** data = BNMetadataGetArray(m_object, &size); @@ -311,7 +311,7 @@ vector<Ref<Metadata>> Metadata::GetArray() return result; } -map<string, Ref<Metadata>> Metadata::GetKeyValueStore() +map<string, Ref<Metadata>> Metadata::GetKeyValueStore() const { BNMetadataValueStore* data = BNMetadataGetValueStore(m_object); map<string, Ref<Metadata>> result; @@ -1233,8 +1233,6 @@ std::vector<TypeDefinitionLine> Type::GetLines(const TypeContainer& types, const string Type::GetSizeSuffix(size_t size) { - char sizeStr[32]; - switch (size) { case 0: @@ -1252,8 +1250,7 @@ string Type::GetSizeSuffix(size_t size) case 16: return ".o"; default: - snprintf(sizeStr, sizeof(sizeStr), ".%" PRIuPTR, size); - return sizeStr; + return fmt::format(".{}", size); } } @@ -18,7 +18,7 @@ std::string BINARYNINJAUIAPI getStringForLocalVariable(ArchitectureRef arch, Fun std::string BINARYNINJAUIAPI getStringForRegisterValue(ArchitectureRef arch, BinaryNinja::RegisterValue value); std::string BINARYNINJAUIAPI getPossibleValueSetStateName(BNRegisterValueType state); std::string BINARYNINJAUIAPI getStringForIntegerValue(int64_t value); -std::string BINARYNINJAUIAPI getStringForIntegerValue(uint64_t value); +std::string BINARYNINJAUIAPI getStringForUIntegerValue(uint64_t value); std::string BINARYNINJAUIAPI getStringForPossibleValueSet(ArchitectureRef arch, const BinaryNinja::PossibleValueSet& values); std::string BINARYNINJAUIAPI getStringForInstructionDataflowDetails(BinaryViewRef data, ArchitectureRef arch, FunctionRef func, uint64_t address); std::optional<BinaryNinja::PossibleValueSet> BINARYNINJAUIAPI getPossibleValueSetForToken(View* view, BinaryViewRef data, ArchitectureRef arch, @@ -34,6 +34,16 @@ bool BINARYNINJAUIAPI isBinaryNinjaDataBase(QFileInfo& info, QFileAccessor& acce PlatformRef BINARYNINJAUIAPI getOrAskForPlatform(QWidget* parent, BinaryViewRef data); PlatformRef BINARYNINJAUIAPI getOrAskForPlatform(QWidget* parent, PlatformRef defaultValue); + +namespace fmt +{ + template<typename... T> + QString qformat(format_string<T...> fmt, T&&... args) + { + return QString::fromStdString(vformat(fmt, make_format_args(args...))); + } +} + /*! @} */ diff --git a/vendor/fmt b/vendor/fmt new file mode 160000 +Subproject f5e54359df4c26b6230fc61d38aa29458139308 |
