/******************************************************************************* * Copyright (c) 2000, 2008 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * QNX Software Systems - Initial API and implementation * Alena Laskavaia (QNX) - Bug 221224 *******************************************************************************/ package org.eclipse.cdt.debug.mi.core.cdi; import java.math.BigInteger; import java.util.StringTokenizer; import org.eclipse.cdt.debug.core.cdi.CDIException; import org.eclipse.cdt.debug.core.cdi.model.ICDIInstruction; import org.eclipse.cdt.debug.core.cdi.model.ICDIMixedInstruction; import org.eclipse.cdt.debug.mi.core.GDBTypeParser; import org.eclipse.cdt.debug.mi.core.MIException; import org.eclipse.cdt.debug.mi.core.MISession; import org.eclipse.cdt.debug.mi.core.RxThread; import org.eclipse.cdt.debug.mi.core.GDBTypeParser.GDBDerivedType; import org.eclipse.cdt.debug.mi.core.GDBTypeParser.GDBType; import org.eclipse.cdt.debug.mi.core.cdi.model.Instruction; import org.eclipse.cdt.debug.mi.core.cdi.model.MixedInstruction; import org.eclipse.cdt.debug.mi.core.cdi.model.StackFrame; import org.eclipse.cdt.debug.mi.core.cdi.model.Target; import org.eclipse.cdt.debug.mi.core.cdi.model.Thread; import org.eclipse.cdt.debug.mi.core.cdi.model.type.ArrayType; import org.eclipse.cdt.debug.mi.core.cdi.model.type.BoolType; import org.eclipse.cdt.debug.mi.core.cdi.model.type.CharType; import org.eclipse.cdt.debug.mi.core.cdi.model.type.DerivedType; import org.eclipse.cdt.debug.mi.core.cdi.model.type.DoubleType; import org.eclipse.cdt.debug.mi.core.cdi.model.type.EnumType; import org.eclipse.cdt.debug.mi.core.cdi.model.type.FloatType; import org.eclipse.cdt.debug.mi.core.cdi.model.type.FunctionType; import org.eclipse.cdt.debug.mi.core.cdi.model.type.IntType; import org.eclipse.cdt.debug.mi.core.cdi.model.type.LongLongType; import org.eclipse.cdt.debug.mi.core.cdi.model.type.LongType; import org.eclipse.cdt.debug.mi.core.cdi.model.type.PointerType; import org.eclipse.cdt.debug.mi.core.cdi.model.type.ReferenceType; import org.eclipse.cdt.debug.mi.core.cdi.model.type.ShortType; import org.eclipse.cdt.debug.mi.core.cdi.model.type.StructType; import org.eclipse.cdt.debug.mi.core.cdi.model.type.Type; import org.eclipse.cdt.debug.mi.core.cdi.model.type.VoidType; import org.eclipse.cdt.debug.mi.core.cdi.model.type.WCharType; import org.eclipse.cdt.debug.mi.core.command.CommandFactory; import org.eclipse.cdt.debug.mi.core.command.MIDataDisassemble; import org.eclipse.cdt.debug.mi.core.command.MIEnvironmentDirectory; import org.eclipse.cdt.debug.mi.core.command.MIGDBShowDirectories; import org.eclipse.cdt.debug.mi.core.command.CLIPType; import org.eclipse.cdt.debug.mi.core.command.CLIWhatis; import org.eclipse.cdt.debug.mi.core.output.MIAsm; import org.eclipse.cdt.debug.mi.core.output.MIDataDisassembleInfo; import org.eclipse.cdt.debug.mi.core.output.MIGDBShowDirectoriesInfo; import org.eclipse.cdt.debug.mi.core.output.CLIPTypeInfo; import org.eclipse.cdt.debug.mi.core.output.MISrcAsm; import org.eclipse.cdt.debug.mi.core.output.CLIWhatisInfo; /** */ public class SourceManager extends Manager { GDBTypeParser gdbTypeParser; public SourceManager(Session session) { super(session, false); gdbTypeParser = new GDBTypeParser(); } public void setSourcePaths(Target target, String[] dirs) throws CDIException { MISession mi = target.getMISession(); CommandFactory factory = mi.getCommandFactory(); MIEnvironmentDirectory dir = factory.createMIEnvironmentDirectory(true, dirs); try { mi.postCommand(dir); dir.getMIInfo(); } catch (MIException e) { throw new MI2CDIException(e); } } public String[] getSourcePaths(Target target) throws CDIException { MISession mi = target.getMISession(); CommandFactory factory = mi.getCommandFactory(); MIGDBShowDirectories dir = factory.createMIGDBShowDirectories(); try { mi.postCommand(dir); MIGDBShowDirectoriesInfo info = dir.getMIGDBShowDirectoriesInfo(); return info.getDirectories(); } catch (MIException e) { throw new MI2CDIException(e); } } public ICDIInstruction[] getInstructions(Target target, String filename, int linenum) throws CDIException { return getInstructions(target, filename, linenum, -1); } public ICDIInstruction[] getInstructions(Target target, String filename, int linenum, int lines) throws CDIException { MISession mi = target.getMISession(); CommandFactory factory = mi.getCommandFactory(); MIDataDisassemble dis = factory.createMIDataDisassemble(filename, linenum, lines, false); try { mi.postCommand(dis); MIDataDisassembleInfo info = dis.getMIDataDisassembleInfo(); MIAsm[] asm = info.getMIAsms(); Instruction[] instructions = new Instruction[asm.length]; for (int i = 0; i < instructions.length; i++) { instructions[i] = new Instruction(target, asm[i]); } return instructions; } catch (MIException e) { throw new MI2CDIException(e); } } public ICDIInstruction[] getInstructions(Target target, BigInteger start, BigInteger end) throws CDIException { MISession mi = target.getMISession(); CommandFactory factory = mi.getCommandFactory(); String hex = "0x"; //$NON-NLS-1$ String sa = hex + start.toString(16); String ea = hex + end.toString(16); MIDataDisassemble dis = factory.createMIDataDisassemble(sa, ea, false); try { mi.postCommand(dis); MIDataDisassembleInfo info = dis.getMIDataDisassembleInfo(); MIAsm[] asm = info.getMIAsms(); Instruction[] instructions = new Instruction[asm.length]; for (int i = 0; i < instructions.length; i++) { instructions[i] = new Instruction(target, asm[i]); } return instructions; } catch (MIException e) { throw new MI2CDIException(e); } } public ICDIMixedInstruction[] getMixedInstructions(Target target, String filename, int linenum) throws CDIException { return getMixedInstructions(target, filename, linenum, -1); } public ICDIMixedInstruction[] getMixedInstructions(Target target, String filename, int linenum, int lines) throws CDIException { MISession mi = target.getMISession(); CommandFactory factory = mi.getCommandFactory(); MIDataDisassemble dis = factory.createMIDataDisassemble(filename, linenum, lines, true); try { mi.postCommand(dis); MIDataDisassembleInfo info = dis.getMIDataDisassembleInfo(); MISrcAsm[] srcAsm = info.getMISrcAsms(); ICDIMixedInstruction[] mixed = new ICDIMixedInstruction[srcAsm.length]; for (int i = 0; i < mixed.length; i++) { mixed[i] = new MixedInstruction(target, srcAsm[i]); } return mixed; } catch (MIException e) { throw new MI2CDIException(e); } } public ICDIMixedInstruction[] getMixedInstructions(Target target, BigInteger start, BigInteger end) throws CDIException { MISession mi = target.getMISession(); CommandFactory factory = mi.getCommandFactory(); String hex = "0x"; //$NON-NLS-1$ String sa = hex + start.toString(16); String ea = hex + end.toString(16); MIDataDisassemble dis = factory.createMIDataDisassemble(sa, ea, true); try { mi.postCommand(dis); MIDataDisassembleInfo info = dis.getMIDataDisassembleInfo(); MISrcAsm[] srcAsm = info.getMISrcAsms(); ICDIMixedInstruction[] mixed = new ICDIMixedInstruction[srcAsm.length]; for (int i = 0; i < mixed.length; i++) { mixed[i] = new MixedInstruction(target, srcAsm[i]); } return mixed; } catch (MIException e) { throw new MI2CDIException(e); } } public void update(Target target) throws CDIException { } public Type getType(Target target, String name) throws CDIException { if (name == null) { name = new String(); } String typename = name.trim(); // Parse the string. GDBType gdbType = gdbTypeParser.parse(typename); Type headType = null; Type type = null; // Convert the GDBType to an ICDIType. // So we go through the gdbType tree and reconstruct an ICDIType tree for (Type aType = null; gdbType != null; type = aType) { if (gdbType instanceof GDBDerivedType) { switch(gdbType.getType()) { case GDBType.ARRAY: int d = ((GDBDerivedType)gdbType).getDimension(); aType = new ArrayType(target, gdbType.toString(), d); break; case GDBType.FUNCTION: aType = new FunctionType(target, gdbType.toString()); break; case GDBType.POINTER: aType = new PointerType(target, gdbType.toString()); break; case GDBType.REFERENCE: aType = new ReferenceType(target, gdbType.toString()); break; } gdbType = ((GDBDerivedType)gdbType).getChild(); } else { aType = toCDIType(target, gdbType.toString()); gdbType = null; } if (type instanceof DerivedType) { ((DerivedType)type).setComponentType(aType); } // Save the head to returning it. if (headType == null) { headType = aType; } } if (headType != null) { return headType; } throw new CDIException(CdiResources.getString("cdi.SourceManager.Unknown_type")); //$NON-NLS-1$ } Type toCDIType(Target target, String name) throws CDIException { // Check the derived types and agregate types if (name == null) { name = new String(); } String typename = name.trim(); // Check the primitives. if (typename.equals("char")) { //$NON-NLS-1$ return new CharType(target, typename); } else if (typename.equals("wchar_t")) { //$NON-NLS-1$ return new WCharType(target, typename); } else if (typename.equals("short")) { //$NON-NLS-1$ return new ShortType(target, typename); } else if (typename.equals("int")) { //$NON-NLS-1$ return new IntType(target, typename); } else if (typename.equals("long")) { //$NON-NLS-1$ return new LongType(target, typename); } else if (typename.equals("unsigned")) { //$NON-NLS-1$ return new IntType(target, typename, true); } else if (typename.equals("signed")) { //$NON-NLS-1$ return new IntType(target, typename); } else if (typename.equals("bool")) { //$NON-NLS-1$ return new BoolType(target, typename); } else if (typename.equals("_Bool")) { //$NON-NLS-1$ return new BoolType(target, typename); } else if (typename.equals("float")) { //$NON-NLS-1$ return new FloatType(target, typename); } else if (typename.equals("double")) { //$NON-NLS-1$ return new DoubleType(target, typename); } else if (typename.equals("void")) { //$NON-NLS-1$ return new VoidType(target, typename); } else if (typename.equals("enum")) { //$NON-NLS-1$ return new EnumType(target, typename); } else if (typename.equals("union")) { //$NON-NLS-1$ return new StructType(target, typename); } else if (typename.equals("struct")) { //$NON-NLS-1$ return new StructType(target, typename); } else if (typename.equals("class")) { //$NON-NLS-1$ return new StructType(target, typename); } // GDB has some special types for int if (typename.equals("int8_t")) { //$NON-NLS-1$ return new CharType(target, typename); } else if (typename.equals("int16_t")) { //$NON-NLS-1$ return new ShortType(target, typename); } else if (typename.equals("int32_t")) { //$NON-NLS-1$ return new LongType(target, typename); } else if (typename.equals("int64_t")) { //$NON-NLS-1$ return new LongLongType(target, typename); } else if (typename.equals("int128_t")) { //$NON-NLS-1$ return new IntType(target, typename); // ???? } if (typename.equals("int8_t")) { //$NON-NLS-1$ return new CharType(target, typename); } else if (typename.equals("uint8_t")) { //$NON-NLS-1$ return new CharType(target, typename, true); } else if (typename.equals("int16_t")) { //$NON-NLS-1$ return new ShortType(target, typename); } else if (typename.equals("uint16_t")) { //$NON-NLS-1$ return new ShortType(target, typename, true); } else if (typename.equals("int32_t")) { //$NON-NLS-1$ return new LongType(target, typename); } else if (typename.equals("uint32_t")) { //$NON-NLS-1$ return new LongType(target, typename, true); } else if (typename.equals("int64_t")) { //$NON-NLS-1$ return new LongLongType(target, typename); } else if (typename.equals("uint64_t")) { //$NON-NLS-1$ return new LongLongType(target, typename, true); } else if (typename.equals("int128_t")) { //$NON-NLS-1$ return new IntType(target, typename); // ???? } else if (typename.equals("uint128_t")) { //$NON-NLS-1$ return new IntType(target, typename, true); // ???? } StringTokenizer st = new StringTokenizer(typename); int count = st.countTokens(); if (count == 2) { String first = st.nextToken(); String second = st.nextToken(); // ISOC allows permutations: // "signed int" and "int signed" are equivalent boolean isUnsigned = (first.equals("unsigned") || second.equals("unsigned")); //$NON-NLS-1$ //$NON-NLS-2$ boolean isSigned = (first.equals("signed") || second.equals("signed")); //$NON-NLS-1$ //$NON-NLS-2$ boolean isChar = (first.equals("char") || second.equals("char")); //$NON-NLS-1$ //$NON-NLS-2$ boolean isInt = (first.equals("int") || second.equals("int")); //$NON-NLS-1$ //$NON-NLS-2$ boolean isLong = (first.equals("long") || second.equals("long")); //$NON-NLS-1$ //$NON-NLS-2$ boolean isShort = (first.equals("short") || second.equals("short")); //$NON-NLS-1$ //$NON-NLS-2$ boolean isLongLong = (first.equals("long") && second.equals("long")); //$NON-NLS-1$ //$NON-NLS-2$ boolean isDouble = (first.equals("double") || second.equals("double")); //$NON-NLS-1$ //$NON-NLS-2$ boolean isFloat = (first.equals("float") || second.equals("float")); //$NON-NLS-1$ //$NON-NLS-2$ boolean isComplex = (first.equals("complex") || second.equals("complex") || //$NON-NLS-1$ //$NON-NLS-2$ first.equals("_Complex") || second.equals("_Complex")); //$NON-NLS-1$ //$NON-NLS-2$ boolean isImaginery = (first.equals("_Imaginary") || second.equals("_Imaginary")); //$NON-NLS-1$ //$NON-NLS-2$ boolean isStruct = first.equals("struct"); //$NON-NLS-1$ boolean isClass = first.equals("class"); //$NON-NLS-1$ boolean isUnion = first.equals("union"); //$NON-NLS-1$ boolean isEnum = first.equals("enum"); //$NON-NLS-1$ if (isChar && (isSigned || isUnsigned)) { return new CharType(target, typename, isUnsigned); } else if (isShort && (isInt || isSigned || isUnsigned)) { return new ShortType(target, typename, isUnsigned); } else if (isInt && (isSigned || isUnsigned)) { return new IntType(target, typename, isUnsigned); } else if (isLong && (isInt || isSigned || isUnsigned)) { return new LongType(target, typename, isUnsigned); } else if (isLongLong) { return new LongLongType(target, typename); } else if (isDouble && (isLong || isComplex || isImaginery)) { return new DoubleType(target, typename, isComplex, isImaginery, isLong); } else if (isFloat && (isComplex || isImaginery)) { return new FloatType(target, typename, isComplex, isImaginery); } else if (isStruct) { return new StructType(target, typename); } else if (isClass) { return new StructType(target, typename); } else if (isUnion) { return new StructType(target, typename); } else if (isEnum) { return new EnumType(target, typename); } } else if (count == 3) { // ISOC allows permutation. replace short by: long or short // "unsigned short int", "unsigned int short" // "short unsigned int". "short int unsigned" // "int unsinged short". "int short unsigned" // // "unsigned long long", "long long unsigned" // "signed long long", "long long signed" String first = st.nextToken(); String second = st.nextToken(); String third = st.nextToken(); boolean isSigned = (first.equals("signed") || second.equals("signed") || third.equals("signed")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ boolean unSigned = (first.equals("unsigned") || second.equals("unsigned") || third.equals("unsigned")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ boolean isInt = (first.equals("int") || second.equals("int") || third.equals("int")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ boolean isLong = (first.equals("long") || second.equals("long") || third.equals("long")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ boolean isShort = (first.equals("short") || second.equals("short") || third.equals("short")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ boolean isLongLong = (first.equals("long") && second.equals("long")) || //$NON-NLS-1$ //$NON-NLS-2$ (second.equals("long") && third.equals("long")); //$NON-NLS-1$ //$NON-NLS-2$ boolean isDouble = (first.equals("double") || second.equals("double") || third.equals("double")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ boolean isComplex = (first.equals("complex") || second.equals("complex") || third.equals("complex") || //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ first.equals("_Complex") || second.equals("_Complex") || third.equals("_Complex")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ boolean isImaginery = (first.equals("_Imaginary") || second.equals("_Imaginary") || third.equals("_Imaginary")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ if (isSigned == false && unSigned==false) { isSigned = true; // otherwise long long int would not work } if (isShort && isInt && (isSigned || unSigned)) { return new ShortType(target, typename, unSigned); } else if (isLongLong && (isSigned || unSigned)) { return new LongLongType(target, typename, unSigned); } else if (isLong && isInt && (isSigned || unSigned)) { return new LongType(target, typename, unSigned); } else if (isDouble && isLong && (isComplex || isImaginery)) { return new DoubleType(target, typename, isComplex, isImaginery, isLong); } } else if (count == 4) { // ISOC allows permutation: // "unsigned long long int", "unsigned int long long" // "long long unsigned int". "long long int unsigned" // "int unsigned long long". "int long long unsigned" String first = st.nextToken(); String second = st.nextToken(); String third = st.nextToken(); String fourth = st.nextToken(); boolean unSigned = (first.equals("unsigned") || second.equals("unsigned") || third.equals("unsigned") || fourth.equals("unsigned")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ boolean isSigned = (first.equals("signed") || second.equals("signed") || third.equals("signed") || fourth.equals("signed")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ boolean isInt = (first.equals("int") || second.equals("int") || third.equals("int") || fourth.equals("int")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ boolean isLongLong = (first.equals("long") && second.equals("long")) //$NON-NLS-1$ //$NON-NLS-2$ || (second.equals("long") && third.equals("long")) //$NON-NLS-1$ //$NON-NLS-2$ || (third.equals("long") && fourth.equals("long")); //$NON-NLS-1$ //$NON-NLS-2$ if (isLongLong && isInt && (isSigned || unSigned)) { return new LongLongType(target, typename, unSigned); } } throw new CDIException(CdiResources.getString("cdi.SourceManager.Unknown_type")); //$NON-NLS-1$ } public String getDetailTypeNameFromVariable(StackFrame frame, String variable) throws CDIException { Target target = (Target)frame.getTarget(); Thread currentThread = (Thread)target.getCurrentThread(); StackFrame currentFrame = currentThread.getCurrentStackFrame(); synchronized(target.getLock()) { try { target.setCurrentThread(frame.getThread(), false); ((Thread)frame.getThread()).setCurrentStackFrame(frame, false); return getDetailTypeName(target, variable); } finally { target.setCurrentThread(currentThread, false); currentThread.setCurrentStackFrame(currentFrame, false); } } } public String getDetailTypeName(Target target, String typename) throws CDIException { try { MISession mi = target.getMISession(); RxThread rxThread = mi.getRxThread(); rxThread.setEnableConsole(false); CommandFactory factory = mi.getCommandFactory(); CLIPType ptype = factory.createCLIPType(typename); mi.postCommand(ptype); CLIPTypeInfo info = ptype.getMIPtypeInfo(); if (info == null) { throw new CDIException(CdiResources.getString("cdi.Common.No_answer")); //$NON-NLS-1$ } return info.getType(); } catch (MIException e) { throw new MI2CDIException(e); } finally { MISession mi = target.getMISession(); RxThread rxThread = mi.getRxThread(); rxThread.setEnableConsole(true); } } public String getTypeNameFromVariable(StackFrame frame, String variable) throws CDIException { Target target = (Target)frame.getTarget(); Thread currentThread = (Thread)target.getCurrentThread(); StackFrame currentFrame = currentThread.getCurrentStackFrame(); synchronized(target.getLock()) { try { target.setCurrentThread(frame.getThread(), false); ((Thread)frame.getThread()).setCurrentStackFrame(frame, false); return getTypeName(target, variable); } finally { target.setCurrentThread(currentThread, false); currentThread.setCurrentStackFrame(currentFrame, false); } } } public String getTypeName(Target target, String variable) throws CDIException { MISession miSession = target.getMISession(); try { RxThread rxThread = miSession.getRxThread(); rxThread.setEnableConsole(false); CommandFactory factory = miSession.getCommandFactory(); CLIWhatis whatis = factory.createCLIWhatis(variable); miSession.postCommand(whatis); CLIWhatisInfo info = whatis.getMIWhatisInfo(); if (info == null) { throw new CDIException(CdiResources.getString("cdi.Common.No_answer")); //$NON-NLS-1$ } return info.getType(); } catch (MIException e) { throw new MI2CDIException(e); } finally { RxThread rxThread = miSession.getRxThread(); rxThread.setEnableConsole(true); } } }