diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj
index 676349a80..7ade3618d 100644
--- a/ILSpy/ILSpy.csproj
+++ b/ILSpy/ILSpy.csproj
@@ -54,6 +54,8 @@
+
+
diff --git a/ILSpy/LoadedAssembly.cs b/ILSpy/LoadedAssembly.cs
index ad1dae9dc..320a7f581 100644
--- a/ILSpy/LoadedAssembly.cs
+++ b/ILSpy/LoadedAssembly.cs
@@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
+using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@@ -35,6 +36,8 @@ using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util;
using ICSharpCode.ILSpy.Options;
+using K4os.Compression.LZ4;
+
#nullable enable
namespace ICSharpCode.ILSpy
@@ -323,6 +326,15 @@ namespace ICSharpCode.ILSpy
{
loadAssemblyException = ex;
}
+ // Maybe its a compressed Xamarin/Mono assembly, see https://github.com/xamarin/xamarin-android/pull/4686
+ try
+ {
+ return LoadCompressedAssembly(fileName);
+ }
+ catch (InvalidDataException)
+ {
+ // Not a compressed module, try other options below
+ }
// If it's not a .NET module, maybe it's a single-file bundle
var bundle = LoadedPackage.FromBundle(fileName);
if (bundle != null)
@@ -365,6 +377,42 @@ namespace ICSharpCode.ILSpy
return new LoadResult(module);
}
+ LoadResult LoadCompressedAssembly(string fileName)
+ {
+ const uint CompressedDataMagic = 0x5A4C4158; // Magic used for Xamarin compressed module header ('XALZ', little-endian)
+ using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
+ using (var fileReader = new BinaryReader(fileStream))
+ {
+ // Read compressed file header
+ var magic = fileReader.ReadUInt32();
+ if (magic != CompressedDataMagic)
+ throw new InvalidDataException($"Xamarin compressed module header magic {magic} does not match expected {CompressedDataMagic}");
+ _ = fileReader.ReadUInt32(); // skip index into descriptor table, unused
+ int uncompressedLength = (int)fileReader.ReadUInt32();
+ int compressedLength = (int)fileStream.Length; // Ensure we read all of compressed data
+ ArrayPool pool = ArrayPool.Shared;
+ var src = pool.Rent(compressedLength);
+ var dst = pool.Rent(uncompressedLength);
+ try
+ {
+ // fileReader stream position is now at compressed module data
+ fileStream.Read(src, 0, compressedLength);
+ // Decompress
+ LZ4Codec.Decode(src, 0, compressedLength, dst, 0, uncompressedLength);
+ // Load module from decompressed data buffer
+ using (var uncompressedStream = new MemoryStream(dst, writable: false))
+ {
+ return LoadAssembly(uncompressedStream, PEStreamOptions.PrefetchEntireImage);
+ }
+ }
+ finally
+ {
+ pool.Return(dst);
+ pool.Return(src);
+ }
+ }
+ }
+
IDebugInfoProvider? LoadDebugInfo(PEFile module)
{
if (DecompilerSettingsPanel.CurrentDecompilerSettings.UseDebugSymbols)
diff --git a/doc/third-party-notices.txt b/doc/third-party-notices.txt
index 39961ecc9..3f54b3b86 100644
--- a/doc/third-party-notices.txt
+++ b/doc/third-party-notices.txt
@@ -415,6 +415,34 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+License Notice for K4os.Compression.LZ4 (part of ILSpy)
+---------------------------
+
+https://github.com/MiloszKrajewski/K4os.Compression.LZ4/blob/master/LICENSE
+
+MIT License
+
+Copyright (c) 2017 Milosz Krajewski
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+
License Notice for LightJson (part of ICSharpCode.Decompiler)
---------------------------