Skip to content
This repository was archived by the owner on Nov 16, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Agents/Xamarin.Interactive.Mac/NativeExceptionHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ static readonly IntPtr objCExceptionPreprocessorFnptr

static IntPtr ObjCExceptionPreprocessor (IntPtr exceptionPtr)
{
throw new TrappedNativeException (Runtime.GetNSObject<NSException> (exceptionPtr));
throw new TrappedNativeException (ObjCRuntime.Runtime.GetNSObject<NSException> (exceptionPtr));
}

public static IDisposable Trap ()
Expand Down
2 changes: 1 addition & 1 deletion Agents/Xamarin.Interactive.iOS/NativeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public static UIWindow GetStatusBarWindow (this UIApplication app)
return null;

var ptr = IntPtr_objc_msgSend (app.Handle, Selectors.statusBarWindow.Handle);
return ptr != IntPtr.Zero ? (UIWindow)Runtime.GetNSObject (ptr) : null;
return ptr != IntPtr.Zero ? (UIWindow)ObjCRuntime.Runtime.GetNSObject (ptr) : null;
}

public static void TryHideStatusClockView (this UIApplication app)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ public Task<TargetCompilationConfiguration> CreateEvaluationContextAsync (
var globalStateObject = CreateGlobalState ();

targetCompilationConfiguration = targetCompilationConfiguration.With (
runtime: Runtime.CurrentProcessRuntime,
defaultImports: defaultImports);

targetCompilationConfiguration = PrepareTargetCompilationConfiguration (
Expand Down
242 changes: 242 additions & 0 deletions Agents/Xamarin.Interactive/CodeAnalysis/Resolving/DllMap.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Xml;

namespace Xamarin.Interactive.CodeAnalysis.Resolving
{
sealed class DllMap : IEnumerable<KeyValuePair<DllMap.Entity, DllMap.Entity>>
{
public struct Entity : IEquatable<Entity>
{
public string LibraryName { get; }
public string SymbolName { get; }

public Entity (
string libraryName,
string symbolName = null)
{
LibraryName = libraryName;
SymbolName = symbolName;
}

public bool Equals (Entity other)
=> LibraryName == other.LibraryName && SymbolName == other.SymbolName;

public override bool Equals (object obj)
=> obj is Entity entity && Equals (entity);

public override int GetHashCode ()
=> Hash.Combine (LibraryName, SymbolName);

public override string ToString ()
=> $"({LibraryName ?? "(null)"}, {SymbolName ?? "(null)"})";
}

internal struct Filter
{
public string OperatingSystem { get; }
public string Cpu { get; }
public string WordSize { get; }

public Filter (
string operatingSystem,
string cpu,
string wordSize)
{
OperatingSystem = operatingSystem;
Cpu = cpu;
WordSize = wordSize;
}

public bool Matches (Filter targetFilter)
{
if (OperatingSystem != null &&
targetFilter.OperatingSystem != null &&
!Matches (targetFilter.OperatingSystem, OperatingSystem))
return false;

if (Cpu != null &&
targetFilter.Cpu != null &&
!Matches (targetFilter.Cpu, Cpu))
return false;

if (WordSize != null &&
targetFilter.WordSize != null &&
!Matches (targetFilter.WordSize, WordSize))
return false;

return true;
}

static bool Matches (string value, string predicate)
{
if (string.IsNullOrEmpty (predicate) || string.IsNullOrEmpty (value))
return false;

var invert = false;

if (predicate [0] == '!') {
invert = true;
predicate = predicate.Substring (1);
}

foreach (var predicateItem in predicate.Split (',')) {
if (predicateItem == value)
return !invert;
}

return invert;
}
}

readonly Filter targetFilter;
readonly Dictionary<Entity, Entity> map = new Dictionary<Entity, Entity> ();

public DllMap () : this (Runtime.CurrentProcessRuntime)
{
}

public DllMap (Runtime targetRuntime)
{
var os = targetRuntime.OSPlatform.ToString ().ToLowerInvariant ();

string cpu = null;
string wordSize = null;
switch (targetRuntime.Architecture) {
case Architecture.X86:
cpu = "x86";
wordSize = "32";
break;
case Architecture.X64:
cpu = "x86-64";
wordSize = "64";
break;
case Architecture.Arm:
cpu = "arm";
wordSize = "32";
break;
case Architecture.Arm64:
cpu = "armv8";
wordSize = "64";
break;
}

targetFilter = new Filter (os, cpu, wordSize);
}

public bool TryMap (Entity source, out Entity target)
{
if (!map.TryGetValue (source, out target) &&
!map.TryGetValue (new Entity (source.LibraryName), out target)) {
target = source;
return false;
}

target = new Entity (target.LibraryName, target.SymbolName ?? source.SymbolName);
return true;
}

public bool TryMap (Entity source, string basePath, out Entity target)
{
if (basePath == null)
throw new ArgumentNullException (nameof (basePath));

if (TryMap (source, out target)) {
target = new Entity (
Path.Combine (basePath, target.LibraryName),
target.SymbolName);
return true;
}

return false;
}

public DllMap Add (Entity source, Entity target)
{
map.Add (source, target);
return this;
}

public DllMap LoadXml (string configurationXml)
{
var document = new XmlDocument ();
document.LoadXml (configurationXml);
return Load (document);
}

public DllMap Load (string configurationFile)
{
var document = new XmlDocument ();
document.Load (configurationFile);
return Load (document);
}

public DllMap Load (XmlDocument document)
{
if (document == null)
throw new ArgumentNullException (nameof (document));

if (document.DocumentElement == null)
throw new ArgumentException (
"document is not loaded or has no root element",
nameof (document));

if (document.DocumentElement.Name != "configuration")
return this;

string GetAttribute (XmlElement elem, string attributeName)
{
var value = elem.GetAttribute (attributeName);
return string.IsNullOrEmpty (value) ? null : value;
}

Filter CreateFilter (XmlElement elem)
=> new Filter (
GetAttribute (elem, "os"),
GetAttribute (elem, "cpu"),
GetAttribute (elem, "wordsize"));

foreach (var node in document.DocumentElement.ChildNodes) {
if (node is XmlElement elem && elem.Name == "dllmap") {
if (!CreateFilter (elem).Matches (targetFilter))
continue;

var sourceLibrary = GetAttribute (elem, "dll");
var targetLibrary = GetAttribute (elem, "target");

foreach (var childNode in elem.ChildNodes) {
if (childNode is XmlElement childElem && childElem.Name == "dllentry") {
if (!CreateFilter (childElem).Matches (targetFilter))
continue;

var symbolTargetLibrary = GetAttribute (childElem, "dll") ?? targetLibrary;
var sourceSymbol = GetAttribute (childElem, "name");
var targetSymbol = GetAttribute (childElem, "target");

if (symbolTargetLibrary != null)
map [new Entity (sourceLibrary, sourceSymbol)]
= new Entity (symbolTargetLibrary, targetSymbol);
}
}

if (!elem.HasChildNodes && targetLibrary != null)
map [new Entity (sourceLibrary)] = new Entity (targetLibrary);
}
}

return this;
}

public IEnumerator<KeyValuePair<Entity, Entity>> GetEnumerator ()
=> map.GetEnumerator ();

IEnumerator IEnumerable.GetEnumerator ()
=> GetEnumerator ();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public sealed class TargetCompilationConfiguration
public static TargetCompilationConfiguration CreateInitialForCompilationWorkspace (
IReadOnlyList<string> assemblySearchPaths = null)
=> new TargetCompilationConfiguration (
default,
default,
HostEnvironment.OS,
default,
Expand All @@ -27,6 +28,7 @@ public static TargetCompilationConfiguration CreateInitialForCompilationWorkspac
new List<string> (assemblySearchPaths ?? Array.Empty<string> ()),
default);

public Runtime Runtime { get; }
public Sdk Sdk { get; }
internal HostOS CompilationOS { get; }
public EvaluationContextId EvaluationContextId { get; }
Expand All @@ -39,6 +41,7 @@ public static TargetCompilationConfiguration CreateInitialForCompilationWorkspac

[JsonConstructor]
TargetCompilationConfiguration (
Runtime runtime,
Sdk sdk,
HostOS compilationOS,
EvaluationContextId evaluationContextId,
Expand All @@ -49,6 +52,7 @@ public static TargetCompilationConfiguration CreateInitialForCompilationWorkspac
IReadOnlyList<string> assemblySearchPaths,
bool includePEImagesInDependencyResolution)
{
Runtime = runtime;
Sdk = sdk;
CompilationOS = compilationOS;
EvaluationContextId = evaluationContextId;
Expand All @@ -61,6 +65,7 @@ public static TargetCompilationConfiguration CreateInitialForCompilationWorkspac
}

internal TargetCompilationConfiguration With (
Optional<Runtime> runtime = default,
Optional<Sdk> sdk = default,
Optional<HostOS> compilationOS = default,
Optional<EvaluationContextId> evaluationContextId = default,
Expand All @@ -71,6 +76,7 @@ internal TargetCompilationConfiguration With (
Optional<IReadOnlyList<string>> assemblySearchPaths = default,
Optional<bool> includePEImagesInDependencyResolution = default)
=> new TargetCompilationConfiguration (
runtime.GetValueOrDefault (Runtime),
sdk.GetValueOrDefault (Sdk),
compilationOS.GetValueOrDefault (CompilationOS),
evaluationContextId.GetValueOrDefault (EvaluationContextId),
Expand Down
Loading