| // Copyright 2009 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // Mach-O header data structures |
| // Originally at: |
| // http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html (since deleted by Apple) |
| // Archived copy at: |
| // https://web.archive.org/web/20090819232456/http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachORuntime/index.html |
| // For cloned PDF see: |
| // https://github.com/aidansteele/osx-abi-macho-file-format-reference |
| |
| package macho |
| |
| import "strconv" |
| |
| // A FileHeader represents a Mach-O file header. |
| type FileHeader struct { |
| Magic uint32 |
| Cpu Cpu |
| SubCpu uint32 |
| Type Type |
| Ncmd uint32 |
| Cmdsz uint32 |
| Flags uint32 |
| } |
| |
| const ( |
| fileHeaderSize32 = 7 * 4 |
| fileHeaderSize64 = 8 * 4 |
| ) |
| |
| const ( |
| Magic32 uint32 = 0xfeedface |
| Magic64 uint32 = 0xfeedfacf |
| MagicFat uint32 = 0xcafebabe |
| ) |
| |
| // A Type is the Mach-O file type, e.g. an object file, executable, or dynamic library. |
| type Type uint32 |
| |
| const ( |
| TypeObj Type = 1 |
| TypeExec Type = 2 |
| TypeDylib Type = 6 |
| TypeBundle Type = 8 |
| ) |
| |
| var typeStrings = []intName{ |
| {uint32(TypeObj), "Obj"}, |
| {uint32(TypeExec), "Exec"}, |
| {uint32(TypeDylib), "Dylib"}, |
| {uint32(TypeBundle), "Bundle"}, |
| } |
| |
| func (t Type) String() string { return stringName(uint32(t), typeStrings, false) } |
| func (t Type) GoString() string { return stringName(uint32(t), typeStrings, true) } |
| |
| // A Cpu is a Mach-O cpu type. |
| type Cpu uint32 |
| |
| const cpuArch64 = 0x01000000 |
| |
| const ( |
| Cpu386 Cpu = 7 |
| CpuAmd64 Cpu = Cpu386 | cpuArch64 |
| CpuArm Cpu = 12 |
| CpuArm64 Cpu = CpuArm | cpuArch64 |
| CpuPpc Cpu = 18 |
| CpuPpc64 Cpu = CpuPpc | cpuArch64 |
| ) |
| |
| var cpuStrings = []intName{ |
| {uint32(Cpu386), "Cpu386"}, |
| {uint32(CpuAmd64), "CpuAmd64"}, |
| {uint32(CpuArm), "CpuArm"}, |
| {uint32(CpuArm64), "CpuArm64"}, |
| {uint32(CpuPpc), "CpuPpc"}, |
| {uint32(CpuPpc64), "CpuPpc64"}, |
| } |
| |
| func (i Cpu) String() string { return stringName(uint32(i), cpuStrings, false) } |
| func (i Cpu) GoString() string { return stringName(uint32(i), cpuStrings, true) } |
| |
| // A LoadCmd is a Mach-O load command. |
| type LoadCmd uint32 |
| |
| const ( |
| LoadCmdSegment LoadCmd = 0x1 |
| LoadCmdSymtab LoadCmd = 0x2 |
| LoadCmdThread LoadCmd = 0x4 |
| LoadCmdUnixThread LoadCmd = 0x5 // thread+stack |
| LoadCmdDysymtab LoadCmd = 0xb |
| LoadCmdDylib LoadCmd = 0xc // load dylib command |
| LoadCmdDylinker LoadCmd = 0xf // id dylinker command (not load dylinker command) |
| LoadCmdSegment64 LoadCmd = 0x19 |
| LoadCmdRpath LoadCmd = 0x8000001c |
| ) |
| |
| var cmdStrings = []intName{ |
| {uint32(LoadCmdSegment), "LoadCmdSegment"}, |
| {uint32(LoadCmdThread), "LoadCmdThread"}, |
| {uint32(LoadCmdUnixThread), "LoadCmdUnixThread"}, |
| {uint32(LoadCmdDylib), "LoadCmdDylib"}, |
| {uint32(LoadCmdSegment64), "LoadCmdSegment64"}, |
| {uint32(LoadCmdRpath), "LoadCmdRpath"}, |
| } |
| |
| func (i LoadCmd) String() string { return stringName(uint32(i), cmdStrings, false) } |
| func (i LoadCmd) GoString() string { return stringName(uint32(i), cmdStrings, true) } |
| |
| type ( |
| // A Segment32 is a 32-bit Mach-O segment load command. |
| Segment32 struct { |
| Cmd LoadCmd |
| Len uint32 |
| Name [16]byte |
| Addr uint32 |
| Memsz uint32 |
| Offset uint32 |
| Filesz uint32 |
| Maxprot uint32 |
| Prot uint32 |
| Nsect uint32 |
| Flag uint32 |
| } |
| |
| // A Segment64 is a 64-bit Mach-O segment load command. |
| Segment64 struct { |
| Cmd LoadCmd |
| Len uint32 |
| Name [16]byte |
| Addr uint64 |
| Memsz uint64 |
| Offset uint64 |
| Filesz uint64 |
| Maxprot uint32 |
| Prot uint32 |
| Nsect uint32 |
| Flag uint32 |
| } |
| |
| // A SymtabCmd is a Mach-O symbol table command. |
| SymtabCmd struct { |
| Cmd LoadCmd |
| Len uint32 |
| Symoff uint32 |
| Nsyms uint32 |
| Stroff uint32 |
| Strsize uint32 |
| } |
| |
| // A DysymtabCmd is a Mach-O dynamic symbol table command. |
| DysymtabCmd struct { |
| Cmd LoadCmd |
| Len uint32 |
| Ilocalsym uint32 |
| Nlocalsym uint32 |
| Iextdefsym uint32 |
| Nextdefsym uint32 |
| Iundefsym uint32 |
| Nundefsym uint32 |
| Tocoffset uint32 |
| Ntoc uint32 |
| Modtaboff uint32 |
| Nmodtab uint32 |
| Extrefsymoff uint32 |
| Nextrefsyms uint32 |
| Indirectsymoff uint32 |
| Nindirectsyms uint32 |
| Extreloff uint32 |
| Nextrel uint32 |
| Locreloff uint32 |
| Nlocrel uint32 |
| } |
| |
| // A DylibCmd is a Mach-O load dynamic library command. |
| DylibCmd struct { |
| Cmd LoadCmd |
| Len uint32 |
| Name uint32 |
| Time uint32 |
| CurrentVersion uint32 |
| CompatVersion uint32 |
| } |
| |
| // A RpathCmd is a Mach-O rpath command. |
| RpathCmd struct { |
| Cmd LoadCmd |
| Len uint32 |
| Path uint32 |
| } |
| |
| // A Thread is a Mach-O thread state command. |
| Thread struct { |
| Cmd LoadCmd |
| Len uint32 |
| Type uint32 |
| Data []uint32 |
| } |
| ) |
| |
| const ( |
| FlagNoUndefs uint32 = 0x1 |
| FlagIncrLink uint32 = 0x2 |
| FlagDyldLink uint32 = 0x4 |
| FlagBindAtLoad uint32 = 0x8 |
| FlagPrebound uint32 = 0x10 |
| FlagSplitSegs uint32 = 0x20 |
| FlagLazyInit uint32 = 0x40 |
| FlagTwoLevel uint32 = 0x80 |
| FlagForceFlat uint32 = 0x100 |
| FlagNoMultiDefs uint32 = 0x200 |
| FlagNoFixPrebinding uint32 = 0x400 |
| FlagPrebindable uint32 = 0x800 |
| FlagAllModsBound uint32 = 0x1000 |
| FlagSubsectionsViaSymbols uint32 = 0x2000 |
| FlagCanonical uint32 = 0x4000 |
| FlagWeakDefines uint32 = 0x8000 |
| FlagBindsToWeak uint32 = 0x10000 |
| FlagAllowStackExecution uint32 = 0x20000 |
| FlagRootSafe uint32 = 0x40000 |
| FlagSetuidSafe uint32 = 0x80000 |
| FlagNoReexportedDylibs uint32 = 0x100000 |
| FlagPIE uint32 = 0x200000 |
| FlagDeadStrippableDylib uint32 = 0x400000 |
| FlagHasTLVDescriptors uint32 = 0x800000 |
| FlagNoHeapExecution uint32 = 0x1000000 |
| FlagAppExtensionSafe uint32 = 0x2000000 |
| ) |
| |
| // A Section32 is a 32-bit Mach-O section header. |
| type Section32 struct { |
| Name [16]byte |
| Seg [16]byte |
| Addr uint32 |
| Size uint32 |
| Offset uint32 |
| Align uint32 |
| Reloff uint32 |
| Nreloc uint32 |
| Flags uint32 |
| Reserve1 uint32 |
| Reserve2 uint32 |
| } |
| |
| // A Section64 is a 64-bit Mach-O section header. |
| type Section64 struct { |
| Name [16]byte |
| Seg [16]byte |
| Addr uint64 |
| Size uint64 |
| Offset uint32 |
| Align uint32 |
| Reloff uint32 |
| Nreloc uint32 |
| Flags uint32 |
| Reserve1 uint32 |
| Reserve2 uint32 |
| Reserve3 uint32 |
| } |
| |
| // An Nlist32 is a Mach-O 32-bit symbol table entry. |
| type Nlist32 struct { |
| Name uint32 |
| Type uint8 |
| Sect uint8 |
| Desc uint16 |
| Value uint32 |
| } |
| |
| // An Nlist64 is a Mach-O 64-bit symbol table entry. |
| type Nlist64 struct { |
| Name uint32 |
| Type uint8 |
| Sect uint8 |
| Desc uint16 |
| Value uint64 |
| } |
| |
| // Regs386 is the Mach-O 386 register structure. |
| type Regs386 struct { |
| AX uint32 |
| BX uint32 |
| CX uint32 |
| DX uint32 |
| DI uint32 |
| SI uint32 |
| BP uint32 |
| SP uint32 |
| SS uint32 |
| FLAGS uint32 |
| IP uint32 |
| CS uint32 |
| DS uint32 |
| ES uint32 |
| FS uint32 |
| GS uint32 |
| } |
| |
| // RegsAMD64 is the Mach-O AMD64 register structure. |
| type RegsAMD64 struct { |
| AX uint64 |
| BX uint64 |
| CX uint64 |
| DX uint64 |
| DI uint64 |
| SI uint64 |
| BP uint64 |
| SP uint64 |
| R8 uint64 |
| R9 uint64 |
| R10 uint64 |
| R11 uint64 |
| R12 uint64 |
| R13 uint64 |
| R14 uint64 |
| R15 uint64 |
| IP uint64 |
| FLAGS uint64 |
| CS uint64 |
| FS uint64 |
| GS uint64 |
| } |
| |
| type intName struct { |
| i uint32 |
| s string |
| } |
| |
| func stringName(i uint32, names []intName, goSyntax bool) string { |
| for _, n := range names { |
| if n.i == i { |
| if goSyntax { |
| return "macho." + n.s |
| } |
| return n.s |
| } |
| } |
| return strconv.FormatUint(uint64(i), 10) |
| } |