[Lldb-commits] LLDB Windows Driver Patch
Aidan Dodds
aidan at codeplay.com
Fri Sep 27 09:56:19 PDT 2013
Hello,
As an extension of our PlatformWindows patch, we would like to submit
some changes to the LLDB Command Line Driver allowing it to cleanly
build and run on Windows.
This patch will not show any change in functionality for non windows
hosts. Without any Windows specific testing in place we have simply
loaded an elf file and viewed its sections, etc to confirm that it
functions properly.
An work-in-progress wrapper for EditLine functionality has been created,
leaving the main driver code minimally modified. Also a minimal
abstraction of the pthread code has been made. Our intention is to later
revise the threading code and instead use the existing threading classes
of LLDB.
The Linux test suite passes successfully after application of this patch.
This patch is based on trunk revision,
https://llvm.org/svn/llvm-project/lldb/trunk@191399
Thanks,
Aidan Dodds
-------------- next part --------------
diff --git tools/CMakeLists.txt tools/CMakeLists.txt
index b1989f8..43163f6 100644
--- tools/CMakeLists.txt
+++ tools/CMakeLists.txt
@@ -1,7 +1,7 @@
-if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
- add_subdirectory(debugserver)
-endif()
-if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
- add_subdirectory(driver)
- add_subdirectory(lldb-platform)
-endif()
+if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
+ add_subdirectory(debugserver)
+endif()
+add_subdirectory(driver)
+if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
+ add_subdirectory(lldb-platform)
+endif()
diff --git tools/driver/CMakeLists.txt tools/driver/CMakeLists.txt
index c70a2db..aa4c798 100644
--- tools/driver/CMakeLists.txt
+++ tools/driver/CMakeLists.txt
@@ -1,18 +1,22 @@
-set(LLVM_NO_RTTI 1)
-add_lldb_executable(lldb
- Driver.cpp
- #DriverEvents.cpp
- #DriverOptions.cpp
- #DriverPosix.cpp
- IOChannel.cpp
- )
-
-target_link_libraries(lldb liblldb)
-# TODO: why isn't this done by add_lldb_executable?
-#target_link_libraries(lldb ${LLDB_USED_LIBS})
-#llvm_config(lldb ${LLVM_LINK_COMPONENTS})
-
-set_target_properties(lldb PROPERTIES VERSION ${LLDB_VERSION})
-
-install(TARGETS lldb
- RUNTIME DESTINATION bin)
+set(LLVM_NO_RTTI 1)
+add_lldb_executable(lldb
+ Driver.cpp
+ #DriverEvents.cpp
+ #DriverOptions.cpp
+ #DriverPosix.cpp
+ IOChannel.cpp
+ ELWrapper.cpp
+ Mutex.cpp
+ Platform.cpp
+ GetOptWrapper.cpp
+ )
+
+target_link_libraries(lldb liblldb)
+# TODO: why isn't this done by add_lldb_executable?
+#target_link_libraries(lldb ${LLDB_USED_LIBS})
+#llvm_config(lldb ${LLVM_LINK_COMPONENTS})
+
+set_target_properties(lldb PROPERTIES VERSION ${LLDB_VERSION})
+
+install(TARGETS lldb
+ RUNTIME DESTINATION bin)
diff --git tools/driver/Driver.cpp tools/driver/Driver.cpp
index a4fc67f..98977ba 100644
--- tools/driver/Driver.cpp
+++ tools/driver/Driver.cpp
@@ -9,16 +9,11 @@
#include "Driver.h"
-#include <getopt.h>
-#include <libgen.h>
-#include <sys/ioctl.h>
-#include <termios.h>
-#include <unistd.h>
+#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <fcntl.h>
-#include <inttypes.h>
#include <string>
@@ -155,7 +150,9 @@ Driver::CloseIOChannelFile ()
// Write an End of File sequence to the file descriptor to ensure any
// read functions can exit.
char eof_str[] = "\x04";
- ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
+ int mfd = m_editline_pty.GetMasterFileDescriptor();
+ if ( mfd != -1 )
+ ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
m_editline_pty.CloseMasterFileDescriptor();
@@ -569,7 +566,7 @@ Driver::GetDebugMode() const
// if the user only wanted help or version information.
SBError
-Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
+Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting)
{
ResetOptionValues ();
@@ -802,12 +799,12 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
if (error.Fail() || m_option_data.m_print_help)
{
ShowUsage (out_fh, g_options, m_option_data);
- exit = true;
+ exiting = true;
}
else if (m_option_data.m_print_version)
{
::fprintf (out_fh, "%s\n", m_debugger.GetVersionString());
- exit = true;
+ exiting = true;
}
else if (m_option_data.m_print_python_path)
{
@@ -825,7 +822,7 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exit)
}
else
::fprintf (out_fh, "<COULD NOT FIND PATH>\n");
- exit = true;
+ exiting = true;
}
else if (m_option_data.m_process_name.empty() && m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID)
{
@@ -1311,6 +1308,12 @@ Driver::EditLineInputReaderCallback
void
Driver::MainLoop ()
{
+#if defined( _MSC_VER )
+ m_editline_slave_fh = stdin;
+ FILE *editline_output_slave_fh = stdout;
+ lldb_utility::PseudoTerminal editline_output_pty;
+#else
+
char error_str[1024];
if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
{
@@ -1371,6 +1374,7 @@ Driver::MainLoop ()
::setbuf (editline_output_slave_fh, NULL);
}
}
+#endif
// struct termios stdin_termios;
@@ -1780,15 +1784,15 @@ main (int argc, char const *argv[], const char *envp[])
{
Driver driver;
- bool exit = false;
- SBError error (driver.ParseArgs (argc, argv, stdout, exit));
+ bool exiting = false;
+ SBError error (driver.ParseArgs (argc, argv, stdout, exiting));
if (error.Fail())
{
const char *error_cstr = error.GetCString ();
if (error_cstr)
::fprintf (stderr, "error: %s\n", error_cstr);
}
- else if (!exit)
+ else if (!exiting)
{
driver.MainLoop ();
}
diff --git tools/driver/Driver.h tools/driver/Driver.h
index 6681611..dcfd5ed 100644
--- tools/driver/Driver.h
+++ tools/driver/Driver.h
@@ -10,6 +10,7 @@
#ifndef lldb_Driver_h_
#define lldb_Driver_h_
+#include "Platform.h"
#include "lldb/Utility/PseudoTerminal.h"
#include <set>
diff --git tools/driver/ELWrapper.cpp tools/driver/ELWrapper.cpp
new file mode 100644
index 0000000..dc71b7f
--- /dev/null
+++ tools/driver/ELWrapper.cpp
@@ -0,0 +1,398 @@
+//===-- ELWrapper.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// this file is only relevant for Visual C++
+#if defined( _MSC_VER )
+
+#include "lldb/Host/windows/windows.h"
+
+#include "ELWrapper.h"
+#include <vector>
+#include <assert.h>
+
+// index one of the variable arguments
+// presuming "(EditLine *el, ..." is first in the argument list
+#define GETARG( X ) ( (void* ) *( ( (int**) &el ) + ((X) + 2) ) )
+
+// edit line EL_ADDFN function pointer type
+typedef unsigned char (*el_addfn_func)(EditLine *e, int ch);
+
+// edit line wrapper binding container
+struct el_binding
+{
+ //
+ const char *name;
+ const char *help;
+ // function pointer to callback routine
+ el_addfn_func func;
+ // ascii key this function is bound to
+ const char *key;
+};
+
+// stored key bindings
+static std::vector<el_binding*> _bindings;
+
+//TODO: this should infact be related to the exact edit line context we create
+static void *clientData = NULL;
+
+// store the current prompt string
+// default to what we expect to receive anyway
+static const char *_prompt = "(lldb) ";
+
+#if !defined( _WIP_INPUT_METHOD )
+
+static char *el_get_s( char *buffer, int chars )
+{
+ return gets_s( buffer, chars );
+}
+#else
+
+static void con_output( char _in )
+{
+ HANDLE hout = GetStdHandle( STD_OUTPUT_HANDLE );
+ DWORD written = 0;
+ // get the cursor position
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ GetConsoleScreenBufferInfo( hout, &info );
+ // output this char
+ WriteConsoleOutputCharacterA( hout, &_in, 1, info.dwCursorPosition, &written );
+ // advance cursor position
+ info.dwCursorPosition.X++;
+ SetConsoleCursorPosition( hout, info.dwCursorPosition );
+}
+
+static void con_backspace( void )
+{
+ HANDLE hout = GetStdHandle( STD_OUTPUT_HANDLE );
+ DWORD written = 0;
+ // get cursor position
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ GetConsoleScreenBufferInfo( hout, &info );
+ // nudge cursor backwards
+ info.dwCursorPosition.X--;
+ SetConsoleCursorPosition( hout, info.dwCursorPosition );
+ // blank out the last character
+ WriteConsoleOutputCharacterA( hout, " ", 1, info.dwCursorPosition, &written );
+}
+
+static void con_return( void )
+{
+ HANDLE hout = GetStdHandle( STD_OUTPUT_HANDLE );
+ DWORD written = 0;
+ // get cursor position
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ GetConsoleScreenBufferInfo( hout, &info );
+ // move onto the new line
+ info.dwCursorPosition.X = 0;
+ info.dwCursorPosition.Y++;
+ SetConsoleCursorPosition( hout, info.dwCursorPosition );
+}
+
+static bool runBind( char _key )
+{
+ for ( int i=0; i<_bindings.size(); i++ )
+ {
+ el_binding *bind = _bindings[i];
+ if ( bind->key[0] == _key )
+ {
+ bind->func( (EditLine*) -1, _key );
+ return true;
+ }
+ }
+ return false;
+}
+
+// replacement get_s which is EL_BIND aware
+static char *el_get_s( char *buffer, int chars )
+{
+ //
+ char *head = buffer;
+ //
+ for ( ;; Sleep( 10 ) )
+ {
+ //
+ INPUT_RECORD _record;
+ //
+ DWORD _read = 0;
+ if ( ReadConsoleInputA( GetStdHandle( STD_INPUT_HANDLE ), &_record, 1, &_read ) == FALSE )
+ break;
+ // if we didnt read a key
+ if ( _read == 0 )
+ continue;
+ // only interested in key events
+ if ( _record.EventType != KEY_EVENT )
+ continue;
+ // is the key down
+ if (! _record.Event.KeyEvent.bKeyDown )
+ continue;
+ // read the ascii key character
+ char _key = _record.Event.KeyEvent.uChar.AsciiChar;
+ // non ascii conformant key press
+ if ( _key == 0 )
+ {
+ // check the scan code
+ // if VK_UP scroll back through history
+ // if VK_DOWN scroll forward through history
+ continue;
+ }
+ // try to execute any bind this key may have
+ if ( runBind( _key ) )
+ continue;
+ // if we read a return key
+ if ( _key == '\n' || _key == '\r' )
+ {
+ con_return( );
+ break;
+ }
+ // key is backspace
+ if ( _key == 0x8 )
+ {
+ // avoid deleting past beginning
+ if ( head > buffer )
+ {
+ con_backspace( );
+ head--;
+ }
+ continue;
+ }
+
+ // add this key to the input buffer
+ if ( (head-buffer) < (chars-1) )
+ {
+ con_output( _key );
+ *(head++) = _key;
+ }
+ }
+ // insert end of line character
+ *head = '\0';
+
+ return buffer;
+}
+#endif
+
+// edit line initalise
+EditLine *el_init( const char *, FILE *, FILE *, FILE * )
+{
+ //
+ SetConsoleTitleA( "lldb" );
+ // return dummy handle
+ return (EditLine*) -1;
+}
+
+const char *el_gets( EditLine *el, int *length )
+{
+ // print the prompt if we have one
+ if ( _prompt != NULL )
+ printf( _prompt );
+ // create a buffer for the user input
+ char *buffer = new char[ 64 ];
+ // try to get user input string
+ if ( el_get_s( buffer, 64 ) )
+ {
+ // get the string length in 'length'
+ while ( buffer[ *length ] != '\0' )
+ (*length)++;
+ // return the input buffer
+ // remember that this memory has the be free'd somewhere
+ return buffer;
+ }
+ else
+ {
+ // on error
+ delete [] buffer;
+ return NULL;
+ }
+}
+
+int el_set( EditLine *el, int code, ... )
+{
+ int **arg = (int**) ⪙
+ //
+ switch ( code )
+ {
+ // edit line set prompt message
+ case ( EL_PROMPT ):
+ {
+ // EL_PROMPT, char *(*f)( EditLine *)
+ // define a prompt printing function as 'f', which is to return a string that
+ // contains the prompt.
+
+ // get the function pointer from the arg list
+ void *func_vp = (void*) *(arg+2);
+ // cast to suitable prototype
+ const char* (*func_fp)(EditLine*) = (const char*(*)(EditLine *)) func_vp;
+ // call to get the prompt as a string
+ _prompt = func_fp( el );
+ }
+ break;
+ case ( EL_EDITOR ):
+ {
+ // EL_EDITOR, const char *mode
+ // set editing mode to "emacs" or "vi"
+ }
+ break;
+ case ( EL_HIST ):
+ {
+ // EL_HIST, History *(*fun)(History *, int op, ... ), const char *ptr
+ // defines which histroy function to use, which is usualy history(). Ptr should be the
+ // value returned by history_init().
+ }
+ break;
+ case ( EL_ADDFN ):
+ {
+ // EL_ADDFN, const char *name, const char *help, unsigned char (*func)(EditLine *e, int ch)
+ // add a user defined function, func), referred to as 'name' which is invoked when a key which is bound to 'name' is
+ // entered. 'help' is a description of 'name'. at involcation time, 'ch' is the key which caused the invocation. the
+ // return value of 'func()' should be one of:
+ // CC_NORM add a normal character
+ // CC_NEWLINE end of line was entered
+ // CC_EOF EOF was entered
+ // CC_ARGHACK expecting further command input as arguments, do nothing visually.
+ // CC_REFRESH refresh display.
+ // CC_REFRESH_BEEP refresh display and beep.
+ // CC_CURSOR cursor moved so update and perform CC_REFRESH
+ // CC_REDISPLAY redisplay entire input line. this is usefull if a key binding outputs extra information.
+ // CC_ERROR an error occured. beep and flush tty.
+ // CC_FATAL fatal error, reset tty to known state.
+
+ el_binding *binding = new el_binding;
+ binding->name = (const char *) GETARG( 0 );
+ binding->help = (const char *) GETARG( 1 );
+ binding->func = (el_addfn_func) GETARG( 2 );
+ binding->key = 0;
+ // add this to the bindings list
+ _bindings.push_back( binding );
+ }
+ break;
+ case ( EL_BIND ):
+ {
+ // EL_BIND, const char *, ..., NULL
+ // perform the BIND buildin command. Refer to editrc(5) for more information.
+
+ const char *name = (const char*) GETARG( 1 );
+
+ for ( int i=0; i<_bindings.size(); i++ )
+ {
+ el_binding *bind = _bindings[i];
+ if ( strcmp( bind->name, name ) == 0 )
+ {
+ bind->key = (const char *) GETARG( 0 );
+ break;
+ }
+ }
+
+ }
+ break;
+ case ( EL_CLIENTDATA ):
+ {
+ clientData = GETARG( 0 );
+ }
+ break;
+ default:
+ assert( !"Not Implemented!" );
+ }
+ return 0;
+}
+
+void el_end( EditLine *el )
+{
+ assert( !"Not implemented!" );
+}
+
+void el_reset( EditLine * )
+{
+ assert( !"Not implemented!" );
+}
+
+int el_getc( EditLine *, char * )
+{
+ assert( !"Not implemented!" );
+ return 0;
+}
+
+void el_push( EditLine *, char * )
+{
+ assert( !"Not implemented!" );
+}
+
+void el_beep( EditLine * )
+{
+ Beep( 1000, 500 );
+}
+
+int el_parse( EditLine *, int, const char ** )
+{
+ assert( !"Not implemented!" );
+ return 0;
+}
+
+int el_get( EditLine *el, int code, ... )
+{
+ switch ( code )
+ {
+ case ( EL_CLIENTDATA ):
+ {
+ void **dout = (void**) GETARG( 0 );
+ *dout = clientData;
+ }
+ break;
+ default:
+ assert( !"Not implemented!" );
+ }
+ return 0;
+}
+
+int el_source( EditLine *el, const char *file )
+{
+ // init edit line by reading the contents of 'file'
+ // nothing to do here on windows...
+ return 0;
+}
+
+void el_resize( EditLine * )
+{
+ assert( !"Not implemented!" );
+}
+
+const LineInfo *el_line( EditLine *el )
+{
+ assert( !"Not implemented!" );
+ return 0;
+}
+
+int el_insertstr( EditLine *, const char * )
+{
+ assert( !"Not implemented!" );
+ return 0;
+}
+
+void el_deletestr( EditLine *, int )
+{
+ assert( !"Not implemented!" );
+}
+
+History *history_init( void )
+{
+ // return dummy handle
+ return (History*) -1;
+}
+
+void history_end( History * )
+{
+ assert( !"Not implemented!" );
+}
+
+int history( History *, HistEvent *, int op, ... )
+{
+ // perform operation 'op' on the history list with optional argumetns as needed by
+ // the operation.
+ return 0;
+}
+
+#endif
diff --git tools/driver/ELWrapper.h tools/driver/ELWrapper.h
new file mode 100644
index 0000000..a30182d
--- /dev/null
+++ tools/driver/ELWrapper.h
@@ -0,0 +1,122 @@
+//===-- ELWrapper.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+#include <stdio.h>
+
+// EditLine editor function return codes.
+// For user-defined function interface
+#define CC_NORM 0
+#define CC_NEWLINE 1
+#define CC_EOF 2
+#define CC_ARGHACK 3
+#define CC_REFRESH 4
+#define CC_CURSOR 5
+#define CC_ERROR 6
+#define CC_FATAL 7
+#define CC_REDISPLAY 8
+#define CC_REFRESH_BEEP 9
+
+// el_set/el_get parameters
+#define EL_PROMPT 0 // , el_pfunc_t
+#define EL_TERMINAL 1 // , const char *
+#define EL_EDITOR 2 // , const char *
+#define EL_SIGNAL 3 // , int);
+#define EL_BIND 4 // , const char *, ..., NULL
+#define EL_TELLTC 5 // , const char *, ..., NULL
+#define EL_SETTC 6 // , const char *, ..., NULL
+#define EL_ECHOTC 7 // , const char *, ..., NULL
+#define EL_SETTY 8 // , const char *, ..., NULL
+#define EL_ADDFN 9 // , const char *, const char *, el_func_t
+#define EL_HIST 10 // , hist_fun_t, const char *
+#define EL_EDITMODE 11 // , int
+#define EL_RPROMPT 12 // , el_pfunc_t
+#define EL_GETCFN 13 // , el_rfunc_t
+#define EL_CLIENTDATA 14 // , void *
+#define EL_UNBUFFERED 15 // , int
+#define EL_PREP_TERM 16 // , int
+#define EL_GETTC 17 // , const char *, ..., NULL
+#define EL_GETFP 18 // , int, FILE **
+#define EL_SETFP 19 // , int, FILE *
+#define EL_REFRESH 20 // , void
+
+#define EL_BUILTIN_GETCFN (NULL)
+
+// history defines
+#define H_FUNC 0 // , UTSL
+#define H_SETSIZE 1 // , const int
+#define H_GETSIZE 2 // , void
+#define H_FIRST 3 // , void
+#define H_LAST 4 // , void
+#define H_PREV 5 // , void
+#define H_NEXT 6 // , void
+#define H_CURR 8 // , const int
+#define H_SET 7 // , int
+#define H_ADD 9 // , const char *
+#define H_ENTER 10 // , const char *
+#define H_APPEND 11 // , const char *
+#define H_END 12 // , void
+#define H_NEXT_STR 13 // , const char *
+#define H_PREV_STR 14 // , const char *
+#define H_NEXT_EVENT 15 // , const int
+#define H_PREV_EVENT 16 // , const int
+#define H_LOAD 17 // , const char *
+#define H_SAVE 18 // , const char *
+#define H_CLEAR 19 // , void
+#define H_SETUNIQUE 20 // , int
+#define H_GETUNIQUE 21 // , void
+#define H_DEL 22 // , int
+
+struct EditLine
+{
+};
+
+struct LineInfo
+{
+ const char *buffer;
+ const char *cursor;
+ const char *lastchar;
+};
+
+struct History
+{
+};
+
+struct HistEvent
+{
+ int num;
+ const char *str;
+};
+
+extern "C"
+{
+ // edit line API
+ EditLine *el_init ( const char *, FILE *, FILE *, FILE * );
+ const char *el_gets ( EditLine *, int * );
+ int el_set ( EditLine *, int, ... );
+
+ void el_end ( EditLine * );
+ void el_reset ( EditLine * );
+ int el_getc ( EditLine *, char * );
+ void el_push ( EditLine *, char * );
+ void el_beep ( EditLine * );
+ int el_parse ( EditLine *, int, const char ** );
+ int el_get ( EditLine *, int, ... );
+ int el_source ( EditLine *, const char * );
+ void el_resize ( EditLine * );
+ const LineInfo *el_line ( EditLine * );
+ int el_insertstr( EditLine *, const char * );
+ void el_deletestr( EditLine *, int );
+
+ // history API
+ History *history_init( void );
+ void history_end ( History * );
+ int history ( History *, HistEvent *, int, ... );
+};
\ No newline at end of file
diff --git tools/driver/GetOptWrapper.cpp tools/driver/GetOptWrapper.cpp
new file mode 100644
index 0000000..d190867
--- /dev/null
+++ tools/driver/GetOptWrapper.cpp
@@ -0,0 +1,32 @@
+//===-- GetOptWrapper.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// this file is only relevant for Visual C++
+#if defined( _MSC_VER )
+
+#include "GetOptWrapper.h"
+
+/*
+
+// already defined in lldbHostCommon.lib due to 'getopt.inc'
+
+extern int getopt_long_only
+(
+ int ___argc,
+ char *const *___argv,
+ const char *__shortopts,
+ const struct option *__longopts,
+ int *__longind
+)
+{
+ return -1;
+}
+*/
+
+#endif
\ No newline at end of file
diff --git tools/driver/GetOptWrapper.h tools/driver/GetOptWrapper.h
new file mode 100644
index 0000000..9c9cf03
--- /dev/null
+++ tools/driver/GetOptWrapper.h
@@ -0,0 +1,49 @@
+//===-- GetOptWrapper.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_GetOptWrapper_h_
+#define lldb_GetOptWrapper_h_
+
+// from getopt.h
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+// defined int unistd.h
+extern int optreset;
+
+// from getopt.h
+extern char *optarg;
+extern int optind;
+extern int opterr;
+extern int optopt;
+
+// option structure
+struct option
+{
+ const char *name;
+ // has_arg can't be an enum because some compilers complain about
+ // type mismatches in all the code that assumes it is an int.
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+//
+extern int
+getopt_long_only
+(
+ int ___argc,
+ char *const *___argv,
+ const char *__shortopts,
+ const struct option *__longopts,
+ int *__longind
+);
+
+#endif // lldb_GetOptWrapper_h_
\ No newline at end of file
diff --git tools/driver/IOChannel.cpp tools/driver/IOChannel.cpp
index 520cba8..79c500d 100644
--- tools/driver/IOChannel.cpp
+++ tools/driver/IOChannel.cpp
@@ -73,7 +73,8 @@ void
IOChannel::EraseCharsBeforeCursor ()
{
const LineInfo *line_info = el_line(m_edit_line);
- el_deletestr(m_edit_line, line_info->cursor - line_info->buffer);
+ if ( line_info != NULL )
+ el_deletestr(m_edit_line, line_info->cursor - line_info->buffer);
}
unsigned char
@@ -242,19 +243,7 @@ IOChannel::IOChannel
// Set up mutex to make sure OutErr, OutWrite and RefreshPrompt do not interfere
// with each other when writing.
- int error;
- ::pthread_mutexattr_t attr;
- error = ::pthread_mutexattr_init (&attr);
- assert (error == 0);
- error = ::pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
- assert (error == 0);
- error = ::pthread_mutex_init (&m_output_mutex, &attr);
- assert (error == 0);
- error = ::pthread_mutexattr_destroy (&attr);
- assert (error == 0);
-
- error = ::pthread_cond_init (&m_output_cond, NULL);
- assert (error == 0);
+ mutex_init( &m_output_mutex );
// Initialize time that ::el_gets was last called.
@@ -279,8 +268,7 @@ IOChannel::~IOChannel ()
m_edit_line = NULL;
}
- ::pthread_cond_destroy (&m_output_cond);
- ::pthread_mutex_destroy (&m_output_mutex);
+ mutex_free(&m_output_mutex);
}
void
@@ -347,7 +335,7 @@ IOChannel::LibeditOutputBytesReceived (void *baton, const void *src, size_t src_
// Signal that we have finished all data up to the sync point.
IOLocker locker (io_channel->m_output_mutex);
io_channel->m_output_flushed = true;
- pthread_cond_signal (&io_channel->m_output_cond);
+ condvar_signal( &io_channel->m_output_cond );
}
}
@@ -379,7 +367,7 @@ IOChannel::LibeditGetInput (std::string &new_line)
// LibeditOutputBytesReceived has processed everything up till that mark.
fputc (0, m_editline_out);
- while (!m_output_flushed && pthread_cond_wait (&m_output_cond, &m_output_mutex))
+ while (!m_output_flushed && condvar_wait(&m_output_cond, &m_output_mutex))
{ /* wait */ }
}
@@ -417,8 +405,8 @@ IOChannel::LibeditGetInput (std::string &new_line)
return retval;
}
-void *
-IOChannel::IOReadThread (void *ptr)
+thread_result_t
+IOChannel::IOReadThread( void *ptr )
{
IOChannel *myself = static_cast<IOChannel *> (ptr);
myself->Run();
@@ -540,8 +528,7 @@ IOChannel::Start ()
if (IS_VALID_LLDB_HOST_THREAD(m_read_thread))
return true;
- m_read_thread = SBHostOS::ThreadCreate ("<lldb.driver.commandline_io>", IOChannel::IOReadThread, this,
- NULL);
+ m_read_thread = SBHostOS::ThreadCreate( "<lldb.driver.commandline_io>", (lldb::thread_func_t) IOChannel::IOReadThread, this, NULL );
return (IS_VALID_LLDB_HOST_THREAD(m_read_thread));
}
@@ -670,16 +657,16 @@ IOChannel::SetGettingCommand (bool new_value)
m_getting_command = new_value;
}
-IOLocker::IOLocker (pthread_mutex_t &mutex) :
+IOLocker::IOLocker (lldb_mutex &mutex) :
m_mutex_ptr (&mutex)
{
if (m_mutex_ptr)
- ::pthread_mutex_lock (m_mutex_ptr);
+ mutex_lock (m_mutex_ptr);
}
IOLocker::~IOLocker ()
{
if (m_mutex_ptr)
- ::pthread_mutex_unlock (m_mutex_ptr);
+ mutex_unlock (m_mutex_ptr);
}
diff --git tools/driver/IOChannel.h tools/driver/IOChannel.h
index 9006f70..2b82b3a 100644
--- tools/driver/IOChannel.h
+++ tools/driver/IOChannel.h
@@ -12,16 +12,6 @@
#include <string>
#include <queue>
-
-#if defined(__FreeBSD__) || defined(__NetBSD__)
-#include <readline/readline.h>
-#else
-#include <editline/readline.h>
-#endif
-#include <histedit.h>
-#include <pthread.h>
-#include <sys/time.h>
-
#include "Driver.h"
class IOChannel : public lldb::SBBroadcaster
@@ -63,7 +53,7 @@ public:
bool
Stop ();
- static void *
+ static lldb::thread_result_t
IOReadThread (void *);
void
@@ -127,8 +117,8 @@ protected:
private:
- pthread_mutex_t m_output_mutex;
- pthread_cond_t m_output_cond;
+ lldb_mutex m_output_mutex;
+ lldb_cond m_output_cond;
struct timeval m_enter_elgets_time;
Driver *m_driver;
@@ -160,13 +150,13 @@ class IOLocker
{
public:
- IOLocker (pthread_mutex_t &mutex);
+ IOLocker (lldb_mutex &mutex);
~IOLocker ();
protected:
- pthread_mutex_t *m_mutex_ptr;
+ lldb_mutex *m_mutex_ptr;
private:
diff --git tools/driver/Mutex.cpp tools/driver/Mutex.cpp
new file mode 100644
index 0000000..fd38480
--- /dev/null
+++ tools/driver/Mutex.cpp
@@ -0,0 +1,91 @@
+//===-- Mutex.cpp -----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Platform.h"
+
+#if defined( _MSC_VER )
+
+// platform indepentent locking functions
+void mutex_init( lldb_mutex *mux )
+{
+ InitializeCriticalSection( mux );
+}
+
+void mutex_free( lldb_mutex *mux )
+{
+ DeleteCriticalSection( mux );
+}
+
+void mutex_lock( lldb_mutex *mux )
+{
+ EnterCriticalSection( mux );
+}
+
+void mutex_unlock( lldb_mutex *mux )
+{
+ LeaveCriticalSection( mux );
+}
+
+// condition variables
+int condvar_signal( lldb_cond *cv )
+{
+ return 0;
+}
+
+int condvar_wait( lldb_cond *cv, lldb_mutex *mux )
+{
+ return 0;
+}
+
+
+#else
+ #include <assert.h>
+
+// platform indepentent locking functions
+void mutex_init( lldb_mutex *mux )
+{
+ int error;
+ ::pthread_mutexattr_t attr;
+ error = ::pthread_mutexattr_init (&attr);
+ assert (error == 0);
+ error = ::pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
+ assert (error == 0);
+ error = ::pthread_mutex_init ( mux, &attr);
+ assert (error == 0);
+ error = ::pthread_mutexattr_destroy (&attr);
+ assert (error == 0);
+}
+
+void mutex_free( lldb_mutex *mux )
+{
+ ::pthread_mutex_destroy ( mux);
+}
+
+void mutex_lock( lldb_mutex *mux )
+{
+ ::pthread_mutex_lock( mux );
+}
+
+void mutex_unlock( lldb_mutex *mux )
+{
+ ::pthread_mutex_unlock( mux );
+}
+
+// condition variables
+int condvar_signal( lldb_cond *cv )
+{
+ return pthread_cond_signal( cv );
+}
+
+int condvar_wait( lldb_cond *cv, lldb_mutex *mux )
+{
+ return pthread_cond_wait( cv, mux );
+}
+
+#endif
\ No newline at end of file
diff --git tools/driver/Platform.cpp tools/driver/Platform.cpp
new file mode 100644
index 0000000..1ca38d9
--- /dev/null
+++ tools/driver/Platform.cpp
@@ -0,0 +1,105 @@
+//===-- Platform.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// this file is only relevant for Visual C++
+#if defined( _MSC_VER )
+
+#include <process.h>
+#include <assert.h>
+
+#include "Platform.h"
+
+// index one of the variable arguments
+// presuming "(EditLine *el, ..." is first in the argument list
+#define GETARG( Y, X ) ( (void* ) *( ( (int**) &(Y) ) + (X) ) )
+
+// the control handler or SIGINT handler
+static sighandler_t _ctrlHandler = NULL;
+
+// the default console control handler
+BOOL WINAPI CtrlHandler( DWORD ctrlType )
+{
+ if ( _ctrlHandler != NULL )
+ {
+ _ctrlHandler( 0 );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+int ioctl( int d, int request, ... )
+{
+ switch ( request )
+ {
+ // request the console windows size
+ case ( TIOCGWINSZ ):
+ {
+ // locate the window size structure on stack
+ winsize *ws = (winsize*) GETARG( d, 2 );
+ // get screen buffer information
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE ), &info );
+ // fill in the columns
+ ws->ws_col = info.dwMaximumWindowSize.X;
+ //
+ return 0;
+ }
+ break;
+ default:
+ assert( !"Not implemented!" );
+ }
+ return -1;
+}
+
+int kill ( pid_t pid, int sig )
+{
+ // is the app trying to kill itself
+ if ( pid == getpid( ) )
+ exit( sig );
+ //
+ assert( !"Not implemented!" );
+ return -1;
+}
+
+int tcsetattr( int fd, int optional_actions, const struct termios *termios_p )
+{
+ assert( !"Not implemented!" );
+ return -1;
+}
+
+int tcgetattr( int fildes, struct termios *termios_p )
+{
+// assert( !"Not implemented!" );
+ // error return value (0=success)
+ return -1;
+}
+
+sighandler_t signal( int sig, sighandler_t sigFunc )
+{
+ switch ( sig )
+ {
+ case ( SIGINT ):
+ {
+ _ctrlHandler = sigFunc;
+ SetConsoleCtrlHandler( CtrlHandler, TRUE );
+ }
+ break;
+ case ( SIGPIPE ):
+ case ( SIGWINCH ):
+ case ( SIGTSTP ):
+ case ( SIGCONT ):
+ // ignore these for now
+ break;
+ default:
+ assert( !"Not implemented!" );
+ }
+ return 0;
+}
+
+#endif
\ No newline at end of file
diff --git tools/driver/Platform.h tools/driver/Platform.h
new file mode 100644
index 0000000..f3c0b82
--- /dev/null
+++ tools/driver/Platform.h
@@ -0,0 +1,134 @@
+//===-- Platform.h ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_Platform_h_
+#define lldb_Platform_h_
+
+#if defined( _MSC_VER )
+
+ #define PRIu32 "u"
+ #define PRId64 "I64d"
+ #define PRIi64 "I64i"
+ #define PRIo64 "I64o"
+ #define PRIu64 "I64u"
+ #define PRIx64 "I64x"
+ #define PRIX64 "I64X"
+
+ // this will stop signal.h being included
+ #define _INC_SIGNAL
+
+ #include <io.h>
+ #include "ELWrapper.h"
+ #include "lldb/Host/windows/Windows.h"
+ #include "GetOptWrapper.h"
+
+ struct timeval
+ {
+ long tv_sec;
+ long tv_usec;
+ };
+
+ struct winsize
+ {
+ long ws_col;
+ };
+
+ typedef unsigned char cc_t;
+ typedef unsigned int speed_t;
+ typedef unsigned int tcflag_t;
+
+ // fcntl.h
+ #define O_NOCTTY 0400
+
+ // ioctls.h
+ #define TIOCGWINSZ 0x5413
+
+ // signal.h
+ #define SIGPIPE 13
+ #define SIGCONT 18
+ #define SIGTSTP 20
+ #define SIGWINCH 28
+
+ // tcsetattr arguments
+ #define TCSANOW 0
+
+ #define NCCS 32
+ struct termios
+ {
+ tcflag_t c_iflag; // input mode flags
+ tcflag_t c_oflag; // output mode flags
+ tcflag_t c_cflag; // control mode flags
+ tcflag_t c_lflag; // local mode flags
+ cc_t c_line; // line discipline
+ cc_t c_cc[NCCS]; // control characters
+ speed_t c_ispeed; // input speed
+ speed_t c_ospeed; // output speed
+ };
+
+ typedef long pid_t;
+ typedef CRITICAL_SECTION lldb_mutex;
+ typedef CONDITION_VARIABLE lldb_cond;
+
+ #define STDIN_FILENO 0
+
+ #define PATH_MAX MAX_PATH
+ #define snprintf _snprintf
+
+ extern int ioctl( int d, int request, ... );
+ extern int kill ( pid_t pid, int sig );
+ extern int tcsetattr( int fd, int optional_actions, const struct termios *termios_p );
+ extern int tcgetattr( int fildes, struct termios *termios_p );
+
+ // signal handler function pointer type
+ typedef void (*sighandler_t)(int);
+
+ // signal.h
+ #define SIGINT 2
+ // default handler
+ #define SIG_DFL ( (sighandler_t) -1 )
+ // ignored
+ #define SIG_IGN ( (sighandler_t) -2 )
+ extern sighandler_t signal( int sig, sighandler_t );
+
+#else
+
+ #if defined(__FreeBSD__)
+ #include <readline/readline.h>
+ #else
+ #include <editline/readline.h>
+ #endif
+
+ #include <inttypes.h>
+
+ #include <getopt.h>
+ #include <libgen.h>
+ #include <sys/ioctl.h>
+ #include <termios.h>
+ #include <unistd.h>
+
+ #include <histedit.h>
+ #include <pthread.h>
+ #include <sys/time.h>
+
+ typedef pthread_mutex_t lldb_mutex;
+ typedef pthread_cond_t lldb_cond;
+
+#endif
+
+// platform independant locking functions
+extern void mutex_init ( lldb_mutex *mux );
+extern void mutex_free ( lldb_mutex *mux );
+extern void mutex_lock ( lldb_mutex *mux );
+extern void mutex_unlock( lldb_mutex *mux );
+
+// platform independant condition variables
+extern int condvar_signal( lldb_cond *cnd );
+extern int condvar_wait ( lldb_cond *cnd, lldb_mutex *mux );
+
+#endif // lldb_Platform_h_
\ No newline at end of file
More information about the lldb-commits
mailing list