Skip to content

Commit

Permalink
Few cleanups.
Browse files Browse the repository at this point in the history
Only Ignore references to JavaModules.
  • Loading branch information
wasabii committed Mar 11, 2024
1 parent f6bd4ec commit fdfa1b5
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 53 deletions.
4 changes: 2 additions & 2 deletions src/IKVM.Runtime/DynamicClassLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ private static SerializationInfo ToInfo(byte[] publicKey)

public static ModuleBuilder CreateModuleBuilder(RuntimeContext context)
{
AssemblyName name = new AssemblyName();
var name = new AssemblyName();
name.Name = "ikvm_dynamic_assembly__" + (uint)Environment.TickCount;
return CreateModuleBuilder(context, name);
}
Expand All @@ -523,7 +523,7 @@ public static ModuleBuilder CreateModuleBuilder(RuntimeContext context, Assembly
var now = DateTime.Now;
name.Version = new Version(now.Year, (now.Month * 100) + now.Day, (now.Hour * 100) + now.Minute, (now.Second * 1000) + now.Millisecond);
var attribs = new List<CustomAttributeBuilder>();
AssemblyBuilderAccess access = AssemblyBuilderAccess.Run;
var access = AssemblyBuilderAccess.Run;

#if NETFRAMEWORK
if (!AppDomain.CurrentDomain.IsFullyTrusted)
Expand Down
16 changes: 10 additions & 6 deletions src/IKVM.Runtime/RuntimeJavaType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -867,11 +867,15 @@ internal void SetFields(RuntimeJavaField[] fields)
internal virtual string SigName => "L" + Name + ";";

// returns true iff wrapper is allowed to access us
internal bool IsAccessibleFrom(RuntimeJavaType wrapper)

/// <summary>
/// Returns <c>true</c> if the specified type is able to access us.
/// </summary>
/// <param name="wrapper"></param>
/// <returns></returns>
internal bool IsAccessibleFrom(RuntimeJavaType other)
{
return IsPublic
|| (IsInternal && InternalsVisibleTo(wrapper))
|| IsPackageAccessibleFrom(wrapper);
return IsPublic || (IsInternal && InternalsVisibleTo(other)) || IsPackageAccessibleFrom(other);
}

internal bool InternalsVisibleTo(RuntimeJavaType wrapper)
Expand All @@ -884,14 +888,14 @@ internal virtual bool IsPackageAccessibleFrom(RuntimeJavaType wrapper)
if (MatchingPackageNames(name, wrapper.name))
{
#if IMPORTER
CompilerClassLoader ccl = GetClassLoader() as CompilerClassLoader;
if (ccl != null)
if (GetClassLoader() is CompilerClassLoader ccl)
{
// this is a hack for multi target -sharedclassloader compilation
// (during compilation we have multiple CompilerClassLoader instances to represent the single shared runtime class loader)
return ccl.IsEquivalentTo(wrapper.GetClassLoader());
}
#endif

return GetClassLoader() == wrapper.GetClassLoader();
}
else
Expand Down
1 change: 1 addition & 0 deletions src/IKVM.Tools.Importer.Tests/IkvmImporterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public async Task CanImportSimpleTest(string ikvmFramework, string targetFramewo
File.Exists(asm).Should().BeTrue();
new FileInfo(asm).Length.Should().BeGreaterThanOrEqualTo(128);
}

}

}
101 changes: 56 additions & 45 deletions src/IKVM.Tools.Importer/CompilerClassLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ Jeroen Frijters
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Security;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
Expand Down Expand Up @@ -125,19 +124,6 @@ internal AssemblyName GetAssemblyName()
return assemblyBuilder.GetName();
}

private static PermissionSet Combine(PermissionSet p1, PermissionSet p2)
{
if (p1 == null)
{
return p2;
}
if (p2 == null)
{
return p1;
}
return p1.Union(p2);
}

internal ModuleBuilder CreateModuleBuilder()
{
var name = new AssemblyName();
Expand Down Expand Up @@ -273,17 +259,16 @@ private RuntimeJavaType PeerLoad(string name)

private RuntimeJavaType GetTypeWrapperCompilerHook(string name)
{
RemapperTypeWrapper rtw;
if (remapped.TryGetValue(name, out rtw))
if (remapped.TryGetValue(name, out var rtw))
{
return rtw;
}
else
{
Jar.Item itemRef;
if (classes.TryGetValue(name, out itemRef))
if (classes.TryGetValue(name, out var itemRef))
{
classes.Remove(name);

ClassFile f;
try
{
Expand Down Expand Up @@ -326,6 +311,7 @@ private RuntimeJavaType GetTypeWrapperCompilerHook(string name)
break;
}
}

if (!found)
{
f.SetInternal();
Expand Down Expand Up @@ -370,12 +356,14 @@ private RuntimeJavaType GetTypeWrapperCompilerHook(string name)
{
itemRef.MarkAsStub();
}

int pos = f.Name.LastIndexOf('.');
if (pos != -1)
{
string manifestJar = options.IsClassesJar(itemRef.Jar) ? null : itemRef.Jar.Name;
var manifestJar = options.IsClassesJar(itemRef.Jar) ? null : itemRef.Jar.Name;
packages.DefinePackage(f.Name.Substring(0, pos), manifestJar);
}

return tw;
}
catch (ClassFormatError x)
Expand All @@ -396,12 +384,14 @@ private RuntimeJavaType GetTypeWrapperCompilerHook(string name)
{
Context.StaticCompiler.IssueMessage(options, Message.NoClassDefFoundError, name, x.Message);
}

Context.StaticCompiler.IssueMessage(options, Message.ClassNotFound, x.Message);
}
catch (RetargetableJavaException x)
{
Context.StaticCompiler.IssueMessage(options, Message.GenericUnableToCompileError, name, x.GetType().Name, x.Message);
}

Context.StaticCompiler.SuppressWarning(options, Message.ClassNotFound, name);
return null;
}
Expand All @@ -420,57 +410,63 @@ internal bool IsEquivalentTo(RuntimeClassLoader other)
{
return true;
}
CompilerClassLoader ccl = other as CompilerClassLoader;

var ccl = other as CompilerClassLoader;
if (ccl != null && options.sharedclassloader != null && options.sharedclassloader.Contains(ccl))
{
if (!internalsVisibleTo.Contains(ccl))
{
AddInternalsVisibleToAttribute(ccl);
}

return true;
}

return false;
}

internal override bool InternalsVisibleToImpl(RuntimeJavaType wrapper, RuntimeJavaType friend)
{
Debug.Assert(wrapper.GetClassLoader() == this);
RuntimeClassLoader other = friend.GetClassLoader();
var other = friend.GetClassLoader();

// TODO ideally we should also respect InternalsVisibleToAttribute.Annotation here
if (this == other || internalsVisibleTo.Contains(other))
{
return true;
}
CompilerClassLoader ccl = other as CompilerClassLoader;

var ccl = other as CompilerClassLoader;
if (ccl != null)
{
AddInternalsVisibleToAttribute(ccl);
return true;
}

return false;
}

private void AddInternalsVisibleToAttribute(CompilerClassLoader ccl)
{
internalsVisibleTo.Add(ccl);
AssemblyBuilder asm = ccl.assemblyBuilder;
AssemblyName asmName = asm.GetName();
string name = asmName.Name;
byte[] pubkey = asmName.GetPublicKey();

var asm = ccl.assemblyBuilder;
var asmName = asm.GetName();
var name = asmName.Name;

var pubkey = asmName.GetPublicKey();
if (pubkey == null && asmName.KeyPair != null)
{
pubkey = asmName.KeyPair.PublicKey;
}

if (pubkey != null && pubkey.Length != 0)
{
StringBuilder sb = new StringBuilder(name);
var sb = new StringBuilder(name);
sb.Append(", PublicKey=");
foreach (byte b in pubkey)
{
sb.AppendFormat("{0:X2}", b);
}
name = sb.ToString();
}

Context.AttributeHelper.SetInternalsVisibleToAttribute(this.assemblyBuilder, name);
}

Expand Down Expand Up @@ -571,24 +567,15 @@ void Save()
}
}

if (targetIsModule == false)
{
// add IgnoresAccessChecksToAttribute internal type
var iactBuilder = mb.DefineType("System.Runtime.CompilerServices.IgnoresAccessChecksToAttribute", TypeAttributes.Class | TypeAttributes.Sealed, Context.Types.Attribute);
iactBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new[] { Context.Types.String });
Context.AttributeHelper.SetAttributeUsage(iactBuilder, AttributeTargets.Assembly, true);
var iact = iactBuilder.CreateType();
var iactCtor = iact.GetConstructor(new[] { Context.Types.String });

// add IgnoresAccessChecksToAttribute for each referenced assembly, so access to package-private (internal) members is allowed
for (int i = 0; i < referencedAssemblies.Length; i++)
assemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder(iactCtor, new[] { UnicodeUtil.EscapeInvalidSurrogates(referencedAssemblies[i].MainAssembly.FullName) }));
}

// initialize the global functions for the module
mb.CreateGlobalFunctions();

// signify we are creating a Java module
AddJavaModuleAttribute(mb);

// ignore access checks to referenced Java modules
AddIgnoresAccessChecksToAttribute(mb);

// add a package list and export map
if (options.sharedclassloader == null || options.sharedclassloader[0] == this)
{
Expand Down Expand Up @@ -644,6 +631,30 @@ void Save()
}
}

/// <summary>
/// Adds a 'IgnoresAccessChecksToAttribute' type to the assembly, and attributes on the assembly that ignore
/// access checks to all Java modules which are referenced. This ensures package-private references across
/// assemblies are possible.
/// </summary>
/// <param name="mb"></param>
void AddIgnoresAccessChecksToAttribute(ModuleBuilder mb)
{
if (targetIsModule == false)
{
// add IgnoresAccessChecksToAttribute type
var iactBuilder = mb.DefineType("System.Runtime.CompilerServices.IgnoresAccessChecksToAttribute", TypeAttributes.Class | TypeAttributes.Sealed, Context.Types.Attribute);
iactBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new[] { Context.Types.String });
Context.AttributeHelper.SetAttributeUsage(iactBuilder, AttributeTargets.Assembly, true);
var iact = iactBuilder.CreateType();
var iactCtor = iact.GetConstructor(new[] { Context.Types.String });

// add IgnoresAccessChecksToAttribute to each referenced assembly
for (int i = 0; i < referencedAssemblies.Length; i++)
if (Context.AttributeHelper.IsJavaModule(referencedAssemblies[i].MainAssembly.ManifestModule))
assemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder(iactCtor, new[] { UnicodeUtil.EscapeInvalidSurrogates(referencedAssemblies[i].MainAssembly.FullName) }));
}
}

void AddJavaModuleAttribute(ModuleBuilder mb)
{
var typeofJavaModuleAttribute = Context.Resolver.ResolveRuntimeType(typeof(JavaModuleAttribute).FullName);
Expand Down

0 comments on commit fdfa1b5

Please sign in to comment.