public void Scanner_GlobalDataRecursiveStructs() { var bytes = new byte[] { 0x17, 0x00, 0x21, 0x43, 0x00, 0x00, 0x21, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; Given_Program(Address.Ptr32(0x43210000), bytes); Given_Project(); var sc = new Scanner( this.program, project.LoadedMetadata, new DynamicLinker(project, program, eventListener), this.sc ); var ft = Given_Serialized_Signature(new SerializedSignature { ReturnValue = new Argument_v1 { Type = Real32() }, }); var str = new StructureType(); var fields = new StructureField[] { new StructureField(0, new Pointer(ft, 32), "func"), new StructureField(4, new Pointer(str, 32), "next"), }; str.Fields.AddRange(fields); sc.EnqueueUserGlobalData(Address.Ptr32(0x43210000), str, null); sc.ScanImage(); var sExpSig = @"FpuStack real32 fn43210017() // stackDelta: 4; fpuStackDelta: 1; fpuMaxParam: -1 "; Assert.AreEqual(1, program.Procedures.Count); Assert.AreEqual(sExpSig, program.Procedures[Address.Ptr32(0x43210017)].Signature.ToString("fn43210017", FunctionType.EmitFlags.AllDetails)); }
public override void VisitConstant(Constant c) { DataType dt = c.TypeVariable.DataType; int offset = StructureField.ToOffset(c); Pointer ptr = dt as Pointer; if (ptr != null) { // C is a constant pointer. if (offset == 0) { return; // null pointer is null (//$REVIEW: except for some platforms + archs) } var pointee = ptr.Pointee; var segPointee = pointee.ResolveAs <StructureType>(); if (segPointee != null && segPointee.IsSegment) { //$TODO: these are getting merged earlier, perhaps this is the right place to do those merges? return; } var strGlobals = Globals.TypeVariable.Class.ResolveAs <StructureType>(); if (strGlobals.Fields.AtOffset(offset) == null) { if (!IsInsideArray(strGlobals, offset, pointee)) { strGlobals.Fields.Add(offset, pointee); } } return; } MemberPointer mptr = dt as MemberPointer; if (mptr != null) { // C is a constant offset into a segment. var seg = ((Pointer)mptr.BasePointer).Pointee.ResolveAs <StructureType>(); if (seg != null && //$DEBUG seg.Fields.AtOffset(offset) == null) { seg.Fields.Add(offset, mptr.Pointee); } // VisitConstantMemberPointer(offset, mptr); } }
/// <summary> /// Create a property field of a class with get and set. /// </summary> public void AddField(StructureField field, Type fieldType, int order) { var fieldBuilder = m_structureBuilder.DefineField("_" + field.Name, fieldType, FieldAttributes.Private); var propertyBuilder = m_structureBuilder.DefineProperty( field.Name, PropertyAttributes.None, fieldType, null); var methodAttributes = System.Reflection.MethodAttributes.Public | System.Reflection.MethodAttributes.HideBySig | System.Reflection.MethodAttributes.Virtual; var setBuilder = m_structureBuilder.DefineMethod("set_" + field.Name, methodAttributes, null, new[] { fieldType }); var setIl = setBuilder.GetILGenerator(); setIl.Emit(OpCodes.Ldarg_0); setIl.Emit(OpCodes.Ldarg_1); setIl.Emit(OpCodes.Stfld, fieldBuilder); if (m_structureType == StructureType.Union) { // set the union selector to the new field index FieldInfo unionField = typeof(UnionComplexType).GetField( "m_switchField", BindingFlags.NonPublic | BindingFlags.Instance); setIl.Emit(OpCodes.Ldarg_0); setIl.Emit(OpCodes.Ldc_I4, order); setIl.Emit(OpCodes.Stfld, unionField); } setIl.Emit(OpCodes.Ret); var getBuilder = m_structureBuilder.DefineMethod("get_" + field.Name, methodAttributes, fieldType, Type.EmptyTypes); var getIl = getBuilder.GetILGenerator(); getIl.Emit(OpCodes.Ldarg_0); getIl.Emit(OpCodes.Ldfld, fieldBuilder); getIl.Emit(OpCodes.Ret); propertyBuilder.SetGetMethod(getBuilder); propertyBuilder.SetSetMethod(setBuilder); propertyBuilder.DataMemberAttribute(field.Name, false, order); propertyBuilder.StructureFieldAttribute(field); }
public Expression VisitMkSequence(MkSequence seq) { var ter = new TypedExpressionRewriter(prog); //$TODO: identical to TypedExpressionRewriter except for the ceb.Dereferenced statements. How to combine? var head = seq.Head.Accept(ter); var tail = seq.Tail.Accept(ter); Constant c = tail as Constant; var ptHead = head.TypeVariable.DataType as PrimitiveType; if (head.TypeVariable.DataType is Pointer || (ptHead != null && ptHead.Domain == Domain.Selector)) { if (c != null) { ComplexExpressionBuilder ceb = new ComplexExpressionBuilder( seq.TypeVariable.DataType, head.DataType, head.TypeVariable.OriginalDataType, null, head, null, StructureField.ToOffset(c)); ceb.Dereferenced = true; return(ceb.BuildComplex()); } else { var ceb = new ComplexExpressionBuilder( seq.TypeVariable.DataType, seq.TypeVariable.DataType, seq.TypeVariable.OriginalDataType, head, tail, null, 0); ceb.Dereferenced = true; return(ceb.BuildComplex()); } } else { } return(new MkSequence(seq.DataType, head, tail)); }
private void AddGlobalField(DataType dtField, Address address, string?name) { if (address.Selector.HasValue) { if (program.SegmentMap.TryFindSegment(address, out var seg) && program.TypeStore.SegmentTypes.TryGetValue(seg, out var structureType)) { var f = new StructureField((int)address.Offset, dtField, name); structureType.Fields.Add(f); } } else { var offset = (int)address.ToLinear(); var f = new StructureField(offset, dtField, name); var ptrGlobals = (Pointer)program.Globals.TypeVariable !.OriginalDataType; ((StructureType)ptrGlobals.Pointee).Fields.Add(f); } }
public Expression VisitStructure(StructureType str) { if (++depth > 20) { Debug.Print("*** recursion too deep, quitting. Determine error then remove this"); //$DEBUG return(expComplex); } if (enclosingPtr != null) { int strSize = str.GetInferredSize(); if (str.Size > 0 && // We know the size of the struct, for sure. (offset >= strSize && offset % strSize == 0 && index == null)) { var exp = CreateArrayAccess(str, enclosingPtr, offset / strSize, index); index = null; --depth; return(exp); } else if (index != null && offset == 0) { var idx = this.ScaleDownIndex(index, strSize); index = null; var exp = CreateArrayAccess(str, enclosingPtr, 0, idx); --depth; return(exp); } } StructureField field = str.Fields.LowerBound(this.offset); if (field == null) { throw new TypeInferenceException("Expected structure type {0} to have a field at offset {1} ({1:X}).", str.Name, offset); } dtComplex = field.DataType; dtComplexOrig = field.DataType.ResolveAs <DataType>(); this.expComplex = CreateFieldAccess(str, field.DataType, expComplex, field); offset -= field.Offset; var e = dtComplex.Accept(this); --depth; return(e); }
public void Scanner_GlobalDataRecursiveStructs() { var bytes = new byte[] { 0x17, 0x00, 0x21, 0x43, 0x00, 0x00, 0x21, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; Given_Program(Address.Ptr32(0x43210000), bytes); Given_Project(); var sc = new Scanner( this.program, new ImportResolver(project, program, eventListener), this.sc ); var ft = new FunctionType(new SerializedSignature { ReturnValue = new Argument_v1 { Type = Real32() }, }); var str = new StructureType(); var fields = new StructureField[] { new StructureField(0, new Pointer(ft, 4), "func"), new StructureField(4, new Pointer(str, 4), "next"), }; str.Fields.AddRange(fields); sc.EnqueueUserGlobalData(Address.Ptr32(0x43210000), str); sc.ScanImage(); var sExpSig = @"Register real32 ()() // stackDelta: 4; fpuStackDelta: 0; fpuMaxParam: -1 "; Assert.AreEqual(1, program.Procedures.Count); Assert.AreEqual(sExpSig, program.Procedures[Address.Ptr32(0x43210017)].Signature.ToString()); }
private Expression VisitConstant(Constant c, bool dereferenced) { if (basePointer != null) { ComplexExpressionBuilder ceb = new ComplexExpressionBuilder( dtResult, basePointer.TypeVariable.DataType, basePointer.TypeVariable.OriginalDataType, null, basePointer, null, StructureField.ToOffset(c)); ceb.Dereferenced = dereferenced; return(ceb.BuildComplex()); } else { return(tcr.Rewrite(c, dereferenced)); } }
public bool Match(StructureField fa, StructureField fb) { this.fa = fa; this.fb = fb; this.fNestedStruct = null; this.fOther = null; this.NextFieldA = null; this.NextFieldB = null; var strFa = fa.DataType.TypeReferenceAs <StructureType>(); var strFb = fb.DataType.TypeReferenceAs <StructureType>(); // only one field should be nested structure if ( (strFa == null && strFb == null) || (strFa != null && strFb != null)) { return(false); } // check which of two fields is nested structure and store it // and other field in corresponding variables. int strSize; if (strFa != null) { fNestedStruct = fa; fOther = fb; strSize = strFa.GetInferredSize(); } else { fNestedStruct = fb; fOther = fa; strSize = strFb !.GetInferredSize(); } // check if other field is inside nested structure return( fOther.Offset >= fNestedStruct.Offset && fOther.Offset < fNestedStruct.Offset + strSize); }
private TypeVariable GetTypeVariableForField(DataType fieldType) { StructureType s = fieldType as StructureType; if (s != null) { StructureField f = s.Fields.AtOffset(0); if (f == null) { return(null); } return(f.DataType as TypeVariable); } FunctionType fn = fieldType as FunctionType; if (fn != null) { throw new NotImplementedException(); } throw new NotImplementedException(string.Format("Don't know how to handle pointers to {0}.", fieldType)); }
private void AddFieldToCluster(StructureField field, List <StructureField> overlappingFields) { if (!(field.DataType is EquivalenceClass eq)) { overlappingFields.Add(field); return; } if (eq.DataType is UnionType u) { foreach (UnionAlternative alt in u.Alternatives.Values) { StructureField f = new StructureField(field.Offset, alt.DataType); overlappingFields.Add(f); } } else { overlappingFields.Add(field); return; } }
private void WriteGlobalVariable(StructureField field) { var name = program.NamingPolicy.GlobalName(field); var addr = Address.Ptr32((uint)field.Offset); //$BUG: this is completely wrong; field.Offsets should be as wide as the platform permits. var oneLineDeclaration = IsOneLineDeclaration(field.DataType); try { tw.WriteDeclaration(field.DataType, name); if (program.SegmentMap.IsValidAddress(addr)) { formatter.Write(" = "); if (!oneLineDeclaration && showAddressInComment) { formatter.Write("// {0}", addr); } this.rdr = program.CreateImageReader(program.Architecture, addr); field.DataType.Accept(this); } } catch (Exception ex) { var dc = services.RequireService <DecompilerEventListener>(); dc.Error( dc.CreateAddressNavigator(program, addr), ex, "Failed to write global variable {0}.", name); formatter.Terminate(";"); return; } if (oneLineDeclaration && showAddressInComment) { formatter.Write("; // {0}", addr); formatter.Terminate(); } else { formatter.Terminate(";"); } }
public override Expression VisitMkSequence(MkSequence seq) { var head = seq.Head.Accept(this); var tail = seq.Tail.Accept(this); Constant c = seq.Tail as Constant; var ptHead = head.TypeVariable.DataType as PrimitiveType; if (head.TypeVariable.DataType is Pointer || (ptHead != null && ptHead.Domain == Domain.Selector)) { if (c != null) { ComplexExpressionBuilder ceb = new ComplexExpressionBuilder( seq.TypeVariable.DataType, head.TypeVariable.DataType, head.TypeVariable.OriginalDataType, null, head, null, StructureField.ToOffset(c)); return(ceb.BuildComplex()); } else { var ceb = new ComplexExpressionBuilder( seq.TypeVariable.DataType, seq.TypeVariable.DataType, seq.TypeVariable.OriginalDataType, head, new MemberPointerSelector(seq.DataType, head, tail), null, 0); return(ceb.BuildComplex()); } } else { } return(new MkSequence(seq.DataType, head, tail)); }
private Expression RewriteGlobalFieldAccess( DataType dt, int offset) { var f = GlobalVars.Fields.LowerBound(offset); if (f == null || !IsInsideField(offset, f)) { f = new StructureField(offset, dt); GlobalVars.Fields.Add(f); } var ptrStr = new Pointer(GlobalVars, platform.PointerType.BitSize); var fa = new FieldAccess(f.DataType, new Dereference(ptrStr, globals), f); if (f.Offset != offset) { var ceb = new ComplexExpressionBuilder( null, null, fa, null, offset - f.Offset); return(ceb.BuildComplex(false)); } return(fa); }
private StructureField EnsureFieldAtOffset(StructureType str, DataType dt, int offset) { StructureField f = str.Fields.AtOffset(offset); if (f == null) { //$TODO: overlaps and conflicts. //$TODO: strings. f = new StructureField(offset, dt); str.Fields.Add(f); } return(f); #if TODO var f = GlobalVars.Fields.LowerBound(c.ToInt32()); //StructureField f = str.Fields.AtOffset(offset); if (f != null) { Unifier u = new Unifier(); if (u.AreCompatible(f.DataType, dt)) { return(f); } // Check for special case when an array ends at the offset. f = GlobalVars.Fields.LowerBound(c.ToInt32() - 1); var array = f.DataType.ResolveAs <ArrayType>(); if (array != null && u.AreCompatible(array.ElementType, dt)) { return(f); } } //$TODO: overlaps and conflicts. //$TODO: strings. f = new StructureField(offset, dt); str.Fields.Add(f); return(f); #endif }
private bool IsInsideField(int offset, StructureField field) { if (offset < field.Offset) { return(false); } if (offset == field.Offset) { return(true); } if (offset < field.Offset + field.DataType.Size) { return(true); } var str = field.DataType.ResolveAs <StructureType>(); if (str != null && offset < field.Offset + str.GetInferredSize()) { return(true); } return(false); }
/// <summary> /// Build the StructureField attribute for a complex type. /// </summary> public static void StructureFieldAttribute( this PropertyBuilder typeBuilder, StructureField structureField) { var attributeType = typeof(StructureFieldAttribute); ConstructorInfo ctorInfo = attributeType.GetConstructor(Type.EmptyTypes); CustomAttributeBuilder builder = new CustomAttributeBuilder( ctorInfo, new object[0], // constructor arguments new[] // properties to assign { attributeType.GetProperty("ValueRank"), attributeType.GetProperty("MaxStringLength"), attributeType.GetProperty("IsOptional") }, new object[] // values to assign { structureField.ValueRank, structureField.MaxStringLength, structureField.IsOptional }); typeBuilder.SetCustomAttribute(builder); }
/// <summary> /// Exports a DataTypeDefinition /// </summary> private Opc.Ua.Export.DataTypeDefinition Export( DataTypeState dataType, ExtensionObject source, NamespaceTable namespaceUris, bool outputRedundantNames) { if (source == null || source.Body == null) { return(null); } DataTypeDefinition definition = new DataTypeDefinition(); if (outputRedundantNames || dataType.BrowseName != null) { definition.Name = Export(dataType.BrowseName, namespaceUris); } if (dataType.BrowseName.Name != dataType.SymbolicName) { definition.SymbolicName = dataType.SymbolicName; } StructureDefinition sd = source.Body as StructureDefinition; if (sd != null) { if (sd.StructureType == StructureType.Union || sd.StructureType == (StructureType)4) // StructureType.UnionWithSubtypedValues) { definition.IsUnion = true; } if (sd.Fields != null) { List <Opc.Ua.Export.DataTypeField> fields = new List <DataTypeField>(); for (int ii = sd.FirstExplicitFieldIndex; ii < sd.Fields.Count; ii++) { StructureField field = sd.Fields[ii]; Opc.Ua.Export.DataTypeField output = new Opc.Ua.Export.DataTypeField(); output.Name = field.Name; output.Description = Export(new Opc.Ua.LocalizedText[] { field.Description }); if (sd.StructureType == StructureType.StructureWithOptionalFields) { output.IsOptional = field.IsOptional; output.AllowSubTypes = false; } else if (sd.StructureType == (StructureType)3 || // StructureType.StructureWithSubtypedValues || sd.StructureType == (StructureType)4) // StructureType.UnionWithSubtypedValues) { output.IsOptional = false; output.AllowSubTypes = field.IsOptional; } else { output.IsOptional = false; output.AllowSubTypes = false; } if (NodeId.IsNull(field.DataType)) { output.DataType = Export(DataTypeIds.BaseDataType, namespaceUris); } else { output.DataType = Export(field.DataType, namespaceUris); } output.ValueRank = field.ValueRank; fields.Add(output); } definition.Field = fields.ToArray(); } } EnumDefinition ed = source.Body as EnumDefinition; if (ed != null) { definition.IsOptionSet = ed.IsOptionSet; if (ed.Fields != null) { List <Opc.Ua.Export.DataTypeField> fields = new List <DataTypeField>(); foreach (EnumField field in ed.Fields) { Opc.Ua.Export.DataTypeField output = new Opc.Ua.Export.DataTypeField(); output.Name = field.Name; if (field.DisplayName != null && output.Name != field.DisplayName.Text) { output.DisplayName = Export(new Opc.Ua.LocalizedText[] { field.DisplayName }); } else { output.DisplayName = Array.Empty <LocalizedText>(); } output.Description = Export(new Opc.Ua.LocalizedText[] { field.Description }); output.ValueRank = ValueRanks.Scalar; output.Value = (int)field.Value; fields.Add(output); } definition.Field = fields.ToArray(); } } return(definition); }
public StructureFieldParameter(StructureField structureField) { Name = structureField.Name; BuiltInType = TypeInfo.GetBuiltInType(structureField.DataType); }
public void Scanner_GlobalData() { var bytes = new byte[] { 0x48, 0x00, 0x21, 0x43, 0x00, 0x00, 0x00, 0x01, 0x53, 0x00, 0x21, 0x43, 0x28, 0x00, 0x21, 0x43, 0x00, 0x00, 0x00, 0x02, 0x63, 0x00, 0x21, 0x43, 0x38, 0x00, 0x21, 0x43, 0x00, 0x00, 0x00, 0x03, 0x73, 0x00, 0x21, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; Given_Program(Address.Ptr32(0x43210000), bytes); var project = new Project { Programs = { program } }; var sc = new Scanner( this.program, new ImportResolver(project, program, eventListener), this.sc ); var ft1 = new FunctionType(new SerializedSignature { ReturnValue = new Argument_v1 { Type = Int32() } }); var ft2 = new FunctionType(new SerializedSignature { ReturnValue = new Argument_v1 { Type = Char() } }); var str = new StructureType(); var fields = new StructureField[] { new StructureField(0, new Pointer(ft1, 4), "A"), new StructureField(4, PrimitiveType.Int32, "B"), new StructureField(8, new Pointer(ft2, 4), "C"), }; str.Fields.AddRange(fields); var elementType = new TypeReference("test", str); var arrayType = new ArrayType(elementType, 3); sc.EnqueueUserGlobalData(Address.Ptr32(0x43210000), arrayType); sc.ScanImage(); var sExpSig1 = @"Register ui32 ()() // stackDelta: 4; fpuStackDelta: 0; fpuMaxParam: -1 "; var sExpSig2 = @"Register char ()() // stackDelta: 4; fpuStackDelta: 0; fpuMaxParam: -1 "; Assert.AreEqual(6, program.Procedures.Count); Assert.AreEqual(sExpSig1, program.Procedures[Address.Ptr32(0x43210028)].Signature.ToString()); Assert.AreEqual(sExpSig1, program.Procedures[Address.Ptr32(0x43210038)].Signature.ToString()); Assert.AreEqual(sExpSig1, program.Procedures[Address.Ptr32(0x43210048)].Signature.ToString()); Assert.AreEqual(sExpSig2, program.Procedures[Address.Ptr32(0x43210053)].Signature.ToString()); Assert.AreEqual(sExpSig2, program.Procedures[Address.Ptr32(0x43210063)].Signature.ToString()); Assert.AreEqual(sExpSig2, program.Procedures[Address.Ptr32(0x43210073)].Signature.ToString()); }
public void Scanner_GlobalDataRecursiveStructs() { var bytes = new byte[] { 0x17, 0x00, 0x21, 0x43, 0x00, 0x00, 0x21, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; Given_Program(Address.Ptr32(0x43210000), bytes); Given_Project(); var sc = new Scanner( this.program, new ImportResolver(project, program, eventListener), this.sc ); var ft = Given_Serialized_Signature(new SerializedSignature { ReturnValue = new Argument_v1 { Type = Real32() }, }); var str = new StructureType(); var fields = new StructureField[] { new StructureField(0, new Pointer(ft, 4), "func"), new StructureField(4, new Pointer(str, 4), "next"), }; str.Fields.AddRange(fields); sc.EnqueueUserGlobalData(Address.Ptr32(0x43210000), str); sc.ScanImage(); var sExpSig = @"Register real32 fn43210017() // stackDelta: 4; fpuStackDelta: 0; fpuMaxParam: -1 "; Assert.AreEqual(1, program.Procedures.Count); Assert.AreEqual(sExpSig, program.Procedures[Address.Ptr32(0x43210017)].Signature.ToString("fn43210017", FunctionType.EmitFlags.AllDetails)); }
/// <summary> /// Imports a DataTypeDefinition /// </summary> private Opc.Ua.DataTypeDefinition Import(UADataType dataType, Opc.Ua.Export.DataTypeDefinition source, NamespaceTable namespaceUris) { if (source == null) { return(null); } Opc.Ua.DataTypeDefinition definition = null; if (source.Field != null) { // check if definition is for enumeration or structure. bool isStructure = Array.Exists <DataTypeField>(source.Field, delegate(DataTypeField fieldLookup) { return(fieldLookup.Value == -1); }); if (isStructure) { StructureDefinition structureDefinition = new StructureDefinition(); structureDefinition.BaseDataType = ImportNodeId(source.BaseType, namespaceUris, true); if (source.IsUnion) { structureDefinition.StructureType = StructureType.Union; } if (source.Field != null) { List <StructureField> fields = new List <StructureField>(); foreach (DataTypeField field in source.Field) { if (field.IsOptional) { structureDefinition.StructureType = StructureType.StructureWithOptionalFields; } StructureField output = new StructureField(); output.Name = field.Name; output.Description = Import(field.Description); output.DataType = ImportNodeId(field.DataType, namespaceUris, true); output.ValueRank = field.ValueRank; output.IsOptional = field.IsOptional; fields.Add(output); } structureDefinition.Fields = fields.ToArray(); } definition = structureDefinition; } else { EnumDefinition enumDefinition = new EnumDefinition(); if (source.Field != null) { List <EnumField> fields = new List <EnumField>(); foreach (DataTypeField field in source.Field) { EnumField output = new EnumField(); output.Name = field.Name; output.DisplayName = Import(field.DisplayName); output.Description = Import(field.Description); output.Value = field.Value; fields.Add(output); } enumDefinition.Fields = fields.ToArray(); } definition = enumDefinition; } } return(definition); }
public StructureType CreateStructureType(string name, int size, StructureField field) { return new StructureType(name, size) { Fields = { field } }; }
public Expression VisitBinaryExpression(BinaryExpression binExp) { Expression left = binExp.Left; Expression right = binExp.Right; TypeVariable tvLeft = left.TypeVariable; TypeVariable tvRight = right.TypeVariable; if (!tvLeft.DataType.IsComplex) { if (!tvRight.DataType.IsComplex) { throw new NotImplementedException(string.Format("Neither subexpression is complex in {0}: [[{1}]] and [[{2}]]", binExp, tvLeft.DataType, tvRight.DataType)); } return(VisitBinaryExpression(binExp.Commute())); } else if (tvRight.DataType.IsComplex) { throw new TypeInferenceException("Both subexpressions are complex in {0}. Left type: {1}, right type {2}", binExp, tvLeft.DataType, tvRight.DataType); } var ter = new TypedExpressionRewriter(prog); ComplexExpressionBuilder ceb; Constant cLeft = left as Constant; if (cLeft != null) { binExp.Right = binExp.Right.Accept(ter); if (basePointer == null) { basePointer = globals; } ceb = new ComplexExpressionBuilder( dtResult, basePointer.TypeVariable.DataType, basePointer.TypeVariable.OriginalDataType, null, basePointer, binExp.Right, StructureField.ToOffset(cLeft)); } else { var binLeft = binExp.Left.Accept(ter); var binRight = binExp.Right.Accept(ter); var cRight = binRight as Constant; ceb = new ComplexExpressionBuilder( binExp.DataType, tvLeft.DataType, tvLeft.OriginalDataType, basePointer, binLeft, cRight != null ? null : binRight, StructureField.ToOffset(binRight as Constant)); } ceb.Dereferenced = true; return(ceb.BuildComplex()); }
public void Scanner_GlobalData() { var bytes = new byte[] { 0x48, 0x00, 0x21, 0x43, 0x00, 0x00, 0x00, 0x01, 0x53, 0x00, 0x21, 0x43, 0x28, 0x00, 0x21, 0x43, 0x00, 0x00, 0x00, 0x02, 0x63, 0x00, 0x21, 0x43, 0x38, 0x00, 0x21, 0x43, 0x00, 0x00, 0x00, 0x03, 0x73, 0x00, 0x21, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; Given_Program(Address.Ptr32(0x43210000), bytes); var project = new Project { Programs = { program } }; var sc = new Scanner( this.program, new ImportResolver(project, program, eventListener), this.sc ); var ft1 = Given_Serialized_Signature(new SerializedSignature { ReturnValue = new Argument_v1 { Type = Int32() }, }); var ft2 = Given_Serialized_Signature(new SerializedSignature { ReturnValue = new Argument_v1 { Type = Char() } }); var str = new StructureType(); var fields = new StructureField[] { new StructureField(0, new Pointer(ft1, 4), "A"), new StructureField(4, PrimitiveType.Int32, "B"), new StructureField(8, new Pointer(ft2, 4), "C"), }; str.Fields.AddRange(fields); var elementType = new TypeReference("test", str); var arrayType = new ArrayType(elementType, 3); sc.EnqueueUserGlobalData(Address.Ptr32(0x43210000), arrayType); sc.ScanImage(); var sExpSig1 = @"Register ui32 sig1() // stackDelta: 4; fpuStackDelta: 0; fpuMaxParam: -1 "; var sExpSig2 = @"Register char sig2() // stackDelta: 4; fpuStackDelta: 0; fpuMaxParam: -1 "; Assert.AreEqual(6, program.Procedures.Count); Assert.AreEqual(sExpSig1, program.Procedures[Address.Ptr32(0x43210028)].Signature.ToString("sig1", FunctionType.EmitFlags.AllDetails)); Assert.AreEqual(sExpSig1, program.Procedures[Address.Ptr32(0x43210038)].Signature.ToString("sig1", FunctionType.EmitFlags.AllDetails)); Assert.AreEqual(sExpSig1, program.Procedures[Address.Ptr32(0x43210048)].Signature.ToString("sig1", FunctionType.EmitFlags.AllDetails)); Assert.AreEqual(sExpSig2, program.Procedures[Address.Ptr32(0x43210053)].Signature.ToString("sig2", FunctionType.EmitFlags.AllDetails)); Assert.AreEqual(sExpSig2, program.Procedures[Address.Ptr32(0x43210063)].Signature.ToString("sig2", FunctionType.EmitFlags.AllDetails)); Assert.AreEqual(sExpSig2, program.Procedures[Address.Ptr32(0x43210073)].Signature.ToString("sig2", FunctionType.EmitFlags.AllDetails)); }
public DataType MemoryAccessCommon(Expression tBase, Expression tStruct, int offset, DataType tField, int structPtrSize) { var s = factory.CreateStructureType(null, 0); var field = new StructureField(offset, tField); s.Fields.Add(field); var pointer = tBase != null ? (DataType)factory.CreateMemberPointer(tBase.TypeVariable, s, structPtrSize) : (DataType)factory.CreatePointer(s, structPtrSize); return MergeIntoDataType(tStruct, pointer); }
public DataType MemFieldTrait(Expression tBase, Expression tStruct, Expression tField, int offset) { var s = factory.CreateStructureType(null, 0); var field = new StructureField(offset, tField.TypeVariable); s.Fields.Add(field); return MergeIntoDataType(tStruct, s); }
public TypeVariable EnsureFieldTypeVariable(TypeFactory factory, StructureField field) { throw new NotImplementedException(); }
private bool FieldOverlaps(StructureField field, int clusterEndOffset) { return(field.Offset < clusterEndOffset); }
public FieldAccess Field(DataType dt, Expression e, string fieldName) { var field = new StructureField(0, dt, fieldName); return new FieldAccess(dt, e, field); }
/// <summary> /// Exports a DataTypeDefinition /// </summary> private Opc.Ua.Export.DataTypeDefinition Export( DataTypeState dataType, ExtensionObject source, NamespaceTable namespaceUris, bool outputRedundantNames) { if (source == null || source.Body == null) { return(null); } DataTypeDefinition definition = new DataTypeDefinition(); if (outputRedundantNames || dataType.BrowseName != null) { definition.Name = Export(dataType.BrowseName, namespaceUris); } if (dataType.BrowseName.Name != dataType.SymbolicName) { definition.SymbolicName = dataType.SymbolicName; } switch (dataType.DataTypeModifier) { case DataTypeModifier.Union: { definition.IsUnion = true; break; } case DataTypeModifier.OptionSet: { definition.IsOptionSet = true; break; } } StructureDefinition structureDefinition = source.Body as StructureDefinition; if (structureDefinition != null) { if (structureDefinition.StructureType == StructureType.Union) { definition.IsUnion = true; } if (structureDefinition.Fields != null) { List <Opc.Ua.Export.DataTypeField> fields = new List <DataTypeField>(); for (int ii = structureDefinition.FirstExplicitFieldIndex; ii < structureDefinition.Fields.Count; ii++) { StructureField field = structureDefinition.Fields[ii]; Opc.Ua.Export.DataTypeField output = new Opc.Ua.Export.DataTypeField(); output.Name = field.Name; output.Description = Export(new Opc.Ua.LocalizedText[] { field.Description }); if (NodeId.IsNull(field.DataType)) { output.DataType = Export(DataTypeIds.BaseDataType, namespaceUris); } else { output.DataType = Export(field.DataType, namespaceUris); } output.ValueRank = field.ValueRank; fields.Add(output); } definition.Field = fields.ToArray(); } } EnumDefinition enumDefinition = source.Body as EnumDefinition; if (enumDefinition != null) { if (enumDefinition.Fields != null) { List <Opc.Ua.Export.DataTypeField> fields = new List <DataTypeField>(); foreach (EnumField field in enumDefinition.Fields) { Opc.Ua.Export.DataTypeField output = new Opc.Ua.Export.DataTypeField(); output.Name = field.Name; output.Description = Export(new Opc.Ua.LocalizedText[] { field.Description }); output.ValueRank = ValueRanks.Scalar; output.Value = (int)field.Value; fields.Add(output); } definition.Field = fields.ToArray(); } } return(definition); }
public void CreateField() { int off = StructureField.ToOffset(Constant.Word16(4)); Assert.AreEqual(4, off); }
private StructureType FindStructureToFitIn(StructureField field,int commonOffset, List<StructureType> types) { foreach (StructureType type in types) { int offset = field.Offset - commonOffset; StructureField low = type.Fields.LowerBound(offset); if (low == null) return type; if (low.DataType.Size + low.Offset <= offset) return type; } return null; }
private bool TryMakeFieldName(StructureField fa, StructureField fb, out string name) { name = null; if (fa.IsNameSet && fb.IsNameSet && fa.Name != fb.Name) return false; if (fa.IsNameSet) name = fa.Name; if (fb.IsNameSet) name = fb.Name; return true; }
private void AddFieldToCluster(StructureField field, List<StructureField> overlappingFields) { EquivalenceClass eq = field.DataType as EquivalenceClass; if (eq == null) { overlappingFields.Add(field); return; } UnionType u = (UnionType) eq.DataType; foreach (UnionAlternative alt in u.Alternatives.Values) { StructureField f = new StructureField(field.Offset, alt.DataType); overlappingFields.Add(f); } }
public Expression VisitPointer(Pointer ptr) { Expression e = c; if (IsSegmentPointer(ptr)) { Identifier segID; if (mpSelectorToSegId.TryGetValue(c.ToUInt16(), out segID)) { return(segID); } return(e); } else if (GlobalVars != null) { // Null pointer. if (c.IsZero) { var np = Address.Create(ptr, 0); np.TypeVariable = c.TypeVariable; np.DataType = c.DataType; return(np); } var addr = program.Platform.MakeAddressFromConstant(c); // An invalid pointer -- often used as sentinels in code. if (!program.SegmentMap.IsValidAddress(addr)) { //$TODO: probably should use a reinterpret_cast here. var ce = new Cast(ptr, c) { TypeVariable = c.TypeVariable }; return(ce); } var dt = ptr.Pointee.ResolveAs <DataType>(); var charType = MaybeCharType(dt); if (charType != null && IsPtrToReadonlySection(c, dt)) { PromoteToCString(c, charType); return(ReadNullTerminatedString(c, charType)); } StructureField f = EnsureFieldAtOffset(GlobalVars, dt, c.ToInt32()); var ptrGlobals = new Pointer(GlobalVars, platform.PointerType.BitSize); e = new FieldAccess(ptr.Pointee, new Dereference(ptrGlobals, globals), f); if (dereferenced) { e.DataType = ptr.Pointee; } else { var array = f.DataType as ArrayType; if (array != null) // C language rules 'promote' arrays to pointers. { e.DataType = program.TypeFactory.CreatePointer( array.ElementType, platform.PointerType.BitSize); } else { e = new UnaryExpression(Operator.AddrOf, ptr, e); } } } return(e); }
private bool FieldOverlaps(StructureField field, int clusterEndOffset) { return field.Offset < clusterEndOffset; }
/// <summary> /// Convert a binary schema type definition to a /// StructureDefinition. /// </summary> /// <remarks> /// Support for: /// - Structures, structures with optional fields and unions. /// - Nested types and typed arrays with length field. /// The converter has the following known restrictions: /// - Support only for V1.03 structured types which can be mapped to the V1.04 /// structured type definition. /// The following dictionary tags cause bail out for a structure: /// - use of a terminator of length in bytes /// - an array length field is not a direct predecessor of the array /// - The switch value of a union is not the first field. /// - The selector bits of optional fields are not stored in a 32 bit variable /// and do not add up to 32 bits. /// </remarks> public static StructureDefinition ToStructureDefinition( this Schema.Binary.StructuredType structuredType, ExpandedNodeId defaultEncodingId, Dictionary <XmlQualifiedName, NodeId> typeDictionary, NamespaceTable namespaceTable, NodeId dataTypeNodeId) { var structureDefinition = new StructureDefinition() { BaseDataType = null, DefaultEncodingId = ExpandedNodeId.ToNodeId(defaultEncodingId, namespaceTable), Fields = new StructureFieldCollection(), StructureType = StructureType.Structure }; bool isSupportedType = true; bool hasBitField = false; bool isUnionType = false; foreach (var field in structuredType.Field) { // check for yet unsupported properties if (field.IsLengthInBytes || field.Terminator != null) { isSupportedType = false; } if (field.SwitchValue != 0) { isUnionType = true; } if (field.TypeName.Namespace == Namespaces.OpcBinarySchema || field.TypeName.Namespace == Namespaces.OpcUa) { if (field.TypeName.Name == "Bit") { hasBitField = true; continue; } } if (field.Length != 0) { isSupportedType = false; } } // test forbidden combinations if (!isSupportedType) { throw new DataTypeNotSupportedException( "The structure definition uses a Terminator or LengthInBytes, which are not supported."); } if (isUnionType && hasBitField) { throw new DataTypeNotSupportedException( "The structure definition combines a Union and a bit filed, both of which are not supported in a single structure."); } if (isUnionType) { structureDefinition.StructureType = StructureType.Union; } if (hasBitField) { structureDefinition.StructureType = StructureType.StructureWithOptionalFields; } byte switchFieldBitPosition = 0; Int32 dataTypeFieldPosition = 0; var switchFieldBits = new Dictionary <string, byte>(); // convert fields foreach (var field in structuredType.Field) { // consume optional bits if (field.TypeName.IsXmlBitType()) { var count = structureDefinition.Fields.Count; if (count == 0 && switchFieldBitPosition < 32) { structureDefinition.StructureType = StructureType.StructureWithOptionalFields; byte fieldLength = (byte)((field.Length == 0) ? 1u : field.Length); switchFieldBits[field.Name] = switchFieldBitPosition; switchFieldBitPosition += fieldLength; } else { throw new DataTypeNotSupportedException( "Options for bit selectors must be 32 bit in size, use the Int32 datatype and must be the first element in the structure."); } continue; } if (switchFieldBitPosition != 0 && switchFieldBitPosition != 32) { throw new DataTypeNotSupportedException( "Bitwise option selectors must have 32 bits."); } NodeId fieldDataTypeNodeId; if (field.TypeName == structuredType.QName) { // recursive type fieldDataTypeNodeId = dataTypeNodeId; } else { fieldDataTypeNodeId = field.TypeName.ToNodeId(typeDictionary); } var dataTypeField = new StructureField() { Name = field.Name, Description = null, DataType = fieldDataTypeNodeId, IsOptional = false, MaxStringLength = 0, ArrayDimensions = null, ValueRank = -1 }; if (field.LengthField != null) { // handle array length var lastField = structureDefinition.Fields.Last(); if (lastField.Name != field.LengthField) { throw new DataTypeNotSupportedException( "The length field must precede the type field of an array."); } lastField.Name = field.Name; lastField.DataType = fieldDataTypeNodeId; lastField.ValueRank = 1; } else { if (isUnionType) { // ignore the switchfield if (field.SwitchField == null) { if (structureDefinition.Fields.Count != 0) { throw new DataTypeNotSupportedException( "The switch field of a union must be the first field in the complex type."); } continue; } if (structureDefinition.Fields.Count != dataTypeFieldPosition) { throw new DataTypeNotSupportedException( "The count of the switch field of the union member is not matching the field position."); } dataTypeFieldPosition++; } else { if (field.SwitchField != null) { dataTypeField.IsOptional = true; byte value; if (!switchFieldBits.TryGetValue(field.SwitchField, out value)) { throw new DataTypeNotSupportedException( $"The switch field for {field.SwitchField} does not exist."); } } } structureDefinition.Fields.Add(dataTypeField); } } return(structureDefinition); }
/// <summary> /// Imports a DataTypeDefinition /// </summary> private Opc.Ua.DataTypeDefinition Import(UADataType dataType, Opc.Ua.Export.DataTypeDefinition source, NamespaceTable namespaceUris) { if (source == null) { return(null); } Opc.Ua.DataTypeDefinition definition = null; if (source.Field != null) { // check if definition is for enumeration or structure. bool isStructure = Array.Exists <DataTypeField>(source.Field, delegate(DataTypeField fieldLookup) { return(fieldLookup.Value == -1); }); if (isStructure) { StructureDefinition sd = new StructureDefinition(); sd.BaseDataType = ImportNodeId(source.BaseType, namespaceUris, true); if (source.IsUnion) { sd.StructureType = StructureType.Union; } if (source.Field != null) { List <StructureField> fields = new List <StructureField>(); foreach (DataTypeField field in source.Field) { if (sd.StructureType == StructureType.Structure || sd.StructureType == StructureType.Union) { if (field.IsOptional) { sd.StructureType = StructureType.StructureWithOptionalFields; } else if (field.AllowSubTypes) { if (source.IsUnion) { sd.StructureType = (StructureType)4; // StructureType.UnionWithSubtypedValues; } else { sd.StructureType = (StructureType)3; // StructureType.StructureWithSubtypedValues; } } } StructureField output = new StructureField(); output.Name = field.Name; output.Description = Import(field.Description); output.DataType = ImportNodeId(field.DataType, namespaceUris, true); output.ValueRank = field.ValueRank; if (sd.StructureType == StructureType.Structure || sd.StructureType == StructureType.Union) { output.IsOptional = false; } else if (sd.StructureType == (StructureType)3 || //StructureType.StructureWithSubtypedValues || sd.StructureType == (StructureType)4) //StructureType.UnionWithSubtypedValues) { output.IsOptional = field.AllowSubTypes; } else { output.IsOptional = field.IsOptional; } fields.Add(output); } sd.Fields = fields.ToArray(); } definition = sd; } else { EnumDefinition ed = new EnumDefinition(); ed.IsOptionSet = source.IsOptionSet; if (source.Field != null) { List <EnumField> fields = new List <EnumField>(); foreach (DataTypeField field in source.Field) { EnumField output = new EnumField(); output.Name = field.Name; output.DisplayName = Import(field.DisplayName); output.Description = Import(field.Description); output.Value = field.Value; fields.Add(output); } ed.Fields = fields.ToArray(); } definition = ed; } } return(definition); }
public FieldAccess Field(DataType dt, Expression e, string fieldName) { var field = new StructureField(0, dt, fieldName); return(new FieldAccess(dt, e, field)); }
public Expression Rewrite(Address addr, Expression?basePtr, bool dereferenced) { if (addr.Selector.HasValue) { if (!mpSelectorToSegId.TryGetValue(addr.Selector.Value, out Identifier segId)) { eventListener.Warn( "Selector {0:X4} has no known segment.", addr.Selector.Value); return(addr); } var ptrSeg = segId.TypeVariable !.DataType.ResolveAs <Pointer>(); if (ptrSeg == null) { //$TODO: what should the warning be? //$BUG: create a fake field for now. var field = new StructureField((int)addr.Offset, new UnknownType()); Expression x = new FieldAccess(new UnknownType(), new Dereference(segId.DataType, segId), field); if (!dereferenced) { x = new UnaryExpression(Operator.AddrOf, addr.DataType, x); } return(x); } var baseType = ptrSeg.Pointee.ResolveAs <StructureType>() !; var dt = addr.TypeVariable !.DataType.ResolveAs <Pointer>() !; this.c = Constant.Create( PrimitiveType.CreateWord(addr.DataType.BitSize - ptrSeg.BitSize), addr.Offset); DataType pointee; if (dt != null) { pointee = dt.Pointee; } else { pointee = new UnknownType(); } var f = EnsureFieldAtOffset(baseType, pointee, c.ToInt32()); Expression ex = new FieldAccess(f.DataType, new Dereference(ptrSeg, segId), f); if (dereferenced || pointee is ArrayType) { return(ex); } else { var un = new UnaryExpression(Operator.AddrOf, addr.TypeVariable !.DataType, ex); return(un); } } else { this.c = addr.ToConstant(); this.c.TypeVariable = addr.TypeVariable; var dtInferred = addr.TypeVariable !.DataType.ResolveAs <DataType>() !; this.pOrig = addr.TypeVariable.OriginalDataType as PrimitiveType; this.dereferenced = dereferenced; return(dtInferred.Accept(this)); } }