|
1 Class { |
|
2 #name : #GDBPortlibPharo, |
|
3 #superclass : #GDBPortlib, |
|
4 #category : #'LibGDBs-Internal-Portlib-Pharo' |
|
5 } |
|
6 |
|
7 { #category : #initialization } |
|
8 GDBPortlibPharo class >> initialize [ |
|
9 Current := self basicNew initialize. |
|
10 |
|
11 " |
|
12 GDBPortlib current |
|
13 " |
|
14 ] |
|
15 |
|
16 { #category : #'user interface' } |
|
17 GDBPortlibPharo >> newCLI: aGDBDebugger [ |
|
18 "Open GDB CLI for interactive debugging for given debugger. |
|
19 See `GDBDebugger >> #cli`." |
|
20 |
|
21 | win | |
|
22 |
|
23 (Smalltalk includesKey: #TerminalEmulator) ifFalse: [ |
|
24 self error: 'PTerm not available - you may want to load PTerm from https://github.com/janvrany/PTerm' |
|
25 |
|
26 ]. |
|
27 |
|
28 win := aGDBDebugger propertyAt: #cli. |
|
29 win isNil ifTrue: [ |
|
30 aGDBDebugger consoleOutput isNil ifTrue:[ |
|
31 self error: 'This GDBDebugger does not have CLI channel open - you may want to use GDBUnixProcess.' |
|
32 ]. |
|
33 win := TerminalEmulator openPTY: aGDBDebugger consoleOutput fileDescriptor. |
|
34 win setLabel: 'GDB CLI'. |
|
35 |
|
36 "When window is closed, forget it (so subsequent call to |
|
37 `GDBDebugger >> #cli` opens a new CLI window):" |
|
38 win announcer when: WindowClosed do: [ :windowClosed | |
|
39 windowClosed window == win ifTrue:[ |
|
40 aGDBDebugger propertyAt: #cli put: win. |
|
41 ] |
|
42 ]. |
|
43 |
|
44 "When GDB terminates, close the CLI." |
|
45 aGDBDebugger announcer when: GDBExitEvent do:[ :exit | |
|
46 | winFromDebugger | |
|
47 |
|
48 winFromDebugger := aGDBDebugger propertyAt: #cli. |
|
49 winFromDebugger notNil ifTrue:[ |
|
50 winFromDebugger close. |
|
51 ]. |
|
52 ]. |
|
53 |
|
54 "Finally, store the reference to CLI window into debugger |
|
55 so we can fetch it later..." |
|
56 aGDBDebugger propertyAt: #cli put: win. |
|
57 ] ifFalse: [ |
|
58 win activate. |
|
59 ]. |
|
60 |
|
61 "Created: / 05-08-2023 / 07:38:23 / Jan Vrany <jan.vrany@labware.com>" |
|
62 |
|
63 ] |
|
64 |
|
65 { #category : #streams } |
|
66 GDBPortlibPharo >> newPTY [ |
|
67 "Allocate a PTY and return it as an instance of GDBPTY" |
|
68 |
|
69 | fdM fdS name streamM streamS | |
|
70 |
|
71 fdM := LibC posix_openpt: (2"O_RDWR" | 0400"O_NOCTTY" | 04000"O_NONBLOCK"). |
|
72 fdM < 0 ifTrue:[ |
|
73 self error: 'posix_openpt() failed'. |
|
74 ^ nil |
|
75 ]. |
|
76 LibC grantpt: fdM. |
|
77 LibC unlockpt: fdM. |
|
78 name := LibC ptsname: fdM. |
|
79 name isNil ifTrue:[ |
|
80 LibC close: fdM. |
|
81 self error: 'ptsname() failed'. |
|
82 ^ nil |
|
83 ]. |
|
84 fdS := LibC open: name _: 2"O_RDWR". |
|
85 fdS < 0 ifTrue:[ |
|
86 LibC close: fdM. |
|
87 self error: 'Failed to open ', name. |
|
88 ^ nil. |
|
89 ]. |
|
90 |
|
91 streamM := BinaryPipeStream basicNew descriptor: fdM writable: true. |
|
92 streamS := BinaryPipeStream basicNew descriptor: fdS writable: true. |
|
93 |
|
94 ^ GDBPTY name: name |
|
95 masterReadStream: (ZnCharacterReadStream on: streamM encoding: 'ascii') |
|
96 masterWriteStream: (ZnCharacterWriteStream on: streamM encoding: 'ascii') |
|
97 slaveReadStream: (ZnCharacterReadStream on: streamS encoding: 'ascii') |
|
98 slaveWriteStream: (ZnCharacterWriteStream on: streamS encoding: 'ascii') |
|
99 |
|
100 ] |
|
101 |
|
102 { #category : #streams } |
|
103 GDBPortlibPharo >> newPipe [ |
|
104 "Create a pipe and return an array with pipe's read end and write end |
|
105 (in this order) as smalltalk streams." |
|
106 |
|
107 | pipe | |
|
108 |
|
109 pipe := BinaryPipeStream create. |
|
110 ^ { ZnCharacterReadStream on: pipe first encoding: 'ascii' . |
|
111 ZnCharacterWriteStream on: pipe second encoding: 'ascii' } |
|
112 |
|
113 |
|
114 ] |
|
115 |
|
116 { #category : #processes } |
|
117 GDBPortlibPharo >> spawn: argv stdin: stdin stdout: stdout stderr: stderr exit: action [ |
|
118 ^ Smalltalk os spawn: argv stdin: stdin stdout: stdout stderr: stderr exit: action |
|
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 ] |