github.com/april1989/origin-go-tools@v0.0.32/cmd/splitdwarf/internal/macho/macho.go (about)

     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  // http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html
     7  
     8  package macho
     9  
    10  import (
    11  	"encoding/binary"
    12  	"strconv"
    13  )
    14  
    15  // A FileHeader represents a Mach-O file header.
    16  type FileHeader struct {
    17  	Magic        uint32
    18  	Cpu          Cpu
    19  	SubCpu       uint32
    20  	Type         HdrType
    21  	NCommands    uint32 // number of load commands
    22  	SizeCommands uint32 // size of all the load commands, not including this header.
    23  	Flags        HdrFlags
    24  }
    25  
    26  func (h *FileHeader) Put(b []byte, o binary.ByteOrder) int {
    27  	o.PutUint32(b[0:], h.Magic)
    28  	o.PutUint32(b[4:], uint32(h.Cpu))
    29  	o.PutUint32(b[8:], h.SubCpu)
    30  	o.PutUint32(b[12:], uint32(h.Type))
    31  	o.PutUint32(b[16:], h.NCommands)
    32  	o.PutUint32(b[20:], h.SizeCommands)
    33  	o.PutUint32(b[24:], uint32(h.Flags))
    34  	if h.Magic == Magic32 {
    35  		return 28
    36  	}
    37  	o.PutUint32(b[28:], 0)
    38  	return 32
    39  }
    40  
    41  const (
    42  	fileHeaderSize32 = 7 * 4
    43  	fileHeaderSize64 = 8 * 4
    44  )
    45  
    46  const (
    47  	Magic32  uint32 = 0xfeedface
    48  	Magic64  uint32 = 0xfeedfacf
    49  	MagicFat uint32 = 0xcafebabe
    50  )
    51  
    52  type HdrFlags uint32
    53  type SegFlags uint32
    54  type SecFlags uint32
    55  
    56  // A HdrType is the Mach-O file type, e.g. an object file, executable, or dynamic library.
    57  type HdrType uint32
    58  
    59  const ( // SNAKE_CASE to CamelCase translation from C names
    60  	MhObject  HdrType = 1
    61  	MhExecute HdrType = 2
    62  	MhCore    HdrType = 4
    63  	MhDylib   HdrType = 6
    64  	MhBundle  HdrType = 8
    65  	MhDsym    HdrType = 0xa
    66  )
    67  
    68  var typeStrings = []intName{
    69  	{uint32(MhObject), "Obj"},
    70  	{uint32(MhExecute), "Exec"},
    71  	{uint32(MhDylib), "Dylib"},
    72  	{uint32(MhBundle), "Bundle"},
    73  	{uint32(MhDsym), "Dsym"},
    74  }
    75  
    76  func (t HdrType) String() string   { return stringName(uint32(t), typeStrings, false) }
    77  func (t HdrType) GoString() string { return stringName(uint32(t), typeStrings, true) }
    78  
    79  // A Cpu is a Mach-O cpu type.
    80  type Cpu uint32
    81  
    82  const cpuArch64 = 0x01000000
    83  
    84  const (
    85  	Cpu386   Cpu = 7
    86  	CpuAmd64 Cpu = Cpu386 | cpuArch64
    87  	CpuArm   Cpu = 12
    88  	CpuArm64 Cpu = CpuArm | cpuArch64
    89  	CpuPpc   Cpu = 18
    90  	CpuPpc64 Cpu = CpuPpc | cpuArch64
    91  )
    92  
    93  var cpuStrings = []intName{
    94  	{uint32(Cpu386), "Cpu386"},
    95  	{uint32(CpuAmd64), "CpuAmd64"},
    96  	{uint32(CpuArm), "CpuArm"},
    97  	{uint32(CpuArm64), "CpuArm64"},
    98  	{uint32(CpuPpc), "CpuPpc"},
    99  	{uint32(CpuPpc64), "CpuPpc64"},
   100  }
   101  
   102  func (i Cpu) String() string   { return stringName(uint32(i), cpuStrings, false) }
   103  func (i Cpu) GoString() string { return stringName(uint32(i), cpuStrings, true) }
   104  
   105  // A LoadCmd is a Mach-O load command.
   106  type LoadCmd uint32
   107  
   108  func (c LoadCmd) Command() LoadCmd { return c }
   109  
   110  const ( // SNAKE_CASE to CamelCase translation from C names
   111  	// Note 3 and 8 are obsolete
   112  	LcSegment            LoadCmd = 0x1
   113  	LcSymtab             LoadCmd = 0x2
   114  	LcThread             LoadCmd = 0x4
   115  	LcUnixthread         LoadCmd = 0x5 // thread+stack
   116  	LcDysymtab           LoadCmd = 0xb
   117  	LcDylib              LoadCmd = 0xc // load dylib command
   118  	LcIdDylib            LoadCmd = 0xd // dynamically linked shared lib ident
   119  	LcLoadDylinker       LoadCmd = 0xe // load a dynamic linker
   120  	LcIdDylinker         LoadCmd = 0xf // id dylinker command (not load dylinker command)
   121  	LcSegment64          LoadCmd = 0x19
   122  	LcUuid               LoadCmd = 0x1b
   123  	LcCodeSignature      LoadCmd = 0x1d
   124  	LcSegmentSplitInfo   LoadCmd = 0x1e
   125  	LcRpath              LoadCmd = 0x8000001c
   126  	LcEncryptionInfo     LoadCmd = 0x21
   127  	LcDyldInfo           LoadCmd = 0x22
   128  	LcDyldInfoOnly       LoadCmd = 0x80000022
   129  	LcVersionMinMacosx   LoadCmd = 0x24
   130  	LcVersionMinIphoneos LoadCmd = 0x25
   131  	LcFunctionStarts     LoadCmd = 0x26
   132  	LcDyldEnvironment    LoadCmd = 0x27
   133  	LcMain               LoadCmd = 0x80000028 // replacement for UnixThread
   134  	LcDataInCode         LoadCmd = 0x29       // There are non-instructions in text
   135  	LcSourceVersion      LoadCmd = 0x2a       // Source version used to build binary
   136  	LcDylibCodeSignDrs   LoadCmd = 0x2b
   137  	LcEncryptionInfo64   LoadCmd = 0x2c
   138  	LcVersionMinTvos     LoadCmd = 0x2f
   139  	LcVersionMinWatchos  LoadCmd = 0x30
   140  )
   141  
   142  var cmdStrings = []intName{
   143  	{uint32(LcSegment), "LoadCmdSegment"},
   144  	{uint32(LcThread), "LoadCmdThread"},
   145  	{uint32(LcUnixthread), "LoadCmdUnixThread"},
   146  	{uint32(LcDylib), "LoadCmdDylib"},
   147  	{uint32(LcIdDylib), "LoadCmdIdDylib"},
   148  	{uint32(LcLoadDylinker), "LoadCmdLoadDylinker"},
   149  	{uint32(LcIdDylinker), "LoadCmdIdDylinker"},
   150  	{uint32(LcSegment64), "LoadCmdSegment64"},
   151  	{uint32(LcUuid), "LoadCmdUuid"},
   152  	{uint32(LcRpath), "LoadCmdRpath"},
   153  	{uint32(LcDyldEnvironment), "LoadCmdDyldEnv"},
   154  	{uint32(LcMain), "LoadCmdMain"},
   155  	{uint32(LcDataInCode), "LoadCmdDataInCode"},
   156  	{uint32(LcSourceVersion), "LoadCmdSourceVersion"},
   157  	{uint32(LcDyldInfo), "LoadCmdDyldInfo"},
   158  	{uint32(LcDyldInfoOnly), "LoadCmdDyldInfoOnly"},
   159  	{uint32(LcVersionMinMacosx), "LoadCmdMinOsx"},
   160  	{uint32(LcFunctionStarts), "LoadCmdFunctionStarts"},
   161  }
   162  
   163  func (i LoadCmd) String() string   { return stringName(uint32(i), cmdStrings, false) }
   164  func (i LoadCmd) GoString() string { return stringName(uint32(i), cmdStrings, true) }
   165  
   166  type (
   167  	// A Segment32 is a 32-bit Mach-O segment load command.
   168  	Segment32 struct {
   169  		LoadCmd
   170  		Len     uint32
   171  		Name    [16]byte
   172  		Addr    uint32
   173  		Memsz   uint32
   174  		Offset  uint32
   175  		Filesz  uint32
   176  		Maxprot uint32
   177  		Prot    uint32
   178  		Nsect   uint32
   179  		Flag    SegFlags
   180  	}
   181  
   182  	// A Segment64 is a 64-bit Mach-O segment load command.
   183  	Segment64 struct {
   184  		LoadCmd
   185  		Len     uint32
   186  		Name    [16]byte
   187  		Addr    uint64
   188  		Memsz   uint64
   189  		Offset  uint64
   190  		Filesz  uint64
   191  		Maxprot uint32
   192  		Prot    uint32
   193  		Nsect   uint32
   194  		Flag    SegFlags
   195  	}
   196  
   197  	// A SymtabCmd is a Mach-O symbol table command.
   198  	SymtabCmd struct {
   199  		LoadCmd
   200  		Len     uint32
   201  		Symoff  uint32
   202  		Nsyms   uint32
   203  		Stroff  uint32
   204  		Strsize uint32
   205  	}
   206  
   207  	// A DysymtabCmd is a Mach-O dynamic symbol table command.
   208  	DysymtabCmd struct {
   209  		LoadCmd
   210  		Len            uint32
   211  		Ilocalsym      uint32
   212  		Nlocalsym      uint32
   213  		Iextdefsym     uint32
   214  		Nextdefsym     uint32
   215  		Iundefsym      uint32
   216  		Nundefsym      uint32
   217  		Tocoffset      uint32
   218  		Ntoc           uint32
   219  		Modtaboff      uint32
   220  		Nmodtab        uint32
   221  		Extrefsymoff   uint32
   222  		Nextrefsyms    uint32
   223  		Indirectsymoff uint32
   224  		Nindirectsyms  uint32
   225  		Extreloff      uint32
   226  		Nextrel        uint32
   227  		Locreloff      uint32
   228  		Nlocrel        uint32
   229  	}
   230  
   231  	// A DylibCmd is a Mach-O load dynamic library command.
   232  	DylibCmd struct {
   233  		LoadCmd
   234  		Len            uint32
   235  		Name           uint32
   236  		Time           uint32
   237  		CurrentVersion uint32
   238  		CompatVersion  uint32
   239  	}
   240  
   241  	// A DylinkerCmd is a Mach-O load dynamic linker or environment command.
   242  	DylinkerCmd struct {
   243  		LoadCmd
   244  		Len  uint32
   245  		Name uint32
   246  	}
   247  
   248  	// A RpathCmd is a Mach-O rpath command.
   249  	RpathCmd struct {
   250  		LoadCmd
   251  		Len  uint32
   252  		Path uint32
   253  	}
   254  
   255  	// A Thread is a Mach-O thread state command.
   256  	Thread struct {
   257  		LoadCmd
   258  		Len  uint32
   259  		Type uint32
   260  		Data []uint32
   261  	}
   262  
   263  	// LC_DYLD_INFO, LC_DYLD_INFO_ONLY
   264  	DyldInfoCmd struct {
   265  		LoadCmd
   266  		Len                      uint32
   267  		RebaseOff, RebaseLen     uint32 // file offset and length; data contains segment indices
   268  		BindOff, BindLen         uint32 // file offset and length; data contains segment indices
   269  		WeakBindOff, WeakBindLen uint32 // file offset and length
   270  		LazyBindOff, LazyBindLen uint32 // file offset and length
   271  		ExportOff, ExportLen     uint32 // file offset and length
   272  	}
   273  
   274  	// LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO, LC_FUNCTION_STARTS, LC_DATA_IN_CODE, LC_DYLIB_CODE_SIGN_DRS
   275  	LinkEditDataCmd struct {
   276  		LoadCmd
   277  		Len              uint32
   278  		DataOff, DataLen uint32 // file offset and length
   279  	}
   280  
   281  	// LC_ENCRYPTION_INFO, LC_ENCRYPTION_INFO_64
   282  	EncryptionInfoCmd struct {
   283  		LoadCmd
   284  		Len                uint32
   285  		CryptOff, CryptLen uint32 // file offset and length
   286  		CryptId            uint32
   287  	}
   288  
   289  	UuidCmd struct {
   290  		LoadCmd
   291  		Len uint32
   292  		Id  [16]byte
   293  	}
   294  
   295  	// TODO Commands below not fully supported yet.
   296  
   297  	EntryPointCmd struct {
   298  		LoadCmd
   299  		Len       uint32
   300  		EntryOff  uint64 // file offset
   301  		StackSize uint64 // if not zero, initial stack size
   302  	}
   303  
   304  	NoteCmd struct {
   305  		LoadCmd
   306  		Len            uint32
   307  		Name           [16]byte
   308  		Offset, Filesz uint64 // file offset and length
   309  	}
   310  )
   311  
   312  const (
   313  	FlagNoUndefs              HdrFlags = 0x1
   314  	FlagIncrLink              HdrFlags = 0x2
   315  	FlagDyldLink              HdrFlags = 0x4
   316  	FlagBindAtLoad            HdrFlags = 0x8
   317  	FlagPrebound              HdrFlags = 0x10
   318  	FlagSplitSegs             HdrFlags = 0x20
   319  	FlagLazyInit              HdrFlags = 0x40
   320  	FlagTwoLevel              HdrFlags = 0x80
   321  	FlagForceFlat             HdrFlags = 0x100
   322  	FlagNoMultiDefs           HdrFlags = 0x200
   323  	FlagNoFixPrebinding       HdrFlags = 0x400
   324  	FlagPrebindable           HdrFlags = 0x800
   325  	FlagAllModsBound          HdrFlags = 0x1000
   326  	FlagSubsectionsViaSymbols HdrFlags = 0x2000
   327  	FlagCanonical             HdrFlags = 0x4000
   328  	FlagWeakDefines           HdrFlags = 0x8000
   329  	FlagBindsToWeak           HdrFlags = 0x10000
   330  	FlagAllowStackExecution   HdrFlags = 0x20000
   331  	FlagRootSafe              HdrFlags = 0x40000
   332  	FlagSetuidSafe            HdrFlags = 0x80000
   333  	FlagNoReexportedDylibs    HdrFlags = 0x100000
   334  	FlagPIE                   HdrFlags = 0x200000
   335  	FlagDeadStrippableDylib   HdrFlags = 0x400000
   336  	FlagHasTLVDescriptors     HdrFlags = 0x800000
   337  	FlagNoHeapExecution       HdrFlags = 0x1000000
   338  	FlagAppExtensionSafe      HdrFlags = 0x2000000
   339  )
   340  
   341  // A Section32 is a 32-bit Mach-O section header.
   342  type Section32 struct {
   343  	Name     [16]byte
   344  	Seg      [16]byte
   345  	Addr     uint32
   346  	Size     uint32
   347  	Offset   uint32
   348  	Align    uint32
   349  	Reloff   uint32
   350  	Nreloc   uint32
   351  	Flags    SecFlags
   352  	Reserve1 uint32
   353  	Reserve2 uint32
   354  }
   355  
   356  // A Section64 is a 64-bit Mach-O section header.
   357  type Section64 struct {
   358  	Name     [16]byte
   359  	Seg      [16]byte
   360  	Addr     uint64
   361  	Size     uint64
   362  	Offset   uint32
   363  	Align    uint32
   364  	Reloff   uint32
   365  	Nreloc   uint32
   366  	Flags    SecFlags
   367  	Reserve1 uint32
   368  	Reserve2 uint32
   369  	Reserve3 uint32
   370  }
   371  
   372  // An Nlist32 is a Mach-O 32-bit symbol table entry.
   373  type Nlist32 struct {
   374  	Name  uint32
   375  	Type  uint8
   376  	Sect  uint8
   377  	Desc  uint16
   378  	Value uint32
   379  }
   380  
   381  // An Nlist64 is a Mach-O 64-bit symbol table entry.
   382  type Nlist64 struct {
   383  	Name  uint32
   384  	Type  uint8
   385  	Sect  uint8
   386  	Desc  uint16
   387  	Value uint64
   388  }
   389  
   390  func (n *Nlist64) Put64(b []byte, o binary.ByteOrder) uint32 {
   391  	o.PutUint32(b[0:], n.Name)
   392  	b[4] = byte(n.Type)
   393  	b[5] = byte(n.Sect)
   394  	o.PutUint16(b[6:], n.Desc)
   395  	o.PutUint64(b[8:], n.Value)
   396  	return 8 + 8
   397  }
   398  
   399  func (n *Nlist64) Put32(b []byte, o binary.ByteOrder) uint32 {
   400  	o.PutUint32(b[0:], n.Name)
   401  	b[4] = byte(n.Type)
   402  	b[5] = byte(n.Sect)
   403  	o.PutUint16(b[6:], n.Desc)
   404  	o.PutUint32(b[8:], uint32(n.Value))
   405  	return 8 + 4
   406  }
   407  
   408  // Regs386 is the Mach-O 386 register structure.
   409  type Regs386 struct {
   410  	AX    uint32
   411  	BX    uint32
   412  	CX    uint32
   413  	DX    uint32
   414  	DI    uint32
   415  	SI    uint32
   416  	BP    uint32
   417  	SP    uint32
   418  	SS    uint32
   419  	FLAGS uint32
   420  	IP    uint32
   421  	CS    uint32
   422  	DS    uint32
   423  	ES    uint32
   424  	FS    uint32
   425  	GS    uint32
   426  }
   427  
   428  // RegsAMD64 is the Mach-O AMD64 register structure.
   429  type RegsAMD64 struct {
   430  	AX    uint64
   431  	BX    uint64
   432  	CX    uint64
   433  	DX    uint64
   434  	DI    uint64
   435  	SI    uint64
   436  	BP    uint64
   437  	SP    uint64
   438  	R8    uint64
   439  	R9    uint64
   440  	R10   uint64
   441  	R11   uint64
   442  	R12   uint64
   443  	R13   uint64
   444  	R14   uint64
   445  	R15   uint64
   446  	IP    uint64
   447  	FLAGS uint64
   448  	CS    uint64
   449  	FS    uint64
   450  	GS    uint64
   451  }
   452  
   453  type intName struct {
   454  	i uint32
   455  	s string
   456  }
   457  
   458  func stringName(i uint32, names []intName, goSyntax bool) string {
   459  	for _, n := range names {
   460  		if n.i == i {
   461  			if goSyntax {
   462  				return "macho." + n.s
   463  			}
   464  			return n.s
   465  		}
   466  	}
   467  	return "0x" + strconv.FormatUint(uint64(i), 16)
   468  }