Added preliminary support for Apple Mach-O executable format

This commit is contained in:
Michael Becker 2015-05-12 16:10:57 -04:00
parent 8b8a0c18f0
commit db69cc2714
8 changed files with 598 additions and 2 deletions

View File

@ -2,7 +2,7 @@
<UniversalEditor Version="4.0">
<Associations>
<Association>
<!-- Associate the Chunked ObjectModel with the UXT DataFormats and the FileSystem Editor -->
<!-- Associate the Executable ObjectModel with the Microsoft MZ executable DataFormats and the Executable Editor -->
<Filters>
<Filter Title="Microsoft executable">
<FileNameFilters>
@ -12,7 +12,7 @@
<FileNameFilter>*.rll</FileNameFilter>
<FileNameFilter>*.fon</FileNameFilter>
<FileNameFilter>*.olb</FileNameFilter>
<FileNameFilter>*.tlb"</FileNameFilter>
<FileNameFilter>*.tlb</FileNameFilter>
</FileNameFilters>
<MagicByteSequences>
<MagicByteSequence>
@ -28,5 +28,58 @@
<DataFormat TypeName="UniversalEditor.DataFormats.Executable.Microsoft.MicrosoftExecutableDataFormat" />
</DataFormats>
</Association>
<Association>
<Filters>
<Filter Title="Executable and Linkable Format">
<FileNameFilters>
<FileNameFilter>*.axf</FileNameFilter>
<FileNameFilter>*.bin</FileNameFilter>
<FileNameFilter>*.elf</FileNameFilter>
<FileNameFilter>*.o</FileNameFilter>
<FileNameFilter>*.prx</FileNameFilter>
<FileNameFilter>*.puff</FileNameFilter>
<FileNameFilter>*.so</FileNameFilter>
</FileNameFilters>
<MagicByteSequences>
<MagicByteSequence>
<MagicByte Type="Hexadecimal">7F</MagicByte>
<MagicByte Type="String">ELF</MagicByte>
</MagicByteSequence>
</MagicByteSequences>
</Filter>
</Filters>
<ObjectModels>
<ObjectModel TypeName="UniversalEditor.ObjectModels.Executable.ExecutableObjectModel" />
</ObjectModels>
<DataFormats>
<DataFormat TypeName="UniversalEditor.DataFormats.Executable.Microsoft.MicrosoftExecutableDataFormat" />
</DataFormats>
</Association>
<Association>
<Filters>
<Filter Title="Apple Mach-O executable">
<FileNameFilters>
<FileNameFilter>*.dylib</FileNameFilter>
<FileNameFilter>*.bundle</FileNameFilter>
</FileNameFilters>
<MagicByteSequences>
<MagicByteSequence>
<!-- normal endianness -->
<MagicByte Type="Hexadecimal">FEEDFACE</MagicByte>
</MagicByteSequence>
<MagicByteSequence>
<!-- reverse endianness -->
<MagicByte Type="Hexadecimal">CEFAEDFE</MagicByte>
</MagicByteSequence>
</MagicByteSequences>
</Filter>
</Filters>
<ObjectModels>
<ObjectModel TypeName="UniversalEditor.ObjectModels.Executable.ExecutableObjectModel" />
</ObjectModels>
<DataFormats>
<DataFormat TypeName="UniversalEditor.DataFormats.Executable.Microsoft.MicrosoftExecutableDataFormat" />
</DataFormats>
</Association>
</Associations>
</UniversalEditor>

View File

@ -0,0 +1,211 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.Executable.Apple.MachO
{
/// <summary>
/// Machine subtypes
/// </summary>
public enum MachOCpuSubType
{
// VAX subtypes (these do *not* necessary conform to the actual cpu ID assigned by DEC
// available via the SID register,.
VAX_780 = 1,
VAX_785 = 2,
VAX_750 = 3,
VAX_730 = 4,
UVAX_I = 5,
UVAX_II = 6,
VAX_8200 = 7,
VAX_8500 = 8,
VAX_8600 = 9,
VAX_8650 = 10,
VAX_8800 = 11,
UVAX_III = 12,
// Alpha subtypes (these do *not* necessary conform to the actual cpu ID assigned by DEC
// available via the SID register,.
AlphaADU = 1,
DEC_4000 = 2,
DEC_7000 = 3,
DEC_3000_500 = 4,
DEC_3000_400 = 5,
DEC_10000 = 6,
DEC_3000_300 = 7,
DEC_2000_300 = 8,
DEC_2100_A500 = 9,
DEC_AXPVME_64 = 10,
/* #define DEC_MORGAN = 11, */
/* cancelled */
DEC_AXPPCI_33 = 11,
DEC_AVANTI = 13,
DEC_MUSTANG = 14,
DEC_800_5 = 15,
DEC_21000_800 = 16,
DEC_1000 = 17,
DEC_21000_900 = 18,
EB66 = 19,
EB64P = 20,
ALPHABOOK = 21,
DEC_4100 = 22,
DEC_EV45_PBP = 23,
DEC_2100A_A500 = 24,
EB164 = 26,
DEC_1000A = 27,
DEC_ALPHAVME_224 = 28,
DEC_550 = 30,
DEC_EV56_PBP = 32,
DEC_ALPHAVME_320 = 33,
DEC_6600 = 34,
ALPHA_WILDFIRE = 35,
DMCC_EV6 = 37,
/*
* ROMP subtypes.
*/
RT_PC = 1,
RT_APC = 2,
RT_135 = 3,
/*
* 68020 subtypes.
*/
SUN3_50 = 1,
SUN3_160 = 2,
SUN3_260 = 3,
SUN3_110 = 4,
SUN3_60 = 5,
HP_320 = 6,
/* 16.67 Mhz HP 300 series, custom MMU [HP 320] */
HP_330 = 7,
/* 16.67 Mhz HP 300 series, MC68851 MMU [HP 318,319,330,349] */
HP_350 = 8,
/* 25.00 Mhz HP 300 series, custom MMU [HP 350] */
APOLLO_3000 = 9,
APOLLO_4000 = 10,
/*
* 32032/32332/32532 subtypes.
*/
MMAX_DPC = 1, /* 032 CPU */
SQT = 2,
MMAX_APC_FPU = 3, /* 32081 FPU */
MMAX_APC_FPA = 4, /* Weitek FPA */
MMAX_XPC_FPU = 5, /* 532 +'381 FPU */
MMAX_XPC_FPA = 6, /* 532 +580+WTL3164 */
// MMAX_RES1 /* Reserved */
// MMAX_RES2 /* Reserved */
/*
* 80386 subtypes.
*/
AT386 = 1,
EXL = 2,
SQT86 = 3,
/*
* Mips subtypes.
*/
MIPS_R2300 = 1,
MIPS_R2600 = 2,
MIPS_R2800 = 3,
MIPS_R2000a = 4,
/* dgd -- addition for 3max support */
MIPS_R3000a = 5,
/*
* MC68030 subtypes
*/
/// <summary>
/// NeXt thinks MC68030 is 6 rather than 9
/// </summary>
NeXT = 1,
HP_340 = 2,
/* 16.67 Mhz HP 300 series [HP 332,340] */
HP_360 = 3,
/* 25.00 Mhz HP 300 series [HP 360] */
HP_370 = 4,
/* 33.33 Mhz HP 300 series [HP 370] */
APOLLO_2500 = 5,
APOLLO_3500 = 6,
APOLLO_4500 = 7,
/*
* PA_RISC subtypes Hewlett-Packard HP-PA family of
* risc processors 800 series workstations.
* Port done by Hewlett-Packard
*/
PA_RISC_840 = 0x004,
PA_RISC_825 = 0x008,
PA_RISC_835 = 0x00a,
PA_RISC_850 = 0x00c,
PA_RISC_855 = 0x081,
PA_RISC_810 = 0x100,
PA_RISC_815 = 0x103,
PA_RISC_710 = 0x300,
PA_RISC_720 = 0x200,
PA_RISC_730 = 0x202,
PA_RISC_750 = 0x201,
/*
* Acorn subtypes - Acorn Risc Machine port done by
* Olivetti System Software Laboratory
*/
ARM_A500_ARCH = 1,
ARM_A500 = 2,
ARM_A440 = 3,
ARM_M4 = 4,
ARM_A680 = 5,
/*
* MC88000 subtypes - Encore doing port.
*/
MMAX_JPC = 1,
/*
* Sun4 subtypes - port done at CMU
*/
Sun4_All = 0,
Sun4_260 = 1,
Sun4_110 = 2,
Sparc_All = 0,
// PowerPC subtypes
PowerPC_All = 0,
PowerPC_601 = 1,
PowerPC_602 = 2,
PowerPC_603 = 3,
PowerPC_603e = 4,
PowerPC_603ev = 5,
PowerPC_604 = 6,
PowerPC_604e = 7,
PowerPC_620 = 8,
PowerPC_750 = 9,
PowerPC_7400 = 10,
PowerPC_7450 = 11,
PowerPC_970 = 100,
// VEO subtypes
// Note: the VEO_ALL will likely change over time to be defined as one of the specific
// subtypes.
VEO_1 = 1,
VEO_2 = 2,
VEO_3 = 3,
VEO_4 = 4,
VEO_ALL = VEO_2
}
}

View File

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.Executable.Apple.MachO
{
public enum MachOCpuType
{
Any = -1,
VAX = 1,
ROMP = 2,
MC68020 = 3,
NS32032 = 4,
NS32332 = 5,
NS32532 = 6,
X86 = 7,
MIPS = 8,
MC68030 = 9,
MC68040 = 10,
HPPA = 11,
ARM = 12,
MC88000 = 13,
SPARC = 14,
I860 = 15,
ALPHA = 16,
POWERPC = 18,
X86_64 = 0x01000007
}
}

View File

@ -0,0 +1,140 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UniversalEditor.IO;
using UniversalEditor.ObjectModels.Executable;
namespace UniversalEditor.DataFormats.Executable.Apple.MachO
{
public class MachODataFormat : DataFormat
{
private static DataFormatReference _dfr = null;
protected override DataFormatReference MakeReferenceInternal()
{
if (_dfr == null)
{
_dfr = base.MakeReferenceInternal();
_dfr.Capabilities.Add(typeof(ExecutableObjectModel), DataFormatCapabilities.All);
_dfr.Sources.Add("https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/MachORuntime/index.html#//apple_ref/c/tag/mach_header");
}
return _dfr;
}
private MachOCpuType mvarCpuType = MachOCpuType.X86;
/// <summary>
/// The architecture you intend to use the file on.
/// </summary>
public MachOCpuType CpuType { get { return mvarCpuType; } set { mvarCpuType = value; } }
private MachOCpuSubType mvarCpuSubType = MachOCpuSubType.PowerPC_All;
public MachOCpuSubType CpuSubType { get { return mvarCpuSubType; } set { mvarCpuSubType = value; } }
private MachOFileType mvarFileType = MachOFileType.Executable;
public MachOFileType FileType { get { return mvarFileType; } set { mvarFileType = value; } }
private MachOFlags mvarFlags = MachOFlags.None;
public MachOFlags Flags { get { return mvarFlags; } set { mvarFlags = value; } }
protected override void LoadInternal(ref ObjectModel objectModel)
{
ExecutableObjectModel exe = (objectModel as ExecutableObjectModel);
if (exe == null) throw new ObjectModelNotSupportedException();
Reader reader = base.Accessor.Reader;
// An integer containing a value identifying this file as a 32-bit Mach-O file. Use the
// constant MH_MAGIC if the file is intended for use on a CPU with the same endianness
// as the computer on which the compiler is running. The constant MH_CIGAM can be used
// when the byte ordering scheme of the target machine is the reverse of the host CPU.
MachOMagic magic = (MachOMagic)reader.ReadUInt32();
// set up endianness
switch (magic)
{
case MachOMagic.MachOBigEndian:
{
reader.Endianness = Endianness.BigEndian;
break;
}
case MachOMagic.MachOLittleEndian:
{
reader.Endianness = Endianness.LittleEndian;
break;
}
}
// parse the format
switch (magic)
{
case MachOMagic.MachOBigEndian:
case MachOMagic.MachOLittleEndian:
{
mvarCpuType = (MachOCpuType)reader.ReadInt32();
mvarCpuSubType = (MachOCpuSubType)reader.ReadInt32();
mvarFileType = (MachOFileType)reader.ReadInt32();
uint loadCommandCount = reader.ReadUInt32();
uint loadCommandAreaSize = reader.ReadUInt32();
mvarFlags = (MachOFlags)reader.ReadInt32();
break;
}
default:
{
throw new InvalidDataFormatException("The executable format 0x" + ((uint)magic).ToString("X") + " is not supported");
}
}
}
protected override void SaveInternal(ObjectModel objectModel)
{
ExecutableObjectModel exe = (objectModel as ExecutableObjectModel);
if (exe == null) throw new ObjectModelNotSupportedException();
Writer writer = base.Accessor.Writer;
MachOMagic magic = MachOMagic.MachOBigEndian;
writer.WriteUInt32((uint)magic);
switch (magic)
{
case MachOMagic.MachOBigEndian:
{
writer.Endianness = Endianness.BigEndian;
break;
}
case MachOMagic.MachOLittleEndian:
{
writer.Endianness = Endianness.LittleEndian;
break;
}
}
switch (magic)
{
case MachOMagic.MachOBigEndian:
case MachOMagic.MachOLittleEndian:
{
writer.WriteInt32((int)mvarCpuType);
writer.WriteInt32((int)mvarCpuSubType);
writer.WriteInt32((int)mvarFileType);
uint loadCommandCount = 0;
uint loadCommandSize = 0;
writer.WriteUInt32(loadCommandCount);
writer.WriteUInt32(loadCommandSize);
writer.WriteInt32((int)mvarFlags);
break;
}
default:
{
throw new InvalidDataFormatException("The executable format 0x" + ((uint)magic).ToString("X") + " is not supported");
}
}
}
}
}

View File

@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.Executable.Apple.MachO
{
public enum MachOFileType
{
/// <summary>
/// Used for intermediate object files. It is a very compact format containing all its
/// sections in one segment. The compiler and assembler usually create one Object file
/// for each source code file. By convention, the file name extension for this format
/// is .o.
/// </summary>
Object = 0x1,
/// <summary>
/// Used by standard executable programs.
/// </summary>
Executable = 0x2,
FVMLibrary = 0x3,
/// <summary>
/// Used to store core files, which are traditionally created when a program crashes. Core
/// files store the entire address space of a process at the time it crashed. You can later
/// run gdb on the core file to figure out why the crash occurred.
/// </summary>
Core = 0x4,
/// <summary>
/// Used for special-purpose programs that are not loaded by the OS X kernel, such as
/// programs burned into programmable ROM chips. Do not confuse this file type with the
/// <see cref="Prebound"/> flag, which is a flag that the static linker sets in the header
/// structure to mark a prebound image.
/// </summary>
Preload = 0x5,
/// <summary>
/// For dynamic shared libraries. It contains some additional tables to support multiple
/// modules. By convention, the file name extension for this format is .dylib, except for
/// the main shared library of a framework, which does not usually have a file name
/// extension.
/// </summary>
DynamicLibrary = 0x6,
/// <summary>
/// The type of a dynamic linker shared library. This is the type of the dyld file.
/// </summary>
DynamicLinkerLibrary = 0x7,
/// <summary>
/// Typically used by code that you load at runtime (typically called bundles or plug-ins).
/// By convention, the file name extension for this format is .bundle.
/// </summary>
Bundle = 0x8,
DynamicLibraryStub = 0x9,
/// <summary>
/// Designates files that store symbol information for a corresponding binary file.
/// </summary>
DebuggingSymbols = 0xA
}
}

View File

@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.Executable.Apple.MachO
{
[Flags()]
public enum MachOFlags
{
None = 0x000000,
/// <summary>
/// The object file contained no undefined references when it was built.
/// </summary>
NoUndefinedReferences = 0x000001,
/// <summary>
/// The object file is the output of an incremental link against a base file and cannot be
/// linked again.
/// </summary>
IncrementalLink = 0x000002,
/// <summary>
/// The file is input for the dynamic linker and cannot be statically linked again.
/// </summary>
DynamicLink = 0x000004,
/// <summary>
/// The dynamic linker should bind the undefined references when the file is loaded.
/// </summary>
BindAtLoad = 0x000008,
/// <summary>
/// The files undefined references are prebound.
/// </summary>
Prebound = 0x000010,
/// <summary>
/// The file has its read-only and read-write segments split.
/// </summary>
SplitSegments = 0x000020,
LazyInitialization = 0x000040,
/// <summary>
/// The image is using two-level namespace bindings.
/// </summary>
TwoLevelNamespace = 0x000080,
/// <summary>
/// The executable is forcing all images to use flat namespace bindings.
/// </summary>
ForceFlatNamespace = 0x000100,
/// <summary>
/// This umbrella guarantees there are no multiple definitions of symbols in its subimages.
/// As a result, the two-level namespace hints can always be used.
/// </summary>
NoMultipleDefinitions = 0x000200,
/// <summary>
/// The dynamic linker doesnt notify the prebinding agent about this executable.
/// </summary>
NoFixPrebinding = 0x000400,
/// <summary>
/// This file is not prebound but can have its prebinding redone. Used only when
/// Prebound is not set.
/// </summary>
Prebindable = 0x000800,
/// <summary>
/// Indicates that this binary binds to all two-level namespace modules of its dependent
/// libraries. Used only when Prebindable and TwoLevelNamespace are set.
/// </summary>
AllModulesBound = 0x001000,
/// <summary>
/// This file has been canonicalized by unprebinding—clearing prebinding information from
/// the file. See the redo_prebinding man page for details.
/// </summary>
Canonicalized = 0x004000,
WeakDefines = 0x008000,
BindsToWeak = 0x010000,
RootSafe = 0x040000,
SetUIDSafe = 0x080000,
NoReExportedDynamicLibraries = 0x100000,
PIE = 0x200000,
/// <summary>
/// The sections of the object file can be divided into individual blocks. These blocks are
/// dead-stripped if they are not used by other code. See Linking for details.
/// </summary>
SubsectionsViaSymbols = 0x0000
}
}

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.DataFormats.Executable.Apple.MachO
{
public enum MachOMagic : uint
{
MachOBigEndian = 0xFEEDFACE,
MachOLittleEndian = 0xCEFAEDFE,
FatBinaryBigEndian = 0xCAFEBABE,
FatBinaryLittleEndian = 0xBEBAFECA,
MachO64BigEndian = 0xFEEDFACF,
MachO64LittleEndian = 0xCFFAEDFE
}
}

View File

@ -36,6 +36,12 @@
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="DataFormats\Executable\Apple\MachO\MachOCpuSubType.cs" />
<Compile Include="DataFormats\Executable\Apple\MachO\MachOCpuType.cs" />
<Compile Include="DataFormats\Executable\Apple\MachO\MachODataFormat.cs" />
<Compile Include="DataFormats\Executable\Apple\MachO\MachOFileType.cs" />
<Compile Include="DataFormats\Executable\Apple\MachO\MachOFlags.cs" />
<Compile Include="DataFormats\Executable\Apple\MachO\MachOMagic.cs" />
<Compile Include="DataFormats\Executable\ELF\ELFCapacity.cs" />
<Compile Include="DataFormats\Executable\ELF\ELFDataFormat.cs" />
<Compile Include="DataFormats\Executable\ELF\ELFEncoding.cs" />