Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@

using System.Runtime.InteropServices;

#if HOST_MODEL
namespace Microsoft.NET.HostModel.MachO;
#else
namespace ILCompiler.Reflection.ReadyToRun.MachO;
#endif

/// <summary>
/// The base structure for all load commands in a Mach-O binary.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@

using System.Runtime.InteropServices;

#if HOST_MODEL
namespace Microsoft.NET.HostModel.MachO;
#else
namespace ILCompiler.Reflection.ReadyToRun.MachO;
#endif

/// <summary>
/// The Mach-O header is the first data in a Mach-O file.
Expand All @@ -25,6 +29,7 @@ internal struct MachHeader
public uint SizeOfCommands { get => _magic.ConvertValue(_sizeOfCommands); set => _sizeOfCommands = _magic.ConvertValue(value); }
public bool Is64Bit => _magic is MachMagic.MachHeader64CurrentEndian or MachMagic.MachHeader64OppositeEndian;
public MachFileType FileType => (MachFileType)_magic.ConvertValue((uint)_fileType);
public uint CpuType => _magic.ConvertValue(_cpuType);

public uint ConvertValue(uint value) => _magic.ConvertValue(value);
public ulong ConvertValue(ulong value) => _magic.ConvertValue(value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
using System;
using System.Runtime.InteropServices;

#if HOST_MODEL
namespace Microsoft.NET.HostModel.MachO;
#else
namespace ILCompiler.Reflection.ReadyToRun.MachO;
#endif

/// <summary>
/// A 16 byte buffer used to store names in Mach-O load commands.
Expand All @@ -15,9 +19,11 @@ internal struct NameBuffer
private ulong _nameLower;
private ulong _nameUpper;

private const int BufferLength = 16;

private NameBuffer(ReadOnlySpan<byte> nameBytes)
{
byte[] buffer = new byte[16];
byte[] buffer = new byte[BufferLength];
nameBytes.CopyTo(buffer);

if (BitConverter.IsLittleEndian)
Expand All @@ -34,4 +40,19 @@ private NameBuffer(ReadOnlySpan<byte> nameBytes)

public static NameBuffer __TEXT = new NameBuffer("__TEXT"u8);
public static NameBuffer __LINKEDIT = new NameBuffer("__LINKEDIT"u8);

public unsafe string GetString()
{
fixed (ulong* ptr = &_nameLower)
{
byte* bytePtr = (byte*)ptr;
int length = 0;
while (length < BufferLength && bytePtr[length] != 0)
{
length++;
}

return System.Text.Encoding.UTF8.GetString(bytePtr, length);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@

using System.Runtime.InteropServices;

#if HOST_MODEL
namespace Microsoft.NET.HostModel.MachO;
#else
namespace ILCompiler.Reflection.ReadyToRun.MachO;
#endif

/// <summary>
/// A load command that provides information about a section in a segment.
Expand All @@ -25,5 +29,8 @@ internal readonly struct Section64LoadCommand
private readonly uint _reserved2;
private readonly uint _reserved3;

internal NameBuffer SectionName => _sectionName;
internal ulong GetVMAddress(MachHeader header) => header.ConvertValue(_address);
internal ulong GetSize(MachHeader header) => header.ConvertValue(_size);
internal uint GetFileOffset(MachHeader header) => header.ConvertValue(_fileOffset);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@

using System.Runtime.InteropServices;

#if HOST_MODEL
namespace Microsoft.NET.HostModel.MachO;
#else
namespace ILCompiler.Reflection.ReadyToRun.MachO;
#endif

/// <summary>
/// The structure for the 64-bit segment load command in a Mach-O binary.
Expand All @@ -29,6 +33,7 @@ internal struct Segment64LoadCommand
public ulong GetFileOffset(MachHeader header) => header.ConvertValue(_fileOffset);
public ulong GetFileSize(MachHeader header) => header.ConvertValue(_fileSize);
public void SetFileSize(ulong value, MachHeader header) => _fileSize = header.ConvertValue(value);
public ulong GetVMAddress(MachHeader header) => header.ConvertValue(_address);
public void SetVMSize(ulong value, MachHeader header) => _size = header.ConvertValue(value);
public ulong GetVMSize(MachHeader header) => header.ConvertValue(_size);
public uint GetSectionsCount(MachHeader header) => header.ConvertValue(_numberOfSections);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@

using System.Runtime.InteropServices;

#if HOST_MODEL
namespace Microsoft.NET.HostModel.MachO;
#else
namespace ILCompiler.Reflection.ReadyToRun.MachO;
#endif

/// <summary>
/// A load command with info about the location of the symbol table and string table.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#if HOST_MODEL
namespace Microsoft.NET.HostModel.MachO;
#else
namespace ILCompiler.Reflection.ReadyToRun.MachO;
#endif

internal enum MachFileType : uint
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#if HOST_MODEL
namespace Microsoft.NET.HostModel.MachO;
#else
namespace ILCompiler.Reflection.ReadyToRun.MachO;
#endif

/// <summary>
/// See https://github.com/apple-oss-distributions/cctools/blob/7a5450708479bbff61527d5e0c32a3f7b7e4c1d0/include/mach-o/loader.h#L282 for reference.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#if HOST_MODEL
namespace Microsoft.NET.HostModel.MachO;
#else
namespace ILCompiler.Reflection.ReadyToRun.MachO;
#endif

/// <summary>
/// See https://github.com/apple-oss-distributions/cctools/blob/7a5450708479bbff61527d5e0c32a3f7b7e4c1d0/tests/include/MachO/MachHeader.pm#L12 for definitions.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
using System.Buffers.Binary;
using System.IO;

#if HOST_MODEL
namespace Microsoft.NET.HostModel.MachO;
#else
namespace ILCompiler.Reflection.ReadyToRun.MachO;
#endif

internal static class MachMagicExtensions
{
Expand Down
32 changes: 32 additions & 0 deletions src/coreclr/tools/Common/MachO/MachObjectFile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.IO;

#if HOST_MODEL
namespace Microsoft.NET.HostModel.MachO;
#else
namespace ILCompiler.Reflection.ReadyToRun.MachO;
#endif

/// <summary>
/// A managed object containing relevant information for AdHoc signing a Mach-O file.
/// The object is created from a memory mapped file, and a signature can be calculated from the memory mapped file.
/// However, since a memory mapped file cannot be extended, the signature is written to a file stream.
/// </summary>
internal unsafe partial class MachObjectFile
{
public static bool IsMachOImage(string filePath)
{
using (BinaryReader reader = new BinaryReader(File.OpenRead(filePath)))
{
if (reader.BaseStream.Length < 256) // Header size
{
return false;
}
uint magic = reader.ReadUInt32();
return Enum.IsDefined(typeof(MachMagic), magic);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Text;

namespace ILCompiler.DependencyAnalysis
namespace ILCompiler
{
public enum ReadyToRunContainerFormat
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Reflection.PortableExecutable;

namespace ILCompiler.Reflection.ReadyToRun
{
/// <summary>
/// Interface for abstracting binary image reading across different formats (PE, MachO)
/// </summary>
public interface IBinaryImageReader
{
/// <summary>
/// Gets the machine type of the binary image
/// </summary>
Machine Machine { get; }

/// <summary>
/// Gets the operating system of the binary image
/// </summary>
OperatingSystem OperatingSystem { get; }

/// <summary>
/// Gets the image base address
/// </summary>
ulong ImageBase { get; }

/// <summary>
/// Get the entire image content
/// </summary>
ImmutableArray<byte> GetEntireImage();

/// <summary>
/// Get the index in the image byte array corresponding to the RVA
/// </summary>
/// <param name="rva">The relative virtual address</param>
int GetOffset(int rva);

/// <summary>
/// Try to get the ReadyToRun header RVA for this image.
/// </summary>
/// <param name="rva">RVA of the ReadyToRun header if available, 0 when not</param>
/// <param name="isComposite">true when the reader represents a composite ReadyToRun image, false for regular R2R</param>
/// <returns>true when the reader represents a ReadyToRun image (composite or regular), false otherwise</returns>
bool TryGetReadyToRunHeader(out int rva, out bool isComposite);

/// <summary>
/// Creates standalone assembly metadata from the image's embedded metadata.
/// </summary>
/// <returns>Assembly metadata, or null if the image has no embedded metadata</returns>
IAssemblyMetadata GetStandaloneAssemblyMetadata();

/// <summary>
/// Creates manifest assembly metadata from the R2R manifest
/// </summary>
/// <param name="manifestReader">Manifest metadata reader</param>
/// <returns>Manifest assembly metadata</returns>
IAssemblyMetadata GetManifestAssemblyMetadata(System.Reflection.Metadata.MetadataReader manifestReader);

/// <summary>
/// Write out image information using the specified writer
/// </summary>
/// <param name="writer">The writer to use</param>
void DumpImageInformation(TextWriter writer);

/// <summary>
/// Gets the sections (name and size) of the binary image
/// </summary>
Dictionary<string, int> GetSections();

}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>ILCompiler.Reflection.ReadyToRun</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
Expand Down Expand Up @@ -31,6 +31,8 @@
<Compile Include="..\..\Common\Internal\Runtime\ModuleHeaders.cs" Link="Common\ModuleHeaders.cs" />
<Compile Include="..\..\Common\Internal\Runtime\ReadyToRunConstants.cs" Link="Common\ReadyToRunConstants.cs" />
<Compile Include="..\..\Common\Internal\Runtime\ReadyToRunInstructionSet.cs" Link="Common\ReadyToRunInstructionSet.cs" />
<Compile Include="..\..\Common\MachO\**\*.cs" Link="MachO\%(RecursiveDir)%(Filename)%(Extension)" />
<Compile Include="..\..\Common\Pgo\PgoFormat.cs" Link="Common\PgoFormat.cs" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.InteropServices;

namespace ILCompiler.Reflection.ReadyToRun.MachO;

/// <summary>
/// Represents a 64-bit symbol table entry.
/// See https://github.com/apple-oss-distributions/cctools/blob/7a5450708479bbff61527d5e0c32a3f7b7e4c1d0/include/mach-o/nlist.h#L92 for reference.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal readonly struct NList64
{
private readonly uint _stringTableIndex;
private readonly byte _type;
private readonly byte _section;
private readonly ushort _description;
private readonly ulong _value;

public uint GetStringTableIndex(MachHeader header) => header.ConvertValue(_stringTableIndex);
public ulong GetValue(MachHeader header) => header.ConvertValue(_value);
}
Loading
Loading