From johnny.chen at apple.com Mon Jan 10 11:44:09 2011
From: johnny.chen at apple.com (Johnny Chen)
Date: Mon, 10 Jan 2011 17:44:09 -0000
Subject: [Lldb-commits] [lldb] r123181 - in
/lldb/trunk/test/python_api/frame: TestFrames.py main.c
Message-ID: <20110110174409.140C22A6C12C@llvm.org>
Author: johnny
Date: Mon Jan 10 11:44:08 2011
New Revision: 123181
URL: http://llvm.org/viewvc/llvm-project?rev=123181&view=rev
Log:
Fix wrong test case in main.c. Oops!
Modified:
lldb/trunk/test/python_api/frame/TestFrames.py
lldb/trunk/test/python_api/frame/main.c
Modified: lldb/trunk/test/python_api/frame/TestFrames.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/frame/TestFrames.py?rev=123181&r1=123180&r2=123181&view=diff
==============================================================================
--- lldb/trunk/test/python_api/frame/TestFrames.py (original)
+++ lldb/trunk/test/python_api/frame/TestFrames.py Mon Jan 10 11:44:08 2011
@@ -12,7 +12,6 @@
mydir = os.path.join("python_api", "frame")
- @unittest2.expectedFailure
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
@python_api_test
def test_get_arg_vals_for_call_stack_with_dsym(self):
@@ -20,7 +19,6 @@
self.buildDsym()
self.do_get_arg_vals()
- @unittest2.expectedFailure
@python_api_test
def test_get_arg_vals_for_call_stack_with_dwarf(self):
"""Exercise SBFrame.GetVariables() API to get argument vals."""
@@ -103,8 +101,6 @@
# o a((int)val=3, (char)ch='A')
print "Full stack traces when stopped on the breakpoint 'c':"
print session.getvalue()
- # rdar://problem/8801262
- # test failure: ./dotest.py -v -w -t -p TestFrames (argument values are wrong)
self.expect(session.getvalue(), "Argugment values displayed correctly",
exe=False,
substrs = ["a((int)val=1, (char)ch='A')",
Modified: lldb/trunk/test/python_api/frame/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/frame/main.c?rev=123181&r1=123180&r2=123181&view=diff
==============================================================================
--- lldb/trunk/test/python_api/frame/main.c (original)
+++ lldb/trunk/test/python_api/frame/main.c Mon Jan 10 11:44:08 2011
@@ -20,9 +20,9 @@
char my_ch = ch;
printf("a(val=%d, ch='%c')\n", val, ch);
if (val <= 1)
- return b(++val, ++ch);
+ return b(val+1, ch+1);
else if (val >= 3)
- return c(++val, ++ch);
+ return c(val+1, ch+1);
return val;
}
@@ -32,7 +32,7 @@
int my_val = val;
char my_ch = ch;
printf("b(val=%d, ch='%c')\n", val, ch);
- return c(++val, ++ch);
+ return c(val+1, ch+1);
}
int c(int val, char ch)
From gclayton at apple.com Mon Jan 10 13:28:56 2011
From: gclayton at apple.com (Greg Clayton)
Date: Mon, 10 Jan 2011 19:28:56 -0000
Subject: [Lldb-commits] [lldb] r123187 - in /lldb/trunk:
lldb.xcodeproj/project.pbxproj resources/LLDB-Info.plist
tools/debugserver/debugserver.xcodeproj/project.pbxproj
Message-ID: <20110110192856.3C88D2A6C12C@llvm.org>
Author: gclayton
Date: Mon Jan 10 13:28:56 2011
New Revision: 123187
URL: http://llvm.org/viewvc/llvm-project?rev=123187&view=rev
Log:
Bumped Xcode versions to lldb-39 and debugserver-125.
Modified:
lldb/trunk/lldb.xcodeproj/project.pbxproj
lldb/trunk/resources/LLDB-Info.plist
lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj
Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=123187&r1=123186&r2=123187&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Mon Jan 10 13:28:56 2011
@@ -2926,9 +2926,9 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 38;
+ CURRENT_PROJECT_VERSION = 39;
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 38;
+ DYLIB_CURRENT_VERSION = 39;
EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -2978,11 +2978,11 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 38;
+ CURRENT_PROJECT_VERSION = 39;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 38;
+ DYLIB_CURRENT_VERSION = 39;
EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -3052,7 +3052,7 @@
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = YES;
- CURRENT_PROJECT_VERSION = 38;
+ CURRENT_PROJECT_VERSION = 39;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -3087,11 +3087,11 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
COPY_PHASE_STRIP = YES;
- CURRENT_PROJECT_VERSION = 38;
+ CURRENT_PROJECT_VERSION = 39;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 38;
+ DYLIB_CURRENT_VERSION = 39;
EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -3140,7 +3140,7 @@
buildSettings = {
CODE_SIGN_IDENTITY = lldb_codesign;
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 38;
+ CURRENT_PROJECT_VERSION = 39;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"",
@@ -3178,7 +3178,7 @@
);
CODE_SIGN_IDENTITY = lldb_codesign;
COPY_PHASE_STRIP = YES;
- CURRENT_PROJECT_VERSION = 38;
+ CURRENT_PROJECT_VERSION = 39;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
Modified: lldb/trunk/resources/LLDB-Info.plist
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/resources/LLDB-Info.plist?rev=123187&r1=123186&r2=123187&view=diff
==============================================================================
--- lldb/trunk/resources/LLDB-Info.plist (original)
+++ lldb/trunk/resources/LLDB-Info.plist Mon Jan 10 13:28:56 2011
@@ -17,7 +17,7 @@
CFBundleSignature
????
CFBundleVersion
- 38
+ 39
CFBundleName
${EXECUTABLE_NAME}
Modified: lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj?rev=123187&r1=123186&r2=123187&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj Mon Jan 10 13:28:56 2011
@@ -460,7 +460,7 @@
i386,
);
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 124;
+ CURRENT_PROJECT_VERSION = 125;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
STRIP_INSTALLED_PRODUCT = NO;
@@ -478,7 +478,7 @@
x86_64,
i386,
);
- CURRENT_PROJECT_VERSION = 124;
+ CURRENT_PROJECT_VERSION = 125;
DEAD_CODE_STRIPPING = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
@@ -498,7 +498,7 @@
x86_64,
i386,
);
- CURRENT_PROJECT_VERSION = 124;
+ CURRENT_PROJECT_VERSION = 125;
DEAD_CODE_STRIPPING = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
@@ -515,7 +515,7 @@
buildSettings = {
"CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]" = "source/debugserver-entitlements.plist";
COPY_PHASE_STRIP = YES;
- CURRENT_PROJECT_VERSION = 124;
+ CURRENT_PROJECT_VERSION = 125;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks;
"FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = (
@@ -556,7 +556,7 @@
"CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]" = "source/debugserver-entitlements.plist";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = lldb_codesign;
COPY_PHASE_STRIP = YES;
- CURRENT_PROJECT_VERSION = 124;
+ CURRENT_PROJECT_VERSION = 125;
FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks;
"FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = (
"$(SDKROOT)/System/Library/PrivateFrameworks",
@@ -597,7 +597,7 @@
"CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]" = "source/debugserver-entitlements.plist";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = lldb_codesign;
COPY_PHASE_STRIP = YES;
- CURRENT_PROJECT_VERSION = 124;
+ CURRENT_PROJECT_VERSION = 125;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks;
"FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = (
From gclayton at apple.com Tue Jan 11 20:25:42 2011
From: gclayton at apple.com (Greg Clayton)
Date: Wed, 12 Jan 2011 02:25:42 -0000
Subject: [Lldb-commits] [lldb] r123300 - in /lldb/trunk:
include/lldb/API/SBThread.h include/lldb/Target/Thread.h
include/lldb/lldb-defines.h source/API/SBThread.cpp
source/Target/Thread.cpp
Message-ID: <20110112022543.0E8DD2A6C12C@llvm.org>
Author: gclayton
Date: Tue Jan 11 20:25:42 2011
New Revision: 123300
URL: http://llvm.org/viewvc/llvm-project?rev=123300&view=rev
Log:
Added the following functions to SBThread to allow threads to be suspended when a process is resumed:
bool SBThread::Suspend();
bool SBThread::Resume();
bool SBThread::IsSuspended();
Modified:
lldb/trunk/include/lldb/API/SBThread.h
lldb/trunk/include/lldb/Target/Thread.h
lldb/trunk/include/lldb/lldb-defines.h
lldb/trunk/source/API/SBThread.cpp
lldb/trunk/source/Target/Thread.cpp
Modified: lldb/trunk/include/lldb/API/SBThread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBThread.h?rev=123300&r1=123299&r2=123300&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBThread.h (original)
+++ lldb/trunk/include/lldb/API/SBThread.h Tue Jan 11 20:25:42 2011
@@ -90,6 +90,36 @@
void
RunToAddress (lldb::addr_t addr);
+ //--------------------------------------------------------------------------
+ // LLDB currently supports process centric debugging which means when any
+ // thread in a process stops, all other threads are stopped. The Suspend()
+ // call here tells our process to suspend a thread and not let it run when
+ // the other threads in a process are allowed to run. So when
+ // SBProcess::Continue() is called, any threads that aren't suspended will
+ // be allowed to run. If any of the SBThread functions for stepping are
+ // called (StepOver, StepInto, StepOut, StepInstruction, RunToAddres), the
+ // thread will now be allowed to run and these funtions will simply return.
+ //
+ // Eventually we plan to add support for thread centric debugging where each
+ // thread is controlled individually and each thread would broadcast its
+ // state, but we haven't implemented this yet.
+ //
+ // Likewise the SBThread::Resume() call will again allow the thread to run
+ // when the process is continued.
+ //
+ // The Suspend() and Resume() functions are not currently reference counted,
+ // if anyone has the need for them to be reference counted, please let us
+ // know.
+ //--------------------------------------------------------------------------
+ bool
+ Suspend();
+
+ bool
+ Resume ();
+
+ bool
+ IsSuspended();
+
uint32_t
GetNumFrames ();
Modified: lldb/trunk/include/lldb/Target/Thread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Thread.h?rev=123300&r1=123299&r2=123300&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Thread.h (original)
+++ lldb/trunk/include/lldb/Target/Thread.h Tue Jan 11 20:25:42 2011
@@ -186,10 +186,16 @@
GetProcess() const { return m_process; }
int
- GetResumeSignal () const;
+ GetResumeSignal () const
+ {
+ return m_resume_signal;
+ }
void
- SetResumeSignal (int signal);
+ SetResumeSignal (int signal)
+ {
+ m_resume_signal = signal;
+ }
lldb::StateType
GetState() const;
@@ -201,10 +207,16 @@
SetState (lldb::StateType state);
lldb::StateType
- GetResumeState () const;
+ GetResumeState () const
+ {
+ return m_resume_state;
+ }
void
- SetResumeState (lldb::StateType state);
+ SetResumeState (lldb::StateType state)
+ {
+ m_resume_state = state;
+ }
// This function is called on all the threads before "WillResume" in case
// a thread needs to change its state before the ThreadList polls all the
Modified: lldb/trunk/include/lldb/lldb-defines.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-defines.h?rev=123300&r1=123299&r2=123300&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-defines.h (original)
+++ lldb/trunk/include/lldb/lldb-defines.h Tue Jan 11 20:25:42 2011
@@ -21,7 +21,14 @@
#endif
//----------------------------------------------------------------------
-// lldb defines
+// LLDB version
+//
+// A build script phase can modify this version number if needed.
+//----------------------------------------------------------------------
+//#define LLDB_VERSION
+
+//----------------------------------------------------------------------
+// LLDB defines
//----------------------------------------------------------------------
#define LLDB_GENERIC_ERROR UINT32_MAX
Modified: lldb/trunk/source/API/SBThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBThread.cpp?rev=123300&r1=123299&r2=123300&view=diff
==============================================================================
--- lldb/trunk/source/API/SBThread.cpp (original)
+++ lldb/trunk/source/API/SBThread.cpp Tue Jan 11 20:25:42 2011
@@ -562,6 +562,36 @@
}
+bool
+SBThread::Suspend()
+{
+ if (m_opaque_sp)
+ {
+ m_opaque_sp->SetResumeState (eStateSuspended);
+ return true;
+ }
+ return false;
+}
+
+bool
+SBThread::Resume ()
+{
+ if (m_opaque_sp)
+ {
+ m_opaque_sp->SetResumeState (eStateRunning);
+ return true;
+ }
+ return false;
+}
+
+bool
+SBThread::IsSuspended()
+{
+ if (m_opaque_sp)
+ m_opaque_sp->GetResumeState () == eStateSuspended;
+ return false;
+}
+
SBProcess
SBThread::GetProcess ()
{
Modified: lldb/trunk/source/Target/Thread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Thread.cpp?rev=123300&r1=123299&r2=123300&view=diff
==============================================================================
--- lldb/trunk/source/Target/Thread.cpp (original)
+++ lldb/trunk/source/Target/Thread.cpp Tue Jan 11 20:25:42 2011
@@ -85,30 +85,6 @@
m_destroy_called = true;
}
-int
-Thread::GetResumeSignal () const
-{
- return m_resume_signal;
-}
-
-void
-Thread::SetResumeSignal (int signal)
-{
- m_resume_signal = signal;
-}
-
-StateType
-Thread::GetResumeState () const
-{
- return m_resume_state;
-}
-
-void
-Thread::SetResumeState (StateType state)
-{
- m_resume_state = state;
-}
-
lldb::StopInfoSP
Thread::GetStopInfo ()
{
From wilsons at start.ca Tue Jan 11 21:51:27 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Tue, 11 Jan 2011 22:51:27 -0500
Subject: [Lldb-commits] [PATCH] Log diagnostic when setting software
breakpoints only on failure.
Message-ID:
Previously we would be posting a "FAILED" message to the log channel even when
the operation succeeded.
Also, take this opportunity to add braces thus eliminating an "ambiguous else"
compiler warning.
diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp
index 36f21ac..42e0cf7 100644
--- a/source/Target/Process.cpp
+++ b/source/Target/Process.cpp
@@ -1080,7 +1080,7 @@ Process::EnableSoftwareBreakpoint (BreakpointSite *bp_site)
else
error.SetErrorString("Unable to read memory at breakpoint address.");
}
- if (log)
+ if (log && error.Fail())
log->Printf ("Process::EnableSoftwareBreakpoint (site_id = %d) addr = 0x%llx -- FAILED: %s",
bp_site->GetID(),
(uint64_t)bp_addr,
@@ -2628,13 +2628,14 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
// Right now this is the only way to tell we've timed out...
// We should interrupt the process here...
// Not really sure what to do if Halt fails here...
- if (log)
+ if (log) {
if (try_all_threads)
log->Printf ("Running function with timeout: %d timed out, trying with all threads enabled.",
single_thread_timeout_usec);
else
log->Printf ("Running function with timeout: %d timed out, abandoning execution.",
single_thread_timeout_usec);
+ }
if (exe_ctx.process->Halt().Success())
{
--
1.7.3.5
From wilsons at start.ca Tue Jan 11 21:52:45 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Tue, 11 Jan 2011 22:52:45 -0500
Subject: [Lldb-commits] [PATCH] linux: Null terminate path returned by
readlink()
Message-ID:
diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp
index 8d82097..f7a1a24 100644
--- a/source/Host/common/Host.cpp
+++ b/source/Host/common/Host.cpp
@@ -620,9 +620,11 @@ Host::GetProgramFileSpec ()
}
#elif defined (__linux__)
char exe_path[PATH_MAX];
- ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path));
- if (len >= 0)
+ ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1);
+ if (len > 0) {
+ exe_path[len] = 0;
g_program_filespec = FileSpec(exe_path, true);
+ }
#elif defined (__FreeBSD__)
int exe_path_mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, getpid() };
size_t exe_path_size;
--
1.7.3.5
From wilsons at start.ca Tue Jan 11 21:53:28 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Tue, 11 Jan 2011 22:53:28 -0500
Subject: [Lldb-commits] [PATCH] Initialize SymbolFileDWARFDebugMap on Apple
platforms only.
Message-ID:
SymbolFileDWARFDebugMap handles the parsing of OSO stabs which are effectively a
Mach-O specific feature and is incompatible with other object file formats.
diff --git a/source/lldb.cpp b/source/lldb.cpp
index 137ad86..47f403d 100644
--- a/source/lldb.cpp
+++ b/source/lldb.cpp
@@ -71,7 +71,6 @@ lldb_private::Initialize ()
ObjectContainerBSDArchive::Initialize();
ObjectFileELF::Initialize();
SymbolFileDWARF::Initialize();
- SymbolFileDWARFDebugMap::Initialize();
SymbolFileSymtab::Initialize();
UnwindAssemblyProfiler_x86::Initialize();
ArchDefaultUnwindPlan_x86::Initialize();
@@ -81,6 +80,7 @@ lldb_private::Initialize ()
ABIMacOSX_i386::Initialize();
ABISysV_x86_64::Initialize();
DynamicLoaderMacOSXDYLD::Initialize();
+ SymbolFileDWARFDebugMap::Initialize();
ItaniumABILanguageRuntime::Initialize();
AppleObjCRuntimeV2::Initialize();
AppleObjCRuntimeV1::Initialize();
@@ -110,7 +110,6 @@ lldb_private::Terminate ()
ObjectContainerBSDArchive::Terminate();
ObjectFileELF::Terminate();
SymbolFileDWARF::Terminate();
- SymbolFileDWARFDebugMap::Terminate();
SymbolFileSymtab::Terminate();
UnwindAssemblyProfiler_x86::Terminate();
ArchDefaultUnwindPlan_x86::Terminate();
@@ -118,6 +117,7 @@ lldb_private::Terminate ()
#ifdef __APPLE__
DynamicLoaderMacOSXDYLD::Terminate();
+ SymbolFileDWARFDebugMap::Terminate();
ItaniumABILanguageRuntime::Terminate();
AppleObjCRuntimeV2::Terminate();
AppleObjCRuntimeV1::Terminate();
--
1.7.3.5
--
steve
From wilsons at start.ca Tue Jan 11 21:54:44 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Tue, 11 Jan 2011 22:54:44 -0500
Subject: [Lldb-commits] [PATCH] Do not pass an invalid thread to
Thread{Cancel, Join}.
Message-ID:
A race condition exists between StopReadThread and the reader thread proper.
When StopReadThread sets m_read_thread_enabled to false the reader thread can
terminate and set m_read_thread to LLDB_INVALID_HOST_THREAD on exit. Thus calls
to ThreadCancel or ThreadJoin in StopReadThread can be passed an invalid handle.
This patch removes the race by using m_read_thread_enabled as the flag thru
which the reader thread can notify the parent thread of early/abnormal
termination.
diff --git a/source/Core/Communication.cpp b/source/Core/Communication.cpp
index 99c619d..b178657 100644
--- a/source/Core/Communication.cpp
+++ b/source/Core/Communication.cpp
@@ -138,7 +138,7 @@ Communication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, Connectio
timeout_usec,
m_connection_sp.get());
- if (m_read_thread != LLDB_INVALID_HOST_THREAD)
+ if (m_read_thread_enabled)
{
// We have a dedicated read thread that is getting data for us
size_t cached_bytes = GetCachedBytes (dst, dst_len);
@@ -257,8 +257,9 @@ Communication::StopReadThread (Error *error_ptr)
Host::ThreadCancel (m_read_thread, error_ptr);
- return Host::ThreadJoin (m_read_thread, NULL, error_ptr);
+ bool status = Host::ThreadJoin (m_read_thread, NULL, error_ptr);
m_read_thread = LLDB_INVALID_HOST_THREAD;
+ return status;
}
@@ -317,7 +318,7 @@ Communication::ReadFromConnection (void *dst, size_t dst_len, ConnectionStatus &
bool
Communication::ReadThreadIsRunning ()
{
- return m_read_thread != LLDB_INVALID_HOST_THREAD;
+ return m_read_thread_enabled;
}
void *
@@ -370,7 +371,7 @@ Communication::ReadThread (void *p)
// Let clients know that this thread is exiting
comm->BroadcastEvent (eBroadcastBitReadThreadDidExit);
- comm->m_read_thread = LLDB_INVALID_HOST_THREAD;
+ comm->m_read_thread_enabled = false;
comm->Disconnect();
return NULL;
}
--
1.7.3.5
From gclayton at apple.com Tue Jan 11 22:05:42 2011
From: gclayton at apple.com (Greg Clayton)
Date: Tue, 11 Jan 2011 20:05:42 -0800
Subject: [Lldb-commits] [PATCH] Do not pass an invalid thread
to Thread{Cancel, Join}.
In-Reply-To:
References:
Message-ID:
All patches look good. Feel free to submit them anytime.
On Jan 11, 2011, at 7:54 PM, Stephen Wilson wrote:
>
> A race condition exists between StopReadThread and the reader thread proper.
> When StopReadThread sets m_read_thread_enabled to false the reader thread can
> terminate and set m_read_thread to LLDB_INVALID_HOST_THREAD on exit. Thus calls
> to ThreadCancel or ThreadJoin in StopReadThread can be passed an invalid handle.
>
> This patch removes the race by using m_read_thread_enabled as the flag thru
> which the reader thread can notify the parent thread of early/abnormal
> termination.
>
>
> diff --git a/source/Core/Communication.cpp b/source/Core/Communication.cpp
> index 99c619d..b178657 100644
> --- a/source/Core/Communication.cpp
> +++ b/source/Core/Communication.cpp
> @@ -138,7 +138,7 @@ Communication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, Connectio
> timeout_usec,
> m_connection_sp.get());
>
> - if (m_read_thread != LLDB_INVALID_HOST_THREAD)
> + if (m_read_thread_enabled)
> {
> // We have a dedicated read thread that is getting data for us
> size_t cached_bytes = GetCachedBytes (dst, dst_len);
> @@ -257,8 +257,9 @@ Communication::StopReadThread (Error *error_ptr)
>
> Host::ThreadCancel (m_read_thread, error_ptr);
>
> - return Host::ThreadJoin (m_read_thread, NULL, error_ptr);
> + bool status = Host::ThreadJoin (m_read_thread, NULL, error_ptr);
> m_read_thread = LLDB_INVALID_HOST_THREAD;
> + return status;
> }
>
>
> @@ -317,7 +318,7 @@ Communication::ReadFromConnection (void *dst, size_t dst_len, ConnectionStatus &
> bool
> Communication::ReadThreadIsRunning ()
> {
> - return m_read_thread != LLDB_INVALID_HOST_THREAD;
> + return m_read_thread_enabled;
> }
>
> void *
> @@ -370,7 +371,7 @@ Communication::ReadThread (void *p)
>
> // Let clients know that this thread is exiting
> comm->BroadcastEvent (eBroadcastBitReadThreadDidExit);
> - comm->m_read_thread = LLDB_INVALID_HOST_THREAD;
> + comm->m_read_thread_enabled = false;
> comm->Disconnect();
> return NULL;
> }
> --
> 1.7.3.5
>
>
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
From gclayton at apple.com Tue Jan 11 22:03:58 2011
From: gclayton at apple.com (Greg Clayton)
Date: Wed, 12 Jan 2011 04:03:58 -0000
Subject: [Lldb-commits] [lldb] r123305 - in /lldb/trunk:
lldb.xcodeproj/project.pbxproj resources/LLDB-Info.plist
Message-ID: <20110112040359.0AC0B2A6C12C@llvm.org>
Author: gclayton
Date: Tue Jan 11 22:03:58 2011
New Revision: 123305
URL: http://llvm.org/viewvc/llvm-project?rev=123305&view=rev
Log:
Bumped Xcode project version to 40 for lldb-40.
Modified:
lldb/trunk/lldb.xcodeproj/project.pbxproj
lldb/trunk/resources/LLDB-Info.plist
Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=123305&r1=123304&r2=123305&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Tue Jan 11 22:03:58 2011
@@ -2420,7 +2420,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "cd \"${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}\"\nfor file in *.h\ndo\n\t/usr/bin/sed -i '' 's/\\(#include\\)[ ]*\"lldb\\/\\(API\\/\\)\\{0,1\\}\\(.*\\)\"/\\1 /1' \"$file\"\n\t/usr/bin/sed -i '' 's|/1' \"$file\"\n\t/usr/bin/sed -i '' 's|CFBundleSignature
????
CFBundleVersion
- 39
+ 40
CFBundleName
${EXECUTABLE_NAME}
From wilsons at start.ca Tue Jan 11 22:20:03 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Wed, 12 Jan 2011 04:20:03 -0000
Subject: [Lldb-commits] [lldb] r123306 -
/lldb/trunk/source/Target/Process.cpp
Message-ID: <20110112042003.DD6FA2A6C12C@llvm.org>
Author: wilsons
Date: Tue Jan 11 22:20:03 2011
New Revision: 123306
URL: http://llvm.org/viewvc/llvm-project?rev=123306&view=rev
Log:
Log diagnostic when setting software breakpoints only on failure.
Previously we would be posting a "FAILED" message to the log channel even when
the operation succeeded.
Also, take this opportunity to add braces thus eliminating an "ambiguous else"
compiler warning.
Modified:
lldb/trunk/source/Target/Process.cpp
Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=123306&r1=123305&r2=123306&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Tue Jan 11 22:20:03 2011
@@ -1080,7 +1080,7 @@
else
error.SetErrorString("Unable to read memory at breakpoint address.");
}
- if (log)
+ if (log && error.Fail())
log->Printf ("Process::EnableSoftwareBreakpoint (site_id = %d) addr = 0x%llx -- FAILED: %s",
bp_site->GetID(),
(uint64_t)bp_addr,
@@ -2628,13 +2628,14 @@
// Right now this is the only way to tell we've timed out...
// We should interrupt the process here...
// Not really sure what to do if Halt fails here...
- if (log)
+ if (log) {
if (try_all_threads)
log->Printf ("Running function with timeout: %d timed out, trying with all threads enabled.",
single_thread_timeout_usec);
else
log->Printf ("Running function with timeout: %d timed out, abandoning execution.",
single_thread_timeout_usec);
+ }
if (exe_ctx.process->Halt().Success())
{
From wilsons at start.ca Tue Jan 11 22:21:22 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Wed, 12 Jan 2011 04:21:22 -0000
Subject: [Lldb-commits] [lldb] r123307 -
/lldb/trunk/source/Host/common/Host.cpp
Message-ID: <20110112042122.0EEC92A6C12C@llvm.org>
Author: wilsons
Date: Tue Jan 11 22:21:21 2011
New Revision: 123307
URL: http://llvm.org/viewvc/llvm-project?rev=123307&view=rev
Log:
Null terminate path returned by readlink().
Modified:
lldb/trunk/source/Host/common/Host.cpp
Modified: lldb/trunk/source/Host/common/Host.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/Host.cpp?rev=123307&r1=123306&r2=123307&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/Host.cpp (original)
+++ lldb/trunk/source/Host/common/Host.cpp Tue Jan 11 22:21:21 2011
@@ -620,9 +620,11 @@
}
#elif defined (__linux__)
char exe_path[PATH_MAX];
- ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path));
- if (len >= 0)
+ ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1);
+ if (len > 0) {
+ exe_path[len] = 0;
g_program_filespec = FileSpec(exe_path, true);
+ }
#elif defined (__FreeBSD__)
int exe_path_mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, getpid() };
size_t exe_path_size;
From wilsons at start.ca Tue Jan 11 22:22:09 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Wed, 12 Jan 2011 04:22:09 -0000
Subject: [Lldb-commits] [lldb] r123308 - /lldb/trunk/source/lldb.cpp
Message-ID: <20110112042209.BEBD92A6C12C@llvm.org>
Author: wilsons
Date: Tue Jan 11 22:22:09 2011
New Revision: 123308
URL: http://llvm.org/viewvc/llvm-project?rev=123308&view=rev
Log:
Initialize SymbolFileDWARFDebugMap on Apple platforms only.
SymbolFileDWARFDebugMap handles the parsing of OSO stabs which are effectively a
Mach-O specific feature and is incompatible with other object file formats.
Modified:
lldb/trunk/source/lldb.cpp
Modified: lldb/trunk/source/lldb.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/lldb.cpp?rev=123308&r1=123307&r2=123308&view=diff
==============================================================================
--- lldb/trunk/source/lldb.cpp (original)
+++ lldb/trunk/source/lldb.cpp Tue Jan 11 22:22:09 2011
@@ -71,7 +71,6 @@
ObjectContainerBSDArchive::Initialize();
ObjectFileELF::Initialize();
SymbolFileDWARF::Initialize();
- SymbolFileDWARFDebugMap::Initialize();
SymbolFileSymtab::Initialize();
UnwindAssemblyProfiler_x86::Initialize();
ArchDefaultUnwindPlan_x86::Initialize();
@@ -81,6 +80,7 @@
ABIMacOSX_i386::Initialize();
ABISysV_x86_64::Initialize();
DynamicLoaderMacOSXDYLD::Initialize();
+ SymbolFileDWARFDebugMap::Initialize();
ItaniumABILanguageRuntime::Initialize();
AppleObjCRuntimeV2::Initialize();
AppleObjCRuntimeV1::Initialize();
@@ -110,7 +110,6 @@
ObjectContainerBSDArchive::Terminate();
ObjectFileELF::Terminate();
SymbolFileDWARF::Terminate();
- SymbolFileDWARFDebugMap::Terminate();
SymbolFileSymtab::Terminate();
UnwindAssemblyProfiler_x86::Terminate();
ArchDefaultUnwindPlan_x86::Terminate();
@@ -118,6 +117,7 @@
#ifdef __APPLE__
DynamicLoaderMacOSXDYLD::Terminate();
+ SymbolFileDWARFDebugMap::Terminate();
ItaniumABILanguageRuntime::Terminate();
AppleObjCRuntimeV2::Terminate();
AppleObjCRuntimeV1::Terminate();
From wilsons at start.ca Tue Jan 11 22:22:54 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Wed, 12 Jan 2011 04:22:54 -0000
Subject: [Lldb-commits] [lldb] r123309 -
/lldb/trunk/source/Core/Communication.cpp
Message-ID: <20110112042254.DC7D92A6C12C@llvm.org>
Author: wilsons
Date: Tue Jan 11 22:22:54 2011
New Revision: 123309
URL: http://llvm.org/viewvc/llvm-project?rev=123309&view=rev
Log:
Do not pass an invalid thread to Thread{Cancel,Join}.
A race condition exists between StopReadThread and the reader thread proper.
When StopReadThread sets m_read_thread_enabled to false the reader thread can
terminate and set m_read_thread to LLDB_INVALID_HOST_THREAD on exit. Thus calls
to ThreadCancel or ThreadJoin in StopReadThread can be passed an invalid handle.
This patch removes the race by using m_read_thread_enabled as the flag thru
which the reader thread can notify the parent thread of early/abnormal
termination.
Modified:
lldb/trunk/source/Core/Communication.cpp
Modified: lldb/trunk/source/Core/Communication.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Communication.cpp?rev=123309&r1=123308&r2=123309&view=diff
==============================================================================
--- lldb/trunk/source/Core/Communication.cpp (original)
+++ lldb/trunk/source/Core/Communication.cpp Tue Jan 11 22:22:54 2011
@@ -138,7 +138,7 @@
timeout_usec,
m_connection_sp.get());
- if (m_read_thread != LLDB_INVALID_HOST_THREAD)
+ if (m_read_thread_enabled)
{
// We have a dedicated read thread that is getting data for us
size_t cached_bytes = GetCachedBytes (dst, dst_len);
@@ -257,8 +257,9 @@
Host::ThreadCancel (m_read_thread, error_ptr);
- return Host::ThreadJoin (m_read_thread, NULL, error_ptr);
+ bool status = Host::ThreadJoin (m_read_thread, NULL, error_ptr);
m_read_thread = LLDB_INVALID_HOST_THREAD;
+ return status;
}
@@ -317,7 +318,7 @@
bool
Communication::ReadThreadIsRunning ()
{
- return m_read_thread != LLDB_INVALID_HOST_THREAD;
+ return m_read_thread_enabled;
}
void *
@@ -370,7 +371,7 @@
// Let clients know that this thread is exiting
comm->BroadcastEvent (eBroadcastBitReadThreadDidExit);
- comm->m_read_thread = LLDB_INVALID_HOST_THREAD;
+ comm->m_read_thread_enabled = false;
comm->Disconnect();
return NULL;
}
From gclayton at apple.com Wed Jan 12 12:36:46 2011
From: gclayton at apple.com (Greg Clayton)
Date: Wed, 12 Jan 2011 10:36:46 -0800
Subject: [Lldb-commits] [lldb] r123307
- /lldb/trunk/source/Host/common/Host.cpp
In-Reply-To: <20110112042122.0EEC92A6C12C@llvm.org>
References: <20110112042122.0EEC92A6C12C@llvm.org>
Message-ID:
Quick possible optimization on the code below: I am guessing that readlink() returns a path that is already resolved? If so then passing true to the FileSpec constructor line:
g_program_filespec = FileSpec(exe_path, true);
will cause realpath() to be called on exe_path to try and resolve the path (which is typically meant for paths that might be symlinks, or "~/path/to/file", or "relative/path/to/file") which is probably redundant. We can pass false to this if the path is already resolved and avoid this:
g_program_filespec = FileSpec(exe_path, false);
Better yet, since the FileSpec constructor calls FileSpec::SetFile(...) anyway, this could just become:
g_program_filespec.SetFile (exe_path, false);
On Jan 11, 2011, at 8:21 PM, Stephen Wilson wrote:
> Author: wilsons
> Date: Tue Jan 11 22:21:21 2011
> New Revision: 123307
>
> URL: http://llvm.org/viewvc/llvm-project?rev=123307&view=rev
> Log:
> Null terminate path returned by readlink().
>
>
> Modified:
> lldb/trunk/source/Host/common/Host.cpp
>
> Modified: lldb/trunk/source/Host/common/Host.cpp
> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/Host.cpp?rev=123307&r1=123306&r2=123307&view=diff
> ==============================================================================
> --- lldb/trunk/source/Host/common/Host.cpp (original)
> +++ lldb/trunk/source/Host/common/Host.cpp Tue Jan 11 22:21:21 2011
> @@ -620,9 +620,11 @@
> }
> #elif defined (__linux__)
> char exe_path[PATH_MAX];
> - ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path));
> - if (len >= 0)
> + ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1);
> + if (len > 0) {
> + exe_path[len] = 0;
> g_program_filespec = FileSpec(exe_path, true);
> + }
> #elif defined (__FreeBSD__)
> int exe_path_mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, getpid() };
> size_t exe_path_size;
>
>
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
From wilsons at start.ca Wed Jan 12 17:04:23 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Wed, 12 Jan 2011 18:04:23 -0500
Subject: [Lldb-commits] [lldb] r123307
- /lldb/trunk/source/Host/common/Host.cpp
In-Reply-To: (Greg Clayton's
message of "Wed, 12 Jan 2011 10:36:46 -0800")
References: <20110112042122.0EEC92A6C12C@llvm.org>
Message-ID:
Greg Clayton writes:
> Quick possible optimization on the code below: I am guessing that
> readlink() returns a path that is already resolved? If so then passing
> true to the FileSpec constructor line:
>
> g_program_filespec = FileSpec(exe_path, true);
>
> will cause realpath() to be called on exe_path to try and resolve the
> path (which is typically meant for paths that might be symlinks, or
> "~/path/to/file", or "relative/path/to/file") which is probably
> redundant. We can pass false to this if the path is already resolved
> and avoid this:
>
> g_program_filespec = FileSpec(exe_path, false);
>
> Better yet, since the FileSpec constructor calls
> FileSpec::SetFile(...) anyway, this could just become:
>
> g_program_filespec.SetFile (exe_path, false);
>
Yes, absolutely. The following has been tested and works fine. I can
commit the patch in a few hours if you wish (running a bit short on time
ATM).
diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp
index de0883c..a47a14c 100644
--- a/source/Host/common/Host.cpp
+++ b/source/Host/common/Host.cpp
@@ -624,7 +624,7 @@ Host::GetProgramFileSpec ()
ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1);
if (len > 0) {
exe_path[len] = 0;
- g_program_filespec = FileSpec(exe_path, true);
+ g_program_filespec.SetFile(exe_path, false);
}
#elif defined (__FreeBSD__)
int exe_path_mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, getpid() };
From gclayton at apple.com Wed Jan 12 19:23:43 2011
From: gclayton at apple.com (Greg Clayton)
Date: Thu, 13 Jan 2011 01:23:43 -0000
Subject: [Lldb-commits] [lldb] r123355 -
/lldb/trunk/source/Host/common/Host.cpp
Message-ID: <20110113012344.01D7F2A6C12C@llvm.org>
Author: gclayton
Date: Wed Jan 12 19:23:43 2011
New Revision: 123355
URL: http://llvm.org/viewvc/llvm-project?rev=123355&view=rev
Log:
Don't have the program path be resolved when they already are when assigning g_program_filespec in the Host calls.
Modified:
lldb/trunk/source/Host/common/Host.cpp
Modified: lldb/trunk/source/Host/common/Host.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/Host.cpp?rev=123355&r1=123354&r2=123355&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/Host.cpp (original)
+++ lldb/trunk/source/Host/common/Host.cpp Wed Jan 12 19:23:43 2011
@@ -607,14 +607,14 @@
uint32_t len = sizeof(program_fullpath);
int err = _NSGetExecutablePath (program_fullpath, &len);
if (err == 0)
- g_program_filespec.SetFile (program_fullpath, true);
+ g_program_filespec.SetFile (program_fullpath, false);
else if (err == -1)
{
char *large_program_fullpath = (char *)::malloc (len + 1);
err = _NSGetExecutablePath (large_program_fullpath, &len);
if (err == 0)
- g_program_filespec.SetFile (large_program_fullpath, true);
+ g_program_filespec.SetFile (large_program_fullpath, false);
::free (large_program_fullpath);
}
@@ -623,7 +623,7 @@
ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1);
if (len > 0) {
exe_path[len] = 0;
- g_program_filespec = FileSpec(exe_path, true);
+ g_program_filespec.SetFile(exe_path, false);
}
#elif defined (__FreeBSD__)
int exe_path_mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, getpid() };
@@ -632,7 +632,7 @@
{
char *exe_path = new char[exe_path_size];
if (sysctl(exe_path_mib, 4, exe_path, &exe_path_size, NULL, 0) == 0)
- g_program_filespec = FileSpec(exe_path, true);
+ g_program_filespec = FileSpec(exe_path, false);
}
#endif
}
From gclayton at apple.com Wed Jan 12 19:25:48 2011
From: gclayton at apple.com (Greg Clayton)
Date: Thu, 13 Jan 2011 01:25:48 -0000
Subject: [Lldb-commits] [lldb] r123356 -
/lldb/trunk/source/Host/common/Host.cpp
Message-ID: <20110113012548.A96102A6C12C@llvm.org>
Author: gclayton
Date: Wed Jan 12 19:25:48 2011
New Revision: 123356
URL: http://llvm.org/viewvc/llvm-project?rev=123356&view=rev
Log:
Call SetFile instead of constructing a temp object and assigning to g_program_filespec for Free BSD port.
Modified:
lldb/trunk/source/Host/common/Host.cpp
Modified: lldb/trunk/source/Host/common/Host.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/Host.cpp?rev=123356&r1=123355&r2=123356&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/Host.cpp (original)
+++ lldb/trunk/source/Host/common/Host.cpp Wed Jan 12 19:25:48 2011
@@ -632,7 +632,7 @@
{
char *exe_path = new char[exe_path_size];
if (sysctl(exe_path_mib, 4, exe_path, &exe_path_size, NULL, 0) == 0)
- g_program_filespec = FileSpec(exe_path, false);
+ g_program_filespec.SetFile(exe_path, false);
}
#endif
}
From gclayton at apple.com Wed Jan 12 19:27:55 2011
From: gclayton at apple.com (Greg Clayton)
Date: Thu, 13 Jan 2011 01:27:55 -0000
Subject: [Lldb-commits] [lldb] r123357 -
/lldb/trunk/source/Host/common/Host.cpp
Message-ID: <20110113012755.E7EF92A6C12C@llvm.org>
Author: gclayton
Date: Wed Jan 12 19:27:55 2011
New Revision: 123357
URL: http://llvm.org/viewvc/llvm-project?rev=123357&view=rev
Log:
Plug Free BSD memory leak.
Modified:
lldb/trunk/source/Host/common/Host.cpp
Modified: lldb/trunk/source/Host/common/Host.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/Host.cpp?rev=123357&r1=123356&r2=123357&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/Host.cpp (original)
+++ lldb/trunk/source/Host/common/Host.cpp Wed Jan 12 19:27:55 2011
@@ -630,9 +630,10 @@
size_t exe_path_size;
if (sysctl(exe_path_mib, 4, NULL, &exe_path_size, NULL, 0) == 0)
{
- char *exe_path = new char[exe_path_size];
- if (sysctl(exe_path_mib, 4, exe_path, &exe_path_size, NULL, 0) == 0)
- g_program_filespec.SetFile(exe_path, false);
+ char *exe_path = new char[exe_path_size];
+ if (sysctl(exe_path_mib, 4, exe_path, &exe_path_size, NULL, 0) == 0)
+ g_program_filespec.SetFile(exe_path, false);
+ delete[] exe_path;
}
#endif
}
From scallanan at apple.com Thu Jan 13 02:53:35 2011
From: scallanan at apple.com (Sean Callanan)
Date: Thu, 13 Jan 2011 08:53:35 -0000
Subject: [Lldb-commits] [lldb] r123371 - in /lldb/trunk:
include/lldb/Expression/ include/lldb/Symbol/ include/lldb/Target/
source/API/ source/Breakpoint/ source/Commands/ source/Core/
source/Expression/ source/Plugins/Process/gdb-remote/ source/Symbol/
source/Target/
Message-ID: <20110113085335.AFFD12A6C12D@llvm.org>
Author: spyffe
Date: Thu Jan 13 02:53:35 2011
New Revision: 123371
URL: http://llvm.org/viewvc/llvm-project?rev=123371&view=rev
Log:
Implemented a major overhaul of the way variables are handled
by LLDB. Instead of being materialized into the input structure
passed to the expression, variables are left in place and pointers
to them are materialzied into the structure. Variables not resident
in memory (notably, registers) get temporary memory regions allocated
for them.
Persistent variables are the most complex part of this, because they
are made in various ways and there are different expectations about
their lifetime. Persistent variables now have flags indicating their
status and what the expectations for longevity are. They can be
marked as residing in target memory permanently -- this is the
default for result variables from expressions entered on the command
line and for explicitly declared persistent variables (but more on
that below). Other result variables have their memory freed.
Some major improvements resulting from this include being able to
properly take the address of variables, better and cleaner support
for functions that return references, and cleaner C++ support in
general. One problem that remains is the problem of explicitly
declared persistent variables; I have not yet implemented the code
that makes references to them into indirect references, so currently
materialization and dematerialization of these variables is broken.
Modified:
lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h
lldb/trunk/include/lldb/Expression/ClangExpressionVariable.h
lldb/trunk/include/lldb/Expression/ClangUserExpression.h
lldb/trunk/include/lldb/Expression/IRForTarget.h
lldb/trunk/include/lldb/Symbol/ClangASTContext.h
lldb/trunk/include/lldb/Target/Target.h
lldb/trunk/source/API/SBFrame.cpp
lldb/trunk/source/Breakpoint/BreakpointOptions.cpp
lldb/trunk/source/Commands/CommandObjectExpression.cpp
lldb/trunk/source/Core/ValueObject.cpp
lldb/trunk/source/Expression/ASTResultSynthesizer.cpp
lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
lldb/trunk/source/Expression/ClangExpressionVariable.cpp
lldb/trunk/source/Expression/ClangUserExpression.cpp
lldb/trunk/source/Expression/ClangUtilityFunction.cpp
lldb/trunk/source/Expression/IRForTarget.cpp
lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
lldb/trunk/source/Symbol/ClangASTContext.cpp
lldb/trunk/source/Target/Process.cpp
lldb/trunk/source/Target/Target.cpp
Modified: lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h Thu Jan 13 02:53:35 2011
@@ -70,9 +70,14 @@
//------------------------------------------------------------------
/// Constructor
///
- /// Initializes class variabes.
+ /// Initializes class variables.
+ ///
+ /// @param[in] keep_result_in_memory
+ /// If true, inhibits the normal deallocation of the memory for
+ /// the result persistent variable, and instead marks the variable
+ /// as persisting.
//------------------------------------------------------------------
- ClangExpressionDeclMap ();
+ ClangExpressionDeclMap (bool keep_result_in_memory);
//------------------------------------------------------------------
/// Destructor
@@ -151,7 +156,9 @@
bool
AddPersistentVariable (const clang::NamedDecl *decl,
const ConstString &name,
- TypeFromParser type);
+ TypeFromParser type,
+ bool is_result,
+ bool is_lvalue);
//------------------------------------------------------------------
/// [Used by IRForTarget] Add a variable to the struct that needs to
@@ -443,6 +450,7 @@
private:
ClangExpressionVariableList m_found_entities; ///< All entities that were looked up for the parser.
ClangExpressionVariableList m_struct_members; ///< All entities that need to be placed in the struct.
+ bool m_keep_result_in_memory; ///< True if result persistent variables generated by this expression should stay in memory.
//----------------------------------------------------------------------
/// The following values should not live beyond parsing
@@ -797,11 +805,11 @@
/// @param[in] sym_ctx
/// The symbol context to use (for looking the variable up).
///
- /// @param[in] name
- /// The name of the variable (for looking the variable up).
- ///
- /// @param[in] type
- /// The required type of the variable (for looking the variable up).
+ /// @param[in] expr_var
+ /// The entity that the expression parser uses for the variable.
+ /// In case the variable needs to be copied into the target's
+ /// memory, this location is stored in the variable during
+ /// materialization and cleared when it is demateralized.
///
/// @param[in] addr
/// The address at which to materialize the variable.
@@ -817,8 +825,7 @@
DoMaterializeOneVariable (bool dematerialize,
ExecutionContext &exe_ctx,
const SymbolContext &sym_ctx,
- const ConstString &name,
- TypeFromUser type,
+ lldb::ClangExpressionVariableSP &expr_var,
lldb::addr_t addr,
Error &err);
Modified: lldb/trunk/include/lldb/Expression/ClangExpressionVariable.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangExpressionVariable.h?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangExpressionVariable.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangExpressionVariable.h Thu Jan 13 02:53:35 2011
@@ -199,7 +199,6 @@
void
ValueUpdated ();
-
typedef lldb::SharedPtr::Type ValueObjectConstResultSP;
//----------------------------------------------------------------------
@@ -207,9 +206,22 @@
//----------------------------------------------------------------------
std::auto_ptr m_parser_vars;
std::auto_ptr m_jit_vars;
- //ValueObjectConstResultSP m_valojb_sp;
- lldb::ValueObjectSP m_valojb_sp;
-
+
+ enum Flags
+ {
+ EVNone = 0,
+ EVIsLLDBAllocated = 1 << 0, ///< This variable is resident in a location specifically allocated for it by LLDB in the target process
+ EVIsProgramReference = 1 << 1, ///< This variable is a reference to a (possibly invalid) area managed by the target program
+ EVNeedsAllocation = 1 << 2, ///< Space for this variable has yet to be allocated in the target process
+ EVIsFreezeDried = 1 << 3, ///< This variable's authoritative version is in m_frozen_sp (for example, for statically-computed results)
+ EVNeedsFreezeDry = 1 << 4, ///< Copy from m_live_sp to m_frozen_sp during dematerialization
+ EVKeepInTarget = 1 << 5 ///< Keep the allocation after the expression is complete rather than freeze drying its contents and freeing it
+ };
+
+ uint16_t m_flags; // takes elements of Flags
+
+ lldb::ValueObjectSP m_frozen_sp;
+ lldb::ValueObjectSP m_live_sp;
private:
DISALLOW_COPY_AND_ASSIGN (ClangExpressionVariable);
};
Modified: lldb/trunk/include/lldb/Expression/ClangUserExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangUserExpression.h?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangUserExpression.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangUserExpression.h Thu Jan 13 02:53:35 2011
@@ -81,6 +81,10 @@
/// The type that the expression should be coerced to. If NULL,
/// inferred from the expression itself.
///
+ /// @param[in] keep_result_in_memory
+ /// True if the resulting persistent variable should reside in
+ /// target memory, if applicable.
+ ///
/// @param[out] const_result
/// If this is non-NULL, the expression has no side effects, and
/// the expression returns a constant result, then that result
@@ -93,6 +97,7 @@
Parse (Stream &error_stream,
ExecutionContext &exe_ctx,
TypeFromUser desired_type,
+ bool keep_result_in_memory,
lldb::ClangExpressionVariableSP *const_result = NULL);
//------------------------------------------------------------------
@@ -109,6 +114,7 @@
/// If true, and the execution stops before completion, we unwind the
/// function call, and return the program state to what it was before the
/// execution. If false, we leave the program in the stopped state.
+ ///
/// @param[in] shared_ptr_to_me
/// This is a shared pointer to this ClangUserExpression. This is
/// needed because Execute can push a thread plan that will hold onto
@@ -127,12 +133,14 @@
Execute (Stream &error_stream,
ExecutionContext &exe_ctx,
bool discard_on_error,
+ bool keep_in_memory,
ClangUserExpressionSP &shared_ptr_to_me,
lldb::ClangExpressionVariableSP &result);
ThreadPlan *
GetThreadPlanToExecuteJITExpression (Stream &error_stream,
ExecutionContext &exe_ctx);
+
bool
FinalizeJITExecution (Stream &error_stream,
ExecutionContext &exe_ctx,
@@ -232,6 +240,14 @@
/// @param[in] exe_ctx
/// The execution context to use when evaluating the expression.
///
+ /// @param[in] discard_on_error
+ /// True if the thread's state should be restored in the case
+ /// of an error.
+ ///
+ /// @param[in] keep_in_memory
+ /// True if the resulting persistent variable should reside in
+ /// target memory, if applicable.
+ ///
/// @param[in] expr_cstr
/// A C string containing the expression to be evaluated.
///
@@ -248,6 +264,7 @@
static lldb::ExecutionResults
Evaluate (ExecutionContext &exe_ctx,
bool discard_on_error,
+ bool keep_in_memory,
const char *expr_cstr,
const char *expr_prefix,
lldb::ValueObjectSP &result_valobj_sp);
Modified: lldb/trunk/include/lldb/Expression/IRForTarget.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/IRForTarget.h?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/IRForTarget.h (original)
+++ lldb/trunk/include/lldb/Expression/IRForTarget.h Thu Jan 13 02:53:35 2011
@@ -448,12 +448,14 @@
/// Flags
bool m_resolve_vars; ///< True if external variable references and persistent variable references should be resolved
std::string m_func_name; ///< The name of the function to translate
+ lldb_private::ConstString m_result_name; ///< The name of the result variable ($0, $1, ...)
lldb_private::ClangExpressionDeclMap *m_decl_map; ///< The DeclMap containing the Decls
llvm::Constant *m_CFStringCreateWithBytes; ///< The address of the function CFStringCreateWithBytes, cast to the appropriate function pointer type
llvm::Constant *m_sel_registerName; ///< The address of the function sel_registerName, cast to the appropriate function pointer type
lldb::ClangExpressionVariableSP *m_const_result; ///< If non-NULL, this value should be set to the return value of the expression if it is constant and the expression has no side effects
bool m_has_side_effects; ///< True if the function's result cannot be simply determined statically
+ bool m_result_is_pointer; ///< True if the function's result in the AST is a pointer (see comments in ASTResultSynthesizer::SynthesizeBodyResult)
private:
//------------------------------------------------------------------
Modified: lldb/trunk/include/lldb/Symbol/ClangASTContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTContext.h?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ClangASTContext.h (original)
+++ lldb/trunk/include/lldb/Symbol/ClangASTContext.h Thu Jan 13 02:53:35 2011
@@ -529,11 +529,25 @@
CreatePointerType (clang::ASTContext *ast,
lldb::clang_type_t clang_type);
+ static lldb::clang_type_t
+ CreateLValueReferenceType (clang::ASTContext *ast_context,
+ lldb::clang_type_t clang_type);
+
+ static lldb::clang_type_t
+ CreateRValueReferenceType (clang::ASTContext *ast_context,
+ lldb::clang_type_t clang_type);
+
lldb::clang_type_t
- CreateLValueReferenceType (lldb::clang_type_t clang_type);
+ CreateLValueReferenceType (lldb::clang_type_t clang_type)
+ {
+ return ClangASTContext::CreateLValueReferenceType(getASTContext(), clang_type);
+ }
lldb::clang_type_t
- CreateRValueReferenceType (lldb::clang_type_t clang_type);
+ CreateRValueReferenceType (lldb::clang_type_t clang_type)
+ {
+ return ClangASTContext::CreateRValueReferenceType(getASTContext(), clang_type);
+ }
lldb::clang_type_t
CreateMemberPointerType (lldb::clang_type_t clang_pointee_type,
Modified: lldb/trunk/include/lldb/Target/Target.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Target.h?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Target.h (original)
+++ lldb/trunk/include/lldb/Target/Target.h Thu Jan 13 02:53:35 2011
@@ -476,6 +476,7 @@
EvaluateExpression (const char *expression,
StackFrame *frame,
bool unwind_on_error,
+ bool keep_in_memory,
lldb::ValueObjectSP &result_valobj_sp);
ClangPersistentVariables &
Modified: lldb/trunk/source/API/SBFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBFrame.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/API/SBFrame.cpp (original)
+++ lldb/trunk/source/API/SBFrame.cpp Thu Jan 13 02:53:35 2011
@@ -689,8 +689,9 @@
{
ExecutionResults exe_results;
const bool unwind_on_error = true;
+ const bool keep_in_memory = false;
- exe_results = m_opaque_sp->GetThread().GetProcess().GetTarget().EvaluateExpression(expr, m_opaque_sp.get(), unwind_on_error, *expr_result);
+ exe_results = m_opaque_sp->GetThread().GetProcess().GetTarget().EvaluateExpression(expr, m_opaque_sp.get(), unwind_on_error, keep_in_memory, *expr_result);
}
if (expr_log)
Modified: lldb/trunk/source/Breakpoint/BreakpointOptions.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointOptions.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/BreakpointOptions.cpp (original)
+++ lldb/trunk/source/Breakpoint/BreakpointOptions.cpp Thu Jan 13 02:53:35 2011
@@ -199,7 +199,7 @@
ClangASTContext *ast_context = exe_ctx.target->GetScratchClangASTContext();
TypeFromUser bool_type(ast_context->GetBuiltInType_bool(), ast_context->getASTContext());
- if (!m_condition_ap->Parse (error_stream, exe_ctx, bool_type))
+ if (!m_condition_ap->Parse (error_stream, exe_ctx, bool_type, false /* keep_in_memory */))
{
// Errors mean we should stop.
return NULL;
Modified: lldb/trunk/source/Commands/CommandObjectExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectExpression.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectExpression.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectExpression.cpp Thu Jan 13 02:53:35 2011
@@ -237,7 +237,10 @@
lldb::ValueObjectSP result_valobj_sp;
lldb::ExecutionResults exe_results;
- exe_results = m_exe_ctx.target->EvaluateExpression(expr, m_exe_ctx.frame, m_options.unwind_on_error, result_valobj_sp);
+
+ bool keep_in_memory = true;
+
+ exe_results = m_exe_ctx.target->EvaluateExpression(expr, m_exe_ctx.frame, m_options.unwind_on_error, keep_in_memory, result_valobj_sp);
if (exe_results == eExecutionInterrupted && !m_options.unwind_on_error)
{
Modified: lldb/trunk/source/Core/ValueObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObject.cpp (original)
+++ lldb/trunk/source/Core/ValueObject.cpp Thu Jan 13 02:53:35 2011
@@ -1316,7 +1316,7 @@
ClangASTContext::CreatePointerType (ast, clang_type),
ConstString (name.c_str()),
addr,
- address_type,
+ eAddressTypeInvalid,
m_data.GetAddressByteSize()));
}
}
Modified: lldb/trunk/source/Expression/ASTResultSynthesizer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ASTResultSynthesizer.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ASTResultSynthesizer.cpp (original)
+++ lldb/trunk/source/Expression/ASTResultSynthesizer.cpp Thu Jan 13 02:53:35 2011
@@ -246,6 +246,49 @@
// No auxiliary variable necessary; expression returns void
return true;
+ // is_lvalue is used to record whether the expression returns an assignable Lvalue or an
+ // Rvalue. This is relevant because they are handled differently.
+ //
+ // For Lvalues
+ //
+ // - In AST result synthesis (here!) the expression E is transformed into an initialization
+ // T *$__lldb_expr_result_ptr = &E.
+ //
+ // - In structure allocation, a pointer-sized slot is allocated in the struct that is to be
+ // passed into the expression.
+ //
+ // - In IR transformations, reads and writes to $__lldb_expr_result_ptr are redirected at
+ // an entry in the struct ($__lldb_arg) passed into the expression. (Other persistent
+ // variables are treated similarly, having been materialized as references, but in those
+ // cases the value of the reference itself is never modified.)
+ //
+ // - During materialization, $0 (the result persistent variable) is ignored.
+ //
+ // - During dematerialization, $0 is marked up as a load address with value equal to the
+ // contents of the structure entry.
+ //
+ // For Rvalues
+ //
+ // - In AST result synthesis the expression E is transformed into an initialization
+ // static T $__lldb_expr_result = E.
+ //
+ // - In structure allocation, a pointer-sized slot is allocated in the struct that is to be
+ // passed into the expression.
+ //
+ // - In IR transformations, an instruction is inserted at the beginning of the function to
+ // dereference the pointer resident in the slot. Reads and writes to $__lldb_expr_result
+ // are redirected at that dereferenced version. Guard variables for the static variable
+ // are excised.
+ //
+ // - During materialization, $0 (the result persistent variable) is populated with the location
+ // of a newly-allocated area of memory.
+ //
+ // - During dematerialization, $0 is ignored.
+
+ bool is_lvalue =
+ (last_expr->getValueKind() == VK_LValue || last_expr->getValueKind() == VK_XValue) &&
+ (last_expr->getObjectKind() == OK_Ordinary);
+
QualType expr_qual_type = last_expr->getType();
clang::Type *expr_type = expr_qual_type.getTypePtr();
@@ -259,22 +302,51 @@
{
std::string s = expr_qual_type.getAsString();
- log->Printf("Last statement's type: %s", s.c_str());
+ log->Printf("Last statement is an %s with type: %s", (is_lvalue ? "lvalue" : "rvalue"), s.c_str());
}
- IdentifierInfo &result_id = Ctx.Idents.get("$__lldb_expr_result");
-
- clang::VarDecl *result_decl = VarDecl::Create(Ctx,
- DC,
- SourceLocation(),
- &result_id,
- expr_qual_type,
- NULL,
- SC_Static,
- SC_Static);
+ clang::VarDecl *result_decl;
- if (!result_decl)
- return false;
+ if (is_lvalue)
+ {
+ IdentifierInfo &result_ptr_id = Ctx.Idents.get("$__lldb_expr_result_ptr");
+
+ QualType ptr_qual_type = Ctx.getPointerType(expr_qual_type);
+
+ result_decl = VarDecl::Create(Ctx,
+ DC,
+ SourceLocation(),
+ &result_ptr_id,
+ ptr_qual_type,
+ NULL,
+ SC_Static,
+ SC_Static);
+
+ if (!result_decl)
+ return false;
+
+ ExprResult address_of_expr = m_sema->CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, last_expr);
+
+ m_sema->AddInitializerToDecl(result_decl, address_of_expr.take());
+ }
+ else
+ {
+ IdentifierInfo &result_id = Ctx.Idents.get("$__lldb_expr_result");
+
+ result_decl = VarDecl::Create(Ctx,
+ DC,
+ SourceLocation(),
+ &result_id,
+ expr_qual_type,
+ NULL,
+ SC_Static,
+ SC_Static);
+
+ if (!result_decl)
+ return false;
+
+ m_sema->AddInitializerToDecl(result_decl, last_expr);
+ }
DC->addDecl(result_decl);
@@ -282,7 +354,7 @@
// call AddInitializerToDecl
//
- m_sema->AddInitializerToDecl(result_decl, last_expr);
+ //m_sema->AddInitializerToDecl(result_decl, last_expr);
/////////////////////////////////
// call ConvertDeclToDeclGroup
Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Thu Jan 13 02:53:35 2011
@@ -45,11 +45,12 @@
using namespace lldb_private;
using namespace clang;
-ClangExpressionDeclMap::ClangExpressionDeclMap () :
+ClangExpressionDeclMap::ClangExpressionDeclMap (bool keep_result_in_memory) :
m_found_entities (),
m_struct_members (),
m_parser_vars (),
- m_struct_vars ()
+ m_struct_vars (),
+ m_keep_result_in_memory (keep_result_in_memory)
{
EnableStructVars();
}
@@ -187,6 +188,8 @@
return lldb::ClangExpressionVariableSP();
}
}
+
+ pvar_sp->m_flags |= ClangExpressionVariable::EVIsFreezeDried;
return pvar_sp;
}
@@ -196,11 +199,15 @@
(
const clang::NamedDecl *decl,
const ConstString &name,
- TypeFromParser parser_type
+ TypeFromParser parser_type,
+ bool is_result,
+ bool is_lvalue
)
{
assert (m_parser_vars.get());
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
clang::ASTContext *context(m_parser_vars->m_exe_ctx->target->GetScratchClangASTContext()->getASTContext());
TypeFromUser user_type(ClangASTContext::CopyType(context,
@@ -219,6 +226,24 @@
if (!var_sp)
return false;
+ if (is_result)
+ var_sp->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry;
+ else
+ var_sp->m_flags |= ClangExpressionVariable::EVKeepInTarget; // explicitly-declared persistent variables should persist
+
+ if (is_lvalue)
+ {
+ var_sp->m_flags |= ClangExpressionVariable::EVIsProgramReference;
+ }
+ else
+ {
+ var_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
+ var_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
+ }
+
+ if (log)
+ log->Printf("Created persistent variable with flags 0x%hx", var_sp->m_flags);
+
var_sp->EnableParserVars();
var_sp->m_parser_vars->m_named_decl = decl;
@@ -441,7 +466,7 @@
m_material_vars->m_process = exe_ctx.process;
- bool result = DoMaterialize(false, exe_ctx, NULL, err);
+ bool result = DoMaterialize(false /* dematerialize */, exe_ctx, NULL, err);
if (result)
struct_address = m_material_vars->m_materialized_location;
@@ -740,9 +765,8 @@
if (!DoMaterializeOneVariable (dematerialize,
exe_ctx,
- sym_ctx,
- member_sp->GetName(),
- member_sp->GetTypeFromUser(),
+ sym_ctx,
+ member_sp,
m_material_vars->m_materialized_location + member_sp->m_jit_vars->m_offset,
err))
return false;
@@ -754,20 +778,21 @@
// with with a '$' character...
if (member_sp->GetName().AsCString ("!")[0] == '$' && persistent_vars.ContainsVariable(member_sp))
{
+ bool keep_this_in_memory = false;
+
if (member_sp->GetName() == m_struct_vars->m_result_name)
{
- if (!dematerialize)
- continue;
-
if (log)
log->PutCString("Found result member in the struct");
-
+
if (result_sp_ptr)
*result_sp_ptr = member_sp;
+
+ keep_this_in_memory = m_keep_result_in_memory;
}
if (!DoMaterializeOnePersistentVariable (dematerialize,
- exe_ctx,
+ exe_ctx,
member_sp,
m_material_vars->m_materialized_location + member_sp->m_jit_vars->m_offset,
err))
@@ -784,6 +809,63 @@
return true;
}
+static bool WriteAddressInto
+(
+ ExecutionContext &exe_ctx,
+ lldb::addr_t target,
+ lldb::addr_t address,
+ Error &err
+)
+{
+ size_t pointer_byte_size = exe_ctx.process->GetAddressByteSize();
+
+ StreamString str (0 | Stream::eBinary,
+ pointer_byte_size,
+ exe_ctx.process->GetByteOrder());
+
+ switch (pointer_byte_size)
+ {
+ default:
+ assert(!"Unhandled byte size");
+ case 4:
+ {
+ uint32_t address32 = address & 0xffffffffll;
+ str.PutRawBytes(&address32, sizeof(address32), eByteOrderHost, eByteOrderInvalid);
+ }
+ break;
+ case 8:
+ {
+ uint64_t address64 = address;
+ str.PutRawBytes(&address64, sizeof(address64), eByteOrderHost, eByteOrderInvalid);
+ }
+ break;
+ }
+
+ return (exe_ctx.process->WriteMemory (target, str.GetData(), pointer_byte_size, err) == pointer_byte_size);
+}
+
+static lldb::addr_t ReadAddressFrom
+(
+ ExecutionContext &exe_ctx,
+ lldb::addr_t source,
+ Error &err
+)
+{
+ size_t pointer_byte_size = exe_ctx.process->GetAddressByteSize();
+
+ DataBufferHeap *buf = new DataBufferHeap(pointer_byte_size, 0);
+ DataBufferSP buf_sp(buf);
+
+ if (exe_ctx.process->ReadMemory (source, buf->GetBytes(), pointer_byte_size, err) != pointer_byte_size)
+ return LLDB_INVALID_ADDRESS;
+
+ DataExtractor extractor (buf_sp, exe_ctx.process->GetByteOrder(), exe_ctx.process->GetAddressByteSize());
+
+ uint32_t offset = 0;
+
+ return (lldb::addr_t)extractor.GetPointer(&offset);
+}
+
bool
ClangExpressionDeclMap::DoMaterializeOnePersistentVariable
(
@@ -794,6 +876,8 @@
Error &err
)
{
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
if (!var_sp)
{
err.SetErrorString("Invalid persistent variable");
@@ -808,20 +892,167 @@
Error error;
+ lldb::addr_t mem; // The address of a spare memory area used to hold the persistent variable.
+
if (dematerialize)
{
- var_sp->ValueUpdated ();
- if (exe_ctx.process->ReadMemory (addr, pvar_data, pvar_byte_size, error) != pvar_byte_size)
+ if (log)
+ log->Printf("Dematerializing persistent variable with flags 0x%hx", var_sp->m_flags);
+
+ if ((var_sp->m_flags & ClangExpressionVariable::EVIsLLDBAllocated) ||
+ (var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference))
{
- err.SetErrorStringWithFormat ("Couldn't read a composite type from the target: %s", error.AsCString());
+ // Get the location of the target out of the struct.
+
+ Error read_error;
+ mem = ReadAddressFrom(exe_ctx, addr, read_error);
+
+ if (mem == LLDB_INVALID_ADDRESS)
+ {
+ err.SetErrorStringWithFormat("Couldn't read address of %s from struct: %s", var_sp->GetName().GetCString(), error.AsCString());
+ return false;
+ }
+
+ if (var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference &&
+ !var_sp->m_live_sp)
+ {
+ // If the reference comes from the program, then the ClangExpressionVariable's
+ // live variable data hasn't been set up yet. Do this now.
+
+ var_sp->m_live_sp.reset(new lldb_private::ValueObjectConstResult(var_sp->GetTypeFromUser().GetASTContext(),
+ var_sp->GetTypeFromUser().GetOpaqueQualType(),
+ var_sp->GetName(),
+ mem,
+ lldb::eAddressTypeLoad,
+ pvar_byte_size));
+ }
+
+ if (!var_sp->m_live_sp)
+ {
+ err.SetErrorStringWithFormat("Couldn't find the memory area used to store %s", var_sp->GetName().GetCString());
+ return false;
+ }
+
+ if (var_sp->m_live_sp->GetValue().GetValueAddressType() != lldb::eAddressTypeLoad)
+ {
+ err.SetErrorStringWithFormat("The address of the memory area for %s is in an incorrect format", var_sp->GetName().GetCString());
+ return false;
+ }
+
+ if (var_sp->m_flags & ClangExpressionVariable::EVNeedsFreezeDry)
+ {
+ mem = var_sp->m_live_sp->GetValue().GetScalar().ULongLong();
+
+ if (log)
+ log->Printf("Dematerializing %s from 0x%llx", var_sp->GetName().GetCString(), (uint64_t)mem);
+
+ // Read the contents of the spare memory area
+
+ if (log)
+ log->Printf("Read");
+
+ var_sp->ValueUpdated ();
+ if (exe_ctx.process->ReadMemory (mem, pvar_data, pvar_byte_size, error) != pvar_byte_size)
+ {
+ err.SetErrorStringWithFormat ("Couldn't read a composite type from the target: %s", error.AsCString());
+ return false;
+ }
+
+ var_sp->m_flags &= ~ClangExpressionVariable::EVNeedsFreezeDry;
+ }
+
+ if (var_sp->m_flags & ClangExpressionVariable::EVNeedsAllocation &&
+ !(var_sp->m_flags & ClangExpressionVariable::EVKeepInTarget))
+ {
+ if (m_keep_result_in_memory)
+ {
+ var_sp->m_flags |= ClangExpressionVariable::EVKeepInTarget;
+ }
+ else
+ {
+ Error deallocate_error = exe_ctx.process->DeallocateMemory(mem);
+
+ if (!err.Success())
+ {
+ err.SetErrorStringWithFormat ("Couldn't deallocate memory for %s: %s", var_sp->GetName().GetCString(), deallocate_error.AsCString());
+ return false;
+ }
+ }
+ }
+ }
+ else
+ {
+ err.SetErrorStringWithFormat("Persistent variables without separate allocations are not currently supported.");
return false;
}
}
else
{
- if (exe_ctx.process->WriteMemory (addr, pvar_data, pvar_byte_size, error) != pvar_byte_size)
+ if (log)
+ log->Printf("Materializing persistent variable with flags 0x%hx", var_sp->m_flags);
+
+ if (var_sp->m_flags & ClangExpressionVariable::EVNeedsAllocation)
+ {
+ // Allocate a spare memory area to store the persistent variable's contents.
+
+ Error allocate_error;
+
+ mem = exe_ctx.process->AllocateMemory(pvar_byte_size,
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ allocate_error);
+
+ if (mem == LLDB_INVALID_ADDRESS)
+ {
+ err.SetErrorStringWithFormat("Couldn't allocate a memory area to store %s: %s", var_sp->GetName().GetCString(), allocate_error.AsCString());
+ return false;
+ }
+
+ if (log)
+ log->Printf("Allocated %s (0x%llx) sucessfully", var_sp->GetName().GetCString(), mem);
+
+ // Put the location of the spare memory into the live data of the ValueObject.
+
+ var_sp->m_live_sp.reset(new lldb_private::ValueObjectConstResult(var_sp->GetTypeFromUser().GetASTContext(),
+ var_sp->GetTypeFromUser().GetOpaqueQualType(),
+ var_sp->GetName(),
+ mem,
+ lldb::eAddressTypeLoad,
+ pvar_byte_size));
+
+ // Clear the flag if the variable will never be deallocated.
+
+ if (var_sp->m_flags & ClangExpressionVariable::EVKeepInTarget)
+ var_sp->m_flags &= ~ClangExpressionVariable::EVNeedsAllocation;
+
+ // Write the contents of the variable to the area.
+
+ if (exe_ctx.process->WriteMemory (mem, pvar_data, pvar_byte_size, error) != pvar_byte_size)
+ {
+ err.SetErrorStringWithFormat ("Couldn't write a composite type to the target: %s", error.AsCString());
+ return false;
+ }
+ }
+
+ if ((var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference && var_sp->m_live_sp) ||
+ var_sp->m_flags & ClangExpressionVariable::EVIsLLDBAllocated)
{
- err.SetErrorStringWithFormat ("Couldn't write a composite type to the target: %s", error.AsCString());
+ mem = var_sp->m_live_sp->GetValue().GetScalar().ULongLong();
+
+ // Now write the location of the area into the struct.
+
+ Error write_error;
+ if (!WriteAddressInto(exe_ctx, addr, mem, write_error))
+ {
+ err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", var_sp->GetName().GetCString(), write_error.AsCString());
+ return false;
+ }
+
+ if (log)
+ log->Printf("Materialized %s into 0x%llx", var_sp->GetName().GetCString(), (uint64_t)mem);
+ }
+ else if (!var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference)
+ {
+ err.SetErrorStringWithFormat("Persistent variables without separate allocations are not currently supported.");
return false;
}
}
@@ -835,8 +1066,7 @@
bool dematerialize,
ExecutionContext &exe_ctx,
const SymbolContext &sym_ctx,
- const ConstString &name,
- TypeFromUser type,
+ ClangExpressionVariableSP &expr_var,
lldb::addr_t addr,
Error &err
)
@@ -846,6 +1076,11 @@
if (!exe_ctx.frame || !exe_ctx.process)
return false;
+ // Vital information about the value
+
+ const ConstString &name(expr_var->GetName());
+ TypeFromUser type(expr_var->GetTypeFromUser());
+
Variable *var = FindVariableInScope (*exe_ctx.frame, name, &type);
if (!var)
@@ -869,8 +1104,8 @@
// The size of the type contained in addr
- size_t addr_bit_size = ClangASTType::GetClangTypeBitWidth(type.GetASTContext(), type.GetOpaqueQualType());
- size_t addr_byte_size = addr_bit_size % 8 ? ((addr_bit_size + 8) / 8) : (addr_bit_size / 8);
+ size_t value_bit_size = ClangASTType::GetClangTypeBitWidth(type.GetASTContext(), type.GetOpaqueQualType());
+ size_t value_byte_size = value_bit_size % 8 ? ((value_bit_size + 8) / 8) : (value_bit_size / 8);
Value::ValueType value_type = location_value->GetValueType();
@@ -888,40 +1123,21 @@
break;
case Value::eValueTypeLoadAddress:
{
- lldb::addr_t value_addr = location_value->GetScalar().ULongLong();
-
- DataBufferHeap data;
- data.SetByteSize(addr_byte_size);
-
- lldb::addr_t src_addr;
- lldb::addr_t dest_addr;
-
- if (dematerialize)
- {
- src_addr = addr;
- dest_addr = value_addr;
- }
- else
- {
- src_addr = value_addr;
- dest_addr = addr;
- }
-
- Error error;
- if (exe_ctx.process->ReadMemory (src_addr, data.GetBytes(), addr_byte_size, error) != addr_byte_size)
- {
- err.SetErrorStringWithFormat ("Couldn't read %s from the target: %s", name.GetCString(), error.AsCString());
- return false;
- }
-
- if (exe_ctx.process->WriteMemory (dest_addr, data.GetBytes(), addr_byte_size, error) != addr_byte_size)
+ if (!dematerialize)
{
- err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", name.GetCString(), error.AsCString());
- return false;
+ lldb::addr_t value_addr = location_value->GetScalar().ULongLong();
+
+ Error error;
+
+ if (!WriteAddressInto(exe_ctx,
+ addr,
+ value_addr,
+ error))
+ {
+ err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", name.GetCString(), error.AsCString());
+ return false;
+ }
}
-
- if (log)
- log->Printf("Copied from 0x%llx to 0x%llx", (uint64_t)src_addr, (uint64_t)addr);
}
break;
case Value::eValueTypeScalar:
@@ -929,13 +1145,14 @@
if (location_value->GetContextType() != Value::eContextTypeRegisterInfo)
{
StreamString ss;
-
location_value->Dump(&ss);
err.SetErrorStringWithFormat("%s is a scalar of unhandled type: %s", name.GetCString(), ss.GetString().c_str());
return false;
}
+ lldb::addr_t mem; // The address of a spare memory area aused to hold the variable.
+
lldb::RegisterInfo *register_info = location_value->GetRegisterInfo();
if (!register_info)
@@ -957,6 +1174,22 @@
if (dematerialize)
{
+ // Get the location of the spare memory area out of the variable's live data.
+
+ if (!expr_var->m_live_sp)
+ {
+ err.SetErrorStringWithFormat("Couldn't find the memory area used to store %s", name.GetCString());
+ return false;
+ }
+
+ if (expr_var->m_live_sp->GetValue().GetValueAddressType() != lldb::eAddressTypeLoad)
+ {
+ err.SetErrorStringWithFormat("The address of the memory area for %s is in an incorrect format", name.GetCString());
+ return false;
+ }
+
+ mem = expr_var->m_live_sp->GetValue().GetScalar().ULongLong();
+
// Moving from addr into a register
//
// Case 1: addr_byte_size and register_byte_size are the same
@@ -974,7 +1207,7 @@
// |AABB0000| Register contents [on little-endian hardware]
// |0000AABB| Register contents [on big-endian hardware]
- if (addr_byte_size > register_byte_size)
+ if (value_byte_size > register_byte_size)
{
err.SetErrorStringWithFormat("%s is too big to store in %s", name.GetCString(), register_info->name);
return false;
@@ -991,14 +1224,14 @@
register_offset = 0;
break;
case lldb::eByteOrderBig:
- register_offset = register_byte_size - addr_byte_size;
+ register_offset = register_byte_size - value_byte_size;
break;
}
DataBufferHeap register_data (register_byte_size, 0);
Error error;
- if (exe_ctx.process->ReadMemory (addr, register_data.GetBytes() + register_offset, addr_byte_size, error) != addr_byte_size)
+ if (exe_ctx.process->ReadMemory (mem, register_data.GetBytes() + register_offset, value_byte_size, error) != value_byte_size)
{
err.SetErrorStringWithFormat ("Couldn't read %s from the target: %s", name.GetCString(), error.AsCString());
return false;
@@ -1011,9 +1244,54 @@
err.SetErrorStringWithFormat("Couldn't read %s from %s", name.GetCString(), register_info->name);
return false;
}
+
+ // Deallocate the spare area and clear the variable's live data.
+
+ Error deallocate_error = exe_ctx.process->DeallocateMemory(mem);
+
+ if (!deallocate_error.Success())
+ {
+ err.SetErrorStringWithFormat("Couldn't deallocate spare memory area for %s: %s", name.GetCString(), deallocate_error.AsCString());
+ return false;
+ }
+
+ expr_var->m_live_sp.reset();
}
else
{
+ // Allocate a spare memory area to place the register's contents into. This memory area will be pointed to by the slot in the
+ // struct.
+
+ Error allocate_error;
+
+ mem = exe_ctx.process->AllocateMemory(value_byte_size,
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ allocate_error);
+
+ if (mem == LLDB_INVALID_ADDRESS)
+ {
+ err.SetErrorStringWithFormat("Couldn't allocate a memory area to store %s: %s", name.GetCString(), allocate_error.AsCString());
+ return false;
+ }
+
+ // Put the location of the spare memory into the live data of the ValueObject.
+
+ expr_var->m_live_sp.reset(new lldb_private::ValueObjectConstResult(type.GetASTContext(),
+ type.GetOpaqueQualType(),
+ name,
+ mem,
+ lldb::eAddressTypeLoad,
+ value_byte_size));
+
+ // Now write the location of the area into the struct.
+
+ Error write_error;
+ if (!WriteAddressInto(exe_ctx, addr, mem, write_error))
+ {
+ err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", name.GetCString(), write_error.AsCString());
+ return false;
+ }
+
// Moving from a register into addr
//
// Case 1: addr_byte_size and register_byte_size are the same
@@ -1031,7 +1309,7 @@
// |AABB| Address contents on little-endian hardware
// |CCDD| Address contents on big-endian hardware
- if (addr_byte_size > register_byte_size)
+ if (value_byte_size > register_byte_size)
{
err.SetErrorStringWithFormat("%s is too big to store in %s", name.GetCString(), register_info->name);
return false;
@@ -1048,7 +1326,7 @@
register_offset = 0;
break;
case lldb::eByteOrderBig:
- register_offset = register_byte_size - addr_byte_size;
+ register_offset = register_byte_size - value_byte_size;
break;
}
@@ -1060,7 +1338,7 @@
return false;
}
- const void *register_data = register_extractor.GetData(®ister_offset, addr_byte_size);
+ const void *register_data = register_extractor.GetData(®ister_offset, value_byte_size);
if (!register_data)
{
@@ -1068,10 +1346,9 @@
return false;
}
- Error error;
- if (exe_ctx.process->WriteMemory (addr, register_data, addr_byte_size, error) != addr_byte_size)
+ if (exe_ctx.process->WriteMemory (mem, register_data, value_byte_size, write_error) != value_byte_size)
{
- err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", error.AsCString());
+ err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", write_error.AsCString());
return false;
}
}
@@ -1581,7 +1858,7 @@
if (!var_location)
return;
- NamedDecl *var_decl = context.AddVarDecl(pt.GetOpaqueQualType());
+ NamedDecl *var_decl = context.AddVarDecl(ClangASTContext::CreateLValueReferenceType(pt.GetASTContext(), pt.GetOpaqueQualType()));
std::string decl_name(context.m_decl_name.getAsString());
ConstString entity_name(decl_name.c_str());
ClangExpressionVariableSP entity(m_found_entities.CreateVariable (entity_name,
@@ -1619,7 +1896,7 @@
user_type.GetOpaqueQualType()),
context.GetASTContext());
- NamedDecl *var_decl = context.AddVarDecl(parser_type.GetOpaqueQualType());
+ NamedDecl *var_decl = context.AddVarDecl(ClangASTContext::CreateLValueReferenceType(parser_type.GetASTContext(), parser_type.GetOpaqueQualType()));
pvar_sp->EnableParserVars();
pvar_sp->m_parser_vars->m_parser_type = parser_type;
Modified: lldb/trunk/source/Expression/ClangExpressionVariable.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionVariable.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionVariable.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionVariable.cpp Thu Jan 13 02:53:35 2011
@@ -28,14 +28,16 @@
ClangExpressionVariable::ClangExpressionVariable(lldb::ByteOrder byte_order, uint32_t addr_byte_size) :
m_parser_vars(),
m_jit_vars (),
- m_valojb_sp (new ValueObjectConstResult(byte_order, addr_byte_size))
+ m_frozen_sp (new ValueObjectConstResult(byte_order, addr_byte_size)),
+ m_flags (EVNone)
{
}
ClangExpressionVariable::ClangExpressionVariable (const lldb::ValueObjectSP &valobj_sp) :
m_parser_vars(),
m_jit_vars (),
- m_valojb_sp (valobj_sp)
+ m_frozen_sp (valobj_sp),
+ m_flags (EVNone)
{
}
@@ -45,76 +47,76 @@
size_t
ClangExpressionVariable::GetByteSize ()
{
- return m_valojb_sp->GetByteSize();
+ return m_frozen_sp->GetByteSize();
}
const ConstString &
ClangExpressionVariable::GetName ()
{
- return m_valojb_sp->GetName();
+ return m_frozen_sp->GetName();
}
lldb::ValueObjectSP
ClangExpressionVariable::GetValueObject()
{
- return m_valojb_sp;
+ return m_frozen_sp;
}
lldb::RegisterInfo *
ClangExpressionVariable::GetRegisterInfo()
{
- return m_valojb_sp->GetValue().GetRegisterInfo();
+ return m_frozen_sp->GetValue().GetRegisterInfo();
}
void
ClangExpressionVariable::SetRegisterInfo (const lldb::RegisterInfo *reg_info)
{
- return m_valojb_sp->GetValue().SetContext (Value::eContextTypeRegisterInfo, const_cast(reg_info));
+ return m_frozen_sp->GetValue().SetContext (Value::eContextTypeRegisterInfo, const_cast(reg_info));
}
lldb::clang_type_t
ClangExpressionVariable::GetClangType()
{
- return m_valojb_sp->GetClangType();
+ return m_frozen_sp->GetClangType();
}
void
ClangExpressionVariable::SetClangType(lldb::clang_type_t clang_type)
{
- m_valojb_sp->GetValue().SetContext(Value::eContextTypeClangType, clang_type);
+ m_frozen_sp->GetValue().SetContext(Value::eContextTypeClangType, clang_type);
}
clang::ASTContext *
ClangExpressionVariable::GetClangAST()
{
- return m_valojb_sp->GetClangAST();
+ return m_frozen_sp->GetClangAST();
}
void
ClangExpressionVariable::SetClangAST (clang::ASTContext *ast)
{
- m_valojb_sp->SetClangAST (ast);
+ m_frozen_sp->SetClangAST (ast);
}
TypeFromUser
ClangExpressionVariable::GetTypeFromUser()
{
- TypeFromUser tfu (m_valojb_sp->GetClangType(), m_valojb_sp->GetClangAST());
+ TypeFromUser tfu (m_frozen_sp->GetClangType(), m_frozen_sp->GetClangAST());
return tfu;
}
uint8_t *
ClangExpressionVariable::GetValueBytes()
{
- const size_t byte_size = m_valojb_sp->GetByteSize();
+ const size_t byte_size = m_frozen_sp->GetByteSize();
if (byte_size > 0)
{
- if (m_valojb_sp->GetDataExtractor().GetByteSize() < byte_size)
+ if (m_frozen_sp->GetDataExtractor().GetByteSize() < byte_size)
{
- m_valojb_sp->GetValue().ResizeData(byte_size);
- m_valojb_sp->GetValue().GetData (m_valojb_sp->GetDataExtractor());
+ m_frozen_sp->GetValue().ResizeData(byte_size);
+ m_frozen_sp->GetValue().GetData (m_frozen_sp->GetDataExtractor());
}
- return const_cast(m_valojb_sp->GetDataExtractor().GetDataStart());
+ return const_cast(m_frozen_sp->GetDataExtractor().GetDataStart());
}
return NULL;
}
@@ -122,12 +124,12 @@
void
ClangExpressionVariable::SetName (const ConstString &name)
{
- m_valojb_sp->SetName (name);
+ m_frozen_sp->SetName (name);
}
void
ClangExpressionVariable::ValueUpdated ()
{
- m_valojb_sp->ValueUpdated ();
+ m_frozen_sp->ValueUpdated ();
}
Modified: lldb/trunk/source/Expression/ClangUserExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangUserExpression.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangUserExpression.cpp (original)
+++ lldb/trunk/source/Expression/ClangUserExpression.cpp Thu Jan 13 02:53:35 2011
@@ -144,6 +144,7 @@
ClangUserExpression::Parse (Stream &error_stream,
ExecutionContext &exe_ctx,
TypeFromUser desired_type,
+ bool keep_result_in_memory,
lldb::ClangExpressionVariableSP *const_result)
{
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -248,7 +249,7 @@
m_desired_type = desired_type;
- m_expr_decl_map.reset(new ClangExpressionDeclMap());
+ m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory));
m_expr_decl_map->WillParse(exe_ctx);
@@ -398,7 +399,7 @@
ThreadPlan *
ClangUserExpression::GetThreadPlanToExecuteJITExpression (Stream &error_stream,
- ExecutionContext &exe_ctx)
+ ExecutionContext &exe_ctx)
{
lldb::addr_t struct_address;
@@ -460,6 +461,7 @@
ClangUserExpression::Execute (Stream &error_stream,
ExecutionContext &exe_ctx,
bool discard_on_error,
+ bool keep_in_memory,
ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me,
lldb::ClangExpressionVariableSP &result)
{
@@ -556,6 +558,7 @@
lldb::ExecutionResults
ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
bool discard_on_error,
+ bool keep_in_memory,
const char *expr_cstr,
const char *expr_prefix,
lldb::ValueObjectSP &result_valobj_sp)
@@ -619,7 +622,7 @@
{
lldb::ClangExpressionVariableSP expr_result;
- if (const_result.get())
+ if (const_result.get() && !keep_in_memory)
{
if (log)
log->Printf("== [ClangUserExpression::Evaluate] Expression evaluated as a constant ==");
@@ -635,7 +638,8 @@
execution_results = user_expression_sp->Execute (error_stream,
exe_ctx,
- discard_on_error,
+ discard_on_error,
+ keep_in_memory,
user_expression_sp,
expr_result);
Modified: lldb/trunk/source/Expression/ClangUtilityFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangUtilityFunction.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangUtilityFunction.cpp (original)
+++ lldb/trunk/source/Expression/ClangUtilityFunction.cpp Thu Jan 13 02:53:35 2011
@@ -99,7 +99,9 @@
// Parse the expression
//
- m_expr_decl_map.reset(new ClangExpressionDeclMap());
+ bool keep_result_in_memory = false;
+
+ m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory));
m_expr_decl_map->WillParse(exe_ctx);
Modified: lldb/trunk/source/Expression/IRForTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRForTarget.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Expression/IRForTarget.cpp (original)
+++ lldb/trunk/source/Expression/IRForTarget.cpp Thu Jan 13 02:53:35 2011
@@ -43,7 +43,8 @@
m_func_name(func_name),
m_resolve_vars(resolve_vars),
m_const_result(const_result),
- m_has_side_effects(NULL)
+ m_has_side_effects(false),
+ m_result_is_pointer(false)
{
}
@@ -153,10 +154,19 @@
vi != ve;
++vi)
{
+ if (strstr(vi->first(), "$__lldb_expr_result_ptr") &&
+ !strstr(vi->first(), "GV"))
+ {
+ result_name = vi->first();
+ m_result_is_pointer = true;
+ break;
+ }
+
if (strstr(vi->first(), "$__lldb_expr_result") &&
!strstr(vi->first(), "GV"))
{
result_name = vi->first();
+ m_result_is_pointer = false;
break;
}
}
@@ -178,7 +188,7 @@
{
if (log)
log->PutCString("Result variable had no data");
-
+
return false;
}
@@ -240,14 +250,43 @@
// Get the next available result name from m_decl_map and create the persistent
// variable for it
- lldb_private::TypeFromParser result_decl_type (result_decl->getType().getAsOpaquePtr(),
- &result_decl->getASTContext());
-
- lldb_private::ConstString new_result_name (m_decl_map->GetPersistentResultName());
- m_decl_map->AddPersistentVariable(result_decl, new_result_name, result_decl_type);
+ lldb_private::TypeFromParser result_decl_type;
+
+ if (m_result_is_pointer)
+ {
+ clang::QualType pointer_qual_type = result_decl->getType();
+ clang::Type *pointer_type = pointer_qual_type.getTypePtr();
+ clang::PointerType *pointer_pointertype = dyn_cast(pointer_type);
+
+ if (!pointer_pointertype)
+ {
+ if (log)
+ log->PutCString("Expected result to have pointer type, but it did not");
+ return false;
+ }
+
+ clang::QualType element_qual_type = pointer_pointertype->getPointeeType();
+
+ result_decl_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(),
+ &result_decl->getASTContext());
+ }
+ else
+ {
+ result_decl_type = lldb_private::TypeFromParser(result_decl->getType().getAsOpaquePtr(),
+ &result_decl->getASTContext());
+ }
+
+ m_result_name = m_decl_map->GetPersistentResultName();
+ // If the result is an Lvalue, it is emitted as a pointer; see
+ // ASTResultSynthesizer::SynthesizeBodyResult.
+ m_decl_map->AddPersistentVariable(result_decl,
+ m_result_name,
+ result_decl_type,
+ true,
+ m_result_is_pointer);
if (log)
- log->Printf("Creating a new result global: \"%s\"", new_result_name.GetCString());
+ log->Printf("Creating a new result global: \"%s\"", m_result_name.GetCString());
// Construct a new result global and set up its metadata
@@ -256,7 +295,7 @@
false, /* not constant */
GlobalValue::ExternalLinkage,
NULL, /* no initializer */
- new_result_name.GetCString ());
+ m_result_name.GetCString ());
// It's too late in compilation to create a new VarDecl for this, but we don't
// need to. We point the metadata at the old VarDecl. This creates an odd
@@ -307,7 +346,7 @@
if (!m_has_side_effects)
{
MaybeSetConstantResult (initializer,
- new_result_name,
+ m_result_name,
result_decl_type);
}
@@ -800,7 +839,7 @@
StringRef decl_name (decl->getName());
lldb_private::ConstString persistent_variable_name (decl_name.data(), decl_name.size());
- if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name, result_decl_type))
+ if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name, result_decl_type, false, false))
return false;
GlobalVariable *persistent_global = new GlobalVariable(llvm_module,
@@ -964,9 +1003,27 @@
return false;
}
- clang::QualType qual_type(clang::QualType::getFromOpaquePtr(opaque_type));
+ clang::QualType qual_type;
+ const Type *value_type;
+
+ if (!name.compare("$__lldb_expr_result"))
+ {
+ // The $__lldb_expr_result name indicates the the return value has allocated as
+ // a static variable. Per the comment at ASTResultSynthesizer::SynthesizeBodyResult,
+ // accesses to this static variable need to be redirected to the result of dereferencing
+ // a pointer that is passed in as one of the arguments.
+ //
+ // Consequently, when reporting the size of the type, we report a pointer type pointing
+ // to the type of $__lldb_expr_result, not the type itself.
- const Type *value_type = global_variable->getType();
+ qual_type = ast_context->getPointerType(clang::QualType::getFromOpaquePtr(opaque_type));
+ value_type = PointerType::get(global_variable->getType(), 0);
+ }
+ else
+ {
+ qual_type = clang::QualType::getFromOpaquePtr(opaque_type);
+ value_type = global_variable->getType();
+ }
size_t value_size = (ast_context->getTypeSize(qual_type) + 7) / 8;
off_t value_alignment = (ast_context->getTypeAlign(qual_type) + 7) / 8;
@@ -1479,12 +1536,31 @@
ConstantInt *offset_int(ConstantInt::getSigned(offset_type, offset));
GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(argument, offset_int, "", FirstEntryInstruction);
- BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType(), "", FirstEntryInstruction);
+
+ Value *replacement;
+
+ // Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, in cases where the result
+ // variable is an rvalue, we have to synthesize a dereference of the appropriate structure
+ // entry in order to produce the static variable that the AST thinks it is accessing.
+ if (name == m_result_name && !m_result_is_pointer)
+ {
+ BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType()->getPointerTo(), "", FirstEntryInstruction);
+ LoadInst *load = new LoadInst(bit_cast, "", FirstEntryInstruction);
+
+ replacement = load;
+ }
+ else
+ {
+ BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType(), "", FirstEntryInstruction);
+
+ replacement = bit_cast;
+ }
+
if (Constant *constant = dyn_cast(value))
- UnfoldConstant(constant, bit_cast, FirstEntryInstruction);
+ UnfoldConstant(constant, replacement, FirstEntryInstruction);
else
- value->replaceAllUsesWith(bit_cast);
+ value->replaceAllUsesWith(replacement);
if (GlobalVariable *var = dyn_cast(value))
var->eraseFromParent();
@@ -1507,7 +1583,7 @@
{
if (log)
log->Printf("Couldn't find \"%s()\" in the module", m_func_name.c_str());
-
+
return false;
}
Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp Thu Jan 13 02:53:35 2011
@@ -859,7 +859,7 @@
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse (packet, response, timeout_seconds, false))
{
- if (!response.IsOKPacket())
+ if (response.IsOKPacket())
return true;
}
return false;
Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTContext.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTContext.cpp Thu Jan 13 02:53:35 2011
@@ -3615,18 +3615,20 @@
}
clang_type_t
-ClangASTContext::CreateLValueReferenceType (clang_type_t clang_type)
+ClangASTContext::CreateLValueReferenceType (clang::ASTContext *ast,
+ clang_type_t clang_type)
{
if (clang_type)
- return getASTContext()->getLValueReferenceType (QualType::getFromOpaquePtr(clang_type)).getAsOpaquePtr();
+ return ast->getLValueReferenceType (QualType::getFromOpaquePtr(clang_type)).getAsOpaquePtr();
return NULL;
}
clang_type_t
-ClangASTContext::CreateRValueReferenceType (clang_type_t clang_type)
+ClangASTContext::CreateRValueReferenceType (clang::ASTContext *ast,
+ clang_type_t clang_type)
{
if (clang_type)
- return getASTContext()->getRValueReferenceType (QualType::getFromOpaquePtr(clang_type)).getAsOpaquePtr();
+ return ast->getRValueReferenceType (QualType::getFromOpaquePtr(clang_type)).getAsOpaquePtr();
return NULL;
}
Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Thu Jan 13 02:53:35 2011
@@ -709,13 +709,14 @@
ExecutionContext exe_ctx;
frame_sp->CalculateExecutionContext (exe_ctx);
bool unwind_on_error = true;
+ bool keep_in_memory = false;
StreamString expr;
char path[PATH_MAX];
image_spec.GetPath(path, sizeof(path));
expr.Printf("dlopen (\"%s\", 2)", path);
const char *prefix = "extern \"C\" void* dlopen (const char *path, int mode);\n";
lldb::ValueObjectSP result_valobj_sp;
- ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
+ ClangUserExpression::Evaluate (exe_ctx, keep_in_memory, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
if (result_valobj_sp->GetError().Success())
{
Scalar scalar;
@@ -776,11 +777,12 @@
ExecutionContext exe_ctx;
frame_sp->CalculateExecutionContext (exe_ctx);
bool unwind_on_error = true;
+ bool keep_in_memory = false;
StreamString expr;
expr.Printf("dlclose ((void *)0x%llx)", image_addr);
const char *prefix = "extern \"C\" int dlclose(void* handle);\n";
lldb::ValueObjectSP result_valobj_sp;
- ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
+ ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, keep_in_memory, expr.GetData(), prefix, result_valobj_sp);
if (result_valobj_sp->GetError().Success())
{
Scalar scalar;
Modified: lldb/trunk/source/Target/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Target/Target.cpp (original)
+++ lldb/trunk/source/Target/Target.cpp Thu Jan 13 02:53:35 2011
@@ -910,6 +910,7 @@
const char *expr_cstr,
StackFrame *frame,
bool unwind_on_error,
+ bool keep_in_memory,
lldb::ValueObjectSP &result_valobj_sp
)
{
@@ -952,10 +953,32 @@
const_valobj_sp = result_valobj_sp->CreateConstantValue (exe_ctx.GetBestExecutionContextScope(),
persistent_variable_name);
+ lldb::ValueObjectSP live_valobj_sp = result_valobj_sp;
+
result_valobj_sp = const_valobj_sp;
- ClangExpressionVariableSP clang_expr_variable_sp(m_persistent_variables.CreatePersistentVariable(result_valobj_sp));
- assert (clang_expr_variable_sp.get());
+ ClangExpressionVariableSP clang_expr_variable_sp(m_persistent_variables.CreatePersistentVariable(result_valobj_sp));
+ assert (clang_expr_variable_sp.get());
+
+ // Set flags and live data as appropriate
+
+ const Value &result_value = live_valobj_sp->GetValue();
+
+ switch (result_value.GetValueType())
+ {
+ case Value::eValueTypeHostAddress:
+ case Value::eValueTypeFileAddress:
+ // we don't do anything with these for now
+ break;
+ case Value::eValueTypeScalar:
+ clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
+ clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
+ break;
+ case Value::eValueTypeLoadAddress:
+ clang_expr_variable_sp->m_live_sp = live_valobj_sp;
+ clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVIsProgramReference;
+ break;
+ }
}
else
{
@@ -976,7 +999,8 @@
const char *prefix = GetExpressionPrefixContentsAsCString();
execution_results = ClangUserExpression::Evaluate (exe_ctx,
- unwind_on_error,
+ unwind_on_error,
+ keep_in_memory,
expr_cstr,
prefix,
result_valobj_sp);
From scallanan at apple.com Thu Jan 13 15:23:32 2011
From: scallanan at apple.com (Sean Callanan)
Date: Thu, 13 Jan 2011 21:23:32 -0000
Subject: [Lldb-commits] [lldb] r123398 - in /lldb/trunk/source/Expression:
ClangExpressionDeclMap.cpp IRForTarget.cpp
Message-ID: <20110113212332.C550A2A6C12C@llvm.org>
Author: spyffe
Date: Thu Jan 13 15:23:32 2011
New Revision: 123398
URL: http://llvm.org/viewvc/llvm-project?rev=123398&view=rev
Log:
Fixed handling of explicitly-declared persistent
variables.
Modified:
lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
lldb/trunk/source/Expression/IRForTarget.cpp
Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp?rev=123398&r1=123397&r2=123398&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Thu Jan 13 15:23:32 2011
@@ -213,7 +213,7 @@
TypeFromUser user_type(ClangASTContext::CopyType(context,
parser_type.GetASTContext(),
parser_type.GetOpaqueQualType()),
- context);
+ context);
if (!m_parser_vars->m_persistent_vars->CreatePersistentVariable (name,
user_type,
@@ -939,7 +939,8 @@
return false;
}
- if (var_sp->m_flags & ClangExpressionVariable::EVNeedsFreezeDry)
+ if (var_sp->m_flags & ClangExpressionVariable::EVNeedsFreezeDry ||
+ var_sp->m_flags & ClangExpressionVariable::EVKeepInTarget)
{
mem = var_sp->m_live_sp->GetValue().GetScalar().ULongLong();
Modified: lldb/trunk/source/Expression/IRForTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRForTarget.cpp?rev=123398&r1=123397&r2=123398&view=diff
==============================================================================
--- lldb/trunk/source/Expression/IRForTarget.cpp (original)
+++ lldb/trunk/source/Expression/IRForTarget.cpp Thu Jan 13 15:23:32 2011
@@ -816,6 +816,8 @@
IRForTarget::RewritePersistentAlloc (llvm::Instruction *persistent_alloc,
llvm::Module &llvm_module)
{
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
AllocaInst *alloc = dyn_cast(persistent_alloc);
MDNode *alloc_md = alloc->getMetadata("clang.decl.ptr");
@@ -842,8 +844,8 @@
if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name, result_decl_type, false, false))
return false;
- GlobalVariable *persistent_global = new GlobalVariable(llvm_module,
- alloc->getType()->getElementType(),
+ GlobalVariable *persistent_global = new GlobalVariable(llvm_module,
+ alloc->getType(),
false, /* not constant */
GlobalValue::ExternalLinkage,
NULL, /* no initializer */
@@ -861,7 +863,17 @@
MDNode *persistent_global_md = MDNode::get(llvm_module.getContext(), values, 2);
named_metadata->addOperand(persistent_global_md);
- alloc->replaceAllUsesWith(persistent_global);
+ // Now, since the variable is a pointer variable, we will drop in a load of that
+ // pointer variable.
+
+ LoadInst *persistent_load = new LoadInst (persistent_global, "", alloc);
+
+ if (log)
+ log->Printf("Replacing \"%s\" with \"%s\"",
+ PrintValue(alloc).c_str(),
+ PrintValue(persistent_load).c_str());
+
+ alloc->replaceAllUsesWith(persistent_load);
alloc->eraseFromParent();
return true;
@@ -1006,7 +1018,7 @@
clang::QualType qual_type;
const Type *value_type;
- if (!name.compare("$__lldb_expr_result"))
+ if (name[0] == '$')
{
// The $__lldb_expr_result name indicates the the return value has allocated as
// a static variable. Per the comment at ASTResultSynthesizer::SynthesizeBodyResult,
@@ -1015,6 +1027,8 @@
//
// Consequently, when reporting the size of the type, we report a pointer type pointing
// to the type of $__lldb_expr_result, not the type itself.
+ //
+ // We also do this for any user-declared persistent variables.
qual_type = ast_context->getPointerType(clang::QualType::getFromOpaquePtr(opaque_type));
value_type = PointerType::get(global_variable->getType(), 0);
@@ -1029,7 +1043,7 @@
off_t value_alignment = (ast_context->getTypeAlign(qual_type) + 7) / 8;
if (log)
- log->Printf("Type of \"%s\" is [clang \"%s\", lldb \"%s\"] [size %d, align %d]",
+ log->Printf("Type of \"%s\" is [clang \"%s\", llvm \"%s\"] [size %d, align %d]",
name.c_str(),
qual_type.getAsString().c_str(),
PrintType(value_type).c_str(),
From ctice at apple.com Thu Jan 13 18:29:17 2011
From: ctice at apple.com (Caroline Tice)
Date: Fri, 14 Jan 2011 00:29:17 -0000
Subject: [Lldb-commits] [lldb] r123415 - in /lldb/trunk: include/lldb/Core/
include/lldb/Interpreter/ scripts/ source/ source/Core/ source/Interpreter/
Message-ID: <20110114002917.31F182A6C12C@llvm.org>
Author: ctice
Date: Thu Jan 13 18:29:16 2011
New Revision: 123415
URL: http://llvm.org/viewvc/llvm-project?rev=123415&view=rev
Log:
Split up the Python script interpreter code to allow multiple script interpreter objects to
exist within the same process (one script interpreter object per debugger object). The
python script interpreter objects are all using the same global Python script interpreter;
they use separate dictionaries to keep their data separate, and mutex's to prevent any object
attempting to use the global Python interpreter when another object is already using it.
Modified:
lldb/trunk/include/lldb/Core/Debugger.h
lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h
lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h
lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h
lldb/trunk/scripts/lldb.swig
lldb/trunk/source/Core/Debugger.cpp
lldb/trunk/source/Interpreter/CommandInterpreter.cpp
lldb/trunk/source/Interpreter/CommandObjectScript.cpp
lldb/trunk/source/Interpreter/CommandObjectScript.h
lldb/trunk/source/Interpreter/ScriptInterpreter.cpp
lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp
lldb/trunk/source/Interpreter/embedded_interpreter.py
lldb/trunk/source/lldb.cpp
Modified: lldb/trunk/include/lldb/Core/Debugger.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Debugger.h?rev=123415&r1=123414&r2=123415&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Debugger.h (original)
+++ lldb/trunk/include/lldb/Core/Debugger.h Thu Jan 13 18:29:16 2011
@@ -166,7 +166,6 @@
m_auto_confirm_on = auto_confirm_on;
}
-
protected:
void
@@ -375,6 +374,9 @@
void
CleanUpInputReaders ();
+ static int
+ TestDebuggerRefCount ();
+
protected:
static void
Modified: lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h?rev=123415&r1=123414&r2=123415&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h (original)
+++ lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h Thu Jan 13 18:29:16 2011
@@ -262,6 +262,7 @@
OptionArgMap m_alias_options; // Stores any options (with or without arguments) that go with any alias.
std::vector m_command_history;
std::string m_repeat_command; // Stores the command that will be executed for an empty command string.
+ std::auto_ptr m_script_interpreter_ap;
};
Modified: lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h?rev=123415&r1=123414&r2=123415&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h (original)
+++ lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h Thu Jan 13 18:29:16 2011
@@ -90,16 +90,23 @@
int
GetMasterFileDescriptor ();
- CommandInterpreter *
- GetCommandInterpreter ();
+ CommandInterpreter &
+ GetCommandInterpreter ();
- static std::string
- LanguageToString (lldb::ScriptLanguage);
+ static std::string
+ LanguageToString (lldb::ScriptLanguage language);
+
+ static void
+ Initialize ();
+
+ static void
+ Terminate ();
+
+ virtual void
+ ResetOutputFileHandle (FILE *new_fh) { } //By default, do nothing.
protected:
CommandInterpreter &m_interpreter;
-
-private:
lldb::ScriptLanguage m_script_lang;
// Scripting languages may need to use stdin for their interactive loops;
@@ -108,8 +115,11 @@
// embedded scripting loops. Therefore we need to set up a pseudoterminal and use that
// as stdin for the script interpreter interactive loops/prompts.
- lldb_utility::PseudoTerminal m_interpreter_pty;
- std::string m_pty_slave_name;
+ lldb_utility::PseudoTerminal m_interpreter_pty; // m_session_pty
+ std::string m_pty_slave_name; //m_session_pty_slave_name
+
+private:
+
};
} // namespace lldb_private
Modified: lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h?rev=123415&r1=123414&r2=123415&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h (original)
+++ lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h Thu Jan 13 18:29:16 2011
@@ -11,6 +11,12 @@
#ifndef liblldb_ScriptInterpreterPython_h_
#define liblldb_ScriptInterpreterPython_h_
+#if defined (__APPLE__)
+#include
+#else
+#include
+#endif
+
#include "lldb/lldb-private.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Core/InputReader.h"
@@ -70,9 +76,26 @@
StringList
ReadCommandInputFromUser (FILE *in_file);
+ virtual void
+ ResetOutputFileHandle (FILE *new_fh);
+
static lldb::thread_result_t
RunEmbeddedPythonInterpreter (lldb::thread_arg_t baton);
+ static void
+ Initialize ();
+
+ static void
+ Terminate ();
+
+protected:
+
+ void
+ EnterSession ();
+
+ void
+ LeaveSession ();
+
private:
static size_t
@@ -81,12 +104,19 @@
lldb::InputReaderAction notification,
const char *bytes,
size_t bytes_len);
-
- void *m_compiled_module;
- struct termios m_termios;
- bool m_termios_valid;
+
+
lldb_utility::PseudoTerminal m_embedded_python_pty;
lldb::InputReaderSP m_embedded_thread_input_reader_sp;
+ FILE *m_dbg_stdout;
+ PyObject *m_new_sysout;
+ std::string m_dictionary_name;
+ struct termios m_termios;
+ bool m_termios_valid;
+ bool m_session_is_active;
+ bool m_pty_slave_is_open;
+ bool m_valid_session;
+
};
} // namespace lldb_private
Modified: lldb/trunk/scripts/lldb.swig
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/lldb.swig?rev=123415&r1=123414&r2=123415&view=diff
==============================================================================
--- lldb/trunk/scripts/lldb.swig (original)
+++ lldb/trunk/scripts/lldb.swig Thu Jan 13 18:29:16 2011
@@ -1,8 +1,6 @@
/*
lldb.swig
- Created by Caroline Tice 1/18/2010
-
This is the input file for SWIG, to create the appropriate C++ wrappers and
functions for various scripting languages, to enable them to call the
liblldb Script Bridge functions.
@@ -151,6 +149,7 @@
LLDBSWIGPythonBreakpointCallbackFunction
(
const char *python_function_name,
+ const char *session_dictionary_name,
lldb::SBFrame& sb_frame,
lldb::SBBreakpointLocation& sb_bp_loc
)
@@ -161,20 +160,70 @@
if (Frame_PyObj == NULL || Bp_Loc_PyObj == NULL)
return stop_at_breakpoint;
+
+ if (!python_function_name || !session_dictionary_name)
+ return stop_at_breakpoint;
- PyObject *pmodule, *pdict, *pfunc;
+ PyObject *pmodule, *main_dict, *session_dict, *pfunc;
PyObject *pargs, *pvalue;
pmodule = PyImport_AddModule ("__main__");
if (pmodule != NULL)
{
- pdict = PyModule_GetDict (pmodule);
- if (pdict != NULL)
+ main_dict = PyModule_GetDict (pmodule);
+ if (main_dict != NULL)
{
- pfunc = PyObject_GetAttrString (pmodule, python_function_name);
+ PyObject *key, *value;
+ Py_ssize_t pos = 0;
+
+ // Find the current session's dictionary in the main module's dictionary.
+
+ if (PyDict_Check (main_dict))
+
+ {
+ session_dict = NULL;
+ while (PyDict_Next (main_dict, &pos, &key, &value))
+ {
+ // We have stolen references to the key and value objects in the dictionary; we need to increment
+ // them now so that Python's garbage collector doesn't collect them out from under us.
+ Py_INCREF (key);
+ Py_INCREF (value);
+ if (strcmp (PyString_AsString (key), session_dictionary_name) == 0)
+ {
+ session_dict = value;
+ break;
+ }
+ }
+ }
+
+ if (!session_dict || !PyDict_Check (session_dict))
+ return stop_at_breakpoint;
+
+ // Find the function we need to call in the current session's dictionary.
+
+ pos = 0;
+ pfunc = NULL;
+ while (PyDict_Next (session_dict, &pos, &key, &value))
+ {
+ if (PyString_Check (key))
+ {
+ // We have stolen references to the key and value objects in the dictionary; we need to increment
+ // them now so that Python's garbage collector doesn't collect them out from under us.
+ Py_INCREF (key);
+ Py_INCREF (value);
+ if (strcmp (PyString_AsString (key), python_function_name) == 0)
+ {
+ pfunc = value;
+ break;
+ }
+ }
+ }
+
+ // Set up the arguments and call the function.
+
if (pfunc && PyCallable_Check (pfunc))
{
- pargs = PyTuple_New (2);
+ pargs = PyTuple_New (3);
if (pargs == NULL)
{
if (PyErr_Occurred())
@@ -184,6 +233,7 @@
PyTuple_SetItem (pargs, 0, Frame_PyObj); // This "steals" a reference to Frame_PyObj
PyTuple_SetItem (pargs, 1, Bp_Loc_PyObj); // This "steals" a reference to Bp_Loc_PyObj
+ PyTuple_SetItem (pargs, 2, session_dict); // This "steals" a reference to session_dict
pvalue = PyObject_CallObject (pfunc, pargs);
Py_DECREF (pargs);
@@ -195,7 +245,7 @@
{
PyErr_Clear();
}
- Py_DECREF (pfunc);
+ Py_INCREF (session_dict);
}
else if (PyErr_Occurred())
{
Modified: lldb/trunk/source/Core/Debugger.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=123415&r1=123414&r2=123415&view=diff
==============================================================================
--- lldb/trunk/source/Core/Debugger.cpp (original)
+++ lldb/trunk/source/Core/Debugger.cpp Thu Jan 13 18:29:16 2011
@@ -59,6 +59,12 @@
return g_settings_controller;
}
+int
+Debugger::TestDebuggerRefCount ()
+{
+ return g_shared_debugger_refcount;
+}
+
void
Debugger::Initialize ()
{
@@ -252,6 +258,8 @@
m_output_file.SetFileHandle (fh, tranfer_ownership);
if (m_output_file.GetFileHandle() == NULL)
m_output_file.SetFileHandle (stdin, false);
+
+ GetCommandInterpreter().GetScriptInterpreter()->ResetOutputFileHandle (fh);
}
FILE *
Modified: lldb/trunk/source/Interpreter/CommandInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandInterpreter.cpp?rev=123415&r1=123414&r2=123415&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandInterpreter.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandInterpreter.cpp Thu Jan 13 18:29:16 2011
@@ -50,6 +50,8 @@
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/ScriptInterpreterNone.h"
+#include "lldb/Interpreter/ScriptInterpreterPython.h"
using namespace lldb;
using namespace lldb_private;
@@ -63,7 +65,8 @@
Broadcaster ("lldb.command-interpreter"),
m_debugger (debugger),
m_synchronous_execution (synchronous_execution),
- m_skip_lldbinit_files (false)
+ m_skip_lldbinit_files (false),
+ m_script_interpreter_ap ()
{
const char *dbg_name = debugger.GetInstanceName().AsCString();
std::string lang_name = ScriptInterpreter::LanguageToString (script_language);
@@ -1460,15 +1463,23 @@
ScriptInterpreter *
CommandInterpreter::GetScriptInterpreter ()
{
- CommandObject::CommandMap::iterator pos;
+ if (m_script_interpreter_ap.get() != NULL)
+ return m_script_interpreter_ap.get();
- pos = m_command_dict.find ("script");
- if (pos != m_command_dict.end())
+ lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage();
+ switch (script_lang)
{
- CommandObject *script_cmd_obj = pos->second.get();
- return ((CommandObjectScript *) script_cmd_obj)->GetInterpreter ();
- }
- return NULL;
+ case eScriptLanguageNone:
+ m_script_interpreter_ap.reset (new ScriptInterpreterNone (*this));
+ break;
+ case eScriptLanguagePython:
+ m_script_interpreter_ap.reset (new ScriptInterpreterPython (*this));
+ break;
+ default:
+ break;
+ };
+
+ return m_script_interpreter_ap.get();
}
Modified: lldb/trunk/source/Interpreter/CommandObjectScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObjectScript.cpp?rev=123415&r1=123414&r2=123415&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandObjectScript.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandObjectScript.cpp Thu Jan 13 18:29:16 2011
@@ -17,8 +17,7 @@
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
-#include "lldb/Interpreter/ScriptInterpreterPython.h"
-#include "lldb/Interpreter/ScriptInterpreterNone.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
using namespace lldb;
using namespace lldb_private;
@@ -32,8 +31,7 @@
"script",
"Pass an expression to the script interpreter for evaluation and return the results. Drop into the interactive interpreter if no expression is given.",
"script []"),
- m_script_lang (script_lang),
- m_interpreter_ap ()
+ m_script_lang (script_lang)
{
}
@@ -48,7 +46,7 @@
CommandReturnObject &result
)
{
- ScriptInterpreter *script_interpreter = GetInterpreter ();
+ ScriptInterpreter *script_interpreter = m_interpreter.GetScriptInterpreter ();
if (script_interpreter == NULL)
{
@@ -88,22 +86,3 @@
return false;
}
-
-ScriptInterpreter *
-CommandObjectScript::GetInterpreter ()
-{
- if (m_interpreter_ap.get() == NULL)
- {
- switch (m_script_lang)
- {
- case eScriptLanguagePython:
- m_interpreter_ap.reset (new ScriptInterpreterPython (m_interpreter));
- break;
-
- case eScriptLanguageNone:
- m_interpreter_ap.reset (new ScriptInterpreterNone (m_interpreter));
- break;
- }
- }
- return m_interpreter_ap.get();
-}
Modified: lldb/trunk/source/Interpreter/CommandObjectScript.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObjectScript.h?rev=123415&r1=123414&r2=123415&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandObjectScript.h (original)
+++ lldb/trunk/source/Interpreter/CommandObjectScript.h Thu Jan 13 18:29:16 2011
@@ -42,12 +42,8 @@
Execute (Args& command,
CommandReturnObject &result);
- ScriptInterpreter *
- GetInterpreter ();
-
private:
lldb::ScriptLanguage m_script_lang;
- std::auto_ptr m_interpreter_ap;
};
} // namespace lldb_private
Modified: lldb/trunk/source/Interpreter/ScriptInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreter.cpp?rev=123415&r1=123414&r2=123415&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/ScriptInterpreter.cpp (original)
+++ lldb/trunk/source/Interpreter/ScriptInterpreter.cpp Thu Jan 13 18:29:16 2011
@@ -17,15 +17,17 @@
#include "lldb/Core/Stream.h"
#include "lldb/Core/StringList.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/ScriptInterpreterPython.h"
#include "lldb/Utility/PseudoTerminal.h"
using namespace lldb;
using namespace lldb_private;
-ScriptInterpreter::ScriptInterpreter (CommandInterpreter &interpreter, ScriptLanguage script_lang) :
+ScriptInterpreter::ScriptInterpreter (CommandInterpreter &interpreter, lldb::ScriptLanguage script_lang) :
m_interpreter (interpreter),
m_script_lang (script_lang),
- m_interpreter_pty ()
+ m_interpreter_pty (),
+ m_pty_slave_name ()
{
if (m_interpreter_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, NULL, 0))
{
@@ -40,6 +42,12 @@
m_interpreter_pty.CloseMasterFileDescriptor();
}
+CommandInterpreter &
+ScriptInterpreter::GetCommandInterpreter ()
+{
+ return m_interpreter;
+}
+
const char *
ScriptInterpreter::GetScriptInterpreterPtyName ()
{
@@ -81,3 +89,16 @@
return return_value;
}
+
+void
+ScriptInterpreter::Initialize ()
+{
+ ScriptInterpreterPython::Initialize ();
+}
+
+void
+ScriptInterpreter::Terminate ()
+{
+ ScriptInterpreterPython::Terminate ();
+}
+
Modified: lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp?rev=123415&r1=123414&r2=123415&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp (original)
+++ lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp Thu Jan 13 18:29:16 2011
@@ -52,6 +52,7 @@
LLDBSWIGPythonBreakpointCallbackFunction
(
const char *python_function_name,
+ const char *session_dictionary_name,
lldb::SBFrame& sb_frame,
lldb::SBBreakpointLocation& sb_bp_loc
);
@@ -146,10 +147,22 @@
if not more:\n\
break\n\
\n\
+ def one_line (self, input):\n\
+ line = self.process_input (input)\n\
+ more = self.push(line)\n\
+ if more:\n\
+ self.write (\"Input not a complete line.\")\n\
+ self.resetbuffer()\n\
+ more = 0\n\
+\n\
def run_python_interpreter (dict):\n\
# Pass in the dictionary, for continuity from one session to the next.\n\
repl = SimpleREPL('>>> ', dict)\n\
- repl.interact()\n";
+ repl.interact()\n\
+\n\
+def run_one_line (dict, input_string):\n\
+ repl = SimpleREPL ('', dict)\n\
+ repl.one_line (input_string)\n";
static int
_check_and_flush (FILE *stream)
@@ -158,146 +171,171 @@
return fflush (stream) || prev_fail ? EOF : 0;
}
+static Mutex &
+GetPythonMutex ()
+{
+ static Mutex g_python_mutex (Mutex::eMutexTypeRecursive);
+ return g_python_mutex;
+}
+
ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interpreter) :
ScriptInterpreter (interpreter, eScriptLanguagePython),
- m_compiled_module (NULL),
+ m_embedded_python_pty (),
+ m_embedded_thread_input_reader_sp (),
+ m_dbg_stdout (interpreter.GetDebugger().GetOutputFileHandle()),
+ m_new_sysout (NULL),
+ m_dictionary_name (interpreter.GetDebugger().GetInstanceName().AsCString()),
m_termios (),
m_termios_valid (false),
- m_embedded_python_pty (),
- m_embedded_thread_input_reader_sp ()
+ m_session_is_active (false),
+ m_pty_slave_is_open (false),
+ m_valid_session (true)
{
+ Mutex::Locker locker (GetPythonMutex());
- Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+ m_dictionary_name.append("_dict");
+ StreamString run_string;
+ run_string.Printf ("%s = dict()", m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+
+ run_string.Clear();
+ run_string.Printf ("run_one_line (%s, 'import sys')", m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+
+ // Importing 'lldb' module calls SBDebugger::Initialize, which calls Debugger::Initialize, which increments a
+ // global debugger ref-count; therefore we need to check the ref-count before and after importing lldb, and if the
+ // ref-count increased we need to call Debugger::Terminate here to decrement the ref-count so that when the final
+ // call to Debugger::Terminate is made, the ref-count has the correct value.
+ //
+ // Bonus question: Why doesn't the ref-count always increase? Because sometimes lldb has already been imported, in
+ // which case the code inside it, including the call to SBDebugger::Initialize(), does not get executed.
+
+ int old_count = Debugger::TestDebuggerRefCount();
- // Save terminal settings if we can
- int input_fd;
- FILE *input_fh = m_interpreter.GetDebugger().GetInputFileHandle();
- if (input_fh != NULL)
- input_fd = ::fileno (input_fh);
- else
- input_fd = STDIN_FILENO;
+ run_string.Clear();
+ run_string.Printf ("run_one_line (%s, 'import lldb')", m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+
+ int new_count = Debugger::TestDebuggerRefCount();
- m_termios_valid = ::tcgetattr (input_fd, &m_termios) == 0;
-
- // Find the module that owns this code and use that path we get to
- // set the PYTHONPATH appropriately.
+ if (new_count > old_count)
+ Debugger::Terminate();
- FileSpec file_spec;
- char python_dir_path[PATH_MAX];
- if (Host::GetLLDBPath (ePathTypePythonDir, file_spec))
+ run_string.Clear();
+ run_string.Printf ("run_one_line (%s, 'import copy')", m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+
+ run_string.Clear();
+ run_string.Printf ("run_one_line (%s, 'lldb.debugger_unique_id = %d')", m_dictionary_name.c_str(),
+ interpreter.GetDebugger().GetID());
+ PyRun_SimpleString (run_string.GetData());
+
+ if (m_dbg_stdout != NULL)
{
- std::string python_path;
- const char *curr_python_path = ::getenv ("PYTHONPATH");
- if (curr_python_path)
- {
- // We have a current value for PYTHONPATH, so lets append to it
- python_path.append (curr_python_path);
- }
-
- if (file_spec.GetPath(python_dir_path, sizeof (python_dir_path)))
- {
- if (!python_path.empty())
- python_path.append (1, ':');
- python_path.append (python_dir_path);
- }
-
- if (Host::GetLLDBPath (ePathTypeLLDBShlibDir, file_spec))
- {
- if (file_spec.GetPath(python_dir_path, sizeof (python_dir_path)))
- {
- if (!python_path.empty())
- python_path.append (1, ':');
- python_path.append (python_dir_path);
- }
- }
- const char *pathon_path_env_cstr = python_path.c_str();
- ::setenv ("PYTHONPATH", pathon_path_env_cstr, 1);
+ m_new_sysout = PyFile_FromFile (m_dbg_stdout, (char *) "", (char *) "w", _check_and_flush);
}
+}
- Py_Initialize ();
-
- PyObject *compiled_module = Py_CompileString (embedded_interpreter_string,
- "embedded_interpreter.py",
- Py_file_input);
+ScriptInterpreterPython::~ScriptInterpreterPython ()
+{
+ Debugger &debugger = GetCommandInterpreter().GetDebugger();
- m_compiled_module = static_cast(compiled_module);
+ if (m_embedded_thread_input_reader_sp.get() != NULL)
+ {
+ m_embedded_thread_input_reader_sp->SetIsDone (true);
+ m_embedded_python_pty.CloseSlaveFileDescriptor();
+ m_pty_slave_is_open = false;
+ const InputReaderSP reader_sp = m_embedded_thread_input_reader_sp;
+ m_embedded_thread_input_reader_sp.reset();
+ debugger.PopInputReader (reader_sp);
+ }
+
+ if (m_new_sysout)
+ {
+ Mutex::Locker locker(GetPythonMutex());
+ Py_DECREF (m_new_sysout);
+ }
+}
- // This function is in the C++ output file generated by SWIG after it is
- // run on all of the headers in "lldb/API/SB*.h"
- init_lldb ();
+void
+ScriptInterpreterPython::ResetOutputFileHandle (FILE *fh)
+{
+ if (fh == NULL)
+ return;
+
+ m_dbg_stdout = fh;
+ Mutex::Locker locker (GetPythonMutex());
- // Update the path python uses to search for modules to include the current directory.
+ EnterSession ();
+ m_new_sysout = PyFile_FromFile (m_dbg_stdout, (char *) "", (char *) "w", _check_and_flush);
+ LeaveSession ();
+}
- int success = PyRun_SimpleString ("import sys");
- success = PyRun_SimpleString ("sys.path.append ('.')");
- if (success == 0)
- {
- // Import the Script Bridge module.
- success = PyRun_SimpleString ("import lldb");
- }
+void
+ScriptInterpreterPython::LeaveSession ()
+{
+ m_session_is_active = false;
+}
- const char *pty_slave_name = GetScriptInterpreterPtyName ();
- FILE *out_fh = interpreter.GetDebugger().GetOutputFileHandle();
+void
+ScriptInterpreterPython::EnterSession ()
+{
+ // If we have already entered the session, without having officially 'left' it, then there is no need to
+ // 'enter' it again.
- PyObject *pmod = PyImport_ExecCodeModule (const_cast ("embedded_interpreter"),
- static_cast(m_compiled_module));
+ if (m_session_is_active)
+ return;
- if (pmod != NULL)
- {
- PyRun_SimpleString ("ConsoleDict = locals()");
- PyRun_SimpleString ("from embedded_interpreter import run_python_interpreter");
- PyRun_SimpleString ("import sys");
- PyRun_SimpleString ("from termios import *");
-
- if (out_fh != NULL)
- {
- PyObject *new_sysout = PyFile_FromFile (out_fh, (char *) "", (char *) "w",
- _check_and_flush);
- PyObject *sysmod = PyImport_AddModule ("sys");
- PyObject *sysdict = PyModule_GetDict (sysmod);
-
- if ((new_sysout != NULL)
- && (sysmod != NULL)
- && (sysdict != NULL))
- {
- PyDict_SetItemString (sysdict, "stdout", new_sysout);
- }
+ m_session_is_active = true;
- if (PyErr_Occurred())
- PyErr_Clear();
- }
+ Mutex::Locker locker (GetPythonMutex());
- StreamString run_string;
- run_string.Printf ("new_stdin = open('%s', 'r')", pty_slave_name);
+ PyObject *sysmod = PyImport_AddModule ("sys");
+ PyObject *sysdict = PyModule_GetDict (sysmod);
+
+ if ((m_new_sysout != NULL)
+ && (sysmod != NULL)
+ && (sysdict != NULL))
+ PyDict_SetItemString (sysdict, "stdout", m_new_sysout);
+
+ if (PyErr_Occurred())
+ PyErr_Clear ();
+
+ StreamString run_string;
+ if (!m_pty_slave_is_open)
+ {
+ run_string.Printf ("run_one_line (%s, \"new_stdin = open('%s', 'r')\")", m_dictionary_name.c_str(),
+ m_pty_slave_name.c_str());
PyRun_SimpleString (run_string.GetData());
- PyRun_SimpleString ("sys.stdin = new_stdin");
-
+ m_pty_slave_is_open = true;
+
run_string.Clear();
- run_string.Printf ("lldb.debugger_unique_id = %d", interpreter.GetDebugger().GetID());
+ run_string.Printf ("run_one_line (%s, 'sys.stdin = new_stdin')", m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
}
+}
- // Restore terminal settings if they were validly saved
- if (m_termios_valid)
- {
- ::tcsetattr (input_fd, TCSANOW, &m_termios);
- }
-}
-
-ScriptInterpreterPython::~ScriptInterpreterPython ()
-{
- Py_Finalize ();
-}
-
bool
ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObject *result)
{
+ if (!m_valid_session)
+ return false;
+
+ EnterSession ();
+
+ Mutex::Locker locker (GetPythonMutex());
+
if (command)
{
int success;
- success = PyRun_SimpleString (command);
+ StreamString sstr;
+ sstr.Printf ("run_one_line (%s, '%s')", m_dictionary_name.c_str(), command);
+ success = PyRun_SimpleString (sstr.GetData());
+
+ LeaveSession ();
+
if (success == 0)
return true;
@@ -307,6 +345,7 @@
return false;
}
+ LeaveSession ();
if (result)
result->AppendError ("empty command passed to python\n");
return false;
@@ -329,12 +368,16 @@
if (baton == NULL)
return 0;
-
+
+ ScriptInterpreterPython *script_interpreter = (ScriptInterpreterPython *) baton;
+
+ if (script_interpreter->m_script_lang != eScriptLanguagePython)
+ return 0;
+
FILE *out_fh = reader.GetDebugger().GetOutputFileHandle ();
if (out_fh == NULL)
out_fh = stdout;
- ScriptInterpreterPython *script_interpreter = (ScriptInterpreterPython *) baton;
switch (notification)
{
case eInputReaderActivate:
@@ -384,14 +427,17 @@
log->Printf ("ScriptInterpreterPython::InputReaderCallback, Activate, failed to open master pty ");
reader.SetIsDone (true);
}
+ script_interpreter->EnterSession ();
}
break;
case eInputReaderDeactivate:
+ script_interpreter->LeaveSession ();
break;
case eInputReaderReactivate:
+ script_interpreter->EnterSession ();
break;
case eInputReaderInterrupt:
@@ -429,10 +475,8 @@
break;
case eInputReaderDone:
- // Send a control D to the script interpreter
- //::write (interpreter->GetMasterFileDescriptor(), "\nquit()\n", strlen("\nquit()\n"));
- // Write a newline out to the reader output
- //::fwrite ("\n", 1, 1, out_fh);
+ script_interpreter->LeaveSession ();
+
// Restore terminal settings if they were validly saved
if (log)
log->Printf ("ScriptInterpreterPython::InputReaderCallback, Done, closing down input reader.");
@@ -460,7 +504,7 @@
{
Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
- Debugger &debugger = m_interpreter.GetDebugger();
+ Debugger &debugger = GetCommandInterpreter().GetDebugger();
// At the moment, the only time the debugger does not have an input file handle is when this is called
// directly from Python, in which case it is both dangerous and unnecessary (not to mention confusing) to
@@ -493,14 +537,54 @@
ScriptInterpreter::ReturnType return_type,
void *ret_value)
{
+ EnterSession ();
+
+ Mutex::Locker locker (GetPythonMutex());
+
PyObject *py_return = NULL;
PyObject *mainmod = PyImport_AddModule ("__main__");
PyObject *globals = PyModule_GetDict (mainmod);
- PyObject *locals = globals;
+ PyObject *locals = NULL;
PyObject *py_error = NULL;
bool ret_success;
+ bool should_decrement_locals = false;
int success;
+
+ if (PyDict_Check (globals))
+ {
+ PyObject *key, *value;
+ Py_ssize_t pos = 0;
+
+ int i = 0;
+ while (PyDict_Next (globals, &pos, &key, &value))
+ {
+ // We have stolen references to the key and value objects in the dictionary; we need to increment them now
+ // so that Python's garbage collector doesn't collect them out from under us.
+ Py_INCREF (key);
+ Py_INCREF (value);
+ char *c_str = PyString_AsString (key);
+ if (strcmp (c_str, m_dictionary_name.c_str()) == 0)
+ locals = value;
+ ++i;
+ }
+ }
+ if (locals == NULL)
+ {
+ locals = PyObject_GetAttrString (globals, m_dictionary_name.c_str());
+ should_decrement_locals = true;
+ }
+
+ if (locals == NULL)
+ {
+ locals = globals;
+ should_decrement_locals = false;
+ }
+
+ py_error = PyErr_Occurred();
+ if (py_error != NULL)
+ PyErr_Clear();
+
if (in_string != NULL)
{
py_return = PyRun_String (in_string, Py_eval_input, globals, locals);
@@ -513,6 +597,10 @@
py_return = PyRun_String (in_string, Py_single_input, globals, locals);
}
+ if (locals != NULL
+ && should_decrement_locals)
+ Py_DECREF (locals);
+
if (py_return != NULL)
{
switch (return_type)
@@ -614,6 +702,8 @@
PyErr_Clear();
ret_success = false;
}
+
+ LeaveSession ();
return ret_success;
}
@@ -621,13 +711,50 @@
bool
ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string)
{
+ EnterSession ();
+
+ Mutex::Locker locker (GetPythonMutex());
+
bool success = false;
PyObject *py_return = NULL;
PyObject *mainmod = PyImport_AddModule ("__main__");
PyObject *globals = PyModule_GetDict (mainmod);
- PyObject *locals = globals;
+ PyObject *locals = NULL;
PyObject *py_error = NULL;
+ bool should_decrement_locals = false;
+ if (PyDict_Check (globals))
+ {
+ PyObject *key, *value;
+ Py_ssize_t pos = 0;
+
+ while (PyDict_Next (globals, &pos, &key, &value))
+ {
+ // We have stolen references to the key and value objects in the dictionary; we need to increment them now
+ // so that Python's garbage collector doesn't collect them out from under us.
+ Py_INCREF (key);
+ Py_INCREF (value);
+ if (strcmp (PyString_AsString (key), m_dictionary_name.c_str()) == 0)
+ locals = value;
+ }
+ }
+
+ if (locals == NULL)
+ {
+ locals = PyObject_GetAttrString (globals, m_dictionary_name.c_str());
+ should_decrement_locals = true;
+ }
+
+ if (locals == NULL)
+ {
+ locals = globals;
+ should_decrement_locals = false;
+ }
+
+ py_error = PyErr_Occurred();
+ if (py_error != NULL)
+ PyErr_Clear();
+
if (in_string != NULL)
{
struct _node *compiled_node = PyParser_SimpleParseString (in_string, Py_file_input);
@@ -642,6 +769,8 @@
success = true;
Py_DECREF (py_return);
}
+ if (locals && should_decrement_locals)
+ Py_DECREF (locals);
}
}
}
@@ -655,6 +784,8 @@
success = false;
}
+ LeaveSession ();
+
return success;
}
@@ -764,7 +895,8 @@
ScriptInterpreterPython::CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options,
CommandReturnObject &result)
{
- Debugger &debugger = m_interpreter.GetDebugger();
+ Debugger &debugger = GetCommandInterpreter().GetDebugger();
+
InputReaderSP reader_sp (new InputReader (debugger));
if (reader_sp)
@@ -861,8 +993,16 @@
// Create the function name & definition string.
- sstr.Printf ("def %s (frame, bp_loc):", auto_generated_function_name.c_str());
+ sstr.Printf ("def %s (frame, bp_loc, dict):", auto_generated_function_name.c_str());
auto_generated_function.AppendString (sstr.GetData());
+
+ // Pre-pend code for setting up the session dictionary.
+
+ auto_generated_function.AppendString (" global_dict = globals()"); // Grab the global dictionary
+ auto_generated_function.AppendString (" new_keys = dict.keys()"); // Make a list of keys in the session dict
+ auto_generated_function.AppendString (" old_keys = global_dict.keys()"); // Save list of keys in global dict
+ auto_generated_function.AppendString (" global_dict.update (dict)"); // Add the session dictionary to the
+ // global dictionary.
// Wrap everything up inside the function, increasing the indentation.
@@ -873,6 +1013,14 @@
auto_generated_function.AppendString (sstr.GetData());
}
+ // Append code to clean up the global dictionary and update the session dictionary (all updates in the function
+ // got written to the values in the global dictionary, not the session dictionary).
+
+ auto_generated_function.AppendString (" for key in new_keys:"); // Iterate over all the keys from session dict
+ auto_generated_function.AppendString (" dict[key] = global_dict[key]"); // Update session dict values
+ auto_generated_function.AppendString (" if key not in old_keys:"); // If key was not originally in global dict
+ auto_generated_function.AppendString (" del global_dict[key]"); // ...then remove key/value from global dict
+
// Verify that the results are valid Python.
if (!ExportFunctionDefinitionToInterpreter (auto_generated_function))
@@ -897,6 +1045,21 @@
{
BreakpointOptions::CommandData *bp_option_data = (BreakpointOptions::CommandData *) baton;
const char *python_function_name = bp_option_data->script_source.GetStringAtIndex (0);
+
+ if (!context)
+ return true;
+
+ Target *target = context->exe_ctx.target;
+
+ if (!target)
+ return true;
+
+ Debugger &debugger = target->GetDebugger();
+ ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
+ ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter;
+
+ if (!script_interpreter)
+ return true;
if (python_function_name != NULL
&& python_function_name[0] != '\0')
@@ -911,7 +1074,15 @@
SBBreakpointLocation sb_bp_loc (bp_loc_sp);
if (sb_bp_loc.IsValid() || sb_frame.IsValid())
- return LLDBSWIGPythonBreakpointCallbackFunction (python_function_name, sb_frame, sb_bp_loc);
+ {
+ python_interpreter->EnterSession ();
+ Mutex::Locker locker (GetPythonMutex());
+ bool ret_val = LLDBSWIGPythonBreakpointCallbackFunction(python_function_name,
+ python_interpreter->m_dictionary_name.c_str(),
+ sb_frame, sb_bp_loc);
+ python_interpreter->LeaveSession ();
+ return ret_val;
+ }
}
// We currently always true so we stop in case anything goes wrong when
// trying to call the script function
@@ -923,6 +1094,8 @@
{
ScriptInterpreterPython *script_interpreter = (ScriptInterpreterPython *) baton;
+ script_interpreter->EnterSession ();
+
LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
if (log)
@@ -932,39 +1105,172 @@
const char *pty_slave_name = script_interpreter->m_embedded_python_pty.GetSlaveName (error_str, sizeof (error_str));
if (pty_slave_name != NULL)
{
+ Mutex::Locker locker (GetPythonMutex());
+
StreamString run_string;
- PyRun_SimpleString ("save_stderr = sys.stderr");
- PyRun_SimpleString ("sys.stderr = sys.stdout");
- PyRun_SimpleString ("save_stdin = sys.stdin");
- run_string.Printf ("sys.stdin = open ('%s', 'r')", pty_slave_name);
+
+ run_string.Printf ("run_one_line (%s, 'save_stderr = sys.stderr')", script_interpreter->m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear ();
+
+ run_string.Printf ("run_one_line (%s, 'sys.stderr = sys.stdout')", script_interpreter->m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear ();
+
+ run_string.Printf ("run_one_line (%s, 'save_stdin = sys.stdin')", script_interpreter->m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
+ run_string.Clear ();
+ run_string.Printf ("run_one_line (%s, \"sys.stdin = open ('%s', 'r')\")", script_interpreter->m_dictionary_name.c_str(),
+ pty_slave_name);
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear ();
+
// The following call drops into the embedded interpreter loop and stays there until the
// user chooses to exit from the Python interpreter.
- script_interpreter->ExecuteOneLine ("run_python_interpreter(ConsoleDict)", NULL);
+
+ run_string.Printf ("run_python_interpreter (%s)", script_interpreter->m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear ();
+
+ run_string.Printf ("run_one_line (%s, 'sys.stdin = save_stdin')", script_interpreter->m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear();
- PyRun_SimpleString ("sys.stdin = save_stdin");
- PyRun_SimpleString ("sys.stderr = save_stderr");
+ run_string.Printf ("run_one_line (%s, 'sys.stderr = save_stderr')", script_interpreter->m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear();
}
if (script_interpreter->m_embedded_thread_input_reader_sp)
script_interpreter->m_embedded_thread_input_reader_sp->SetIsDone (true);
script_interpreter->m_embedded_python_pty.CloseSlaveFileDescriptor();
+
+ script_interpreter->m_pty_slave_is_open = false;
log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT);
if (log)
log->Printf ("%p ScriptInterpreterPython::RunEmbeddedPythonInterpreter () thread exiting...", baton);
- // Clean up the input reader and make the debugger pop it off the stack.
- Debugger &debugger = script_interpreter->m_interpreter.GetDebugger();
+ // Clean up the input reader and make the debugger pop it off the stack.
+ Debugger &debugger = script_interpreter->GetCommandInterpreter().GetDebugger();
const InputReaderSP reader_sp = script_interpreter->m_embedded_thread_input_reader_sp;
script_interpreter->m_embedded_thread_input_reader_sp.reset();
debugger.PopInputReader (reader_sp);
+
+ script_interpreter->LeaveSession ();
return NULL;
}
+void
+ScriptInterpreterPython::Initialize ()
+{
+
+ Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+
+ int input_fd = STDIN_FILENO;
+
+ struct termios stdin_termios;
+ bool valid_termios = ::tcgetattr (input_fd, &stdin_termios) == 0;
+
+ // Find the module that owns this code and use that path we get to
+ // set the PYTHONPATH appropriately.
+ FileSpec file_spec;
+ char python_dir_path[PATH_MAX];
+ if (Host::GetLLDBPath (ePathTypePythonDir, file_spec))
+ {
+ std::string python_path;
+ const char *curr_python_path = ::getenv ("PYTHONPATH");
+ if (curr_python_path)
+ {
+ // We have a current value for PYTHONPATH, so lets append to it
+ python_path.append (curr_python_path);
+ }
+
+ if (file_spec.GetPath(python_dir_path, sizeof (python_dir_path)))
+ {
+ if (!python_path.empty())
+ python_path.append (1, ':');
+ python_path.append (python_dir_path);
+ }
+
+ if (Host::GetLLDBPath (ePathTypeLLDBShlibDir, file_spec))
+ {
+ if (file_spec.GetPath(python_dir_path, sizeof (python_dir_path)))
+ {
+ if (!python_path.empty())
+ python_path.append (1, ':');
+ python_path.append (python_dir_path);
+ }
+ }
+ const char *pathon_path_env_cstr = python_path.c_str();
+ ::setenv ("PYTHONPATH", pathon_path_env_cstr, 1);
+ }
+
+ Py_Initialize ();
+
+ PyObject *compiled_module = Py_CompileString (embedded_interpreter_string,
+ "embedded_interpreter.py",
+ Py_file_input);
+
+ PyObject *py_error = PyErr_Occurred ();
+ if (py_error != NULL)
+ {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+
+ // This function is in the C++ output file generated by SWIG after it is
+ // run on all of the headers in "lldb/API/SB*.h"
+ init_lldb ();
+
+ // Update the path python uses to search for modules to include the current directory.
+
+ int success = PyRun_SimpleString ("import sys");
+ success = PyRun_SimpleString ("sys.path.append ('.')");
+
+ PyObject *pmod = NULL;
+
+ if (compiled_module)
+ {
+ pmod = PyImport_ExecCodeModule (const_cast ("embedded_interpreter"),
+ compiled_module);
+ Py_DECREF (compiled_module);
+ }
+
+ if (pmod != NULL)
+ {
+ PyRun_SimpleString ("from embedded_interpreter import run_python_interpreter");
+ PyRun_SimpleString ("from embedded_interpreter import run_one_line");
+ PyRun_SimpleString ("import sys");
+ PyRun_SimpleString ("from termios import *");
+ Py_DECREF (pmod);
+ }
+
+ if (valid_termios)
+ ::tcsetattr (input_fd, TCSANOW, &stdin_termios);
+}
+
+void
+ScriptInterpreterPython::Terminate ()
+{
+ // We are intentionally NOT calling Py_Finalize here (this would be the logical place to call it). Calling
+ // Py_Finalize here causes test suite runs to seg fault: The test suite runs in Python. It registers
+ // SBDebugger::Terminate to be called 'at_exit'. When the test suite Python harness finishes up, it calls
+ // Py_Finalize, which calls all the 'at_exit' registered functions. SBDebugger::Terminate calls Debugger::Terminate,
+ // which calls lldb::Terminate, which calls ScriptInterpreter::Terminate, which calls
+ // ScriptInterpreterPython::Terminate. So if we call Py_Finalize here, we end up with Py_Finalize being called from
+ // within Py_Finalize, which results in a seg fault.
+ //
+ // Since this function only gets called when lldb is shutting down and going away anyway, the fact that we don't
+ // actually call Py_Finalize should not cause any problems (everything should shut down/go away anyway when the
+ // process exits).
+ //
+// Py_Finalize ();
+}
Modified: lldb/trunk/source/Interpreter/embedded_interpreter.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/embedded_interpreter.py?rev=123415&r1=123414&r2=123415&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/embedded_interpreter.py (original)
+++ lldb/trunk/source/Interpreter/embedded_interpreter.py Thu Jan 13 18:29:16 2011
@@ -84,7 +84,20 @@
if not more:
break
+ def one_line (self, input):
+ line = self.process_input (input)
+ more = self.push(line)
+ if more:
+ self.write ("Input not a complete line.")
+ self.resetbuffer()
+ more = 0
+
def run_python_interpreter (dict):
# Pass in the dictionary, for continuity from one session to the next.
repl = SimpleREPL('>>> ', dict)
repl.interact()
+
+def run_one_line (dict, input_string):
+ repl = SimpleREPL ('', dict)
+ repl.one_line (input_string)
+
Modified: lldb/trunk/source/lldb.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/lldb.cpp?rev=123415&r1=123414&r2=123415&view=diff
==============================================================================
--- lldb/trunk/source/lldb.cpp (original)
+++ lldb/trunk/source/lldb.cpp Thu Jan 13 18:29:16 2011
@@ -14,6 +14,7 @@
#include "lldb/Core/Timer.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/Mutex.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
@@ -53,7 +54,7 @@
lldb_private::Initialize ()
{
// Make sure we inialize only once
- static Mutex g_inited_mutex(Mutex::eMutexTypeNormal);
+ static Mutex g_inited_mutex(Mutex::eMutexTypeRecursive);
static bool g_inited = false;
Mutex::Locker locker(g_inited_mutex);
@@ -75,6 +76,7 @@
UnwindAssemblyProfiler_x86::Initialize();
ArchDefaultUnwindPlan_x86::Initialize();
ArchVolatileRegs_x86::Initialize();
+ ScriptInterpreter::Initialize ();
#ifdef __APPLE__
ABIMacOSX_i386::Initialize();
@@ -114,6 +116,7 @@
UnwindAssemblyProfiler_x86::Terminate();
ArchDefaultUnwindPlan_x86::Terminate();
ArchVolatileRegs_x86::Terminate();
+ ScriptInterpreter::Terminate ();
#ifdef __APPLE__
DynamicLoaderMacOSXDYLD::Terminate();
From gclayton at apple.com Thu Jan 13 22:54:56 2011
From: gclayton at apple.com (Greg Clayton)
Date: Fri, 14 Jan 2011 04:54:56 -0000
Subject: [Lldb-commits] [lldb] r123428 - in /lldb/trunk:
include/lldb/Core/Error.h include/lldb/Symbol/ClangASTContext.h
scripts/lldb.swig source/Core/Error.cpp
source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
source/Symbol/ClangASTContext.cpp test/foundation/main.m
Message-ID: <20110114045456.B85B12A6C12C@llvm.org>
Author: gclayton
Date: Thu Jan 13 22:54:56 2011
New Revision: 123428
URL: http://llvm.org/viewvc/llvm-project?rev=123428&view=rev
Log:
Fixed an error in the type map for "char **" that was a bad memory smasher.
Anytime we had a valid python list that was trying to go from Python down into
our C++ API, it was allocating too little memory and it ended up smashing
whatever was next to the allocated memory.
Added typemap conversions for "void *, size_t" so we can get
SBProcess::ReadMemory() working. Also added a typemap for "const void *, size_t"
so we can get SBProcess::WriteMemory() to work.
Fixed an issue in the DWARF parser where we weren't correctly calculating the
DeclContext for all types and classes. We now should be a lot more accurate.
Fixes include: enums should now be setting their parent decl context correctly.
We saw a lot of examples where enums in classes were not being properly
namespace scoped. Also, classes within classes now get properly scoped.
Fixed the objective C runtime pointer checkers to let "nil" pointers through
since these are accepted by compiled code. We also now don't call "abort()"
when a pointer doesn't validate correctly since this was wreaking havoc on
the process due to the way abort() works. We now just dereference memory
which should give us an exception from which we can easily and reliably
recover.
Modified:
lldb/trunk/include/lldb/Core/Error.h
lldb/trunk/include/lldb/Symbol/ClangASTContext.h
lldb/trunk/scripts/lldb.swig
lldb/trunk/source/Core/Error.cpp
lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
lldb/trunk/source/Symbol/ClangASTContext.cpp
lldb/trunk/test/foundation/main.m
Modified: lldb/trunk/include/lldb/Core/Error.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Error.h?rev=123428&r1=123427&r2=123428&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Error.h (original)
+++ lldb/trunk/include/lldb/Core/Error.h Thu Jan 13 22:54:56 2011
@@ -64,9 +64,12 @@
/// @param[in] type
/// The type for \a err.
//------------------------------------------------------------------
+ Error ();
+
explicit
- Error (ValueType err = 0, lldb::ErrorType type = lldb::eErrorTypeGeneric);
+ Error (ValueType err, lldb::ErrorType type = lldb::eErrorTypeGeneric);
+ Error (const Error &rhs);
//------------------------------------------------------------------
/// Assignment operator.
///
Modified: lldb/trunk/include/lldb/Symbol/ClangASTContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTContext.h?rev=123428&r1=123427&r2=123428&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ClangASTContext.h (original)
+++ lldb/trunk/include/lldb/Symbol/ClangASTContext.h Thu Jan 13 22:54:56 2011
@@ -506,7 +506,10 @@
// Enumeration Types
//------------------------------------------------------------------
lldb::clang_type_t
- CreateEnumerationType (const Declaration &decl, const char *name, lldb::clang_type_t integer_qual_type);
+ CreateEnumerationType (const char *name,
+ clang::DeclContext *decl_ctx,
+ const Declaration &decl,
+ lldb::clang_type_t integer_qual_type);
static lldb::clang_type_t
GetEnumerationIntegerType (lldb::clang_type_t enum_clang_type);
Modified: lldb/trunk/scripts/lldb.swig
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/lldb.swig?rev=123428&r1=123427&r2=123428&view=diff
==============================================================================
--- lldb/trunk/scripts/lldb.swig (original)
+++ lldb/trunk/scripts/lldb.swig Thu Jan 13 22:54:56 2011
@@ -18,11 +18,11 @@
if (PyList_Check($input)) {
int size = PyList_Size($input);
int i = 0;
- $1 = (char **) malloc((size+1) * sizeof(char));
+ $1 = (char **) malloc((size+1) * sizeof(char*));
for (i = 0; i < size; i++) {
PyObject *o = PyList_GetItem($input,i);
if (PyString_Check(o))
- $1[i] = PyString_AsString(PyList_GetItem($input,i));
+ $1[i] = PyString_AsString(o);
else {
PyErr_SetString(PyExc_TypeError,"list must contain strings");
free($1);
@@ -54,6 +54,43 @@
}
+
+// typemap for an outgoing buffer
+%typemap(in) (const void *wbuffer, size_t len) {
+ if (!PyString_Check($input)) {
+ PyErr_SetString(PyExc_ValueError, "Expecting a string");
+ return NULL;
+ }
+ $1 = (void *) PyString_AsString($input);
+ $2 = PyString_Size($input);
+}
+
+// typemap for an incoming buffer
+%typemap(in) (void *rbuffer, size_t len) {
+ if (!PyInt_Check($input)) {
+ PyErr_SetString(PyExc_ValueError, "Expecting an integer");
+ return NULL;
+ }
+ $2 = PyInt_AsLong($input);
+ if ($2 < 0) {
+ PyErr_SetString(PyExc_ValueError, "Positive integer expected");
+ return NULL;
+ }
+ $1 = (void *) malloc($2);
+}
+
+// Return the buffer. Discarding any previous return result
+%typemap(argout) (void *rbuffer, size_t len) {
+ Py_XDECREF($result); /* Blow away any previous result */
+ if (result < 0) { /* Check for I/O error */
+ free($1);
+ PyErr_SetFromErrno(PyExc_IOError);
+ return NULL;
+ }
+ $result = PyString_FromStringAndSize($1,result);
+ free($1);
+}
+
/* The liblldb header files to be included. */
%{
Modified: lldb/trunk/source/Core/Error.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Error.cpp?rev=123428&r1=123427&r2=123428&view=diff
==============================================================================
--- lldb/trunk/source/Core/Error.cpp (original)
+++ lldb/trunk/source/Core/Error.cpp Thu Jan 13 22:54:56 2011
@@ -27,6 +27,13 @@
using namespace lldb;
using namespace lldb_private;
+Error::Error ():
+ m_code (0),
+ m_type (eErrorTypeInvalid),
+ m_string ()
+{
+}
+
//----------------------------------------------------------------------
// Default constructor
//----------------------------------------------------------------------
@@ -36,6 +43,14 @@
m_string ()
{
}
+
+Error::Error (const Error &rhs) :
+ m_code (rhs.m_code),
+ m_type (rhs.m_type),
+ m_string (rhs.m_string)
+{
+}
+
//----------------------------------------------------------------------
// Assignment operator
//----------------------------------------------------------------------
Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp?rev=123428&r1=123427&r2=123428&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp Thu Jan 13 22:54:56 2011
@@ -124,40 +124,45 @@
}
}
-struct BufStruct {
- char contents[1024];
-};
-
ClangUtilityFunction *
AppleObjCRuntimeV2::CreateObjectChecker(const char *name)
{
- std::auto_ptr buf(new BufStruct);
+ char check_function_code[1024];
+ int len = 0;
if (m_has_object_getClass)
{
- assert(snprintf(&buf->contents[0], sizeof(buf->contents),
- "extern \"C\" void *gdb_object_getClass(void *); \n"
- "extern \"C\" void \n"
- "%s(void *$__lldb_arg_obj) \n"
- "{ \n"
- " if (!gdb_object_getClass($__lldb_arg_obj)) \n"
- " abort(); \n"
- "} \n",
- name) < sizeof(buf->contents));
+ len = ::snprintf (check_function_code,
+ sizeof(check_function_code),
+ "extern \"C\" void *gdb_object_getClass(void *); \n"
+ "extern \"C\" void \n"
+ "%s(void *$__lldb_arg_obj) \n"
+ "{ \n"
+ " if ($__lldb_arg_obj == (void *)0) \n"
+ " return; // nil is ok \n"
+ " if (!gdb_object_getClass($__lldb_arg_obj)) \n"
+ " *((volatile int *)0) = 'ocgc'; \n"
+ "} \n",
+ name);
}
else
{
- assert(snprintf(&buf->contents[0], sizeof(buf->contents),
- "extern \"C\" void *gdb_class_getClass(void *); \n"
- "extern \"C\" void \n"
- "%s(void *$__lldb_arg_obj) \n"
- "{ \n"
- " void **$isa_ptr = (void **)$__lldb_arg_obj; \n"
- " if (!$isa_ptr || !gdb_class_getClass(*$isa_ptr)) \n"
- " abort(); \n"
- "} \n",
- name) < sizeof(buf->contents));
+ len = ::snprintf (check_function_code,
+ sizeof(check_function_code),
+ "extern \"C\" void *gdb_class_getClass(void *); \n"
+ "extern \"C\" void \n"
+ "%s(void *$__lldb_arg_obj) \n"
+ "{ \n"
+ " if ($__lldb_arg_obj == (void *)0) \n"
+ " return; // nil is ok \n"
+ " void **$isa_ptr = (void **)$__lldb_arg_obj; \n"
+ " if (!gdb_class_getClass(*$isa_ptr)) \n"
+ " *((volatile int *)0) = 'ocgc'; \n"
+ "} \n",
+ name);
}
- return new ClangUtilityFunction(buf->contents, name);
+ assert (len < sizeof(check_function_code));
+
+ return new ClangUtilityFunction(check_function_code, name);
}
Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=123428&r1=123427&r2=123428&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Thu Jan 13 22:54:56 2011
@@ -1300,7 +1300,21 @@
DWARFCompileUnitSP cu_sp;
const DWARFDebugInfoEntry* type_die = debug_info->GetDIEPtr(type_uid, &cu_sp);
if (type_die != NULL)
+ {
+ // We might be coming in in the middle of a type tree (a class
+ // withing a class, an enum within a class), so parse any needed
+ // parent DIEs before we get to this one...
+ const DWARFDebugInfoEntry* parent_die = type_die->GetParent();
+ switch (parent_die->Tag())
+ {
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_class_type:
+ ResolveType(cu_sp.get(), parent_die);
+ break;
+ }
return ResolveType (cu_sp.get(), type_die);
+ }
}
return NULL;
}
@@ -2651,7 +2665,9 @@
Type *type_ptr = m_die_to_type.lookup (die);
if (type_ptr == NULL)
{
- SymbolContext sc(GetCompUnitForDWARFCompUnit(curr_cu));
+ CompileUnit* lldb_cu = GetCompUnitForDWARFCompUnit(curr_cu);
+ assert (lldb_cu);
+ SymbolContext sc(lldb_cu);
type_sp = ParseType(sc, curr_cu, die, NULL);
}
else if (type_ptr != DIE_IS_BEING_PARSED)
@@ -2698,45 +2714,89 @@
clang::DeclContext *
SymbolFileDWARF::GetClangDeclContextForDIE (DWARFCompileUnit *curr_cu, const DWARFDebugInfoEntry *die)
{
- DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find(die);
- if (pos != m_die_to_decl_ctx.end())
- return pos->second;
+ if (m_clang_tu_decl == NULL)
+ m_clang_tu_decl = GetClangASTContext().getASTContext()->getTranslationUnitDecl();
+ //printf ("SymbolFileDWARF::GetClangDeclContextForDIE ( die = 0x%8.8x )\n", die->GetOffset());
+ const DWARFDebugInfoEntry * const decl_die = die;
while (die != NULL)
{
- switch (die->Tag())
+ // If this is the original DIE that we are searching for a declaration
+ // for, then don't look in the cache as we don't want our own decl
+ // context to be our decl context...
+ if (decl_die != die)
{
- case DW_TAG_namespace:
+ DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find(die);
+ if (pos != m_die_to_decl_ctx.end())
{
- const char *namespace_name = die->GetAttributeValueAsString(this, curr_cu, DW_AT_name, NULL);
- if (namespace_name)
+ //printf ("SymbolFileDWARF::GetClangDeclContextForDIE ( die = 0x%8.8x ) => 0x%8.8x\n", decl_die->GetOffset(), die->GetOffset());
+ return pos->second;
+ }
+
+ //printf ("SymbolFileDWARF::GetClangDeclContextForDIE ( die = 0x%8.8x ) checking parent 0x%8.8x\n", decl_die->GetOffset(), die->GetOffset());
+
+ switch (die->Tag())
+ {
+ case DW_TAG_namespace:
{
- Declaration decl; // TODO: fill in the decl object
- clang::NamespaceDecl *namespace_decl = GetClangASTContext().GetUniqueNamespaceDeclaration (namespace_name, decl, GetClangDeclContextForDIE (curr_cu, die->GetParent()));
- if (namespace_decl)
- m_die_to_decl_ctx[die] = (clang::DeclContext*)namespace_decl;
- return namespace_decl;
+ const char *namespace_name = die->GetAttributeValueAsString(this, curr_cu, DW_AT_name, NULL);
+ if (namespace_name)
+ {
+ Declaration decl; // TODO: fill in the decl object
+ clang::NamespaceDecl *namespace_decl = GetClangASTContext().GetUniqueNamespaceDeclaration (namespace_name, decl, GetClangDeclContextForDIE (curr_cu, die->GetParent()));
+ if (namespace_decl)
+ {
+ //printf ("SymbolFileDWARF::GetClangDeclContextForDIE ( die = 0x%8.8x ) => 0x%8.8x\n", decl_die->GetOffset(), die->GetOffset());
+ m_die_to_decl_ctx[die] = (clang::DeclContext*)namespace_decl;
+ }
+ return namespace_decl;
+ }
}
- }
- break;
+ break;
- default:
- break;
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_class_type:
+ {
+ ResolveType (curr_cu, die);
+ pos = m_die_to_decl_ctx.find(die);
+ assert (pos != m_die_to_decl_ctx.end());
+ if (pos != m_die_to_decl_ctx.end())
+ {
+ //printf ("SymbolFileDWARF::GetClangDeclContextForDIE ( die = 0x%8.8x ) => 0x%8.8x\n", decl_die->GetOffset(), die->GetOffset());
+ return pos->second;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
}
+
clang::DeclContext *decl_ctx;
- decl_ctx = GetClangDeclContextForDIEOffset (die->GetAttributeValueAsUnsigned(this, curr_cu, DW_AT_specification, DW_INVALID_OFFSET));
- if (decl_ctx)
- return decl_ctx;
-
- decl_ctx = GetClangDeclContextForDIEOffset (die->GetAttributeValueAsUnsigned(this, curr_cu, DW_AT_abstract_origin, DW_INVALID_OFFSET));
- if (decl_ctx)
- return decl_ctx;
+ dw_offset_t die_offset = die->GetAttributeValueAsUnsigned(this, curr_cu, DW_AT_specification, DW_INVALID_OFFSET);
+ if (die_offset != DW_INVALID_OFFSET)
+ {
+ //printf ("SymbolFileDWARF::GetClangDeclContextForDIE ( die = 0x%8.8x ) check DW_AT_specification 0x%8.8x\n", decl_die->GetOffset(), die_offset);
+ decl_ctx = GetClangDeclContextForDIEOffset (die_offset);
+ if (decl_ctx != m_clang_tu_decl)
+ return decl_ctx;
+ }
+
+ die_offset = die->GetAttributeValueAsUnsigned(this, curr_cu, DW_AT_abstract_origin, DW_INVALID_OFFSET);
+ if (die_offset != DW_INVALID_OFFSET)
+ {
+ //printf ("SymbolFileDWARF::GetClangDeclContextForDIE ( die = 0x%8.8x ) check DW_AT_abstract_origin 0x%8.8x\n", decl_die->GetOffset(), die_offset);
+ decl_ctx = GetClangDeclContextForDIEOffset (die_offset);
+ if (decl_ctx != m_clang_tu_decl)
+ return decl_ctx;
+ }
die = die->GetParent();
}
// Right now we have only one translation unit per module...
- if (m_clang_tu_decl == NULL)
- m_clang_tu_decl = GetClangASTContext().getASTContext()->getTranslationUnitDecl();
+ //printf ("SymbolFileDWARF::GetClangDeclContextForDIE ( die = 0x%8.8x ) => 0x%8.8x\n", decl_die->GetOffset(), curr_cu->GetFirstDIEOffset());
return m_clang_tu_decl;
}
@@ -3051,7 +3111,7 @@
}
- if (is_forward_declaration)
+ if (is_forward_declaration && die->HasChildren() == false)
{
// We have a forward declaration to a type and we need
// to try and find a full declaration. We look in the
@@ -3183,8 +3243,9 @@
enumerator_clang_type = ast.GetBuiltinTypeForDWARFEncodingAndBitSize (NULL,
DW_ATE_signed,
byte_size * 8);
- clang_type = ast.CreateEnumerationType (decl,
- type_name_cstr,
+ clang_type = ast.CreateEnumerationType (type_name_cstr,
+ GetClangDeclContextForDIE (dwarf_cu, die->GetParent()),
+ decl,
enumerator_clang_type);
}
else
Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=123428&r1=123427&r2=123428&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTContext.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTContext.cpp Thu Jan 13 22:54:56 2011
@@ -3487,7 +3487,13 @@
#pragma mark Enumeration Types
clang_type_t
-ClangASTContext::CreateEnumerationType (const Declaration &decl, const char *name, clang_type_t integer_qual_type)
+ClangASTContext::CreateEnumerationType
+(
+ const char *name,
+ DeclContext *decl_ctx,
+ const Declaration &decl,
+ clang_type_t integer_qual_type
+)
{
// TODO: Do something intelligent with the Declaration object passed in
// like maybe filling in the SourceLocation with it...
@@ -3499,7 +3505,7 @@
// const bool IsFixed = false;
EnumDecl *enum_decl = EnumDecl::Create (*ast_context,
- ast_context->getTranslationUnitDecl(),
+ decl_ctx,
SourceLocation(),
name && name[0] ? &ast_context->Idents.get(name) : NULL,
SourceLocation(),
Modified: lldb/trunk/test/foundation/main.m
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/foundation/main.m?rev=123428&r1=123427&r2=123428&view=diff
==============================================================================
--- lldb/trunk/test/foundation/main.m (original)
+++ lldb/trunk/test/foundation/main.m Thu Jan 13 22:54:56 2011
@@ -98,6 +98,7 @@
int
Test_NSArray ()
{
+ NSMutableArray *nil_mutable_array = nil;
NSArray *array1 = [NSArray arrayWithObjects: @"array1 object1", @"array1 object2", @"array1 object3", nil];
NSArray *array2 = [NSArray arrayWithObjects: array1, @"array2 object2", @"array2 object3", nil];
// Expressions to test here for NSArray:
@@ -105,6 +106,7 @@
// expression array1.count
// expression [array2 count]
// expression array2.count
+ // expression [nil_mutable_array count]
id obj;
// After each object at index call, use expression and validate object
obj = [array1 objectAtIndex: 0];
@@ -114,7 +116,7 @@
obj = [array2 objectAtIndex: 0];
obj = [array2 objectAtIndex: 1];
obj = [array2 objectAtIndex: 2];
-
+ NSUInteger count = [nil_mutable_array count];
return 0;
}
From johnny.chen at apple.com Fri Jan 14 12:19:53 2011
From: johnny.chen at apple.com (Johnny Chen)
Date: Fri, 14 Jan 2011 18:19:53 -0000
Subject: [Lldb-commits] [lldb] r123451 - /lldb/trunk/test/make/Makefile.rules
Message-ID: <20110114181953.37B7B2A6C12C@llvm.org>
Author: johnny
Date: Fri Jan 14 12:19:53 2011
New Revision: 123451
URL: http://llvm.org/viewvc/llvm-project?rev=123451&view=rev
Log:
The cxx_compiler function should not blindly return clang++ as the C++ compiler if $(CC) contains "clang".
Instead, it should perform a textual replacement of $(CC) from "clang" to "clang++". The same is true
for "llvm-gcc" to "llvm-g++" and for "gcc" to "g++". This way, we keep the path component of the $(CC)
passed in from the user and do not end up with a mixed toolchains with different paths.
Ditto for a newly added function called cxx_linker.
Modified:
lldb/trunk/test/make/Makefile.rules
Modified: lldb/trunk/test/make/Makefile.rules
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/make/Makefile.rules?rev=123451&r1=123450&r2=123451&view=diff
==============================================================================
--- lldb/trunk/test/make/Makefile.rules (original)
+++ lldb/trunk/test/make/Makefile.rules Fri Jan 14 12:19:53 2011
@@ -31,8 +31,11 @@
EXE = a.out
DSYM = $(EXE).dSYM
-# Function that returns the counterpart C++ compiler.
-cxx_compiler = $(if $(findstring clang,$(1)), clang++, $(if $(findstring llvm-gcc,$(1)), llvm-g++, g++))
+# Function that returns the counterpart C++ compiler, given $(CC) as arg.
+cxx_compiler = $(if $(findstring clang,$(1)), $(subst clang,clang++,$(1)), $(if $(findstring llvm-gcc,$(1)), $(subst llvm-gcc,llvm-g++,$(1)), $(subst gcc,g++,$(1))))
+
+# Function that returns the C++ linker, given $(CC) as arg.
+cxx_linker = $(if $(findstring clang,$(1)), $(subst clang,g++,$(1)), $(if $(findstring llvm-gcc,$(1)), $(subst llvm-gcc,g++,$(1)), $(subst gcc,g++,$(1))))
#----------------------------------------------------------------------
# dylib settings
@@ -55,7 +58,7 @@
ifneq "$(strip $(CXX_SOURCES))" ""
OBJECTS +=$(strip $(CXX_SOURCES:.cpp=.o))
CXX = $(call cxx_compiler,$(CC))
- LD = g++
+ LD = $(call cxx_linker,$(CC))
endif
#----------------------------------------------------------------------
@@ -72,7 +75,7 @@
ifneq "$(strip $(OBJCXX_SOURCES))" ""
OBJECTS +=$(strip $(OBJCXX_SOURCES:.mm=.o))
CXX = $(call cxx_compiler,$(CC))
- LD = g++
+ LD = $(call cxx_linker,$(CC))
ifeq $(findstring lobjc,$(LDFLAGS)) ""
LDFLAGS +=-lobjc
endif
From johnny.chen at apple.com Fri Jan 14 13:19:30 2011
From: johnny.chen at apple.com (Johnny Chen)
Date: Fri, 14 Jan 2011 19:19:30 -0000
Subject: [Lldb-commits] [lldb] r123454 - in /lldb/trunk/test/foundation:
TestObjCMethods2.py main.m
Message-ID: <20110114191930.BB3C92A6C12C@llvm.org>
Author: johnny
Date: Fri Jan 14 13:19:30 2011
New Revision: 123454
URL: http://llvm.org/viewvc/llvm-project?rev=123454&view=rev
Log:
Add an expression command:
expression (int)[nil_mutable_array count]
within NSArray_expr() function and expect a return of 0.
Modified:
lldb/trunk/test/foundation/TestObjCMethods2.py
lldb/trunk/test/foundation/main.m
Modified: lldb/trunk/test/foundation/TestObjCMethods2.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/foundation/TestObjCMethods2.py?rev=123454&r1=123453&r2=123454&view=diff
==============================================================================
--- lldb/trunk/test/foundation/TestObjCMethods2.py (original)
+++ lldb/trunk/test/foundation/TestObjCMethods2.py Fri Jan 14 13:19:30 2011
@@ -106,6 +106,8 @@
# Test_NSArray:
self.runCmd("thread backtrace")
+ self.expect("expression (int)[nil_mutable_array count]",
+ patterns = ["\(int\) \$.* = 0"])
self.expect("expression (int)[array1 count]",
patterns = ["\(int\) \$.* = 3"])
self.expect("expression (int)[array2 count]",
Modified: lldb/trunk/test/foundation/main.m
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/foundation/main.m?rev=123454&r1=123453&r2=123454&view=diff
==============================================================================
--- lldb/trunk/test/foundation/main.m (original)
+++ lldb/trunk/test/foundation/main.m Fri Jan 14 13:19:30 2011
@@ -102,11 +102,11 @@
NSArray *array1 = [NSArray arrayWithObjects: @"array1 object1", @"array1 object2", @"array1 object3", nil];
NSArray *array2 = [NSArray arrayWithObjects: array1, @"array2 object2", @"array2 object3", nil];
// Expressions to test here for NSArray:
+ // expression [nil_mutable_array count]
// expression [array1 count]
// expression array1.count
// expression [array2 count]
// expression array2.count
- // expression [nil_mutable_array count]
id obj;
// After each object at index call, use expression and validate object
obj = [array1 objectAtIndex: 0];
From gclayton at apple.com Fri Jan 14 13:21:25 2011
From: gclayton at apple.com (Greg Clayton)
Date: Fri, 14 Jan 2011 19:21:25 -0000
Subject: [Lldb-commits] [lldb] r123455 -
/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
Message-ID: <20110114192125.9DB252A6C12C@llvm.org>
Author: gclayton
Date: Fri Jan 14 13:21:25 2011
New Revision: 123455
URL: http://llvm.org/viewvc/llvm-project?rev=123455&view=rev
Log:
Removed printf statements in code.
Modified:
lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp?rev=123455&r1=123454&r2=123455&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp Fri Jan 14 13:21:25 2011
@@ -788,12 +788,12 @@
if (sc.symbol != NULL)
impl_code_address = sc.symbol->GetValue();
- lldb::addr_t addr = impl_code_address.GetLoadAddress (exe_ctx.target);
- printf ("Getting address for our_utility_function: 0x%llx.\n", addr);
+ //lldb::addr_t addr = impl_code_address.GetLoadAddress (exe_ctx.target);
+ //printf ("Getting address for our_utility_function: 0x%llx.\n", addr);
}
else
{
- printf ("Could not find implementation function address.\n");
+ //printf ("Could not find implementation function address.\n");
return ret_plan_sp;
}
}
From johnny.chen at apple.com Fri Jan 14 14:46:49 2011
From: johnny.chen at apple.com (Johnny Chen)
Date: Fri, 14 Jan 2011 20:46:49 -0000
Subject: [Lldb-commits] [lldb] r123461 - /lldb/trunk/test/make/Makefile.rules
Message-ID: <20110114204649.ACA762A6C12C@llvm.org>
Author: johnny
Date: Fri Jan 14 14:46:49 2011
New Revision: 123461
URL: http://llvm.org/viewvc/llvm-project?rev=123461&view=rev
Log:
Make CC defaults to gcc. The cxx_compiler and cxx_linker functions rely on substituting "g++"
for "gcc".
Modified:
lldb/trunk/test/make/Makefile.rules
Modified: lldb/trunk/test/make/Makefile.rules
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/make/Makefile.rules?rev=123461&r1=123460&r2=123461&view=diff
==============================================================================
--- lldb/trunk/test/make/Makefile.rules (original)
+++ lldb/trunk/test/make/Makefile.rules Fri Jan 14 14:46:49 2011
@@ -18,11 +18,18 @@
endif
#----------------------------------------------------------------------
+# CC defaults to gcc.
+#----------------------------------------------------------------------
+CC ?= gcc
+ifeq "$(CC)" "cc"
+ CC = gcc
+endif
+
+#----------------------------------------------------------------------
# Change any build/tool options needed
#----------------------------------------------------------------------
DS := /usr/bin/dsymutil
DSFLAGS =
-CC ?= gcc
CFLAGS ?=-arch $(ARCH) -gdwarf-2 -O0
CXXFLAGS +=$(CFLAGS)
LD = $(CC)
From wilsons at start.ca Fri Jan 14 14:56:31 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Fri, 14 Jan 2011 15:56:31 -0500
Subject: [Lldb-commits] [PATCH 0/3] trivial lldb fixes
Message-ID: <1295038594-9585-1-git-send-email-wilsons@start.ca>
This patch series contains two trivial fixes. Also, an extension to the
ObjectFile interface is provided as discussed here:
http://lists.cs.uiuc.edu/pipermail/lldb-dev/2011-January/000325.html
The fixes pave the way for a second patch series I will be sending shortly
containing various fixes/improvements to the ObjectFileELF and ProcessLinux
plugins.
From wilsons at start.ca Fri Jan 14 14:56:32 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Fri, 14 Jan 2011 15:56:32 -0500
Subject: [Lldb-commits] [PATCH 1/3] Do not prefix log messages with
ProcessMacOSX from the context of Process.
In-Reply-To: <1295038594-9585-1-git-send-email-wilsons@start.ca>
References: <1295038594-9585-1-git-send-email-wilsons@start.ca>
Message-ID: <1295038594-9585-2-git-send-email-wilsons@start.ca>
---
source/Target/Process.cpp | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp
index 2a83829..fdfa3a6 100644
--- a/source/Target/Process.cpp
+++ b/source/Target/Process.cpp
@@ -1099,7 +1099,7 @@ Process::DisableSoftwareBreakpoint (BreakpointSite *bp_site)
addr_t bp_addr = bp_site->GetLoadAddress();
lldb::user_id_t breakID = bp_site->GetID();
if (log)
- log->Printf ("ProcessMacOSX::DisableBreakpoint (breakID = %d) addr = 0x%llx", breakID, (uint64_t)bp_addr);
+ log->Printf ("Process::DisableBreakpoint (breakID = %d) addr = 0x%llx", breakID, (uint64_t)bp_addr);
if (bp_site->IsHardware())
{
--
1.7.3.5
From wilsons at start.ca Fri Jan 14 14:56:33 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Fri, 14 Jan 2011 15:56:33 -0500
Subject: [Lldb-commits] [PATCH 2/3] Do not prematurely invalidate thread
handle.
In-Reply-To: <1295038594-9585-1-git-send-email-wilsons@start.ca>
References: <1295038594-9585-1-git-send-email-wilsons@start.ca>
Message-ID: <1295038594-9585-3-git-send-email-wilsons@start.ca>
Setting m_private_state_thread to an invalid value when the child thread exits
results in a race condition between calls to ThreadCancel and ThreadJoin.
---
source/Target/Process.cpp | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp
index fdfa3a6..5834b8d 100644
--- a/source/Target/Process.cpp
+++ b/source/Target/Process.cpp
@@ -2173,7 +2173,6 @@ Process::RunPrivateStateThread ()
if (log)
log->Printf ("Process::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, this, GetID());
- m_private_state_thread = LLDB_INVALID_HOST_THREAD;
return NULL;
}
--
1.7.3.5
From wilsons at start.ca Fri Jan 14 14:56:34 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Fri, 14 Jan 2011 15:56:34 -0500
Subject: [Lldb-commits] [PATCH 3/3] Extend the ObjectFile interface to
support dynamic loading on ELF platforms.
In-Reply-To: <1295038594-9585-1-git-send-email-wilsons@start.ca>
References: <1295038594-9585-1-git-send-email-wilsons@start.ca>
Message-ID: <1295038594-9585-4-git-send-email-wilsons@start.ca>
Debuggers on ELF platforms hook into the runtime linker by monitoring a special
"rendezvous" embedded in the address space of the inferior process. The exact
location of this structure is filled in by the runtime linker and can be
resolved by locating the DT_DEBUG entry in the processes .dynamic section. The
new GetImageInfo() method (morally equivalent to Process::GetImageInfo) provides
the mechanism to locate this information.
GetEntryPoint() simply returns the address of the start symbol in the executable
if present. It is useful to the dynamic loader plugin for ELF systems as this
is the earliest point where LLDB can break and probe the inferiors .dynamic
section and rendezvous structure. Also, this address can be used in the
computation of the virtual base address for position independent executables.
---
include/lldb/Symbol/ObjectFile.h | 27 +++++++++++++++++++++++++++
1 files changed, 27 insertions(+), 0 deletions(-)
diff --git a/include/lldb/Symbol/ObjectFile.h b/include/lldb/Symbol/ObjectFile.h
index 184e80c..8e51571 100644
--- a/include/lldb/Symbol/ObjectFile.h
+++ b/include/lldb/Symbol/ObjectFile.h
@@ -173,6 +173,17 @@ public:
//------------------------------------------------------------------
virtual bool
IsExecutable () const = 0;
+
+ //------------------------------------------------------------------
+ /// Returns the virtual address of the entry point for this object
+ /// file.
+ ///
+ /// @return
+ /// The virtual address of the entry point or an invalid address
+ /// if an entry point is not defined.
+ //------------------------------------------------------------------
+ virtual lldb_private::Address
+ GetEntryPoint () const { return Address(); }
//------------------------------------------------------------------
/// Returns the offset into a file at which this object resides.
@@ -311,6 +322,22 @@ public:
virtual lldb_private::UnwindTable&
GetUnwindTable () { return m_unwind_table; }
+ //------------------------------------------------------------------
+ /// Similar to Process::GetImageInfoAddress().
+ ///
+ /// Some platforms embed auxiliary structures useful to debuggers in the
+ /// address space of the inferior process. This method returns the address
+ /// of such a structure if the information can be resolved via entries in
+ /// the object file. ELF, for example, provides a means to hook into the
+ /// runtime linker so that a debugger may monitor the loading and unloading
+ /// of shared libraries.
+ ///
+ /// @return
+ /// The address of any auxiliary tables, or an invalid address if this
+ /// object file format does not support or contain such information.
+ virtual lldb_private::Address
+ GetImageInfoAddress () { return Address(); }
+
protected:
//------------------------------------------------------------------
// Member variables.
--
1.7.3.5
From johnny.chen at apple.com Fri Jan 14 14:55:13 2011
From: johnny.chen at apple.com (Johnny Chen)
Date: Fri, 14 Jan 2011 20:55:13 -0000
Subject: [Lldb-commits] [lldb] r123463 - /lldb/trunk/test/make/Makefile.rules
Message-ID: <20110114205513.D268A2A6C12C@llvm.org>
Author: johnny
Date: Fri Jan 14 14:55:13 2011
New Revision: 123463
URL: http://llvm.org/viewvc/llvm-project?rev=123463&view=rev
Log:
Added comments.
Modified:
lldb/trunk/test/make/Makefile.rules
Modified: lldb/trunk/test/make/Makefile.rules
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/make/Makefile.rules?rev=123463&r1=123462&r2=123463&view=diff
==============================================================================
--- lldb/trunk/test/make/Makefile.rules (original)
+++ lldb/trunk/test/make/Makefile.rules Fri Jan 14 14:55:13 2011
@@ -19,6 +19,9 @@
#----------------------------------------------------------------------
# CC defaults to gcc.
+# See also these functions:
+# o cxx_compiler
+# o cxx_linker
#----------------------------------------------------------------------
CC ?= gcc
ifeq "$(CC)" "cc"
From gclayton at apple.com Fri Jan 14 15:03:17 2011
From: gclayton at apple.com (Greg Clayton)
Date: Fri, 14 Jan 2011 13:03:17 -0800
Subject: [Lldb-commits] [PATCH 0/3] trivial lldb fixes
In-Reply-To: <1295038594-9585-1-git-send-email-wilsons@start.ca>
References: <1295038594-9585-1-git-send-email-wilsons@start.ca>
Message-ID: <496726F5-12E2-4456-A9E4-DE205AF36565@apple.com>
These look good. Commit them at will.
On Jan 14, 2011, at 12:56 PM, Stephen Wilson wrote:
> This patch series contains two trivial fixes. Also, an extension to the
> ObjectFile interface is provided as discussed here:
>
> http://lists.cs.uiuc.edu/pipermail/lldb-dev/2011-January/000325.html
>
> The fixes pave the way for a second patch series I will be sending shortly
> containing various fixes/improvements to the ObjectFileELF and ProcessLinux
> plugins.
>
>
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
From wilsons at start.ca Fri Jan 14 15:07:07 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Fri, 14 Jan 2011 21:07:07 -0000
Subject: [Lldb-commits] [lldb] r123464 -
/lldb/trunk/source/Target/Process.cpp
Message-ID: <20110114210708.011202A6C12C@llvm.org>
Author: wilsons
Date: Fri Jan 14 15:07:07 2011
New Revision: 123464
URL: http://llvm.org/viewvc/llvm-project?rev=123464&view=rev
Log:
Do not prefix log messages with ProcessMacOSX from the context of Process.
Modified:
lldb/trunk/source/Target/Process.cpp
Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=123464&r1=123463&r2=123464&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Fri Jan 14 15:07:07 2011
@@ -1099,7 +1099,7 @@
addr_t bp_addr = bp_site->GetLoadAddress();
lldb::user_id_t breakID = bp_site->GetID();
if (log)
- log->Printf ("ProcessMacOSX::DisableBreakpoint (breakID = %d) addr = 0x%llx", breakID, (uint64_t)bp_addr);
+ log->Printf ("Process::DisableBreakpoint (breakID = %d) addr = 0x%llx", breakID, (uint64_t)bp_addr);
if (bp_site->IsHardware())
{
From wilsons at start.ca Fri Jan 14 15:07:56 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Fri, 14 Jan 2011 21:07:56 -0000
Subject: [Lldb-commits] [lldb] r123465 -
/lldb/trunk/source/Target/Process.cpp
Message-ID: <20110114210756.90D1D2A6C12C@llvm.org>
Author: wilsons
Date: Fri Jan 14 15:07:56 2011
New Revision: 123465
URL: http://llvm.org/viewvc/llvm-project?rev=123465&view=rev
Log:
Do not prematurely invalidate thread handle.
Setting m_private_state_thread to an invalid value when the child thread exits
results in a race condition between calls to ThreadCancel and ThreadJoin.
Modified:
lldb/trunk/source/Target/Process.cpp
Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=123465&r1=123464&r2=123465&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Fri Jan 14 15:07:56 2011
@@ -2173,7 +2173,6 @@
if (log)
log->Printf ("Process::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, this, GetID());
- m_private_state_thread = LLDB_INVALID_HOST_THREAD;
return NULL;
}
From wilsons at start.ca Fri Jan 14 15:08:59 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Fri, 14 Jan 2011 21:08:59 -0000
Subject: [Lldb-commits] [lldb] r123466 -
/lldb/trunk/include/lldb/Symbol/ObjectFile.h
Message-ID: <20110114210859.CF7752A6C12C@llvm.org>
Author: wilsons
Date: Fri Jan 14 15:08:59 2011
New Revision: 123466
URL: http://llvm.org/viewvc/llvm-project?rev=123466&view=rev
Log:
Extend the ObjectFile interface to support dynamic loading on ELF platforms.
Debuggers on ELF platforms hook into the runtime linker by monitoring a special
"rendezvous" embedded in the address space of the inferior process. The exact
location of this structure is filled in by the runtime linker and can be
resolved by locating the DT_DEBUG entry in the processes .dynamic section. The
new GetImageInfoAddress() method (morally equivalent to
Process::GetImageInfoAddress) provides the mechanism to locate this information.
GetEntryPoint() simply returns the address of the start symbol in the executable
if present. It is useful to the dynamic loader plugin for ELF systems as this
is the earliest point where LLDB can break and probe the inferiors .dynamic
section and rendezvous structure. Also, this address can be used in the
computation of the virtual base address for position independent executables.
Modified:
lldb/trunk/include/lldb/Symbol/ObjectFile.h
Modified: lldb/trunk/include/lldb/Symbol/ObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ObjectFile.h?rev=123466&r1=123465&r2=123466&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ObjectFile.h (original)
+++ lldb/trunk/include/lldb/Symbol/ObjectFile.h Fri Jan 14 15:08:59 2011
@@ -173,6 +173,17 @@
//------------------------------------------------------------------
virtual bool
IsExecutable () const = 0;
+
+ //------------------------------------------------------------------
+ /// Returns the virtual address of the entry point for this object
+ /// file.
+ ///
+ /// @return
+ /// The virtual address of the entry point or an invalid address
+ /// if an entry point is not defined.
+ //------------------------------------------------------------------
+ virtual lldb_private::Address
+ GetEntryPoint () const { return Address(); }
//------------------------------------------------------------------
/// Returns the offset into a file at which this object resides.
@@ -311,6 +322,22 @@
virtual lldb_private::UnwindTable&
GetUnwindTable () { return m_unwind_table; }
+ //------------------------------------------------------------------
+ /// Similar to Process::GetImageInfoAddress().
+ ///
+ /// Some platforms embed auxiliary structures useful to debuggers in the
+ /// address space of the inferior process. This method returns the address
+ /// of such a structure if the information can be resolved via entries in
+ /// the object file. ELF, for example, provides a means to hook into the
+ /// runtime linker so that a debugger may monitor the loading and unloading
+ /// of shared libraries.
+ ///
+ /// @return
+ /// The address of any auxiliary tables, or an invalid address if this
+ /// object file format does not support or contain such information.
+ virtual lldb_private::Address
+ GetImageInfoAddress () { return Address(); }
+
protected:
//------------------------------------------------------------------
// Member variables.
From ctice at apple.com Fri Jan 14 15:09:29 2011
From: ctice at apple.com (Caroline Tice)
Date: Fri, 14 Jan 2011 21:09:29 -0000
Subject: [Lldb-commits] [lldb] r123467 - in /lldb/trunk/source:
Commands/CommandObjectSettings.cpp Interpreter/ScriptInterpreterPython.cpp
Message-ID: <20110114210929.4D6BA2A6C12C@llvm.org>
Author: ctice
Date: Fri Jan 14 15:09:29 2011
New Revision: 123467
URL: http://llvm.org/viewvc/llvm-project?rev=123467&view=rev
Log:
Recent modifications to the Python script interpreter caused some problems
when handling one-liner commands that contain escaped characters. In
order to deal with the new namespace/dictionary stuff, the command was
being embedded within a second string, which messed up the escaping.
This fixes the problem by handling one-liners in a different manner, so they
no longer need to be embedded within another string, and can still be
processed in the proper namespace/dictionary context.
Modified:
lldb/trunk/source/Commands/CommandObjectSettings.cpp
lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp
Modified: lldb/trunk/source/Commands/CommandObjectSettings.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectSettings.cpp?rev=123467&r1=123466&r2=123467&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectSettings.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectSettings.cpp Fri Jan 14 15:09:29 2011
@@ -355,10 +355,10 @@
}
else
{
+ StreamString tmp_str;
char *type_name = (char *) "";
if (var_type != eSetVarTypeNone)
{
- StreamString tmp_str;
tmp_str.Printf (" (%s)", UserSettingsController::GetTypeString (var_type));
type_name = (char *) tmp_str.GetData();
}
Modified: lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp?rev=123467&r1=123466&r2=123467&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp (original)
+++ lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp Fri Jan 14 15:09:29 2011
@@ -326,17 +326,98 @@
Mutex::Locker locker (GetPythonMutex());
+ // We want to call run_one_line, passing in the dictionary and the command string. We cannot do this through
+ // PyRun_SimpleString here because the command string may contain escaped characters, and putting it inside
+ // another string to pass to PyRun_SimpleString messes up the escaping. So we use the following more complicated
+ // method to pass the command string directly down to Python.
+
+
+ bool success = false;
+
if (command)
{
- int success;
+ // Find the correct script interpreter dictionary in the main module.
+ PyObject *main_mod = PyImport_AddModule ("__main__");
+ PyObject *script_interpreter_dict = NULL;
+ if (main_mod != NULL)
+ {
+ PyObject *main_dict = PyModule_GetDict (main_mod);
+ if ((main_dict != NULL)
+ && PyDict_Check (main_dict))
+ {
+ // Go through the main dictionary looking for the correct python script interpreter dictionary
+ PyObject *key, *value;
+ Py_ssize_t pos = 0;
+
+ while (PyDict_Next (main_dict, &pos, &key, &value))
+ {
+ // We have stolen references to the key and value objects in the dictionary; we need to increment
+ // them now so that Python's garbage collector doesn't collect them out from under us.
+ Py_INCREF (key);
+ Py_INCREF (value);
+ if (strcmp (PyString_AsString (key), m_dictionary_name.c_str()) == 0)
+ {
+ script_interpreter_dict = value;
+ break;
+ }
+ }
+ }
+
+ if (script_interpreter_dict != NULL)
+ {
+ PyObject *pfunc = NULL;
+ PyObject *pmod = PyImport_AddModule ("embedded_interpreter");
+ if (pmod != NULL)
+ {
+ PyObject *pmod_dict = PyModule_GetDict (pmod);
+ if ((pmod_dict != NULL)
+ && PyDict_Check (pmod_dict))
+ {
+ PyObject *key, *value;
+ Py_ssize_t pos = 0;
+
+ while (PyDict_Next (pmod_dict, &pos, &key, &value))
+ {
+ Py_INCREF (key);
+ Py_INCREF (value);
+ if (strcmp (PyString_AsString (key), "run_one_line") == 0)
+ {
+ pfunc = value;
+ break;
+ }
+ }
+
+ PyObject *string_arg = PyString_FromString (command);
+ if (pfunc && string_arg && PyCallable_Check (pfunc))
+ {
+ PyObject *pargs = PyTuple_New (2);
+ if (pargs != NULL)
+ {
+ PyTuple_SetItem (pargs, 0, script_interpreter_dict);
+ PyTuple_SetItem (pargs, 1, string_arg);
+ PyObject *pvalue = PyObject_CallObject (pfunc, pargs);
+ Py_DECREF (pargs);
+ if (pvalue != NULL)
+ {
+ Py_DECREF (pvalue);
+ success = true;
+ }
+ else if (PyErr_Occurred ())
+ {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ }
+ }
+ }
+ }
+ Py_INCREF (script_interpreter_dict);
+ }
+ }
- StreamString sstr;
- sstr.Printf ("run_one_line (%s, '%s')", m_dictionary_name.c_str(), command);
- success = PyRun_SimpleString (sstr.GetData());
-
LeaveSession ();
- if (success == 0)
+ if (success)
return true;
// The one-liner failed. Append the error message.
From wilsons at start.ca Fri Jan 14 15:12:14 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Fri, 14 Jan 2011 16:12:14 -0500
Subject: [Lldb-commits] [PATCH 0/8] linux: process and object file plugin
updates
Message-ID: <1295039542-9640-1-git-send-email-wilsons@start.ca>
This patch series provides some relatively straightforward updates and fixes to
the ProcessLinux and ObjectFileELF plugins. Most notably the new ObjectFile
methods GetImageInfoAddress and GetEntryPoint are implemented for ELF's, as well
as Process::GetImageInfoAddress.
This patch series paves the way for the addition of a new DynamicLoader plugin
for Linux that I will be sending out shortly.
From wilsons at start.ca Fri Jan 14 15:12:15 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Fri, 14 Jan 2011 16:12:15 -0500
Subject: [Lldb-commits] [PATCH 1/8] Have LinuxThread cache it's current
StopInfo object.
In-Reply-To: <1295039542-9640-1-git-send-email-wilsons@start.ca>
References: <1295039542-9640-1-git-send-email-wilsons@start.ca>
Message-ID: <1295039542-9640-2-git-send-email-wilsons@start.ca>
---
source/Plugins/Process/Linux/LinuxThread.cpp | 47 ++++++++++++++++----------
source/Plugins/Process/Linux/LinuxThread.h | 4 ++
2 files changed, 33 insertions(+), 18 deletions(-)
diff --git a/source/Plugins/Process/Linux/LinuxThread.cpp b/source/Plugins/Process/Linux/LinuxThread.cpp
index e189064..4ceb051 100644
--- a/source/Plugins/Process/Linux/LinuxThread.cpp
+++ b/source/Plugins/Process/Linux/LinuxThread.cpp
@@ -40,6 +40,7 @@ LinuxThread::GetMonitor()
void
LinuxThread::RefreshStateAfterStop()
{
+ RefreshPrivateStopReason();
}
const char *
@@ -101,24 +102,9 @@ LinuxThread::CreateRegisterContextForFrame (lldb_private::StackFrame *frame)
lldb::StopInfoSP
LinuxThread::GetPrivateStopReason()
{
- lldb::StopInfoSP stop_info;
-
- switch (m_note)
- {
- default:
- break;
-
- case eBreak:
- stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(
- *this, m_breakpoint->GetID());
- break;
-
- case eTrace:
- stop_info = StopInfo::CreateStopReasonToTrace(*this);
- break;
- }
-
- return stop_info;
+ if (!m_stop_info || !m_stop_info->IsValid())
+ RefreshPrivateStopReason();
+ return m_stop_info;
}
Unwind *
@@ -196,3 +182,28 @@ LinuxThread::ExitNotify()
{
m_note = eExit;
}
+
+void
+LinuxThread::RefreshPrivateStopReason()
+{
+ switch (m_note) {
+
+ default:
+ case eNone:
+ m_stop_info.reset();
+ break;
+
+ case eBreak:
+ m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(
+ *this, m_breakpoint->GetID());
+ break;
+
+ case eTrace:
+ m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
+ break;
+
+ case eExit:
+ m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, SIGCHLD);
+ break;
+ }
+}
diff --git a/source/Plugins/Process/Linux/LinuxThread.h b/source/Plugins/Process/Linux/LinuxThread.h
index 4dcdbb3..ee69cf7 100644
--- a/source/Plugins/Process/Linux/LinuxThread.h
+++ b/source/Plugins/Process/Linux/LinuxThread.h
@@ -72,6 +72,7 @@ private:
std::auto_ptr m_frame_ap;
lldb::BreakpointSiteSP m_breakpoint;
+ lldb::StopInfoSP m_stop_info;
enum Notification {
eNone,
@@ -87,6 +88,9 @@ private:
lldb::StopInfoSP
GetPrivateStopReason();
+ void
+ RefreshPrivateStopReason();
+
lldb_private::Unwind *
GetUnwinder();
};
--
1.7.3.5
From wilsons at start.ca Fri Jan 14 15:12:16 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Fri, 14 Jan 2011 16:12:16 -0500
Subject: [Lldb-commits] [PATCH 2/8] Implement GetEntryPoint,
GetImageInfoAddress and GetArchitecture for ObjectFileELF.
In-Reply-To: <1295039542-9640-1-git-send-email-wilsons@start.ca>
References: <1295039542-9640-1-git-send-email-wilsons@start.ca>
Message-ID: <1295039542-9640-3-git-send-email-wilsons@start.ca>
---
source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 78 ++++++++++++++++++++++-
source/Plugins/ObjectFile/ELF/ObjectFileELF.h | 9 +++
2 files changed, 85 insertions(+), 2 deletions(-)
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 3f6dd20..5b99d01 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -12,6 +12,7 @@
#include
#include
+#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/DataBuffer.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/FileSpecList.h"
@@ -70,9 +71,10 @@ ObjectFileELF::CreateInstance(Module *module,
unsigned address_size = ELFHeader::AddressSizeInBytes(magic);
if (address_size == 4 || address_size == 8)
{
- std::auto_ptr objfile_ap(
+ std::auto_ptr objfile_ap(
new ObjectFileELF(module, data_sp, file, offset, length));
- if (objfile_ap->ParseHeader())
+ ArchSpec spec = objfile_ap->GetArchitecture();
+ if (spec.IsValid() && objfile_ap->SetModulesArchitecture(spec))
return objfile_ap.release();
}
}
@@ -80,6 +82,15 @@ ObjectFileELF::CreateInstance(Module *module,
return NULL;
}
+ArchSpec
+ObjectFileELF::GetArchitecture()
+{
+ if (!ParseHeader())
+ return ArchSpec();
+
+ return ArchSpec(eArchTypeELF, m_header.e_machine, m_header.e_flags);
+}
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -151,6 +162,15 @@ ObjectFileELF::IsExecutable() const
return m_header.e_type == ET_EXEC;
}
+Address
+ObjectFileELF::GetEntryPoint() const
+{
+ if (m_header.e_entry)
+ return Address(NULL, m_header.e_entry);
+ else
+ return Address();
+}
+
ByteOrder
ObjectFileELF::GetByteOrder() const
{
@@ -208,6 +228,60 @@ ObjectFileELF::GetDependentModules(FileSpecList &files)
return num_specs;
}
+Address
+ObjectFileELF::GetImageInfoAddress()
+{
+ if (!ParseSectionHeaders())
+ return Address();
+
+ user_id_t dynsym_id = 0;
+ for (SectionHeaderCollIter sh_pos = m_section_headers.begin();
+ sh_pos != m_section_headers.end(); ++sh_pos)
+ {
+ if (sh_pos->sh_type == SHT_DYNAMIC)
+ {
+ dynsym_id = SectionIndex(sh_pos);
+ break;
+ }
+ }
+
+ if (!dynsym_id)
+ return Address();
+
+ SectionList *section_list = GetSectionList();
+ if (!section_list)
+ return Address();
+
+ // Resolve the dynamic table entries.
+ Section *dynsym = section_list->FindSectionByID(dynsym_id).get();
+ if (!dynsym)
+ return Address();
+
+ DataExtractor dynsym_data;
+ if (dynsym->ReadSectionDataFromObjectFile(this, dynsym_data))
+ {
+ ELFDynamic symbol;
+ const unsigned section_size = dynsym_data.GetByteSize();
+ unsigned offset = 0;
+ unsigned cursor = 0;
+
+ // Look for a DT_DEBUG entry.
+ while (cursor < section_size)
+ {
+ offset = cursor;
+ if (!symbol.Parse(dynsym_data, &cursor))
+ break;
+
+ if (symbol.d_tag != DT_DEBUG)
+ continue;
+
+ return Address(dynsym, offset + sizeof(symbol.d_tag));
+ }
+ }
+
+ return Address();
+}
+
//----------------------------------------------------------------------
// ParseDependentModules
//----------------------------------------------------------------------
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index e91fabb..69a9a68 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -89,6 +89,9 @@ public:
virtual bool
IsExecutable () const;
+ virtual lldb_private::Address
+ GetEntryPoint() const;
+
virtual size_t
GetAddressByteSize() const;
@@ -110,6 +113,12 @@ public:
virtual uint32_t
GetDependentModules(lldb_private::FileSpecList& files);
+ virtual lldb_private::Address
+ GetImageInfoAddress();
+
+ lldb_private::ArchSpec
+ GetArchitecture();
+
private:
ObjectFileELF(lldb_private::Module* module,
lldb::DataBufferSP& dataSP,
--
1.7.3.5
From wilsons at start.ca Fri Jan 14 15:12:17 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Fri, 14 Jan 2011 16:12:17 -0500
Subject: [Lldb-commits] [PATCH 3/8] Test if an ELF object is executable by
checking if an entry point is defined.
In-Reply-To: <1295039542-9640-1-git-send-email-wilsons@start.ca>
References: <1295039542-9640-1-git-send-email-wilsons@start.ca>
Message-ID: <1295039542-9640-4-git-send-email-wilsons@start.ca>
The previous check on header type ET_EXEC is not general enough. Position
independent executables have type ET_DYN.
---
source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 5b99d01..f58c779 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -159,7 +159,7 @@ ObjectFileELF::~ObjectFileELF()
bool
ObjectFileELF::IsExecutable() const
{
- return m_header.e_type == ET_EXEC;
+ return m_header.e_entry != 0;
}
Address
--
1.7.3.5
From wilsons at start.ca Fri Jan 14 15:12:18 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Fri, 14 Jan 2011 16:12:18 -0500
Subject: [Lldb-commits] [PATCH 4/8] Implement
ProcessLinux::GetImageInfoAddress().
In-Reply-To: <1295039542-9640-1-git-send-email-wilsons@start.ca>
References: <1295039542-9640-1-git-send-email-wilsons@start.ca>
Message-ID: <1295039542-9640-5-git-send-email-wilsons@start.ca>
---
source/Plugins/Process/Linux/ProcessLinux.cpp | 13 +++++++++++++
source/Plugins/Process/Linux/ProcessLinux.h | 3 +++
2 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/source/Plugins/Process/Linux/ProcessLinux.cpp b/source/Plugins/Process/Linux/ProcessLinux.cpp
index 5e9a19d..6e9c0fb 100644
--- a/source/Plugins/Process/Linux/ProcessLinux.cpp
+++ b/source/Plugins/Process/Linux/ProcessLinux.cpp
@@ -149,6 +149,19 @@ ProcessLinux::DoResume()
return Error();
}
+addr_t
+ProcessLinux::GetImageInfoAddress()
+{
+ Target *target = &GetTarget();
+ ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
+ Address addr = obj_file->GetImageInfoAddress();
+
+ if (addr.IsValid())
+ return addr.GetLoadAddress(target);
+ else
+ return LLDB_INVALID_ADDRESS;
+}
+
Error
ProcessLinux::DoHalt(bool &caused_stop)
{
diff --git a/source/Plugins/Process/Linux/ProcessLinux.h b/source/Plugins/Process/Linux/ProcessLinux.h
index 16c2bec..3e23a7a 100644
--- a/source/Plugins/Process/Linux/ProcessLinux.h
+++ b/source/Plugins/Process/Linux/ProcessLinux.h
@@ -128,6 +128,9 @@ public:
virtual lldb::ByteOrder
GetByteOrder() const;
+ virtual lldb::addr_t
+ GetImageInfoAddress();
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
--
1.7.3.5
From wilsons at start.ca Fri Jan 14 15:12:20 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Fri, 14 Jan 2011 16:12:20 -0500
Subject: [Lldb-commits] [PATCH 6/8] Miscellaneous cleanups in ProcessMonitor.
In-Reply-To: <1295039542-9640-1-git-send-email-wilsons@start.ca>
References: <1295039542-9640-1-git-send-email-wilsons@start.ca>
Message-ID: <1295039542-9640-7-git-send-email-wilsons@start.ca>
Propagate the environment if one is not provided. Also, do not allocate the
monitor threads launch arguments on the stack (let the monitor thread assume
ownership).
---
source/Plugins/Process/Linux/ProcessMonitor.cpp | 29 +++++++++++++++--------
1 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/source/Plugins/Process/Linux/ProcessMonitor.cpp b/source/Plugins/Process/Linux/ProcessMonitor.cpp
index 1522263..8dd9804 100644
--- a/source/Plugins/Process/Linux/ProcessMonitor.cpp
+++ b/source/Plugins/Process/Linux/ProcessMonitor.cpp
@@ -463,7 +463,7 @@ ProcessMonitor::ProcessMonitor(ProcessLinux *process,
m_client_fd(-1),
m_server_fd(-1)
{
- LaunchArgs args(this, module, argv, envp,
+ LaunchArgs *args = new LaunchArgs(this, module, argv, envp,
stdin_path, stdout_path, stderr_path);
// Server/client descriptors.
@@ -473,13 +473,13 @@ ProcessMonitor::ProcessMonitor(ProcessLinux *process,
error.SetErrorString("Monitor failed to initialize.");
}
- StartOperationThread(&args, error);
+ StartOperationThread(args, error);
if (!error.Success())
return;
WAIT_AGAIN:
// Wait for the operation thread to initialize.
- if (sem_wait(&args.m_semaphore))
+ if (sem_wait(&args->m_semaphore))
{
if (errno == EINTR)
goto WAIT_AGAIN;
@@ -491,16 +491,17 @@ WAIT_AGAIN:
}
// Check that the launch was a success.
- if (!args.m_error.Success())
+ if (!args->m_error.Success())
{
StopOperationThread();
- error = args.m_error;
+ error = args->m_error;
return;
}
// Finally, start monitoring the child process for change in state.
- if (!(m_monitor_thread = Host::StartMonitoringChildProcess(
- ProcessMonitor::MonitorCallback, this, GetPID(), true)))
+ m_monitor_thread = Host::StartMonitoringChildProcess(
+ ProcessMonitor::MonitorCallback, this, GetPID(), true);
+ if (m_monitor_thread == LLDB_INVALID_HOST_THREAD)
{
error.SetErrorToGenericError();
error.SetErrorString("Process launch failed.");
@@ -524,12 +525,16 @@ void
ProcessMonitor::StartOperationThread(LaunchArgs *args, Error &error)
{
static const char *g_thread_name = "lldb.process.linux.operation";
+ std::auto_ptr args_ap(args);
if (m_operation_thread != LLDB_INVALID_HOST_THREAD)
return;
m_operation_thread =
Host::ThreadCreate(g_thread_name, OperationThread, args, &error);
+
+ if (error.Success())
+ args_ap.release();
}
void
@@ -547,12 +552,12 @@ ProcessMonitor::StopOperationThread()
void *
ProcessMonitor::OperationThread(void *arg)
{
- LaunchArgs *args = static_cast(arg);
+ std::auto_ptr args_ap(static_cast(arg));
- if (!Launch(args))
+ if (!Launch(args_ap.get()))
return NULL;
- ServeOperation(args->m_monitor);
+ ServeOperation(args_ap->m_monitor);
return NULL;
}
@@ -574,6 +579,10 @@ ProcessMonitor::Launch(LaunchArgs *args)
lldb::ThreadSP inferior;
+ // Propagate the environment if one is not supplied.
+ if (envp == NULL || envp[0] == NULL)
+ envp = const_cast(environ);
+
// Pseudo terminal setup.
if (!terminal.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY, err_str, err_len))
{
--
1.7.3.5
From wilsons at start.ca Fri Jan 14 15:12:21 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Fri, 14 Jan 2011 16:12:21 -0500
Subject: [Lldb-commits] [PATCH 7/8] Set the ID of a ProcessLinux instance to
the PID of the inferior on launch.
In-Reply-To: <1295039542-9640-1-git-send-email-wilsons@start.ca>
References: <1295039542-9640-1-git-send-email-wilsons@start.ca>
Message-ID: <1295039542-9640-8-git-send-email-wilsons@start.ca>
---
source/Plugins/Process/Linux/ProcessLinux.cpp | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/source/Plugins/Process/Linux/ProcessLinux.cpp b/source/Plugins/Process/Linux/ProcessLinux.cpp
index 6e9c0fb..00bdda5 100644
--- a/source/Plugins/Process/Linux/ProcessLinux.cpp
+++ b/source/Plugins/Process/Linux/ProcessLinux.cpp
@@ -124,6 +124,7 @@ ProcessLinux::DoLaunch(Module *module,
if (!error.Success())
return error;
+ SetID(m_monitor->GetPID());
return error;
}
--
1.7.3.5
From wilsons at start.ca Fri Jan 14 15:12:19 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Fri, 14 Jan 2011 16:12:19 -0500
Subject: [Lldb-commits] [PATCH 5/8] Use the correct type for thread handle.
In-Reply-To: <1295039542-9640-1-git-send-email-wilsons@start.ca>
References: <1295039542-9640-1-git-send-email-wilsons@start.ca>
Message-ID: <1295039542-9640-6-git-send-email-wilsons@start.ca>
---
source/Plugins/Process/Linux/ProcessMonitor.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/source/Plugins/Process/Linux/ProcessMonitor.h b/source/Plugins/Process/Linux/ProcessMonitor.h
index 7c3ae74..431fab7 100644
--- a/source/Plugins/Process/Linux/ProcessMonitor.h
+++ b/source/Plugins/Process/Linux/ProcessMonitor.h
@@ -140,7 +140,7 @@ private:
lldb::pid_t m_pid;
int m_terminal_fd;
- uint32_t m_monitor_thread;
+ lldb::thread_t m_monitor_thread;
lldb_private::Mutex m_server_mutex;
int m_client_fd;
--
1.7.3.5
From wilsons at start.ca Fri Jan 14 15:12:22 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Fri, 14 Jan 2011 16:12:22 -0500
Subject: [Lldb-commits] [PATCH 8/8] Add empty implementation of pure virtual
RegisterContext::InvalidateAllRegisters.
In-Reply-To: <1295039542-9640-1-git-send-email-wilsons@start.ca>
References: <1295039542-9640-1-git-send-email-wilsons@start.ca>
Message-ID: <1295039542-9640-9-git-send-email-wilsons@start.ca>
---
.../Process/Linux/RegisterContextLinux_x86_64.cpp | 5 +++++
.../Process/Linux/RegisterContextLinux_x86_64.h | 3 +++
2 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp b/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp
index da6ea8d..27cd6c6 100644
--- a/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp
+++ b/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp
@@ -423,6 +423,11 @@ RegisterContextLinux_x86_64::Invalidate()
{
}
+void
+RegisterContextLinux_x86_64::InvalidateAllRegisters()
+{
+}
+
size_t
RegisterContextLinux_x86_64::GetRegisterCount()
{
diff --git a/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h b/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h
index dc421ec..876d685 100644
--- a/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h
+++ b/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h
@@ -26,6 +26,9 @@ public:
void
Invalidate();
+ void
+ InvalidateAllRegisters();
+
size_t
GetRegisterCount();
--
1.7.3.5
From johnny.chen at apple.com Fri Jan 14 15:18:12 2011
From: johnny.chen at apple.com (Johnny Chen)
Date: Fri, 14 Jan 2011 21:18:12 -0000
Subject: [Lldb-commits] [lldb] r123469 - /lldb/trunk/test/make/Makefile.rules
Message-ID: <20110114211812.453682A6C12C@llvm.org>
Author: johnny
Date: Fri Jan 14 15:18:12 2011
New Revision: 123469
URL: http://llvm.org/viewvc/llvm-project?rev=123469&view=rev
Log:
Add makefile debugging rule for printing out the value of a variable.
>From http://blog.melski.net/tag/debugging-makefiles/.
Example:
[13:14:59] johnny:/Volumes/data/lldb/svn/trunk/test/class_static $ make print-CC
CC=gcc
origin = file
flavor = recursive
value = gcc
[13:15:09] johnny:/Volumes/data/lldb/svn/trunk/test/class_static $ make print-LD
LD= g++
origin = file
flavor = recursive
value = $(call cxx_linker,$(CC))
[13:15:21] johnny:/Volumes/data/lldb/svn/trunk/test/class_static $ make print-CXX
CXX= g++
origin = file
flavor = recursive
value = $(call cxx_compiler,$(CC))
[13:15:29] johnny:/Volumes/data/lldb/svn/trunk/test/class_static $
Modified:
lldb/trunk/test/make/Makefile.rules
Modified: lldb/trunk/test/make/Makefile.rules
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/make/Makefile.rules?rev=123469&r1=123468&r2=123469&view=diff
==============================================================================
--- lldb/trunk/test/make/Makefile.rules (original)
+++ lldb/trunk/test/make/Makefile.rules Fri Jan 14 15:18:12 2011
@@ -175,3 +175,14 @@
else
rm -rf "$(EXE)" "$(DSYM)" $(OBJECTS) $(PREREQS) $(DYLIB_OBJECTS) $(DYLIB_NAME) $(DYLIB_NAME).dSYM
endif
+
+#----------------------------------------------------------------------
+# From http://blog.melski.net/tag/debugging-makefiles/
+#
+# Usage: make print-CC print-CXX print-LD
+#----------------------------------------------------------------------
+print-%:
+ @echo '$*=$($*)'
+ @echo ' origin = $(origin $*)'
+ @echo ' flavor = $(flavor $*)'
+ @echo ' value = $(value $*)'
From gclayton at apple.com Fri Jan 14 15:34:58 2011
From: gclayton at apple.com (Greg Clayton)
Date: Fri, 14 Jan 2011 13:34:58 -0800
Subject: [Lldb-commits] [PATCH 3/8] Test if an ELF object is executable
by checking if an entry point is defined.
In-Reply-To: <1295039542-9640-4-git-send-email-wilsons@start.ca>
References: <1295039542-9640-1-git-send-email-wilsons@start.ca>
<1295039542-9640-4-git-send-email-wilsons@start.ca>
Message-ID: <7A4E6B48-9A78-4414-B6E2-BD36D07B65F6@apple.com>
Could a bootloader ELF file have an entry point of zero? Should this be:
bool
ObjectFileELF::IsExecutable() const
{
return m_header.e_entry != LLDB_INVALID_ADDRESS;
}
And then you would need to make sure that m_header.e_entry always gets initialized to LLDB_INVALID_ADDRESS?
On Jan 14, 2011, at 1:12 PM, Stephen Wilson wrote:
> The previous check on header type ET_EXEC is not general enough. Position
> independent executables have type ET_DYN.
> ---
> source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
> index 5b99d01..f58c779 100644
> --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
> +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
> @@ -159,7 +159,7 @@ ObjectFileELF::~ObjectFileELF()
> bool
> ObjectFileELF::IsExecutable() const
> {
> - return m_header.e_type == ET_EXEC;
> + return m_header.e_entry != 0;
> }
>
> Address
> --
> 1.7.3.5
>
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
From gclayton at apple.com Fri Jan 14 15:35:25 2011
From: gclayton at apple.com (Greg Clayton)
Date: Fri, 14 Jan 2011 13:35:25 -0800
Subject: [Lldb-commits] [PATCH 4/8] Implement
ProcessLinux::GetImageInfoAddress().
In-Reply-To: <1295039542-9640-5-git-send-email-wilsons@start.ca>
References: <1295039542-9640-1-git-send-email-wilsons@start.ca>
<1295039542-9640-5-git-send-email-wilsons@start.ca>
Message-ID: <79C732C6-62F6-49F9-82C4-183B6BE03B7D@apple.com>
Looks good.
On Jan 14, 2011, at 1:12 PM, Stephen Wilson wrote:
> ---
> source/Plugins/Process/Linux/ProcessLinux.cpp | 13 +++++++++++++
> source/Plugins/Process/Linux/ProcessLinux.h | 3 +++
> 2 files changed, 16 insertions(+), 0 deletions(-)
>
> diff --git a/source/Plugins/Process/Linux/ProcessLinux.cpp b/source/Plugins/Process/Linux/ProcessLinux.cpp
> index 5e9a19d..6e9c0fb 100644
> --- a/source/Plugins/Process/Linux/ProcessLinux.cpp
> +++ b/source/Plugins/Process/Linux/ProcessLinux.cpp
> @@ -149,6 +149,19 @@ ProcessLinux::DoResume()
> return Error();
> }
>
> +addr_t
> +ProcessLinux::GetImageInfoAddress()
> +{
> + Target *target = &GetTarget();
> + ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
> + Address addr = obj_file->GetImageInfoAddress();
> +
> + if (addr.IsValid())
> + return addr.GetLoadAddress(target);
> + else
> + return LLDB_INVALID_ADDRESS;
> +}
> +
> Error
> ProcessLinux::DoHalt(bool &caused_stop)
> {
> diff --git a/source/Plugins/Process/Linux/ProcessLinux.h b/source/Plugins/Process/Linux/ProcessLinux.h
> index 16c2bec..3e23a7a 100644
> --- a/source/Plugins/Process/Linux/ProcessLinux.h
> +++ b/source/Plugins/Process/Linux/ProcessLinux.h
> @@ -128,6 +128,9 @@ public:
> virtual lldb::ByteOrder
> GetByteOrder() const;
>
> + virtual lldb::addr_t
> + GetImageInfoAddress();
> +
> //------------------------------------------------------------------
> // PluginInterface protocol
> //------------------------------------------------------------------
> --
> 1.7.3.5
>
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
From gclayton at apple.com Fri Jan 14 15:41:59 2011
From: gclayton at apple.com (Greg Clayton)
Date: Fri, 14 Jan 2011 13:41:59 -0800
Subject: [Lldb-commits] [PATCH 6/8] Miscellaneous cleanups in
ProcessMonitor.
In-Reply-To: <1295039542-9640-7-git-send-email-wilsons@start.ca>
References: <1295039542-9640-1-git-send-email-wilsons@start.ca>
<1295039542-9640-7-git-send-email-wilsons@start.ca>
Message-ID: <7962DEC7-6AA6-4021-B30B-AB8A8EA070F3@apple.com>
The lifetime of args seems possibly racy? What if "StartOperationThread()" spawns a thread which gets an error and exits super quickly, could the thread put "args" into its auto_ptr and delete "args" before the code that launches that thread is done with "args"? I can't see all the code here, so I am just curious.
Other than that check, it looks good.
On Jan 14, 2011, at 1:12 PM, Stephen Wilson wrote:
> Propagate the environment if one is not provided. Also, do not allocate the
> monitor threads launch arguments on the stack (let the monitor thread assume
> ownership).
> ---
> source/Plugins/Process/Linux/ProcessMonitor.cpp | 29 +++++++++++++++--------
> 1 files changed, 19 insertions(+), 10 deletions(-)
>
> diff --git a/source/Plugins/Process/Linux/ProcessMonitor.cpp b/source/Plugins/Process/Linux/ProcessMonitor.cpp
> index 1522263..8dd9804 100644
> --- a/source/Plugins/Process/Linux/ProcessMonitor.cpp
> +++ b/source/Plugins/Process/Linux/ProcessMonitor.cpp
> @@ -463,7 +463,7 @@ ProcessMonitor::ProcessMonitor(ProcessLinux *process,
> m_client_fd(-1),
> m_server_fd(-1)
> {
> - LaunchArgs args(this, module, argv, envp,
> + LaunchArgs *args = new LaunchArgs(this, module, argv, envp,
> stdin_path, stdout_path, stderr_path);
>
> // Server/client descriptors.
> @@ -473,13 +473,13 @@ ProcessMonitor::ProcessMonitor(ProcessLinux *process,
> error.SetErrorString("Monitor failed to initialize.");
> }
>
> - StartOperationThread(&args, error);
> + StartOperationThread(args, error);
> if (!error.Success())
> return;
>
> WAIT_AGAIN:
> // Wait for the operation thread to initialize.
> - if (sem_wait(&args.m_semaphore))
> + if (sem_wait(&args->m_semaphore))
> {
> if (errno == EINTR)
> goto WAIT_AGAIN;
> @@ -491,16 +491,17 @@ WAIT_AGAIN:
> }
>
> // Check that the launch was a success.
> - if (!args.m_error.Success())
> + if (!args->m_error.Success())
> {
> StopOperationThread();
> - error = args.m_error;
> + error = args->m_error;
> return;
> }
>
> // Finally, start monitoring the child process for change in state.
> - if (!(m_monitor_thread = Host::StartMonitoringChildProcess(
> - ProcessMonitor::MonitorCallback, this, GetPID(), true)))
> + m_monitor_thread = Host::StartMonitoringChildProcess(
> + ProcessMonitor::MonitorCallback, this, GetPID(), true);
> + if (m_monitor_thread == LLDB_INVALID_HOST_THREAD)
> {
> error.SetErrorToGenericError();
> error.SetErrorString("Process launch failed.");
> @@ -524,12 +525,16 @@ void
> ProcessMonitor::StartOperationThread(LaunchArgs *args, Error &error)
> {
> static const char *g_thread_name = "lldb.process.linux.operation";
> + std::auto_ptr args_ap(args);
>
> if (m_operation_thread != LLDB_INVALID_HOST_THREAD)
> return;
>
> m_operation_thread =
> Host::ThreadCreate(g_thread_name, OperationThread, args, &error);
> +
> + if (error.Success())
> + args_ap.release();
> }
>
> void
> @@ -547,12 +552,12 @@ ProcessMonitor::StopOperationThread()
> void *
> ProcessMonitor::OperationThread(void *arg)
> {
> - LaunchArgs *args = static_cast(arg);
> + std::auto_ptr args_ap(static_cast(arg));
>
> - if (!Launch(args))
> + if (!Launch(args_ap.get()))
> return NULL;
>
> - ServeOperation(args->m_monitor);
> + ServeOperation(args_ap->m_monitor);
> return NULL;
> }
>
> @@ -574,6 +579,10 @@ ProcessMonitor::Launch(LaunchArgs *args)
>
> lldb::ThreadSP inferior;
>
> + // Propagate the environment if one is not supplied.
> + if (envp == NULL || envp[0] == NULL)
> + envp = const_cast(environ);
> +
> // Pseudo terminal setup.
> if (!terminal.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY, err_str, err_len))
> {
> --
> 1.7.3.5
>
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
From gclayton at apple.com Fri Jan 14 15:46:24 2011
From: gclayton at apple.com (Greg Clayton)
Date: Fri, 14 Jan 2011 13:46:24 -0800
Subject: [Lldb-commits] [PATCH 7/8] Set the ID of a ProcessLinux
instance to the PID of the inferior on launch.
In-Reply-To: <1295039542-9640-8-git-send-email-wilsons@start.ca>
References: <1295039542-9640-1-git-send-email-wilsons@start.ca>
<1295039542-9640-8-git-send-email-wilsons@start.ca>
Message-ID: <30785D6F-3C39-410B-91EA-4E220938894F@apple.com>
Good.
On Jan 14, 2011, at 1:12 PM, Stephen Wilson wrote:
> ---
> source/Plugins/Process/Linux/ProcessLinux.cpp | 1 +
> 1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/source/Plugins/Process/Linux/ProcessLinux.cpp b/source/Plugins/Process/Linux/ProcessLinux.cpp
> index 6e9c0fb..00bdda5 100644
> --- a/source/Plugins/Process/Linux/ProcessLinux.cpp
> +++ b/source/Plugins/Process/Linux/ProcessLinux.cpp
> @@ -124,6 +124,7 @@ ProcessLinux::DoLaunch(Module *module,
> if (!error.Success())
> return error;
>
> + SetID(m_monitor->GetPID());
> return error;
> }
>
> --
> 1.7.3.5
>
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
From gclayton at apple.com Fri Jan 14 15:47:34 2011
From: gclayton at apple.com (Greg Clayton)
Date: Fri, 14 Jan 2011 13:47:34 -0800
Subject: [Lldb-commits] [PATCH 5/8] Use the correct type for thread
handle.
In-Reply-To: <1295039542-9640-6-git-send-email-wilsons@start.ca>
References: <1295039542-9640-1-git-send-email-wilsons@start.ca>
<1295039542-9640-6-git-send-email-wilsons@start.ca>
Message-ID: <10154A14-11B6-4F0B-8776-18A79C2EB15A@apple.com>
Good.
On Jan 14, 2011, at 1:12 PM, Stephen Wilson wrote:
> ---
> source/Plugins/Process/Linux/ProcessMonitor.h | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/source/Plugins/Process/Linux/ProcessMonitor.h b/source/Plugins/Process/Linux/ProcessMonitor.h
> index 7c3ae74..431fab7 100644
> --- a/source/Plugins/Process/Linux/ProcessMonitor.h
> +++ b/source/Plugins/Process/Linux/ProcessMonitor.h
> @@ -140,7 +140,7 @@ private:
> lldb::pid_t m_pid;
> int m_terminal_fd;
>
> - uint32_t m_monitor_thread;
> + lldb::thread_t m_monitor_thread;
>
> lldb_private::Mutex m_server_mutex;
> int m_client_fd;
> --
> 1.7.3.5
>
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
From gclayton at apple.com Fri Jan 14 15:50:42 2011
From: gclayton at apple.com (Greg Clayton)
Date: Fri, 14 Jan 2011 13:50:42 -0800
Subject: [Lldb-commits] [PATCH 8/8] Add empty implementation of pure
virtual RegisterContext::InvalidateAllRegisters.
In-Reply-To: <1295039542-9640-9-git-send-email-wilsons@start.ca>
References: <1295039542-9640-1-git-send-email-wilsons@start.ca>
<1295039542-9640-9-git-send-email-wilsons@start.ca>
Message-ID:
Here is where you will want to track if you have read your regiters from what ever you read registers from on Linux.
You might to just want to copy the "lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_x86_64.cpp" and "lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_x86_64.h" files and modify the structures to match linux. This has all of the invalidating code done on a per/register group basis (gpr, fpu and exc registers).
On Jan 14, 2011, at 1:12 PM, Stephen Wilson wrote:
> ---
> .../Process/Linux/RegisterContextLinux_x86_64.cpp | 5 +++++
> .../Process/Linux/RegisterContextLinux_x86_64.h | 3 +++
> 2 files changed, 8 insertions(+), 0 deletions(-)
>
> diff --git a/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp b/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp
> index da6ea8d..27cd6c6 100644
> --- a/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp
> +++ b/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp
> @@ -423,6 +423,11 @@ RegisterContextLinux_x86_64::Invalidate()
> {
> }
>
> +void
> +RegisterContextLinux_x86_64::InvalidateAllRegisters()
> +{
> +}
> +
> size_t
> RegisterContextLinux_x86_64::GetRegisterCount()
> {
> diff --git a/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h b/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h
> index dc421ec..876d685 100644
> --- a/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h
> +++ b/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h
> @@ -26,6 +26,9 @@ public:
> void
> Invalidate();
>
> + void
> + InvalidateAllRegisters();
> +
> size_t
> GetRegisterCount();
>
> --
> 1.7.3.5
>
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
From johnny.chen at apple.com Fri Jan 14 15:55:29 2011
From: johnny.chen at apple.com (Johnny Chen)
Date: Fri, 14 Jan 2011 21:55:29 -0000
Subject: [Lldb-commits] [lldb] r123471 - /lldb/trunk/test/objc/Makefile
Message-ID: <20110114215529.E1B792A6C12C@llvm.org>
Author: johnny
Date: Fri Jan 14 15:55:29 2011
New Revision: 123471
URL: http://llvm.org/viewvc/llvm-project?rev=123471&view=rev
Log:
Converted to use Makefile.rules.
Modified:
lldb/trunk/test/objc/Makefile
Modified: lldb/trunk/test/objc/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/objc/Makefile?rev=123471&r1=123470&r2=123471&view=diff
==============================================================================
--- lldb/trunk/test/objc/Makefile (original)
+++ lldb/trunk/test/objc/Makefile Fri Jan 14 15:55:29 2011
@@ -1,125 +1,6 @@
-#----------------------------------------------------------------------
-# Fill in the source files to build
-#----------------------------------------------------------------------
-C_SOURCES :=
-CXX_SOURCES :=
-OBJC_SOURCES :=main.m
-OBJCXX_SOURCES :=
+LEVEL = ../make
-# Uncomment line below for debugging shell commands
-# SHELL = /bin/sh -x
-
-#----------------------------------------------------------------------
-# Change any build/tool options needed
-#----------------------------------------------------------------------
-DS := /usr/bin/dsymutil
-DSFLAGS =
-CFLAGS ?=-arch x86_64 -g -O0
-CPLUSPLUSFLAGS +=$(CFLAGS)
-CPPFLAGS +=$(CFLAGS)
-LD = gcc
+OBJC_SOURCES := main.m
LDFLAGS = $(CFLAGS) -lobjc -framework Foundation
-OBJECTS =
-EXE=a.out
-DSYM=$(EXE).dSYM
-
-#----------------------------------------------------------------------
-# Check if we have any C source files
-#----------------------------------------------------------------------
-ifneq "$(strip $(C_SOURCES))" ""
- OBJECTS +=$(strip $(C_SOURCES:.c=.o))
-endif
-
-#----------------------------------------------------------------------
-# Check if we have any C++ source files
-#----------------------------------------------------------------------
-ifneq "$(strip $(CXX_SOURCES))" ""
- OBJECTS +=$(strip $(CXX_SOURCES:.cpp=.o))
- LD = g++
-endif
-
-#----------------------------------------------------------------------
-# Check if we have any ObjC source files
-#----------------------------------------------------------------------
-ifneq "$(strip $(OBJC_SOURCES))" ""
- OBJECTS +=$(strip $(OBJC_SOURCES:.m=.o))
- LDFLAGS +=-lobjc
-endif
-
-#----------------------------------------------------------------------
-# Check if we have any ObjC++ source files
-#----------------------------------------------------------------------
-ifneq "$(strip $(OBJCXX_SOURCES))" ""
- OBJECTS +=$(strip $(OBJCXX_SOURCES:.mm=.o))
- LD = g++
- ifeq $(findstring lobjc,$(LDFLAGS)) ""
- LDFLAGS +=-lobjc
- endif
-endif
-
-
-#----------------------------------------------------------------------
-# Make the dSYM file from the executable
-#----------------------------------------------------------------------
-$(DSYM) : $(EXE)
- $(DS) $(DSFLAGS) -o "$(DSYM)" "$(EXE)"
-
-#----------------------------------------------------------------------
-# Compile the executable from all the objects (default rule) with no
-# dsym file.
-#----------------------------------------------------------------------
-$(EXE) : $(OBJECTS)
- $(LD) $(LDFLAGS) $(OBJECTS) -o "$(EXE)"
-
-
-#----------------------------------------------------------------------
-# Automatic variables based on items already entered. Below we create
-# an objects lists from the list of sources by replacing all entries
-# that end with .c with .o, and we also create a list of prerequisite
-# files by replacing all .c files with .d.
-#----------------------------------------------------------------------
-PREREQS := $(OBJECTS:.o=.d)
-
-#----------------------------------------------------------------------
-# Rule for Generating Prerequisites Automatically using .d files and
-# the compiler -MM option. The -M option will list all system headers,
-# and the -MM option will list all non-system dependencies.
-#----------------------------------------------------------------------
-%.d: %.c
- @set -e; rm -f $@; \
- $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
- sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
- rm -f $@.$$$$
-
-%.d: %.cpp
- @set -e; rm -f $@; \
- $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
- sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
- rm -f $@.$$$$
-
-%.d: %.m
- @set -e; rm -f $@; \
- $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
- sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
- rm -f $@.$$$$
-
-%.d: %.mm
- @set -e; rm -f $@; \
- $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
- sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
- rm -f $@.$$$$
-
-#----------------------------------------------------------------------
-# Include all of the makefiles for each source file so we don't have
-# to manually track all of the prerequisites for each source file.
-#----------------------------------------------------------------------
-sinclude $(PREREQS)
-
-.PHONY: clean
-dsym: $(DSYM)
-all: $(EXE) $(DSYM)
-clean:
- rm -rf "$(EXE)" "$(DSYM)" $(OBJECTS) $(PREREQS)
-
-
+include $(LEVEL)/Makefile.rules
From wilsons at start.ca Fri Jan 14 16:19:38 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Fri, 14 Jan 2011 17:19:38 -0500
Subject: [Lldb-commits] [PATCH 3/8] Test if an ELF object is executable
by checking if an entry point is defined.
In-Reply-To: <7A4E6B48-9A78-4414-B6E2-BD36D07B65F6@apple.com> (Greg Clayton's
message of "Fri, 14 Jan 2011 13:34:58 -0800")
References: <1295039542-9640-1-git-send-email-wilsons@start.ca>
<1295039542-9640-4-git-send-email-wilsons@start.ca>
<7A4E6B48-9A78-4414-B6E2-BD36D07B65F6@apple.com>
Message-ID:
Greg Clayton writes:
> Could a bootloader ELF file have an entry point of zero? Should this be:
Interesting question. I have never seen one myself (but that does not
mean they do not exist).
However the spec specifically says that if an ELF does not have an entry
point then this field must be zero. For that reason I think this should
be a relatively safe test.
> bool
> ObjectFileELF::IsExecutable() const
> {
> return m_header.e_entry != LLDB_INVALID_ADDRESS;
> }
>
> And then you would need to make sure that m_header.e_entry always gets initialized to LLDB_INVALID_ADDRESS?
>
>
> On Jan 14, 2011, at 1:12 PM, Stephen Wilson wrote:
>
>> The previous check on header type ET_EXEC is not general enough. Position
>> independent executables have type ET_DYN.
>> ---
>> source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 2 +-
>> 1 files changed, 1 insertions(+), 1 deletions(-)
>>
>> diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
>> index 5b99d01..f58c779 100644
>> --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
>> +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
>> @@ -159,7 +159,7 @@ ObjectFileELF::~ObjectFileELF()
>> bool
>> ObjectFileELF::IsExecutable() const
>> {
>> - return m_header.e_type == ET_EXEC;
>> + return m_header.e_entry != 0;
>> }
>>
>> Address
>> --
>> 1.7.3.5
>>
>> _______________________________________________
>> lldb-commits mailing list
>> lldb-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
>
--
steve
From wilsons at start.ca Fri Jan 14 16:57:48 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Fri, 14 Jan 2011 17:57:48 -0500
Subject: [Lldb-commits] [PATCH 6/8] Miscellaneous cleanups in
ProcessMonitor.
In-Reply-To: <7962DEC7-6AA6-4021-B30B-AB8A8EA070F3@apple.com> (Greg Clayton's
message of "Fri, 14 Jan 2011 13:41:59 -0800")
References: <1295039542-9640-1-git-send-email-wilsons@start.ca>
<1295039542-9640-7-git-send-email-wilsons@start.ca>
<7962DEC7-6AA6-4021-B30B-AB8A8EA070F3@apple.com>
Message-ID:
Greg Clayton writes:
> The lifetime of args seems possibly racy? What if
> "StartOperationThread()" spawns a thread which gets an error and exits
> super quickly, could the thread put "args" into its auto_ptr and
> delete "args" before the code that launches that thread is done with
> "args"? I can't see all the code here, so I am just curious.
I took another look over the code. You are right, there is a race if
the monitor thread encounters an error when launching the inferior.
This corrected patch uses the previous approach of having the parent
thread maintain ownership. Holding onto the launch args in an auto_ptr
should be safe here since we synchronize with the child thread via a
semaphore, and the child does not reference the launch args beyond that
point.
Thanks for the review!
Miscellaneous cleanups in ProcessMonitor.
Propagate the environment if one is not provided. Also, do not allocate the
monitor threads launch arguments on the stack.
diff --git a/source/Plugins/Process/Linux/ProcessMonitor.cpp b/source/Plugins/Process/Linux/ProcessMonitor.cpp
index 1522263..f21cb00 100644
--- a/source/Plugins/Process/Linux/ProcessMonitor.cpp
+++ b/source/Plugins/Process/Linux/ProcessMonitor.cpp
@@ -463,8 +463,10 @@ ProcessMonitor::ProcessMonitor(ProcessLinux *process,
m_client_fd(-1),
m_server_fd(-1)
{
- LaunchArgs args(this, module, argv, envp,
- stdin_path, stdout_path, stderr_path);
+ std::auto_ptr args;
+
+ args.reset(new LaunchArgs(this, module, argv, envp,
+ stdin_path, stdout_path, stderr_path));
// Server/client descriptors.
if (!EnableIPC())
@@ -473,13 +475,13 @@ ProcessMonitor::ProcessMonitor(ProcessLinux *process,
error.SetErrorString("Monitor failed to initialize.");
}
- StartOperationThread(&args, error);
+ StartOperationThread(args.get(), error);
if (!error.Success())
return;
WAIT_AGAIN:
// Wait for the operation thread to initialize.
- if (sem_wait(&args.m_semaphore))
+ if (sem_wait(&args->m_semaphore))
{
if (errno == EINTR)
goto WAIT_AGAIN;
@@ -491,16 +493,17 @@ WAIT_AGAIN:
}
// Check that the launch was a success.
- if (!args.m_error.Success())
+ if (!args->m_error.Success())
{
StopOperationThread();
- error = args.m_error;
+ error = args->m_error;
return;
}
// Finally, start monitoring the child process for change in state.
- if (!(m_monitor_thread = Host::StartMonitoringChildProcess(
- ProcessMonitor::MonitorCallback, this, GetPID(), true)))
+ m_monitor_thread = Host::StartMonitoringChildProcess(
+ ProcessMonitor::MonitorCallback, this, GetPID(), true);
+ if (m_monitor_thread == LLDB_INVALID_HOST_THREAD)
{
error.SetErrorToGenericError();
error.SetErrorString("Process launch failed.");
@@ -574,6 +577,10 @@ ProcessMonitor::Launch(LaunchArgs *args)
lldb::ThreadSP inferior;
+ // Propagate the environment if one is not supplied.
+ if (envp == NULL || envp[0] == NULL)
+ envp = const_cast(environ);
+
// Pseudo terminal setup.
if (!terminal.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY, err_str, err_len))
{
From wilsons at start.ca Fri Jan 14 17:01:29 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Fri, 14 Jan 2011 18:01:29 -0500
Subject: [Lldb-commits] [PATCH 8/8] Add empty implementation of pure
virtual RegisterContext::InvalidateAllRegisters.
In-Reply-To: (Greg Clayton's
message of "Fri, 14 Jan 2011 13:50:42 -0800")
References: <1295039542-9640-1-git-send-email-wilsons@start.ca>
<1295039542-9640-9-git-send-email-wilsons@start.ca>
Message-ID:
Greg Clayton writes:
> Here is where you will want to track if you have read your regiters
> from what ever you read registers from on Linux.
OK.
> You might to just want to copy the
> "lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_x86_64.cpp"
> and
> "lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_x86_64.h"
> files and modify the structures to match linux. This has all of the
> invalidating code done on a per/register group basis (gpr, fpu and exc
> registers).
Absolutely. Is it OK for this patch to go in as is? Since the method
is pure virtual this empty implementation simply allows the tree to
build. I will certainly look into implementing the method properly in
the near future.
>
> On Jan 14, 2011, at 1:12 PM, Stephen Wilson wrote:
>
>> ---
>> .../Process/Linux/RegisterContextLinux_x86_64.cpp | 5 +++++
>> .../Process/Linux/RegisterContextLinux_x86_64.h | 3 +++
>> 2 files changed, 8 insertions(+), 0 deletions(-)
>>
>> diff --git a/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp b/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp
>> index da6ea8d..27cd6c6 100644
>> --- a/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp
>> +++ b/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp
>> @@ -423,6 +423,11 @@ RegisterContextLinux_x86_64::Invalidate()
>> {
>> }
>>
>> +void
>> +RegisterContextLinux_x86_64::InvalidateAllRegisters()
>> +{
>> +}
>> +
>> size_t
>> RegisterContextLinux_x86_64::GetRegisterCount()
>> {
>> diff --git a/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h b/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h
>> index dc421ec..876d685 100644
>> --- a/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h
>> +++ b/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h
>> @@ -26,6 +26,9 @@ public:
>> void
>> Invalidate();
>>
>> + void
>> + InvalidateAllRegisters();
>> +
>> size_t
>> GetRegisterCount();
>>
>> --
>> 1.7.3.5
>>
>> _______________________________________________
>> lldb-commits mailing list
>> lldb-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
>
--
steve
From gclayton at apple.com Fri Jan 14 17:37:51 2011
From: gclayton at apple.com (Greg Clayton)
Date: Fri, 14 Jan 2011 23:37:51 -0000
Subject: [Lldb-commits] [lldb] r123492 -
/lldb/trunk/include/lldb/Host/Predicate.h
Message-ID: <20110114233751.B3EC02A6C12C@llvm.org>
Author: gclayton
Date: Fri Jan 14 17:37:51 2011
New Revision: 123492
URL: http://llvm.org/viewvc/llvm-project?rev=123492&view=rev
Log:
Added the ability to wait for a predicate value, and set it to a new value all in a thread safe fashion.
Modified:
lldb/trunk/include/lldb/Host/Predicate.h
Modified: lldb/trunk/include/lldb/Host/Predicate.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/Predicate.h?rev=123492&r1=123491&r2=123492&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/Predicate.h (original)
+++ lldb/trunk/include/lldb/Host/Predicate.h Fri Jan 14 17:37:51 2011
@@ -320,6 +320,38 @@
return m_value == value;
}
+ bool
+ WaitForValueEqualToAndSetValueTo (T wait_value, T new_value, const TimeValue *abstime = NULL, bool *timed_out = NULL)
+ {
+ int err = 0;
+ // pthread_cond_timedwait() or pthread_cond_wait() will atomically
+ // unlock the mutex and wait for the condition to be set. When either
+ // function returns, they will re-lock the mutex. We use an auto lock/unlock
+ // class (Mutex::Locker) to allow us to return at any point in this
+ // function and not have to worry about unlocking the mutex.
+ Mutex::Locker locker(m_mutex);
+
+#ifdef DB_PTHREAD_LOG_EVENTS
+ printf("%s (value = 0x%8.8x, abstime = %p), m_value = 0x%8.8x", __FUNCTION__, value, abstime, m_value);
+#endif
+ if (timed_out)
+ *timed_out = false;
+
+ while (err == 0 && m_value != wait_value)
+ {
+ err = m_condition.Wait (m_mutex.GetMutex(), abstime, timed_out);
+ }
+
+ if (m_value == wait_value)
+ {
+ m_value = new_value;
+ return true;
+ }
+
+ return false;
+ }
+
+
//------------------------------------------------------------------
/// Wait for \a m_value to not be equal to \a value.
///
From gclayton at apple.com Fri Jan 14 17:43:29 2011
From: gclayton at apple.com (Greg Clayton)
Date: Fri, 14 Jan 2011 15:43:29 -0800
Subject: [Lldb-commits] [PATCH 3/8] Test if an ELF object is executable
by checking if an entry point is defined.
In-Reply-To:
References: <1295039542-9640-1-git-send-email-wilsons@start.ca>
<1295039542-9640-4-git-send-email-wilsons@start.ca>
<7A4E6B48-9A78-4414-B6E2-BD36D07B65F6@apple.com>
Message-ID: <5F0711E4-09C6-4D6F-9D02-CFD98758B17F@apple.com>
Sounds good, just checking.
On Jan 14, 2011, at 2:19 PM, Stephen Wilson wrote:
> Greg Clayton writes:
>
>> Could a bootloader ELF file have an entry point of zero? Should this be:
>
> Interesting question. I have never seen one myself (but that does not
> mean they do not exist).
>
> However the spec specifically says that if an ELF does not have an entry
> point then this field must be zero. For that reason I think this should
> be a relatively safe test.
>
>
>> bool
>> ObjectFileELF::IsExecutable() const
>> {
>> return m_header.e_entry != LLDB_INVALID_ADDRESS;
>> }
>>
>> And then you would need to make sure that m_header.e_entry always gets initialized to LLDB_INVALID_ADDRESS?
>>
>>
>> On Jan 14, 2011, at 1:12 PM, Stephen Wilson wrote:
>>
>>> The previous check on header type ET_EXEC is not general enough. Position
>>> independent executables have type ET_DYN.
>>> ---
>>> source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 2 +-
>>> 1 files changed, 1 insertions(+), 1 deletions(-)
>>>
>>> diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
>>> index 5b99d01..f58c779 100644
>>> --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
>>> +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
>>> @@ -159,7 +159,7 @@ ObjectFileELF::~ObjectFileELF()
>>> bool
>>> ObjectFileELF::IsExecutable() const
>>> {
>>> - return m_header.e_type == ET_EXEC;
>>> + return m_header.e_entry != 0;
>>> }
>>>
>>> Address
>>> --
>>> 1.7.3.5
>>>
>>> _______________________________________________
>>> lldb-commits mailing list
>>> lldb-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
>>
>
>
>
> --
> steve
From gclayton at apple.com Fri Jan 14 17:49:08 2011
From: gclayton at apple.com (Greg Clayton)
Date: Fri, 14 Jan 2011 15:49:08 -0800
Subject: [Lldb-commits] [PATCH 6/8] Miscellaneous cleanups in
ProcessMonitor.
In-Reply-To:
References: <1295039542-9640-1-git-send-email-wilsons@start.ca>
<1295039542-9640-7-git-send-email-wilsons@start.ca>
<7962DEC7-6AA6-4021-B30B-AB8A8EA070F3@apple.com>
Message-ID: <5553927F-5974-41E7-A196-0D907609BB22@apple.com>
Yep, just make sure if the parent of the thread goes away, that it is sure to make the thread terminate otherwise the parent will delete the value in the auto_ptr and the still running thread might crash? Most of our code has a parent class object that might spawn a thread, then the parent object will pass itself (the "this" pointer to the thread), and the parent object ensures that the thread is shut down properly when it "void Clear()" is called on the object. The destructor of the parent object then calls Clear() to make sure the thread shuts down.
Then you can call accessors on the parent class object to get the LaunchArgs data. Feel free to take your own approch, but I just wanted to tell you what other code is commonly doing withing LLDB.
Greg Clayton
On Jan 14, 2011, at 2:57 PM, Stephen Wilson wrote:
> Greg Clayton writes:
>
>> The lifetime of args seems possibly racy? What if
>> "StartOperationThread()" spawns a thread which gets an error and exits
>> super quickly, could the thread put "args" into its auto_ptr and
>> delete "args" before the code that launches that thread is done with
>> "args"? I can't see all the code here, so I am just curious.
>
> I took another look over the code. You are right, there is a race if
> the monitor thread encounters an error when launching the inferior.
>
> This corrected patch uses the previous approach of having the parent
> thread maintain ownership. Holding onto the launch args in an auto_ptr
> should be safe here since we synchronize with the child thread via a
> semaphore, and the child does not reference the launch args beyond that
> point.
>
> Thanks for the review!
>
>
>
>
> Miscellaneous cleanups in ProcessMonitor.
>
> Propagate the environment if one is not provided. Also, do not allocate the
> monitor threads launch arguments on the stack.
>
> diff --git a/source/Plugins/Process/Linux/ProcessMonitor.cpp b/source/Plugins/Process/Linux/ProcessMonitor.cpp
> index 1522263..f21cb00 100644
> --- a/source/Plugins/Process/Linux/ProcessMonitor.cpp
> +++ b/source/Plugins/Process/Linux/ProcessMonitor.cpp
> @@ -463,8 +463,10 @@ ProcessMonitor::ProcessMonitor(ProcessLinux *process,
> m_client_fd(-1),
> m_server_fd(-1)
> {
> - LaunchArgs args(this, module, argv, envp,
> - stdin_path, stdout_path, stderr_path);
> + std::auto_ptr args;
> +
> + args.reset(new LaunchArgs(this, module, argv, envp,
> + stdin_path, stdout_path, stderr_path));
>
> // Server/client descriptors.
> if (!EnableIPC())
> @@ -473,13 +475,13 @@ ProcessMonitor::ProcessMonitor(ProcessLinux *process,
> error.SetErrorString("Monitor failed to initialize.");
> }
>
> - StartOperationThread(&args, error);
> + StartOperationThread(args.get(), error);
> if (!error.Success())
> return;
>
> WAIT_AGAIN:
> // Wait for the operation thread to initialize.
> - if (sem_wait(&args.m_semaphore))
> + if (sem_wait(&args->m_semaphore))
> {
> if (errno == EINTR)
> goto WAIT_AGAIN;
> @@ -491,16 +493,17 @@ WAIT_AGAIN:
> }
>
> // Check that the launch was a success.
> - if (!args.m_error.Success())
> + if (!args->m_error.Success())
> {
> StopOperationThread();
> - error = args.m_error;
> + error = args->m_error;
> return;
> }
>
> // Finally, start monitoring the child process for change in state.
> - if (!(m_monitor_thread = Host::StartMonitoringChildProcess(
> - ProcessMonitor::MonitorCallback, this, GetPID(), true)))
> + m_monitor_thread = Host::StartMonitoringChildProcess(
> + ProcessMonitor::MonitorCallback, this, GetPID(), true);
> + if (m_monitor_thread == LLDB_INVALID_HOST_THREAD)
> {
> error.SetErrorToGenericError();
> error.SetErrorString("Process launch failed.");
> @@ -574,6 +577,10 @@ ProcessMonitor::Launch(LaunchArgs *args)
>
> lldb::ThreadSP inferior;
>
> + // Propagate the environment if one is not supplied.
> + if (envp == NULL || envp[0] == NULL)
> + envp = const_cast(environ);
> +
> // Pseudo terminal setup.
> if (!terminal.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY, err_str, err_len))
> {
>
From gclayton at apple.com Fri Jan 14 17:49:40 2011
From: gclayton at apple.com (Greg Clayton)
Date: Fri, 14 Jan 2011 15:49:40 -0800
Subject: [Lldb-commits] [PATCH 8/8] Add empty implementation of pure
virtual RegisterContext::InvalidateAllRegisters.
In-Reply-To:
References: <1295039542-9640-1-git-send-email-wilsons@start.ca>
<1295039542-9640-9-git-send-email-wilsons@start.ca>
Message-ID:
Good to go.
On Jan 14, 2011, at 3:01 PM, Stephen Wilson wrote:
> Greg Clayton writes:
>
>> Here is where you will want to track if you have read your regiters
>> from what ever you read registers from on Linux.
>
> OK.
>
>> You might to just want to copy the
>> "lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_x86_64.cpp"
>> and
>> "lldb/source/Plugins/Process/MacOSX-User/source/RegisterContextMach_x86_64.h"
>> files and modify the structures to match linux. This has all of the
>> invalidating code done on a per/register group basis (gpr, fpu and exc
>> registers).
>
> Absolutely. Is it OK for this patch to go in as is? Since the method
> is pure virtual this empty implementation simply allows the tree to
> build. I will certainly look into implementing the method properly in
> the near future.
>
>
>>
>> On Jan 14, 2011, at 1:12 PM, Stephen Wilson wrote:
>>
>>> ---
>>> .../Process/Linux/RegisterContextLinux_x86_64.cpp | 5 +++++
>>> .../Process/Linux/RegisterContextLinux_x86_64.h | 3 +++
>>> 2 files changed, 8 insertions(+), 0 deletions(-)
>>>
>>> diff --git a/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp b/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp
>>> index da6ea8d..27cd6c6 100644
>>> --- a/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp
>>> +++ b/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp
>>> @@ -423,6 +423,11 @@ RegisterContextLinux_x86_64::Invalidate()
>>> {
>>> }
>>>
>>> +void
>>> +RegisterContextLinux_x86_64::InvalidateAllRegisters()
>>> +{
>>> +}
>>> +
>>> size_t
>>> RegisterContextLinux_x86_64::GetRegisterCount()
>>> {
>>> diff --git a/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h b/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h
>>> index dc421ec..876d685 100644
>>> --- a/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h
>>> +++ b/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h
>>> @@ -26,6 +26,9 @@ public:
>>> void
>>> Invalidate();
>>>
>>> + void
>>> + InvalidateAllRegisters();
>>> +
>>> size_t
>>> GetRegisterCount();
>>>
>>> --
>>> 1.7.3.5
>>>
>>> _______________________________________________
>>> lldb-commits mailing list
>>> lldb-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
>>
>
>
>
> --
> steve
From wilsons at start.ca Fri Jan 14 18:07:36 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Sat, 15 Jan 2011 00:07:36 -0000
Subject: [Lldb-commits] [lldb] r123495 - in
/lldb/trunk/source/Plugins/Process/Linux: LinuxThread.cpp LinuxThread.h
Message-ID: <20110115000736.CBC042A6C12C@llvm.org>
Author: wilsons
Date: Fri Jan 14 18:07:36 2011
New Revision: 123495
URL: http://llvm.org/viewvc/llvm-project?rev=123495&view=rev
Log:
Have LinuxThread cache it's current StopInfo object.
Modified:
lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp
lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h
Modified: lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp?rev=123495&r1=123494&r2=123495&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp Fri Jan 14 18:07:36 2011
@@ -26,6 +26,7 @@
LinuxThread::LinuxThread(Process &process, lldb::tid_t tid)
: Thread(process, tid),
m_frame_ap(0),
+ m_stop_info_id(0),
m_note(eNone)
{
}
@@ -40,6 +41,7 @@
void
LinuxThread::RefreshStateAfterStop()
{
+ RefreshPrivateStopReason();
}
const char *
@@ -101,24 +103,11 @@
lldb::StopInfoSP
LinuxThread::GetPrivateStopReason()
{
- lldb::StopInfoSP stop_info;
+ const uint32_t process_stop_id = GetProcess().GetStopID();
- switch (m_note)
- {
- default:
- break;
-
- case eBreak:
- stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(
- *this, m_breakpoint->GetID());
- break;
-
- case eTrace:
- stop_info = StopInfo::CreateStopReasonToTrace(*this);
- break;
- }
-
- return stop_info;
+ if (m_stop_info_id != process_stop_id || !m_stop_info || !m_stop_info->IsValid())
+ RefreshPrivateStopReason();
+ return m_stop_info;
}
Unwind *
@@ -196,3 +185,30 @@
{
m_note = eExit;
}
+
+void
+LinuxThread::RefreshPrivateStopReason()
+{
+ m_stop_info_id = GetProcess().GetStopID();
+
+ switch (m_note) {
+
+ default:
+ case eNone:
+ m_stop_info.reset();
+ break;
+
+ case eBreak:
+ m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(
+ *this, m_breakpoint->GetID());
+ break;
+
+ case eTrace:
+ m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
+ break;
+
+ case eExit:
+ m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, SIGCHLD);
+ break;
+ }
+}
Modified: lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h?rev=123495&r1=123494&r2=123495&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h Fri Jan 14 18:07:36 2011
@@ -72,6 +72,11 @@
std::auto_ptr m_frame_ap;
lldb::BreakpointSiteSP m_breakpoint;
+ lldb::StopInfoSP m_stop_info;
+
+ // Cached process stop id. Used to ensure we do not recalculate stop
+ // information/state needlessly.
+ uint32_t m_stop_info_id;
enum Notification {
eNone,
@@ -87,6 +92,9 @@
lldb::StopInfoSP
GetPrivateStopReason();
+ void
+ RefreshPrivateStopReason();
+
lldb_private::Unwind *
GetUnwinder();
};
From wilsons at start.ca Fri Jan 14 18:08:44 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Sat, 15 Jan 2011 00:08:44 -0000
Subject: [Lldb-commits] [lldb] r123496 - in
/lldb/trunk/source/Plugins/ObjectFile/ELF: ObjectFileELF.cpp
ObjectFileELF.h
Message-ID: <20110115000844.A032C2A6C12C@llvm.org>
Author: wilsons
Date: Fri Jan 14 18:08:44 2011
New Revision: 123496
URL: http://llvm.org/viewvc/llvm-project?rev=123496&view=rev
Log:
Implement GetEntryPoint, GetImageInfoAddress and GetArchitecture for ObjectFileELF.
Modified:
lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp?rev=123496&r1=123495&r2=123496&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp Fri Jan 14 18:08:44 2011
@@ -12,6 +12,7 @@
#include
#include
+#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/DataBuffer.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/FileSpecList.h"
@@ -70,9 +71,10 @@
unsigned address_size = ELFHeader::AddressSizeInBytes(magic);
if (address_size == 4 || address_size == 8)
{
- std::auto_ptr objfile_ap(
+ std::auto_ptr objfile_ap(
new ObjectFileELF(module, data_sp, file, offset, length));
- if (objfile_ap->ParseHeader())
+ ArchSpec spec = objfile_ap->GetArchitecture();
+ if (spec.IsValid() && objfile_ap->SetModulesArchitecture(spec))
return objfile_ap.release();
}
}
@@ -80,6 +82,15 @@
return NULL;
}
+ArchSpec
+ObjectFileELF::GetArchitecture()
+{
+ if (!ParseHeader())
+ return ArchSpec();
+
+ return ArchSpec(eArchTypeELF, m_header.e_machine, m_header.e_flags);
+}
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -151,6 +162,15 @@
return m_header.e_type == ET_EXEC;
}
+Address
+ObjectFileELF::GetEntryPoint() const
+{
+ if (m_header.e_entry)
+ return Address(NULL, m_header.e_entry);
+ else
+ return Address();
+}
+
ByteOrder
ObjectFileELF::GetByteOrder() const
{
@@ -208,6 +228,60 @@
return num_specs;
}
+Address
+ObjectFileELF::GetImageInfoAddress()
+{
+ if (!ParseSectionHeaders())
+ return Address();
+
+ user_id_t dynsym_id = 0;
+ for (SectionHeaderCollIter sh_pos = m_section_headers.begin();
+ sh_pos != m_section_headers.end(); ++sh_pos)
+ {
+ if (sh_pos->sh_type == SHT_DYNAMIC)
+ {
+ dynsym_id = SectionIndex(sh_pos);
+ break;
+ }
+ }
+
+ if (!dynsym_id)
+ return Address();
+
+ SectionList *section_list = GetSectionList();
+ if (!section_list)
+ return Address();
+
+ // Resolve the dynamic table entries.
+ Section *dynsym = section_list->FindSectionByID(dynsym_id).get();
+ if (!dynsym)
+ return Address();
+
+ DataExtractor dynsym_data;
+ if (dynsym->ReadSectionDataFromObjectFile(this, dynsym_data))
+ {
+ ELFDynamic symbol;
+ const unsigned section_size = dynsym_data.GetByteSize();
+ unsigned offset = 0;
+ unsigned cursor = 0;
+
+ // Look for a DT_DEBUG entry.
+ while (cursor < section_size)
+ {
+ offset = cursor;
+ if (!symbol.Parse(dynsym_data, &cursor))
+ break;
+
+ if (symbol.d_tag != DT_DEBUG)
+ continue;
+
+ return Address(dynsym, offset + sizeof(symbol.d_tag));
+ }
+ }
+
+ return Address();
+}
+
//----------------------------------------------------------------------
// ParseDependentModules
//----------------------------------------------------------------------
Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h?rev=123496&r1=123495&r2=123496&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h Fri Jan 14 18:08:44 2011
@@ -89,6 +89,9 @@
virtual bool
IsExecutable () const;
+ virtual lldb_private::Address
+ GetEntryPoint() const;
+
virtual size_t
GetAddressByteSize() const;
@@ -110,6 +113,12 @@
virtual uint32_t
GetDependentModules(lldb_private::FileSpecList& files);
+ virtual lldb_private::Address
+ GetImageInfoAddress();
+
+ lldb_private::ArchSpec
+ GetArchitecture();
+
private:
ObjectFileELF(lldb_private::Module* module,
lldb::DataBufferSP& dataSP,
From wilsons at start.ca Fri Jan 14 18:09:50 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Sat, 15 Jan 2011 00:09:50 -0000
Subject: [Lldb-commits] [lldb] r123498 -
/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
Message-ID: <20110115000950.F14A82A6C12C@llvm.org>
Author: wilsons
Date: Fri Jan 14 18:09:50 2011
New Revision: 123498
URL: http://llvm.org/viewvc/llvm-project?rev=123498&view=rev
Log:
Test if an ELF object is executable by checking if an entry point is defined.
The previous check on header type ET_EXEC is not general enough. Position
independent executables have type ET_DYN.
Modified:
lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp?rev=123498&r1=123497&r2=123498&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp Fri Jan 14 18:09:50 2011
@@ -159,7 +159,7 @@
bool
ObjectFileELF::IsExecutable() const
{
- return m_header.e_type == ET_EXEC;
+ return m_header.e_entry != 0;
}
Address
From wilsons at start.ca Fri Jan 14 18:10:37 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Sat, 15 Jan 2011 00:10:37 -0000
Subject: [Lldb-commits] [lldb] r123499 - in
/lldb/trunk/source/Plugins/Process/Linux: ProcessLinux.cpp ProcessLinux.h
Message-ID: <20110115001037.BC9C32A6C12C@llvm.org>
Author: wilsons
Date: Fri Jan 14 18:10:37 2011
New Revision: 123499
URL: http://llvm.org/viewvc/llvm-project?rev=123499&view=rev
Log:
Implement ProcessLinux::GetImageInfoAddress().
Modified:
lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp
lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h
Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp?rev=123499&r1=123498&r2=123499&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp Fri Jan 14 18:10:37 2011
@@ -149,6 +149,19 @@
return Error();
}
+addr_t
+ProcessLinux::GetImageInfoAddress()
+{
+ Target *target = &GetTarget();
+ ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
+ Address addr = obj_file->GetImageInfoAddress();
+
+ if (addr.IsValid())
+ return addr.GetLoadAddress(target);
+ else
+ return LLDB_INVALID_ADDRESS;
+}
+
Error
ProcessLinux::DoHalt(bool &caused_stop)
{
Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h?rev=123499&r1=123498&r2=123499&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h Fri Jan 14 18:10:37 2011
@@ -128,6 +128,9 @@
virtual lldb::ByteOrder
GetByteOrder() const;
+ virtual lldb::addr_t
+ GetImageInfoAddress();
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
From wilsons at start.ca Fri Jan 14 18:11:28 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Sat, 15 Jan 2011 00:11:28 -0000
Subject: [Lldb-commits] [lldb] r123500 -
/lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h
Message-ID: <20110115001128.E5BBA2A6C12C@llvm.org>
Author: wilsons
Date: Fri Jan 14 18:11:28 2011
New Revision: 123500
URL: http://llvm.org/viewvc/llvm-project?rev=123500&view=rev
Log:
Use the correct type for thread handle.
Modified:
lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h
Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h?rev=123500&r1=123499&r2=123500&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h Fri Jan 14 18:11:28 2011
@@ -140,7 +140,7 @@
lldb::pid_t m_pid;
int m_terminal_fd;
- uint32_t m_monitor_thread;
+ lldb::thread_t m_monitor_thread;
lldb_private::Mutex m_server_mutex;
int m_client_fd;
From wilsons at start.ca Fri Jan 14 18:12:41 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Sat, 15 Jan 2011 00:12:41 -0000
Subject: [Lldb-commits] [lldb] r123502 -
/lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp
Message-ID: <20110115001241.C13C42A6C12D@llvm.org>
Author: wilsons
Date: Fri Jan 14 18:12:41 2011
New Revision: 123502
URL: http://llvm.org/viewvc/llvm-project?rev=123502&view=rev
Log:
Miscellaneous cleanups in ProcessMonitor.
Propagate the environment if one is not provided. Also, do not allocate the
monitor threads launch arguments on the stack.
Modified:
lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp
Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp?rev=123502&r1=123501&r2=123502&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp Fri Jan 14 18:12:41 2011
@@ -463,8 +463,10 @@
m_client_fd(-1),
m_server_fd(-1)
{
- LaunchArgs args(this, module, argv, envp,
- stdin_path, stdout_path, stderr_path);
+ std::auto_ptr args;
+
+ args.reset(new LaunchArgs(this, module, argv, envp,
+ stdin_path, stdout_path, stderr_path));
// Server/client descriptors.
if (!EnableIPC())
@@ -473,13 +475,13 @@
error.SetErrorString("Monitor failed to initialize.");
}
- StartOperationThread(&args, error);
+ StartOperationThread(args.get(), error);
if (!error.Success())
return;
WAIT_AGAIN:
// Wait for the operation thread to initialize.
- if (sem_wait(&args.m_semaphore))
+ if (sem_wait(&args->m_semaphore))
{
if (errno == EINTR)
goto WAIT_AGAIN;
@@ -491,16 +493,17 @@
}
// Check that the launch was a success.
- if (!args.m_error.Success())
+ if (!args->m_error.Success())
{
StopOperationThread();
- error = args.m_error;
+ error = args->m_error;
return;
}
// Finally, start monitoring the child process for change in state.
- if (!(m_monitor_thread = Host::StartMonitoringChildProcess(
- ProcessMonitor::MonitorCallback, this, GetPID(), true)))
+ m_monitor_thread = Host::StartMonitoringChildProcess(
+ ProcessMonitor::MonitorCallback, this, GetPID(), true);
+ if (m_monitor_thread == LLDB_INVALID_HOST_THREAD)
{
error.SetErrorToGenericError();
error.SetErrorString("Process launch failed.");
@@ -574,6 +577,10 @@
lldb::ThreadSP inferior;
+ // Propagate the environment if one is not supplied.
+ if (envp == NULL || envp[0] == NULL)
+ envp = const_cast(environ);
+
// Pseudo terminal setup.
if (!terminal.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY, err_str, err_len))
{
From wilsons at start.ca Fri Jan 14 18:13:27 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Sat, 15 Jan 2011 00:13:27 -0000
Subject: [Lldb-commits] [lldb] r123503 -
/lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp
Message-ID: <20110115001327.DCD592A6C12C@llvm.org>
Author: wilsons
Date: Fri Jan 14 18:13:27 2011
New Revision: 123503
URL: http://llvm.org/viewvc/llvm-project?rev=123503&view=rev
Log:
Set the ID of a ProcessLinux instance to the PID of the inferior on launch.
Modified:
lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp
Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp?rev=123503&r1=123502&r2=123503&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp Fri Jan 14 18:13:27 2011
@@ -124,6 +124,7 @@
if (!error.Success())
return error;
+ SetID(m_monitor->GetPID());
return error;
}
From wilsons at start.ca Fri Jan 14 18:15:12 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Sat, 15 Jan 2011 00:15:12 -0000
Subject: [Lldb-commits] [lldb] r123504 - in
/lldb/trunk/source/Plugins/Process/Linux: RegisterContextLinux_x86_64.cpp
RegisterContextLinux_x86_64.h
Message-ID: <20110115001513.02CF92A6C12C@llvm.org>
Author: wilsons
Date: Fri Jan 14 18:15:12 2011
New Revision: 123504
URL: http://llvm.org/viewvc/llvm-project?rev=123504&view=rev
Log:
Add empty implementation of pure virtual RegisterContext::InvalidateAllRegisters.
This patch simply allows the tree to build. A proper implementation still needs
to be provided.
Modified:
lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp
lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h
Modified: lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp?rev=123504&r1=123503&r2=123504&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp Fri Jan 14 18:15:12 2011
@@ -423,6 +423,11 @@
{
}
+void
+RegisterContextLinux_x86_64::InvalidateAllRegisters()
+{
+}
+
size_t
RegisterContextLinux_x86_64::GetRegisterCount()
{
Modified: lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h?rev=123504&r1=123503&r2=123504&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h Fri Jan 14 18:15:12 2011
@@ -26,6 +26,9 @@
void
Invalidate();
+ void
+ InvalidateAllRegisters();
+
size_t
GetRegisterCount();
From gclayton at apple.com Fri Jan 14 19:32:14 2011
From: gclayton at apple.com (Greg Clayton)
Date: Sat, 15 Jan 2011 01:32:14 -0000
Subject: [Lldb-commits] [lldb] r123507 -
/lldb/trunk/source/Expression/ClangExpressionParser.cpp
Message-ID: <20110115013214.446242A6C12C@llvm.org>
Author: gclayton
Date: Fri Jan 14 19:32:14 2011
New Revision: 123507
URL: http://llvm.org/viewvc/llvm-project?rev=123507&view=rev
Log:
Enabled ObjC 2 abilities for expressions. We will enable the fragile ivar
stuff soon when we get a fix for looking up the "OBJC_IVAR_$_Class.ivar"
style symbols into IRForTarget::ResolveExternals() next week.
Modified:
lldb/trunk/source/Expression/ClangExpressionParser.cpp
Modified: lldb/trunk/source/Expression/ClangExpressionParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionParser.cpp?rev=123507&r1=123506&r2=123507&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionParser.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionParser.cpp Fri Jan 14 19:32:14 2011
@@ -207,7 +207,15 @@
// Parse expressions as Objective C++ regardless of context.
// Our hook into Clang's lookup mechanism only works in C++.
m_compiler->getLangOpts().CPlusPlus = true;
+
+ // Setup objective C
m_compiler->getLangOpts().ObjC1 = true;
+ m_compiler->getLangOpts().ObjC2 = true;
+ // We need to enable the fragile ABI for things target triples that
+ // support it.
+// m_compiler->getLangOpts().ObjCNonFragileABI = true; // NOT i386
+// m_compiler->getLangOpts().ObjCNonFragileABI2 = true; // NOT i386
+
m_compiler->getLangOpts().ThreadsafeStatics = false;
m_compiler->getLangOpts().AccessControl = false; // Debuggers get universal access
m_compiler->getLangOpts().DollarIdents = true; // $ indicates a persistent variable name
From gclayton at apple.com Fri Jan 14 20:52:14 2011
From: gclayton at apple.com (Greg Clayton)
Date: Sat, 15 Jan 2011 02:52:14 -0000
Subject: [Lldb-commits] [lldb] r123509 - in /lldb/trunk:
include/lldb/lldb-enumerations.h source/Core/DataExtractor.cpp
source/Symbol/ClangASTContext.cpp source/Symbol/ClangASTType.cpp
Message-ID: <20110115025214.84D542A6C12C@llvm.org>
Author: gclayton
Date: Fri Jan 14 20:52:14 2011
New Revision: 123509
URL: http://llvm.org/viewvc/llvm-project?rev=123509&view=rev
Log:
Added complete complex support for displaying and parsing complex types.
Modified:
lldb/trunk/include/lldb/lldb-enumerations.h
lldb/trunk/source/Core/DataExtractor.cpp
lldb/trunk/source/Symbol/ClangASTContext.cpp
lldb/trunk/source/Symbol/ClangASTType.cpp
Modified: lldb/trunk/include/lldb/lldb-enumerations.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-enumerations.h?rev=123509&r1=123508&r2=123509&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-enumerations.h (original)
+++ lldb/trunk/include/lldb/lldb-enumerations.h Fri Jan 14 20:52:14 2011
@@ -148,7 +148,8 @@
eFormatBytesWithASCII,
eFormatChar,
eFormatCharPrintable, // Only printable characters, space if not printable
- eFormatComplex,
+ eFormatComplex, // Floating point complex type
+ eFormatComplexFloat = eFormatComplex,
eFormatCString, // NULL terminated C strings
eFormatDecimal,
eFormatEnum,
@@ -171,7 +172,8 @@
eFormatVectorOfUInt64,
eFormatVectorOfFloat32,
eFormatVectorOfFloat64,
- eFormatVectorOfUInt128
+ eFormatVectorOfUInt128,
+ eFormatComplexInteger, // Integer complex type
} Format;
Modified: lldb/trunk/source/Core/DataExtractor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/DataExtractor.cpp?rev=123509&r1=123508&r2=123509&view=diff
==============================================================================
--- lldb/trunk/source/Core/DataExtractor.cpp (original)
+++ lldb/trunk/source/Core/DataExtractor.cpp Fri Jan 14 20:52:14 2011
@@ -1390,6 +1390,19 @@
s->Address(GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset), sizeof (addr_t));
break;
+
+ case eFormatComplexInteger:
+ {
+ uint32_t complex_int_byte_size = item_byte_size / 2;
+
+ if (complex_int_byte_size <= 8)
+ {
+ s->Printf("%llu", GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0));
+ s->Printf(" + %llui", GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0));
+ }
+ }
+ break;
+
case eFormatComplex:
if (sizeof(float) * 2 == item_byte_size)
{
@@ -1414,9 +1427,12 @@
s->Printf ("%Lg + %Lgi", ld64_1, ld64_2);
break;
}
-
- // Fall through to hex for any other sizes
- item_format = eFormatHex;
+ else
+ {
+ s->Printf ("unsupported complex float byte size %u", item_byte_size);
+ return start_offset;
+ }
+ break;
default:
case eFormatDefault:
Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=123509&r1=123508&r2=123509&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTContext.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTContext.cpp Fri Jan 14 20:52:14 2011
@@ -548,13 +548,27 @@
return ast_context->UnsignedIntTy.getAsOpaquePtr();
break;
+ case DW_ATE_lo_user:
+ // This has been seen to mean DW_AT_complex_integer
+ if (strcmp(type_name, "complex") == 0)
+ {
+ clang_type_t complex_int_clang_type = GetBuiltinTypeForDWARFEncodingAndBitSize ("int", DW_ATE_signed, bit_size/2);
+ return ast_context->getComplexType (QualType::getFromOpaquePtr(complex_int_clang_type)).getAsOpaquePtr();
+ }
+ break;
+
case DW_ATE_complex_float:
if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->FloatComplexTy))
return ast_context->FloatComplexTy.getAsOpaquePtr();
- if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->DoubleComplexTy))
+ else if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->DoubleComplexTy))
return ast_context->DoubleComplexTy.getAsOpaquePtr();
- if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->LongDoubleComplexTy))
+ else if (QualTypeMatchesBitSize (bit_size, ast_context, ast_context->LongDoubleComplexTy))
return ast_context->LongDoubleComplexTy.getAsOpaquePtr();
+ else
+ {
+ clang_type_t complex_float_clang_type = GetBuiltinTypeForDWARFEncodingAndBitSize ("float", DW_ATE_float, bit_size/2);
+ return ast_context->getComplexType (QualType::getFromOpaquePtr(complex_float_clang_type)).getAsOpaquePtr();
+ }
break;
case DW_ATE_float:
@@ -1773,7 +1787,7 @@
*pointee_or_element_clang_type = qual_type->getPointeeType().getAsOpaquePtr();
return eTypeIsPointer | eTypeHasChildren | eTypeIsBlock;
- case clang::Type::Complex: return eTypeHasChildren | eTypeIsBuiltIn | eTypeHasValue;
+ case clang::Type::Complex: return eTypeIsBuiltIn | eTypeHasValue;
case clang::Type::ConstantArray:
case clang::Type::DependentSizedArray:
@@ -1902,8 +1916,7 @@
}
break;
- case clang::Type::Complex:
- return 2;
+ case clang::Type::Complex: return 0;
case clang::Type::Record:
if (ClangASTType::IsDefined (clang_qual_type))
@@ -2090,7 +2103,7 @@
}
break;
- case clang::Type::Complex: return 2;
+ case clang::Type::Complex: return 1;
case clang::Type::Pointer: return 1;
case clang::Type::BlockPointer: return 0; // If block pointers don't have debug info, then no children for them
case clang::Type::LValueReference: return 1;
Modified: lldb/trunk/source/Symbol/ClangASTType.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTType.cpp?rev=123509&r1=123508&r2=123509&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTType.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTType.cpp Fri Jan 14 20:52:14 2011
@@ -177,10 +177,22 @@
case clang::Type::LValueReference:
case clang::Type::RValueReference:
case clang::Type::MemberPointer: return lldb::eEncodingUint;
- // Complex numbers are made up of floats
case clang::Type::Complex:
- count = 2;
- return lldb::eEncodingIEEE754;
+ {
+ lldb::Encoding encoding = lldb::eEncodingIEEE754;
+ if (qual_type->isComplexType())
+ encoding = lldb::eEncodingIEEE754;
+ else
+ {
+ const clang::ComplexType *complex_type = qual_type->getAsComplexIntegerType();
+ if (complex_type)
+ encoding = GetEncoding (complex_type->getElementType().getAsOpaquePtr(), count);
+ else
+ encoding = lldb::eEncodingSint;
+ }
+ count = 2;
+ return encoding;
+ }
case clang::Type::ObjCInterface: break;
case clang::Type::Record: break;
@@ -270,7 +282,13 @@
case clang::Type::LValueReference:
case clang::Type::RValueReference: return lldb::eFormatHex;
case clang::Type::MemberPointer: break;
- case clang::Type::Complex: return lldb::eFormatComplex;
+ case clang::Type::Complex:
+ {
+ if (qual_type->isComplexType())
+ return lldb::eFormatComplex;
+ else
+ return lldb::eFormatComplexInteger;
+ }
case clang::Type::ObjCInterface: break;
case clang::Type::Record: break;
case clang::Type::Enum: return lldb::eFormatEnum;
From gclayton at apple.com Fri Jan 14 21:06:23 2011
From: gclayton at apple.com (Greg Clayton)
Date: Sat, 15 Jan 2011 03:06:23 -0000
Subject: [Lldb-commits] [lldb] r123513 - in /lldb/trunk:
lldb.xcodeproj/project.pbxproj resources/LLDB-Info.plist
tools/debugserver/debugserver.xcodeproj/project.pbxproj
Message-ID: <20110115030623.347452A6C12C@llvm.org>
Author: gclayton
Date: Fri Jan 14 21:06:23 2011
New Revision: 123513
URL: http://llvm.org/viewvc/llvm-project?rev=123513&view=rev
Log:
lldb-41 and debugserver-126 are set in the Xcode projects.
Modified:
lldb/trunk/lldb.xcodeproj/project.pbxproj
lldb/trunk/resources/LLDB-Info.plist
lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj
Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=123513&r1=123512&r2=123513&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/lldb.xcodeproj/project.pbxproj Fri Jan 14 21:06:23 2011
@@ -2926,9 +2926,9 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 40;
+ CURRENT_PROJECT_VERSION = 41;
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 40;
+ DYLIB_CURRENT_VERSION = 41;
EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -2978,11 +2978,11 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 40;
+ CURRENT_PROJECT_VERSION = 41;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 40;
+ DYLIB_CURRENT_VERSION = 41;
EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -3052,7 +3052,7 @@
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = YES;
- CURRENT_PROJECT_VERSION = 40;
+ CURRENT_PROJECT_VERSION = 41;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -3087,11 +3087,11 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
COPY_PHASE_STRIP = YES;
- CURRENT_PROJECT_VERSION = 40;
+ CURRENT_PROJECT_VERSION = 41;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 40;
+ DYLIB_CURRENT_VERSION = 41;
EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -3140,7 +3140,7 @@
buildSettings = {
CODE_SIGN_IDENTITY = lldb_codesign;
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 40;
+ CURRENT_PROJECT_VERSION = 41;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"",
@@ -3178,7 +3178,7 @@
);
CODE_SIGN_IDENTITY = lldb_codesign;
COPY_PHASE_STRIP = YES;
- CURRENT_PROJECT_VERSION = 40;
+ CURRENT_PROJECT_VERSION = 41;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
Modified: lldb/trunk/resources/LLDB-Info.plist
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/resources/LLDB-Info.plist?rev=123513&r1=123512&r2=123513&view=diff
==============================================================================
--- lldb/trunk/resources/LLDB-Info.plist (original)
+++ lldb/trunk/resources/LLDB-Info.plist Fri Jan 14 21:06:23 2011
@@ -17,7 +17,7 @@
CFBundleSignature
????
CFBundleVersion
- 40
+ 41
CFBundleName
${EXECUTABLE_NAME}
Modified: lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj?rev=123513&r1=123512&r2=123513&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj (original)
+++ lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj Fri Jan 14 21:06:23 2011
@@ -460,7 +460,7 @@
i386,
);
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 125;
+ CURRENT_PROJECT_VERSION = 126;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
STRIP_INSTALLED_PRODUCT = NO;
@@ -478,7 +478,7 @@
x86_64,
i386,
);
- CURRENT_PROJECT_VERSION = 125;
+ CURRENT_PROJECT_VERSION = 126;
DEAD_CODE_STRIPPING = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
@@ -498,7 +498,7 @@
x86_64,
i386,
);
- CURRENT_PROJECT_VERSION = 125;
+ CURRENT_PROJECT_VERSION = 126;
DEAD_CODE_STRIPPING = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
@@ -515,7 +515,7 @@
buildSettings = {
"CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]" = "source/debugserver-entitlements.plist";
COPY_PHASE_STRIP = YES;
- CURRENT_PROJECT_VERSION = 125;
+ CURRENT_PROJECT_VERSION = 126;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks;
"FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = (
@@ -556,7 +556,7 @@
"CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]" = "source/debugserver-entitlements.plist";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = lldb_codesign;
COPY_PHASE_STRIP = YES;
- CURRENT_PROJECT_VERSION = 125;
+ CURRENT_PROJECT_VERSION = 126;
FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks;
"FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = (
"$(SDKROOT)/System/Library/PrivateFrameworks",
@@ -597,7 +597,7 @@
"CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]" = "source/debugserver-entitlements.plist";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = lldb_codesign;
COPY_PHASE_STRIP = YES;
- CURRENT_PROJECT_VERSION = 125;
+ CURRENT_PROJECT_VERSION = 126;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks;
"FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = (
From wilsons at start.ca Sat Jan 15 13:31:28 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Sat, 15 Jan 2011 14:31:28 -0500
Subject: [Lldb-commits] [PATCH] linux: Make a mandatory call to
DestroyThread() in ~LinuxThread()
Message-ID:
diff --git a/source/Plugins/Process/Linux/LinuxThread.cpp b/source/Plugins/Process/Linux/LinuxThread.cpp
index caed8e1..de1ca51 100644
--- a/source/Plugins/Process/Linux/LinuxThread.cpp
+++ b/source/Plugins/Process/Linux/LinuxThread.cpp
@@ -31,6 +31,11 @@ LinuxThread::LinuxThread(Process &process, lldb::tid_t tid)
{
}
+LinuxThread::~LinuxThread()
+{
+ DestroyThread();
+}
+
ProcessMonitor &
LinuxThread::GetMonitor()
{
diff --git a/source/Plugins/Process/Linux/LinuxThread.h b/source/Plugins/Process/Linux/LinuxThread.h
index 7e30f0a..c7f29ca 100644
--- a/source/Plugins/Process/Linux/LinuxThread.h
+++ b/source/Plugins/Process/Linux/LinuxThread.h
@@ -29,6 +29,8 @@ class LinuxThread
public:
LinuxThread(lldb_private::Process &process, lldb::tid_t tid);
+ virtual ~LinuxThread();
+
void
RefreshStateAfterStop();
From wilsons at start.ca Sat Jan 15 13:40:42 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Sat, 15 Jan 2011 14:40:42 -0500
Subject: [Lldb-commits] [PATCH][RFC] Linux DynamicLoader plugin.
Message-ID:
This patch is enough to have shared objects recognized by LLDB on Linux.
We can handle position independent executables. We can handle
dynamically loaded modules brought in via dlopen.
The DYLDRendezvous class provides an interface to a structure present in
the address space of ELF-based processes. This structure provides the
location of a function which is called by the runtime linker each time a
shared object is loaded and unloaded (thus a breakpoint at that address
will let LLDB intercept such events), a list of entries describing the
currently loaded shared objects, plus a few other things.
On Linux, processes are brought up with an auxiliary vector on the
stack. One element in this vector contains the (possibly dynamic) entry
address of the process. One does not need to walk the stack to find
this information as it is available under /proc//auxv. The new
AuxVector class provides a convenient read-only view of this auxiliary
information. We use the dynamic entry address and the address as
specified in the object file to compute the actual load address of the
inferior image. This strategy works for both normal executables and
PIE's.
As most of this code is new the following diff might not be the most
readable. One can also browse the files online here:
https://github.com/eightcien/lldb/tree/lldb-linux/source/Plugins/DynamicLoader/Linux-DYLD
---
lib/Makefile | 3 +-
.../Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp | 191 ++++++++++
.../Plugins/DynamicLoader/Linux-DYLD/AuxVector.h | 97 +++++
.../DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp | 315 +++++++++++++++++
.../DynamicLoader/Linux-DYLD/DYLDRendezvous.h | 227 ++++++++++++
.../Linux-DYLD/DynamicLoaderLinuxDYLD.cpp | 371 ++++++++++++++++++++
.../Linux-DYLD/DynamicLoaderLinuxDYLD.h | 165 +++++++++
source/Plugins/DynamicLoader/Linux-DYLD/Makefile | 14 +
source/Plugins/Makefile | 2 +-
source/Plugins/Process/Linux/ProcessLinux.cpp | 27 ++
source/Plugins/Process/Linux/ProcessLinux.h | 12 +
source/lldb.cpp | 3 +
12 files changed, 1425 insertions(+), 2 deletions(-)
create mode 100644 source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp
create mode 100644 source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h
create mode 100644 source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp
create mode 100644 source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h
create mode 100644 source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp
create mode 100644 source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h
create mode 100644 source/Plugins/DynamicLoader/Linux-DYLD/Makefile
diff --git a/lib/Makefile b/lib/Makefile
index 881b23c..abd9c1d 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -67,7 +67,8 @@ ifeq ($(HOST_OS),Darwin)
endif
ifeq ($(HOST_OS),Linux)
- USEDLIBS += lldbPluginProcessLinux.a
+ USEDLIBS += lldbPluginProcessLinux.a \
+ lldbPluginDynamicLoaderLinux.a
endif
include $(LEVEL)/Makefile.common
diff --git a/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp b/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp
new file mode 100644
index 0000000..6954e4c
--- /dev/null
+++ b/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp
@@ -0,0 +1,191 @@
+//===-- AuxVector.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+#include
+#include
+#include
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Target/Process.h"
+
+#include "AuxVector.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static bool
+GetMaxU64(DataExtractor &data,
+ uint32_t *offset, uint64_t *value, unsigned int byte_size)
+{
+ uint32_t saved_offset = *offset;
+ *value = data.GetMaxU64(offset, byte_size);
+ return *offset != saved_offset;
+}
+
+static bool
+ParseAuxvEntry(DataExtractor &data, AuxVector::Entry &entry,
+ uint32_t *offset, unsigned int byte_size)
+{
+ if (!GetMaxU64(data, offset, &entry.type, byte_size))
+ return false;
+
+ if (!GetMaxU64(data, offset, &entry.value, byte_size))
+ return false;
+
+ return true;
+}
+
+DataBufferSP
+AuxVector::GetAuxvData()
+{
+ static const size_t path_size = 128;
+ static char path[path_size];
+ DataBufferSP buf_sp;
+ int fd;
+
+ // Ideally, we would simply create a FileSpec and call ReadFileContents.
+ // However, files in procfs have zero size (since they are, in general,
+ // dynamically generated by the kernel) which is incompatible with the
+ // current ReadFileContents implementation. Therefore we simply stream the
+ // data into a DataBuffer ourselves.
+ if (snprintf(path, path_size, "/proc/%d/auxv", m_process->GetID()) < 0)
+ return buf_sp;
+
+ if ((fd = open(path, O_RDONLY, 0)) < 0)
+ return buf_sp;
+
+ size_t bytes_read = 0;
+ std::auto_ptr buf_ap(new DataBufferHeap(1024, 0));
+ for (;;)
+ {
+ size_t avail = buf_ap->GetByteSize() - bytes_read;
+ ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail);
+
+ if (status < 0)
+ break;
+
+ bytes_read += status;
+
+ if (status == 0)
+ {
+ buf_ap->SetByteSize(bytes_read);
+ buf_sp.reset(buf_ap.release());
+ break;
+ }
+
+ if (avail - status == 0)
+ buf_ap->SetByteSize(2 * buf_ap->GetByteSize());
+ }
+
+ return buf_sp;
+}
+
+void
+AuxVector::ParseAuxv(DataExtractor &data)
+{
+ const unsigned int byte_size = m_process->GetAddressByteSize();
+ uint32_t offset = 0;
+
+ for (;;)
+ {
+ Entry entry;
+
+ if (!ParseAuxvEntry(data, entry, &offset, byte_size))
+ break;
+
+ if (entry.type == AT_NULL)
+ break;
+
+ if (entry.type == AT_IGNORE)
+ continue;
+
+ m_auxv.push_back(entry);
+ }
+}
+
+AuxVector::AuxVector(Process *process)
+ : m_process(process)
+{
+ DataExtractor data;
+ LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+
+ data.SetData(GetAuxvData());
+ data.SetByteOrder(m_process->GetByteOrder());
+ data.SetAddressByteSize(m_process->GetAddressByteSize());
+
+ ParseAuxv(data);
+
+ if (log)
+ DumpToLog(log);
+}
+
+AuxVector::iterator
+AuxVector::FindEntry(EntryType type) const
+{
+ for (iterator I = begin(); I != end(); ++I)
+ {
+ if (I->type == static_cast(type))
+ return I;
+ }
+
+ return end();
+}
+
+void
+AuxVector::DumpToLog(LogSP log) const
+{
+ if (!log)
+ return;
+
+ log->PutCString("AuxVector: ");
+ for (iterator I = begin(); I != end(); ++I)
+ {
+ log->Printf(" %s [%d]: %lx", GetEntryName(*I), I->type, I->value);
+ }
+}
+
+const char *
+AuxVector::GetEntryName(EntryType type)
+{
+ const char *name;
+
+#define ENTRY_NAME(_type) _type: name = #_type
+ switch (type)
+ {
+ default:
+ name = "unkown";
+ break;
+
+ case ENTRY_NAME(AT_NULL); break;
+ case ENTRY_NAME(AT_IGNORE); break;
+ case ENTRY_NAME(AT_EXECFD); break;
+ case ENTRY_NAME(AT_PHDR); break;
+ case ENTRY_NAME(AT_PHENT); break;
+ case ENTRY_NAME(AT_PHNUM); break;
+ case ENTRY_NAME(AT_PAGESZ); break;
+ case ENTRY_NAME(AT_BASE); break;
+ case ENTRY_NAME(AT_FLAGS); break;
+ case ENTRY_NAME(AT_ENTRY); break;
+ case ENTRY_NAME(AT_NOTELF); break;
+ case ENTRY_NAME(AT_UID); break;
+ case ENTRY_NAME(AT_EUID); break;
+ case ENTRY_NAME(AT_GID); break;
+ case ENTRY_NAME(AT_EGID); break;
+ case ENTRY_NAME(AT_CLKTCK); break;
+ }
+#undef ENTRY_NAME
+
+ return name;
+}
+
diff --git a/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h b/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h
new file mode 100644
index 0000000..7a5b370
--- /dev/null
+++ b/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h
@@ -0,0 +1,97 @@
+//===-- AuxVector.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_AuxVector_H_
+#define liblldb_AuxVector_H_
+
+// C Includes
+// C++ Includes
+#include
+
+// Other libraries and framework includes
+#include "lldb/lldb-forward-rtti.h"
+
+namespace lldb_private {
+class DataExtractor;
+}
+
+/// @class AuxVector
+/// @brief Represents a processes auxiliary vector.
+///
+/// When a process is loaded on Linux a vector of values is placed onto the
+/// stack communicating operating system specific information. On construction
+/// this class locates and parses this information and provides a simple
+/// read-only interface to the entries found.
+class AuxVector {
+
+public:
+ AuxVector(lldb_private::Process *process);
+
+ struct Entry {
+ uint64_t type;
+ uint64_t value;
+
+ Entry() : type(0), value(0) { }
+ };
+
+ /// Constants describing the type of entry.
+ enum EntryType {
+ AT_NULL = 0, ///< End of auxv.
+ AT_IGNORE = 1, ///< Ignore entry.
+ AT_EXECFD = 2, ///< File descriptor of program.
+ AT_PHDR = 3, ///< Program headers.
+ AT_PHENT = 4, ///< Size of program header.
+ AT_PHNUM = 5, ///< Number of program headers.
+ AT_PAGESZ = 6, ///< Page size.
+ AT_BASE = 7, ///< Interpreter base address.
+ AT_FLAGS = 8, ///< Flags.
+ AT_ENTRY = 9, ///< Program entry point.
+ AT_NOTELF = 10, ///< Set if program is not an ELF.
+ AT_UID = 11, ///< UID.
+ AT_EUID = 12, ///< Effective UID.
+ AT_GID = 13, ///< GID.
+ AT_EGID = 14, ///< Effective GID.
+ AT_CLKTCK = 17 ///< Clock frequency (e.g. times(2)).
+ };
+
+private:
+ typedef std::vector EntryVector;
+
+public:
+ typedef EntryVector::const_iterator iterator;
+
+ iterator begin() const { return m_auxv.begin(); }
+ iterator end() const { return m_auxv.end(); }
+
+ iterator
+ FindEntry(EntryType type) const;
+
+ static const char *
+ GetEntryName(const Entry &entry) {
+ return GetEntryName(static_cast(entry.type));
+ }
+
+ static const char *
+ GetEntryName(EntryType type);
+
+ void
+ DumpToLog(lldb::LogSP log) const;
+
+private:
+ lldb_private::Process *m_process;
+ EntryVector m_auxv;
+
+ lldb::DataBufferSP
+ GetAuxvData();
+
+ void
+ ParseAuxv(lldb_private::DataExtractor &data);
+};
+
+#endif
diff --git a/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp
new file mode 100644
index 0000000..8b4795d
--- /dev/null
+++ b/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp
@@ -0,0 +1,315 @@
+//===-- DYLDRendezvous.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "DYLDRendezvous.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+/// Locates the address of the rendezvous structure. Returns the address on
+/// success and LLDB_INVALID_ADDRESS on failure.
+static addr_t
+ResolveRendezvousAddress(Process *process)
+{
+ addr_t info_location;
+ addr_t info_addr;
+ Error error;
+ size_t size;
+
+ info_location = process->GetImageInfoAddress();
+
+ if (info_location == LLDB_INVALID_ADDRESS)
+ return LLDB_INVALID_ADDRESS;
+
+ info_addr = 0;
+ size = process->DoReadMemory(info_location, &info_addr,
+ process->GetAddressByteSize(), error);
+ if (size != process->GetAddressByteSize() || error.Fail())
+ return LLDB_INVALID_ADDRESS;
+
+ if (info_addr == 0)
+ return LLDB_INVALID_ADDRESS;
+
+ return info_addr;
+}
+
+DYLDRendezvous::DYLDRendezvous(Process *process)
+ : m_process(process),
+ m_rendezvous_addr(LLDB_INVALID_ADDRESS),
+ m_current(),
+ m_previous(),
+ m_soentries(),
+ m_added_soentries(),
+ m_removed_soentries()
+{
+}
+
+bool
+DYLDRendezvous::Resolve()
+{
+ const size_t word_size = 4;
+ Rendezvous info;
+ size_t address_size;
+ size_t padding;
+ addr_t info_addr;
+ addr_t cursor;
+
+ address_size = m_process->GetAddressByteSize();
+ padding = address_size - word_size;
+
+ if (m_rendezvous_addr == LLDB_INVALID_ADDRESS)
+ cursor = info_addr = ResolveRendezvousAddress(m_process);
+ else
+ cursor = info_addr = m_rendezvous_addr;
+
+ if (cursor == LLDB_INVALID_ADDRESS)
+ return false;
+
+ if (!(cursor = ReadMemory(cursor, &info.version, word_size)))
+ return false;
+
+ if (!(cursor = ReadMemory(cursor + padding, &info.map_addr, address_size)))
+ return false;
+
+ if (!(cursor = ReadMemory(cursor, &info.brk, address_size)))
+ return false;
+
+ if (!(cursor = ReadMemory(cursor, &info.state, word_size)))
+ return false;
+
+ if (!(cursor = ReadMemory(cursor + padding, &info.ldbase, address_size)))
+ return false;
+
+ // The rendezvous was successfully read. Update our internal state.
+ m_rendezvous_addr = info_addr;
+ m_previous = m_current;
+ m_current = info;
+
+ return UpdateSOEntries();
+}
+
+bool
+DYLDRendezvous::IsValid()
+{
+ return m_rendezvous_addr != LLDB_INVALID_ADDRESS;
+}
+
+bool
+DYLDRendezvous::UpdateSOEntries()
+{
+ SOEntry entry;
+
+ if (m_current.map_addr == 0)
+ return false;
+
+ // If we are about to add or remove a shared object clear out the current
+ // state and take a snapshot of the currently loaded images.
+ if (m_current.state == eAdd || m_current.state == eDelete)
+ {
+ assert(m_previous.state == eConsistent);
+ m_soentries.clear();
+ m_added_soentries.clear();
+ m_removed_soentries.clear();
+ return TakeSnapshot(m_soentries);
+ }
+
+ // Otherwise check the previous state to determine what to expect and update
+ // accordingly.
+ if (m_previous.state == eAdd)
+ return UpdateSOEntriesForAddition();
+ else if (m_previous.state == eDelete)
+ return UpdateSOEntriesForDeletion();
+
+ return false;
+}
+
+bool
+DYLDRendezvous::UpdateSOEntriesForAddition()
+{
+ SOEntry entry;
+ iterator pos;
+
+ assert(m_previous.state == eAdd);
+
+ if (m_current.map_addr == 0)
+ return false;
+
+ for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
+ {
+ if (!ReadSOEntryFromMemory(cursor, entry))
+ return false;
+
+ if (entry.path.empty())
+ continue;
+
+ pos = std::find(m_soentries.begin(), m_soentries.end(), entry);
+ if (pos == m_soentries.end())
+ {
+ m_soentries.push_back(entry);
+ m_added_soentries.push_back(entry);
+ }
+ }
+
+ return true;
+}
+
+bool
+DYLDRendezvous::UpdateSOEntriesForDeletion()
+{
+ SOEntryList entry_list;
+ iterator pos;
+
+ assert(m_previous.state == eDelete);
+
+ if (!TakeSnapshot(entry_list))
+ return false;
+
+ for (iterator I = begin(); I != end(); ++I)
+ {
+ pos = std::find(entry_list.begin(), entry_list.end(), *I);
+ if (pos == entry_list.end())
+ m_removed_soentries.push_back(*I);
+ }
+
+ m_soentries = entry_list;
+ return true;
+}
+
+bool
+DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list)
+{
+ SOEntry entry;
+
+ if (m_current.map_addr == 0)
+ return false;
+
+ for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
+ {
+ if (!ReadSOEntryFromMemory(cursor, entry))
+ return false;
+
+ if (entry.path.empty())
+ continue;
+
+ entry_list.push_back(entry);
+ }
+
+ return true;
+}
+
+addr_t
+DYLDRendezvous::ReadMemory(addr_t addr, void *dst, size_t size)
+{
+ size_t bytes_read;
+ Error error;
+
+ bytes_read = m_process->DoReadMemory(addr, dst, size, error);
+ if (bytes_read != size || error.Fail())
+ return 0;
+
+ return addr + bytes_read;
+}
+
+std::string
+DYLDRendezvous::ReadStringFromMemory(addr_t addr)
+{
+ std::string str;
+ Error error;
+ size_t size;
+ char c;
+
+ if (addr == LLDB_INVALID_ADDRESS)
+ return std::string();
+
+ for (;;) {
+ size = m_process->DoReadMemory(addr, &c, 1, error);
+ if (size != 1 || error.Fail())
+ return std::string();
+ if (c == 0)
+ break;
+ else {
+ str.push_back(c);
+ addr++;
+ }
+ }
+
+ return str;
+}
+
+bool
+DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
+{
+ size_t address_size = m_process->GetAddressByteSize();
+
+ entry.clear();
+
+ if (!(addr = ReadMemory(addr, &entry.base_addr, address_size)))
+ return false;
+
+ if (!(addr = ReadMemory(addr, &entry.path_addr, address_size)))
+ return false;
+
+ if (!(addr = ReadMemory(addr, &entry.dyn_addr, address_size)))
+ return false;
+
+ if (!(addr = ReadMemory(addr, &entry.next, address_size)))
+ return false;
+
+ if (!(addr = ReadMemory(addr, &entry.prev, address_size)))
+ return false;
+
+ entry.path = ReadStringFromMemory(entry.path_addr);
+
+ return true;
+}
+
+void
+DYLDRendezvous::DumpToLog(LogSP log) const
+{
+ int state = GetState();
+
+ if (!log)
+ return;
+
+ log->PutCString("DYLDRendezvous:");
+ log->Printf(" Address: %lx", GetRendezvousAddress());
+ log->Printf(" Version: %d", GetVersion());
+ log->Printf(" Link : %lx", GetLinkMapAddress());
+ log->Printf(" Break : %lx", GetBreakAddress());
+ log->Printf(" LDBase : %lx", GetLDBase());
+ log->Printf(" State : %s",
+ (state == eConsistent) ? "consistent" :
+ (state == eAdd) ? "add" :
+ (state == eDelete) ? "delete" : "unknown");
+
+ iterator I = begin();
+ iterator E = end();
+
+ if (I != E)
+ log->PutCString("DYLDRendezvous SOEntries:");
+
+ for (int i = 1; I != E; ++I, ++i)
+ {
+ log->Printf("\n SOEntry [%d] %s", i, I->path.c_str());
+ log->Printf(" Base : %lx", I->base_addr);
+ log->Printf(" Path : %lx", I->path_addr);
+ log->Printf(" Dyn : %lx", I->dyn_addr);
+ log->Printf(" Next : %lx", I->next);
+ log->Printf(" Prev : %lx", I->prev);
+ }
+}
diff --git a/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h b/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h
new file mode 100644
index 0000000..e8052ae
--- /dev/null
+++ b/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h
@@ -0,0 +1,227 @@
+//===-- DYLDRendezvous.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Rendezvous_H_
+#define liblldb_Rendezvous_H_
+
+// C Includes
+// C++ Includes
+#include
+#include
+
+// Other libraries and framework includes
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-types.h"
+
+namespace lldb_private {
+class Process;
+}
+
+/// @class DYLDRendezvous
+/// @brief Interface to the runtime linker.
+///
+/// A structure is present in a processes memory space which is updated by the
+/// runtime liker each time a module is loaded or unloaded. This class provides
+/// an interface to this structure and maintains a consistent snapshot of the
+/// currently loaded modules.
+class DYLDRendezvous {
+
+ // This structure is used to hold the contents of the debug rendezvous
+ // information (struct r_debug) as found in the inferiors memory. Note that
+ // the layout of this struct is not binary compatible, it is simply large
+ // enough to hold the information on both 32 and 64 bit platforms.
+ struct Rendezvous {
+ uint64_t version;
+ lldb::addr_t map_addr;
+ lldb::addr_t brk;
+ uint64_t state;
+ lldb::addr_t ldbase;
+
+ Rendezvous()
+ : version(0), map_addr(0), brk(0), state(0), ldbase(0) { }
+ };
+
+public:
+ DYLDRendezvous(lldb_private::Process *process);
+
+ /// Update the internal snapshot of runtime linker rendezvous and recompute
+ /// the currently loaded modules.
+ ///
+ /// This method should be called once one start up, then once each time the
+ /// runtime linker enters the function given by GetBreakAddress().
+ ///
+ /// @returns true on success and false on failure.
+ ///
+ /// @see GetBreakAddress().
+ bool
+ Resolve();
+
+ /// @returns true if this rendezvous has been located in the inferiors
+ /// address space and false otherwise.
+ bool
+ IsValid();
+
+ /// @returns the address of the rendezvous structure in the inferiors
+ /// address space.
+ lldb::addr_t
+ GetRendezvousAddress() const { return m_rendezvous_addr; }
+
+ /// @returns the version of the rendezvous protocol being used.
+ int
+ GetVersion() const { return m_current.version; }
+
+ /// @returns address in the inferiors address space containing the linked
+ /// list of shared object descriptors.
+ lldb::addr_t
+ GetLinkMapAddress() const { return m_current.map_addr; }
+
+ /// A breakpoint should be set at this address and Resolve called on each
+ /// hit.
+ ///
+ /// @returns the address of a function called by the runtime linker each
+ /// time a module is loaded/unloaded, or about to be loaded/unloaded.
+ ///
+ /// @see Resolve()
+ lldb::addr_t
+ GetBreakAddress() const { return m_current.brk; }
+
+ /// Returns the current state of the rendezvous structure.
+ int
+ GetState() const { return m_current.state; }
+
+ /// @returns the base address of the runtime linker in the inferiors address
+ /// space.
+ lldb::addr_t
+ GetLDBase() const { return m_current.ldbase; }
+
+ /// @returns true if modules have been loaded into the inferior since the
+ /// last call to Resolve().
+ bool
+ ModulesDidLoad() const { return !m_added_soentries.empty(); }
+
+ /// @returns true if modules have been unloaded from the inferior since the
+ /// last call to Resolve().
+ bool
+ ModulesDidUnload() const { return !m_removed_soentries.empty(); }
+
+ void
+ DumpToLog(lldb::LogSP log) const;
+
+ /// @brief Constants describing the state of the rendezvous.
+ ///
+ /// @see GetState().
+ enum RendezvousState {
+ eConsistent,
+ eAdd,
+ eDelete
+ };
+
+ /// @brief Structure representing the shared objects currently loaded into
+ /// the inferior process.
+ ///
+ /// This object is a rough analogue to the struct link_map object which
+ /// actually lives in the inferiors memory.
+ struct SOEntry {
+ lldb::addr_t base_addr; ///< Base address of the loaded object.
+ lldb::addr_t path_addr; ///< String naming the shared object.
+ lldb::addr_t dyn_addr; ///< Dynamic section of shared object.
+ lldb::addr_t next; ///< Address of next so_entry.
+ lldb::addr_t prev; ///< Address of previous so_entry.
+ std::string path; ///< File name of shared object.
+
+ SOEntry() { clear(); }
+
+ bool operator ==(const SOEntry &entry) {
+ return this->path == entry.path;
+ }
+
+ void clear() {
+ base_addr = 0;
+ path_addr = 0;
+ dyn_addr = 0;
+ next = 0;
+ prev = 0;
+ path.clear();
+ }
+ };
+
+protected:
+ typedef std::list SOEntryList;
+
+public:
+ typedef SOEntryList::const_iterator iterator;
+
+ /// Iterators over all currently loaded modules.
+ iterator begin() const { return m_soentries.begin(); }
+ iterator end() const { return m_soentries.end(); }
+
+ /// Iterators over all modules loaded into the inferior since the last call
+ /// to Resolve().
+ iterator loaded_begin() const { return m_added_soentries.begin(); }
+ iterator loaded_end() const { return m_added_soentries.end(); }
+
+ /// Iterators over all modules unloaded from the inferior since the last
+ /// call to Resolve().
+ iterator unloaded_begin() const { return m_removed_soentries.begin(); }
+ iterator unloaded_end() const { return m_removed_soentries.end(); }
+
+protected:
+ lldb_private::Process *m_process;
+
+ /// Location of the r_debug structure in the inferiors address space.
+ lldb::addr_t m_rendezvous_addr;
+
+ /// Current and previous snapshots of the rendezvous structure.
+ Rendezvous m_current;
+ Rendezvous m_previous;
+
+ /// List of SOEntry objects corresponding to the current link map state.
+ SOEntryList m_soentries;
+
+ /// List of SOEntry's added to the link map since the last call to Resolve().
+ SOEntryList m_added_soentries;
+
+ /// List of SOEntry's removed from the link map since the last call to
+ /// Resolve().
+ SOEntryList m_removed_soentries;
+
+ /// Reads @p size bytes from the inferiors address space starting at @p
+ /// addr.
+ ///
+ /// @returns addr + size if the read was successful and false otherwise.
+ lldb::addr_t
+ ReadMemory(lldb::addr_t addr, void *dst, size_t size);
+
+ /// Reads a null-terminated C string from the memory location starting at @p
+ /// addr.
+ std::string
+ ReadStringFromMemory(lldb::addr_t addr);
+
+ /// Reads an SOEntry starting at @p addr.
+ bool
+ ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry);
+
+ /// Updates the current set of SOEntries, the set of added entries, and the
+ /// set of removed entries.
+ bool
+ UpdateSOEntries();
+
+ bool
+ UpdateSOEntriesForAddition();
+
+ bool
+ UpdateSOEntriesForDeletion();
+
+ /// Reads the current list of shared objects according to the link map
+ /// supplied by the runtime linker.
+ bool
+ TakeSnapshot(SOEntryList &entry_list);
+};
+
+#endif
diff --git a/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp b/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp
new file mode 100644
index 0000000..0802ff6
--- /dev/null
+++ b/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp
@@ -0,0 +1,371 @@
+//===-- DynamicLoaderLinux.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+#include
+
+// Other libraries and framework includes
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "AuxVector.h"
+#include "DynamicLoaderLinuxDYLD.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+DynamicLoaderLinuxDYLD::Initialize()
+{
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(),
+ CreateInstance);
+}
+
+void
+DynamicLoaderLinuxDYLD::Terminate()
+{
+}
+
+const char *
+DynamicLoaderLinuxDYLD::GetPluginName()
+{
+ return "DynamicLoaderLinuxDYLD";
+}
+
+const char *
+DynamicLoaderLinuxDYLD::GetShortPluginName()
+{
+ return "linux-dyld";
+}
+
+const char *
+DynamicLoaderLinuxDYLD::GetPluginNameStatic()
+{
+ return "dynamic-loader.linux-dyld";
+}
+
+const char *
+DynamicLoaderLinuxDYLD::GetPluginDescriptionStatic()
+{
+ return "Dynamic loader plug-in that watches for shared library "
+ "loads/unloads in Linux processes.";
+}
+
+void
+DynamicLoaderLinuxDYLD::GetPluginCommandHelp(const char *command, Stream *strm)
+{
+}
+
+uint32_t
+DynamicLoaderLinuxDYLD::GetPluginVersion()
+{
+ return 1;
+}
+
+DynamicLoader *
+DynamicLoaderLinuxDYLD::CreateInstance(Process *process)
+{
+ return new DynamicLoaderLinuxDYLD(process);
+}
+
+DynamicLoaderLinuxDYLD::DynamicLoaderLinuxDYLD(Process *process)
+ : DynamicLoader(process),
+ m_rendezvous(process),
+ m_load_offset(LLDB_INVALID_ADDRESS),
+ m_entry_point(LLDB_INVALID_ADDRESS),
+ m_auxv(NULL)
+{
+}
+
+DynamicLoaderLinuxDYLD::~DynamicLoaderLinuxDYLD()
+{
+}
+
+void
+DynamicLoaderLinuxDYLD::DidAttach()
+{
+ ModuleSP executable;
+ addr_t load_offset;
+
+ m_auxv.reset(new AuxVector(m_process));
+
+ executable = m_process->GetTarget().GetExecutableModule();
+ load_offset = ComputeLoadOffset();
+
+ if (!executable.empty() && load_offset != LLDB_INVALID_ADDRESS)
+ {
+ ModuleList module_list;
+ module_list.Append(executable);
+ UpdateLoadedSections(executable, load_offset);
+ m_process->GetTarget().ModulesDidLoad(module_list);
+ }
+}
+
+void
+DynamicLoaderLinuxDYLD::DidLaunch()
+{
+ ModuleSP executable;
+ addr_t load_offset;
+
+ m_auxv.reset(new AuxVector(m_process));
+
+ executable = m_process->GetTarget().GetExecutableModule();
+ load_offset = ComputeLoadOffset();
+
+ if (!executable.empty() && load_offset != LLDB_INVALID_ADDRESS)
+ {
+ ModuleList module_list;
+ module_list.Append(executable);
+ UpdateLoadedSections(executable, load_offset);
+ ProbeEntry();
+ m_process->GetTarget().ModulesDidLoad(module_list);
+ }
+}
+
+Error
+DynamicLoaderLinuxDYLD::ExecutePluginCommand(Args &command, Stream *strm)
+{
+ return Error();
+}
+
+Log *
+DynamicLoaderLinuxDYLD::EnablePluginLogging(Stream *strm, Args &command)
+{
+ return NULL;
+}
+
+Error
+DynamicLoaderLinuxDYLD::CanLoadImage()
+{
+ return Error();
+}
+
+void
+DynamicLoaderLinuxDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr)
+{
+ ObjectFile *obj_file = module->GetObjectFile();
+ SectionList *sections = obj_file->GetSectionList();
+ SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList();
+ const size_t num_sections = sections->GetSize();
+
+ for (unsigned i = 0; i < num_sections; ++i)
+ {
+ Section *section = sections->GetSectionAtIndex(i).get();
+ lldb::addr_t new_load_addr = section->GetFileAddress() + base_addr;
+ lldb::addr_t old_load_addr = load_list.GetSectionLoadAddress(section);
+
+ // If the file address of the section is zero then this is not an
+ // allocatable/loadable section (property of ELF sh_addr). Skip it.
+ if (new_load_addr == base_addr)
+ continue;
+
+ if (old_load_addr == LLDB_INVALID_ADDRESS ||
+ old_load_addr != new_load_addr)
+ load_list.SetSectionLoadAddress(section, new_load_addr);
+ }
+}
+
+void
+DynamicLoaderLinuxDYLD::ProbeEntry()
+{
+ Breakpoint *entry_break;
+ addr_t entry;
+
+ if ((entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS)
+ return;
+
+ entry_break = m_process->GetTarget().CreateBreakpoint(entry, true).get();
+ entry_break->SetCallback(EntryBreakpointHit, this, true);
+}
+
+// The runtime linker has run and initialized the rendezvous structure once the
+// process has hit its entry point. When we hit the corresponding breakpoint we
+// interrogate the rendezvous structure to get the load addresses of all
+// dependent modules for the process. Similarly, we can discover the runtime
+// linker function and setup a breakpoint to notify us of any dynamically loaded
+// modules (via dlopen).
+bool
+DynamicLoaderLinuxDYLD::EntryBreakpointHit(void *baton,
+ StoppointCallbackContext *context,
+ user_id_t break_id,
+ user_id_t break_loc_id)
+{
+ DynamicLoaderLinuxDYLD* dyld_instance;
+
+ dyld_instance = static_cast(baton);
+ dyld_instance->LoadAllCurrentModules();
+ dyld_instance->SetRendezvousBreakpoint();
+ return false; // Continue running.
+}
+
+void
+DynamicLoaderLinuxDYLD::SetRendezvousBreakpoint()
+{
+ Breakpoint *dyld_break;
+ addr_t break_addr;
+
+ break_addr = m_rendezvous.GetBreakAddress();
+ dyld_break = m_process->GetTarget().CreateBreakpoint(break_addr, true).get();
+ dyld_break->SetCallback(RendezvousBreakpointHit, this, true);
+}
+
+bool
+DynamicLoaderLinuxDYLD::RendezvousBreakpointHit(void *baton,
+ StoppointCallbackContext *context,
+ user_id_t break_id,
+ user_id_t break_loc_id)
+{
+ DynamicLoaderLinuxDYLD* dyld_instance;
+
+ dyld_instance = static_cast(baton);
+ dyld_instance->RefreshModules();
+
+ // Return true to stop the target, false to just let the target run.
+ return dyld_instance->GetStopWhenImagesChange();
+}
+
+void
+DynamicLoaderLinuxDYLD::RefreshModules()
+{
+ if (!m_rendezvous.Resolve())
+ return;
+
+ DYLDRendezvous::iterator I;
+ DYLDRendezvous::iterator E;
+
+ ModuleList &loaded_modules = m_process->GetTarget().GetImages();
+
+ if (m_rendezvous.ModulesDidLoad())
+ {
+ ModuleList new_modules;
+
+ E = m_rendezvous.loaded_end();
+ for (I = m_rendezvous.loaded_begin(); I != E; ++I)
+ {
+ FileSpec file(I->path.c_str(), true);
+ ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);
+ if (!module_sp.empty())
+ new_modules.Append(module_sp);
+ }
+ m_process->GetTarget().ModulesDidLoad(new_modules);
+ }
+
+ if (m_rendezvous.ModulesDidUnload())
+ {
+ ModuleList old_modules;
+
+ E = m_rendezvous.unloaded_end();
+ for (I = m_rendezvous.unloaded_begin(); I != E; ++I)
+ {
+ FileSpec file(I->path.c_str(), true);
+ ModuleSP module_sp = loaded_modules.FindFirstModuleForFileSpec(file);
+ if (!module_sp.empty())
+ old_modules.Append(module_sp);
+ }
+ m_process->GetTarget().ModulesDidUnload(old_modules);
+ }
+}
+
+ThreadPlanSP
+DynamicLoaderLinuxDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop_others)
+{
+ LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ ThreadPlanSP thread_plan_sp;
+
+ if (log)
+ log->PutCString("DynamicLoaderLinuxDYLD: "
+ "GetStepThroughTrampolinePlan not implemented\n");
+
+ return thread_plan_sp;
+}
+
+void
+DynamicLoaderLinuxDYLD::LoadAllCurrentModules()
+{
+ DYLDRendezvous::iterator I;
+ DYLDRendezvous::iterator E;
+ ModuleList module_list;
+
+ if (!m_rendezvous.Resolve())
+ return;
+
+ for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)
+ {
+ FileSpec file(I->path.c_str(), false);
+ ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);
+ if (!module_sp.empty())
+ module_list.Append(module_sp);
+ }
+
+ m_process->GetTarget().ModulesDidLoad(module_list);
+}
+
+ModuleSP
+DynamicLoaderLinuxDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_addr)
+{
+ Target &target = m_process->GetTarget();
+ ModuleList &modules = target.GetImages();
+ ModuleSP module_sp;
+
+ if ((module_sp = modules.FindFirstModuleForFileSpec(file)))
+ {
+ UpdateLoadedSections(module_sp, base_addr);
+ }
+ else if ((module_sp = target.GetSharedModule(file, target.GetArchitecture())))
+ {
+ UpdateLoadedSections(module_sp, base_addr);
+ modules.Append(module_sp);
+ }
+
+ return module_sp;
+}
+
+addr_t
+DynamicLoaderLinuxDYLD::ComputeLoadOffset()
+{
+ addr_t virt_entry;
+
+ if (m_load_offset != LLDB_INVALID_ADDRESS)
+ return m_load_offset;
+
+ if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS)
+ return LLDB_INVALID_ADDRESS;
+
+ ModuleSP module = m_process->GetTarget().GetExecutableModule();
+ ObjectFile *exe = module->GetObjectFile();
+ Address file_entry = exe->GetEntryPoint();
+
+ if (!file_entry.IsValid())
+ return LLDB_INVALID_ADDRESS;
+
+ m_load_offset = virt_entry - file_entry.GetFileAddress();
+ return m_load_offset;
+}
+
+addr_t
+DynamicLoaderLinuxDYLD::GetEntryPoint()
+{
+ if (m_entry_point != LLDB_INVALID_ADDRESS)
+ return m_entry_point;
+
+ if (m_auxv.get() == NULL)
+ return LLDB_INVALID_ADDRESS;
+
+ AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY);
+
+ if (I == m_auxv->end())
+ return LLDB_INVALID_ADDRESS;
+
+ m_entry_point = static_cast(I->value);
+ return m_entry_point;
+}
diff --git a/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h b/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h
new file mode 100644
index 0000000..bc537ce
--- /dev/null
+++ b/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h
@@ -0,0 +1,165 @@
+//===-- DynamicLoaderLinux.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_DynamicLoaderLinux_H_
+#define liblldb_DynamicLoaderLinux_H_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Target/DynamicLoader.h"
+
+#include "DYLDRendezvous.h"
+
+class AuxVector;
+
+class DynamicLoaderLinuxDYLD : public lldb_private::DynamicLoader
+{
+public:
+
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static const char *
+ GetPluginNameStatic();
+
+ static const char *
+ GetPluginDescriptionStatic();
+
+ static lldb_private::DynamicLoader *
+ CreateInstance(lldb_private::Process *process);
+
+ DynamicLoaderLinuxDYLD(lldb_private::Process *process);
+
+ virtual
+ ~DynamicLoaderLinuxDYLD();
+
+ //------------------------------------------------------------------
+ // DynamicLoader protocol
+ //------------------------------------------------------------------
+
+ virtual void
+ DidAttach();
+
+ virtual void
+ DidLaunch();
+
+ virtual lldb::ThreadPlanSP
+ GetStepThroughTrampolinePlan(lldb_private::Thread &thread,
+ bool stop_others);
+
+ virtual lldb_private::Error
+ CanLoadImage();
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ virtual const char *
+ GetPluginName();
+
+ virtual const char *
+ GetShortPluginName();
+
+ virtual uint32_t
+ GetPluginVersion();
+
+ virtual void
+ GetPluginCommandHelp(const char *command, lldb_private::Stream *strm);
+
+ virtual lldb_private::Error
+ ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm);
+
+ virtual lldb_private::Log *
+ EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command);
+
+protected:
+ /// Runtime linker rendezvous structure.
+ DYLDRendezvous m_rendezvous;
+
+ /// Virtual load address of the inferior process.
+ lldb::addr_t m_load_offset;
+
+ /// Virtual entry address of the inferior process.
+ lldb::addr_t m_entry_point;
+
+ /// Auxiliary vector of the inferior process.
+ std::auto_ptr m_auxv;
+
+ /// Enables a breakpoint on a function called by the runtime
+ /// linker each time a module is loaded or unloaded.
+ void
+ SetRendezvousBreakpoint();
+
+ /// Callback routine which updates the current list of loaded modules based
+ /// on the information supplied by the runtime linker.
+ static bool
+ RendezvousBreakpointHit(void *baton,
+ lldb_private::StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
+
+ /// Helper method for RendezvousBreakpointHit. Updates LLDB's current set
+ /// of loaded modules.
+ void
+ RefreshModules();
+
+ /// Updates the load address of every allocatable section in @p module.
+ ///
+ /// @param module The module to traverse.
+ ///
+ /// @param base_addr The virtual base address @p module is loaded at.
+ void
+ UpdateLoadedSections(lldb::ModuleSP module,
+ lldb::addr_t base_addr = 0);
+
+ /// Locates or creates a module given by @p file and updates/loads the
+ /// resulting module at the virtual base address @p base_addr.
+ lldb::ModuleSP
+ LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t base_addr);
+
+ /// Resolves the entry point for the current inferior process and sets a
+ /// breakpoint at that address.
+ void
+ ProbeEntry();
+
+ /// Callback routine invoked when we hit the breakpoint on process entry.
+ ///
+ /// This routine is responsible for resolving the load addresses of all
+ /// dependent modules required by the inferior and setting up the rendezvous
+ /// breakpoint.
+ static bool
+ EntryBreakpointHit(void *baton,
+ lldb_private::StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
+
+ /// Helper for the entry breakpoint callback. Resolves the load addresses
+ /// of all dependent modules.
+ void
+ LoadAllCurrentModules();
+
+ /// Computes a value for m_load_offset returning the computed address on
+ /// success and LLDB_INVALID_ADDRESS on failure.
+ lldb::addr_t
+ ComputeLoadOffset();
+
+ /// Computes a value for m_entry_point returning the computed address on
+ /// success and LLDB_INVALID_ADDRESS on failure.
+ lldb::addr_t
+ GetEntryPoint();
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(DynamicLoaderLinuxDYLD);
+};
+
+#endif // liblldb_DynamicLoaderLinuxDYLD_H_
diff --git a/source/Plugins/DynamicLoader/Linux-DYLD/Makefile b/source/Plugins/DynamicLoader/Linux-DYLD/Makefile
new file mode 100644
index 0000000..94025dd
--- /dev/null
+++ b/source/Plugins/DynamicLoader/Linux-DYLD/Makefile
@@ -0,0 +1,14 @@
+##===- source/Plugins/DynamicLoader/Linux-DYLD/Makefile ----*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LLDB_LEVEL := ../../../..
+LIBRARYNAME := lldbPluginDynamicLoaderLinux
+BUILD_ARCHIVE = 1
+
+include $(LLDB_LEVEL)/Makefile
diff --git a/source/Plugins/Makefile b/source/Plugins/Makefile
index 14eed8a..a3d644f 100644
--- a/source/Plugins/Makefile
+++ b/source/Plugins/Makefile
@@ -23,7 +23,7 @@ DIRS += DynamicLoader/MacOSX-DYLD ObjectContainer/Universal-Mach-O \
endif
ifeq ($(HOST_OS),Linux)
-DIRS += Process/Linux
+DIRS += Process/Linux DynamicLoader/Linux-DYLD
endif
include $(LLDB_LEVEL)/Makefile
diff --git a/source/Plugins/Process/Linux/ProcessLinux.cpp b/source/Plugins/Process/Linux/ProcessLinux.cpp
index 00bdda5..d7fe1da 100644
--- a/source/Plugins/Process/Linux/ProcessLinux.cpp
+++ b/source/Plugins/Process/Linux/ProcessLinux.cpp
@@ -13,6 +13,7 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Target.h"
#include "ProcessLinux.h"
@@ -102,6 +103,19 @@ ProcessLinux::DoAttachToProcessWithID(lldb::pid_t pid)
}
Error
+ProcessLinux::WillLaunch(Module* module)
+{
+ Error error;
+
+ m_dyld_ap.reset(DynamicLoader::FindPlugin(this, "dynamic-loader.linux-dyld"));
+ if (m_dyld_ap.get() == NULL)
+ error.SetErrorString("unable to find the dynamic loader named "
+ "'dynamic-loader.linux-dyld'");
+
+ return error;
+}
+
+Error
ProcessLinux::DoLaunch(Module *module,
char const *argv[],
char const *envp[],
@@ -128,6 +142,13 @@ ProcessLinux::DoLaunch(Module *module,
return error;
}
+void
+ProcessLinux::DidLaunch()
+{
+ if (m_dyld_ap.get() != NULL)
+ m_dyld_ap->DidLaunch();
+}
+
Error
ProcessLinux::DoResume()
{
@@ -371,6 +392,12 @@ ProcessLinux::GetByteOrder() const
return m_byte_order;
}
+DynamicLoader *
+ProcessLinux::GetDynamicLoader()
+{
+ return m_dyld_ap.get();
+}
+
//------------------------------------------------------------------------------
// ProcessInterface protocol.
diff --git a/source/Plugins/Process/Linux/ProcessLinux.h b/source/Plugins/Process/Linux/ProcessLinux.h
index 3e23a7a..fbf14df 100644
--- a/source/Plugins/Process/Linux/ProcessLinux.h
+++ b/source/Plugins/Process/Linux/ProcessLinux.h
@@ -60,6 +60,9 @@ public:
CanDebug(lldb_private::Target &target);
virtual lldb_private::Error
+ WillLaunch(lldb_private::Module *module);
+
+ virtual lldb_private::Error
DoAttachToProcessWithID(lldb::pid_t pid);
virtual lldb_private::Error
@@ -71,6 +74,9 @@ public:
const char *stdout_path,
const char *stderr_path);
+ virtual void
+ DidLaunch();
+
virtual lldb_private::Error
DoResume();
@@ -131,6 +137,9 @@ public:
virtual lldb::addr_t
GetImageInfoAddress();
+ virtual lldb_private::DynamicLoader *
+ GetDynamicLoader();
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -176,6 +185,9 @@ private:
lldb_private::Mutex m_message_mutex;
std::queue m_message_queue;
+ /// Dynamic loader plugin associated with this process.
+ std::auto_ptr m_dyld_ap;
+
/// Updates the loaded sections provided by the executable.
///
/// FIXME: It would probably be better to delegate this task to the
diff --git a/source/lldb.cpp b/source/lldb.cpp
index 05c7f4b..ac281a2 100644
--- a/source/lldb.cpp
+++ b/source/lldb.cpp
@@ -44,6 +44,7 @@
#ifdef __linux__
#include "Plugins/Process/Linux/ProcessLinux.h"
+#include "Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h"
#endif
using namespace lldb;
@@ -94,6 +95,7 @@ lldb_private::Initialize ()
#endif
#ifdef __linux__
ProcessLinux::Initialize();
+ DynamicLoaderLinuxDYLD::Initialize();
#endif
}
}
@@ -137,6 +139,7 @@ lldb_private::Terminate ()
#ifdef __linux__
ProcessLinux::Terminate();
+ DynamicLoaderLinuxDYLD::Terminate();
#endif
Log::Terminate();
--
1.7.3.5
From gclayton at apple.com Sat Jan 15 17:48:37 2011
From: gclayton at apple.com (Greg Clayton)
Date: Sat, 15 Jan 2011 15:48:37 -0800
Subject: [Lldb-commits] [PATCH][RFC] Linux DynamicLoader plugin.
In-Reply-To:
References:
Message-ID:
Looks good, and great news that linux now has a dynamic loader.
The nice thing is if you want remote linux debugging, we can modify the ProcessGDBRemote plug-in, on linux by default, to use this dynamic loader plug-in since they are completely pluggable. We would need to just write a linux remote debug server. The current "debugserver" project really needs to be re-written from the ground up using the classes we have in LLDB (StringExtractor, GDBRemoteCommunication, StringExtractorGDBRemote).
One might also be able to make slight modifications to the existing GDB gdbserver binary (from the current GDB sources) for linux, and use it as the remote stub to connect to with LLDB!
Greg Clayton
On Jan 15, 2011, at 11:40 AM, Stephen Wilson wrote:
>
> This patch is enough to have shared objects recognized by LLDB on Linux.
> We can handle position independent executables. We can handle
> dynamically loaded modules brought in via dlopen.
>
> The DYLDRendezvous class provides an interface to a structure present in
> the address space of ELF-based processes. This structure provides the
> location of a function which is called by the runtime linker each time a
> shared object is loaded and unloaded (thus a breakpoint at that address
> will let LLDB intercept such events), a list of entries describing the
> currently loaded shared objects, plus a few other things.
>
> On Linux, processes are brought up with an auxiliary vector on the
> stack. One element in this vector contains the (possibly dynamic) entry
> address of the process. One does not need to walk the stack to find
> this information as it is available under /proc//auxv. The new
> AuxVector class provides a convenient read-only view of this auxiliary
> information. We use the dynamic entry address and the address as
> specified in the object file to compute the actual load address of the
> inferior image. This strategy works for both normal executables and
> PIE's.
>
> As most of this code is new the following diff might not be the most
> readable. One can also browse the files online here:
>
> https://github.com/eightcien/lldb/tree/lldb-linux/source/Plugins/DynamicLoader/Linux-DYLD
>
>
> ---
> lib/Makefile | 3 +-
> .../Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp | 191 ++++++++++
> .../Plugins/DynamicLoader/Linux-DYLD/AuxVector.h | 97 +++++
> .../DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp | 315 +++++++++++++++++
> .../DynamicLoader/Linux-DYLD/DYLDRendezvous.h | 227 ++++++++++++
> .../Linux-DYLD/DynamicLoaderLinuxDYLD.cpp | 371 ++++++++++++++++++++
> .../Linux-DYLD/DynamicLoaderLinuxDYLD.h | 165 +++++++++
> source/Plugins/DynamicLoader/Linux-DYLD/Makefile | 14 +
> source/Plugins/Makefile | 2 +-
> source/Plugins/Process/Linux/ProcessLinux.cpp | 27 ++
> source/Plugins/Process/Linux/ProcessLinux.h | 12 +
> source/lldb.cpp | 3 +
> 12 files changed, 1425 insertions(+), 2 deletions(-)
> create mode 100644 source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp
> create mode 100644 source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h
> create mode 100644 source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp
> create mode 100644 source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h
> create mode 100644 source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp
> create mode 100644 source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h
> create mode 100644 source/Plugins/DynamicLoader/Linux-DYLD/Makefile
>
> diff --git a/lib/Makefile b/lib/Makefile
> index 881b23c..abd9c1d 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -67,7 +67,8 @@ ifeq ($(HOST_OS),Darwin)
> endif
>
> ifeq ($(HOST_OS),Linux)
> - USEDLIBS += lldbPluginProcessLinux.a
> + USEDLIBS += lldbPluginProcessLinux.a \
> + lldbPluginDynamicLoaderLinux.a
> endif
>
> include $(LEVEL)/Makefile.common
> diff --git a/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp b/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp
> new file mode 100644
> index 0000000..6954e4c
> --- /dev/null
> +++ b/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp
> @@ -0,0 +1,191 @@
> +//===-- AuxVector.cpp -------------------------------------------*- C++ -*-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +// C Includes
> +#include
> +#include
> +#include
> +
> +// C++ Includes
> +// Other libraries and framework includes
> +#include "lldb/Core/DataBufferHeap.h"
> +#include "lldb/Core/DataExtractor.h"
> +#include "lldb/Core/Log.h"
> +#include "lldb/Target/Process.h"
> +
> +#include "AuxVector.h"
> +
> +using namespace lldb;
> +using namespace lldb_private;
> +
> +static bool
> +GetMaxU64(DataExtractor &data,
> + uint32_t *offset, uint64_t *value, unsigned int byte_size)
> +{
> + uint32_t saved_offset = *offset;
> + *value = data.GetMaxU64(offset, byte_size);
> + return *offset != saved_offset;
> +}
> +
> +static bool
> +ParseAuxvEntry(DataExtractor &data, AuxVector::Entry &entry,
> + uint32_t *offset, unsigned int byte_size)
> +{
> + if (!GetMaxU64(data, offset, &entry.type, byte_size))
> + return false;
> +
> + if (!GetMaxU64(data, offset, &entry.value, byte_size))
> + return false;
> +
> + return true;
> +}
> +
> +DataBufferSP
> +AuxVector::GetAuxvData()
> +{
> + static const size_t path_size = 128;
> + static char path[path_size];
> + DataBufferSP buf_sp;
> + int fd;
> +
> + // Ideally, we would simply create a FileSpec and call ReadFileContents.
> + // However, files in procfs have zero size (since they are, in general,
> + // dynamically generated by the kernel) which is incompatible with the
> + // current ReadFileContents implementation. Therefore we simply stream the
> + // data into a DataBuffer ourselves.
> + if (snprintf(path, path_size, "/proc/%d/auxv", m_process->GetID()) < 0)
> + return buf_sp;
> +
> + if ((fd = open(path, O_RDONLY, 0)) < 0)
> + return buf_sp;
> +
> + size_t bytes_read = 0;
> + std::auto_ptr buf_ap(new DataBufferHeap(1024, 0));
> + for (;;)
> + {
> + size_t avail = buf_ap->GetByteSize() - bytes_read;
> + ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail);
> +
> + if (status < 0)
> + break;
> +
> + bytes_read += status;
> +
> + if (status == 0)
> + {
> + buf_ap->SetByteSize(bytes_read);
> + buf_sp.reset(buf_ap.release());
> + break;
> + }
> +
> + if (avail - status == 0)
> + buf_ap->SetByteSize(2 * buf_ap->GetByteSize());
> + }
> +
> + return buf_sp;
> +}
> +
> +void
> +AuxVector::ParseAuxv(DataExtractor &data)
> +{
> + const unsigned int byte_size = m_process->GetAddressByteSize();
> + uint32_t offset = 0;
> +
> + for (;;)
> + {
> + Entry entry;
> +
> + if (!ParseAuxvEntry(data, entry, &offset, byte_size))
> + break;
> +
> + if (entry.type == AT_NULL)
> + break;
> +
> + if (entry.type == AT_IGNORE)
> + continue;
> +
> + m_auxv.push_back(entry);
> + }
> +}
> +
> +AuxVector::AuxVector(Process *process)
> + : m_process(process)
> +{
> + DataExtractor data;
> + LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
> +
> + data.SetData(GetAuxvData());
> + data.SetByteOrder(m_process->GetByteOrder());
> + data.SetAddressByteSize(m_process->GetAddressByteSize());
> +
> + ParseAuxv(data);
> +
> + if (log)
> + DumpToLog(log);
> +}
> +
> +AuxVector::iterator
> +AuxVector::FindEntry(EntryType type) const
> +{
> + for (iterator I = begin(); I != end(); ++I)
> + {
> + if (I->type == static_cast(type))
> + return I;
> + }
> +
> + return end();
> +}
> +
> +void
> +AuxVector::DumpToLog(LogSP log) const
> +{
> + if (!log)
> + return;
> +
> + log->PutCString("AuxVector: ");
> + for (iterator I = begin(); I != end(); ++I)
> + {
> + log->Printf(" %s [%d]: %lx", GetEntryName(*I), I->type, I->value);
> + }
> +}
> +
> +const char *
> +AuxVector::GetEntryName(EntryType type)
> +{
> + const char *name;
> +
> +#define ENTRY_NAME(_type) _type: name = #_type
> + switch (type)
> + {
> + default:
> + name = "unkown";
> + break;
> +
> + case ENTRY_NAME(AT_NULL); break;
> + case ENTRY_NAME(AT_IGNORE); break;
> + case ENTRY_NAME(AT_EXECFD); break;
> + case ENTRY_NAME(AT_PHDR); break;
> + case ENTRY_NAME(AT_PHENT); break;
> + case ENTRY_NAME(AT_PHNUM); break;
> + case ENTRY_NAME(AT_PAGESZ); break;
> + case ENTRY_NAME(AT_BASE); break;
> + case ENTRY_NAME(AT_FLAGS); break;
> + case ENTRY_NAME(AT_ENTRY); break;
> + case ENTRY_NAME(AT_NOTELF); break;
> + case ENTRY_NAME(AT_UID); break;
> + case ENTRY_NAME(AT_EUID); break;
> + case ENTRY_NAME(AT_GID); break;
> + case ENTRY_NAME(AT_EGID); break;
> + case ENTRY_NAME(AT_CLKTCK); break;
> + }
> +#undef ENTRY_NAME
> +
> + return name;
> +}
> +
> diff --git a/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h b/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h
> new file mode 100644
> index 0000000..7a5b370
> --- /dev/null
> +++ b/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h
> @@ -0,0 +1,97 @@
> +//===-- AuxVector.h ---------------------------------------------*- C++ -*-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef liblldb_AuxVector_H_
> +#define liblldb_AuxVector_H_
> +
> +// C Includes
> +// C++ Includes
> +#include
> +
> +// Other libraries and framework includes
> +#include "lldb/lldb-forward-rtti.h"
> +
> +namespace lldb_private {
> +class DataExtractor;
> +}
> +
> +/// @class AuxVector
> +/// @brief Represents a processes auxiliary vector.
> +///
> +/// When a process is loaded on Linux a vector of values is placed onto the
> +/// stack communicating operating system specific information. On construction
> +/// this class locates and parses this information and provides a simple
> +/// read-only interface to the entries found.
> +class AuxVector {
> +
> +public:
> + AuxVector(lldb_private::Process *process);
> +
> + struct Entry {
> + uint64_t type;
> + uint64_t value;
> +
> + Entry() : type(0), value(0) { }
> + };
> +
> + /// Constants describing the type of entry.
> + enum EntryType {
> + AT_NULL = 0, ///< End of auxv.
> + AT_IGNORE = 1, ///< Ignore entry.
> + AT_EXECFD = 2, ///< File descriptor of program.
> + AT_PHDR = 3, ///< Program headers.
> + AT_PHENT = 4, ///< Size of program header.
> + AT_PHNUM = 5, ///< Number of program headers.
> + AT_PAGESZ = 6, ///< Page size.
> + AT_BASE = 7, ///< Interpreter base address.
> + AT_FLAGS = 8, ///< Flags.
> + AT_ENTRY = 9, ///< Program entry point.
> + AT_NOTELF = 10, ///< Set if program is not an ELF.
> + AT_UID = 11, ///< UID.
> + AT_EUID = 12, ///< Effective UID.
> + AT_GID = 13, ///< GID.
> + AT_EGID = 14, ///< Effective GID.
> + AT_CLKTCK = 17 ///< Clock frequency (e.g. times(2)).
> + };
> +
> +private:
> + typedef std::vector EntryVector;
> +
> +public:
> + typedef EntryVector::const_iterator iterator;
> +
> + iterator begin() const { return m_auxv.begin(); }
> + iterator end() const { return m_auxv.end(); }
> +
> + iterator
> + FindEntry(EntryType type) const;
> +
> + static const char *
> + GetEntryName(const Entry &entry) {
> + return GetEntryName(static_cast(entry.type));
> + }
> +
> + static const char *
> + GetEntryName(EntryType type);
> +
> + void
> + DumpToLog(lldb::LogSP log) const;
> +
> +private:
> + lldb_private::Process *m_process;
> + EntryVector m_auxv;
> +
> + lldb::DataBufferSP
> + GetAuxvData();
> +
> + void
> + ParseAuxv(lldb_private::DataExtractor &data);
> +};
> +
> +#endif
> diff --git a/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp
> new file mode 100644
> index 0000000..8b4795d
> --- /dev/null
> +++ b/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp
> @@ -0,0 +1,315 @@
> +//===-- DYLDRendezvous.cpp --------------------------------------*- C++ -*-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +// C Includes
> +// C++ Includes
> +// Other libraries and framework includes
> +#include "lldb/Core/ArchSpec.h"
> +#include "lldb/Core/Error.h"
> +#include "lldb/Core/Log.h"
> +#include "lldb/Target/Process.h"
> +#include "lldb/Target/Target.h"
> +
> +#include "DYLDRendezvous.h"
> +
> +using namespace lldb;
> +using namespace lldb_private;
> +
> +/// Locates the address of the rendezvous structure. Returns the address on
> +/// success and LLDB_INVALID_ADDRESS on failure.
> +static addr_t
> +ResolveRendezvousAddress(Process *process)
> +{
> + addr_t info_location;
> + addr_t info_addr;
> + Error error;
> + size_t size;
> +
> + info_location = process->GetImageInfoAddress();
> +
> + if (info_location == LLDB_INVALID_ADDRESS)
> + return LLDB_INVALID_ADDRESS;
> +
> + info_addr = 0;
> + size = process->DoReadMemory(info_location, &info_addr,
> + process->GetAddressByteSize(), error);
> + if (size != process->GetAddressByteSize() || error.Fail())
> + return LLDB_INVALID_ADDRESS;
> +
> + if (info_addr == 0)
> + return LLDB_INVALID_ADDRESS;
> +
> + return info_addr;
> +}
> +
> +DYLDRendezvous::DYLDRendezvous(Process *process)
> + : m_process(process),
> + m_rendezvous_addr(LLDB_INVALID_ADDRESS),
> + m_current(),
> + m_previous(),
> + m_soentries(),
> + m_added_soentries(),
> + m_removed_soentries()
> +{
> +}
> +
> +bool
> +DYLDRendezvous::Resolve()
> +{
> + const size_t word_size = 4;
> + Rendezvous info;
> + size_t address_size;
> + size_t padding;
> + addr_t info_addr;
> + addr_t cursor;
> +
> + address_size = m_process->GetAddressByteSize();
> + padding = address_size - word_size;
> +
> + if (m_rendezvous_addr == LLDB_INVALID_ADDRESS)
> + cursor = info_addr = ResolveRendezvousAddress(m_process);
> + else
> + cursor = info_addr = m_rendezvous_addr;
> +
> + if (cursor == LLDB_INVALID_ADDRESS)
> + return false;
> +
> + if (!(cursor = ReadMemory(cursor, &info.version, word_size)))
> + return false;
> +
> + if (!(cursor = ReadMemory(cursor + padding, &info.map_addr, address_size)))
> + return false;
> +
> + if (!(cursor = ReadMemory(cursor, &info.brk, address_size)))
> + return false;
> +
> + if (!(cursor = ReadMemory(cursor, &info.state, word_size)))
> + return false;
> +
> + if (!(cursor = ReadMemory(cursor + padding, &info.ldbase, address_size)))
> + return false;
> +
> + // The rendezvous was successfully read. Update our internal state.
> + m_rendezvous_addr = info_addr;
> + m_previous = m_current;
> + m_current = info;
> +
> + return UpdateSOEntries();
> +}
> +
> +bool
> +DYLDRendezvous::IsValid()
> +{
> + return m_rendezvous_addr != LLDB_INVALID_ADDRESS;
> +}
> +
> +bool
> +DYLDRendezvous::UpdateSOEntries()
> +{
> + SOEntry entry;
> +
> + if (m_current.map_addr == 0)
> + return false;
> +
> + // If we are about to add or remove a shared object clear out the current
> + // state and take a snapshot of the currently loaded images.
> + if (m_current.state == eAdd || m_current.state == eDelete)
> + {
> + assert(m_previous.state == eConsistent);
> + m_soentries.clear();
> + m_added_soentries.clear();
> + m_removed_soentries.clear();
> + return TakeSnapshot(m_soentries);
> + }
> +
> + // Otherwise check the previous state to determine what to expect and update
> + // accordingly.
> + if (m_previous.state == eAdd)
> + return UpdateSOEntriesForAddition();
> + else if (m_previous.state == eDelete)
> + return UpdateSOEntriesForDeletion();
> +
> + return false;
> +}
> +
> +bool
> +DYLDRendezvous::UpdateSOEntriesForAddition()
> +{
> + SOEntry entry;
> + iterator pos;
> +
> + assert(m_previous.state == eAdd);
> +
> + if (m_current.map_addr == 0)
> + return false;
> +
> + for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
> + {
> + if (!ReadSOEntryFromMemory(cursor, entry))
> + return false;
> +
> + if (entry.path.empty())
> + continue;
> +
> + pos = std::find(m_soentries.begin(), m_soentries.end(), entry);
> + if (pos == m_soentries.end())
> + {
> + m_soentries.push_back(entry);
> + m_added_soentries.push_back(entry);
> + }
> + }
> +
> + return true;
> +}
> +
> +bool
> +DYLDRendezvous::UpdateSOEntriesForDeletion()
> +{
> + SOEntryList entry_list;
> + iterator pos;
> +
> + assert(m_previous.state == eDelete);
> +
> + if (!TakeSnapshot(entry_list))
> + return false;
> +
> + for (iterator I = begin(); I != end(); ++I)
> + {
> + pos = std::find(entry_list.begin(), entry_list.end(), *I);
> + if (pos == entry_list.end())
> + m_removed_soentries.push_back(*I);
> + }
> +
> + m_soentries = entry_list;
> + return true;
> +}
> +
> +bool
> +DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list)
> +{
> + SOEntry entry;
> +
> + if (m_current.map_addr == 0)
> + return false;
> +
> + for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
> + {
> + if (!ReadSOEntryFromMemory(cursor, entry))
> + return false;
> +
> + if (entry.path.empty())
> + continue;
> +
> + entry_list.push_back(entry);
> + }
> +
> + return true;
> +}
> +
> +addr_t
> +DYLDRendezvous::ReadMemory(addr_t addr, void *dst, size_t size)
> +{
> + size_t bytes_read;
> + Error error;
> +
> + bytes_read = m_process->DoReadMemory(addr, dst, size, error);
> + if (bytes_read != size || error.Fail())
> + return 0;
> +
> + return addr + bytes_read;
> +}
> +
> +std::string
> +DYLDRendezvous::ReadStringFromMemory(addr_t addr)
> +{
> + std::string str;
> + Error error;
> + size_t size;
> + char c;
> +
> + if (addr == LLDB_INVALID_ADDRESS)
> + return std::string();
> +
> + for (;;) {
> + size = m_process->DoReadMemory(addr, &c, 1, error);
> + if (size != 1 || error.Fail())
> + return std::string();
> + if (c == 0)
> + break;
> + else {
> + str.push_back(c);
> + addr++;
> + }
> + }
> +
> + return str;
> +}
> +
> +bool
> +DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
> +{
> + size_t address_size = m_process->GetAddressByteSize();
> +
> + entry.clear();
> +
> + if (!(addr = ReadMemory(addr, &entry.base_addr, address_size)))
> + return false;
> +
> + if (!(addr = ReadMemory(addr, &entry.path_addr, address_size)))
> + return false;
> +
> + if (!(addr = ReadMemory(addr, &entry.dyn_addr, address_size)))
> + return false;
> +
> + if (!(addr = ReadMemory(addr, &entry.next, address_size)))
> + return false;
> +
> + if (!(addr = ReadMemory(addr, &entry.prev, address_size)))
> + return false;
> +
> + entry.path = ReadStringFromMemory(entry.path_addr);
> +
> + return true;
> +}
> +
> +void
> +DYLDRendezvous::DumpToLog(LogSP log) const
> +{
> + int state = GetState();
> +
> + if (!log)
> + return;
> +
> + log->PutCString("DYLDRendezvous:");
> + log->Printf(" Address: %lx", GetRendezvousAddress());
> + log->Printf(" Version: %d", GetVersion());
> + log->Printf(" Link : %lx", GetLinkMapAddress());
> + log->Printf(" Break : %lx", GetBreakAddress());
> + log->Printf(" LDBase : %lx", GetLDBase());
> + log->Printf(" State : %s",
> + (state == eConsistent) ? "consistent" :
> + (state == eAdd) ? "add" :
> + (state == eDelete) ? "delete" : "unknown");
> +
> + iterator I = begin();
> + iterator E = end();
> +
> + if (I != E)
> + log->PutCString("DYLDRendezvous SOEntries:");
> +
> + for (int i = 1; I != E; ++I, ++i)
> + {
> + log->Printf("\n SOEntry [%d] %s", i, I->path.c_str());
> + log->Printf(" Base : %lx", I->base_addr);
> + log->Printf(" Path : %lx", I->path_addr);
> + log->Printf(" Dyn : %lx", I->dyn_addr);
> + log->Printf(" Next : %lx", I->next);
> + log->Printf(" Prev : %lx", I->prev);
> + }
> +}
> diff --git a/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h b/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h
> new file mode 100644
> index 0000000..e8052ae
> --- /dev/null
> +++ b/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h
> @@ -0,0 +1,227 @@
> +//===-- DYLDRendezvous.h ----------------------------------------*- C++ -*-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef liblldb_Rendezvous_H_
> +#define liblldb_Rendezvous_H_
> +
> +// C Includes
> +// C++ Includes
> +#include
> +#include
> +
> +// Other libraries and framework includes
> +#include "lldb/lldb-defines.h"
> +#include "lldb/lldb-types.h"
> +
> +namespace lldb_private {
> +class Process;
> +}
> +
> +/// @class DYLDRendezvous
> +/// @brief Interface to the runtime linker.
> +///
> +/// A structure is present in a processes memory space which is updated by the
> +/// runtime liker each time a module is loaded or unloaded. This class provides
> +/// an interface to this structure and maintains a consistent snapshot of the
> +/// currently loaded modules.
> +class DYLDRendezvous {
> +
> + // This structure is used to hold the contents of the debug rendezvous
> + // information (struct r_debug) as found in the inferiors memory. Note that
> + // the layout of this struct is not binary compatible, it is simply large
> + // enough to hold the information on both 32 and 64 bit platforms.
> + struct Rendezvous {
> + uint64_t version;
> + lldb::addr_t map_addr;
> + lldb::addr_t brk;
> + uint64_t state;
> + lldb::addr_t ldbase;
> +
> + Rendezvous()
> + : version(0), map_addr(0), brk(0), state(0), ldbase(0) { }
> + };
> +
> +public:
> + DYLDRendezvous(lldb_private::Process *process);
> +
> + /// Update the internal snapshot of runtime linker rendezvous and recompute
> + /// the currently loaded modules.
> + ///
> + /// This method should be called once one start up, then once each time the
> + /// runtime linker enters the function given by GetBreakAddress().
> + ///
> + /// @returns true on success and false on failure.
> + ///
> + /// @see GetBreakAddress().
> + bool
> + Resolve();
> +
> + /// @returns true if this rendezvous has been located in the inferiors
> + /// address space and false otherwise.
> + bool
> + IsValid();
> +
> + /// @returns the address of the rendezvous structure in the inferiors
> + /// address space.
> + lldb::addr_t
> + GetRendezvousAddress() const { return m_rendezvous_addr; }
> +
> + /// @returns the version of the rendezvous protocol being used.
> + int
> + GetVersion() const { return m_current.version; }
> +
> + /// @returns address in the inferiors address space containing the linked
> + /// list of shared object descriptors.
> + lldb::addr_t
> + GetLinkMapAddress() const { return m_current.map_addr; }
> +
> + /// A breakpoint should be set at this address and Resolve called on each
> + /// hit.
> + ///
> + /// @returns the address of a function called by the runtime linker each
> + /// time a module is loaded/unloaded, or about to be loaded/unloaded.
> + ///
> + /// @see Resolve()
> + lldb::addr_t
> + GetBreakAddress() const { return m_current.brk; }
> +
> + /// Returns the current state of the rendezvous structure.
> + int
> + GetState() const { return m_current.state; }
> +
> + /// @returns the base address of the runtime linker in the inferiors address
> + /// space.
> + lldb::addr_t
> + GetLDBase() const { return m_current.ldbase; }
> +
> + /// @returns true if modules have been loaded into the inferior since the
> + /// last call to Resolve().
> + bool
> + ModulesDidLoad() const { return !m_added_soentries.empty(); }
> +
> + /// @returns true if modules have been unloaded from the inferior since the
> + /// last call to Resolve().
> + bool
> + ModulesDidUnload() const { return !m_removed_soentries.empty(); }
> +
> + void
> + DumpToLog(lldb::LogSP log) const;
> +
> + /// @brief Constants describing the state of the rendezvous.
> + ///
> + /// @see GetState().
> + enum RendezvousState {
> + eConsistent,
> + eAdd,
> + eDelete
> + };
> +
> + /// @brief Structure representing the shared objects currently loaded into
> + /// the inferior process.
> + ///
> + /// This object is a rough analogue to the struct link_map object which
> + /// actually lives in the inferiors memory.
> + struct SOEntry {
> + lldb::addr_t base_addr; ///< Base address of the loaded object.
> + lldb::addr_t path_addr; ///< String naming the shared object.
> + lldb::addr_t dyn_addr; ///< Dynamic section of shared object.
> + lldb::addr_t next; ///< Address of next so_entry.
> + lldb::addr_t prev; ///< Address of previous so_entry.
> + std::string path; ///< File name of shared object.
> +
> + SOEntry() { clear(); }
> +
> + bool operator ==(const SOEntry &entry) {
> + return this->path == entry.path;
> + }
> +
> + void clear() {
> + base_addr = 0;
> + path_addr = 0;
> + dyn_addr = 0;
> + next = 0;
> + prev = 0;
> + path.clear();
> + }
> + };
> +
> +protected:
> + typedef std::list SOEntryList;
> +
> +public:
> + typedef SOEntryList::const_iterator iterator;
> +
> + /// Iterators over all currently loaded modules.
> + iterator begin() const { return m_soentries.begin(); }
> + iterator end() const { return m_soentries.end(); }
> +
> + /// Iterators over all modules loaded into the inferior since the last call
> + /// to Resolve().
> + iterator loaded_begin() const { return m_added_soentries.begin(); }
> + iterator loaded_end() const { return m_added_soentries.end(); }
> +
> + /// Iterators over all modules unloaded from the inferior since the last
> + /// call to Resolve().
> + iterator unloaded_begin() const { return m_removed_soentries.begin(); }
> + iterator unloaded_end() const { return m_removed_soentries.end(); }
> +
> +protected:
> + lldb_private::Process *m_process;
> +
> + /// Location of the r_debug structure in the inferiors address space.
> + lldb::addr_t m_rendezvous_addr;
> +
> + /// Current and previous snapshots of the rendezvous structure.
> + Rendezvous m_current;
> + Rendezvous m_previous;
> +
> + /// List of SOEntry objects corresponding to the current link map state.
> + SOEntryList m_soentries;
> +
> + /// List of SOEntry's added to the link map since the last call to Resolve().
> + SOEntryList m_added_soentries;
> +
> + /// List of SOEntry's removed from the link map since the last call to
> + /// Resolve().
> + SOEntryList m_removed_soentries;
> +
> + /// Reads @p size bytes from the inferiors address space starting at @p
> + /// addr.
> + ///
> + /// @returns addr + size if the read was successful and false otherwise.
> + lldb::addr_t
> + ReadMemory(lldb::addr_t addr, void *dst, size_t size);
> +
> + /// Reads a null-terminated C string from the memory location starting at @p
> + /// addr.
> + std::string
> + ReadStringFromMemory(lldb::addr_t addr);
> +
> + /// Reads an SOEntry starting at @p addr.
> + bool
> + ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry);
> +
> + /// Updates the current set of SOEntries, the set of added entries, and the
> + /// set of removed entries.
> + bool
> + UpdateSOEntries();
> +
> + bool
> + UpdateSOEntriesForAddition();
> +
> + bool
> + UpdateSOEntriesForDeletion();
> +
> + /// Reads the current list of shared objects according to the link map
> + /// supplied by the runtime linker.
> + bool
> + TakeSnapshot(SOEntryList &entry_list);
> +};
> +
> +#endif
> diff --git a/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp b/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp
> new file mode 100644
> index 0000000..0802ff6
> --- /dev/null
> +++ b/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp
> @@ -0,0 +1,371 @@
> +//===-- DynamicLoaderLinux.h ------------------------------------*- C++ -*-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +// C Includes
> +// C++ Includes
> +#include
> +
> +// Other libraries and framework includes
> +#include "lldb/Core/PluginManager.h"
> +#include "lldb/Core/Log.h"
> +#include "lldb/Target/Process.h"
> +#include "lldb/Target/Target.h"
> +
> +#include "AuxVector.h"
> +#include "DynamicLoaderLinuxDYLD.h"
> +
> +using namespace lldb;
> +using namespace lldb_private;
> +
> +void
> +DynamicLoaderLinuxDYLD::Initialize()
> +{
> + PluginManager::RegisterPlugin(GetPluginNameStatic(),
> + GetPluginDescriptionStatic(),
> + CreateInstance);
> +}
> +
> +void
> +DynamicLoaderLinuxDYLD::Terminate()
> +{
> +}
> +
> +const char *
> +DynamicLoaderLinuxDYLD::GetPluginName()
> +{
> + return "DynamicLoaderLinuxDYLD";
> +}
> +
> +const char *
> +DynamicLoaderLinuxDYLD::GetShortPluginName()
> +{
> + return "linux-dyld";
> +}
> +
> +const char *
> +DynamicLoaderLinuxDYLD::GetPluginNameStatic()
> +{
> + return "dynamic-loader.linux-dyld";
> +}
> +
> +const char *
> +DynamicLoaderLinuxDYLD::GetPluginDescriptionStatic()
> +{
> + return "Dynamic loader plug-in that watches for shared library "
> + "loads/unloads in Linux processes.";
> +}
> +
> +void
> +DynamicLoaderLinuxDYLD::GetPluginCommandHelp(const char *command, Stream *strm)
> +{
> +}
> +
> +uint32_t
> +DynamicLoaderLinuxDYLD::GetPluginVersion()
> +{
> + return 1;
> +}
> +
> +DynamicLoader *
> +DynamicLoaderLinuxDYLD::CreateInstance(Process *process)
> +{
> + return new DynamicLoaderLinuxDYLD(process);
> +}
> +
> +DynamicLoaderLinuxDYLD::DynamicLoaderLinuxDYLD(Process *process)
> + : DynamicLoader(process),
> + m_rendezvous(process),
> + m_load_offset(LLDB_INVALID_ADDRESS),
> + m_entry_point(LLDB_INVALID_ADDRESS),
> + m_auxv(NULL)
> +{
> +}
> +
> +DynamicLoaderLinuxDYLD::~DynamicLoaderLinuxDYLD()
> +{
> +}
> +
> +void
> +DynamicLoaderLinuxDYLD::DidAttach()
> +{
> + ModuleSP executable;
> + addr_t load_offset;
> +
> + m_auxv.reset(new AuxVector(m_process));
> +
> + executable = m_process->GetTarget().GetExecutableModule();
> + load_offset = ComputeLoadOffset();
> +
> + if (!executable.empty() && load_offset != LLDB_INVALID_ADDRESS)
> + {
> + ModuleList module_list;
> + module_list.Append(executable);
> + UpdateLoadedSections(executable, load_offset);
> + m_process->GetTarget().ModulesDidLoad(module_list);
> + }
> +}
> +
> +void
> +DynamicLoaderLinuxDYLD::DidLaunch()
> +{
> + ModuleSP executable;
> + addr_t load_offset;
> +
> + m_auxv.reset(new AuxVector(m_process));
> +
> + executable = m_process->GetTarget().GetExecutableModule();
> + load_offset = ComputeLoadOffset();
> +
> + if (!executable.empty() && load_offset != LLDB_INVALID_ADDRESS)
> + {
> + ModuleList module_list;
> + module_list.Append(executable);
> + UpdateLoadedSections(executable, load_offset);
> + ProbeEntry();
> + m_process->GetTarget().ModulesDidLoad(module_list);
> + }
> +}
> +
> +Error
> +DynamicLoaderLinuxDYLD::ExecutePluginCommand(Args &command, Stream *strm)
> +{
> + return Error();
> +}
> +
> +Log *
> +DynamicLoaderLinuxDYLD::EnablePluginLogging(Stream *strm, Args &command)
> +{
> + return NULL;
> +}
> +
> +Error
> +DynamicLoaderLinuxDYLD::CanLoadImage()
> +{
> + return Error();
> +}
> +
> +void
> +DynamicLoaderLinuxDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr)
> +{
> + ObjectFile *obj_file = module->GetObjectFile();
> + SectionList *sections = obj_file->GetSectionList();
> + SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList();
> + const size_t num_sections = sections->GetSize();
> +
> + for (unsigned i = 0; i < num_sections; ++i)
> + {
> + Section *section = sections->GetSectionAtIndex(i).get();
> + lldb::addr_t new_load_addr = section->GetFileAddress() + base_addr;
> + lldb::addr_t old_load_addr = load_list.GetSectionLoadAddress(section);
> +
> + // If the file address of the section is zero then this is not an
> + // allocatable/loadable section (property of ELF sh_addr). Skip it.
> + if (new_load_addr == base_addr)
> + continue;
> +
> + if (old_load_addr == LLDB_INVALID_ADDRESS ||
> + old_load_addr != new_load_addr)
> + load_list.SetSectionLoadAddress(section, new_load_addr);
> + }
> +}
> +
> +void
> +DynamicLoaderLinuxDYLD::ProbeEntry()
> +{
> + Breakpoint *entry_break;
> + addr_t entry;
> +
> + if ((entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS)
> + return;
> +
> + entry_break = m_process->GetTarget().CreateBreakpoint(entry, true).get();
> + entry_break->SetCallback(EntryBreakpointHit, this, true);
> +}
> +
> +// The runtime linker has run and initialized the rendezvous structure once the
> +// process has hit its entry point. When we hit the corresponding breakpoint we
> +// interrogate the rendezvous structure to get the load addresses of all
> +// dependent modules for the process. Similarly, we can discover the runtime
> +// linker function and setup a breakpoint to notify us of any dynamically loaded
> +// modules (via dlopen).
> +bool
> +DynamicLoaderLinuxDYLD::EntryBreakpointHit(void *baton,
> + StoppointCallbackContext *context,
> + user_id_t break_id,
> + user_id_t break_loc_id)
> +{
> + DynamicLoaderLinuxDYLD* dyld_instance;
> +
> + dyld_instance = static_cast(baton);
> + dyld_instance->LoadAllCurrentModules();
> + dyld_instance->SetRendezvousBreakpoint();
> + return false; // Continue running.
> +}
> +
> +void
> +DynamicLoaderLinuxDYLD::SetRendezvousBreakpoint()
> +{
> + Breakpoint *dyld_break;
> + addr_t break_addr;
> +
> + break_addr = m_rendezvous.GetBreakAddress();
> + dyld_break = m_process->GetTarget().CreateBreakpoint(break_addr, true).get();
> + dyld_break->SetCallback(RendezvousBreakpointHit, this, true);
> +}
> +
> +bool
> +DynamicLoaderLinuxDYLD::RendezvousBreakpointHit(void *baton,
> + StoppointCallbackContext *context,
> + user_id_t break_id,
> + user_id_t break_loc_id)
> +{
> + DynamicLoaderLinuxDYLD* dyld_instance;
> +
> + dyld_instance = static_cast(baton);
> + dyld_instance->RefreshModules();
> +
> + // Return true to stop the target, false to just let the target run.
> + return dyld_instance->GetStopWhenImagesChange();
> +}
> +
> +void
> +DynamicLoaderLinuxDYLD::RefreshModules()
> +{
> + if (!m_rendezvous.Resolve())
> + return;
> +
> + DYLDRendezvous::iterator I;
> + DYLDRendezvous::iterator E;
> +
> + ModuleList &loaded_modules = m_process->GetTarget().GetImages();
> +
> + if (m_rendezvous.ModulesDidLoad())
> + {
> + ModuleList new_modules;
> +
> + E = m_rendezvous.loaded_end();
> + for (I = m_rendezvous.loaded_begin(); I != E; ++I)
> + {
> + FileSpec file(I->path.c_str(), true);
> + ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);
> + if (!module_sp.empty())
> + new_modules.Append(module_sp);
> + }
> + m_process->GetTarget().ModulesDidLoad(new_modules);
> + }
> +
> + if (m_rendezvous.ModulesDidUnload())
> + {
> + ModuleList old_modules;
> +
> + E = m_rendezvous.unloaded_end();
> + for (I = m_rendezvous.unloaded_begin(); I != E; ++I)
> + {
> + FileSpec file(I->path.c_str(), true);
> + ModuleSP module_sp = loaded_modules.FindFirstModuleForFileSpec(file);
> + if (!module_sp.empty())
> + old_modules.Append(module_sp);
> + }
> + m_process->GetTarget().ModulesDidUnload(old_modules);
> + }
> +}
> +
> +ThreadPlanSP
> +DynamicLoaderLinuxDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop_others)
> +{
> + LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
> + ThreadPlanSP thread_plan_sp;
> +
> + if (log)
> + log->PutCString("DynamicLoaderLinuxDYLD: "
> + "GetStepThroughTrampolinePlan not implemented\n");
> +
> + return thread_plan_sp;
> +}
> +
> +void
> +DynamicLoaderLinuxDYLD::LoadAllCurrentModules()
> +{
> + DYLDRendezvous::iterator I;
> + DYLDRendezvous::iterator E;
> + ModuleList module_list;
> +
> + if (!m_rendezvous.Resolve())
> + return;
> +
> + for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)
> + {
> + FileSpec file(I->path.c_str(), false);
> + ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);
> + if (!module_sp.empty())
> + module_list.Append(module_sp);
> + }
> +
> + m_process->GetTarget().ModulesDidLoad(module_list);
> +}
> +
> +ModuleSP
> +DynamicLoaderLinuxDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_addr)
> +{
> + Target &target = m_process->GetTarget();
> + ModuleList &modules = target.GetImages();
> + ModuleSP module_sp;
> +
> + if ((module_sp = modules.FindFirstModuleForFileSpec(file)))
> + {
> + UpdateLoadedSections(module_sp, base_addr);
> + }
> + else if ((module_sp = target.GetSharedModule(file, target.GetArchitecture())))
> + {
> + UpdateLoadedSections(module_sp, base_addr);
> + modules.Append(module_sp);
> + }
> +
> + return module_sp;
> +}
> +
> +addr_t
> +DynamicLoaderLinuxDYLD::ComputeLoadOffset()
> +{
> + addr_t virt_entry;
> +
> + if (m_load_offset != LLDB_INVALID_ADDRESS)
> + return m_load_offset;
> +
> + if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS)
> + return LLDB_INVALID_ADDRESS;
> +
> + ModuleSP module = m_process->GetTarget().GetExecutableModule();
> + ObjectFile *exe = module->GetObjectFile();
> + Address file_entry = exe->GetEntryPoint();
> +
> + if (!file_entry.IsValid())
> + return LLDB_INVALID_ADDRESS;
> +
> + m_load_offset = virt_entry - file_entry.GetFileAddress();
> + return m_load_offset;
> +}
> +
> +addr_t
> +DynamicLoaderLinuxDYLD::GetEntryPoint()
> +{
> + if (m_entry_point != LLDB_INVALID_ADDRESS)
> + return m_entry_point;
> +
> + if (m_auxv.get() == NULL)
> + return LLDB_INVALID_ADDRESS;
> +
> + AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY);
> +
> + if (I == m_auxv->end())
> + return LLDB_INVALID_ADDRESS;
> +
> + m_entry_point = static_cast(I->value);
> + return m_entry_point;
> +}
> diff --git a/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h b/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h
> new file mode 100644
> index 0000000..bc537ce
> --- /dev/null
> +++ b/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h
> @@ -0,0 +1,165 @@
> +//===-- DynamicLoaderLinux.h ------------------------------------*- C++ -*-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef liblldb_DynamicLoaderLinux_H_
> +#define liblldb_DynamicLoaderLinux_H_
> +
> +// C Includes
> +// C++ Includes
> +// Other libraries and framework includes
> +#include "lldb/Breakpoint/StoppointCallbackContext.h"
> +#include "lldb/Target/DynamicLoader.h"
> +
> +#include "DYLDRendezvous.h"
> +
> +class AuxVector;
> +
> +class DynamicLoaderLinuxDYLD : public lldb_private::DynamicLoader
> +{
> +public:
> +
> + static void
> + Initialize();
> +
> + static void
> + Terminate();
> +
> + static const char *
> + GetPluginNameStatic();
> +
> + static const char *
> + GetPluginDescriptionStatic();
> +
> + static lldb_private::DynamicLoader *
> + CreateInstance(lldb_private::Process *process);
> +
> + DynamicLoaderLinuxDYLD(lldb_private::Process *process);
> +
> + virtual
> + ~DynamicLoaderLinuxDYLD();
> +
> + //------------------------------------------------------------------
> + // DynamicLoader protocol
> + //------------------------------------------------------------------
> +
> + virtual void
> + DidAttach();
> +
> + virtual void
> + DidLaunch();
> +
> + virtual lldb::ThreadPlanSP
> + GetStepThroughTrampolinePlan(lldb_private::Thread &thread,
> + bool stop_others);
> +
> + virtual lldb_private::Error
> + CanLoadImage();
> +
> + //------------------------------------------------------------------
> + // PluginInterface protocol
> + //------------------------------------------------------------------
> + virtual const char *
> + GetPluginName();
> +
> + virtual const char *
> + GetShortPluginName();
> +
> + virtual uint32_t
> + GetPluginVersion();
> +
> + virtual void
> + GetPluginCommandHelp(const char *command, lldb_private::Stream *strm);
> +
> + virtual lldb_private::Error
> + ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm);
> +
> + virtual lldb_private::Log *
> + EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command);
> +
> +protected:
> + /// Runtime linker rendezvous structure.
> + DYLDRendezvous m_rendezvous;
> +
> + /// Virtual load address of the inferior process.
> + lldb::addr_t m_load_offset;
> +
> + /// Virtual entry address of the inferior process.
> + lldb::addr_t m_entry_point;
> +
> + /// Auxiliary vector of the inferior process.
> + std::auto_ptr m_auxv;
> +
> + /// Enables a breakpoint on a function called by the runtime
> + /// linker each time a module is loaded or unloaded.
> + void
> + SetRendezvousBreakpoint();
> +
> + /// Callback routine which updates the current list of loaded modules based
> + /// on the information supplied by the runtime linker.
> + static bool
> + RendezvousBreakpointHit(void *baton,
> + lldb_private::StoppointCallbackContext *context,
> + lldb::user_id_t break_id,
> + lldb::user_id_t break_loc_id);
> +
> + /// Helper method for RendezvousBreakpointHit. Updates LLDB's current set
> + /// of loaded modules.
> + void
> + RefreshModules();
> +
> + /// Updates the load address of every allocatable section in @p module.
> + ///
> + /// @param module The module to traverse.
> + ///
> + /// @param base_addr The virtual base address @p module is loaded at.
> + void
> + UpdateLoadedSections(lldb::ModuleSP module,
> + lldb::addr_t base_addr = 0);
> +
> + /// Locates or creates a module given by @p file and updates/loads the
> + /// resulting module at the virtual base address @p base_addr.
> + lldb::ModuleSP
> + LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t base_addr);
> +
> + /// Resolves the entry point for the current inferior process and sets a
> + /// breakpoint at that address.
> + void
> + ProbeEntry();
> +
> + /// Callback routine invoked when we hit the breakpoint on process entry.
> + ///
> + /// This routine is responsible for resolving the load addresses of all
> + /// dependent modules required by the inferior and setting up the rendezvous
> + /// breakpoint.
> + static bool
> + EntryBreakpointHit(void *baton,
> + lldb_private::StoppointCallbackContext *context,
> + lldb::user_id_t break_id,
> + lldb::user_id_t break_loc_id);
> +
> + /// Helper for the entry breakpoint callback. Resolves the load addresses
> + /// of all dependent modules.
> + void
> + LoadAllCurrentModules();
> +
> + /// Computes a value for m_load_offset returning the computed address on
> + /// success and LLDB_INVALID_ADDRESS on failure.
> + lldb::addr_t
> + ComputeLoadOffset();
> +
> + /// Computes a value for m_entry_point returning the computed address on
> + /// success and LLDB_INVALID_ADDRESS on failure.
> + lldb::addr_t
> + GetEntryPoint();
> +
> +private:
> + DISALLOW_COPY_AND_ASSIGN(DynamicLoaderLinuxDYLD);
> +};
> +
> +#endif // liblldb_DynamicLoaderLinuxDYLD_H_
> diff --git a/source/Plugins/DynamicLoader/Linux-DYLD/Makefile b/source/Plugins/DynamicLoader/Linux-DYLD/Makefile
> new file mode 100644
> index 0000000..94025dd
> --- /dev/null
> +++ b/source/Plugins/DynamicLoader/Linux-DYLD/Makefile
> @@ -0,0 +1,14 @@
> +##===- source/Plugins/DynamicLoader/Linux-DYLD/Makefile ----*- Makefile -*-===##
> +#
> +# The LLVM Compiler Infrastructure
> +#
> +# This file is distributed under the University of Illinois Open Source
> +# License. See LICENSE.TXT for details.
> +#
> +##===----------------------------------------------------------------------===##
> +
> +LLDB_LEVEL := ../../../..
> +LIBRARYNAME := lldbPluginDynamicLoaderLinux
> +BUILD_ARCHIVE = 1
> +
> +include $(LLDB_LEVEL)/Makefile
> diff --git a/source/Plugins/Makefile b/source/Plugins/Makefile
> index 14eed8a..a3d644f 100644
> --- a/source/Plugins/Makefile
> +++ b/source/Plugins/Makefile
> @@ -23,7 +23,7 @@ DIRS += DynamicLoader/MacOSX-DYLD ObjectContainer/Universal-Mach-O \
> endif
>
> ifeq ($(HOST_OS),Linux)
> -DIRS += Process/Linux
> +DIRS += Process/Linux DynamicLoader/Linux-DYLD
> endif
>
> include $(LLDB_LEVEL)/Makefile
> diff --git a/source/Plugins/Process/Linux/ProcessLinux.cpp b/source/Plugins/Process/Linux/ProcessLinux.cpp
> index 00bdda5..d7fe1da 100644
> --- a/source/Plugins/Process/Linux/ProcessLinux.cpp
> +++ b/source/Plugins/Process/Linux/ProcessLinux.cpp
> @@ -13,6 +13,7 @@
> #include "lldb/Core/PluginManager.h"
> #include "lldb/Host/Host.h"
> #include "lldb/Symbol/ObjectFile.h"
> +#include "lldb/Target/DynamicLoader.h"
> #include "lldb/Target/Target.h"
>
> #include "ProcessLinux.h"
> @@ -102,6 +103,19 @@ ProcessLinux::DoAttachToProcessWithID(lldb::pid_t pid)
> }
>
> Error
> +ProcessLinux::WillLaunch(Module* module)
> +{
> + Error error;
> +
> + m_dyld_ap.reset(DynamicLoader::FindPlugin(this, "dynamic-loader.linux-dyld"));
> + if (m_dyld_ap.get() == NULL)
> + error.SetErrorString("unable to find the dynamic loader named "
> + "'dynamic-loader.linux-dyld'");
> +
> + return error;
> +}
> +
> +Error
> ProcessLinux::DoLaunch(Module *module,
> char const *argv[],
> char const *envp[],
> @@ -128,6 +142,13 @@ ProcessLinux::DoLaunch(Module *module,
> return error;
> }
>
> +void
> +ProcessLinux::DidLaunch()
> +{
> + if (m_dyld_ap.get() != NULL)
> + m_dyld_ap->DidLaunch();
> +}
> +
> Error
> ProcessLinux::DoResume()
> {
> @@ -371,6 +392,12 @@ ProcessLinux::GetByteOrder() const
> return m_byte_order;
> }
>
> +DynamicLoader *
> +ProcessLinux::GetDynamicLoader()
> +{
> + return m_dyld_ap.get();
> +}
> +
> //------------------------------------------------------------------------------
> // ProcessInterface protocol.
>
> diff --git a/source/Plugins/Process/Linux/ProcessLinux.h b/source/Plugins/Process/Linux/ProcessLinux.h
> index 3e23a7a..fbf14df 100644
> --- a/source/Plugins/Process/Linux/ProcessLinux.h
> +++ b/source/Plugins/Process/Linux/ProcessLinux.h
> @@ -60,6 +60,9 @@ public:
> CanDebug(lldb_private::Target &target);
>
> virtual lldb_private::Error
> + WillLaunch(lldb_private::Module *module);
> +
> + virtual lldb_private::Error
> DoAttachToProcessWithID(lldb::pid_t pid);
>
> virtual lldb_private::Error
> @@ -71,6 +74,9 @@ public:
> const char *stdout_path,
> const char *stderr_path);
>
> + virtual void
> + DidLaunch();
> +
> virtual lldb_private::Error
> DoResume();
>
> @@ -131,6 +137,9 @@ public:
> virtual lldb::addr_t
> GetImageInfoAddress();
>
> + virtual lldb_private::DynamicLoader *
> + GetDynamicLoader();
> +
> //------------------------------------------------------------------
> // PluginInterface protocol
> //------------------------------------------------------------------
> @@ -176,6 +185,9 @@ private:
> lldb_private::Mutex m_message_mutex;
> std::queue m_message_queue;
>
> + /// Dynamic loader plugin associated with this process.
> + std::auto_ptr m_dyld_ap;
> +
> /// Updates the loaded sections provided by the executable.
> ///
> /// FIXME: It would probably be better to delegate this task to the
> diff --git a/source/lldb.cpp b/source/lldb.cpp
> index 05c7f4b..ac281a2 100644
> --- a/source/lldb.cpp
> +++ b/source/lldb.cpp
> @@ -44,6 +44,7 @@
>
> #ifdef __linux__
> #include "Plugins/Process/Linux/ProcessLinux.h"
> +#include "Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h"
> #endif
>
> using namespace lldb;
> @@ -94,6 +95,7 @@ lldb_private::Initialize ()
> #endif
> #ifdef __linux__
> ProcessLinux::Initialize();
> + DynamicLoaderLinuxDYLD::Initialize();
> #endif
> }
> }
> @@ -137,6 +139,7 @@ lldb_private::Terminate ()
>
> #ifdef __linux__
> ProcessLinux::Terminate();
> + DynamicLoaderLinuxDYLD::Terminate();
> #endif
>
> Log::Terminate();
> --
> 1.7.3.5
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
From wilsons at start.ca Sun Jan 16 10:56:16 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Sun, 16 Jan 2011 16:56:16 -0000
Subject: [Lldb-commits] [lldb] r123583 - in
/lldb/trunk/source/Plugins/Process/Linux: LinuxThread.cpp LinuxThread.h
Message-ID: <20110116165616.85F3E2A6C12C@llvm.org>
Author: wilsons
Date: Sun Jan 16 10:56:16 2011
New Revision: 123583
URL: http://llvm.org/viewvc/llvm-project?rev=123583&view=rev
Log:
Make a mandatory call to DestroyThread() in ~LinuxThread().
Modified:
lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp
lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h
Modified: lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp?rev=123583&r1=123582&r2=123583&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp Sun Jan 16 10:56:16 2011
@@ -31,6 +31,11 @@
{
}
+LinuxThread::~LinuxThread()
+{
+ DestroyThread();
+}
+
ProcessMonitor &
LinuxThread::GetMonitor()
{
Modified: lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h?rev=123583&r1=123582&r2=123583&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h Sun Jan 16 10:56:16 2011
@@ -29,6 +29,8 @@
public:
LinuxThread(lldb_private::Process &process, lldb::tid_t tid);
+ virtual ~LinuxThread();
+
void
RefreshStateAfterStop();
From wilsons at start.ca Sun Jan 16 13:45:39 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Sun, 16 Jan 2011 19:45:39 -0000
Subject: [Lldb-commits] [lldb] r123592 - in /lldb/trunk: lib/ source/
source/Plugins/ source/Plugins/DynamicLoader/Linux-DYLD/
source/Plugins/Process/Linux/
Message-ID: <20110116194540.1D4872A6C12C@llvm.org>
Author: wilsons
Date: Sun Jan 16 13:45:39 2011
New Revision: 123592
URL: http://llvm.org/viewvc/llvm-project?rev=123592&view=rev
Log:
Initial support for a DynamicLoader plugin on Linux.
This patch is enough to have shared objects recognized by LLDB. We can handle
position independent executables. We can handle dynamically loaded modules
brought in via dlopen.
The DYLDRendezvous class provides an interface to a structure present in the
address space of ELF-based processes. This structure provides the address of a
function which is called by the linker each time a shared object is loaded and
unloaded (thus a breakpoint at that address will let LLDB intercept such
events), a list of entries describing the currently loaded shared objects, plus
a few other things.
On Linux, processes are brought up with an auxiliary vector on the stack. One
element in this vector contains the (possibly dynamic) entry address of the
process. One does not need to walk the stack to find this information as it is
also available under /proc//auxv. The new AuxVector class provides a
convenient read-only view of this auxiliary vector information. We use the
dynamic entry address and the address as specified in the object file to compute
the actual load address of the inferior image. This strategy works for both
normal executables and PIE's.
Added:
lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/
lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp
lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h
lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp
lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h
lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp
lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h
lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/Makefile
Modified:
lldb/trunk/lib/Makefile
lldb/trunk/source/Plugins/Makefile
lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp
lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h
lldb/trunk/source/lldb.cpp
Modified: lldb/trunk/lib/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lib/Makefile?rev=123592&r1=123591&r2=123592&view=diff
==============================================================================
--- lldb/trunk/lib/Makefile (original)
+++ lldb/trunk/lib/Makefile Sun Jan 16 13:45:39 2011
@@ -67,7 +67,8 @@
endif
ifeq ($(HOST_OS),Linux)
- USEDLIBS += lldbPluginProcessLinux.a
+ USEDLIBS += lldbPluginProcessLinux.a \
+ lldbPluginDynamicLoaderLinux.a
endif
include $(LEVEL)/Makefile.common
Added: lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp?rev=123592&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp (added)
+++ lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp Sun Jan 16 13:45:39 2011
@@ -0,0 +1,191 @@
+//===-- AuxVector.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+#include
+#include
+#include
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Target/Process.h"
+
+#include "AuxVector.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static bool
+GetMaxU64(DataExtractor &data,
+ uint32_t *offset, uint64_t *value, unsigned int byte_size)
+{
+ uint32_t saved_offset = *offset;
+ *value = data.GetMaxU64(offset, byte_size);
+ return *offset != saved_offset;
+}
+
+static bool
+ParseAuxvEntry(DataExtractor &data, AuxVector::Entry &entry,
+ uint32_t *offset, unsigned int byte_size)
+{
+ if (!GetMaxU64(data, offset, &entry.type, byte_size))
+ return false;
+
+ if (!GetMaxU64(data, offset, &entry.value, byte_size))
+ return false;
+
+ return true;
+}
+
+DataBufferSP
+AuxVector::GetAuxvData()
+{
+ static const size_t path_size = 128;
+ static char path[path_size];
+ DataBufferSP buf_sp;
+ int fd;
+
+ // Ideally, we would simply create a FileSpec and call ReadFileContents.
+ // However, files in procfs have zero size (since they are, in general,
+ // dynamically generated by the kernel) which is incompatible with the
+ // current ReadFileContents implementation. Therefore we simply stream the
+ // data into a DataBuffer ourselves.
+ if (snprintf(path, path_size, "/proc/%d/auxv", m_process->GetID()) < 0)
+ return buf_sp;
+
+ if ((fd = open(path, O_RDONLY, 0)) < 0)
+ return buf_sp;
+
+ size_t bytes_read = 0;
+ std::auto_ptr buf_ap(new DataBufferHeap(1024, 0));
+ for (;;)
+ {
+ size_t avail = buf_ap->GetByteSize() - bytes_read;
+ ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail);
+
+ if (status < 0)
+ break;
+
+ bytes_read += status;
+
+ if (status == 0)
+ {
+ buf_ap->SetByteSize(bytes_read);
+ buf_sp.reset(buf_ap.release());
+ break;
+ }
+
+ if (avail - status == 0)
+ buf_ap->SetByteSize(2 * buf_ap->GetByteSize());
+ }
+
+ return buf_sp;
+}
+
+void
+AuxVector::ParseAuxv(DataExtractor &data)
+{
+ const unsigned int byte_size = m_process->GetAddressByteSize();
+ uint32_t offset = 0;
+
+ for (;;)
+ {
+ Entry entry;
+
+ if (!ParseAuxvEntry(data, entry, &offset, byte_size))
+ break;
+
+ if (entry.type == AT_NULL)
+ break;
+
+ if (entry.type == AT_IGNORE)
+ continue;
+
+ m_auxv.push_back(entry);
+ }
+}
+
+AuxVector::AuxVector(Process *process)
+ : m_process(process)
+{
+ DataExtractor data;
+ LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+
+ data.SetData(GetAuxvData());
+ data.SetByteOrder(m_process->GetByteOrder());
+ data.SetAddressByteSize(m_process->GetAddressByteSize());
+
+ ParseAuxv(data);
+
+ if (log)
+ DumpToLog(log);
+}
+
+AuxVector::iterator
+AuxVector::FindEntry(EntryType type) const
+{
+ for (iterator I = begin(); I != end(); ++I)
+ {
+ if (I->type == static_cast(type))
+ return I;
+ }
+
+ return end();
+}
+
+void
+AuxVector::DumpToLog(LogSP log) const
+{
+ if (!log)
+ return;
+
+ log->PutCString("AuxVector: ");
+ for (iterator I = begin(); I != end(); ++I)
+ {
+ log->Printf(" %s [%d]: %lx", GetEntryName(*I), I->type, I->value);
+ }
+}
+
+const char *
+AuxVector::GetEntryName(EntryType type)
+{
+ const char *name;
+
+#define ENTRY_NAME(_type) _type: name = #_type
+ switch (type)
+ {
+ default:
+ name = "unkown";
+ break;
+
+ case ENTRY_NAME(AT_NULL); break;
+ case ENTRY_NAME(AT_IGNORE); break;
+ case ENTRY_NAME(AT_EXECFD); break;
+ case ENTRY_NAME(AT_PHDR); break;
+ case ENTRY_NAME(AT_PHENT); break;
+ case ENTRY_NAME(AT_PHNUM); break;
+ case ENTRY_NAME(AT_PAGESZ); break;
+ case ENTRY_NAME(AT_BASE); break;
+ case ENTRY_NAME(AT_FLAGS); break;
+ case ENTRY_NAME(AT_ENTRY); break;
+ case ENTRY_NAME(AT_NOTELF); break;
+ case ENTRY_NAME(AT_UID); break;
+ case ENTRY_NAME(AT_EUID); break;
+ case ENTRY_NAME(AT_GID); break;
+ case ENTRY_NAME(AT_EGID); break;
+ case ENTRY_NAME(AT_CLKTCK); break;
+ }
+#undef ENTRY_NAME
+
+ return name;
+}
+
Added: lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h?rev=123592&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h (added)
+++ lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h Sun Jan 16 13:45:39 2011
@@ -0,0 +1,97 @@
+//===-- AuxVector.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_AuxVector_H_
+#define liblldb_AuxVector_H_
+
+// C Includes
+// C++ Includes
+#include
+
+// Other libraries and framework includes
+#include "lldb/lldb-forward-rtti.h"
+
+namespace lldb_private {
+class DataExtractor;
+}
+
+/// @class AuxVector
+/// @brief Represents a processes auxiliary vector.
+///
+/// When a process is loaded on Linux a vector of values is placed onto the
+/// stack communicating operating system specific information. On construction
+/// this class locates and parses this information and provides a simple
+/// read-only interface to the entries found.
+class AuxVector {
+
+public:
+ AuxVector(lldb_private::Process *process);
+
+ struct Entry {
+ uint64_t type;
+ uint64_t value;
+
+ Entry() : type(0), value(0) { }
+ };
+
+ /// Constants describing the type of entry.
+ enum EntryType {
+ AT_NULL = 0, ///< End of auxv.
+ AT_IGNORE = 1, ///< Ignore entry.
+ AT_EXECFD = 2, ///< File descriptor of program.
+ AT_PHDR = 3, ///< Program headers.
+ AT_PHENT = 4, ///< Size of program header.
+ AT_PHNUM = 5, ///< Number of program headers.
+ AT_PAGESZ = 6, ///< Page size.
+ AT_BASE = 7, ///< Interpreter base address.
+ AT_FLAGS = 8, ///< Flags.
+ AT_ENTRY = 9, ///< Program entry point.
+ AT_NOTELF = 10, ///< Set if program is not an ELF.
+ AT_UID = 11, ///< UID.
+ AT_EUID = 12, ///< Effective UID.
+ AT_GID = 13, ///< GID.
+ AT_EGID = 14, ///< Effective GID.
+ AT_CLKTCK = 17 ///< Clock frequency (e.g. times(2)).
+ };
+
+private:
+ typedef std::vector EntryVector;
+
+public:
+ typedef EntryVector::const_iterator iterator;
+
+ iterator begin() const { return m_auxv.begin(); }
+ iterator end() const { return m_auxv.end(); }
+
+ iterator
+ FindEntry(EntryType type) const;
+
+ static const char *
+ GetEntryName(const Entry &entry) {
+ return GetEntryName(static_cast(entry.type));
+ }
+
+ static const char *
+ GetEntryName(EntryType type);
+
+ void
+ DumpToLog(lldb::LogSP log) const;
+
+private:
+ lldb_private::Process *m_process;
+ EntryVector m_auxv;
+
+ lldb::DataBufferSP
+ GetAuxvData();
+
+ void
+ ParseAuxv(lldb_private::DataExtractor &data);
+};
+
+#endif
Added: lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp?rev=123592&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp (added)
+++ lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp Sun Jan 16 13:45:39 2011
@@ -0,0 +1,315 @@
+//===-- DYLDRendezvous.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "DYLDRendezvous.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+/// Locates the address of the rendezvous structure. Returns the address on
+/// success and LLDB_INVALID_ADDRESS on failure.
+static addr_t
+ResolveRendezvousAddress(Process *process)
+{
+ addr_t info_location;
+ addr_t info_addr;
+ Error error;
+ size_t size;
+
+ info_location = process->GetImageInfoAddress();
+
+ if (info_location == LLDB_INVALID_ADDRESS)
+ return LLDB_INVALID_ADDRESS;
+
+ info_addr = 0;
+ size = process->DoReadMemory(info_location, &info_addr,
+ process->GetAddressByteSize(), error);
+ if (size != process->GetAddressByteSize() || error.Fail())
+ return LLDB_INVALID_ADDRESS;
+
+ if (info_addr == 0)
+ return LLDB_INVALID_ADDRESS;
+
+ return info_addr;
+}
+
+DYLDRendezvous::DYLDRendezvous(Process *process)
+ : m_process(process),
+ m_rendezvous_addr(LLDB_INVALID_ADDRESS),
+ m_current(),
+ m_previous(),
+ m_soentries(),
+ m_added_soentries(),
+ m_removed_soentries()
+{
+}
+
+bool
+DYLDRendezvous::Resolve()
+{
+ const size_t word_size = 4;
+ Rendezvous info;
+ size_t address_size;
+ size_t padding;
+ addr_t info_addr;
+ addr_t cursor;
+
+ address_size = m_process->GetAddressByteSize();
+ padding = address_size - word_size;
+
+ if (m_rendezvous_addr == LLDB_INVALID_ADDRESS)
+ cursor = info_addr = ResolveRendezvousAddress(m_process);
+ else
+ cursor = info_addr = m_rendezvous_addr;
+
+ if (cursor == LLDB_INVALID_ADDRESS)
+ return false;
+
+ if (!(cursor = ReadMemory(cursor, &info.version, word_size)))
+ return false;
+
+ if (!(cursor = ReadMemory(cursor + padding, &info.map_addr, address_size)))
+ return false;
+
+ if (!(cursor = ReadMemory(cursor, &info.brk, address_size)))
+ return false;
+
+ if (!(cursor = ReadMemory(cursor, &info.state, word_size)))
+ return false;
+
+ if (!(cursor = ReadMemory(cursor + padding, &info.ldbase, address_size)))
+ return false;
+
+ // The rendezvous was successfully read. Update our internal state.
+ m_rendezvous_addr = info_addr;
+ m_previous = m_current;
+ m_current = info;
+
+ return UpdateSOEntries();
+}
+
+bool
+DYLDRendezvous::IsValid()
+{
+ return m_rendezvous_addr != LLDB_INVALID_ADDRESS;
+}
+
+bool
+DYLDRendezvous::UpdateSOEntries()
+{
+ SOEntry entry;
+
+ if (m_current.map_addr == 0)
+ return false;
+
+ // If we are about to add or remove a shared object clear out the current
+ // state and take a snapshot of the currently loaded images.
+ if (m_current.state == eAdd || m_current.state == eDelete)
+ {
+ assert(m_previous.state == eConsistent);
+ m_soentries.clear();
+ m_added_soentries.clear();
+ m_removed_soentries.clear();
+ return TakeSnapshot(m_soentries);
+ }
+
+ // Otherwise check the previous state to determine what to expect and update
+ // accordingly.
+ if (m_previous.state == eAdd)
+ return UpdateSOEntriesForAddition();
+ else if (m_previous.state == eDelete)
+ return UpdateSOEntriesForDeletion();
+
+ return false;
+}
+
+bool
+DYLDRendezvous::UpdateSOEntriesForAddition()
+{
+ SOEntry entry;
+ iterator pos;
+
+ assert(m_previous.state == eAdd);
+
+ if (m_current.map_addr == 0)
+ return false;
+
+ for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
+ {
+ if (!ReadSOEntryFromMemory(cursor, entry))
+ return false;
+
+ if (entry.path.empty())
+ continue;
+
+ pos = std::find(m_soentries.begin(), m_soentries.end(), entry);
+ if (pos == m_soentries.end())
+ {
+ m_soentries.push_back(entry);
+ m_added_soentries.push_back(entry);
+ }
+ }
+
+ return true;
+}
+
+bool
+DYLDRendezvous::UpdateSOEntriesForDeletion()
+{
+ SOEntryList entry_list;
+ iterator pos;
+
+ assert(m_previous.state == eDelete);
+
+ if (!TakeSnapshot(entry_list))
+ return false;
+
+ for (iterator I = begin(); I != end(); ++I)
+ {
+ pos = std::find(entry_list.begin(), entry_list.end(), *I);
+ if (pos == entry_list.end())
+ m_removed_soentries.push_back(*I);
+ }
+
+ m_soentries = entry_list;
+ return true;
+}
+
+bool
+DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list)
+{
+ SOEntry entry;
+
+ if (m_current.map_addr == 0)
+ return false;
+
+ for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
+ {
+ if (!ReadSOEntryFromMemory(cursor, entry))
+ return false;
+
+ if (entry.path.empty())
+ continue;
+
+ entry_list.push_back(entry);
+ }
+
+ return true;
+}
+
+addr_t
+DYLDRendezvous::ReadMemory(addr_t addr, void *dst, size_t size)
+{
+ size_t bytes_read;
+ Error error;
+
+ bytes_read = m_process->DoReadMemory(addr, dst, size, error);
+ if (bytes_read != size || error.Fail())
+ return 0;
+
+ return addr + bytes_read;
+}
+
+std::string
+DYLDRendezvous::ReadStringFromMemory(addr_t addr)
+{
+ std::string str;
+ Error error;
+ size_t size;
+ char c;
+
+ if (addr == LLDB_INVALID_ADDRESS)
+ return std::string();
+
+ for (;;) {
+ size = m_process->DoReadMemory(addr, &c, 1, error);
+ if (size != 1 || error.Fail())
+ return std::string();
+ if (c == 0)
+ break;
+ else {
+ str.push_back(c);
+ addr++;
+ }
+ }
+
+ return str;
+}
+
+bool
+DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
+{
+ size_t address_size = m_process->GetAddressByteSize();
+
+ entry.clear();
+
+ if (!(addr = ReadMemory(addr, &entry.base_addr, address_size)))
+ return false;
+
+ if (!(addr = ReadMemory(addr, &entry.path_addr, address_size)))
+ return false;
+
+ if (!(addr = ReadMemory(addr, &entry.dyn_addr, address_size)))
+ return false;
+
+ if (!(addr = ReadMemory(addr, &entry.next, address_size)))
+ return false;
+
+ if (!(addr = ReadMemory(addr, &entry.prev, address_size)))
+ return false;
+
+ entry.path = ReadStringFromMemory(entry.path_addr);
+
+ return true;
+}
+
+void
+DYLDRendezvous::DumpToLog(LogSP log) const
+{
+ int state = GetState();
+
+ if (!log)
+ return;
+
+ log->PutCString("DYLDRendezvous:");
+ log->Printf(" Address: %lx", GetRendezvousAddress());
+ log->Printf(" Version: %d", GetVersion());
+ log->Printf(" Link : %lx", GetLinkMapAddress());
+ log->Printf(" Break : %lx", GetBreakAddress());
+ log->Printf(" LDBase : %lx", GetLDBase());
+ log->Printf(" State : %s",
+ (state == eConsistent) ? "consistent" :
+ (state == eAdd) ? "add" :
+ (state == eDelete) ? "delete" : "unknown");
+
+ iterator I = begin();
+ iterator E = end();
+
+ if (I != E)
+ log->PutCString("DYLDRendezvous SOEntries:");
+
+ for (int i = 1; I != E; ++I, ++i)
+ {
+ log->Printf("\n SOEntry [%d] %s", i, I->path.c_str());
+ log->Printf(" Base : %lx", I->base_addr);
+ log->Printf(" Path : %lx", I->path_addr);
+ log->Printf(" Dyn : %lx", I->dyn_addr);
+ log->Printf(" Next : %lx", I->next);
+ log->Printf(" Prev : %lx", I->prev);
+ }
+}
Added: lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h?rev=123592&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h (added)
+++ lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h Sun Jan 16 13:45:39 2011
@@ -0,0 +1,227 @@
+//===-- DYLDRendezvous.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Rendezvous_H_
+#define liblldb_Rendezvous_H_
+
+// C Includes
+// C++ Includes
+#include
+#include
+
+// Other libraries and framework includes
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-types.h"
+
+namespace lldb_private {
+class Process;
+}
+
+/// @class DYLDRendezvous
+/// @brief Interface to the runtime linker.
+///
+/// A structure is present in a processes memory space which is updated by the
+/// runtime liker each time a module is loaded or unloaded. This class provides
+/// an interface to this structure and maintains a consistent snapshot of the
+/// currently loaded modules.
+class DYLDRendezvous {
+
+ // This structure is used to hold the contents of the debug rendezvous
+ // information (struct r_debug) as found in the inferiors memory. Note that
+ // the layout of this struct is not binary compatible, it is simply large
+ // enough to hold the information on both 32 and 64 bit platforms.
+ struct Rendezvous {
+ uint64_t version;
+ lldb::addr_t map_addr;
+ lldb::addr_t brk;
+ uint64_t state;
+ lldb::addr_t ldbase;
+
+ Rendezvous()
+ : version(0), map_addr(0), brk(0), state(0), ldbase(0) { }
+ };
+
+public:
+ DYLDRendezvous(lldb_private::Process *process);
+
+ /// Update the internal snapshot of runtime linker rendezvous and recompute
+ /// the currently loaded modules.
+ ///
+ /// This method should be called once one start up, then once each time the
+ /// runtime linker enters the function given by GetBreakAddress().
+ ///
+ /// @returns true on success and false on failure.
+ ///
+ /// @see GetBreakAddress().
+ bool
+ Resolve();
+
+ /// @returns true if this rendezvous has been located in the inferiors
+ /// address space and false otherwise.
+ bool
+ IsValid();
+
+ /// @returns the address of the rendezvous structure in the inferiors
+ /// address space.
+ lldb::addr_t
+ GetRendezvousAddress() const { return m_rendezvous_addr; }
+
+ /// @returns the version of the rendezvous protocol being used.
+ int
+ GetVersion() const { return m_current.version; }
+
+ /// @returns address in the inferiors address space containing the linked
+ /// list of shared object descriptors.
+ lldb::addr_t
+ GetLinkMapAddress() const { return m_current.map_addr; }
+
+ /// A breakpoint should be set at this address and Resolve called on each
+ /// hit.
+ ///
+ /// @returns the address of a function called by the runtime linker each
+ /// time a module is loaded/unloaded, or about to be loaded/unloaded.
+ ///
+ /// @see Resolve()
+ lldb::addr_t
+ GetBreakAddress() const { return m_current.brk; }
+
+ /// Returns the current state of the rendezvous structure.
+ int
+ GetState() const { return m_current.state; }
+
+ /// @returns the base address of the runtime linker in the inferiors address
+ /// space.
+ lldb::addr_t
+ GetLDBase() const { return m_current.ldbase; }
+
+ /// @returns true if modules have been loaded into the inferior since the
+ /// last call to Resolve().
+ bool
+ ModulesDidLoad() const { return !m_added_soentries.empty(); }
+
+ /// @returns true if modules have been unloaded from the inferior since the
+ /// last call to Resolve().
+ bool
+ ModulesDidUnload() const { return !m_removed_soentries.empty(); }
+
+ void
+ DumpToLog(lldb::LogSP log) const;
+
+ /// @brief Constants describing the state of the rendezvous.
+ ///
+ /// @see GetState().
+ enum RendezvousState {
+ eConsistent,
+ eAdd,
+ eDelete
+ };
+
+ /// @brief Structure representing the shared objects currently loaded into
+ /// the inferior process.
+ ///
+ /// This object is a rough analogue to the struct link_map object which
+ /// actually lives in the inferiors memory.
+ struct SOEntry {
+ lldb::addr_t base_addr; ///< Base address of the loaded object.
+ lldb::addr_t path_addr; ///< String naming the shared object.
+ lldb::addr_t dyn_addr; ///< Dynamic section of shared object.
+ lldb::addr_t next; ///< Address of next so_entry.
+ lldb::addr_t prev; ///< Address of previous so_entry.
+ std::string path; ///< File name of shared object.
+
+ SOEntry() { clear(); }
+
+ bool operator ==(const SOEntry &entry) {
+ return this->path == entry.path;
+ }
+
+ void clear() {
+ base_addr = 0;
+ path_addr = 0;
+ dyn_addr = 0;
+ next = 0;
+ prev = 0;
+ path.clear();
+ }
+ };
+
+protected:
+ typedef std::list SOEntryList;
+
+public:
+ typedef SOEntryList::const_iterator iterator;
+
+ /// Iterators over all currently loaded modules.
+ iterator begin() const { return m_soentries.begin(); }
+ iterator end() const { return m_soentries.end(); }
+
+ /// Iterators over all modules loaded into the inferior since the last call
+ /// to Resolve().
+ iterator loaded_begin() const { return m_added_soentries.begin(); }
+ iterator loaded_end() const { return m_added_soentries.end(); }
+
+ /// Iterators over all modules unloaded from the inferior since the last
+ /// call to Resolve().
+ iterator unloaded_begin() const { return m_removed_soentries.begin(); }
+ iterator unloaded_end() const { return m_removed_soentries.end(); }
+
+protected:
+ lldb_private::Process *m_process;
+
+ /// Location of the r_debug structure in the inferiors address space.
+ lldb::addr_t m_rendezvous_addr;
+
+ /// Current and previous snapshots of the rendezvous structure.
+ Rendezvous m_current;
+ Rendezvous m_previous;
+
+ /// List of SOEntry objects corresponding to the current link map state.
+ SOEntryList m_soentries;
+
+ /// List of SOEntry's added to the link map since the last call to Resolve().
+ SOEntryList m_added_soentries;
+
+ /// List of SOEntry's removed from the link map since the last call to
+ /// Resolve().
+ SOEntryList m_removed_soentries;
+
+ /// Reads @p size bytes from the inferiors address space starting at @p
+ /// addr.
+ ///
+ /// @returns addr + size if the read was successful and false otherwise.
+ lldb::addr_t
+ ReadMemory(lldb::addr_t addr, void *dst, size_t size);
+
+ /// Reads a null-terminated C string from the memory location starting at @p
+ /// addr.
+ std::string
+ ReadStringFromMemory(lldb::addr_t addr);
+
+ /// Reads an SOEntry starting at @p addr.
+ bool
+ ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry);
+
+ /// Updates the current set of SOEntries, the set of added entries, and the
+ /// set of removed entries.
+ bool
+ UpdateSOEntries();
+
+ bool
+ UpdateSOEntriesForAddition();
+
+ bool
+ UpdateSOEntriesForDeletion();
+
+ /// Reads the current list of shared objects according to the link map
+ /// supplied by the runtime linker.
+ bool
+ TakeSnapshot(SOEntryList &entry_list);
+};
+
+#endif
Added: lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp?rev=123592&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp (added)
+++ lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp Sun Jan 16 13:45:39 2011
@@ -0,0 +1,371 @@
+//===-- DynamicLoaderLinux.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+#include
+
+// Other libraries and framework includes
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "AuxVector.h"
+#include "DynamicLoaderLinuxDYLD.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+DynamicLoaderLinuxDYLD::Initialize()
+{
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(),
+ CreateInstance);
+}
+
+void
+DynamicLoaderLinuxDYLD::Terminate()
+{
+}
+
+const char *
+DynamicLoaderLinuxDYLD::GetPluginName()
+{
+ return "DynamicLoaderLinuxDYLD";
+}
+
+const char *
+DynamicLoaderLinuxDYLD::GetShortPluginName()
+{
+ return "linux-dyld";
+}
+
+const char *
+DynamicLoaderLinuxDYLD::GetPluginNameStatic()
+{
+ return "dynamic-loader.linux-dyld";
+}
+
+const char *
+DynamicLoaderLinuxDYLD::GetPluginDescriptionStatic()
+{
+ return "Dynamic loader plug-in that watches for shared library "
+ "loads/unloads in Linux processes.";
+}
+
+void
+DynamicLoaderLinuxDYLD::GetPluginCommandHelp(const char *command, Stream *strm)
+{
+}
+
+uint32_t
+DynamicLoaderLinuxDYLD::GetPluginVersion()
+{
+ return 1;
+}
+
+DynamicLoader *
+DynamicLoaderLinuxDYLD::CreateInstance(Process *process)
+{
+ return new DynamicLoaderLinuxDYLD(process);
+}
+
+DynamicLoaderLinuxDYLD::DynamicLoaderLinuxDYLD(Process *process)
+ : DynamicLoader(process),
+ m_rendezvous(process),
+ m_load_offset(LLDB_INVALID_ADDRESS),
+ m_entry_point(LLDB_INVALID_ADDRESS),
+ m_auxv(NULL)
+{
+}
+
+DynamicLoaderLinuxDYLD::~DynamicLoaderLinuxDYLD()
+{
+}
+
+void
+DynamicLoaderLinuxDYLD::DidAttach()
+{
+ ModuleSP executable;
+ addr_t load_offset;
+
+ m_auxv.reset(new AuxVector(m_process));
+
+ executable = m_process->GetTarget().GetExecutableModule();
+ load_offset = ComputeLoadOffset();
+
+ if (!executable.empty() && load_offset != LLDB_INVALID_ADDRESS)
+ {
+ ModuleList module_list;
+ module_list.Append(executable);
+ UpdateLoadedSections(executable, load_offset);
+ m_process->GetTarget().ModulesDidLoad(module_list);
+ }
+}
+
+void
+DynamicLoaderLinuxDYLD::DidLaunch()
+{
+ ModuleSP executable;
+ addr_t load_offset;
+
+ m_auxv.reset(new AuxVector(m_process));
+
+ executable = m_process->GetTarget().GetExecutableModule();
+ load_offset = ComputeLoadOffset();
+
+ if (!executable.empty() && load_offset != LLDB_INVALID_ADDRESS)
+ {
+ ModuleList module_list;
+ module_list.Append(executable);
+ UpdateLoadedSections(executable, load_offset);
+ ProbeEntry();
+ m_process->GetTarget().ModulesDidLoad(module_list);
+ }
+}
+
+Error
+DynamicLoaderLinuxDYLD::ExecutePluginCommand(Args &command, Stream *strm)
+{
+ return Error();
+}
+
+Log *
+DynamicLoaderLinuxDYLD::EnablePluginLogging(Stream *strm, Args &command)
+{
+ return NULL;
+}
+
+Error
+DynamicLoaderLinuxDYLD::CanLoadImage()
+{
+ return Error();
+}
+
+void
+DynamicLoaderLinuxDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr)
+{
+ ObjectFile *obj_file = module->GetObjectFile();
+ SectionList *sections = obj_file->GetSectionList();
+ SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList();
+ const size_t num_sections = sections->GetSize();
+
+ for (unsigned i = 0; i < num_sections; ++i)
+ {
+ Section *section = sections->GetSectionAtIndex(i).get();
+ lldb::addr_t new_load_addr = section->GetFileAddress() + base_addr;
+ lldb::addr_t old_load_addr = load_list.GetSectionLoadAddress(section);
+
+ // If the file address of the section is zero then this is not an
+ // allocatable/loadable section (property of ELF sh_addr). Skip it.
+ if (new_load_addr == base_addr)
+ continue;
+
+ if (old_load_addr == LLDB_INVALID_ADDRESS ||
+ old_load_addr != new_load_addr)
+ load_list.SetSectionLoadAddress(section, new_load_addr);
+ }
+}
+
+void
+DynamicLoaderLinuxDYLD::ProbeEntry()
+{
+ Breakpoint *entry_break;
+ addr_t entry;
+
+ if ((entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS)
+ return;
+
+ entry_break = m_process->GetTarget().CreateBreakpoint(entry, true).get();
+ entry_break->SetCallback(EntryBreakpointHit, this, true);
+}
+
+// The runtime linker has run and initialized the rendezvous structure once the
+// process has hit its entry point. When we hit the corresponding breakpoint we
+// interrogate the rendezvous structure to get the load addresses of all
+// dependent modules for the process. Similarly, we can discover the runtime
+// linker function and setup a breakpoint to notify us of any dynamically loaded
+// modules (via dlopen).
+bool
+DynamicLoaderLinuxDYLD::EntryBreakpointHit(void *baton,
+ StoppointCallbackContext *context,
+ user_id_t break_id,
+ user_id_t break_loc_id)
+{
+ DynamicLoaderLinuxDYLD* dyld_instance;
+
+ dyld_instance = static_cast(baton);
+ dyld_instance->LoadAllCurrentModules();
+ dyld_instance->SetRendezvousBreakpoint();
+ return false; // Continue running.
+}
+
+void
+DynamicLoaderLinuxDYLD::SetRendezvousBreakpoint()
+{
+ Breakpoint *dyld_break;
+ addr_t break_addr;
+
+ break_addr = m_rendezvous.GetBreakAddress();
+ dyld_break = m_process->GetTarget().CreateBreakpoint(break_addr, true).get();
+ dyld_break->SetCallback(RendezvousBreakpointHit, this, true);
+}
+
+bool
+DynamicLoaderLinuxDYLD::RendezvousBreakpointHit(void *baton,
+ StoppointCallbackContext *context,
+ user_id_t break_id,
+ user_id_t break_loc_id)
+{
+ DynamicLoaderLinuxDYLD* dyld_instance;
+
+ dyld_instance = static_cast(baton);
+ dyld_instance->RefreshModules();
+
+ // Return true to stop the target, false to just let the target run.
+ return dyld_instance->GetStopWhenImagesChange();
+}
+
+void
+DynamicLoaderLinuxDYLD::RefreshModules()
+{
+ if (!m_rendezvous.Resolve())
+ return;
+
+ DYLDRendezvous::iterator I;
+ DYLDRendezvous::iterator E;
+
+ ModuleList &loaded_modules = m_process->GetTarget().GetImages();
+
+ if (m_rendezvous.ModulesDidLoad())
+ {
+ ModuleList new_modules;
+
+ E = m_rendezvous.loaded_end();
+ for (I = m_rendezvous.loaded_begin(); I != E; ++I)
+ {
+ FileSpec file(I->path.c_str(), true);
+ ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);
+ if (!module_sp.empty())
+ new_modules.Append(module_sp);
+ }
+ m_process->GetTarget().ModulesDidLoad(new_modules);
+ }
+
+ if (m_rendezvous.ModulesDidUnload())
+ {
+ ModuleList old_modules;
+
+ E = m_rendezvous.unloaded_end();
+ for (I = m_rendezvous.unloaded_begin(); I != E; ++I)
+ {
+ FileSpec file(I->path.c_str(), true);
+ ModuleSP module_sp = loaded_modules.FindFirstModuleForFileSpec(file);
+ if (!module_sp.empty())
+ old_modules.Append(module_sp);
+ }
+ m_process->GetTarget().ModulesDidUnload(old_modules);
+ }
+}
+
+ThreadPlanSP
+DynamicLoaderLinuxDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop_others)
+{
+ LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ ThreadPlanSP thread_plan_sp;
+
+ if (log)
+ log->PutCString("DynamicLoaderLinuxDYLD: "
+ "GetStepThroughTrampolinePlan not implemented\n");
+
+ return thread_plan_sp;
+}
+
+void
+DynamicLoaderLinuxDYLD::LoadAllCurrentModules()
+{
+ DYLDRendezvous::iterator I;
+ DYLDRendezvous::iterator E;
+ ModuleList module_list;
+
+ if (!m_rendezvous.Resolve())
+ return;
+
+ for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)
+ {
+ FileSpec file(I->path.c_str(), false);
+ ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);
+ if (!module_sp.empty())
+ module_list.Append(module_sp);
+ }
+
+ m_process->GetTarget().ModulesDidLoad(module_list);
+}
+
+ModuleSP
+DynamicLoaderLinuxDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_addr)
+{
+ Target &target = m_process->GetTarget();
+ ModuleList &modules = target.GetImages();
+ ModuleSP module_sp;
+
+ if ((module_sp = modules.FindFirstModuleForFileSpec(file)))
+ {
+ UpdateLoadedSections(module_sp, base_addr);
+ }
+ else if ((module_sp = target.GetSharedModule(file, target.GetArchitecture())))
+ {
+ UpdateLoadedSections(module_sp, base_addr);
+ modules.Append(module_sp);
+ }
+
+ return module_sp;
+}
+
+addr_t
+DynamicLoaderLinuxDYLD::ComputeLoadOffset()
+{
+ addr_t virt_entry;
+
+ if (m_load_offset != LLDB_INVALID_ADDRESS)
+ return m_load_offset;
+
+ if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS)
+ return LLDB_INVALID_ADDRESS;
+
+ ModuleSP module = m_process->GetTarget().GetExecutableModule();
+ ObjectFile *exe = module->GetObjectFile();
+ Address file_entry = exe->GetEntryPoint();
+
+ if (!file_entry.IsValid())
+ return LLDB_INVALID_ADDRESS;
+
+ m_load_offset = virt_entry - file_entry.GetFileAddress();
+ return m_load_offset;
+}
+
+addr_t
+DynamicLoaderLinuxDYLD::GetEntryPoint()
+{
+ if (m_entry_point != LLDB_INVALID_ADDRESS)
+ return m_entry_point;
+
+ if (m_auxv.get() == NULL)
+ return LLDB_INVALID_ADDRESS;
+
+ AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY);
+
+ if (I == m_auxv->end())
+ return LLDB_INVALID_ADDRESS;
+
+ m_entry_point = static_cast(I->value);
+ return m_entry_point;
+}
Added: lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h?rev=123592&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h (added)
+++ lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h Sun Jan 16 13:45:39 2011
@@ -0,0 +1,165 @@
+//===-- DynamicLoaderLinux.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_DynamicLoaderLinux_H_
+#define liblldb_DynamicLoaderLinux_H_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Target/DynamicLoader.h"
+
+#include "DYLDRendezvous.h"
+
+class AuxVector;
+
+class DynamicLoaderLinuxDYLD : public lldb_private::DynamicLoader
+{
+public:
+
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static const char *
+ GetPluginNameStatic();
+
+ static const char *
+ GetPluginDescriptionStatic();
+
+ static lldb_private::DynamicLoader *
+ CreateInstance(lldb_private::Process *process);
+
+ DynamicLoaderLinuxDYLD(lldb_private::Process *process);
+
+ virtual
+ ~DynamicLoaderLinuxDYLD();
+
+ //------------------------------------------------------------------
+ // DynamicLoader protocol
+ //------------------------------------------------------------------
+
+ virtual void
+ DidAttach();
+
+ virtual void
+ DidLaunch();
+
+ virtual lldb::ThreadPlanSP
+ GetStepThroughTrampolinePlan(lldb_private::Thread &thread,
+ bool stop_others);
+
+ virtual lldb_private::Error
+ CanLoadImage();
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ virtual const char *
+ GetPluginName();
+
+ virtual const char *
+ GetShortPluginName();
+
+ virtual uint32_t
+ GetPluginVersion();
+
+ virtual void
+ GetPluginCommandHelp(const char *command, lldb_private::Stream *strm);
+
+ virtual lldb_private::Error
+ ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm);
+
+ virtual lldb_private::Log *
+ EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command);
+
+protected:
+ /// Runtime linker rendezvous structure.
+ DYLDRendezvous m_rendezvous;
+
+ /// Virtual load address of the inferior process.
+ lldb::addr_t m_load_offset;
+
+ /// Virtual entry address of the inferior process.
+ lldb::addr_t m_entry_point;
+
+ /// Auxiliary vector of the inferior process.
+ std::auto_ptr m_auxv;
+
+ /// Enables a breakpoint on a function called by the runtime
+ /// linker each time a module is loaded or unloaded.
+ void
+ SetRendezvousBreakpoint();
+
+ /// Callback routine which updates the current list of loaded modules based
+ /// on the information supplied by the runtime linker.
+ static bool
+ RendezvousBreakpointHit(void *baton,
+ lldb_private::StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
+
+ /// Helper method for RendezvousBreakpointHit. Updates LLDB's current set
+ /// of loaded modules.
+ void
+ RefreshModules();
+
+ /// Updates the load address of every allocatable section in @p module.
+ ///
+ /// @param module The module to traverse.
+ ///
+ /// @param base_addr The virtual base address @p module is loaded at.
+ void
+ UpdateLoadedSections(lldb::ModuleSP module,
+ lldb::addr_t base_addr = 0);
+
+ /// Locates or creates a module given by @p file and updates/loads the
+ /// resulting module at the virtual base address @p base_addr.
+ lldb::ModuleSP
+ LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t base_addr);
+
+ /// Resolves the entry point for the current inferior process and sets a
+ /// breakpoint at that address.
+ void
+ ProbeEntry();
+
+ /// Callback routine invoked when we hit the breakpoint on process entry.
+ ///
+ /// This routine is responsible for resolving the load addresses of all
+ /// dependent modules required by the inferior and setting up the rendezvous
+ /// breakpoint.
+ static bool
+ EntryBreakpointHit(void *baton,
+ lldb_private::StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
+
+ /// Helper for the entry breakpoint callback. Resolves the load addresses
+ /// of all dependent modules.
+ void
+ LoadAllCurrentModules();
+
+ /// Computes a value for m_load_offset returning the computed address on
+ /// success and LLDB_INVALID_ADDRESS on failure.
+ lldb::addr_t
+ ComputeLoadOffset();
+
+ /// Computes a value for m_entry_point returning the computed address on
+ /// success and LLDB_INVALID_ADDRESS on failure.
+ lldb::addr_t
+ GetEntryPoint();
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(DynamicLoaderLinuxDYLD);
+};
+
+#endif // liblldb_DynamicLoaderLinuxDYLD_H_
Added: lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/Makefile?rev=123592&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/Makefile (added)
+++ lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/Makefile Sun Jan 16 13:45:39 2011
@@ -0,0 +1,14 @@
+##===- source/Plugins/DynamicLoader/Linux-DYLD/Makefile ----*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LLDB_LEVEL := ../../../..
+LIBRARYNAME := lldbPluginDynamicLoaderLinux
+BUILD_ARCHIVE = 1
+
+include $(LLDB_LEVEL)/Makefile
Modified: lldb/trunk/source/Plugins/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Makefile?rev=123592&r1=123591&r2=123592&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Makefile (original)
+++ lldb/trunk/source/Plugins/Makefile Sun Jan 16 13:45:39 2011
@@ -23,7 +23,7 @@
endif
ifeq ($(HOST_OS),Linux)
-DIRS += Process/Linux
+DIRS += Process/Linux DynamicLoader/Linux-DYLD
endif
include $(LLDB_LEVEL)/Makefile
Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp?rev=123592&r1=123591&r2=123592&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp Sun Jan 16 13:45:39 2011
@@ -13,6 +13,7 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Target.h"
#include "ProcessLinux.h"
@@ -102,6 +103,19 @@
}
Error
+ProcessLinux::WillLaunch(Module* module)
+{
+ Error error;
+
+ m_dyld_ap.reset(DynamicLoader::FindPlugin(this, "dynamic-loader.linux-dyld"));
+ if (m_dyld_ap.get() == NULL)
+ error.SetErrorString("unable to find the dynamic loader named "
+ "'dynamic-loader.linux-dyld'");
+
+ return error;
+}
+
+Error
ProcessLinux::DoLaunch(Module *module,
char const *argv[],
char const *envp[],
@@ -128,6 +142,13 @@
return error;
}
+void
+ProcessLinux::DidLaunch()
+{
+ if (m_dyld_ap.get() != NULL)
+ m_dyld_ap->DidLaunch();
+}
+
Error
ProcessLinux::DoResume()
{
@@ -371,6 +392,12 @@
return m_byte_order;
}
+DynamicLoader *
+ProcessLinux::GetDynamicLoader()
+{
+ return m_dyld_ap.get();
+}
+
//------------------------------------------------------------------------------
// ProcessInterface protocol.
Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h?rev=123592&r1=123591&r2=123592&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h Sun Jan 16 13:45:39 2011
@@ -60,6 +60,9 @@
CanDebug(lldb_private::Target &target);
virtual lldb_private::Error
+ WillLaunch(lldb_private::Module *module);
+
+ virtual lldb_private::Error
DoAttachToProcessWithID(lldb::pid_t pid);
virtual lldb_private::Error
@@ -71,6 +74,9 @@
const char *stdout_path,
const char *stderr_path);
+ virtual void
+ DidLaunch();
+
virtual lldb_private::Error
DoResume();
@@ -131,6 +137,9 @@
virtual lldb::addr_t
GetImageInfoAddress();
+ virtual lldb_private::DynamicLoader *
+ GetDynamicLoader();
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -176,6 +185,9 @@
lldb_private::Mutex m_message_mutex;
std::queue m_message_queue;
+ /// Dynamic loader plugin associated with this process.
+ std::auto_ptr m_dyld_ap;
+
/// Updates the loaded sections provided by the executable.
///
/// FIXME: It would probably be better to delegate this task to the
Modified: lldb/trunk/source/lldb.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/lldb.cpp?rev=123592&r1=123591&r2=123592&view=diff
==============================================================================
--- lldb/trunk/source/lldb.cpp (original)
+++ lldb/trunk/source/lldb.cpp Sun Jan 16 13:45:39 2011
@@ -44,6 +44,7 @@
#ifdef __linux__
#include "Plugins/Process/Linux/ProcessLinux.h"
+#include "Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h"
#endif
using namespace lldb;
@@ -94,6 +95,7 @@
#endif
#ifdef __linux__
ProcessLinux::Initialize();
+ DynamicLoaderLinuxDYLD::Initialize();
#endif
}
}
@@ -137,6 +139,7 @@
#ifdef __linux__
ProcessLinux::Terminate();
+ DynamicLoaderLinuxDYLD::Terminate();
#endif
Log::Terminate();
From wilsons at start.ca Sun Jan 16 14:25:22 2011
From: wilsons at start.ca (Stephen Wilson)
Date: Sun, 16 Jan 2011 15:25:22 -0500
Subject: [Lldb-commits] [PATCH][RFC] Linux DynamicLoader plugin.
In-Reply-To: (Greg Clayton's
message of "Sat, 15 Jan 2011 15:48:37 -0800")
References:
Message-ID:
Greg Clayton writes:
> Looks good, and great news that linux now has a dynamic loader.
Committed in r123592.
> The nice thing is if you want remote linux debugging, we can modify
> the ProcessGDBRemote plug-in, on linux by default, to use this dynamic
> loader plug-in since they are completely pluggable. We would need to
> just write a linux remote debug server. The current "debugserver"
> project really needs to be re-written from the ground up using the
> classes we have in LLDB (StringExtractor, GDBRemoteCommunication,
> StringExtractorGDBRemote).
Out of curiosity, would you be OK with a debug server written in plain
C? Main reason is that on many embedded systems a C++ runtime is not
available. I do not have any plans at the moment to work on it, I am
just curious if such an effort could be folded into LLDB proper instead
of being an independent project.
> One might also be able to make slight modifications to the existing
> GDB gdbserver binary (from the current GDB sources) for linux, and use
> it as the remote stub to connect to with LLDB!
That is an interesting option. Will keep it in mind.
Take care,
--
steve
From gclayton at apple.com Sun Jan 16 20:02:07 2011
From: gclayton at apple.com (Greg Clayton)
Date: Sun, 16 Jan 2011 18:02:07 -0800
Subject: [Lldb-commits] [PATCH][RFC] Linux DynamicLoader plugin.
In-Reply-To:
References:
Message-ID:
On Jan 16, 2011, at 12:25 PM, Stephen Wilson wrote:
> Greg Clayton writes:
>> Looks good, and great news that linux now has a dynamic loader.
>
> Committed in r123592.
>
>> The nice thing is if you want remote linux debugging, we can modify
>> the ProcessGDBRemote plug-in, on linux by default, to use this dynamic
>> loader plug-in since they are completely pluggable. We would need to
>> just write a linux remote debug server. The current "debugserver"
>> project really needs to be re-written from the ground up using the
>> classes we have in LLDB (StringExtractor, GDBRemoteCommunication,
>> StringExtractorGDBRemote).
>
> Out of curiosity, would you be OK with a debug server written in plain
> C? Main reason is that on many embedded systems a C++ runtime is not
> available. I do not have any plans at the moment to work on it, I am
> just curious if such an effort could be folded into LLDB proper instead
> of being an independent project.
Anyone else is welcome to do this, but on darwin, we won't be doing this. Why? We want to be sure to share the debugging backend for both the native and remote debugging. Right now we have disabled the native debugging plug-in for MacOSX and we debug remotely even when debugging local processes. We do this by spawning a debugserver instance and attach to a known port number (passed in via a command line option) and then have the debugserver launch the inferior process. Partly to insulate lldb from bad things happening to parent processes when debugging a child process, and partly so we are just ready for remote debugging. Soon we plan to re-enable the native debugging plug-in, but we plan to switch over to using the DNB.h interface that we use inside debugserver for local debugging. Previously we were maintaining both a copy of the debugging backend in both debugserver and in ProcessMacOSX which was a bit tedious and sometimes we would fix something in one and not the other.
BTW: the interface in DNB.h is a nice concise C level debugging interface that could be used for the simpler GDB remote server. If the GDB remote server was written in C, then each new debug target could just implement their own implementation of the DNB.h interface and have it both work for native and remote debugging. The interface in DNB.h is designed to be dynamic to allow for self describing registers and register sets, and much more.
>> One might also be able to make slight modifications to the existing
>> GDB gdbserver binary (from the current GDB sources) for linux, and use
>> it as the remote stub to connect to with LLDB!
>
> That is an interesting option. Will keep it in mind.
>
>
> Take care,
>
> --
> steve
From gclayton at apple.com Sun Jan 16 21:46:26 2011
From: gclayton at apple.com (Greg Clayton)
Date: Mon, 17 Jan 2011 03:46:26 -0000
Subject: [Lldb-commits] [lldb] r123613 - in /lldb/trunk: include/lldb/
include/lldb/API/ include/lldb/Core/ include/lldb/Expression/
include/lldb/Symbol/ lldb.xcodeproj/ source/API/ source/Commands/
source/Core/ source/Expression/ source/Interpreter/
source/Plugins/Disassembler/llvm/ source/Plugins/Process/gdb-remote/
source/Plugins/SymbolFile/DWARF/ source/Symbol/ source/Target/
test/class_types/
Message-ID: <20110117034627.26FD42A6C12C@llvm.org>
Author: gclayton
Date: Sun Jan 16 21:46:26 2011
New Revision: 123613
URL: http://llvm.org/viewvc/llvm-project?rev=123613&view=rev
Log:
A few of the issue I have been trying to track down and fix have been due to
the way LLDB lazily gets complete definitions for types within the debug info.
When we run across a class/struct/union definition in the DWARF, we will only
parse the full definition if we need to. This works fine for top level types
that are assigned directly to variables and arguments, but when we have a
variable with a class, lets say "A" for this example, that has a member:
"B *m_b". Initially we don't need to hunt down a definition for this class
unless we are ever asked to do something with it ("expr m_b->getDecl()" for
example). With my previous approach to lazy type completion, we would be able
to take a "A *a" and get a complete type for it, but we wouldn't be able to
then do an "a->m_b->getDecl()" unless we always expanded all types within a
class prior to handing out the type. Expanding everything is very costly and
it would be great if there were a better way.
A few months ago I worked with the llvm/clang folks to have the
ExternalASTSource class be able to complete classes if there weren't completed
yet:
class ExternalASTSource {
....
virtual void
CompleteType (clang::TagDecl *Tag);
virtual void
CompleteType (clang::ObjCInterfaceDecl *Class);
};
This was great, because we can now have the class that is producing the AST
(SymbolFileDWARF and SymbolFileDWARFDebugMap) sign up as external AST sources
and the object that creates the forward declaration types can now also
complete them anywhere within the clang type system.
This patch makes a few major changes:
- lldb_private::Module classes now own the AST context. Previously the TypeList
objects did.
- The DWARF parsers now sign up as an external AST sources so they can complete
types.
- All of the pure clang type system wrapper code we have in LLDB (ClangASTContext,
ClangASTType, and more) can now be iterating through children of any type,
and if a class/union/struct type (clang::RecordType or ObjC interface)
is found that is incomplete, we can ask the AST to get the definition.
- The SymbolFileDWARFDebugMap class now will create and use a single AST that
all child SymbolFileDWARF classes will share (much like what happens when
we have a complete linked DWARF for an executable).
We will need to modify some of the ClangUserExpression code to take more
advantage of this completion ability in the near future. Meanwhile we should
be better off now that we can be accessing any children of variables through
pointers and always be able to resolve the clang type if needed.
Modified:
lldb/trunk/include/lldb/API/SBValue.h
lldb/trunk/include/lldb/Core/Module.h
lldb/trunk/include/lldb/Core/ValueObject.h
lldb/trunk/include/lldb/Core/ValueObjectChild.h
lldb/trunk/include/lldb/Core/ValueObjectConstResult.h
lldb/trunk/include/lldb/Core/ValueObjectRegister.h
lldb/trunk/include/lldb/Core/ValueObjectVariable.h
lldb/trunk/include/lldb/Expression/ClangASTSource.h
lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h
lldb/trunk/include/lldb/Symbol/ClangASTContext.h
lldb/trunk/include/lldb/Symbol/SymbolFile.h
lldb/trunk/include/lldb/Symbol/TaggedASTType.h
lldb/trunk/include/lldb/Symbol/Type.h
lldb/trunk/include/lldb/Symbol/TypeList.h
lldb/trunk/include/lldb/lldb-forward.h
lldb/trunk/lldb.xcodeproj/project.pbxproj
lldb/trunk/source/API/SBType.cpp
lldb/trunk/source/API/SBValue.cpp
lldb/trunk/source/Commands/CommandObjectArgs.cpp
lldb/trunk/source/Core/Module.cpp
lldb/trunk/source/Core/ValueObject.cpp
lldb/trunk/source/Core/ValueObjectChild.cpp
lldb/trunk/source/Core/ValueObjectConstResult.cpp
lldb/trunk/source/Core/ValueObjectRegister.cpp
lldb/trunk/source/Core/ValueObjectVariable.cpp
lldb/trunk/source/Expression/ClangASTSource.cpp
lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
lldb/trunk/source/Interpreter/CommandInterpreter.cpp
lldb/trunk/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp
lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
lldb/trunk/source/Symbol/ClangASTContext.cpp
lldb/trunk/source/Symbol/ClangASTType.cpp
lldb/trunk/source/Symbol/SymbolFile.cpp
lldb/trunk/source/Symbol/SymbolVendor.cpp
lldb/trunk/source/Symbol/Type.cpp
lldb/trunk/source/Symbol/TypeList.cpp
lldb/trunk/source/Target/StackFrame.cpp
lldb/trunk/source/Target/ThreadPlanTracer.cpp
lldb/trunk/test/class_types/TestClassTypes.py
Modified: lldb/trunk/include/lldb/API/SBValue.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBValue.h?rev=123613&r1=123612&r2=123613&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBValue.h (original)
+++ lldb/trunk/include/lldb/API/SBValue.h Sun Jan 16 21:46:26 2011
@@ -106,6 +106,9 @@
bool
GetExpressionPath (lldb::SBStream &description);
+
+ bool
+ GetExpressionPath (lldb::SBStream &description, bool qualify_cxx_base_classes);
protected:
friend class SBValueList;
Modified: lldb/trunk/include/lldb/Core/Module.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Module.h?rev=123613&r1=123612&r2=123613&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Module.h (original)
+++ lldb/trunk/include/lldb/Core/Module.h Sun Jan 16 21:46:26 2011
@@ -16,6 +16,7 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Host/TimeValue.h"
+#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Symtab.h"
@@ -561,6 +562,9 @@
m_is_dynamic_loader_module = b;
}
+ ClangASTContext &
+ GetClangASTContext ();
+
protected:
//------------------------------------------------------------------
// Member Variables
@@ -573,9 +577,11 @@
ConstString m_object_name; ///< The name an object within this module that is selected, or empty of the module is represented by \a m_file.
std::auto_ptr m_objfile_ap; ///< A pointer to the object file parser for this module.
std::auto_ptr m_symfile_ap; ///< A pointer to the symbol vendor for this module.
+ ClangASTContext m_ast; ///< The AST context for this module.
bool m_did_load_objfile:1,
m_did_load_symbol_vendor:1,
m_did_parse_uuid:1,
+ m_did_init_ast:1,
m_is_dynamic_loader_module:1;
//------------------------------------------------------------------
Modified: lldb/trunk/include/lldb/Core/ValueObject.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=123613&r1=123612&r2=123613&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObject.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObject.h Sun Jan 16 21:46:26 2011
@@ -44,7 +44,7 @@
virtual clang::ASTContext *
GetClangAST () = 0;
- virtual void *
+ virtual lldb::clang_type_t
GetClangType () = 0;
virtual lldb::ValueType
@@ -88,7 +88,7 @@
}
virtual void
- GetExpressionPath (Stream &s);
+ GetExpressionPath (Stream &s, bool qualify_cxx_base_classes);
virtual bool
IsInScope (StackFrame *frame)
Modified: lldb/trunk/include/lldb/Core/ValueObjectChild.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObjectChild.h?rev=123613&r1=123612&r2=123613&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObjectChild.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObjectChild.h Sun Jan 16 21:46:26 2011
@@ -67,7 +67,7 @@
return m_clang_ast;
}
- virtual void *
+ virtual lldb::clang_type_t
GetClangType ()
{
return m_clang_type;
Modified: lldb/trunk/include/lldb/Core/ValueObjectConstResult.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObjectConstResult.h?rev=123613&r1=123612&r2=123613&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObjectConstResult.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObjectConstResult.h Sun Jan 16 21:46:26 2011
@@ -57,7 +57,7 @@
virtual clang::ASTContext *
GetClangAST ();
- virtual void *
+ virtual lldb::clang_type_t
GetClangType ();
virtual lldb::ValueType
Modified: lldb/trunk/include/lldb/Core/ValueObjectRegister.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObjectRegister.h?rev=123613&r1=123612&r2=123613&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObjectRegister.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObjectRegister.h Sun Jan 16 21:46:26 2011
@@ -37,7 +37,7 @@
virtual clang::ASTContext *
GetClangAST ();
- virtual void *
+ virtual lldb::clang_type_t
GetClangType ();
virtual lldb::ValueType
@@ -82,7 +82,7 @@
virtual clang::ASTContext *
GetClangAST ();
- virtual void *
+ virtual lldb::clang_type_t
GetClangType ();
virtual lldb::ValueType
@@ -130,7 +130,7 @@
virtual clang::ASTContext *
GetClangAST ();
- virtual void *
+ virtual lldb::clang_type_t
GetClangType ();
virtual lldb::ValueType
Modified: lldb/trunk/include/lldb/Core/ValueObjectVariable.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObjectVariable.h?rev=123613&r1=123612&r2=123613&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ValueObjectVariable.h (original)
+++ lldb/trunk/include/lldb/Core/ValueObjectVariable.h Sun Jan 16 21:46:26 2011
@@ -36,7 +36,7 @@
virtual clang::ASTContext *
GetClangAST ();
- virtual void *
+ virtual lldb::clang_type_t
GetClangType ();
virtual ConstString
Modified: lldb/trunk/include/lldb/Expression/ClangASTSource.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangASTSource.h?rev=123613&r1=123612&r2=123613&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangASTSource.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangASTSource.h Sun Jan 16 21:46:26 2011
@@ -13,7 +13,7 @@
#include
#include "clang/Basic/IdentifierTable.h"
-#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/AST/ExternalASTSource.h"
namespace lldb_private {
@@ -30,7 +30,7 @@
/// to Clang for these names, consulting the ClangExpressionDeclMap to do
/// the actual lookups.
//----------------------------------------------------------------------
-class ClangASTSource : public clang::ExternalSemaSource
+class ClangASTSource : public clang::ExternalASTSource
{
public:
//------------------------------------------------------------------
@@ -44,8 +44,8 @@
/// @param[in] declMap
/// A reference to the LLDB object that handles entity lookup.
//------------------------------------------------------------------
- ClangASTSource(clang::ASTContext &context,
- ClangExpressionDeclMap &decl_map) :
+ ClangASTSource (clang::ASTContext &context,
+ ClangExpressionDeclMap &decl_map) :
m_ast_context (context),
m_decl_map (decl_map),
m_active_lookups ()
@@ -60,27 +60,59 @@
//------------------------------------------------------------------
/// Interface stub that returns NULL.
//------------------------------------------------------------------
- clang::Decl *GetExternalDecl(uint32_t);
+ virtual clang::Decl *
+ GetExternalDecl(uint32_t)
+ {
+ // These are only required for AST source that want to lazily load
+ // the declarations (or parts thereof) that they return.
+ return NULL;
+ }
//------------------------------------------------------------------
/// Interface stub that returns NULL.
//------------------------------------------------------------------
- clang::Stmt *GetExternalDeclStmt(uint64_t);
+ virtual clang::Stmt *
+ GetExternalDeclStmt(uint64_t)
+ {
+ // These are only required for AST source that want to lazily load
+ // the declarations (or parts thereof) that they return.
+ return NULL;
+ }
//------------------------------------------------------------------
/// Interface stub that returns an undifferentiated Selector.
//------------------------------------------------------------------
- clang::Selector GetExternalSelector(uint32_t);
+ virtual clang::Selector
+ GetExternalSelector(uint32_t)
+ {
+ // These are also optional, although it might help with ObjC
+ // debugging if we have respectable signatures. But a more
+ // efficient interface (that didn't require scanning all files
+ // for method signatures!) might help.
+ return clang::Selector();
+ }
//------------------------------------------------------------------
/// Interface stub that returns 0.
//------------------------------------------------------------------
- uint32_t GetNumExternalSelectors();
+ virtual uint32_t
+ GetNumExternalSelectors()
+ {
+ // These are also optional, although it might help with ObjC
+ // debugging if we have respectable signatures. But a more
+ // efficient interface (that didn't require scanning all files
+ // for method signatures!) might help.
+ return 0;
+ }
//------------------------------------------------------------------
/// Interface stub that returns NULL.
//------------------------------------------------------------------
- clang::CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset);
+ virtual clang::CXXBaseSpecifier *
+ GetExternalCXXBaseSpecifiers(uint64_t Offset)
+ {
+ return NULL;
+ }
//------------------------------------------------------------------
/// Look up all Decls that match a particular name. Only handles
@@ -96,22 +128,31 @@
/// @return
/// Whatever SetExternalVisibleDeclsForName returns.
//------------------------------------------------------------------
- clang::DeclContextLookupResult
+ virtual clang::DeclContextLookupResult
FindExternalVisibleDeclsByName (const clang::DeclContext *DC,
clang::DeclarationName Name);
//------------------------------------------------------------------
/// Interface stub.
//------------------------------------------------------------------
- void MaterializeVisibleDecls (const clang::DeclContext *DC);
+ virtual void
+ MaterializeVisibleDecls (const clang::DeclContext *DC);
//------------------------------------------------------------------
/// Interface stub that returns true.
//------------------------------------------------------------------
- bool FindExternalLexicalDecls (const clang::DeclContext *DC,
- bool (*isKindWeWant)(clang::Decl::Kind),
- llvm::SmallVectorImpl &Decls);
+ virtual bool
+ FindExternalLexicalDecls (const clang::DeclContext *DC,
+ bool (*isKindWeWant)(clang::Decl::Kind),
+ llvm::SmallVectorImpl &Decls);
+
+ virtual void
+ CompleteType (clang::TagDecl *Tag);
+
+ virtual void
+ CompleteType (clang::ObjCInterfaceDecl *Class);
+
//------------------------------------------------------------------
/// Called on entering a translation unit. Tells Clang by calling
/// setHasExternalVisibleStorage() and setHasExternalLexicalStorage()
Modified: lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h?rev=123613&r1=123612&r2=123613&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h Sun Jan 16 21:46:26 2011
@@ -20,6 +20,7 @@
// Other libraries and framework includes
// Project includes
#include "llvm/ADT/DenseMap.h"
+#include "lldb/lldb-include.h"
#include "lldb/Core/ClangForward.h"
#include "lldb/Core/Value.h"
#include "lldb/Expression/ClangExpressionVariable.h"
@@ -27,20 +28,8 @@
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/ExecutionContext.h"
-namespace llvm {
- class Type;
- class Value;
-}
-
namespace lldb_private {
-class ClangExpressionVariables;
-class ClangPersistentVariables;
-class Error;
-class Function;
-class NameSearchContext;
-class Variable;
-
//----------------------------------------------------------------------
/// @class ClangExpressionDeclMap ClangExpressionDeclMap.h "lldb/Expression/ClangExpressionDeclMap.h"
/// @brief Manages named entities that are defined in LLDB's debug information.
@@ -430,11 +419,19 @@
/// True if a $__lldb variable has been found.
//------------------------------------------------------------------
bool
- GetLookupsEnabled ()
+ GetLookupsEnabled () const
{
assert(m_parser_vars.get());
return m_parser_vars->m_enable_lookups;
}
+
+ bool
+ GetImportInProgress () const
+ {
+ if (m_parser_vars.get())
+ return m_parser_vars->m_ignore_lookups;
+ return false;
+ }
//------------------------------------------------------------------
/// [Used by ClangASTSource] Indicate that a $__lldb variable has
Modified: lldb/trunk/include/lldb/Symbol/ClangASTContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTContext.h?rev=123613&r1=123612&r2=123613&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ClangASTContext.h (original)
+++ lldb/trunk/include/lldb/Symbol/ClangASTContext.h Sun Jan 16 21:46:26 2011
@@ -18,6 +18,8 @@
#include
// Other libraries and framework includes
+#include "llvm/ADT/OwningPtr.h"
+
// Project includes
#include "lldb/lldb-enumerations.h"
#include "lldb/Core/ClangForward.h"
@@ -50,10 +52,13 @@
eTypeIsVector = (1u << 16)
};
+ typedef void (*CompleteTagDeclCallback)(void *baton, clang::TagDecl *);
+ typedef void (*CompleteObjCInterfaceDeclCallback)(void *baton, clang::ObjCInterfaceDecl *);
+
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
- ClangASTContext(const char *target_triple);
+ ClangASTContext (const char *triple = NULL);
~ClangASTContext();
@@ -99,6 +104,22 @@
void
SetTargetTriple (const char *target_triple);
+ bool
+ HasExternalSource ();
+
+ void
+ SetExternalSource (llvm::OwningPtr &ast_source_ap);
+
+ void
+ RemoveExternalSource ();
+
+ bool
+ GetCompleteType (lldb::clang_type_t clang_type);
+
+ static bool
+ GetCompleteType (clang::ASTContext *ast,
+ lldb::clang_type_t clang_type);
+
//------------------------------------------------------------------
// Basic Types
//------------------------------------------------------------------
@@ -108,7 +129,7 @@
uint32_t bit_size);
static lldb::clang_type_t
- GetBuiltinTypeForEncodingAndBitSize (clang::ASTContext *ast_context,
+ GetBuiltinTypeForEncodingAndBitSize (clang::ASTContext *ast,
lldb::Encoding encoding,
uint32_t bit_size);
@@ -119,7 +140,7 @@
uint32_t bit_size);
static lldb::clang_type_t
- GetBuiltInType_void(clang::ASTContext *ast_context);
+ GetBuiltInType_void(clang::ASTContext *ast);
lldb::clang_type_t
GetBuiltInType_void()
@@ -146,7 +167,7 @@
GetVoidPtrType(bool is_const);
static lldb::clang_type_t
- GetVoidPtrType(clang::ASTContext *ast_context, bool is_const);
+ GetVoidPtrType(clang::ASTContext *ast, bool is_const);
static lldb::clang_type_t
CopyType(clang::ASTContext *dest_context,
@@ -159,7 +180,7 @@
clang::Decl *source_decl);
static bool
- AreTypesSame(clang::ASTContext *ast_context,
+ AreTypesSame(clang::ASTContext *ast,
lldb::clang_type_t type1,
lldb::clang_type_t type2);
@@ -170,6 +191,13 @@
return ClangASTContext::AreTypesSame(getASTContext(), type1, type2);
}
+
+ lldb::clang_type_t
+ GetTypeForDecl (clang::TagDecl *decl);
+
+ lldb::clang_type_t
+ GetTypeForDecl (clang::ObjCInterfaceDecl *objc_decl);
+
//------------------------------------------------------------------
// CVR modifiers
//------------------------------------------------------------------
@@ -194,7 +222,7 @@
lldb::LanguageType language);
static bool
- AddFieldToRecordType (clang::ASTContext *ast_context,
+ AddFieldToRecordType (clang::ASTContext *ast,
lldb::clang_type_t record_qual_type,
const char *name,
lldb::clang_type_t field_type,
@@ -217,7 +245,7 @@
}
static clang::CXXMethodDecl *
- AddMethodToCXXRecordType (clang::ASTContext *ast_context,
+ AddMethodToCXXRecordType (clang::ASTContext *ast,
lldb::clang_type_t record_opaque_type,
const char *name,
lldb::clang_type_t method_type,
@@ -254,7 +282,7 @@
uint32_t& bitfield_bit_size);
static bool
- FieldIsBitfield (clang::ASTContext *ast_context,
+ FieldIsBitfield (clang::ASTContext *ast,
clang::FieldDecl* field,
uint32_t& bitfield_bit_size);
@@ -274,7 +302,7 @@
bool isInternal);
static bool
- AddObjCClassIVar (clang::ASTContext *ast_context,
+ AddObjCClassIVar (clang::ASTContext *ast,
lldb::clang_type_t class_opaque_type,
const char *name,
lldb::clang_type_t ivar_opaque_type,
@@ -312,7 +340,7 @@
static clang::ObjCMethodDecl *
- AddMethodToObjCObjectType (clang::ASTContext *ast_context,
+ AddMethodToObjCObjectType (clang::ASTContext *ast,
lldb::clang_type_t class_opaque_type,
const char *name, // the full symbol name as seen in the symbol table ("-[NString stringWithCString:]")
lldb::clang_type_t method_opaque_type,
@@ -331,6 +359,8 @@
access);
}
+ static bool
+ SetHasExternalStorage (lldb::clang_type_t clang_type, bool has_extern);
//------------------------------------------------------------------
// Aggregate Types
@@ -341,11 +371,12 @@
// Returns a mask containing bits from the ClangASTContext::eTypeXXX enumerations
static uint32_t
GetTypeInfo (lldb::clang_type_t clang_type,
- clang::ASTContext *ast_context, // The AST for clang_type (can be NULL)
+ clang::ASTContext *ast, // The AST for clang_type (can be NULL)
lldb::clang_type_t *pointee_or_element_type); // (can be NULL)
static uint32_t
- GetNumChildren (lldb::clang_type_t clang_type,
+ GetNumChildren (clang::ASTContext *ast,
+ lldb::clang_type_t clang_type,
bool omit_empty_base_classes);
static uint32_t
@@ -365,7 +396,7 @@
bool &child_is_base_class);
static lldb::clang_type_t
- GetChildClangTypeAtIndex (clang::ASTContext *ast_context,
+ GetChildClangTypeAtIndex (clang::ASTContext *ast,
const char *parent_name,
lldb::clang_type_t parent_clang_type,
uint32_t idx,
@@ -381,7 +412,7 @@
// Lookup a child given a name. This function will match base class names
// and member member names in "clang_type" only, not descendants.
static uint32_t
- GetIndexOfChildWithName (clang::ASTContext *ast_context,
+ GetIndexOfChildWithName (clang::ASTContext *ast,
lldb::clang_type_t clang_type,
const char *name,
bool omit_empty_base_classes);
@@ -392,7 +423,7 @@
// TODO: Return all matches for a given name by returning a vector>
// so we catch all names that match a given child name, not just the first.
static size_t
- GetIndexOfChildMemberWithName (clang::ASTContext *ast_context,
+ GetIndexOfChildMemberWithName (clang::ASTContext *ast,
lldb::clang_type_t clang_type,
const char *name,
bool omit_empty_base_classes,
@@ -452,7 +483,7 @@
bool is_inline);
static lldb::clang_type_t
- CreateFunctionType (clang::ASTContext *ast_context,
+ CreateFunctionType (clang::ASTContext *ast,
lldb::clang_type_t result_type,
lldb::clang_type_t *args,
unsigned num_args,
@@ -611,7 +642,7 @@
GetArraySize (lldb::clang_type_t clang_type);
//static bool
- //ConvertFloatValueToString (clang::ASTContext *ast_context,
+ //ConvertFloatValueToString (clang::ASTContext *ast,
// lldb::clang_type_t clang_type,
// const uint8_t* bytes,
// size_t byte_size,
@@ -619,7 +650,7 @@
// std::string &float_str);
static size_t
- ConvertStringToFloatValue (clang::ASTContext *ast_context,
+ ConvertStringToFloatValue (clang::ASTContext *ast,
lldb::clang_type_t clang_type,
const char *s,
uint8_t *dst,
@@ -635,7 +666,7 @@
// Classes that inherit from ClangASTContext can see and modify these
//------------------------------------------------------------------
std::string m_target_triple;
- std::auto_ptr m_ast_context_ap;
+ std::auto_ptr m_ast_ap;
std::auto_ptr m_language_options_ap;
std::auto_ptr m_file_manager_ap;
std::auto_ptr m_file_system_options_ap;
@@ -647,7 +678,9 @@
std::auto_ptr m_identifier_table_ap;
std::auto_ptr m_selector_table_ap;
std::auto_ptr m_builtins_ap;
-
+ CompleteTagDeclCallback m_callback_tag_decl;
+ CompleteObjCInterfaceDeclCallback m_callback_objc_decl;
+ void * m_callback_baton;
private:
//------------------------------------------------------------------
// For ClangASTContext only
Modified: lldb/trunk/include/lldb/Symbol/SymbolFile.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/SymbolFile.h?rev=123613&r1=123612&r2=123613&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/SymbolFile.h (original)
+++ lldb/trunk/include/lldb/Symbol/SymbolFile.h Sun Jan 16 21:46:26 2011
@@ -56,7 +56,47 @@
{
}
+ //------------------------------------------------------------------
+ /// Get a mask of what this symbol file supports for the object file
+ /// that it was constructed with.
+ ///
+ /// Each symbol file gets to respond with a mask of abilities that
+ /// it supports for each object file. This happens when we are
+ /// trying to figure out which symbol file plug-in will get used
+ /// for a given object file. The plug-in that resoonds with the
+ /// best mix of "SymbolFile::Abilities" bits set, will get chosen to
+ /// be the symbol file parser. This allows each plug-in to check for
+ /// sections that contain data a symbol file plug-in would need. For
+ /// example the DWARF plug-in requires DWARF sections in a file that
+ /// contain debug information. If the DWARF plug-in doesn't find
+ /// these sections, it won't respond with many ability bits set, and
+ /// we will probably fall back to the symbol table SymbolFile plug-in
+ /// which uses any information in the symbol table. Also, plug-ins
+ /// might check for some specific symbols in a symbol table in the
+ /// case where the symbol table contains debug information (STABS
+ /// and COFF). Not a lot of work should happen in these functions
+ /// as the plug-in might not get selected due to another plug-in
+ /// having more abilities. Any initialization work should be saved
+ /// for "void SymbolFile::InitializeObject()" which will get called
+ /// on the SymbolFile object with the best set of abilities.
+ ///
+ /// @return
+ /// A uint32_t mask containing bits from the SymbolFile::Abilities
+ /// enumeration. Any bits that are set represent an ability that
+ /// this symbol plug-in can parse from the object file.
+ ///------------------------------------------------------------------
virtual uint32_t GetAbilities () = 0;
+
+ //------------------------------------------------------------------
+ /// Initialize the SymbolFile object.
+ ///
+ /// The SymbolFile object with the best set of abilities (detected
+ /// in "uint32_t SymbolFile::GetAbilities()) will have this function
+ /// called if it is chosen to parse an object file. More complete
+ /// initialization can happen in this function which will get called
+ /// prior to any other functions in the SymbolFile protocol.
+ //------------------------------------------------------------------
+ virtual void InitializeObject() {}
//------------------------------------------------------------------
// Compile Unit function calls
@@ -83,6 +123,8 @@
virtual uint32_t FindTypes (const SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, TypeList& types) = 0;
// virtual uint32_t FindTypes (const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, TypeList& types) = 0;
virtual TypeList * GetTypeList ();
+ virtual ClangASTContext &
+ GetClangASTContext ();
virtual ClangNamespaceDecl
FindNamespace (const SymbolContext& sc,
const ConstString &name) = 0;
@@ -90,7 +132,7 @@
ObjectFile* GetObjectFile() { return m_obj_file; }
const ObjectFile* GetObjectFile() const { return m_obj_file; }
protected:
- ObjectFile* m_obj_file; // The object file that symbols can be extracted from.
+ ObjectFile* m_obj_file; // The object file that symbols can be extracted from.
private:
DISALLOW_COPY_AND_ASSIGN (SymbolFile);
Modified: lldb/trunk/include/lldb/Symbol/TaggedASTType.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/TaggedASTType.h?rev=123613&r1=123612&r2=123613&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/TaggedASTType.h (original)
+++ lldb/trunk/include/lldb/Symbol/TaggedASTType.h Sun Jan 16 21:46:26 2011
@@ -20,7 +20,7 @@
template class TaggedASTType : public ClangASTType
{
public:
- TaggedASTType (void *type, clang::ASTContext *ast_context) :
+ TaggedASTType (lldb::clang_type_t type, clang::ASTContext *ast_context) :
ClangASTType(type, ast_context) { }
TaggedASTType (const TaggedASTType &tw) :
Modified: lldb/trunk/include/lldb/Symbol/Type.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/Type.h?rev=123613&r1=123612&r2=123613&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/Type.h (original)
+++ lldb/trunk/include/lldb/Symbol/Type.h Sun Jan 16 21:46:26 2011
@@ -226,6 +226,21 @@
uint32_t
GetEncodingMask ();
+ void *
+ CreateClangPointerType (Type *type);
+
+ void *
+ CreateClangTypedefType (Type *typedef_type, Type *base_type);
+
+ // For C++98 references (&)
+ void *
+ CreateClangLValueReferenceType (Type *type);
+
+ // For C++0x references (&&)
+ void *
+ CreateClangRValueReferenceType (Type *type);
+
+
protected:
ConstString m_name;
SymbolFile *m_symbol_file;
Modified: lldb/trunk/include/lldb/Symbol/TypeList.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/TypeList.h?rev=123613&r1=123612&r2=123613&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/TypeList.h (original)
+++ lldb/trunk/include/lldb/Symbol/TypeList.h Sun Jan 16 21:46:26 2011
@@ -11,7 +11,6 @@
#define liblldb_TypeList_h_
#include "lldb/lldb-private.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/Type.h"
#include