@@ -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 { calculateMemoryOffset } from '../util/calculateMemoryOffset' ;
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,99 @@ 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 ) ;
99
+ } ) ;
100
+
101
+ it ( 'can disassemble with negative offsets' , async function ( ) {
102
+ // In this case we attempt to read from where there is no source,
103
+ // GDB returns data in a different format in that case
104
+ const disassemble = ( await dc . send ( 'disassemble' , {
105
+ memoryReference : 'main' ,
106
+ instructionOffset : - 20 ,
107
+ instructionCount : 20 ,
108
+ } as DebugProtocol . DisassembleArguments ) ) as DebugProtocol . DisassembleResponse ;
109
+
110
+ expectsGeneralDisassemble ( disassemble , 20 , true ) ;
111
+ } ) ;
112
+
113
+ it ( 'can disassemble with correct boundries' , async function ( ) {
114
+ const get = (
115
+ disassemble : DebugProtocol . DisassembleResponse ,
116
+ offset : number
117
+ ) => {
118
+ const instruction = disassemble . body ?. instructions [ offset ] ;
119
+ expect ( instruction ) . not . eq ( undefined ) ;
120
+ // Instruction undefined already checked.
121
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
122
+ return instruction ! ;
123
+ } ;
124
+
125
+ const expectsInstructionEquals = (
126
+ instruction1 : DebugProtocol . DisassembledInstruction ,
127
+ instruction2 : DebugProtocol . DisassembledInstruction ,
128
+ message ?: string
129
+ ) => {
130
+ expect ( instruction1 . address ) . to . eq ( instruction2 . address , message ) ;
131
+ } ;
132
+
133
+ // In this case we attempt to read from where there is no source,
134
+ // GDB returns data in a different format in that case
135
+ const disassembleLower = ( await dc . send ( 'disassemble' , {
136
+ memoryReference : 'main' ,
137
+ instructionOffset : - 20 ,
138
+ instructionCount : 20 ,
139
+ } as DebugProtocol . DisassembleArguments ) ) as DebugProtocol . DisassembleResponse ;
140
+ const disassembleMiddle = ( await dc . send ( 'disassemble' , {
141
+ memoryReference : 'main' ,
142
+ instructionOffset : - 10 ,
143
+ instructionCount : 20 ,
144
+ } as DebugProtocol . DisassembleArguments ) ) as DebugProtocol . DisassembleResponse ;
145
+ const disassembleHigher = ( await dc . send ( 'disassemble' , {
146
+ memoryReference : 'main' ,
147
+ instructionOffset : 0 ,
148
+ instructionCount : 20 ,
149
+ } as DebugProtocol . DisassembleArguments ) ) as DebugProtocol . DisassembleResponse ;
150
+
151
+ expectsGeneralDisassemble ( disassembleLower , 20 , true ) ;
152
+ expectsGeneralDisassemble ( disassembleMiddle , 20 , true ) ;
153
+ expectsGeneralDisassemble ( disassembleHigher , 20 , true ) ;
154
+
155
+ expectsInstructionEquals (
156
+ get ( disassembleLower , 15 ) ,
157
+ get ( disassembleMiddle , 5 ) ,
158
+ 'lower[15] should be same with middle[5]'
159
+ ) ;
160
+
161
+ expectsInstructionEquals (
162
+ get ( disassembleMiddle , 15 ) ,
163
+ get ( disassembleHigher , 5 ) ,
164
+ 'middle[15] should be same with higher[5]'
165
+ ) ;
98
166
} ) ;
99
167
100
168
it ( 'can handle disassemble at bad address' , async function ( ) {
101
169
const disassemble = ( await dc . send ( 'disassemble' , {
102
170
memoryReference : '0x0' ,
103
171
instructionCount : 10 ,
104
172
} ) ) as DebugProtocol . DisassembleResponse ;
173
+
105
174
expect ( disassemble ) . not . eq ( undefined ) ;
106
175
expect ( disassemble . body ) . not . eq ( undefined ) ;
107
176
if ( disassemble . body ) {
108
177
const instructions = disassemble . body . instructions ;
109
178
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
- }
179
+ // Checking the invalid instructions content
180
+ instructions . forEach ( ( inst , ix ) => {
181
+ expect ( inst . address ) . to . eq (
182
+ calculateMemoryOffset ( '0x0' , ix * 2 )
183
+ ) ;
184
+ expect ( inst . address ) . to . have . lengthOf . greaterThan ( 0 ) ;
185
+ expect ( inst . instruction ) . to . eq (
186
+ 'failed to retrieve instruction'
187
+ ) ;
188
+ expect ( inst . presentationHint ) . to . eq ( 'invalid' ) ;
189
+ } ) ;
117
190
}
118
191
} ) ;
119
192
} ) ;
0 commit comments