diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java index 3ca89a36e2f..5976b36f649 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java @@ -32,6 +32,7 @@ * Intel Corporation - Added Reverse Debugging BTrace support * Samuel Hultgren (STMicroelectronics) - Bug 533771 * John Dallaway - Add CLI version command (#1186) + * John Dallaway - Add CLI address size command (#1191) *******************************************************************************/ 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.mi.service.IMIContainerDMContext; 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.CLIAttach; 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.MIVarShowFormat; 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.CLICatchInfo; 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 { + /** @since 7.2 */ + public ICommand createCLIAddressSize(IMemoryDMContext ctx) { + return new CLIAddressSize(ctx); + } + /** * @since 4.4 */ diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/CLIAddressSize.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/CLIAddressSize.java new file mode 100644 index 00000000000..64fea6b7a17 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/CLIAddressSize.java @@ -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 { + + 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); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/CLIAddressSizeInfo.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/CLIAddressSizeInfo.java new file mode 100644 index 00000000000..1677d8c9cb1 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/CLIAddressSizeInfo.java @@ -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; + } + +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/CLIAddressableSizeInfo.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/CLIAddressableSizeInfo.java index 2c3e92fac71..e0e96b9435b 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/CLIAddressableSizeInfo.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/CLIAddressableSizeInfo.java @@ -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 * are made available under the terms of the Eclipse Public License 2.0 @@ -10,10 +10,16 @@ * * Contributors: * 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; +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 *
"p/x (char)-1" @@ -26,6 +32,8 @@ package org.eclipse.cdt.dsf.mi.service.command.output; */ 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; public CLIAddressableSizeInfo(MIOutput record) { @@ -50,14 +58,14 @@ public class CLIAddressableSizeInfo extends MIInfo { } private int hexToOctetCount(String hexString) { - //Receiving format is expected in hex form e.g. "$n = 0xffff" or "$n = 0xff" - //which shall result in 2 and 1 octets respectively - int starts = hexString.indexOf("x"); //$NON-NLS-1$ - assert (starts > 0); - String hexDigits = hexString.substring(starts + 1); - assert hexDigits.length() > 1; - int octets = hexDigits.length() / 2; - - return octets; + // Receiving format is expected in hex form e.g. "$n = 0xffff" or "$n = 0xff" + // which shall result in 2 and 1 octets respectively. + // Also accommodate "(char) 0xff -1 '\\xff'\n" returned by LLDB-MI. + Matcher matcher = HEX_DIGITS_PATTERN.matcher(hexString); + if (matcher.find()) { + return matcher.group(1).length() / 2; + } + ILog.get().error("CLIAddressableSizeInfo response not handled: " + hexString); //$NON-NLS-1$ + return 1; } } diff --git a/llvm/org.eclipse.cdt.llvm.dsf.lldb.core/src/org/eclipse/cdt/llvm/dsf/lldb/core/internal/service/LLDBMemory.java b/llvm/org.eclipse.cdt.llvm.dsf.lldb.core/src/org/eclipse/cdt/llvm/dsf/lldb/core/internal/service/LLDBMemory.java new file mode 100644 index 00000000000..e4fdd8e7bca --- /dev/null +++ b/llvm/org.eclipse.cdt.llvm.dsf.lldb.core/src/org/eclipse/cdt/llvm/dsf/lldb/core/internal/service/LLDBMemory.java @@ -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 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(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 drm) { + // assume little-endian - LLDB-MI does not support the "show endian" CLI command + drm.setData(Boolean.FALSE); + drm.done(); + } + +} diff --git a/llvm/org.eclipse.cdt.llvm.dsf.lldb.core/src/org/eclipse/cdt/llvm/dsf/lldb/core/internal/service/LLDBServiceFactory.java b/llvm/org.eclipse.cdt.llvm.dsf.lldb.core/src/org/eclipse/cdt/llvm/dsf/lldb/core/internal/service/LLDBServiceFactory.java index 374dd1f40c7..473064004ce 100644 --- a/llvm/org.eclipse.cdt.llvm.dsf.lldb.core/src/org/eclipse/cdt/llvm/dsf/lldb/core/internal/service/LLDBServiceFactory.java +++ b/llvm/org.eclipse.cdt.llvm.dsf.lldb.core/src/org/eclipse/cdt/llvm/dsf/lldb/core/internal/service/LLDBServiceFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016 Ericsson. + * Copyright (c) 2016, 2025 Ericsson and others. * * This program and the accompanying materials * 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/ * * 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; 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.IRunControl; import org.eclipse.cdt.dsf.debug.service.command.ICommandControl; @@ -56,4 +61,10 @@ public class LLDBServiceFactory extends GdbDebugServicesFactory { protected IProcesses createProcessesService(DsfSession session) { return new LLDBProcesses(session); } + + @Override + protected IMemory createMemoryService(DsfSession session) { + return new LLDBMemory(session); + } + }