public void Include(CIncludes includes) { if (includes.GnuSource) { Define("_GNU_SOURCE"); } Include(includes.Headers); }
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); }
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(); } }
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)}"); } }