1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-02 06:35:28 +02:00

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.
This commit is contained in:
John Dallaway 2025-06-12 17:38:11 +01:00
parent 931051edfe
commit fec29d7713
6 changed files with 215 additions and 11 deletions

View file

@ -32,6 +32,7 @@
* Intel Corporation - Added Reverse Debugging BTrace support * Intel Corporation - Added Reverse Debugging BTrace support
* Samuel Hultgren (STMicroelectronics) - Bug 533771 * Samuel Hultgren (STMicroelectronics) - Bug 533771
* John Dallaway - Add CLI version command (#1186) * John Dallaway - Add CLI version command (#1186)
* John Dallaway - Add CLI address size command (#1191)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.dsf.mi.service.command; package org.eclipse.cdt.dsf.mi.service.command;
@ -54,6 +55,7 @@ import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordDMContext;
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext; import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext;
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext; import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext; import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIAddressSize;
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIAddressableSize; import org.eclipse.cdt.dsf.mi.service.command.commands.CLIAddressableSize;
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIAttach; import org.eclipse.cdt.dsf.mi.service.command.commands.CLIAttach;
import org.eclipse.cdt.dsf.mi.service.command.commands.CLICatch; import org.eclipse.cdt.dsf.mi.service.command.commands.CLICatch;
@ -206,6 +208,7 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarSetUpdateRange;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarShowAttributes; import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarShowAttributes;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarShowFormat; import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarShowFormat;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarUpdate; import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarUpdate;
import org.eclipse.cdt.dsf.mi.service.command.output.CLIAddressSizeInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.CLIAddressableSizeInfo; import org.eclipse.cdt.dsf.mi.service.command.output.CLIAddressableSizeInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.CLICatchInfo; import org.eclipse.cdt.dsf.mi.service.command.output.CLICatchInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoBreakInfo; import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoBreakInfo;
@ -269,6 +272,11 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MiSourceFilesInfo;
*/ */
public class CommandFactory { public class CommandFactory {
/** @since 7.2 */
public ICommand<CLIAddressSizeInfo> createCLIAddressSize(IMemoryDMContext ctx) {
return new CLIAddressSize(ctx);
}
/** /**
* @since 4.4 * @since 4.4
*/ */

View file

@ -0,0 +1,38 @@
/*******************************************************************************
* Copyright (c) 2025 John Dallaway and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* John Dallaway - Initial implementation (#1191)
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service.command.commands;
import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryDMContext;
import org.eclipse.cdt.dsf.mi.service.command.output.CLIAddressSizeInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
/**
* CLI command to report address size where the MI expression evaluator is not available
*
* @since 7.2
*/
public class CLIAddressSize extends MIInterpreterExecConsole<CLIAddressSizeInfo> {
private static final String COMMAND = "p/x sizeof(void*)"; //$NON-NLS-1$
public CLIAddressSize(IMemoryDMContext ctx) {
super(ctx, COMMAND);
}
@Override
public CLIAddressSizeInfo getResult(MIOutput miResult) {
return new CLIAddressSizeInfo(miResult);
}
}

View file

@ -0,0 +1,64 @@
/*******************************************************************************
* Copyright (c) 2025 John Dallaway and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* John Dallaway - Initial implementation (#1191)
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service.command.output;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.runtime.ILog;
/**
* Parses the result of the CLI command "p/x sizeof(void*)"
*
* @since 7.2
*/
public class CLIAddressSizeInfo extends MIInfo {
private static final Pattern HEX_LITERAL_PATTERN = Pattern.compile("0x[0-9a-fA-F]+"); //$NON-NLS-1$
private int fAddressSize = 0;
public CLIAddressSizeInfo(MIOutput record) {
super(record);
parse();
}
protected void parse() {
if (isDone()) {
MIOutput out = getMIOutput();
for (MIOOBRecord oob : out.getMIOOBRecords()) {
if (oob instanceof MIConsoleStreamOutput) {
String line = ((MIConsoleStreamOutput) oob).getString().trim();
fAddressSize = hexToValue(line);
}
}
}
}
public int getAddressSize() {
return fAddressSize;
}
private int hexToValue(String hexString) {
// Extract value from responses such as "(unsigned long) 0x0000000000000008\n"
Matcher matcher = HEX_LITERAL_PATTERN.matcher(hexString);
if (matcher.find()) {
return Integer.decode(matcher.group());
}
ILog.get().error("CLIAddressSizeInfo response not handled: " + hexString); //$NON-NLS-1$
return 0;
}
}

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2014 Ericsson AB and others. * Copyright (c) 2014, 2025 Ericsson AB and others.
* *
* This program and the accompanying materials * This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0 * are made available under the terms of the Eclipse Public License 2.0
@ -10,10 +10,16 @@
* *
* Contributors: * Contributors:
* Alvaro Sanchez-Leon (Ericsson AB) - [Memory] Support 16 bit addressable size (Bug 426730) * Alvaro Sanchez-Leon (Ericsson AB) - [Memory] Support 16 bit addressable size (Bug 426730)
* John Dallaway - Accommodate LLDB response format (#1191)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.dsf.mi.service.command.output; package org.eclipse.cdt.dsf.mi.service.command.output;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.runtime.ILog;
/** /**
* This class takes care of parsing and providing the result of the CLI command * This class takes care of parsing and providing the result of the CLI command
* <br>"p/x (char)-1" * <br>"p/x (char)-1"
@ -26,6 +32,8 @@ package org.eclipse.cdt.dsf.mi.service.command.output;
*/ */
public class CLIAddressableSizeInfo extends MIInfo { public class CLIAddressableSizeInfo extends MIInfo {
private static final Pattern HEX_DIGITS_PATTERN = Pattern.compile("0x([0-9a-fA-F]+)"); //$NON-NLS-1$
private int fAddressableSize = 1; private int fAddressableSize = 1;
public CLIAddressableSizeInfo(MIOutput record) { public CLIAddressableSizeInfo(MIOutput record) {
@ -50,14 +58,14 @@ public class CLIAddressableSizeInfo extends MIInfo {
} }
private int hexToOctetCount(String hexString) { private int hexToOctetCount(String hexString) {
//Receiving format is expected in hex form e.g. "$n = 0xffff" or "$n = 0xff" // Receiving format is expected in hex form e.g. "$n = 0xffff" or "$n = 0xff"
//which shall result in 2 and 1 octets respectively // which shall result in 2 and 1 octets respectively.
int starts = hexString.indexOf("x"); //$NON-NLS-1$ // Also accommodate "(char) 0xff -1 '\\xff'\n" returned by LLDB-MI.
assert (starts > 0); Matcher matcher = HEX_DIGITS_PATTERN.matcher(hexString);
String hexDigits = hexString.substring(starts + 1); if (matcher.find()) {
assert hexDigits.length() > 1; return matcher.group(1).length() / 2;
int octets = hexDigits.length() / 2; }
ILog.get().error("CLIAddressableSizeInfo response not handled: " + hexString); //$NON-NLS-1$
return octets; return 1;
} }
} }

View file

@ -0,0 +1,75 @@
/*******************************************************************************
* Copyright (c) 2025 John Dallaway and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* John Dallaway - Initial implementation (#1191)
*******************************************************************************/
package org.eclipse.cdt.llvm.dsf.lldb.core.internal.service;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.gdb.service.GDBMemory;
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
import org.eclipse.cdt.dsf.mi.service.command.output.CLIAddressSizeInfo;
import org.eclipse.cdt.dsf.service.DsfSession;
/**
* LLDB memory service implementation
*/
public class LLDBMemory extends GDBMemory {
private IGDBControl fCommandControl;
public LLDBMemory(DsfSession session) {
super(session);
}
@Override
public void initialize(final RequestMonitor requestMonitor) {
super.initialize(new ImmediateRequestMonitor(requestMonitor) {
@Override
protected void handleSuccess() {
doInitialize(requestMonitor);
}
});
}
private void doInitialize(final RequestMonitor requestMonitor) {
fCommandControl = getServicesTracker().getService(IGDBControl.class);
requestMonitor.done();
}
@Override
protected void readAddressSize(final IMemoryDMContext memContext, final DataRequestMonitor<Integer> drm) {
// use a CLI command - LLDB-MI does not support expression evaluation until a process is started
CommandFactory commandFactory = fCommandControl.getCommandFactory();
fCommandControl.queueCommand(commandFactory.createCLIAddressSize(memContext),
new DataRequestMonitor<CLIAddressSizeInfo>(ImmediateExecutor.getInstance(), drm) {
@Override
protected void handleSuccess() {
Integer ptrBytes = getData().getAddressSize();
drm.setData(ptrBytes * getAddressableSize(memContext));
drm.done();
}
});
}
@Override
protected void readEndianness(IMemoryDMContext memContext, final DataRequestMonitor<Boolean> drm) {
// assume little-endian - LLDB-MI does not support the "show endian" CLI command
drm.setData(Boolean.FALSE);
drm.done();
}
}

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2016 Ericsson. * Copyright (c) 2016, 2025 Ericsson and others.
* *
* This program and the accompanying materials * This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0 * are made available under the terms of the Eclipse Public License 2.0
@ -7,11 +7,16 @@
* https://www.eclipse.org/legal/epl-2.0/ * https://www.eclipse.org/legal/epl-2.0/
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Ericsson - Initial implementation
* John Dallaway - Use LLDB memory service (#1191)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.llvm.dsf.lldb.core.internal.service; package org.eclipse.cdt.llvm.dsf.lldb.core.internal.service;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints; import org.eclipse.cdt.dsf.debug.service.IBreakpoints;
import org.eclipse.cdt.dsf.debug.service.IMemory;
import org.eclipse.cdt.dsf.debug.service.IProcesses; import org.eclipse.cdt.dsf.debug.service.IProcesses;
import org.eclipse.cdt.dsf.debug.service.IRunControl; import org.eclipse.cdt.dsf.debug.service.IRunControl;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControl; import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
@ -56,4 +61,10 @@ public class LLDBServiceFactory extends GdbDebugServicesFactory {
protected IProcesses createProcessesService(DsfSession session) { protected IProcesses createProcessesService(DsfSession session) {
return new LLDBProcesses(session); return new LLDBProcesses(session);
} }
@Override
protected IMemory createMemoryService(DsfSession session) {
return new LLDBMemory(session);
}
} }