Skip to content

Commit fec29d7

Browse files
committed
Implement LLDB memory service
We use CLI to read address size, replacing MI expression evaluation which is not supported by LLDB-MI outside the context of a running process. We accommodate the LLDB response format when reading addressable size. We assume little-endian since CLI 'show endian' is not supported.
1 parent 931051e commit fec29d7

File tree

6 files changed

+215
-11
lines changed

6 files changed

+215
-11
lines changed

dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
* Intel Corporation - Added Reverse Debugging BTrace support
3333
* Samuel Hultgren (STMicroelectronics) - Bug 533771
3434
* John Dallaway - Add CLI version command (#1186)
35+
* John Dallaway - Add CLI address size command (#1191)
3536
*******************************************************************************/
3637

3738
package org.eclipse.cdt.dsf.mi.service.command;
@@ -54,6 +55,7 @@
5455
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext;
5556
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
5657
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
58+
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIAddressSize;
5759
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIAddressableSize;
5860
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIAttach;
5961
import org.eclipse.cdt.dsf.mi.service.command.commands.CLICatch;
@@ -206,6 +208,7 @@
206208
import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarShowAttributes;
207209
import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarShowFormat;
208210
import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarUpdate;
211+
import org.eclipse.cdt.dsf.mi.service.command.output.CLIAddressSizeInfo;
209212
import org.eclipse.cdt.dsf.mi.service.command.output.CLIAddressableSizeInfo;
210213
import org.eclipse.cdt.dsf.mi.service.command.output.CLICatchInfo;
211214
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoBreakInfo;
@@ -269,6 +272,11 @@
269272
*/
270273
public class CommandFactory {
271274

275+
/** @since 7.2 */
276+
public ICommand<CLIAddressSizeInfo> createCLIAddressSize(IMemoryDMContext ctx) {
277+
return new CLIAddressSize(ctx);
278+
}
279+
272280
/**
273281
* @since 4.4
274282
*/
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 John Dallaway and others.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* John Dallaway - Initial implementation (#1191)
13+
*******************************************************************************/
14+
15+
package org.eclipse.cdt.dsf.mi.service.command.commands;
16+
17+
import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryDMContext;
18+
import org.eclipse.cdt.dsf.mi.service.command.output.CLIAddressSizeInfo;
19+
import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
20+
21+
/**
22+
* CLI command to report address size where the MI expression evaluator is not available
23+
*
24+
* @since 7.2
25+
*/
26+
public class CLIAddressSize extends MIInterpreterExecConsole<CLIAddressSizeInfo> {
27+
28+
private static final String COMMAND = "p/x sizeof(void*)"; //$NON-NLS-1$
29+
30+
public CLIAddressSize(IMemoryDMContext ctx) {
31+
super(ctx, COMMAND);
32+
}
33+
34+
@Override
35+
public CLIAddressSizeInfo getResult(MIOutput miResult) {
36+
return new CLIAddressSizeInfo(miResult);
37+
}
38+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 John Dallaway and others.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* John Dallaway - Initial implementation (#1191)
13+
*******************************************************************************/
14+
15+
package org.eclipse.cdt.dsf.mi.service.command.output;
16+
17+
import java.util.regex.Matcher;
18+
import java.util.regex.Pattern;
19+
20+
import org.eclipse.core.runtime.ILog;
21+
22+
/**
23+
* Parses the result of the CLI command "p/x sizeof(void*)"
24+
*
25+
* @since 7.2
26+
*/
27+
public class CLIAddressSizeInfo extends MIInfo {
28+
29+
private static final Pattern HEX_LITERAL_PATTERN = Pattern.compile("0x[0-9a-fA-F]+"); //$NON-NLS-1$
30+
31+
private int fAddressSize = 0;
32+
33+
public CLIAddressSizeInfo(MIOutput record) {
34+
super(record);
35+
parse();
36+
}
37+
38+
protected void parse() {
39+
if (isDone()) {
40+
MIOutput out = getMIOutput();
41+
for (MIOOBRecord oob : out.getMIOOBRecords()) {
42+
if (oob instanceof MIConsoleStreamOutput) {
43+
String line = ((MIConsoleStreamOutput) oob).getString().trim();
44+
fAddressSize = hexToValue(line);
45+
}
46+
}
47+
}
48+
}
49+
50+
public int getAddressSize() {
51+
return fAddressSize;
52+
}
53+
54+
private int hexToValue(String hexString) {
55+
// Extract value from responses such as "(unsigned long) 0x0000000000000008\n"
56+
Matcher matcher = HEX_LITERAL_PATTERN.matcher(hexString);
57+
if (matcher.find()) {
58+
return Integer.decode(matcher.group());
59+
}
60+
ILog.get().error("CLIAddressSizeInfo response not handled: " + hexString); //$NON-NLS-1$
61+
return 0;
62+
}
63+
64+
}

dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/CLIAddressableSizeInfo.java

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2014 Ericsson AB and others.
2+
* Copyright (c) 2014, 2025 Ericsson AB and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -10,10 +10,16 @@
1010
*
1111
* Contributors:
1212
* Alvaro Sanchez-Leon (Ericsson AB) - [Memory] Support 16 bit addressable size (Bug 426730)
13+
* John Dallaway - Accommodate LLDB response format (#1191)
1314
*******************************************************************************/
1415

1516
package org.eclipse.cdt.dsf.mi.service.command.output;
1617

18+
import java.util.regex.Matcher;
19+
import java.util.regex.Pattern;
20+
21+
import org.eclipse.core.runtime.ILog;
22+
1723
/**
1824
* This class takes care of parsing and providing the result of the CLI command
1925
* <br>"p/x (char)-1"
@@ -26,6 +32,8 @@
2632
*/
2733
public class CLIAddressableSizeInfo extends MIInfo {
2834

35+
private static final Pattern HEX_DIGITS_PATTERN = Pattern.compile("0x([0-9a-fA-F]+)"); //$NON-NLS-1$
36+
2937
private int fAddressableSize = 1;
3038

3139
public CLIAddressableSizeInfo(MIOutput record) {
@@ -50,14 +58,14 @@ public int getAddressableSize() {
5058
}
5159

5260
private int hexToOctetCount(String hexString) {
53-
//Receiving format is expected in hex form e.g. "$n = 0xffff" or "$n = 0xff"
54-
//which shall result in 2 and 1 octets respectively
55-
int starts = hexString.indexOf("x"); //$NON-NLS-1$
56-
assert (starts > 0);
57-
String hexDigits = hexString.substring(starts + 1);
58-
assert hexDigits.length() > 1;
59-
int octets = hexDigits.length() / 2;
60-
61-
return octets;
61+
// Receiving format is expected in hex form e.g. "$n = 0xffff" or "$n = 0xff"
62+
// which shall result in 2 and 1 octets respectively.
63+
// Also accommodate "(char) 0xff -1 '\\xff'\n" returned by LLDB-MI.
64+
Matcher matcher = HEX_DIGITS_PATTERN.matcher(hexString);
65+
if (matcher.find()) {
66+
return matcher.group(1).length() / 2;
67+
}
68+
ILog.get().error("CLIAddressableSizeInfo response not handled: " + hexString); //$NON-NLS-1$
69+
return 1;
6270
}
6371
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 John Dallaway and others.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* John Dallaway - Initial implementation (#1191)
13+
*******************************************************************************/
14+
15+
package org.eclipse.cdt.llvm.dsf.lldb.core.internal.service;
16+
17+
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
18+
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
19+
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
20+
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
21+
import org.eclipse.cdt.dsf.gdb.service.GDBMemory;
22+
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
23+
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
24+
import org.eclipse.cdt.dsf.mi.service.command.output.CLIAddressSizeInfo;
25+
import org.eclipse.cdt.dsf.service.DsfSession;
26+
27+
/**
28+
* LLDB memory service implementation
29+
*/
30+
public class LLDBMemory extends GDBMemory {
31+
32+
private IGDBControl fCommandControl;
33+
34+
public LLDBMemory(DsfSession session) {
35+
super(session);
36+
}
37+
38+
@Override
39+
public void initialize(final RequestMonitor requestMonitor) {
40+
super.initialize(new ImmediateRequestMonitor(requestMonitor) {
41+
@Override
42+
protected void handleSuccess() {
43+
doInitialize(requestMonitor);
44+
}
45+
});
46+
}
47+
48+
private void doInitialize(final RequestMonitor requestMonitor) {
49+
fCommandControl = getServicesTracker().getService(IGDBControl.class);
50+
requestMonitor.done();
51+
}
52+
53+
@Override
54+
protected void readAddressSize(final IMemoryDMContext memContext, final DataRequestMonitor<Integer> drm) {
55+
// use a CLI command - LLDB-MI does not support expression evaluation until a process is started
56+
CommandFactory commandFactory = fCommandControl.getCommandFactory();
57+
fCommandControl.queueCommand(commandFactory.createCLIAddressSize(memContext),
58+
new DataRequestMonitor<CLIAddressSizeInfo>(ImmediateExecutor.getInstance(), drm) {
59+
@Override
60+
protected void handleSuccess() {
61+
Integer ptrBytes = getData().getAddressSize();
62+
drm.setData(ptrBytes * getAddressableSize(memContext));
63+
drm.done();
64+
}
65+
});
66+
}
67+
68+
@Override
69+
protected void readEndianness(IMemoryDMContext memContext, final DataRequestMonitor<Boolean> drm) {
70+
// assume little-endian - LLDB-MI does not support the "show endian" CLI command
71+
drm.setData(Boolean.FALSE);
72+
drm.done();
73+
}
74+
75+
}

llvm/org.eclipse.cdt.llvm.dsf.lldb.core/src/org/eclipse/cdt/llvm/dsf/lldb/core/internal/service/LLDBServiceFactory.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
/*******************************************************************************
2-
* Copyright (c) 2016 Ericsson.
2+
* Copyright (c) 2016, 2025 Ericsson and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
66
* which accompanies this distribution, and is available at
77
* https://www.eclipse.org/legal/epl-2.0/
88
*
99
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* Ericsson - Initial implementation
13+
* John Dallaway - Use LLDB memory service (#1191)
1014
*******************************************************************************/
1115

1216
package org.eclipse.cdt.llvm.dsf.lldb.core.internal.service;
1317

1418
import org.eclipse.cdt.dsf.debug.service.IBreakpoints;
19+
import org.eclipse.cdt.dsf.debug.service.IMemory;
1520
import org.eclipse.cdt.dsf.debug.service.IProcesses;
1621
import org.eclipse.cdt.dsf.debug.service.IRunControl;
1722
import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
@@ -56,4 +61,10 @@ protected IRunControl createRunControlService(DsfSession session) {
5661
protected IProcesses createProcessesService(DsfSession session) {
5762
return new LLDBProcesses(session);
5863
}
64+
65+
@Override
66+
protected IMemory createMemoryService(DsfSession session) {
67+
return new LLDBMemory(session);
68+
}
69+
5970
}

0 commit comments

Comments
 (0)