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 "strconv" 11 12 // A FileHeader represents a Mach-O file header. 13 type FileHeader struct { 14 Magic uint32 15 Cpu Cpu 16 SubCpu uint32 17 Type Type 18 Ncmd uint32 19 Cmdsz uint32 20 Flags uint32 21 } 22 23 const ( 24 fileHeaderSize32 = 7 * 4 25 fileHeaderSize64 = 8 * 4 26 ) 27 28 const ( 29 Magic32 uint32 = 0xfeedface 30 Magic64 uint32 = 0xfeedfacf 31 MagicFat uint32 = 0xcafebabe 32 ) 33 34 // A Type is the Mach-O file type, e.g. an object file, executable, or dynamic library. 35 type Type uint32 36 37 const ( 38 TypeObj Type = 1 39 TypeExec Type = 2 40 TypeDylib Type = 6 41 TypeBundle Type = 8 42 ) 43 44 // A Cpu is a Mach-O cpu type. 45 type Cpu uint32 46 47 const cpuArch64 = 0x01000000 48 49 const ( 50 Cpu386 Cpu = 7 51 CpuAmd64 Cpu = Cpu386 | cpuArch64 52 CpuArm Cpu = 12 53 CpuPpc Cpu = 18 54 CpuPpc64 Cpu = CpuPpc | cpuArch64 55 ) 56 57 var cpuStrings = []intName{ 58 {uint32(Cpu386), "Cpu386"}, 59 {uint32(CpuAmd64), "CpuAmd64"}, 60 {uint32(CpuArm), "CpuArm"}, 61 {uint32(CpuPpc), "CpuPpc"}, 62 {uint32(CpuPpc64), "CpuPpc64"}, 63 } 64 65 func (i Cpu) String() string { return stringName(uint32(i), cpuStrings, false) } 66 func (i Cpu) GoString() string { return stringName(uint32(i), cpuStrings, true) } 67 68 // A LoadCmd is a Mach-O load command. 69 type LoadCmd uint32 70 71 const ( 72 LoadCmdSegment LoadCmd = 1 73 LoadCmdSymtab LoadCmd = 2 74 LoadCmdThread LoadCmd = 4 75 LoadCmdUnixThread LoadCmd = 5 // thread+stack 76 LoadCmdDysymtab LoadCmd = 11 77 LoadCmdDylib LoadCmd = 12 78 LoadCmdDylinker LoadCmd = 15 79 LoadCmdSegment64 LoadCmd = 25 80 ) 81 82 var cmdStrings = []intName{ 83 {uint32(LoadCmdSegment), "LoadCmdSegment"}, 84 {uint32(LoadCmdThread), "LoadCmdThread"}, 85 {uint32(LoadCmdUnixThread), "LoadCmdUnixThread"}, 86 {uint32(LoadCmdDylib), "LoadCmdDylib"}, 87 {uint32(LoadCmdSegment64), "LoadCmdSegment64"}, 88 } 89 90 func (i LoadCmd) String() string { return stringName(uint32(i), cmdStrings, false) } 91 func (i LoadCmd) GoString() string { return stringName(uint32(i), cmdStrings, true) } 92 93 // A Segment64 is a 64-bit Mach-O segment load command. 94 type Segment64 struct { 95 Cmd LoadCmd 96 Len uint32 97 Name [16]byte 98 Addr uint64 99 Memsz uint64 100 Offset uint64 101 Filesz uint64 102 Maxprot uint32 103 Prot uint32 104 Nsect uint32 105 Flag uint32 106 } 107 108 // A Segment32 is a 32-bit Mach-O segment load command. 109 type Segment32 struct { 110 Cmd LoadCmd 111 Len uint32 112 Name [16]byte 113 Addr uint32 114 Memsz uint32 115 Offset uint32 116 Filesz uint32 117 Maxprot uint32 118 Prot uint32 119 Nsect uint32 120 Flag uint32 121 } 122 123 // A DylibCmd is a Mach-O load dynamic library command. 124 type DylibCmd struct { 125 Cmd LoadCmd 126 Len uint32 127 Name uint32 128 Time uint32 129 CurrentVersion uint32 130 CompatVersion uint32 131 } 132 133 // A Section32 is a 32-bit Mach-O section header. 134 type Section32 struct { 135 Name [16]byte 136 Seg [16]byte 137 Addr uint32 138 Size uint32 139 Offset uint32 140 Align uint32 141 Reloff uint32 142 Nreloc uint32 143 Flags uint32 144 Reserve1 uint32 145 Reserve2 uint32 146 } 147 148 // A Section32 is a 64-bit Mach-O section header. 149 type Section64 struct { 150 Name [16]byte 151 Seg [16]byte 152 Addr uint64 153 Size uint64 154 Offset uint32 155 Align uint32 156 Reloff uint32 157 Nreloc uint32 158 Flags uint32 159 Reserve1 uint32 160 Reserve2 uint32 161 Reserve3 uint32 162 } 163 164 // A SymtabCmd is a Mach-O symbol table command. 165 type SymtabCmd struct { 166 Cmd LoadCmd 167 Len uint32 168 Symoff uint32 169 Nsyms uint32 170 Stroff uint32 171 Strsize uint32 172 } 173 174 // A DysymtabCmd is a Mach-O dynamic symbol table command. 175 type DysymtabCmd struct { 176 Cmd LoadCmd 177 Len uint32 178 Ilocalsym uint32 179 Nlocalsym uint32 180 Iextdefsym uint32 181 Nextdefsym uint32 182 Iundefsym uint32 183 Nundefsym uint32 184 Tocoffset uint32 185 Ntoc uint32 186 Modtaboff uint32 187 Nmodtab uint32 188 Extrefsymoff uint32 189 Nextrefsyms uint32 190 Indirectsymoff uint32 191 Nindirectsyms uint32 192 Extreloff uint32 193 Nextrel uint32 194 Locreloff uint32 195 Nlocrel uint32 196 } 197 198 // An Nlist32 is a Mach-O 32-bit symbol table entry. 199 type Nlist32 struct { 200 Name uint32 201 Type uint8 202 Sect uint8 203 Desc uint16 204 Value uint32 205 } 206 207 // An Nlist64 is a Mach-O 64-bit symbol table entry. 208 type Nlist64 struct { 209 Name uint32 210 Type uint8 211 Sect uint8 212 Desc uint16 213 Value uint64 214 } 215 216 // A Symbol is a Mach-O 32-bit or 64-bit symbol table entry. 217 type Symbol struct { 218 Name string 219 Type uint8 220 Sect uint8 221 Desc uint16 222 Value uint64 223 } 224 225 // A Thread is a Mach-O thread state command. 226 type Thread struct { 227 Cmd LoadCmd 228 Len uint32 229 Type uint32 230 Data []uint32 231 } 232 233 // Regs386 is the Mach-O 386 register structure. 234 type Regs386 struct { 235 AX uint32 236 BX uint32 237 CX uint32 238 DX uint32 239 DI uint32 240 SI uint32 241 BP uint32 242 SP uint32 243 SS uint32 244 FLAGS uint32 245 IP uint32 246 CS uint32 247 DS uint32 248 ES uint32 249 FS uint32 250 GS uint32 251 } 252 253 // RegsAMD64 is the Mach-O AMD64 register structure. 254 type RegsAMD64 struct { 255 AX uint64 256 BX uint64 257 CX uint64 258 DX uint64 259 DI uint64 260 SI uint64 261 BP uint64 262 SP uint64 263 R8 uint64 264 R9 uint64 265 R10 uint64 266 R11 uint64 267 R12 uint64 268 R13 uint64 269 R14 uint64 270 R15 uint64 271 IP uint64 272 FLAGS uint64 273 CS uint64 274 FS uint64 275 GS uint64 276 } 277 278 type intName struct { 279 i uint32 280 s string 281 } 282 283 func stringName(i uint32, names []intName, goSyntax bool) string { 284 for _, n := range names { 285 if n.i == i { 286 if goSyntax { 287 return "macho." + n.s 288 } 289 return n.s 290 } 291 } 292 return strconv.FormatUint(uint64(i), 10) 293 } 294 295 func flagName(i uint32, names []intName, goSyntax bool) string { 296 s := "" 297 for _, n := range names { 298 if n.i&i == n.i { 299 if len(s) > 0 { 300 s += "+" 301 } 302 if goSyntax { 303 s += "macho." 304 } 305 s += n.s 306 i -= n.i 307 } 308 } 309 if len(s) == 0 { 310 return "0x" + strconv.FormatUint(uint64(i), 16) 311 } 312 if i != 0 { 313 s += "+0x" + strconv.FormatUint(uint64(i), 16) 314 } 315 return s 316 } 317