Skip to content

Commit 44d5b5f

Browse files
cblichmanncopybara-github
authored andcommitted
Refactor logging and use plain msg() in IDA
This prevents a dead-lock with the log executor that surfaced when building with IDA SDK 7.6. Additionally, the log executor was not really necessary at all, as `msg()`/`vmsg()` are marked as being thread-safe. Also remove `executable` and `executable64` from BinDiff config. Those were never actually used by the Java UI in released versions and we do not support using BinDiff with `idat`/`idat64` anyways. This change also actually implements file logging in the plugins if requested. Before, this could only be requested on the command-line. Other chages: - Suppress MSVC compiler warnings in IDA SDK, disable some globally PiperOrigin-RevId: 374132575 Change-Id: I74c31664a5f2aad1c1bda907521b6028c8a8c8ab
1 parent bd31841 commit 44d5b5f

File tree

9 files changed

+54
-54
lines changed

9 files changed

+54
-54
lines changed

cmake/CompileOptions.cmake

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") # GCC
2727
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") # Clang or Apple Clang
2828
add_compile_options(-Wno-nullability-completeness)
2929
elseif(MSVC) # Visual Studio
30-
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
31-
30+
add_compile_options(
31+
/wd4018 # signed/unsigned mismatch
32+
/wd4244 # 'argument' conversion, possible loss of data
33+
/wd4267 # 'initializing' conversion, possible loss of data
34+
)
3235
# Use the static runtime
3336
foreach(flag_var CMAKE_C_FLAGS CMAKE_CXX_FLAGS
3437
CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG
@@ -60,6 +63,7 @@ if(UNIX)
6063
endif()
6164
elseif(WIN32)
6265
add_definitions(
66+
-D_CRT_SECURE_NO_WARNINGS
6367
# Protobuf iterators trigger deprecation warnings
6468
-D_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS
6569
# Do not define min/max macros which collide with std::min()/std::max()

ida/begin_idasdk.inc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@
4444
#pragma GCC diagnostic push
4545
#pragma GCC diagnostic ignored "-Wvarargs"
4646
#elif _MSC_VER
47+
#pragma warning(push)
48+
#pragma warning(disable : 4005)
49+
#pragma warning(disable : 4244)
50+
#pragma warning(disable : 4267)
4751
#endif
4852

4953
// Now include the problematic header, end_idasdk.inc will clean up again.

ida/end_idasdk.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#elif __GNUC__
2121
#pragma GCC diagnostic pop
2222
#elif _MSC_VER
23+
#pragma warning(pop)
2324
#endif
2425

2526
#undef uint128

ida/log_sink.cc

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
#include "third_party/zynamics/binexport/ida/log_sink.h"
1616

17+
#include <algorithm>
18+
1719
// clang-format off
1820
#include "third_party/zynamics/binexport/ida/begin_idasdk.inc" // NOLINT
1921
#include <kernwin.hpp> // NOLINT
@@ -27,20 +29,12 @@
2729
namespace security::binexport {
2830

2931
void IdaLogSink::Send(const not_absl::LogEntry& entry) {
30-
struct LoggingExecutor : public exec_request_t {
31-
explicit LoggingExecutor(absl::string_view text_message)
32-
: text_message(text_message) {}
33-
34-
int idaapi execute() override {
35-
msg("%s\n", text_message.c_str());
36-
return 0;
37-
}
38-
39-
std::string text_message;
40-
} executor(entry.text_message());
41-
42-
// Do all logging in IDA's main thread.
43-
execute_sync(executor, MFF_FAST);
32+
auto message = entry.text_message();
33+
// Output up to 8K of log data (including the new line).
34+
// Note: msg() and vmsg() are thread-safe.
35+
msg("%.*s\n",
36+
static_cast<int>(std::clamp(message.size(), size_t(0), size_t(8191))),
37+
message.data());
4438
}
4539

4640
} // namespace security::binexport

ida/main_plugin.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,9 +333,10 @@ ssize_t idaapi UiHook(void*, int event_id, va_list arguments) {
333333
Plugin::LoadStatus Plugin::Init() {
334334
alsologtostderr_ =
335335
absl::AsciiStrToUpper(GetArgument("AlsoLogToStdErr")) == "TRUE";
336+
log_filename_ = GetArgument("LogFile");
336337
if (auto status = InitLogging(LoggingOptions{}
337338
.set_alsologtostderr(alsologtostderr_)
338-
.set_log_filename(GetArgument("LogFile")),
339+
.set_log_filename(log_filename_),
339340
absl::make_unique<IdaLogSink>());
340341
!status.ok()) {
341342
LOG(INFO) << "Error initializing logging, skipping BinExport plugin";

ida/main_plugin.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#ifndef IDA_MAIN_PLUGIN_H_
1616
#define IDA_MAIN_PLUGIN_H_
1717

18+
#include <string>
19+
1820
#include "third_party/zynamics/binexport/ida/plugin.h"
1921

2022
namespace security::binexport {
@@ -30,11 +32,13 @@ class Plugin : public IdaPlugin<Plugin> {
3032
void Terminate() override;
3133

3234
bool alsologtostderr() const { return alsologtostderr_; }
35+
const std::string& log_filename() const { return log_filename_; }
3336

3437
bool x86_noreturn_heuristic() const { return x86_noreturn_heuristic_; }
3538

3639
private:
3740
bool alsologtostderr_ = false;
41+
std::string log_filename_;
3842

3943
// Whether to use an X86-specific heuristic to identify functions that do not
4044
// return. See FlowGraph::FindBasicBlockBreaks() for details.

util/filesystem_test.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ TEST(FileSystemTest, Filenames) {
6161
EXPECT_THAT(ReplaceFileExtension(
6262
absl::StrCat("subdir", kPathSeparator, "filename.ext"), ""),
6363
StrEq(absl::StrCat("subdir", kPathSeparator, "filename")));
64-
// Test that directories with a "." in them don't throw of extension
64+
// Test that directories with a "." in them don't throw off the extension
6565
// replacement.
6666
EXPECT_THAT(
6767
ReplaceFileExtension(

util/idb_export.cc

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -59,38 +59,36 @@ absl::Status ExportDatabase(const std::string& idb_path,
5959
return absl::NotFoundError(absl::StrCat("File not found: " + idb_path));
6060
}
6161

62-
std::string ida_exe = is_64bit ? options.ida_exe64 : options.ida_exe;
63-
if (ida_exe.empty()) {
6462
#ifdef _WIN32
65-
ida_exe = is_64bit ? "ida64.exe" : "ida.exe";
63+
const std::string ida_exe = is_64bit ? "ida64.exe" : "ida.exe";
6664
#else
67-
ida_exe = is_64bit ? "ida64" : "ida";
65+
const std::string ida_exe = is_64bit ? "ida64" : "ida";
6866
#endif
67+
std::vector<std::string> args;
68+
args.push_back(JoinPath(options.ida_dir, ida_exe));
69+
args.push_back("-A");
70+
args.push_back("-OBinExportAutoAction:BinExportBinary");
71+
args.push_back(absl::StrCat(
72+
"-OBinExportModule:",
73+
// Make the output name deterministic. When only specifying a directory,
74+
// BinExport will use the IDB's original executable name as the base name.
75+
JoinPath(options.export_dir,
76+
ReplaceFileExtension(Basename(idb_path), kBinExportExtension))));
77+
args.push_back(absl::StrCat("-OBinExportAlsoLogToStdErr:",
78+
OptionBool(options.alsologtostderr)));
79+
if (!options.log_filename.empty()) {
80+
args.push_back(absl::StrCat("-OBinExportLogFile:", options.log_filename));
6981
}
70-
std::vector<std::string> args = {
71-
JoinPath(options.ida_dir, ida_exe),
72-
"-A",
73-
absl::StrCat("-OBinExportModule:",
74-
// Make the output name deterministic. When only using
75-
// specifying a directory, BinExport will use the IDB's
76-
// original executable name as the base name.
77-
JoinPath(options.export_dir,
78-
ReplaceFileExtension(Basename(idb_path),
79-
kBinExportExtension))),
80-
absl::StrCat("-OBinExportX86NoReturnHeuristic:",
81-
OptionBool(options.x86_noreturn_heuristic)),
82-
absl::StrCat("-OBinExportAlsoLogToStdErr:",
83-
OptionBool(options.alsologtostderr)),
84-
"-OBinExportAutoAction:BinExportBinary",
85-
idb_path,
86-
};
82+
args.push_back(absl::StrCat("-OBinExportX86NoReturnHeuristic:",
83+
OptionBool(options.x86_noreturn_heuristic)));
84+
args.push_back(idb_path);
8785

8886
SetEnvironmentVariable("TVHEADLESS", "1");
89-
absl::StatusOr<int> exit_or = SpawnProcessAndWait(args);
87+
absl::StatusOr<int> exit = SpawnProcessAndWait(args);
9088

9189
// Reset environment variable.
9290
SetEnvironmentVariable("TVHEADLESS", /*value=*/"");
93-
return exit_or.status();
91+
return exit.status();
9492
}
9593

9694
absl::Status IdbExporter::Export(
@@ -105,7 +103,7 @@ absl::Status IdbExporter::Export(
105103
while (true) {
106104
std::string idb_path;
107105
{
108-
absl::MutexLock lock{&queue_mutex_};
106+
absl::MutexLock lock(&queue_mutex_);
109107
if (idb_paths_.empty()) {
110108
break;
111109
}

util/idb_export.h

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,6 @@ class IdbExporter {
4646
return *this;
4747
}
4848

49-
Options& set_ida_exe(std::string value) {
50-
ida_exe = std::move(value);
51-
return *this;
52-
}
53-
54-
Options& set_ida_exe64(std::string value) {
55-
ida_exe64 = std::move(value);
56-
return *this;
57-
}
58-
5949
Options& set_num_threads(int value) {
6050
num_threads = value;
6151
return *this;
@@ -66,17 +56,21 @@ class IdbExporter {
6656
return *this;
6757
}
6858

59+
Options& set_log_filename(std::string value) {
60+
log_filename = std::move(value);
61+
return *this;
62+
}
63+
6964
Options& set_x86_noreturn_heuristic(bool value) {
7065
x86_noreturn_heuristic = value;
7166
return *this;
7267
}
7368

7469
std::string export_dir; // Directory to export the files to
7570
std::string ida_dir; // IDA Pro installation directory
76-
std::string ida_exe; // Name of the IDA executable, 32-bit addresses
77-
std::string ida_exe64; // IDA executable, 64-bit addresses
7871
int num_threads = 1;
7972
bool alsologtostderr = false;
73+
std::string log_filename;
8074
bool x86_noreturn_heuristic = false;
8175
};
8276

0 commit comments

Comments
 (0)