@@ -61,6 +61,7 @@ const char* lldb_prep_noninteractive_cmds = "\
61
61
*/
62
62
#define LLDB_FRUITSTRAP_MODULE CFSTR("\
63
63
import lldb\n\
64
+ import os\n\
64
65
import sys\n\
65
66
import shlex\n\
66
67
\n\
@@ -90,13 +91,14 @@ def connect_command(debugger, command, result, internal_dict):\n\
90
91
\n\
91
92
def run_command(debugger, command, result, internal_dict):\n\
92
93
device_app = internal_dict['fruitstrap_device_app']\n\
94
+ args = command.split('--',1)\n\
93
95
error = lldb.SBError()\n\
94
96
lldb.target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec(device_app))\n\
95
- lldb.target.Launch(lldb.SBLaunchInfo(shlex.split('{args}')), error)\n\
97
+ lldb.target.Launch(lldb.SBLaunchInfo(shlex.split(args[1] and args[1] or '{args}')), error)\n\
96
98
lockedstr = ': Locked'\n\
97
99
if lockedstr in str(error):\n\
98
100
print('\\nDevice Locked\\n')\n\
99
- sys.exit (254)\n\
101
+ os._exit (254)\n\
100
102
else:\n\
101
103
print(str(error))\n\
102
104
\n\
@@ -106,23 +108,33 @@ def safequit_command(debugger, command, result, internal_dict):\n\
106
108
listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n\
107
109
event = lldb.SBEvent()\n\
108
110
while True:\n\
109
- if listener.WaitForEvent(1, event):\n\
110
- state = process .GetStateFromEvent(event)\n\
111
+ if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event) :\n\
112
+ state = lldb.SBProcess .GetStateFromEvent(event)\n\
111
113
else:\n\
112
- state = lldb.eStateInvalid\n\
113
- process.Detach()\n\
114
- sys.exit(0)\n\
114
+ state = process.GetState()\n\
115
+ \n\
116
+ if state == lldb.eStateRunning:\n\
117
+ process.Detach()\n\
118
+ os._exit(0)\n\
119
+ elif state > lldb.eStateRunning:\n\
120
+ os._exit(state)\n\
115
121
\n\
116
122
def autoexit_command(debugger, command, result, internal_dict):\n\
117
123
process = lldb.target.process\n\
118
124
listener = debugger.GetListener()\n\
119
125
listener.StartListeningForEvents(process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR)\n\
120
126
event = lldb.SBEvent()\n\
121
127
while True:\n\
122
- if listener.WaitForEvent(1, event):\n\
123
- state = process .GetStateFromEvent(event)\n\
128
+ if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event) :\n\
129
+ state = lldb.SBProcess .GetStateFromEvent(event)\n\
124
130
else:\n\
125
- state = lldb.eStateInvalid\n\
131
+ state = process.GetState()\n\
132
+ \n\
133
+ if state == lldb.eStateExited:\n\
134
+ os._exit(process.GetExitStatus())\n\
135
+ elif state == lldb.eStateStopped:\n\
136
+ debugger.HandleCommand('bt')\n\
137
+ os._exit({exitcode_app_crash})\n\
126
138
\n\
127
139
stdout = process.GetSTDOUT(1024)\n\
128
140
while stdout:\n\
@@ -133,14 +145,6 @@ def autoexit_command(debugger, command, result, internal_dict):\n\
133
145
while stderr:\n\
134
146
sys.stdout.write(stderr)\n\
135
147
stderr = process.GetSTDERR(1024)\n\
136
- \n\
137
- if lldb.SBProcess.EventIsProcessEvent(event):\n\
138
- if state == lldb.eStateExited:\n\
139
- sys.exit(process.GetExitStatus())\n\
140
- if state == lldb.eStateStopped:\n\
141
- debugger.HandleCommand('frame select')\n\
142
- debugger.HandleCommand('bt')\n\
143
- sys.exit({exitcode_app_crash})\n\
144
148
")
145
149
146
150
typedef struct am_device * AMDeviceRef ;
@@ -164,7 +168,7 @@ char *device_id = NULL;
164
168
char * args = NULL ;
165
169
char * list_root = NULL ;
166
170
int timeout = 0 ;
167
- int port = 12345 ;
171
+ int port = 0 ; // 0 means "dynamically assigned"
168
172
CFStringRef last_path = NULL ;
169
173
service_conn_t gdbfd ;
170
174
pid_t parent = 0 ;
@@ -822,22 +826,9 @@ server_callback (CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef add
822
826
int res ;
823
827
824
828
if (CFDataGetLength (data ) == 0 ) {
825
- // FIXME: Close the socket
826
- //shutdown (CFSocketGetNative (lldb_socket), SHUT_RDWR);
827
- //close (CFSocketGetNative (lldb_socket));
828
- CFSocketInvalidate (lldb_socket );
829
- CFSocketInvalidate (server_socket );
830
- int mypid = getpid ();
831
- assert ((child != 0 ) && (child != mypid )); //child should not be here
832
- if ((parent != 0 ) && (parent == mypid ) && (child != 0 ))
833
- {
834
- if (verbose )
835
- {
836
- printf ("Got an empty packet hence killing child (%d) tree\n" , child );
837
- }
838
- kill_ptree (child , SIGHUP );
839
- }
840
- exit (exitcode_error );
829
+ // close the socket on which we've got end-of-file, the server_socket.
830
+ CFSocketInvalidate (s );
831
+ CFRelease (s );
841
832
return ;
842
833
}
843
834
res = write (CFSocketGetNative (lldb_socket ), CFDataGetBytePtr (data ), CFDataGetLength (data ));
@@ -847,8 +838,12 @@ void lldb_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef a
847
838
{
848
839
//printf ("lldb: %s\n", CFDataGetBytePtr (data));
849
840
850
- if (CFDataGetLength (data ) == 0 )
841
+ if (CFDataGetLength (data ) == 0 ) {
842
+ // close the socket on which we've got end-of-file, the lldb_socket.
843
+ CFSocketInvalidate (s );
844
+ CFRelease (s );
851
845
return ;
846
+ }
852
847
write (gdbfd , CFDataGetBytePtr (data ), CFDataGetLength (data ));
853
848
}
854
849
@@ -859,21 +854,20 @@ void fdvendor_callback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataR
859
854
//PRINT ("callback!\n");
860
855
861
856
lldb_socket = CFSocketCreateWithNative (NULL , socket , kCFSocketDataCallBack , & lldb_callback , NULL );
857
+ int flag = 1 ;
858
+ int res = setsockopt (socket , IPPROTO_TCP , TCP_NODELAY , (char * ) & flag , sizeof (flag ));
859
+ assert (res == 0 );
862
860
CFRunLoopAddSource (CFRunLoopGetMain (), CFSocketCreateRunLoopSource (NULL , lldb_socket , 0 ), kCFRunLoopCommonModes );
861
+
862
+ CFSocketInvalidate (s );
863
+ CFRelease (s );
863
864
}
864
865
865
866
void start_remote_debug_server (AMDeviceRef device ) {
866
- char buf [256 ];
867
- int res , err , i ;
868
- char msg [256 ];
869
- int chsum , len ;
870
- struct stat s ;
871
- socklen_t buflen ;
872
- struct sockaddr name ;
873
- int namelen ;
874
-
875
- assert (AMDeviceStartService (device , CFSTR ("com.apple.debugserver" ), & gdbfd , NULL ) == 0 );
876
- assert (gdbfd );
867
+
868
+ int res = AMDeviceStartService (device , CFSTR ("com.apple.debugserver" ), & gdbfd , NULL );
869
+ assert (res == 0 );
870
+ assert (gdbfd > 0 );
877
871
878
872
/*
879
873
* The debugserver connection is through a fd handle, while lldb requires a host/port to connect, so create an intermediate
@@ -887,20 +881,24 @@ void start_remote_debug_server(AMDeviceRef device) {
887
881
addr4 .sin_len = sizeof (addr4 );
888
882
addr4 .sin_family = AF_INET ;
889
883
addr4 .sin_port = htons (port );
890
- addr4 .sin_addr .s_addr = htonl (INADDR_ANY );
884
+ addr4 .sin_addr .s_addr = htonl (INADDR_LOOPBACK );
891
885
892
886
CFSocketRef fdvendor = CFSocketCreate (NULL , PF_INET , 0 , 0 , kCFSocketAcceptCallBack , & fdvendor_callback , NULL );
893
887
894
- int yes = 1 ;
895
- setsockopt (CFSocketGetNative (fdvendor ), SOL_SOCKET , SO_REUSEADDR , & yes , sizeof (yes ));
896
- int flag = 1 ;
897
- res = setsockopt (CFSocketGetNative (fdvendor ), IPPROTO_TCP , TCP_NODELAY , (char * ) & flag , sizeof (int ));
898
- assert (res == 0 );
888
+ if (port ) {
889
+ int yes = 1 ;
890
+ setsockopt (CFSocketGetNative (fdvendor ), SOL_SOCKET , SO_REUSEADDR , & yes , sizeof (yes ));
891
+ }
899
892
900
893
CFDataRef address_data = CFDataCreate (NULL , (const UInt8 * )& addr4 , sizeof (addr4 ));
901
894
902
895
CFSocketSetAddress (fdvendor , address_data );
903
896
CFRelease (address_data );
897
+ socklen_t addrlen = sizeof (addr4 );
898
+ res = getsockname (CFSocketGetNative (fdvendor ),(struct sockaddr * )& addr4 ,& addrlen );
899
+ assert (res == 0 );
900
+ port = ntohs (addr4 .sin_port );
901
+
904
902
CFRunLoopAddSource (CFRunLoopGetMain (), CFSocketCreateRunLoopSource (NULL , fdvendor , 0 ), kCFRunLoopCommonModes );
905
903
}
906
904
@@ -1665,7 +1663,7 @@ void usage(const char* app) {
1665
1663
" -L, --justlaunch just launch the app and exit lldb\n"
1666
1664
" -v, --verbose enable verbose output\n"
1667
1665
" -m, --noinstall directly start debugging without app install (-d not required)\n"
1668
- " -p, --port <number> port used for device, default: 12345 \n"
1666
+ " -p, --port <number> port used for device, default: dynamic \n"
1669
1667
" -r, --uninstall uninstall the app before install (do not use with -m; app cache and data are cleared) \n"
1670
1668
" -1, --bundle_id <bundle id> specify bundle id for list and upload\n"
1671
1669
" -l, --list list files\n"
0 commit comments