[Lldb-commits] [lldb] 7e49b0d - [lldb] Fix nullptr dereference on running x86 binary with x86-disabled llvm (#82603)
via lldb-commits
lldb-commits at lists.llvm.org
Mon Apr 15 23:53:37 PDT 2024
Author: Daniil Kovalev
Date: 2024-04-16T09:53:33+03:00
New Revision: 7e49b0d5a67f212e84f8ec0ec2e39a6a8673bfaf
URL: https://github.com/llvm/llvm-project/commit/7e49b0d5a67f212e84f8ec0ec2e39a6a8673bfaf
DIFF: https://github.com/llvm/llvm-project/commit/7e49b0d5a67f212e84f8ec0ec2e39a6a8673bfaf.diff
LOG: [lldb] Fix nullptr dereference on running x86 binary with x86-disabled llvm (#82603)
If `LLVM_TARGETS_TO_BUILD` does not contain `X86` and we try to run an
x86 binary in lldb, we get a `nullptr` dereference in
`LLVMDisasmInstruction(...)`. We try to call `getDisAsm()` method on a
`LLVMDisasmContext *DC` which is null. The pointer is passed from
`x86AssemblyInspectionEngine::instruction_length(...)` and is originally
`m_disasm_context` member of `x86AssemblyInspectionEngine`. This should
be filled by `LLVMCreateDisasm(...)` in the class constructor, but not
having X86 target enabled in llvm makes
`TargetRegistry::lookupTarget(...)` call return `nullptr`, which results
in `m_disasm_context` initialized with `nullptr` as well.
This patch adds if statements against `m_disasm_context` in
`x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(...)`
and `x86AssemblyInspectionEngine::FindFirstNonPrologueInstruction(...)`
so subsequent calls to
`x86AssemblyInspectionEngine::instruction_length(...)` do not cause a
null pointer dereference.
Added:
lldb/unittests/UnwindAssembly/x86-but-no-x86-target/CMakeLists.txt
lldb/unittests/UnwindAssembly/x86-but-no-x86-target/Testx86AssemblyInspectionEngine.cpp
Modified:
lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
lldb/unittests/UnwindAssembly/CMakeLists.txt
Removed:
################################################################################
diff --git a/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp b/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
index 2032c5a68d054c..6bfaa54135a959 100644
--- a/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
+++ b/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
@@ -909,6 +909,9 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
if (!m_register_map_initialized)
return false;
+ if (m_disasm_context == nullptr)
+ return false;
+
addr_t current_func_text_offset = 0;
int current_sp_bytes_offset_from_fa = 0;
bool is_aligned = false;
@@ -1570,6 +1573,9 @@ bool x86AssemblyInspectionEngine::FindFirstNonPrologueInstruction(
if (!m_register_map_initialized)
return false;
+ if (m_disasm_context == nullptr)
+ return false;
+
while (offset < size) {
int regno;
int insn_len;
diff --git a/lldb/unittests/UnwindAssembly/CMakeLists.txt b/lldb/unittests/UnwindAssembly/CMakeLists.txt
index 136fcd9ae97981..d6e4471af4ecb3 100644
--- a/lldb/unittests/UnwindAssembly/CMakeLists.txt
+++ b/lldb/unittests/UnwindAssembly/CMakeLists.txt
@@ -9,3 +9,7 @@ endif()
if ("X86" IN_LIST LLVM_TARGETS_TO_BUILD)
add_subdirectory(x86)
endif()
+
+if (NOT "X86" IN_LIST LLVM_TARGETS_TO_BUILD)
+ add_subdirectory(x86-but-no-x86-target)
+endif()
diff --git a/lldb/unittests/UnwindAssembly/x86-but-no-x86-target/CMakeLists.txt b/lldb/unittests/UnwindAssembly/x86-but-no-x86-target/CMakeLists.txt
new file mode 100644
index 00000000000000..d28e9629a64cfc
--- /dev/null
+++ b/lldb/unittests/UnwindAssembly/x86-but-no-x86-target/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_lldb_unittest(UnwindAssemblyX86ButNoX86TargetTests
+ Testx86AssemblyInspectionEngine.cpp
+ LINK_LIBS
+ lldbCore
+ lldbSymbol
+ lldbPluginUnwindAssemblyX86
+ LINK_COMPONENTS
+ Support
+ ${LLVM_TARGETS_TO_BUILD}
+ )
diff --git a/lldb/unittests/UnwindAssembly/x86-but-no-x86-target/Testx86AssemblyInspectionEngine.cpp b/lldb/unittests/UnwindAssembly/x86-but-no-x86-target/Testx86AssemblyInspectionEngine.cpp
new file mode 100644
index 00000000000000..ed093d146440e3
--- /dev/null
+++ b/lldb/unittests/UnwindAssembly/x86-but-no-x86-target/Testx86AssemblyInspectionEngine.cpp
@@ -0,0 +1,103 @@
+//===-- Testx86AssemblyInspectionEngine.cpp -------------------------------===//
+
+//
+// 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 "gtest/gtest.h"
+
+#include "Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h"
+#include "lldb/Core/AddressRange.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Utility/ArchSpec.h"
+
+#include "llvm/Support/TargetSelect.h"
+
+#include <memory>
+#include <vector>
+
+using namespace lldb;
+using namespace lldb_private;
+
+class Testx86AssemblyInspectionEngine : public testing::Test {
+public:
+ static void SetUpTestCase();
+};
+
+void Testx86AssemblyInspectionEngine::SetUpTestCase() {
+ llvm::InitializeAllTargets();
+ llvm::InitializeAllAsmPrinters();
+ llvm::InitializeAllTargetMCs();
+ llvm::InitializeAllDisassemblers();
+}
+
+// only defining the register names / numbers that the unwinder is actually
+// using today
+
+// names should match the constants below. These will be the eRegisterKindLLDB
+// register numbers.
+
+const char *x86_64_reg_names[] = {"rax", "rbx", "rcx", "rdx", "rsp", "rbp",
+ "rsi", "rdi", "r8", "r9", "r10", "r11",
+ "r12", "r13", "r14", "r15", "rip"};
+
+enum x86_64_regs {
+ k_rax = 0,
+ k_rbx = 1,
+ k_rcx = 2,
+ k_rdx = 3,
+ k_rsp = 4,
+ k_rbp = 5,
+ k_rsi = 6,
+ k_rdi = 7,
+ k_r8 = 8,
+ k_r9 = 9,
+ k_r10 = 10,
+ k_r11 = 11,
+ k_r12 = 12,
+ k_r13 = 13,
+ k_r14 = 14,
+ k_r15 = 15,
+ k_rip = 16
+};
+
+std::unique_ptr<x86AssemblyInspectionEngine> Getx86_64Inspector() {
+
+ ArchSpec arch("x86_64-apple-macosx");
+ std::unique_ptr<x86AssemblyInspectionEngine> engine(
+ new x86AssemblyInspectionEngine(arch));
+
+ std::vector<x86AssemblyInspectionEngine::lldb_reg_info> lldb_regnums;
+ int i = 0;
+ for (const auto &name : x86_64_reg_names) {
+ x86AssemblyInspectionEngine::lldb_reg_info ri;
+ ri.name = name;
+ ri.lldb_regnum = i++;
+ lldb_regnums.push_back(ri);
+ }
+
+ engine->Initialize(lldb_regnums);
+ return engine;
+}
+
+TEST_F(Testx86AssemblyInspectionEngine, TestSimple64bitFrameFunction) {
+ std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();
+
+ // 'int main() { }' compiled for x86_64-apple-macosx with clang
+ uint8_t data[] = {
+ 0x55, // offset 0 -- pushq %rbp
+ 0x48, 0x89, 0xe5, // offset 1 -- movq %rsp, %rbp
+ 0x31, 0xc0, // offset 4 -- xorl %eax, %eax
+ 0x5d, // offset 6 -- popq %rbp
+ 0xc3 // offset 7 -- retq
+ };
+
+ AddressRange sample_range(0x1000, sizeof(data));
+
+ UnwindPlan unwind_plan(eRegisterKindLLDB);
+ EXPECT_FALSE(engine->GetNonCallSiteUnwindPlanFromAssembly(
+ data, sizeof(data), sample_range, unwind_plan));
+}
More information about the lldb-commits
mailing list