From 04f9d0a0c31398651ecf52a853362aa328756011 Mon Sep 17 00:00:00 2001 From: Nathan Lanza Date: Thu, 15 Nov 2018 20:58:09 +0000 Subject: [PATCH] Implement basic DidAttach and DidLaunch for DynamicLoaderWindowsDYLD Summary: This commit implements basic DidAttach and DidLaunch for the windows DynamicLoader plugin which allow us to load shared libraries from the inferior. Reviewers: sas, zturner Reviewed By: zturner Differential Revision: https://reviews.llvm.org/D54544 llvm-svn: 346994 --- .../test/functionalities/windows_dyld/Makefile | 14 +++++++ .../windows_dyld/TestWindowsDYLD.py | 42 ++++++++++++++++++++ .../test/functionalities/windows_dyld/dllfunc.c | 19 +++++++++ .../test/functionalities/windows_dyld/dllfunc.mk | 7 ++++ .../test/functionalities/windows_dyld/main.c | 19 +++++++++ .../Python/lldbsuite/test/make/Makefile.rules | 4 +- .../Windows-DYLD/DynamicLoaderWindowsDYLD.cpp | 46 +++++++++++++++++++++- 7 files changed, 147 insertions(+), 4 deletions(-) create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/windows_dyld/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/windows_dyld/TestWindowsDYLD.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/windows_dyld/dllfunc.c create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/windows_dyld/dllfunc.mk create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/windows_dyld/main.c diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/windows_dyld/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/windows_dyld/Makefile new file mode 100644 index 0000000..8289e15 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/windows_dyld/Makefile @@ -0,0 +1,14 @@ +LEVEL := ../../make + +LD_EXTRAS := -ldllfunc +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules + +a.out: dllfunc + +dllfunc: + $(MAKE) VERBOSE=1 VPATH=$(SRCDIR) -I $(SRCDIR) -f $(SRCDIR)/dllfunc.mk + +clean:: + $(MAKE) -f $(SRCDIR)/dllfunc.mk clean diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/windows_dyld/TestWindowsDYLD.py b/lldb/packages/Python/lldbsuite/test/functionalities/windows_dyld/TestWindowsDYLD.py new file mode 100644 index 0000000..77d4e71 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/windows_dyld/TestWindowsDYLD.py @@ -0,0 +1,42 @@ +""" +Test that breakpoints work in a DLL +""" + +from __future__ import print_function + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +@skipUnlessWindows +class WindowsDLLTestCase(TestBase): + def setUP(self): + TestBase.setUp(self) + self.build() + + def test_dll_linking(self): + """test that the debugger works with DLLs""" + + exe = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target and target.IsValid(), "Target is valid") + + self.runCmd("breakpoint set --file main.c --line 16") + self.runCmd("breakpoint set --file dllfunc.c --line 18") + + process = target.LaunchSimple(None, None, self.get_process_working_directory()) + + self.expect("p x", "16") + self.runCmd("thread step-out") + self.expect("p x", "16") + self.expect("thread step-in") + self.expect("thread step-in") + self.expect("p n", "8") + self.runCmd("c") + self.expect("p x", "64") + self.runCmd("breakpoint delete 2") + self.runCmd("c") + + self.assertEqual(process.GetExitStatus(), 336, PROCESS_EXITED) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/windows_dyld/dllfunc.c b/lldb/packages/Python/lldbsuite/test/functionalities/windows_dyld/dllfunc.c new file mode 100644 index 0000000..aadf4e3 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/windows_dyld/dllfunc.c @@ -0,0 +1,19 @@ +//===-- a.c -----------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include + +BOOL WINAPI DllMain(HINSTANCE h, DWORD reason, void* reserved) { + return TRUE; +} + +int __declspec(dllexport) DllFunc(int n) { + int x = n * n; + return x; // set breakpoint here +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/windows_dyld/dllfunc.mk b/lldb/packages/Python/lldbsuite/test/functionalities/windows_dyld/dllfunc.mk new file mode 100644 index 0000000..f282344 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/windows_dyld/dllfunc.mk @@ -0,0 +1,7 @@ +LEVEL := ../../make + +DYLIB_NAME := dllfunc +DYLIB_C_SOURCES := dllfunc.c +DYLIB_ONLY := YES + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/windows_dyld/main.c b/lldb/packages/Python/lldbsuite/test/functionalities/windows_dyld/main.c new file mode 100644 index 0000000..4b62744 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/windows_dyld/main.c @@ -0,0 +1,19 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include + +int __declspec(dllimport) DllFunc(int n); + +int main(int argc, char ** argv) { + int x = DllFunc(4); + int y = DllFunc(8); // set breakpoint here + int z = DllFunc(16); + return x + y + z; +} diff --git a/lldb/packages/Python/lldbsuite/test/make/Makefile.rules b/lldb/packages/Python/lldbsuite/test/make/Makefile.rules index 1a36010..8990651 100644 --- a/lldb/packages/Python/lldbsuite/test/make/Makefile.rules +++ b/lldb/packages/Python/lldbsuite/test/make/Makefile.rules @@ -525,7 +525,7 @@ EXE = $(DYLIB_FILENAME) endif else $(EXE) : $(OBJECTS) $(ARCHIVE_NAME) - $(LD) $(OBJECTS) $(LDFLAGS) $(ARCHIVE_NAME) -o "$(EXE)" + "$(LD)" $(OBJECTS) $(LDFLAGS) $(ARCHIVE_NAME) -o "$(EXE)" ifneq "$(CODESIGN)" "" $(CODESIGN) -s - "$(EXE)" endif @@ -582,7 +582,7 @@ ifneq "$(DS)" "" endif endif else - $(LD) $(DYLIB_OBJECTS) $(LDFLAGS) -shared -o "$(DYLIB_FILENAME)" + "$(LD)" $(DYLIB_OBJECTS) $(LDFLAGS) -shared -o "$(DYLIB_FILENAME)" ifeq "$(SPLIT_DEBUG_SYMBOLS)" "YES" $(OBJCOPY) --only-keep-debug "$(DYLIB_FILENAME)" "$(DYLIB_FILENAME).debug" $(OBJCOPY) --strip-debug --add-gnu-debuglink="$(DYLIB_FILENAME).debug" "$(DYLIB_FILENAME)" "$(DYLIB_FILENAME)" diff --git a/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp b/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp index 6502d7a..bb52e6b 100644 --- a/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp @@ -10,12 +10,14 @@ #include "DynamicLoaderWindowsDYLD.h" +#include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Target.h" #include "lldb/Target/ThreadPlanStepInstruction.h" +#include "lldb/Utility/Log.h" #include "llvm/ADT/Triple.h" @@ -60,9 +62,49 @@ DynamicLoader *DynamicLoaderWindowsDYLD::CreateInstance(Process *process, return nullptr; } -void DynamicLoaderWindowsDYLD::DidAttach() {} +void DynamicLoaderWindowsDYLD::DidAttach() { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + if (log) + log->Printf("DynamicLoaderWindowsDYLD::%s()", __FUNCTION__); -void DynamicLoaderWindowsDYLD::DidLaunch() {} + DidLaunch(); + + m_process->LoadModules(); +} + +void DynamicLoaderWindowsDYLD::DidLaunch() { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + if (log) + log->Printf("DynamicLoaderWindowsDYLD::%s()", __FUNCTION__); + + ModuleSP executable = GetTargetExecutable(); + + if (!executable.get()) + return; + + // Try to fetch the load address of the file from the process, since there + // could be randomization of the load address. + + // It might happen that the remote has a different dir for the file, so we + // only send the basename of the executable in the query. I think this is safe + // because I doubt that two executables with the same basenames are loaded in + // memory... + FileSpec file_spec( + executable->GetPlatformFileSpec().GetFilename().GetCString()); + bool is_loaded; + addr_t base_addr = 0; + lldb::addr_t load_addr; + Status error = m_process->GetFileLoadAddress(file_spec, is_loaded, load_addr); + if (error.Success() && is_loaded) { + base_addr = load_addr; + } + + UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, base_addr, false); + + ModuleList module_list; + module_list.Append(executable); + m_process->GetTarget().ModulesDidLoad(module_list); +} Status DynamicLoaderWindowsDYLD::CanLoadImage() { return Status(); } -- 2.7.4