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 }