|
- // Copyright 2018 Google Inc. All Rights Reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
-
- // Mach-O header data structures
- // http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html
-
- package macho // import "cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/macho"
-
- import "strconv"
-
- // A FileHeader represents a Mach-O file header.
- type FileHeader struct {
- Magic uint32
- Cpu Cpu
- SubCpu uint32
- Type Type
- Ncmd uint32
- Cmdsz uint32
- Flags uint32
- }
-
- const (
- fileHeaderSize32 = 7 * 4
- fileHeaderSize64 = 8 * 4
- )
-
- const (
- Magic32 uint32 = 0xfeedface
- Magic64 uint32 = 0xfeedfacf
- MagicFat uint32 = 0xcafebabe
- )
-
- // A Type is the Mach-O file type, e.g. an object file, executable, or dynamic library.
- type Type uint32
-
- const (
- TypeObj Type = 1
- TypeExec Type = 2
- TypeDylib Type = 6
- TypeBundle Type = 8
- )
-
- // A Cpu is a Mach-O cpu type.
- type Cpu uint32
-
- const cpuArch64 = 0x01000000
-
- const (
- Cpu386 Cpu = 7
- CpuAmd64 Cpu = Cpu386 | cpuArch64
- CpuArm Cpu = 12
- CpuPpc Cpu = 18
- CpuPpc64 Cpu = CpuPpc | cpuArch64
- )
-
- var cpuStrings = []intName{
- {uint32(Cpu386), "Cpu386"},
- {uint32(CpuAmd64), "CpuAmd64"},
- {uint32(CpuArm), "CpuArm"},
- {uint32(CpuPpc), "CpuPpc"},
- {uint32(CpuPpc64), "CpuPpc64"},
- }
-
- func (i Cpu) String() string { return stringName(uint32(i), cpuStrings, false) }
- func (i Cpu) GoString() string { return stringName(uint32(i), cpuStrings, true) }
-
- // A LoadCmd is a Mach-O load command.
- type LoadCmd uint32
-
- const (
- LoadCmdSegment LoadCmd = 1
- LoadCmdSymtab LoadCmd = 2
- LoadCmdThread LoadCmd = 4
- LoadCmdUnixThread LoadCmd = 5 // thread+stack
- LoadCmdDysymtab LoadCmd = 11
- LoadCmdDylib LoadCmd = 12
- LoadCmdDylinker LoadCmd = 15
- LoadCmdSegment64 LoadCmd = 25
- )
-
- var cmdStrings = []intName{
- {uint32(LoadCmdSegment), "LoadCmdSegment"},
- {uint32(LoadCmdThread), "LoadCmdThread"},
- {uint32(LoadCmdUnixThread), "LoadCmdUnixThread"},
- {uint32(LoadCmdDylib), "LoadCmdDylib"},
- {uint32(LoadCmdSegment64), "LoadCmdSegment64"},
- }
-
- func (i LoadCmd) String() string { return stringName(uint32(i), cmdStrings, false) }
- func (i LoadCmd) GoString() string { return stringName(uint32(i), cmdStrings, true) }
-
- // A Segment64 is a 64-bit Mach-O segment load command.
- type Segment64 struct {
- Cmd LoadCmd
- Len uint32
- Name [16]byte
- Addr uint64
- Memsz uint64
- Offset uint64
- Filesz uint64
- Maxprot uint32
- Prot uint32
- Nsect uint32
- Flag uint32
- }
-
- // A Segment32 is a 32-bit Mach-O segment load command.
- type Segment32 struct {
- Cmd LoadCmd
- Len uint32
- Name [16]byte
- Addr uint32
- Memsz uint32
- Offset uint32
- Filesz uint32
- Maxprot uint32
- Prot uint32
- Nsect uint32
- Flag uint32
- }
-
- // A DylibCmd is a Mach-O load dynamic library command.
- type DylibCmd struct {
- Cmd LoadCmd
- Len uint32
- Name uint32
- Time uint32
- CurrentVersion uint32
- CompatVersion uint32
- }
-
- // A Section32 is a 32-bit Mach-O section header.
- type Section32 struct {
- Name [16]byte
- Seg [16]byte
- Addr uint32
- Size uint32
- Offset uint32
- Align uint32
- Reloff uint32
- Nreloc uint32
- Flags uint32
- Reserve1 uint32
- Reserve2 uint32
- }
-
- // A Section32 is a 64-bit Mach-O section header.
- type Section64 struct {
- Name [16]byte
- Seg [16]byte
- Addr uint64
- Size uint64
- Offset uint32
- Align uint32
- Reloff uint32
- Nreloc uint32
- Flags uint32
- Reserve1 uint32
- Reserve2 uint32
- Reserve3 uint32
- }
-
- // A SymtabCmd is a Mach-O symbol table command.
- type SymtabCmd struct {
- Cmd LoadCmd
- Len uint32
- Symoff uint32
- Nsyms uint32
- Stroff uint32
- Strsize uint32
- }
-
- // A DysymtabCmd is a Mach-O dynamic symbol table command.
- type DysymtabCmd struct {
- Cmd LoadCmd
- Len uint32
- Ilocalsym uint32
- Nlocalsym uint32
- Iextdefsym uint32
- Nextdefsym uint32
- Iundefsym uint32
- Nundefsym uint32
- Tocoffset uint32
- Ntoc uint32
- Modtaboff uint32
- Nmodtab uint32
- Extrefsymoff uint32
- Nextrefsyms uint32
- Indirectsymoff uint32
- Nindirectsyms uint32
- Extreloff uint32
- Nextrel uint32
- Locreloff uint32
- Nlocrel uint32
- }
-
- // An Nlist32 is a Mach-O 32-bit symbol table entry.
- type Nlist32 struct {
- Name uint32
- Type uint8
- Sect uint8
- Desc uint16
- Value uint32
- }
-
- // An Nlist64 is a Mach-O 64-bit symbol table entry.
- type Nlist64 struct {
- Name uint32
- Type uint8
- Sect uint8
- Desc uint16
- Value uint64
- }
-
- // A Symbol is a Mach-O 32-bit or 64-bit symbol table entry.
- type Symbol struct {
- Name string
- Type uint8
- Sect uint8
- Desc uint16
- Value uint64
- }
-
- // A Thread is a Mach-O thread state command.
- type Thread struct {
- Cmd LoadCmd
- Len uint32
- Type uint32
- Data []uint32
- }
-
- // Regs386 is the Mach-O 386 register structure.
- type Regs386 struct {
- AX uint32
- BX uint32
- CX uint32
- DX uint32
- DI uint32
- SI uint32
- BP uint32
- SP uint32
- SS uint32
- FLAGS uint32
- IP uint32
- CS uint32
- DS uint32
- ES uint32
- FS uint32
- GS uint32
- }
-
- // RegsAMD64 is the Mach-O AMD64 register structure.
- type RegsAMD64 struct {
- AX uint64
- BX uint64
- CX uint64
- DX uint64
- DI uint64
- SI uint64
- BP uint64
- SP uint64
- R8 uint64
- R9 uint64
- R10 uint64
- R11 uint64
- R12 uint64
- R13 uint64
- R14 uint64
- R15 uint64
- IP uint64
- FLAGS uint64
- CS uint64
- FS uint64
- GS uint64
- }
-
- type intName struct {
- i uint32
- s string
- }
-
- func stringName(i uint32, names []intName, goSyntax bool) string {
- for _, n := range names {
- if n.i == i {
- if goSyntax {
- return "macho." + n.s
- }
- return n.s
- }
- }
- return strconv.FormatUint(uint64(i), 10)
- }
-
- func flagName(i uint32, names []intName, goSyntax bool) string {
- s := ""
- for _, n := range names {
- if n.i&i == n.i {
- if len(s) > 0 {
- s += "+"
- }
- if goSyntax {
- s += "macho."
- }
- s += n.s
- i -= n.i
- }
- }
- if len(s) == 0 {
- return "0x" + strconv.FormatUint(uint64(i), 16)
- }
- if i != 0 {
- s += "+0x" + strconv.FormatUint(uint64(i), 16)
- }
- return s
- }
|