示例#1
0
 public void Include(CIncludes includes)
 {
     if (includes.GnuSource)
     {
         Define("_GNU_SOURCE");
     }
     Include(includes.Headers);
 }
示例#2
0
        public void SizeOf(CIncludes includes, Type type)
        {
            int actualSize = Marshal.SizeOf(type);

            PropertyInfo property = typeof(SizeOf).GetProperty(type.Name);

            Assert.NotNull(property);
            int declaredSize = (ushort)property.GetGetMethod().Invoke(null, null);

            Assert.Equal(actualSize, declaredSize);
        }
示例#3
0
        public void Structs(CIncludes includes, Type type)
        {
            string name      = type.Name;
            bool?  supported = TestEnvironment.Current.SupportsStruct(name);

            if (supported == false)
            {
                return;
            }

            string structName = CType.GetName(name);

            using (var program = new CProgram())
            {
                if (TestEnvironment.Current.SupportsHeaders(includes.Headers) == false)
                {
                    return;
                }

                program.Define("_GNU_SOURCE");
                program.Include(includes.Headers);
                program.Include("stddef.h");
                program.AppendLine("#define member_size(type, member) sizeof(((type *)0)->member)");

                // define syscall_arg and long_t
                program.AppendLine("typedef long syscall_arg;");
                program.AppendLine("typedef long long_t;");
                program.AppendLine("typedef unsigned long ulong_t;");

                foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic))
                {
                    string fieldName   = field.Name;
                    int    fieldOffset = Marshal.OffsetOf(type, fieldName).ToInt32();
                    bool   checkField  = fieldName.StartsWith("<") ||                                // Backing field
                                         (fieldName.StartsWith("_") && !fieldName.StartsWith("__")); // Starts with single underscpre
                    if (!checkField)
                    {
                        continue;
                    }
                    if (fieldName.StartsWith("<"))
                    {
                        fieldName = fieldName.Substring(1, fieldName.IndexOf('>') - 1);
                    }
                    else if (fieldName.StartsWith("_"))
                    {
                        fieldName = fieldName.Substring(1);
                    }

                    program.StaticAssert($"offsetof({structName}, {fieldName}) == {fieldOffset}", $"{name}.{fieldName} is not at expected offset");

                    Type fieldType   = field.FieldType;
                    int  fieldLength = 1;
                    var  attr        = field.GetCustomAttribute(typeof(FixedBufferAttribute), false) as FixedBufferAttribute;
                    if (attr != null)
                    {
                        fieldType   = attr.ElementType;
                        fieldLength = attr.Length;
                    }

                    if (s_skipSizeCheckForFields.Contains($"{name}.{fieldName}"))
                    {
                        continue;
                    }

                    program.StaticAssert($"member_size({structName}, {fieldName}) == {Marshal.SizeOf(fieldType) * fieldLength}", $"{name}.{fieldName} is not of expected size");
                }

                program.StaticAssert($"sizeof({structName}) == {Marshal.SizeOf(type)}", $"{structName} does not have expected size");

                program.Compile();
            }
        }
示例#4
0
        public void Functions(CIncludes includes, string[] functions)
        {
            using (CProgram program = new CProgram())
            {
                if (TestEnvironment.Current.SupportsHeaders(includes.Headers) == false)
                {
                    return;
                }

                program.Include(includes);
                program.Include("stdint.h");
                program.BeginMain();

                var symbolsUsedByDotnet = new HashSet <string>();
                int idx = 0;
                foreach (var functionName in functions)
                {
                    bool?supported = TestEnvironment.Current.SupportsFunction(functionName);
                    if (supported == false)
                    {
                        continue;
                    }

                    MethodInfo[]       methods;
                    DllImportAttribute dllImportAttribute;
                    if (functionName == "errno" ||
                        functionName == "SIGRTMIN" ||
                        functionName == "SIGRTMAX")
                    {
                        // call method
                        program.AppendLine($"int rv{idx++} = {functionName};");
                    }
                    else
                    {
                        methods = typeof(LibC).GetMethods(BindingFlags.Static | BindingFlags.Public)
                                  .Where(mi => mi.Name == functionName)
                                  .ToArray();
                        foreach (var method in methods)
                        {
                            // call method
                            AddCall(method.Name, ref idx, method, program);

                            // add symbol used
                            dllImportAttribute = method.GetCustomAttribute <DllImportAttribute>();
                            if (dllImportAttribute != null)
                            {
                                symbolsUsedByDotnet.Add(dllImportAttribute.EntryPoint);
                            }
                        }
                    }

                    // If the function calls a private function it is named "_{function}"
                    methods = typeof(LibC).GetMethods(BindingFlags.Static | BindingFlags.NonPublic)
                              .Where(mi => mi.Name == $"_{functionName}")
                              .ToArray();
                    foreach (var method in methods)
                    {
                        dllImportAttribute = method.GetCustomAttribute <DllImportAttribute>();
                        if (dllImportAttribute != null)
                        {
                            // add symbol used
                            symbolsUsedByDotnet.Add(dllImportAttribute.EntryPoint);
                        }
                    }
                }
                program.EndMain();

                string elfFile = program.Compile();

                var nativeUsed = ElfReader.GetUndefinedSymbols(elfFile);
                IEnumerable <string> wrongNames  = symbolsUsedByDotnet.Except(nativeUsed);
                IEnumerable <string> actualNames = nativeUsed.Except(symbolsUsedByDotnet);
                Assert.True(wrongNames.Count() == 0,
                            $"Used  : {string.Join(", ", wrongNames)}\nActual: {string.Join(", ", actualNames)}");
            }
        }