From e206d3b10fede631b6096f49e01817cd1c8739a0 Mon Sep 17 00:00:00 2001 From: Alain Magloire Date: Wed, 2 Oct 2002 04:51:01 +0000 Subject: [PATCH] Complete rewrite to not use the gdb/mi variable object but rather the -data-list-register-xxx calls. --- .../cdt/debug/mi/core/cdi/Register.java | 285 +++++++++++++++++- .../debug/mi/core/cdi/RegisterManager.java | 126 ++++++++ 2 files changed, 407 insertions(+), 4 deletions(-) create mode 100644 debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/RegisterManager.java diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/Register.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/Register.java index 9c5031f07fe..c8bb283bead 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/Register.java +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/Register.java @@ -5,14 +5,291 @@ */ package org.eclipse.cdt.debug.mi.core.cdi; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import org.eclipse.cdt.debug.core.cdi.CDIException; +import org.eclipse.cdt.debug.core.cdi.ICDIRegisterObject; import org.eclipse.cdt.debug.core.cdi.model.ICDIRegister; -import org.eclipse.cdt.debug.mi.core.output.MIVar; +import org.eclipse.cdt.debug.core.cdi.model.ICDIValue; +import org.eclipse.cdt.debug.core.cdi.model.ICDIVariable; +import org.eclipse.cdt.debug.mi.core.MIException; +import org.eclipse.cdt.debug.mi.core.MIFormat; +import org.eclipse.cdt.debug.mi.core.MISession; +import org.eclipse.cdt.debug.mi.core.command.CommandFactory; +import org.eclipse.cdt.debug.mi.core.command.MIDataListRegisterValues; +import org.eclipse.cdt.debug.mi.core.output.MIDataListRegisterValuesInfo; +import org.eclipse.cdt.debug.mi.core.output.MIRegisterValue; /** */ -public class Register extends Variable implements ICDIRegister { +public class Register extends CObject implements ICDIRegister, ICDIValue { - public Register(StackFrame frame, String name, MIVar var) { - super(frame, name, var); + RegisterObject regObject; + int format = MIFormat.HEXADECIMAL; + Register parent; + String lastname; + + /** + * A container class to hold the values of the registers and sub values + * for example on x86, xmm0 register is consider to be a struct + * gdb/mi -data-list-register-values returns the value like this + * value="{f = {0x0, 0x0, 0x0, 0x0}}" + * we'll parse() it and change it to: + * Argument[0] = { "xmm0", "{f = {0x0, 0x0, 0x0, 0x0}}" + * Argument[1] = { "xmm0.f", "{0x0, 0x0, 0x0, 0x0}"} + * Argument[2] = { "xmm0.f.0", "0x0"} + * Argument[3] = { "xmm0.f.1", "0x0"} + * Argument[4] = { "xmm0.f.2", "0x0"} + * Argument[5] = { "xmm0.f.3", "0x0"} + * see @parse() + */ + class Argument { + String name; + String val; + Argument(String n, String v) { + name = n; + val = v; + } + String getKey() { + return name; + } + String getValue() { + return val; + } + } + + public Register(CTarget target, ICDIRegisterObject r) { + super(target); + parent = null; + lastname = r.getName(); + regObject = (RegisterObject)r; + } + + public Register(Register p, String n) { + super(p.getCTarget()); + parent = p; + lastname = n; + } + + /** + * return the MI regno. + */ + public int getId() { + return regObject.getId(); + } + + /** + * Returns a Unique name separated by '.' to describe the path + * for example xmm0.f.0 + */ + public String getUniqName() { + String n = ""; + if (parent != null) { + n = parent.getUniqName() + "." + getLastName(); + } else { + n = getLastName(); + } + return n; + } + + /** + * Returns the name of the register, for example xmm0. + */ + public String getBaseName() { + String base = ""; + if (parent != null) { + base = parent.getBaseName(); + } else { + base = getLastName(); + } + return base; + } + + /** + * Returns the current name for xmm0.f the last name is "f". + */ + public String getLastName() { + return lastname; + } + + /** + * @see org.eclipse.cdt.debug.core.cdi.model.ICDIVariable#getName() + */ + public String getName() throws CDIException { + return getLastName(); + } + + /** + * @see org.eclipse.cdt.debug.core.cdi.model.ICDIVariable#getTypeName() + */ + public String getTypeName() throws CDIException { + String v = getValueString(); + if (v.startsWith("{")) { + // Use ptype? + return "struct "; + } + return "int"; + } + + /** + * @see org.eclipse.cdt.debug.core.cdi.model.ICDIVariable#getValue() + */ + public ICDIValue getValue() throws CDIException { + return this; + } + + /** + * @see org.eclipse.cdt.debug.core.cdi.model.ICDIValue#getValueString() + */ + public String getValueString() throws CDIException { + if (parent == null) { + MISession mi = getCTarget().getCSession().getMISession(); + CommandFactory factory = mi.getCommandFactory(); + int[] regno = new int[]{((RegisterObject)regObject).getId()}; + MIDataListRegisterValues registers = + factory.createMIDataListRegisterValues(format, regno); + try { + mi.postCommand(registers); + MIDataListRegisterValuesInfo info = + registers.getMIDataListRegisterValuesInfo(); + if (info == null) { + throw new CDIException("No answer"); + } + MIRegisterValue[] regValues = info.getMIRegisterValues(); + // We only ask for one. But do the right thing + for (int i = 0; i < regValues.length; i++) { + if (regValues[i].getNumber() == regno[i]) { + return regValues[i].getValue(); + } + } + } catch (MIException e) { + throw new CDIException(e.getMessage()); + } + } else { + String u = getUniqName(); + String v = parent.getValueString(); + Argument[] args = parse(parent.getUniqName(), v); + for (int i = 0; i < args.length; i++) { + if (u.equals(args[i].getKey())) { + return args[i].getValue(); + } + } + } + return ""; + } + + /** + * @see org.eclipse.cdt.debug.core.cdi.model.ICDIVariable#isEditable() + */ + public boolean isEditable() throws CDIException { + return false; + } + + /** + * @see org.eclipse.cdt.debug.core.cdi.model.ICDIVariable#setValue(ICDIValue) + */ + public void setValue(ICDIValue val) throws CDIException { + setValue(val.getValueString()); + } + + /** + * @see org.eclipse.cdt.debug.core.cdi.model.ICDIVariable#setValue(String) + */ + public void setValue(String expression) throws CDIException { + throw new CDIException("Register setting is not supported"); + } + + /** + * @see org.eclipse.cdt.debug.core.cdi.model.ICDIVariable#setFormat() + */ + public void setFormat(int format) throws CDIException { + format = Format.toMIFormat(format); + } + + /** + * @see org.eclipse.cdt.debug.core.cdi.model.ICDIValue#getChildrenNumber() + */ + public int getChildrenNumber() throws CDIException { + return getVariables().length; + } + + /** + * @see org.eclipse.cdt.debug.core.cdi.model.ICDIValue#getVariables() + */ + public ICDIVariable[] getVariables() throws CDIException { + List aList = new ArrayList(1); + String v = getValueString(); + Argument[] args = parse(getUniqName(), v); + /* The idea here s to get the first level + * + * Argument[0] = { "xmm0", "{f = {0x0, 0x0, 0x0, 0x0}}" + * Argument[1] = { "xmm0.f", "{0x0, 0x0, 0x0, 0x0}"} + * Argument[2] = { "xmm0.f.0", "0x0"} + * Argument[3] = { "xmm0.f.1", "0x0"} + * Argument[4] = { "xmm0.f.2", "0x0"} + * Argument[5] = { "xmm0.f.3", "0x0"} + * + * For example the children or xmm0.f are xmm0.f.{0,1,2,3,} + * + */ + for (int i = 0; i < args.length; i++) { + String n = args[i].getKey(); + String u = getUniqName(); + if (n.startsWith(u) && n.length() > u.length()) { + String p = n.substring(u.length()); + StringTokenizer st = new StringTokenizer(p, "."); + if (st.countTokens() == 1) { + aList.add(new Register(this, (String)st.nextElement())); + } + } + } + return (ICDIVariable[])aList.toArray(new ICDIVariable[0]); + } + + /** + * @see org.eclipse.cdt.debug.core.cdi.model.ICDIValue#hasChildren() + */ + public boolean hasChildren() throws CDIException { + return getChildrenNumber() > 0; + } + + /** + * We are parsing this: + * "{f = {0x0, 0x0, 0x0, 0x0}}" + * into: + * Argument[0] = { "xmm0", "{f = {0x0, 0x0, 0x0, 0x0}}" + * Argument[1] = { "xmm0.f", "{0x0, 0x0, 0x0, 0x0}"} + * Argument[2] = { "xmm0.f.0", "0x0"} + * Argument[3] = { "xmm0.f.1", "0x0"} + * Argument[4] = { "xmm0.f.2", "0x0"} + * Argument[5] = { "xmm0.f.3", "0x0"} + */ + Argument[] parse(String base, String v) throws CDIException { + List aList = new ArrayList(1); + StringBuffer sb = new StringBuffer(base); + aList.add(new Argument(sb.toString(), v.trim())); + while (v.startsWith("{")) { + int idx; + v = v.substring(1); + if (v.endsWith("}")) { + idx = v.lastIndexOf('}'); + v = v.substring(0, idx); + } + idx = v.indexOf('='); + if (idx != -1) { + String n = v.substring(0, idx).trim(); + sb.append('.').append(n); + v = v.substring(idx + 1).trim(); + aList.add(new Argument(sb.toString(), v)); + } else { + StringTokenizer st = new StringTokenizer(v, ","); + for (int i = 0; st.hasMoreElements(); i++) { + aList.add(new Argument(sb.toString() + "." + Integer.toString(i), ((String)st.nextElement()).trim())); + } + } + } + return (Argument[])aList.toArray(new Argument[0]); } } diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/RegisterManager.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/RegisterManager.java new file mode 100644 index 00000000000..ebbb4bd69ec --- /dev/null +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/cdi/RegisterManager.java @@ -0,0 +1,126 @@ +/* + *(c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + * + */ +package org.eclipse.cdt.debug.mi.core.cdi; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.debug.core.cdi.CDIException; +import org.eclipse.cdt.debug.core.cdi.ICDIRegisterObject; +import org.eclipse.cdt.debug.mi.core.MIException; +import org.eclipse.cdt.debug.mi.core.MISession; +import org.eclipse.cdt.debug.mi.core.command.CommandFactory; +import org.eclipse.cdt.debug.mi.core.command.MIDataListChangedRegisters; +import org.eclipse.cdt.debug.mi.core.command.MIDataListRegisterNames; +import org.eclipse.cdt.debug.mi.core.event.MIEvent; +import org.eclipse.cdt.debug.mi.core.event.MIRegisterChangedEvent; +import org.eclipse.cdt.debug.mi.core.output.MIDataListChangedRegistersInfo; +import org.eclipse.cdt.debug.mi.core.output.MIDataListRegisterNamesInfo; + +/** + */ +public class RegisterManager extends SessionObject { + + List regList; + + public RegisterManager(CSession session) { + super(session); + regList = new ArrayList(); + } + + /** + * @see org.eclipse.cdt.debug.core.cdi.model.ICDITarget#getRegisterObjects() + */ + public ICDIRegisterObject[] getRegisterObjects() throws CDIException { + MISession mi = getCSession().getMISession(); + CommandFactory factory = mi.getCommandFactory(); + MIDataListRegisterNames registers = factory.createMIDataListRegisterNames(); + try { + mi.postCommand(registers); + MIDataListRegisterNamesInfo info = + registers.getMIDataListRegisterNamesInfo(); + if (info == null) { + throw new CDIException("No answer"); + } + String[] names = info.getRegisterNames(); + RegisterObject[] regs = new RegisterObject[names.length]; + for (int i = 0; i < names.length; i++) { + regs[i] = new RegisterObject(names[i], i); + } + return regs; + } catch (MIException e) { + throw new CDIException(e.getMessage()); + } + } + + Register[] getRegisters() { + return (Register[])regList.toArray(new Register[0]); + } + + Register getRegister(int regno) throws CDIException { + Register[] regs = getRegisters(); + for (int i = 0; i < regs.length; i++) { + if (regs[i].getId() == regno) { + return regs[i]; + } + } + return null; + } + + Register getRegister(ICDIRegisterObject regObject) throws CDIException { + Register[] regs = getRegisters(); + for (int i = 0; i < regs.length; i++) { + if (regObject.getName().equals(regs[i].getName())) { + return regs[i]; + } + } + return null; + } + + Register createRegister(ICDIRegisterObject regObject) throws CDIException { + Register reg = getRegister(regObject); + if (reg == null) { + reg = new Register(getCSession().getCTarget(), regObject); + regList.add(reg); + } + return reg; + } + + Register[] createRegisters(ICDIRegisterObject[] regObjects) throws CDIException { + Register[] regs = new Register[regObjects.length]; + for (int i = 0; i < regs.length; i++) { + regs[i] = createRegister(regObjects[i]); + } + return regs; + } + + void update() throws CDIException { + MISession mi = getCSession().getMISession(); + CommandFactory factory = mi.getCommandFactory(); + MIDataListChangedRegisters changed = factory.createMIDataListChangedRegisters(); + try { + mi.postCommand(changed); + MIDataListChangedRegistersInfo info = + changed.getMIDataListChangedRegistersInfo(); + if (info == null) { + throw new CDIException("No answer"); + } + int[] regnos = info.getRegisterNumbers(); + List eventList = new ArrayList(regnos.length); + for (int i = 0 ; i < regnos.length; i++) { + Register reg = getRegister(regnos[i]); + if (reg != null) { + eventList.add(new MIRegisterChangedEvent(reg.getName(), regnos[i])); + } + } + MIEvent[] events = (MIEvent[])eventList.toArray(new MIEvent[0]); + mi.fireEvents(events); + } catch (MIException e) { + throw new CDIException(e.getMessage()); + } + } + +}