Skip to content

Commit 9ffbce3

Browse files
committed
Code improvement based on feedback
1 parent dc41f19 commit 9ffbce3

File tree

3 files changed

+80
-78
lines changed

3 files changed

+80
-78
lines changed

src/integration-tests/diassemble.spec.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,6 @@ describe('Disassembly Test Suite', function () {
9999
});
100100

101101
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
104102
const disassemble = (await dc.send('disassemble', {
105103
memoryReference: 'main',
106104
instructionOffset: -20,
@@ -130,8 +128,6 @@ describe('Disassembly Test Suite', function () {
130128
expect(instruction1.address).to.eq(instruction2.address, message);
131129
};
132130

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
135131
const disassembleLower = (await dc.send('disassemble', {
136132
memoryReference: 'main',
137133
instructionOffset: -20,
@@ -152,6 +148,9 @@ describe('Disassembly Test Suite', function () {
152148
expectsGeneralDisassemble(disassembleMiddle, 20, true);
153149
expectsGeneralDisassemble(disassembleHigher, 20, true);
154150

151+
// Current implementation have known edge cases, possibly instruction misaligning while
152+
// handling the negative offsets, please refer to the discussion at the following link:
153+
// https://github.com/eclipse-cdt-cloud/cdt-gdb-adapter/pull/341#discussion_r1857422980
155154
expectsInstructionEquals(
156155
get(disassembleLower, 15),
157156
get(disassembleMiddle, 5),

src/integration-tests/util.spec.ts

+6
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,12 @@ describe('calculateMemoryOffset', () => {
182182
expect(calculateMemoryOffset('0xffeeddcc0000ff00', '0x0100')).to.eq(
183183
'0xffeeddcc00010000'
184184
);
185+
expect(
186+
calculateMemoryOffset('0xefeeddcc0000ff00', '0x10000000000000ff')
187+
).to.eq('0xffeeddcc0000ffff');
188+
expect(
189+
calculateMemoryOffset('0xefeeddcc0000ff00', '0x1000000000000100')
190+
).to.eq('0xffeeddcc00010000');
185191
});
186192
});
187193

src/util/disassembly.ts

+71-74
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,7 @@
88
* SPDX-License-Identifier: EPL-2.0
99
*********************************************************************/
1010
import { DebugProtocol } from '@vscode/debugprotocol';
11-
import {
12-
MIDataDisassembleAsmInsn,
13-
MIDataDisassembleResponse,
14-
sendDataDisassemble,
15-
} from '../mi';
11+
import { MIDataDisassembleAsmInsn, sendDataDisassemble } from '../mi';
1612
import { IGDBBackend } from '../types/gdb';
1713
import { calculateMemoryOffset } from './calculateMemoryOffset';
1814

@@ -115,85 +111,86 @@ export const getInstructions = async (
115111
) => {
116112
const list: DebugProtocol.DisassembledInstruction[] = [];
117113
const meanSizeOfInstruction = 4;
114+
const isReverseFetch = length < 0;
118115
const absLength = Math.abs(length);
119116

120-
let result: MIDataDisassembleResponse | undefined = undefined;
121-
try {
122-
result =
123-
length < 0
124-
? await sendDataDisassemble(
125-
gdb,
126-
`(${memoryReference})-${
127-
absLength * meanSizeOfInstruction
128-
}`,
129-
`(${memoryReference})+0`
130-
)
131-
: await sendDataDisassemble(
132-
gdb,
133-
`(${memoryReference})+0`,
134-
`(${memoryReference})+${
135-
absLength * meanSizeOfInstruction
136-
}`
137-
);
138-
} catch (e) {
139-
// Do nothing in case of memory error.
140-
result = undefined;
141-
}
117+
const formatMemoryAddress = (offset: number) => {
118+
return `(${memoryReference})${offset < 0 ? '-' : '+'}${Math.abs(
119+
offset
120+
)}`;
121+
};
142122

143-
if (result === undefined) {
144-
// result is undefined in case of error,
145-
// then return empty instructions list
146-
return getEmptyInstructions(memoryReference, length, 2);
147-
}
123+
const sendDataDisassembleWrapper = async (lower: number, upper: number) => {
124+
const list: DebugProtocol.DisassembledInstruction[] = [];
148125

149-
for (const asmInsn of result.asm_insns) {
150-
const line: number | undefined = asmInsn.line
151-
? parseInt(asmInsn.line, 10)
152-
: undefined;
153-
const location = {
154-
name: asmInsn.file,
155-
path: asmInsn.fullname,
156-
} as DebugProtocol.Source;
157-
for (const asmLine of asmInsn.line_asm_insn) {
158-
list.push({
159-
...getDisassembledInstruction(asmLine),
160-
location,
161-
line,
162-
});
126+
const result = await sendDataDisassemble(
127+
gdb,
128+
formatMemoryAddress(lower),
129+
formatMemoryAddress(upper)
130+
);
131+
for (const asmInsn of result.asm_insns) {
132+
const line: number | undefined = asmInsn.line
133+
? parseInt(asmInsn.line, 10)
134+
: undefined;
135+
const location = {
136+
name: asmInsn.file,
137+
path: asmInsn.fullname,
138+
} as DebugProtocol.Source;
139+
for (const asmLine of asmInsn.line_asm_insn) {
140+
list.push({
141+
...getDisassembledInstruction(asmLine),
142+
location,
143+
line,
144+
});
145+
}
163146
}
164-
}
147+
return list;
148+
};
165149

166-
if (length < 0) {
167-
// Remove the heading, if necessary
168-
if (absLength < list.length) {
169-
list.splice(0, list.length - absLength);
150+
const target = { lower: 0, higher: 0 };
151+
const recalculateTargetBounds = (length: number) => {
152+
if (isReverseFetch) {
153+
target.higher = target.lower;
154+
target.lower += length * meanSizeOfInstruction;
155+
} else {
156+
target.lower = target.higher;
157+
target.higher += length * meanSizeOfInstruction;
170158
}
171-
172-
// Add empty instructions, if necessary
173-
if (list.length < absLength) {
174-
const startAddress = list[0].address;
175-
const filling = getEmptyInstructions(
176-
startAddress,
177-
absLength - list.length,
178-
-2
159+
};
160+
const remainingLength = () =>
161+
Math.sign(length) * Math.max(absLength - list.length, 0);
162+
try {
163+
// Do we need an explicit guard to prevent infinite loop
164+
while (absLength > list.length) {
165+
recalculateTargetBounds(remainingLength());
166+
const result = await sendDataDisassembleWrapper(
167+
target.lower,
168+
target.higher
179169
);
180-
list.unshift(...filling);
181-
}
182-
} else {
183-
// Remove the tail, if necessary
184-
if (absLength < list.length) {
185-
list.splice(absLength, list.length - absLength);
170+
if (isReverseFetch) {
171+
list.unshift(...result);
172+
} else {
173+
list.push(...result);
174+
}
186175
}
176+
} catch (e) {
177+
// Fill with empty instructions in case of memory error.
178+
const lastMemoryAddress =
179+
list.length === 0
180+
? memoryReference
181+
: list[isReverseFetch ? 0 : list.length - 1].address;
182+
list.push(
183+
...getEmptyInstructions(lastMemoryAddress, remainingLength(), 2)
184+
);
185+
}
187186

188-
// Add empty instructions, if necessary
189-
if (list.length < absLength) {
190-
const startAddress = list[list.length - 1].address;
191-
const filling = getEmptyInstructions(
192-
startAddress,
193-
absLength - list.length,
194-
2
195-
);
196-
list.push(...filling);
187+
if (absLength < list.length) {
188+
if (length < 0) {
189+
// Remove the heading, if necessary
190+
list.splice(0, list.length - absLength);
191+
} else {
192+
// Remove the tail, if necessary
193+
list.splice(absLength, list.length - absLength);
197194
}
198195
}
199196

0 commit comments

Comments
 (0)