@@ -13,13 +13,36 @@ import * as path from 'path';
13
13
import { DebugProtocol } from '@vscode/debugprotocol/lib/debugProtocol' ;
14
14
import { CdtDebugClient } from './debugClient' ;
15
15
import { fillDefaults , standardBeforeEach , testProgramsDir } from './utils' ;
16
+ import { assert } from 'sinon' ;
16
17
17
18
describe ( 'Disassembly Test Suite' , function ( ) {
18
19
let dc : CdtDebugClient ;
19
20
let frame : DebugProtocol . StackFrame ;
20
21
const disProgram = path . join ( testProgramsDir , 'disassemble' ) ;
21
22
const disSrc = path . join ( testProgramsDir , 'disassemble.c' ) ;
22
23
24
+ const expectsGeneralDisassemble = (
25
+ disassemble : DebugProtocol . DisassembleResponse ,
26
+ length : number ,
27
+ ignoreEmptyInstructions ?: boolean
28
+ ) => {
29
+ expect ( disassemble ) . not . eq ( undefined ) ;
30
+ expect ( disassemble . body ) . not . eq ( undefined ) ;
31
+ if ( disassemble . body ) {
32
+ const instructions = disassemble . body . instructions ;
33
+ expect ( instructions ) . to . have . lengthOf ( length ) ;
34
+ // the contents of the instructions are platform dependent, so instead
35
+ // make sure we have read fully
36
+ for ( const i of instructions ) {
37
+ expect ( i . address ) . to . have . lengthOf . greaterThan ( 0 ) ;
38
+ expect ( i . instruction ) . to . have . lengthOf . greaterThan ( 0 ) ;
39
+ if ( ! ignoreEmptyInstructions ) {
40
+ expect ( i . instructionBytes ) . to . have . lengthOf . greaterThan ( 0 ) ;
41
+ }
42
+ }
43
+ }
44
+ } ;
45
+
23
46
beforeEach ( async function ( ) {
24
47
dc = await standardBeforeEach ( ) ;
25
48
@@ -60,19 +83,8 @@ describe('Disassembly Test Suite', function () {
60
83
memoryReference : 'main' ,
61
84
instructionCount : 100 ,
62
85
} ) ) as DebugProtocol . DisassembleResponse ;
63
- expect ( disassemble ) . not . eq ( undefined ) ;
64
- expect ( disassemble . body ) . not . eq ( undefined ) ;
65
- if ( disassemble . body ) {
66
- const instructions = disassemble . body . instructions ;
67
- expect ( instructions ) . to . have . lengthOf ( 100 ) ;
68
- // the contents of the instructions are platform dependent, so instead
69
- // make sure we have read fully
70
- for ( const i of instructions ) {
71
- expect ( i . address ) . to . have . lengthOf . greaterThan ( 0 ) ;
72
- expect ( i . instructionBytes ) . to . have . lengthOf . greaterThan ( 0 ) ;
73
- expect ( i . instruction ) . to . have . lengthOf . greaterThan ( 0 ) ;
74
- }
75
- }
86
+
87
+ expectsGeneralDisassemble ( disassemble , 100 ) ;
76
88
} ) ;
77
89
78
90
it ( 'can disassemble with no source references' , async function ( ) {
@@ -82,38 +94,102 @@ describe('Disassembly Test Suite', function () {
82
94
memoryReference : 'main+1000' ,
83
95
instructionCount : 100 ,
84
96
} ) ) as DebugProtocol . DisassembleResponse ;
85
- expect ( disassemble ) . not . eq ( undefined ) ;
86
- expect ( disassemble . body ) . not . eq ( undefined ) ;
87
- if ( disassemble . body ) {
88
- const instructions = disassemble . body . instructions ;
89
- expect ( instructions ) . to . have . lengthOf ( 100 ) ;
90
- // the contents of the instructions are platform dependent, so instead
91
- // make sure we have read fully
92
- for ( const i of instructions ) {
93
- expect ( i . address ) . to . have . lengthOf . greaterThan ( 0 ) ;
94
- expect ( i . instructionBytes ) . to . have . lengthOf . greaterThan ( 0 ) ;
95
- expect ( i . instruction ) . to . have . lengthOf . greaterThan ( 0 ) ;
96
- }
97
- }
97
+
98
+ expectsGeneralDisassemble ( disassemble , 100 ) ;
98
99
} ) ;
99
100
100
- it ( 'can handle disassemble at bad address ' , async function ( ) {
101
+ it ( 'can disassemble with negative offsets ' , async function ( ) {
101
102
const disassemble = ( await dc . send ( 'disassemble' , {
102
- memoryReference : '0x0' ,
103
- instructionCount : 10 ,
104
- } ) ) as DebugProtocol . DisassembleResponse ;
105
- expect ( disassemble ) . not . eq ( undefined ) ;
106
- expect ( disassemble . body ) . not . eq ( undefined ) ;
107
- if ( disassemble . body ) {
108
- const instructions = disassemble . body . instructions ;
109
- expect ( instructions ) . to . have . lengthOf ( 10 ) ;
110
- // the contens of the instructions are platform dependent, so instead
111
- // make sure we have read fully
112
- for ( const i of instructions ) {
113
- expect ( i . address ) . to . have . lengthOf . greaterThan ( 0 ) ;
114
- expect ( i . instruction ) . to . have . lengthOf . greaterThan ( 0 ) ;
115
- expect ( i . instructionBytes ) . eq ( undefined ) ;
116
- }
103
+ memoryReference : 'main' ,
104
+ instructionOffset : - 20 ,
105
+ instructionCount : 20 ,
106
+ } as DebugProtocol . DisassembleArguments ) ) as DebugProtocol . DisassembleResponse ;
107
+
108
+ expectsGeneralDisassemble ( disassemble , 20 , true ) ;
109
+ } ) ;
110
+
111
+ it ( 'send error response handle on empty memory reference' , async function ( ) {
112
+ try {
113
+ await dc . send ( 'disassemble' , {
114
+ memoryReference : '' ,
115
+ instructionOffset : - 20 ,
116
+ instructionCount : 20 ,
117
+ } as DebugProtocol . DisassembleArguments ) ;
118
+ assert . fail ( 'Should throw error!' ) ;
119
+ } catch ( e ) {
120
+ expect ( e ) . to . be . deep . equal (
121
+ new Error ( 'Target memory reference is not specified!' )
122
+ ) ;
123
+ }
124
+ } ) ;
125
+
126
+ it ( 'can disassemble with correct boundries' , async function ( ) {
127
+ const get = (
128
+ disassemble : DebugProtocol . DisassembleResponse ,
129
+ offset : number
130
+ ) => {
131
+ const instruction = disassemble . body ?. instructions [ offset ] ;
132
+ expect ( instruction ) . not . eq ( undefined ) ;
133
+ // Instruction undefined already checked.
134
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
135
+ return instruction ! ;
136
+ } ;
137
+
138
+ const expectsInstructionEquals = (
139
+ instruction1 : DebugProtocol . DisassembledInstruction ,
140
+ instruction2 : DebugProtocol . DisassembledInstruction ,
141
+ message ?: string
142
+ ) => {
143
+ expect ( instruction1 . address ) . to . eq ( instruction2 . address , message ) ;
144
+ } ;
145
+
146
+ const disassembleLower = ( await dc . send ( 'disassemble' , {
147
+ memoryReference : 'main' ,
148
+ instructionOffset : - 20 ,
149
+ instructionCount : 20 ,
150
+ } as DebugProtocol . DisassembleArguments ) ) as DebugProtocol . DisassembleResponse ;
151
+ const disassembleMiddle = ( await dc . send ( 'disassemble' , {
152
+ memoryReference : 'main' ,
153
+ instructionOffset : - 10 ,
154
+ instructionCount : 20 ,
155
+ } as DebugProtocol . DisassembleArguments ) ) as DebugProtocol . DisassembleResponse ;
156
+ const disassembleHigher = ( await dc . send ( 'disassemble' , {
157
+ memoryReference : 'main' ,
158
+ instructionOffset : 0 ,
159
+ instructionCount : 20 ,
160
+ } as DebugProtocol . DisassembleArguments ) ) as DebugProtocol . DisassembleResponse ;
161
+
162
+ expectsGeneralDisassemble ( disassembleLower , 20 , true ) ;
163
+ expectsGeneralDisassemble ( disassembleMiddle , 20 , true ) ;
164
+ expectsGeneralDisassemble ( disassembleHigher , 20 , true ) ;
165
+
166
+ // Current implementation have known edge cases, possibly instruction misaligning while
167
+ // handling the negative offsets, please refer to the discussion at the following link:
168
+ // https://github.com/eclipse-cdt-cloud/cdt-gdb-adapter/pull/341#discussion_r1857422980
169
+ expectsInstructionEquals (
170
+ get ( disassembleLower , 15 ) ,
171
+ get ( disassembleMiddle , 5 ) ,
172
+ 'lower[15] should be same with middle[5]'
173
+ ) ;
174
+
175
+ expectsInstructionEquals (
176
+ get ( disassembleMiddle , 15 ) ,
177
+ get ( disassembleHigher , 5 ) ,
178
+ 'middle[15] should be same with higher[5]'
179
+ ) ;
180
+ } ) ;
181
+
182
+ it ( 'return error at bad address' , async function ( ) {
183
+ try {
184
+ await dc . send ( 'disassemble' , {
185
+ memoryReference : '0x0' ,
186
+ instructionCount : 10 ,
187
+ } as DebugProtocol . DisassembleArguments ) ;
188
+ assert . fail ( 'Should throw error!' ) ;
189
+ } catch ( e ) {
190
+ expect ( e ) . to . be . deep . equal (
191
+ new Error ( 'Cannot access memory at address 0x0' )
192
+ ) ;
117
193
}
118
194
} ) ;
119
195
} ) ;
0 commit comments