Skip to content

[lldb] Add a fuzzer for the DWARF Expression Evaluator #114286

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 31, 2024

Conversation

JDevlieghere
Copy link
Member

This adds a fuzzer for the DWARF expression evaluator. It does pretty much the same thing as what we do in the corresponding unit test but with data generated by libfuzzer.

This adds a fuzzer for the DWARF expression evaluator. It does pretty
much the same thing as what we do in the corresponding unit test but
with data generated by libfuzzer.
@llvmbot
Copy link
Member

llvmbot commented Oct 30, 2024

@llvm/pr-subscribers-lldb

Author: Jonas Devlieghere (JDevlieghere)

Changes

This adds a fuzzer for the DWARF expression evaluator. It does pretty much the same thing as what we do in the corresponding unit test but with data generated by libfuzzer.


Full diff: https://github.com/llvm/llvm-project/pull/114286.diff

3 Files Affected:

  • (modified) lldb/tools/lldb-fuzzer/CMakeLists.txt (+1)
  • (added) lldb/tools/lldb-fuzzer/lldb-dwarf-expression-fuzzer/CMakeLists.txt (+34)
  • (added) lldb/tools/lldb-fuzzer/lldb-dwarf-expression-fuzzer/lldb-dwarf-expression-fuzzer.cpp (+83)
diff --git a/lldb/tools/lldb-fuzzer/CMakeLists.txt b/lldb/tools/lldb-fuzzer/CMakeLists.txt
index 4c081a9de53e2d..e384ca18583981 100644
--- a/lldb/tools/lldb-fuzzer/CMakeLists.txt
+++ b/lldb/tools/lldb-fuzzer/CMakeLists.txt
@@ -1,4 +1,5 @@
 add_subdirectory(lldb-commandinterpreter-fuzzer)
+add_subdirectory(lldb-dwarf-expression-fuzzer)
 add_subdirectory(lldb-expression-fuzzer)
 add_subdirectory(lldb-target-fuzzer)
 add_subdirectory(utils)
diff --git a/lldb/tools/lldb-fuzzer/lldb-dwarf-expression-fuzzer/CMakeLists.txt b/lldb/tools/lldb-fuzzer/lldb-dwarf-expression-fuzzer/CMakeLists.txt
new file mode 100644
index 00000000000000..374a80b7bb83af
--- /dev/null
+++ b/lldb/tools/lldb-fuzzer/lldb-dwarf-expression-fuzzer/CMakeLists.txt
@@ -0,0 +1,34 @@
+set(LLVM_LINK_COMPONENTS
+  Support
+  )
+
+add_llvm_fuzzer(lldb-dwarf-expression-fuzzer
+  EXCLUDE_FROM_ALL
+  lldb-dwarf-expression-fuzzer.cpp
+  )
+
+include_directories(${LLDB_SOURCE_ROOT})
+
+if(TARGET lldb-dwarf-expression-fuzzer)
+  target_include_directories(lldb-dwarf-expression-fuzzer PRIVATE ..)
+  target_link_libraries(lldb-dwarf-expression-fuzzer
+    PRIVATE
+    lldbCore
+    lldbPluginExpressionParserClang
+    lldbPluginPlatformLinux
+    lldbPluginTypeSystemClang
+    lldbFuzzerUtils
+    )
+
+  add_custom_command(TARGET lldb-dwarf-expression-fuzzer PRE_BUILD
+    COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/fuzzer-artifacts/dwarf-expression-artifacts
+    )
+
+  add_custom_target(fuzz-lldb-dwarf-expression
+    COMMENT "Running the LLDB target fuzzer..."
+    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/fuzzer-artifacts/dwarf-expression-artifacts
+    COMMAND $<TARGET_FILE:lldb-dwarf-expression-fuzzer> -artifact_prefix=dwarf-expression-
+    USES_TERMINAL
+    )
+  set_target_properties(fuzz-lldb-dwarf-expression PROPERTIES FOLDER "LLDB/Fuzzer")
+endif()
diff --git a/lldb/tools/lldb-fuzzer/lldb-dwarf-expression-fuzzer/lldb-dwarf-expression-fuzzer.cpp b/lldb/tools/lldb-fuzzer/lldb-dwarf-expression-fuzzer/lldb-dwarf-expression-fuzzer.cpp
new file mode 100644
index 00000000000000..65c160d7b731c1
--- /dev/null
+++ b/lldb/tools/lldb-fuzzer/lldb-dwarf-expression-fuzzer/lldb-dwarf-expression-fuzzer.cpp
@@ -0,0 +1,83 @@
+//===-- lldb-target-fuzzer.cpp - Fuzz target creation ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "utils/TempFile.h"
+
+#include "Plugins/Platform/Linux/PlatformLinux.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::plugin::dwarf;
+using namespace lldb_fuzzer;
+
+extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
+  FileSystem::Initialize();
+  HostInfo::Initialize();
+  platform_linux::PlatformLinux::Initialize();
+  return 0;
+}
+
+static void Evaluate(llvm::ArrayRef<uint8_t> expr,
+                     lldb::ModuleSP module_sp = {}, DWARFUnit *unit = nullptr,
+                     ExecutionContext *exe_ctx = nullptr) {
+  DataExtractor extractor(expr.data(), expr.size(), lldb::eByteOrderLittle,
+                          /*addr_size*/ 4);
+
+  llvm::Expected<Value> result =
+      DWARFExpression::Evaluate(exe_ctx, /*reg_ctx*/ nullptr, module_sp,
+                                extractor, unit, lldb::eRegisterKindLLDB,
+                                /*initial_value_ptr*/ nullptr,
+                                /*object_address_ptr*/ nullptr);
+
+  if (!result)
+    llvm::consumeError(result.takeError());
+}
+
+class MockTarget : public Target {
+public:
+  MockTarget(Debugger &debugger, const ArchSpec &target_arch,
+             const lldb::PlatformSP &platform_sp, llvm::ArrayRef<uint8_t> data)
+      : Target(debugger, target_arch, platform_sp, true), m_data(data) {}
+
+  size_t ReadMemory(const Address &addr, void *dst, size_t dst_len,
+                    Status &error, bool force_live_memory = false,
+                    lldb::addr_t *load_addr_ptr = nullptr) override {
+    std::memcpy(dst, m_data.data(), m_data.size());
+    return m_data.size();
+  }
+
+private:
+  llvm::ArrayRef<uint8_t> m_data;
+};
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
+  // We're going to use the first half of the input data as the DWARF expression
+  // and the second half as memory.
+  const size_t partition = size / 2;
+  llvm::ArrayRef expression_data(data, partition);
+  llvm::ArrayRef memory_data(data + partition, size - partition);
+
+  // Create a mock target for reading memory.
+  ArchSpec arch("i386-pc-linux");
+  Platform::SetHostPlatform(
+      platform_linux::PlatformLinux::CreateInstance(true, &arch));
+  lldb::DebuggerSP debugger_sp = Debugger::CreateInstance();
+  lldb::PlatformSP platform_sp;
+  auto target_sp = std::make_shared<MockTarget>(*debugger_sp, arch, platform_sp,
+                                                memory_data);
+  ExecutionContext exe_ctx(static_cast<lldb::TargetSP>(target_sp), false);
+
+  Evaluate(expression_data);
+  return 0;
+}

@JDevlieghere
Copy link
Member Author

As an example, this found the issue fixed in #114136 and a crash in lldb_private::Value that I haven't looked into yet.

Copy link
Member

@medismailben medismailben left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with comment

@chelcassanova
Copy link
Contributor

LGTM!

@JDevlieghere JDevlieghere merged commit 42fae38 into llvm:main Oct 31, 2024
7 checks passed
@JDevlieghere JDevlieghere deleted the dwarf-expression-fuzzer branch October 31, 2024 17:27
smallp-o-p pushed a commit to smallp-o-p/llvm-project that referenced this pull request Nov 3, 2024
This adds a fuzzer for the DWARF expression evaluator. It does pretty
much the same thing as what we do in the corresponding unit test but
with data generated by libfuzzer.
NoumanAmir657 pushed a commit to NoumanAmir657/llvm-project that referenced this pull request Nov 4, 2024
This adds a fuzzer for the DWARF expression evaluator. It does pretty
much the same thing as what we do in the corresponding unit test but
with data generated by libfuzzer.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants