macho.mx raw

   1  // Copyright 2009 The Go Authors. All rights reserved.
   2  // Use of this source code is governed by a BSD-style
   3  // license that can be found in the LICENSE file.
   4  
   5  // Mach-O header data structures
   6  // Originally at:
   7  // http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html (since deleted by Apple)
   8  // Archived copy at:
   9  // https://web.archive.org/web/20090819232456/http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachORuntime/index.html
  10  // For cloned PDF see:
  11  // https://github.com/aidansteele/osx-abi-macho-file-format-reference
  12  
  13  package macho
  14  
  15  import "strconv"
  16  
  17  // A FileHeader represents a Mach-O file header.
  18  type FileHeader struct {
  19  	Magic  uint32
  20  	Cpu    Cpu
  21  	SubCpu uint32
  22  	Type   Type
  23  	Ncmd   uint32
  24  	Cmdsz  uint32
  25  	Flags  uint32
  26  }
  27  
  28  const (
  29  	fileHeaderSize32 = 7 * 4
  30  	fileHeaderSize64 = 8 * 4
  31  )
  32  
  33  const (
  34  	Magic32  uint32 = 0xfeedface
  35  	Magic64  uint32 = 0xfeedfacf
  36  	MagicFat uint32 = 0xcafebabe
  37  )
  38  
  39  // A Type is the Mach-O file type, e.g. an object file, executable, or dynamic library.
  40  type Type uint32
  41  
  42  const (
  43  	TypeObj    Type = 1
  44  	TypeExec   Type = 2
  45  	TypeDylib  Type = 6
  46  	TypeBundle Type = 8
  47  )
  48  
  49  var typeStrings = []intName{
  50  	{uint32(TypeObj), "Obj"},
  51  	{uint32(TypeExec), "Exec"},
  52  	{uint32(TypeDylib), "Dylib"},
  53  	{uint32(TypeBundle), "Bundle"},
  54  }
  55  
  56  func (t Type) String() string   { return stringName(uint32(t), typeStrings, false) }
  57  func (t Type) GoString() []byte { return stringName(uint32(t), typeStrings, true) }
  58  
  59  // A Cpu is a Mach-O cpu type.
  60  type Cpu uint32
  61  
  62  const cpuArch64 = 0x01000000
  63  
  64  const (
  65  	Cpu386   Cpu = 7
  66  	CpuAmd64 Cpu = Cpu386 | cpuArch64
  67  	CpuArm   Cpu = 12
  68  	CpuArm64 Cpu = CpuArm | cpuArch64
  69  	CpuPpc   Cpu = 18
  70  	CpuPpc64 Cpu = CpuPpc | cpuArch64
  71  )
  72  
  73  var cpuStrings = []intName{
  74  	{uint32(Cpu386), "Cpu386"},
  75  	{uint32(CpuAmd64), "CpuAmd64"},
  76  	{uint32(CpuArm), "CpuArm"},
  77  	{uint32(CpuArm64), "CpuArm64"},
  78  	{uint32(CpuPpc), "CpuPpc"},
  79  	{uint32(CpuPpc64), "CpuPpc64"},
  80  }
  81  
  82  func (i Cpu) String() string   { return stringName(uint32(i), cpuStrings, false) }
  83  func (i Cpu) GoString() []byte { return stringName(uint32(i), cpuStrings, true) }
  84  
  85  // A LoadCmd is a Mach-O load command.
  86  type LoadCmd uint32
  87  
  88  const (
  89  	LoadCmdSegment    LoadCmd = 0x1
  90  	LoadCmdSymtab     LoadCmd = 0x2
  91  	LoadCmdThread     LoadCmd = 0x4
  92  	LoadCmdUnixThread LoadCmd = 0x5 // thread+stack
  93  	LoadCmdDysymtab   LoadCmd = 0xb
  94  	LoadCmdDylib      LoadCmd = 0xc // load dylib command
  95  	LoadCmdDylinker   LoadCmd = 0xf // id dylinker command (not load dylinker command)
  96  	LoadCmdSegment64  LoadCmd = 0x19
  97  	LoadCmdRpath      LoadCmd = 0x8000001c
  98  )
  99  
 100  var cmdStrings = []intName{
 101  	{uint32(LoadCmdSegment), "LoadCmdSegment"},
 102  	{uint32(LoadCmdThread), "LoadCmdThread"},
 103  	{uint32(LoadCmdUnixThread), "LoadCmdUnixThread"},
 104  	{uint32(LoadCmdDylib), "LoadCmdDylib"},
 105  	{uint32(LoadCmdSegment64), "LoadCmdSegment64"},
 106  	{uint32(LoadCmdRpath), "LoadCmdRpath"},
 107  }
 108  
 109  func (i LoadCmd) String() string   { return stringName(uint32(i), cmdStrings, false) }
 110  func (i LoadCmd) GoString() []byte { return stringName(uint32(i), cmdStrings, true) }
 111  
 112  type (
 113  	// A Segment32 is a 32-bit Mach-O segment load command.
 114  	Segment32 struct {
 115  		Cmd     LoadCmd
 116  		Len     uint32
 117  		Name    [16]byte
 118  		Addr    uint32
 119  		Memsz   uint32
 120  		Offset  uint32
 121  		Filesz  uint32
 122  		Maxprot uint32
 123  		Prot    uint32
 124  		Nsect   uint32
 125  		Flag    uint32
 126  	}
 127  
 128  	// A Segment64 is a 64-bit Mach-O segment load command.
 129  	Segment64 struct {
 130  		Cmd     LoadCmd
 131  		Len     uint32
 132  		Name    [16]byte
 133  		Addr    uint64
 134  		Memsz   uint64
 135  		Offset  uint64
 136  		Filesz  uint64
 137  		Maxprot uint32
 138  		Prot    uint32
 139  		Nsect   uint32
 140  		Flag    uint32
 141  	}
 142  
 143  	// A SymtabCmd is a Mach-O symbol table command.
 144  	SymtabCmd struct {
 145  		Cmd     LoadCmd
 146  		Len     uint32
 147  		Symoff  uint32
 148  		Nsyms   uint32
 149  		Stroff  uint32
 150  		Strsize uint32
 151  	}
 152  
 153  	// A DysymtabCmd is a Mach-O dynamic symbol table command.
 154  	DysymtabCmd struct {
 155  		Cmd            LoadCmd
 156  		Len            uint32
 157  		Ilocalsym      uint32
 158  		Nlocalsym      uint32
 159  		Iextdefsym     uint32
 160  		Nextdefsym     uint32
 161  		Iundefsym      uint32
 162  		Nundefsym      uint32
 163  		Tocoffset      uint32
 164  		Ntoc           uint32
 165  		Modtaboff      uint32
 166  		Nmodtab        uint32
 167  		Extrefsymoff   uint32
 168  		Nextrefsyms    uint32
 169  		Indirectsymoff uint32
 170  		Nindirectsyms  uint32
 171  		Extreloff      uint32
 172  		Nextrel        uint32
 173  		Locreloff      uint32
 174  		Nlocrel        uint32
 175  	}
 176  
 177  	// A DylibCmd is a Mach-O load dynamic library command.
 178  	DylibCmd struct {
 179  		Cmd            LoadCmd
 180  		Len            uint32
 181  		Name           uint32
 182  		Time           uint32
 183  		CurrentVersion uint32
 184  		CompatVersion  uint32
 185  	}
 186  
 187  	// A RpathCmd is a Mach-O rpath command.
 188  	RpathCmd struct {
 189  		Cmd  LoadCmd
 190  		Len  uint32
 191  		Path uint32
 192  	}
 193  
 194  	// A Thread is a Mach-O thread state command.
 195  	Thread struct {
 196  		Cmd  LoadCmd
 197  		Len  uint32
 198  		Type uint32
 199  		Data []uint32
 200  	}
 201  )
 202  
 203  const (
 204  	FlagNoUndefs              uint32 = 0x1
 205  	FlagIncrLink              uint32 = 0x2
 206  	FlagDyldLink              uint32 = 0x4
 207  	FlagBindAtLoad            uint32 = 0x8
 208  	FlagPrebound              uint32 = 0x10
 209  	FlagSplitSegs             uint32 = 0x20
 210  	FlagLazyInit              uint32 = 0x40
 211  	FlagTwoLevel              uint32 = 0x80
 212  	FlagForceFlat             uint32 = 0x100
 213  	FlagNoMultiDefs           uint32 = 0x200
 214  	FlagNoFixPrebinding       uint32 = 0x400
 215  	FlagPrebindable           uint32 = 0x800
 216  	FlagAllModsBound          uint32 = 0x1000
 217  	FlagSubsectionsViaSymbols uint32 = 0x2000
 218  	FlagCanonical             uint32 = 0x4000
 219  	FlagWeakDefines           uint32 = 0x8000
 220  	FlagBindsToWeak           uint32 = 0x10000
 221  	FlagAllowStackExecution   uint32 = 0x20000
 222  	FlagRootSafe              uint32 = 0x40000
 223  	FlagSetuidSafe            uint32 = 0x80000
 224  	FlagNoReexportedDylibs    uint32 = 0x100000
 225  	FlagPIE                   uint32 = 0x200000
 226  	FlagDeadStrippableDylib   uint32 = 0x400000
 227  	FlagHasTLVDescriptors     uint32 = 0x800000
 228  	FlagNoHeapExecution       uint32 = 0x1000000
 229  	FlagAppExtensionSafe      uint32 = 0x2000000
 230  )
 231  
 232  // A Section32 is a 32-bit Mach-O section header.
 233  type Section32 struct {
 234  	Name     [16]byte
 235  	Seg      [16]byte
 236  	Addr     uint32
 237  	Size     uint32
 238  	Offset   uint32
 239  	Align    uint32
 240  	Reloff   uint32
 241  	Nreloc   uint32
 242  	Flags    uint32
 243  	Reserve1 uint32
 244  	Reserve2 uint32
 245  }
 246  
 247  // A Section64 is a 64-bit Mach-O section header.
 248  type Section64 struct {
 249  	Name     [16]byte
 250  	Seg      [16]byte
 251  	Addr     uint64
 252  	Size     uint64
 253  	Offset   uint32
 254  	Align    uint32
 255  	Reloff   uint32
 256  	Nreloc   uint32
 257  	Flags    uint32
 258  	Reserve1 uint32
 259  	Reserve2 uint32
 260  	Reserve3 uint32
 261  }
 262  
 263  // An Nlist32 is a Mach-O 32-bit symbol table entry.
 264  type Nlist32 struct {
 265  	Name  uint32
 266  	Type  uint8
 267  	Sect  uint8
 268  	Desc  uint16
 269  	Value uint32
 270  }
 271  
 272  // An Nlist64 is a Mach-O 64-bit symbol table entry.
 273  type Nlist64 struct {
 274  	Name  uint32
 275  	Type  uint8
 276  	Sect  uint8
 277  	Desc  uint16
 278  	Value uint64
 279  }
 280  
 281  // Regs386 is the Mach-O 386 register structure.
 282  type Regs386 struct {
 283  	AX    uint32
 284  	BX    uint32
 285  	CX    uint32
 286  	DX    uint32
 287  	DI    uint32
 288  	SI    uint32
 289  	BP    uint32
 290  	SP    uint32
 291  	SS    uint32
 292  	FLAGS uint32
 293  	IP    uint32
 294  	CS    uint32
 295  	DS    uint32
 296  	ES    uint32
 297  	FS    uint32
 298  	GS    uint32
 299  }
 300  
 301  // RegsAMD64 is the Mach-O AMD64 register structure.
 302  type RegsAMD64 struct {
 303  	AX    uint64
 304  	BX    uint64
 305  	CX    uint64
 306  	DX    uint64
 307  	DI    uint64
 308  	SI    uint64
 309  	BP    uint64
 310  	SP    uint64
 311  	R8    uint64
 312  	R9    uint64
 313  	R10   uint64
 314  	R11   uint64
 315  	R12   uint64
 316  	R13   uint64
 317  	R14   uint64
 318  	R15   uint64
 319  	IP    uint64
 320  	FLAGS uint64
 321  	CS    uint64
 322  	FS    uint64
 323  	GS    uint64
 324  }
 325  
 326  type intName struct {
 327  	i uint32
 328  	s []byte
 329  }
 330  
 331  func stringName(i uint32, names []intName, goSyntax bool) []byte {
 332  	for _, n := range names {
 333  		if n.i == i {
 334  			if goSyntax {
 335  				return "macho." + n.s
 336  			}
 337  			return n.s
 338  		}
 339  	}
 340  	return strconv.FormatUint(uint64(i), 10)
 341  }
 342