github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/debug/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  // 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() string { 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() string { 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() string { 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 string
   329  }
   330  
   331  func stringName(i uint32, names []intName, goSyntax bool) string {
   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  }