diff --git a/cmd/ipsw/cmd/disass.go b/cmd/ipsw/cmd/disass.go index d2b470031..3e0664125 100644 --- a/cmd/ipsw/cmd/disass.go +++ b/cmd/ipsw/cmd/disass.go @@ -30,8 +30,8 @@ import ( "strings" "github.com/apex/log" + "github.com/blacktop/go-macho" "github.com/blacktop/ipsw/internal/demangle" - "github.com/blacktop/ipsw/pkg/macho" "github.com/knightsc/gapstone" "github.com/pkg/errors" "github.com/spf13/cobra" diff --git a/cmd/ipsw/cmd/download_kernel.go b/cmd/ipsw/cmd/download_kernel.go index a2cffdfa6..28fb2b455 100644 --- a/cmd/ipsw/cmd/download_kernel.go +++ b/cmd/ipsw/cmd/download_kernel.go @@ -101,7 +101,7 @@ var downloadKernelCmd = &cobra.Command{ log.Error(err.Error()) } else { if iCan { - log.WithField("url", jbs.Jailbreaks[index].URL).Warnf("Yo, this shiz is jail breakable via %s B!!!!", jbs.Jailbreaks[index].Name) + log.WithField("url", jbs.Jailbreaks[index].URL).Warnf("Yo, this shiz is jail breakable via %s !!!!", jbs.Jailbreaks[index].Name) utils.Indent(log.Warn, 2)(jbs.Jailbreaks[index].Caveats) } else { log.Warnf("Yo, ain't no one jailbreaking this shizz NOT even %s my dude!!!!", download.GetRandomResearcher()) diff --git a/cmd/ipsw/cmd/dyld_list.go b/cmd/ipsw/cmd/dyld_list.go index 2a2fa3e02..c7b2eb574 100644 --- a/cmd/ipsw/cmd/dyld_list.go +++ b/cmd/ipsw/cmd/dyld_list.go @@ -28,8 +28,8 @@ import ( "text/tabwriter" "github.com/apex/log" + "github.com/blacktop/go-macho" "github.com/blacktop/ipsw/pkg/dyld" - "github.com/blacktop/ipsw/pkg/macho" "github.com/pkg/errors" "github.com/spf13/cobra" ) diff --git a/cmd/ipsw/cmd/macho.go b/cmd/ipsw/cmd/macho.go index 1fa1eef4e..a3806932c 100644 --- a/cmd/ipsw/cmd/macho.go +++ b/cmd/ipsw/cmd/macho.go @@ -29,7 +29,7 @@ import ( "text/tabwriter" "github.com/apex/log" - "github.com/blacktop/ipsw/pkg/macho" + "github.com/blacktop/go-macho" "github.com/spf13/cobra" ) @@ -101,9 +101,13 @@ var machoCmd = &cobra.Command{ // prevSeg = sec.Seg } w.Flush() - - fmt.Printf("Dyld ID: %s (%s)\n", m.DylibID().Name, m.DylibID().CurrentVersion) - fmt.Println("SourceVersion:", m.SourceVersion().Version) + + if m.DylibID() != nil { + fmt.Printf("Dyld ID: %s (%s)\n", m.DylibID().Name, m.DylibID().CurrentVersion) + } + if m.SourceVersion() != nil { + fmt.Println("SourceVersion:", m.SourceVersion().Version) + } if symbols { fmt.Println("SYMBOLS") diff --git a/docs/content/docs/commands/img4.md b/docs/content/docs/commands/img4.md index 67b755299..a9ebb53f8 100644 --- a/docs/content/docs/commands/img4.md +++ b/docs/content/docs/commands/img4.md @@ -29,11 +29,14 @@ $ ipsw img4 dec --iv-key iPhone12,3_D421AP_17E255/iBoot.d421.RELEASE.im4 It's a thing of beauty 😍 ```bash -$ hexdump -C -s 512 -n 80 iPhone12,3_D421AP_17E255/iBoot.d421.RELEASE.im4p.dec +$ hexdump -C -s 512 -n 144 iPhone12,3_D421AP_17E255/iBoot.d421.RELEASE.im4p.dec 00000200 69 42 6f 6f 74 20 66 6f 72 20 64 34 32 31 2c 20 |iBoot for d421, | 00000210 43 6f 70 79 72 69 67 68 74 20 32 30 30 37 2d 32 |Copyright 2007-2| 00000220 30 31 39 2c 20 41 70 70 6c 65 20 49 6e 63 2e 00 |019, Apple Inc..| 00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000240 52 45 4c 45 41 53 45 00 00 00 00 00 00 00 00 00 |RELEASE.........| +00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +* +00000280 69 42 6f 6f 74 2d 35 35 34 30 2e 31 30 32 2e 34 |iBoot-5540.102.4| ``` diff --git a/go.mod b/go.mod index 37f95a70d..c3caf46f4 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,7 @@ module github.com/blacktop/ipsw +go 1.14 + require ( github.com/AlecAivazis/survey/v2 v2.0.7 github.com/Netflix/go-expect v0.0.0-20180928190340-9d1f4485533b // indirect @@ -9,6 +11,7 @@ require ( github.com/antchfx/xpath v1.1.4 // indirect github.com/apex/log v1.1.2 github.com/blacktop/go-lzfse v1.1.10 + github.com/blacktop/go-macho v1.0.1 github.com/blacktop/go-plist v1.0.0 github.com/blacktop/lzss v0.1.0 github.com/blacktop/ranger v1.0.3 @@ -46,5 +49,3 @@ require ( gopkg.in/ini.v1 v1.54.0 // indirect gopkg.in/yaml.v2 v2.2.8 // indirect ) - -go 1.13 diff --git a/go.sum b/go.sum index ab588e4cd..12b1a4367 100644 --- a/go.sum +++ b/go.sum @@ -40,6 +40,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/blacktop/go-lzfse v1.1.10 h1:dbKhrw3/Sv0yPPJdsYDeP05GnEb0P1z7lVT5VSsHoeE= github.com/blacktop/go-lzfse v1.1.10/go.mod h1:b/0s26ecQ5SleO5NO41iY2Ie32rZxS5BKQstc5z2ia8= +github.com/blacktop/go-macho v1.0.1 h1:SMyWxg+U4oB0asphx+8uaNQJbJgo7Kzs4jJ0bKjvPrw= +github.com/blacktop/go-macho v1.0.1/go.mod h1:Mj6ORK0tK9FOkvzUFX1q99/SC2dQT/d43gb9HFY/APM= github.com/blacktop/go-plist v1.0.0 h1:bBpFGaiCdJZbQgOKxjxAUdvugySX+C3RtGvZODcOOoI= github.com/blacktop/go-plist v1.0.0/go.mod h1:niIOeDMEBISbJ9w0PPuc67iLvLh7Ve0N1gAfxIRWSk4= github.com/blacktop/lzss v0.1.0 h1:o0S0ZiBX9tIPNNx4W+AUUbVhcwaVFoFrZa7Zbdo7xJU= @@ -116,7 +118,6 @@ github.com/hinshun/vt10x v0.0.0-20180809195222-d55458df857c/go.mod h1:DqJ97dSdRW github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jawher/mow.cli v1.1.0 h1:NdtHXRc0CwZQ507wMvQ/IS+Q3W3x2fycn973/b8Zuk8= github.com/jawher/mow.cli v1.1.0/go.mod h1:aNaQlc7ozF3vw6IJ2dHjp2ZFiA4ozMIYY6PyuRJwlUg= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jinzhu/gorm v1.9.12 h1:Drgk1clyWT9t9ERbzHza6Mj/8FY/CqMyVzOiHviMo6Q= diff --git a/pkg/dyld/dyld.go b/pkg/dyld/dyld.go index 8f90370eb..b83881dc7 100644 --- a/pkg/dyld/dyld.go +++ b/pkg/dyld/dyld.go @@ -5,7 +5,7 @@ import ( "math/bits" "strings" - "github.com/blacktop/ipsw/pkg/macho/types" + "github.com/blacktop/go-macho/types" ) type formatVersion uint32 diff --git a/pkg/dyld/file.go b/pkg/dyld/file.go index fcdba3fe6..8ca9716db 100644 --- a/pkg/dyld/file.go +++ b/pkg/dyld/file.go @@ -15,8 +15,8 @@ import ( "text/tabwriter" "github.com/apex/log" + "github.com/blacktop/go-macho/types" "github.com/blacktop/ipsw/internal/utils" - "github.com/blacktop/ipsw/pkg/macho/types" "github.com/pkg/errors" ) diff --git a/pkg/dyld/image.go b/pkg/dyld/image.go index 0fddae219..6e63c17d3 100644 --- a/pkg/dyld/image.go +++ b/pkg/dyld/image.go @@ -8,9 +8,9 @@ import ( "strings" "github.com/apex/log" + "github.com/blacktop/go-macho" + "github.com/blacktop/go-macho/types" "github.com/blacktop/ipsw/internal/buffer" - "github.com/blacktop/ipsw/pkg/macho" - "github.com/blacktop/ipsw/pkg/macho/commands" "github.com/pkg/errors" ) @@ -132,7 +132,7 @@ func (i *CacheImage) Open() io.ReadSeeker { // GetPartialMacho parses dyld image header as a partial MachO func (i *CacheImage) GetPartialMacho() (*macho.File, error) { r := io.NewSectionReader(i.sr, int64(i.DylibOffset), int64(i.TextSegmentSize)) - m, err := macho.NewFileFromDyld(r, commands.LoadCmdSegment64, commands.LoadCmdDyldInfoOnly, commands.LoadCmdDylibID) + m, err := macho.NewFile(r, types.LoadCmdSegment64, types.LoadCmdDyldInfoOnly, types.LoadCmdDylibID) if err != nil { return nil, err } diff --git a/pkg/dyld/objc.go b/pkg/dyld/objc.go index a7c770a53..90b5a0b34 100644 --- a/pkg/dyld/objc.go +++ b/pkg/dyld/objc.go @@ -11,7 +11,7 @@ import ( "unicode" "github.com/apex/log" - "github.com/blacktop/ipsw/pkg/macho" + "github.com/blacktop/go-macho" "github.com/pkg/errors" ) diff --git a/pkg/kernelcache/diff.go b/pkg/kernelcache/diff.go index aaaaa403d..219c74970 100644 --- a/pkg/kernelcache/diff.go +++ b/pkg/kernelcache/diff.go @@ -2,7 +2,6 @@ package kernelcache import ( "bufio" - "debug/macho" "fmt" "io" "io/ioutil" @@ -10,6 +9,8 @@ import ( "path/filepath" "strings" "testing/iotest" + + "github.com/blacktop/go-macho" ) // ParseMachO parses the kernelcache as a mach-o diff --git a/pkg/kernelcache/kernelcache.go b/pkg/kernelcache/kernelcache.go index c7e98e7b5..5422575dc 100644 --- a/pkg/kernelcache/kernelcache.go +++ b/pkg/kernelcache/kernelcache.go @@ -5,7 +5,6 @@ package kernelcache import ( "archive/zip" "bytes" - "debug/macho" "encoding/asn1" "encoding/binary" "fmt" @@ -15,6 +14,8 @@ import ( "path/filepath" "strings" + "github.com/blacktop/go-macho" + "github.com/apex/log" lzfse "github.com/blacktop/go-lzfse" "github.com/blacktop/ipsw/internal/utils" diff --git a/pkg/kernelcache/kext.go b/pkg/kernelcache/kext.go index 37520ef32..b9fa18f1d 100644 --- a/pkg/kernelcache/kext.go +++ b/pkg/kernelcache/kext.go @@ -5,8 +5,8 @@ import ( "fmt" "os" + "github.com/blacktop/go-macho" "github.com/blacktop/go-plist" - "github.com/blacktop/ipsw/pkg/macho" ) type prelinkInfo struct { diff --git a/pkg/macho/commands/commands.go b/pkg/macho/commands/commands.go deleted file mode 100644 index 98f1a571e..000000000 --- a/pkg/macho/commands/commands.go +++ /dev/null @@ -1,523 +0,0 @@ -package commands - -import ( - "github.com/blacktop/ipsw/pkg/macho/types" - "github.com/blacktop/ipsw/pkg/macho/utils" -) - -// A LoadCmd is a Mach-O load command. -type LoadCmd uint32 - -const ( - LoadCmdReqDyld LoadCmd = 0x80000000 - LoadCmdSegment LoadCmd = 0x1 // segment of this file to be mapped - LoadCmdSymtab LoadCmd = 0x2 // link-edit stab symbol table info - LoadCmdSymseg LoadCmd = 0x3 // link-edit gdb symbol table info (obsolete) - LoadCmdThread LoadCmd = 0x4 // thread - LoadCmdUnixThread LoadCmd = 0x5 // thread+stack - LoadCmdLoadfvmlib LoadCmd = 0x6 // load a specified fixed VM shared library - LoadCmdIdfvmlib LoadCmd = 0x7 // fixed VM shared library identification - LoadCmdIdent LoadCmd = 0x8 // object identification info (obsolete) - LoadCmdFvmfile LoadCmd = 0x9 // fixed VM file inclusion (internal use) - LoadCmdPrepage LoadCmd = 0xa // prepage command (internal use) - LoadCmdDysymtab LoadCmd = 0xb // dynamic link-edit symbol table info - LoadCmdDylib LoadCmd = 0xc // load dylib command - LoadCmdDylibID LoadCmd = 0xd // id dylib command - LoadCmdDylinker LoadCmd = 0xe // load a dynamic linker - LoadCmdDylinkerID LoadCmd = 0xf // id dylinker command (not load dylinker command) - LoadCmdPreboundDylib LoadCmd = 0x10 // modules prebound for a dynamically linked shared library - LoadCmdRoutines LoadCmd = 0x11 // image routines - LoadCmdSubFramework LoadCmd = 0x12 // sub framework - LoadCmdSubUmbrella LoadCmd = 0x13 // sub umbrella - LoadCmdSubClient LoadCmd = 0x14 // sub client - LoadCmdSubLibrary LoadCmd = 0x15 // sub library - LoadCmdTwolevelHints LoadCmd = 0x16 // two-level namespace lookup hints - LoadCmdPrebindCksum LoadCmd = 0x17 // prebind checksum - /* - * load a dynamically linked shared library that is allowed to be missing - * (all symbols are weak imported). - */ - LoadCmdLoadWeakDylib LoadCmd = (0x18 | LoadCmdReqDyld) - LoadCmdSegment64 LoadCmd = 0x19 // 64-bit segment of this file to be mapped - LoadCmdRoutines64 LoadCmd = 0x1a // 64-bit image routines - LoadCmdUUID LoadCmd = 0x1b // the uuid - LoadCmdRpath LoadCmd = (0x1c | LoadCmdReqDyld) // runpath additions - LoadCmdCodeSignature LoadCmd = 0x1d // local of code signature - LoadCmdSegmentSplitInfo LoadCmd = 0x1e // local of info to split segments - LoadCmdReexportDylib LoadCmd = (0x1f | LoadCmdReqDyld) // load and re-export dylib - LoadCmdLazyLoadDylib LoadCmd = 0x20 // delay load of dylib until first use - LoadCmdEncryptionInfo LoadCmd = 0x21 // encrypted segment information - LoadCmdDyldInfo LoadCmd = 0x22 // compressed dyld information - LoadCmdDyldInfoOnly LoadCmd = (0x22 | LoadCmdReqDyld) // compressed dyld information only - LoadCmdLoadUpwardDylib LoadCmd = (0x23 | LoadCmdReqDyld) // load upward dylib - LoadCmdVersionMinMacosx LoadCmd = 0x24 // build for MacOSX min OS version - LoadCmdVersionMinIphoneos LoadCmd = 0x25 // build for iPhoneOS min OS version - LoadCmdFunctionStarts LoadCmd = 0x26 // compressed table of function start addresses - LoadCmdDyldEnvironment LoadCmd = 0x27 // string for dyld to treat like environment variable - LoadCmdMain LoadCmd = (0x28 | LoadCmdReqDyld) // replacement for LC_UNIXTHREAD - LoadCmdDataInCode LoadCmd = 0x29 // table of non-instructions in __text - LoadCmdSourceVersion LoadCmd = 0x2A // source version used to build binary - LoadCmdDylibCodeSignDrs LoadCmd = 0x2B // Code signing DRs copied from linked dylibs - LoadCmdEncryptionInfo64 LoadCmd = 0x2C // 64-bit encrypted segment information - LoadCmdLinkerOption LoadCmd = 0x2D // linker options in MH_OBJECT files - LoadCmdLinkerOptimizationHint LoadCmd = 0x2E // optimization hints in MH_OBJECT files - LoadCmdVersionMinTvos LoadCmd = 0x2F // build for AppleTV min OS version - LoadCmdVersionMinWatchos LoadCmd = 0x30 // build for Watch min OS version - LoadCmdNote LoadCmd = 0x31 // arbitrary data included within a Mach-O file - LoadCmdBuildVersion LoadCmd = 0x32 // build for platform min OS version - LoadCmdDyldExportsTrie LoadCmd = (0x33 | LoadCmdReqDyld) // used with linkedit_data_command, payload is trie - LoadCmdDyldChainedFixups LoadCmd = (0x34 | LoadCmdReqDyld) // used with linkedit_data_command -) - -var cmdStrings = []utils.IntName{ - {uint32(LoadCmdSegment), "LoadCmdSegment"}, - {uint32(LoadCmdSymtab), "LoadCmdSymtab"}, - {uint32(LoadCmdSymseg), "LoadCmdSymseg"}, - {uint32(LoadCmdThread), "LoadCmdThread"}, - {uint32(LoadCmdUnixThread), "LoadCmdUnixThread"}, - {uint32(LoadCmdLoadfvmlib), "LoadCmdLoadfvmlib"}, - {uint32(LoadCmdIdfvmlib), "LoadCmdIdfvmlib"}, - {uint32(LoadCmdIdent), "LoadCmdIdent"}, - {uint32(LoadCmdFvmfile), "LoadCmdFvmfile"}, - {uint32(LoadCmdPrepage), "LoadCmdPrepage"}, - {uint32(LoadCmdDysymtab), "LoadCmdDysymtab"}, - {uint32(LoadCmdDylib), "LoadCmdDylib"}, - {uint32(LoadCmdDylibID), "LoadCmdDylibID"}, - {uint32(LoadCmdDylinker), "LoadCmdDylinker"}, - {uint32(LoadCmdPreboundDylib), "LoadCmdPreboundDylib"}, - {uint32(LoadCmdRoutines), "LoadCmdRoutines"}, - {uint32(LoadCmdSubFramework), "LoadCmdSubFramework"}, - {uint32(LoadCmdSubUmbrella), "LoadCmdSubUmbrella"}, - {uint32(LoadCmdSubClient), "LoadCmdSubClient"}, - {uint32(LoadCmdSubLibrary), "LoadCmdSubLibrary"}, - {uint32(LoadCmdTwolevelHints), "LoadCmdTwolevelHints"}, - {uint32(LoadCmdPrebindCksum), "LoadCmdPrebindCksum"}, - {uint32(LoadCmdLoadWeakDylib), "LoadCmdLoadWeakDylib"}, - {uint32(LoadCmdSegment64), "LoadCmdSegment64"}, - {uint32(LoadCmdRoutines64), "LoadCmdRoutines64"}, - {uint32(LoadCmdUUID), "LoadCmdUUID"}, - {uint32(LoadCmdRpath), "LoadCmdRpath"}, - {uint32(LoadCmdCodeSignature), "LoadCmdCodeSignature"}, - {uint32(LoadCmdSegmentSplitInfo), "LoadCmdSegmentSplitInfo"}, - {uint32(LoadCmdReexportDylib), "LoadCmdReexportDylib"}, - {uint32(LoadCmdLazyLoadDylib), "LoadCmdLazyLoadDylib"}, - {uint32(LoadCmdEncryptionInfo), "LoadCmdEncryptionInfo"}, - {uint32(LoadCmdDyldInfo), "LoadCmdDyldInfo"}, - {uint32(LoadCmdDyldInfoOnly), "LoadCmdDyldInfoOnly"}, - {uint32(LoadCmdLoadUpwardDylib), "LoadCmdLoadUpwardDylib"}, - {uint32(LoadCmdVersionMinMacosx), "LoadCmdVersionMinMacosx"}, - {uint32(LoadCmdVersionMinIphoneos), "LoadCmdVersionMinIphoneos"}, - {uint32(LoadCmdFunctionStarts), "LoadCmdFunctionStarts"}, - {uint32(LoadCmdDyldEnvironment), "LoadCmdDyldEnvironment"}, - {uint32(LoadCmdMain), "LoadCmdMain"}, - {uint32(LoadCmdDataInCode), "LoadCmdDataInCode"}, - {uint32(LoadCmdSourceVersion), "LoadCmdSourceVersion"}, - {uint32(LoadCmdDylibCodeSignDrs), "LoadCmdDylibCodeSignDrs"}, - {uint32(LoadCmdEncryptionInfo64), "LoadCmdEncryptionInfo64"}, - {uint32(LoadCmdLinkerOption), "LoadCmdLinkerOption"}, - {uint32(LoadCmdLinkerOptimizationHint), "LoadCmdLinkerOptimizationHint"}, - {uint32(LoadCmdVersionMinTvos), "LoadCmdVersionMinTvos"}, - {uint32(LoadCmdVersionMinWatchos), "LoadCmdVersionMinWatchos"}, - {uint32(LoadCmdNote), "LoadCmdNote"}, - {uint32(LoadCmdBuildVersion), "LoadCmdBuildVersion"}, - {uint32(LoadCmdDyldExportsTrie), "LoadCmdDyldExportsTrie"}, - {uint32(LoadCmdDyldChainedFixups), "LoadCmdDyldChainedFixups"}, -} - -func (i LoadCmd) String() string { return utils.StringName(uint32(i), cmdStrings, false) } -func (i LoadCmd) GoString() string { return utils.StringName(uint32(i), cmdStrings, true) } - -type SegFlag uint32 - -/* Constants for the flags field of the segment_command */ -const ( - HighVM SegFlag = 0x1 /* the file contents for this segment is for - the high part of the VM space, the low part - is zero filled (for stacks in core files) */ - FvmLib SegFlag = 0x2 /* this segment is the VM that is allocated by - a fixed VM library, for overlap checking in - the link editor */ - NoReLoc SegFlag = 0x4 /* this segment has nothing that was relocated - in it and nothing relocated to it, that is - it maybe safely replaced without relocation*/ - ProtectedVersion1 SegFlag = 0x8 /* This segment is protected. If the - segment starts at file offset 0, the - first page of the segment is not - protected. All other pages of the - segment are protected. */ - ReadOnly SegFlag = 0x10 /* This segment is made read-only after fixups */ -) - -// A Segment32 is a 32-bit Mach-O segment load command. -type Segment32 struct { - Cmd LoadCmd /* LC_SEGMENT */ - Len uint32 /* includes sizeof section structs */ - Name [16]byte /* segment name */ - Addr uint32 /* memory address of this segment */ - Memsz uint32 /* memory size of this segment */ - Offset uint32 /* file offset of this segment */ - Filesz uint32 /* amount to map from the file */ - Maxprot types.VmProtection /* maximum VM protection */ - Prot types.VmProtection /* initial VM protection */ - Nsect uint32 /* number of sections in segment */ - Flag SegFlag /* flags */ -} - -// A SymtabCmd is a Mach-O symbol table command. -type SymtabCmd struct { - Cmd LoadCmd // LC_SYMTAB - Len uint32 - Symoff uint32 - Nsyms uint32 - Stroff uint32 - Strsize uint32 -} - -/* - * The symseg_command contains the offset and size of the GNU style - * symbol table information as described in the header file . - * The symbol roots of the symbol segments must also be aligned properly - * in the file. So the requirement of keeping the offsets aligned to a - * multiple of a 4 bytes translates to the length field of the symbol - * roots also being a multiple of a long. Also the padding must again be - * zeroed. (THIS IS OBSOLETE and no longer supported). - */ -type SymsegCommand struct { - cmd LoadCmd /* LC_SYMSEG */ - Len uint32 /* sizeof(struct symseg_command) */ - Offset uint32 /* symbol segment offset */ - Size uint32 /* symbol segment size in bytes */ -} - -// A Thread is a Mach-O thread state command. -type Thread struct { - Cmd LoadCmd // LC_THREAD - Len uint32 - Type uint32 - Data []uint32 -} - -// A UnixThreadCmd is a Mach-O unix thread command. -type UnixThreadCmd struct { - Cmd LoadCmd // LC_UNIXTHREAD - Len uint32 -} - -// A LoadFvmLibCmd is a Mach-O load a specified fixed VM shared library command. -type LoadFvmLibCmd struct { - Cmd LoadCmd // LC_IDFVMLIB or LC_LOADFVMLIB - Len uint32 - Name uint32 // library's target pathname - MinorVersion uint32 - HeaderAddr uint32 -} - -// A IDFvmLibCmd is a Mach-O fixed VM shared library identification command. -type IDFvmLibCmd LoadFvmLibCmd // LC_IDFVMLIB -// A IdentCmd is a Mach-O object identification info (obsolete) command. -type IdentCmd struct { - Cmd LoadCmd // LC_IDENT - Len uint32 -} - -// A FvmFileCmd is a Mach-O fixed VM file inclusion (internal use) command. -type FvmFileCmd struct { - Cmd LoadCmd // LC_FVMFILE - Len uint32 - Name uint32 // files pathname - HeaderAddr uint32 // files virtual address -} - -// A PrePageCmd is a Mach-O prepage command (internal use) command. -type PrePageCmd interface{} // LC_PREPAGE -// A DysymtabCmd is a Mach-O dynamic symbol table command. -type DysymtabCmd struct { - Cmd LoadCmd // LC_DYSYMTAB - 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 -} - -// A DylibCmd is a Mach-O load dynamic library command. -// LC_ID_DYLIB, LC_LOAD_{,WEAK_}DYLIB,LC_REEXPORT_DYLIB -type DylibCmd struct { - Cmd LoadCmd // LC_LOAD_DYLIB - Len uint32 - Name uint32 - Time uint32 - CurrentVersion types.Version - CompatVersion types.Version -} - -// A DylibID represents a Mach-O load dynamic library ident command. -type DylibID DylibCmd // LC_ID_DYLIB -// A DylinkerCmd is a Mach-O dynamic load a dynamic linker command. -type DylinkerCmd struct { - Cmd LoadCmd // LC_LOAD_DYLINKER - Len uint32 - Name uint32 // dynamic linker's path name -} - -// A DylinkerIDCmd is a Mach-O dynamic linker identification command. -type DylinkerIDCmd DylinkerCmd // LC_ID_DYLINKER -// PreboundDylibCmd are modules prebound for a dynamically linked shared library -type PreboundDylibCmd struct { - Cmd LoadCmd // LC_PREBOUND_DYLIB - Len uint32 - Name uint32 // library's path name - NumModules uint32 // number of modules in library - LinkedModules uint32 // bit vector of linked modules -} - -// A RoutinesCmd is a Mach-O image routines command. -type RoutinesCmd struct { - Cmd LoadCmd // LC_ROUTINES - Len uint32 - InitAddress uint32 - InitModule uint32 - Reserved1 uint32 - Reserved2 uint32 - Reserved3 uint32 - Reserved4 uint32 - Reserved5 uint32 - Reserved6 uint32 -} - -// A SubFrameworkCmd is a Mach-O dynamic sub_framework_command. -type SubFrameworkCmd struct { - Cmd LoadCmd // LC_SUB_FRAMEWORK - Len uint32 - Framework uint32 -} - -// A SubUmbrellaCmd is a Mach-O dynamic sub_umbrella_command. -type SubUmbrellaCmd struct { - Cmd LoadCmd // LC_SUB_UMBRELLA - Len uint32 - Umbrella uint32 -} - -// A SubClientCmd is a Mach-O dynamic sub client command. -type SubClientCmd struct { - Cmd LoadCmd // LC_SUB_CLIENT - Len uint32 - Client uint32 -} - -// A SubLibraryCmd is a Mach-O dynamic sub_library_command. -type SubLibraryCmd struct { - Cmd LoadCmd // LC_SUB_LIBRARY - Len uint32 - Library uint32 -} - -// A TwolevelHintsCmd is a Mach-O two-level namespace lookup hints command. -type TwolevelHintsCmd struct { - Cmd LoadCmd // LC_TWOLEVEL_HINTS - Len uint32 - Offset uint32 - NumHints uint32 -} - -// A PrebindCksumCmd is a Mach-O prebind checksum command. -type PrebindCksumCmd struct { - Cmd LoadCmd // LC_PREBIND_CKSUM - Len uint32 - CheckSum uint32 -} - -// A WeakDylibCmd is a Mach-O load a dynamically linked shared library that is allowed to be missing -// (all symbols are weak imported) command. -type WeakDylibCmd DylibCmd // LC_LOAD_WEAK_DYLIB -// A Segment64 is a 64-bit Mach-O segment load command. -type Segment64 struct { - Cmd LoadCmd /* LC_SEGMENT_64 */ - Len uint32 /* includes sizeof section_64 structs */ - Name [16]byte /* segment name */ - Addr uint64 /* memory address of this segment */ - Memsz uint64 /* memory size of this segment */ - Offset uint64 /* file offset of this segment */ - Filesz uint64 /* amount to map from the file */ - Maxprot types.VmProtection /* maximum VM protection */ - Prot types.VmProtection /* initial VM protection */ - Nsect uint32 /* number of sections in segment */ - Flag SegFlag /* flags */ -} - -// A Routines64Cmd is a Mach-O 64-bit image routines command. -type Routines64Cmd struct { - Cmd LoadCmd // LC_ROUTINES_64 - Len uint32 - InitAddress uint64 - InitModule uint64 - Reserved1 uint64 - Reserved2 uint64 - Reserved3 uint64 - Reserved4 uint64 - Reserved5 uint64 - Reserved6 uint64 -} - -// A UUIDCmd is a Mach-O uuid load command contains a single -// 128-bit unique random number that identifies an object produced -// by the static link editor. -type UUIDCmd struct { - Cmd LoadCmd // LC_UUID - Len uint32 - UUID types.UUID -} - -// A RpathCmd is a Mach-O rpath command. -type RpathCmd struct { - Cmd LoadCmd // LC_RPATH - Len uint32 - Path uint32 -} - -// A LinkEditDataCmd is a Mach-O linkedit data command. -type LinkEditDataCmd struct { - Cmd LoadCmd - Len uint32 - Offset uint32 - Size uint32 -} - -// A CodeSignatureCmd is a Mach-O code signature command. -type CodeSignatureCmd LinkEditDataCmd // LC_CODE_SIGNATURE -// A SegmentSplitInfoCmd is a Mach-O code info to split segments command. -type SegmentSplitInfoCmd LinkEditDataCmd // LC_SEGMENT_SPLIT_INFO -// A ReExportDylibCmd is a Mach-O load and re-export dylib command. -type ReExportDylibCmd DylibCmd // LC_REEXPORT_DYLIB -// A LazyLoadDylibCmd is a Mach-O delay load of dylib until first use command. -type LazyLoadDylibCmd DylibCmd // LC_LAZY_LOAD_DYLIB -// A EncryptionInfoCmd is a Mach-O encrypted segment information command. -type EncryptionInfoCmd struct { - Cmd LoadCmd // LC_ENCRYPTION_INFO - Len uint32 - Offset uint32 // file offset of encrypted range - Size uint32 // file size of encrypted range - CryptID uint32 // which enryption system, 0 means not-encrypted yet -} - -// A DyldInfoCmd is a Mach-O id dyld info command. -type DyldInfoCmd struct { - Cmd LoadCmd // LC_DYLD_INFO - Len uint32 - RebaseOff uint32 // file offset to rebase info - RebaseSize uint32 // size of rebase info - BindOff uint32 // file offset to binding info - BindSize uint32 // size of binding info - WeakBindOff uint32 // file offset to weak binding info - WeakBindSize uint32 // size of weak binding info - LazyBindOff uint32 // file offset to lazy binding info - LazyBindSize uint32 // size of lazy binding info - ExportOff uint32 // file offset to export info - ExportSize uint32 // size of export info -} - -// A DyldInfoOnlyCmd is a Mach-O compressed dyld information only command. -type DyldInfoOnlyCmd DyldInfoCmd // LC_DYLD_INFO_ONLY -// A UpwardDylibCmd is a Mach-O load upward dylibcommand. -type UpwardDylibCmd DylibCmd // LC_LOAD_UPWARD_DYLIB -// A VersionMinCmd is a Mach-O version min command. -type VersionMinCmd struct { - Cmd LoadCmd - Len uint32 - Version types.Version - Sdk types.Version -} - -// A VersionMinMacOSCmd is a Mach-O build for macOS min OS version command. -type VersionMinMacOSCmd VersionMinCmd // LC_VERSION_MIN_MACOSX -// A VersionMinIPhoneOSCmd is a Mach-O build for iPhoneOS min OS version command. -type VersionMinIPhoneOSCmd VersionMinCmd // LC_VERSION_MIN_IPHONEOS -// A FunctionStartsCmd is a Mach-O compressed table of function start addresses command. -type FunctionStartsCmd LinkEditDataCmd // LC_FUNCTION_STARTS -// A DyldEnvironmentCmd is a Mach-O string for dyld to treat like environment variable command. -type DyldEnvironmentCmd DylinkerCmd // LC_DYLD_ENVIRONMENT -// A EntryPointCmd is a Mach-O main command. -type EntryPointCmd struct { - Cmd LoadCmd // LC_MAIN only used in MH_EXECUTE filetypes - Len uint32 // 24 - Offset uint64 // file (__TEXT) offset of main() - StackSize uint64 // if not zero, initial stack size -} - -// A DataInCodeCmd is a Mach-O data in code command. -type DataInCodeCmd LinkEditDataCmd // LC_DATA_IN_CODE -// A SourceVersionCmd is a Mach-O source version command. -type SourceVersionCmd struct { - Cmd LoadCmd // LC_SOURCE_VERSION - Len uint32 - Version types.SrcVersion // A.B.C.D.E packed as a24.b10.c10.d10.e10 -} - -// A DylibCodeSignDrsCmd is a Mach-O code signing DRs copied from linked dylibs command. -type DylibCodeSignDrsCmd LinkEditDataCmd // LC_DYLIB_CODE_SIGN_DRS -// A EncryptionInfo64Cmd is a Mach-O 64-bit encrypted segment information command. -type EncryptionInfo64Cmd struct { - Cmd LoadCmd // LC_ENCRYPTION_INFO_64 - Len uint32 - Offset uint32 // file offset of encrypted range - Size uint32 // file size of encrypted range - CryptID uint32 // which enryption system, 0 means not-encrypted yet - Pad uint32 // padding to make this struct's size a multiple of 8 bytes -} - -// A LinkerOptionCmd is a Mach-O main command. -type LinkerOptionCmd struct { - Cmd LoadCmd // LC_LINKER_OPTION only used in MH_OBJECT filetypes - Len uint32 - Count uint32 // number of strings concatenation of zero terminated UTF8 strings. Zero filled at end to align -} - -// A LinkerOptimizationHintCmd is a Mach-O optimization hints command. -type LinkerOptimizationHintCmd LinkEditDataCmd // LC_LINKER_OPTIMIZATION_HINT -// A VersionMinTvOSCmd is a Mach-O build for tvOS min OS version command. -type VersionMinTvOSCmd VersionMinCmd // LC_VERSION_MIN_TVOS -// A VersionMinWatchOSCmd is a Mach-O build for watchOS min OS version command. -type VersionMinWatchOSCmd VersionMinCmd // LC_VERSION_MIN_WATCHOS -// A NoteCmd is a Mach-O note command. -type NoteCmd struct { - Cmd LoadCmd // LC_NOTE - Len uint32 - DataOwner [16]byte - Offset uint64 - Size uint64 -} - -/* -* The build_version_command contains the min OS version on which this -* binary was built to run for its platform. The list of known platforms and -* tool values following it. - */ -type BuildVersionCmd struct { - Cmd LoadCmd /* LC_BUILD_VERSION */ - Len uint32 /* sizeof(struct build_version_command) plus */ - /* ntools * sizeof(struct build_tool_version) */ - Platform types.Platform /* platform */ - Minos types.Version /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ - Sdk types.Version /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ - NumTools uint32 /* number of tool entries following this */ -} - -// A DyldExportsTrieCmd is used with linkedit_data_command, payload is trie command. -type DyldExportsTrieCmd LinkEditDataCmd // LC_DYLD_EXPORTS_TRIE -// A DyldChainedFixupsCmd is used with linkedit_data_command command. -type DyldChainedFixupsCmd LinkEditDataCmd // LC_DYLD_CHAINED_FIXUPS diff --git a/pkg/macho/commands/section.go b/pkg/macho/commands/section.go deleted file mode 100644 index bcd87be1b..000000000 --- a/pkg/macho/commands/section.go +++ /dev/null @@ -1,391 +0,0 @@ -package commands - -import ( - "fmt" - "strings" -) - -// 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 SectionFlag - Reserve1 uint32 - Reserve2 uint32 -} - -// A Section64 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 SectionFlag - Reserve1 uint32 - Reserve2 uint32 - Reserve3 uint32 -} - -type SectionFlag uint32 - -const ( - SectionType SectionFlag = 0x000000ff /* 256 section types */ - SectionAttributes SectionFlag = 0xffffff00 /* 24 section attributes */ -) - -/* - * The flags field of a section structure is separated into two parts a section - * type and section attributes. The section types are mutually exclusive (it - * can only have one type) but the section attributes are not (it may have more - * than one attribute). - */ -const ( - /* Constants for the type of a section */ - Regular SectionFlag = 0x0 /* regular section */ - Zerofill SectionFlag = 0x1 /* zero fill on demand section */ - CstringLiterals SectionFlag = 0x2 /* section with only literal C strings*/ - ByteLiterals4 SectionFlag = 0x3 /* section with only 4 byte literals */ - ByteLiterals8 SectionFlag = 0x4 /* section with only 8 byte literals */ - LiteralPointers SectionFlag = 0x5 /* section with only pointers to literals */ - /* - * For the two types of symbol pointers sections and the symbol stubs section - * they have indirect symbol table entries. For each of the entries in the - * section the indirect symbol table entries, in corresponding order in the - * indirect symbol table, start at the index stored in the reserved1 field - * of the section structure. Since the indirect symbol table entries - * correspond to the entries in the section the number of indirect symbol table - * entries is inferred from the size of the section divided by the size of the - * entries in the section. For symbol pointers sections the size of the entries - * in the section is 4 bytes and for symbol stubs sections the byte size of the - * stubs is stored in the reserved2 field of the section structure. - */ - NonLazySymbolPointers SectionFlag = 0x6 /* section with only non-lazy symbol pointers */ - LazySymbolPointers SectionFlag = 0x7 /* section with only lazy symbol pointers */ - SymbolStubs SectionFlag = 0x8 /* section with only symbol stubs, byte size of stub in the reserved2 field */ - ModInitFuncPointers SectionFlag = 0x9 /* section with only function pointers for initialization*/ - ModTermFuncPointers SectionFlag = 0xa /* section with only function pointers for termination */ - Coalesced SectionFlag = 0xb /* section contains symbols that are to be coalesced */ - GbZerofill SectionFlag = 0xc /* zero fill on demand section (that can be larger than 4 gigabytes) */ - Interposing SectionFlag = 0xd /* section with only pairs of function pointers for interposing */ - ByteLiterals16 SectionFlag = 0xe /* section with only 16 byte literals */ - DtraceDof SectionFlag = 0xf /* section contains DTrace Object Format */ - LazyDylibSymbolPointers SectionFlag = 0x10 /* section with only lazy symbol pointers to lazy loaded dylibs */ - /* - * Section types to support thread local variables - */ - ThreadLocalRegular SectionFlag = 0x11 /* template of initial values for TLVs */ - ThreadLocalZerofill SectionFlag = 0x12 /* template of initial values for TLVs */ - ThreadLocalVariables SectionFlag = 0x13 /* TLV descriptors */ - ThreadLocalVariablePointers SectionFlag = 0x14 /* pointers to TLV descriptors */ - ThreadLocalInitFunctionPointers SectionFlag = 0x15 /* functions to call to initialize TLV values */ - InitFuncOffsets SectionFlag = 0x16 /* 32-bit offsets to initializers */ -) - -func (t SectionFlag) IsRegular() bool { - return (t & SectionType) == Regular -} - -func (t SectionFlag) IsZerofill() bool { - return (t & SectionType) == Zerofill -} - -func (t SectionFlag) IsCstringLiterals() bool { - return (t & SectionType) == CstringLiterals -} - -func (t SectionFlag) Is4ByteLiterals() bool { - return (t & SectionType) == ByteLiterals4 -} - -func (t SectionFlag) Is8ByteLiterals() bool { - return (t & SectionType) == ByteLiterals8 -} - -func (t SectionFlag) IsLiteralPointers() bool { - return (t & SectionType) == LiteralPointers -} - -func (t SectionFlag) IsNonLazySymbolPointers() bool { - return (t & SectionType) == NonLazySymbolPointers -} - -func (t SectionFlag) IsLazySymbolPointers() bool { - return (t & SectionType) == LazySymbolPointers -} - -func (t SectionFlag) IsSymbolStubs() bool { - return (t & SectionType) == SymbolStubs -} - -func (t SectionFlag) IsModInitFuncPointers() bool { - return (t & SectionType) == ModInitFuncPointers -} - -func (t SectionFlag) IsModTermFuncPointers() bool { - return (t & SectionType) == ModTermFuncPointers -} - -func (t SectionFlag) IsCoalesced() bool { - return (t & SectionType) == Coalesced -} - -func (t SectionFlag) IsGbZerofill() bool { - return (t & SectionType) == GbZerofill -} - -func (t SectionFlag) IsInterposing() bool { - return (t & SectionType) == Interposing -} - -func (t SectionFlag) Is16ByteLiterals() bool { - return (t & SectionType) == ByteLiterals16 -} - -func (t SectionFlag) IsDtraceDof() bool { - return (t & SectionType) == DtraceDof -} - -func (t SectionFlag) IsLazyDylibSymbolPointers() bool { - return (t & SectionType) == LazyDylibSymbolPointers -} - -func (t SectionFlag) IsThreadLocalRegular() bool { - return (t & SectionType) == ThreadLocalRegular -} - -func (t SectionFlag) IsThreadLocalZerofill() bool { - return (t & SectionType) == ThreadLocalZerofill -} - -func (t SectionFlag) IsThreadLocalVariables() bool { - return (t & SectionType) == ThreadLocalVariables -} - -func (t SectionFlag) IsThreadLocalVariablePointers() bool { - return (t & SectionType) == ThreadLocalVariablePointers -} - -func (t SectionFlag) IsThreadLocalInitFunctionPointers() bool { - return (t & SectionType) == ThreadLocalInitFunctionPointers -} - -func (t SectionFlag) IsInitFuncOffsets() bool { - return (t & SectionType) == InitFuncOffsets -} - -func (f SectionFlag) List() []string { - var flags []string - // if f.IsRegular() { - // fStr += "Regular, " - // } - if f.IsZerofill() { - flags = append(flags, "Zerofill") - } - if f.IsCstringLiterals() { - flags = append(flags, "Cstring Literals") - } - if f.Is4ByteLiterals() { - flags = append(flags, "4Byte Literals") - } - if f.Is8ByteLiterals() { - flags = append(flags, "8Byte Literals") - } - if f.IsLiteralPointers() { - flags = append(flags, "Literal Pointers") - } - if f.IsNonLazySymbolPointers() { - flags = append(flags, "NonLazySymbolPointers") - } - if f.IsLazySymbolPointers() { - flags = append(flags, "LazySymbolPointers") - } - if f.IsSymbolStubs() { - flags = append(flags, "SymbolStubs") - } - if f.IsModInitFuncPointers() { - flags = append(flags, "ModInitFuncPointers") - } - if f.IsModTermFuncPointers() { - flags = append(flags, "ModTermFuncPointers") - } - if f.IsCoalesced() { - flags = append(flags, "Coalesced") - } - if f.IsGbZerofill() { - flags = append(flags, "GbZerofill") - } - if f.IsInterposing() { - flags = append(flags, "Interposing") - } - if f.Is16ByteLiterals() { - flags = append(flags, "16Byte Literals") - } - if f.IsDtraceDof() { - flags = append(flags, "Dtrace DOF") - } - if f.IsLazyDylibSymbolPointers() { - flags = append(flags, "LazyDylibSymbolPointers") - } - if f.IsThreadLocalRegular() { - flags = append(flags, "ThreadLocalRegular") - } - if f.IsThreadLocalZerofill() { - flags = append(flags, "ThreadLocalZerofill") - } - if f.IsThreadLocalVariables() { - flags = append(flags, "ThreadLocalVariables") - } - if f.IsThreadLocalVariablePointers() { - flags = append(flags, "ThreadLocalVariablePointers") - } - if f.IsThreadLocalInitFunctionPointers() { - flags = append(flags, "ThreadLocalInitFunctionPointers") - } - if f.IsInitFuncOffsets() { - flags = append(flags, "InitFuncOffsets") - } - return flags -} - -func (f SectionFlag) String() string { - var fStr string - for _, attr := range f.List() { - fStr += fmt.Sprintf("%s, ", attr) - } - return strings.TrimSuffix(fStr, ", ") -} - -const ( - /* - * Constants for the section attributes part of the flags field of a section - * structure. - */ - SECTION_ATTRIBUTES_USR SectionFlag = 0xff000000 /* User setable attributes */ - SECTION_ATTRIBUTES_SYS SectionFlag = 0x00ffff00 /* system setable attributes */ - - PURE_INSTRUCTIONS SectionFlag = 0x80000000 /* section contains only true machine instructions */ - NO_TOC SectionFlag = 0x40000000 /* section contains coalesced symbols that are not to be in a ranlib table of contents */ - STRIP_STATIC_SYMS SectionFlag = 0x20000000 /* ok to strip static symbols in this section in files with the MH_DYLDLINK flag */ - NO_DEAD_STRIP SectionFlag = 0x10000000 /* no dead stripping */ - LIVE_SUPPORT SectionFlag = 0x08000000 /* blocks are live if they reference live blocks */ - SELF_MODIFYING_CODE SectionFlag = 0x04000000 /* Used with i386 code stubs written on by dyld */ - /* - * If a segment contains any sections marked with DEBUG then all - * sections in that segment must have this attribute. No section other than - * a section marked with this attribute may reference the contents of this - * section. A section with this attribute may contain no symbols and must have - * a section type S_REGULAR. The static linker will not copy section contents - * from sections with this attribute into its output file. These sections - * generally contain DWARF debugging info. - */ - DEBUG SectionFlag = 0x02000000 /* a debug section */ - SOME_INSTRUCTIONS SectionFlag = 0x00000400 /* section contains some machine instructions */ - EXT_RELOC SectionFlag = 0x00000200 /* section has external relocation entries */ - LOC_RELOC SectionFlag = 0x00000100 /* section has local relocation entries */ -) - -func (t SectionFlag) GetAttributes() SectionFlag { - return (t & SectionAttributes) -} - -func (t SectionFlag) IsPureInstructions() bool { - return (t.GetAttributes() & PURE_INSTRUCTIONS) != 0 -} -func (t SectionFlag) IsNoToc() bool { - return (t.GetAttributes() & NO_TOC) != 0 -} -func (t SectionFlag) IsStripStaticSyms() bool { - return (t.GetAttributes() & STRIP_STATIC_SYMS) != 0 -} -func (t SectionFlag) IsNoDeadStrip() bool { - return (t.GetAttributes() & NO_DEAD_STRIP) != 0 -} -func (t SectionFlag) IsLiveSupport() bool { - return (t.GetAttributes() & LIVE_SUPPORT) != 0 -} -func (t SectionFlag) IsSelfModifyingCode() bool { - return (t.GetAttributes() & SELF_MODIFYING_CODE) != 0 -} -func (t SectionFlag) IsDebug() bool { - return (t.GetAttributes() & DEBUG) != 0 -} -func (t SectionFlag) IsSomeInstructions() bool { - return (t.GetAttributes() & SOME_INSTRUCTIONS) != 0 -} -func (t SectionFlag) IsExtReloc() bool { - return (t.GetAttributes() & EXT_RELOC) != 0 -} -func (t SectionFlag) IsLocReloc() bool { - return (t.GetAttributes() & LOC_RELOC) != 0 -} - -func (f SectionFlag) AttributesList() []string { - var attrs []string - if f.IsPureInstructions() { - attrs = append(attrs, "PureInstructions") - } - if f.IsNoToc() { - attrs = append(attrs, "NoToc") - } - if f.IsStripStaticSyms() { - attrs = append(attrs, "StripStaticSyms") - } - if f.IsNoDeadStrip() { - attrs = append(attrs, "NoDeadStrip") - } - if f.IsLiveSupport() { - attrs = append(attrs, "LiveSupport") - } - if f.IsSelfModifyingCode() { - attrs = append(attrs, "SelfModifyingCode") - } - if f.IsDebug() { - attrs = append(attrs, "Debug") - } - if f.IsSomeInstructions() { - attrs = append(attrs, "SomeInstructions") - } - if f.IsExtReloc() { - attrs = append(attrs, "ExtReloc") - } - if f.IsLocReloc() { - attrs = append(attrs, "LocReloc") - } - return attrs -} - -func (f SectionFlag) AttributesString() string { - var aStr string - for _, attr := range f.AttributesList() { - aStr += fmt.Sprintf("%s|", attr) - } - return strings.TrimSuffix(aStr, "|") -} - -// func (ss sections) Print() { -// var secFlags string -// // var prevSeg string -// w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) -// for _, sec := range ss { -// secFlags = "" -// if !sec.Flags.IsRegular() { -// secFlags = fmt.Sprintf("(%s)", sec.Flags) -// } -// // if !strings.EqualFold(sec.Seg, prevSeg) && len(prevSeg) > 0 { -// // fmt.Fprintf(w, "\n") -// // } -// fmt.Fprintf(w, "Mem: 0x%x-0x%x \t %s.%s \t %s \t %s\n", sec.Addr, sec.Addr+sec.Size, sec.Seg, sec.Name, secFlags, sec.Flags.AttributesString()) -// // prevSeg = sec.Seg -// } -// w.Flush() -// } diff --git a/pkg/macho/dyld.go b/pkg/macho/dyld.go deleted file mode 100644 index 214d108ec..000000000 --- a/pkg/macho/dyld.go +++ /dev/null @@ -1,527 +0,0 @@ -package macho - -import ( - "bytes" - "encoding/binary" - "io" - - "github.com/apex/log" - "github.com/blacktop/ipsw/pkg/macho/commands" - "github.com/blacktop/ipsw/pkg/macho/header" - "github.com/blacktop/ipsw/pkg/macho/types" -) - -func loadInSlice(c commands.LoadCmd, list []commands.LoadCmd) bool { - for _, b := range list { - if b == c { - return true - } - } - return false -} - -// NewFileFromDyld creates a new File for accessing an in-cache Dylib data in an underlying reader. -// The Dylib data buffer is expected to start at position 0 in the ReaderAt. -func NewFileFromDyld(r io.ReaderAt, loads ...commands.LoadCmd) (*File, error) { - // func NewFileFromDyld(r io.ReaderAt, vmaToOffsetMap map[uint64]uint64) (*File, error) { - f := new(File) - sr := io.NewSectionReader(r, 0, 1<<63-1) - - // Read and decode Mach magic to determine byte order, size. - // Magic32 and Magic64 differ only in the bottom bit. - var ident [4]byte - if _, err := r.ReadAt(ident[0:], 0); err != nil { - return nil, err - } - be := binary.BigEndian.Uint32(ident[0:]) - le := binary.LittleEndian.Uint32(ident[0:]) - switch header.Magic32.Int() &^ 1 { - case be &^ 1: - f.ByteOrder = binary.BigEndian - f.Magic = header.Magic(be) - case le &^ 1: - f.ByteOrder = binary.LittleEndian - f.Magic = header.Magic(le) - default: - return nil, &FormatError{0, "invalid magic number", nil} - } - - // Read entire file header. - if err := binary.Read(sr, f.ByteOrder, &f.FileHeader); err != nil { - return nil, err - } - // Then load commands. - offset := int64(header.FileHeaderSize32) - if f.Magic == header.Magic64 { - offset = header.FileHeaderSize64 - } - dat := make([]byte, f.Cmdsz) - if _, err := r.ReadAt(dat, offset); err != nil { - return nil, err - } - f.Loads = make([]Load, f.Ncmd) - bo := f.ByteOrder - for i := range f.Loads { - // Each load command begins with uint32 command and length. - if len(dat) < 8 { - return nil, &FormatError{offset, "command block too small", nil} - } - cmd, siz := commands.LoadCmd(bo.Uint32(dat[0:4])), bo.Uint32(dat[4:8]) - if siz < 8 || siz > uint32(len(dat)) { - return nil, &FormatError{offset, "invalid command block size", nil} - } - // skip unwanted load commands - if !loadInSlice(cmd, loads) { - continue - } - - var cmddat []byte - cmddat, dat = dat[0:siz], dat[siz:] - offset += int64(siz) - var s *Segment - switch cmd { - default: - log.Warnf("found NEW load command: %s", cmd) - f.Loads[i] = LoadBytes(cmddat) - case commands.LoadCmdSegment: - var seg32 commands.Segment32 - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &seg32); err != nil { - return nil, err - } - s = new(Segment) - s.LoadBytes = cmddat - s.Cmd = cmd - s.Len = siz - s.Name = cstring(seg32.Name[0:]) - s.Addr = uint64(seg32.Addr) - s.Memsz = uint64(seg32.Memsz) - s.Offset = uint64(seg32.Offset) - s.Filesz = uint64(seg32.Filesz) - s.Maxprot = seg32.Maxprot - s.Prot = seg32.Prot - s.Nsect = seg32.Nsect - s.Flag = seg32.Flag - f.Loads[i] = s - for i := 0; i < int(s.Nsect); i++ { - var sh32 commands.Section32 - if err := binary.Read(b, bo, &sh32); err != nil { - return nil, err - } - sh := new(Section) - sh.Name = cstring(sh32.Name[0:]) - sh.Seg = cstring(sh32.Seg[0:]) - sh.Addr = uint64(sh32.Addr) - sh.Size = uint64(sh32.Size) - sh.Offset = sh32.Offset - sh.Align = sh32.Align - sh.Reloff = sh32.Reloff - sh.Nreloc = sh32.Nreloc - sh.Flags = sh32.Flags - if err := f.pushSection(sh, r); err != nil { - return nil, err - } - } - case commands.LoadCmdSegment64: - var seg64 commands.Segment64 - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &seg64); err != nil { - return nil, err - } - s = new(Segment) - s.LoadBytes = cmddat - s.Cmd = cmd - s.Len = siz - s.Name = cstring(seg64.Name[0:]) - s.Addr = seg64.Addr - s.Memsz = seg64.Memsz - s.Offset = seg64.Offset - s.Filesz = seg64.Filesz - s.Maxprot = seg64.Maxprot - s.Prot = seg64.Prot - s.Nsect = seg64.Nsect - s.Flag = seg64.Flag - f.Loads[i] = s - for i := 0; i < int(s.Nsect); i++ { - var sh64 commands.Section64 - if err := binary.Read(b, bo, &sh64); err != nil { - return nil, err - } - sh := new(Section) - sh.Name = cstring(sh64.Name[0:]) - sh.Seg = cstring(sh64.Seg[0:]) - sh.Addr = sh64.Addr - sh.Size = sh64.Size - sh.Offset = sh64.Offset - sh.Align = sh64.Align - sh.Reloff = sh64.Reloff - sh.Nreloc = sh64.Nreloc - sh.Flags = sh64.Flags - if err := f.pushSection(sh, r); err != nil { - return nil, err - } - } - case commands.LoadCmdSymtab: - var hdr commands.SymtabCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &hdr); err != nil { - return nil, err - } - strtab := make([]byte, hdr.Strsize) - if _, err := r.ReadAt(strtab, int64(hdr.Stroff)); err != nil { - return f, nil - // return nil, err - } - var symsz int - if f.Magic == header.Magic64 { - symsz = 16 - } else { - symsz = 12 - } - symdat := make([]byte, int(hdr.Nsyms)*symsz) - if _, err := r.ReadAt(symdat, int64(hdr.Symoff)); err != nil { - return nil, err - } - st, err := f.parseSymtab(symdat, strtab, cmddat, &hdr, offset) - if err != nil { - return nil, err - } - f.Loads[i] = st - f.Symtab = st - // case commands.LoadCmdSymseg: - // case commands.LoadCmdThread: - case commands.LoadCmdUnixThread: - var ut commands.UnixThreadCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &ut); err != nil { - return nil, err - } - l := new(UnixThread) - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - // case commands.LoadCmdLoadfvmlib: - // case commands.LoadCmdIdfvmlib: - // case commands.LoadCmdIdent: - // case commands.LoadCmdFvmfile: - // case commands.LoadCmdPrepage: - case commands.LoadCmdDysymtab: - var hdr commands.DysymtabCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &hdr); err != nil { - return nil, err - } - dat := make([]byte, hdr.Nindirectsyms*4) - if _, err := r.ReadAt(dat, int64(hdr.Indirectsymoff)); err != nil { - return nil, err - } - x := make([]uint32, hdr.Nindirectsyms) - if err := binary.Read(bytes.NewReader(dat), bo, x); err != nil { - return nil, err - } - st := new(Dysymtab) - st.LoadBytes = LoadBytes(cmddat) - st.DysymtabCmd = hdr - st.IndirectSyms = x - f.Loads[i] = st - f.Dysymtab = st - case commands.LoadCmdDylib: - var hdr commands.DylibCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &hdr); err != nil { - return nil, err - } - l := new(Dylib) - if hdr.Name >= uint32(len(cmddat)) { - return nil, &FormatError{offset, "invalid name in dynamic library command", hdr.Name} - } - l.Name = cstring(cmddat[hdr.Name:]) - l.Time = hdr.Time - l.CurrentVersion = hdr.CurrentVersion.String() - l.CompatVersion = hdr.CompatVersion.String() - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - case commands.LoadCmdDylibID: - var hdr commands.DylibCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &hdr); err != nil { - return nil, err - } - l := new(DylibID) - if hdr.Name >= uint32(len(cmddat)) { - return nil, &FormatError{offset, "invalid name in dynamic library ident command", hdr.Name} - } - l.Name = cstring(cmddat[hdr.Name:]) - l.Time = hdr.Time - l.CurrentVersion = hdr.CurrentVersion.String() - l.CompatVersion = hdr.CompatVersion.String() - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - // case commands.LoadCmdDylinker: - // case commands.LoadCmdDylinkerID: - // case commands.LoadCmdPreboundDylib: - // case commands.LoadCmdRoutines: - case commands.LoadCmdSubFramework: - var sf commands.SubFrameworkCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &sf); err != nil { - return nil, err - } - l := new(SubFramework) - if sf.Framework >= uint32(len(cmddat)) { - return nil, &FormatError{offset, "invalid framework in subframework command", sf.Framework} - } - l.Framework = cstring(cmddat[sf.Framework:]) - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - // case commands.LoadCmdSubUmbrella: - case commands.LoadCmdSubClient: - var sc commands.SubClientCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &sc); err != nil { - return nil, err - } - l := new(SubClient) - if sc.Client >= uint32(len(cmddat)) { - return nil, &FormatError{offset, "invalid path in sub client command", sc.Client} - } - l.Name = cstring(cmddat[sc.Client:]) - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - // case commands.LoadCmdSubLibrary: - // case commands.LoadCmdTwolevelHints: - // case commands.LoadCmdPrebindCksum: - case commands.LoadCmdLoadWeakDylib: - var hdr commands.DylibCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &hdr); err != nil { - return nil, err - } - l := new(WeakDylib) - if hdr.Name >= uint32(len(cmddat)) { - return nil, &FormatError{offset, "invalid name in weak dynamic library command", hdr.Name} - } - l.Name = cstring(cmddat[hdr.Name:]) - l.Time = hdr.Time - l.CurrentVersion = hdr.CurrentVersion.String() - l.CompatVersion = hdr.CompatVersion.String() - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - case commands.LoadCmdRoutines64: - var r64 commands.Routines64Cmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &r64); err != nil { - return nil, err - } - l := new(Routines64) - l.InitAddress = r64.InitAddress - l.InitModule = r64.InitModule - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - case commands.LoadCmdUUID: - var u commands.UUIDCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &u); err != nil { - return nil, err - } - l := new(UUID) - l.ID = u.UUID.String() - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - case commands.LoadCmdRpath: - var hdr commands.RpathCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &hdr); err != nil { - return nil, err - } - l := new(Rpath) - if hdr.Path >= uint32(len(cmddat)) { - return nil, &FormatError{offset, "invalid path in rpath command", hdr.Path} - } - l.Path = cstring(cmddat[hdr.Path:]) - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - // case commands.LoadCmdCodeSignature: - // case commands.LoadCmdSegmentSplitInfo: - case commands.LoadCmdReexportDylib: - var hdr commands.ReExportDylibCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &hdr); err != nil { - return nil, err - } - l := new(ReExportDylib) - if hdr.Name >= uint32(len(cmddat)) { - return nil, &FormatError{offset, "invalid name in dynamic library command", hdr.Name} - } - l.Name = cstring(cmddat[hdr.Name:]) - l.Time = hdr.Time - l.CurrentVersion = hdr.CurrentVersion.String() - l.CompatVersion = hdr.CompatVersion.String() - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - // case commands.LoadCmdLazyLoadDylib: - // case commands.LoadCmdEncryptionInfo: - case commands.LoadCmdDyldInfo: - case commands.LoadCmdDyldInfoOnly: - var info commands.DyldInfoCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &info); err != nil { - return nil, err - } - l := new(DyldInfo) - l.RebaseOff = info.RebaseOff - l.RebaseSize = info.RebaseSize - l.BindOff = info.BindOff - l.BindSize = info.BindSize - l.WeakBindOff = info.WeakBindOff - l.WeakBindSize = info.WeakBindSize - l.LazyBindOff = info.LazyBindOff - l.LazyBindSize = info.LazyBindSize - l.ExportOff = info.ExportOff - l.ExportSize = info.ExportSize - f.Loads[i] = l - case commands.LoadCmdLoadUpwardDylib: - var hdr commands.UpwardDylibCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &hdr); err != nil { - return nil, err - } - l := new(UpwardDylib) - if hdr.Name >= uint32(len(cmddat)) { - return nil, &FormatError{offset, "invalid name in load upwardl dylib command", hdr.Name} - } - l.Name = cstring(cmddat[hdr.Name:]) - l.Time = hdr.Time - l.CurrentVersion = hdr.CurrentVersion.String() - l.CompatVersion = hdr.CompatVersion.String() - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - // case commands.LoadCmdVersionMinMacosx: - // case commands.LoadCmdVersionMinIphoneos: - case commands.LoadCmdFunctionStarts: - var led commands.LinkEditDataCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &led); err != nil { - return nil, err - } - l := new(FunctionStarts) - l.Offset = led.Offset - l.Size = led.Size - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - // case commands.LoadCmdDyldEnvironment: - // case commands.LoadCmdMain: - case commands.LoadCmdDataInCode: - var led commands.LinkEditDataCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &led); err != nil { - return nil, err - } - l := new(DataInCode) - // var e DataInCodeEntry - - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - case commands.LoadCmdSourceVersion: - var sv commands.SourceVersionCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &sv); err != nil { - return nil, err - } - l := new(SourceVersion) - l.Version = sv.Version.String() - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - // case commands.LoadCmdDylibCodeSignDrs: - // case commands.LoadCmdEncryptionInfo64: - // case commands.LoadCmdLinkerOption: - // case commands.LoadCmdLinkerOptimizationHint: - // case commands.LoadCmdVersionMinTvos: - // case commands.LoadCmdVersionMinWatchos: - // case commands.LoadCmdNote: - case commands.LoadCmdBuildVersion: - var build commands.BuildVersionCmd - var buildTool types.BuildToolVersion - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &build); err != nil { - return nil, err - } - l := new(BuildVersion) - l.Platform = build.Platform.String() - l.Minos = build.Minos.String() - l.Sdk = build.Sdk.String() - l.NumTools = build.NumTools - if build.NumTools > 0 { - if err := binary.Read(b, bo, &buildTool); err != nil { - return nil, err - } - l.Tool = buildTool.Tool.String() - l.ToolVersion = buildTool.Version.String() - } - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - // case commands.LoadCmdDyldExportsTrie: - // case commands.LoadCmdDyldChainedFixups: - } - if s != nil { - s.sr = io.NewSectionReader(r, int64(s.Offset), int64(s.Filesz)) - s.ReaderAt = s.sr - } - } - return f, nil -} - -func (f *File) pushRelocatedSection(sh *Section, r io.ReaderAt, vmaToOffsetMap map[uint64]uint64) error { - f.Sections = append(f.Sections, sh) - sh.sr = io.NewSectionReader(r, int64(sh.Offset), int64(sh.Size)) - sh.ReaderAt = sh.sr - - if sh.Nreloc > 0 { - reldat := make([]byte, int(sh.Nreloc)*8) - if _, err := r.ReadAt(reldat, int64(sh.Reloff)); err != nil { - return err - } - b := bytes.NewReader(reldat) - - bo := f.ByteOrder - - sh.Relocs = make([]Reloc, sh.Nreloc) - for i := range sh.Relocs { - rel := &sh.Relocs[i] - - var ri relocInfo - if err := binary.Read(b, bo, &ri); err != nil { - return err - } - - if ri.Addr&(1<<31) != 0 { // scattered - rel.Addr = ri.Addr & (1<<24 - 1) - rel.Type = uint8((ri.Addr >> 24) & (1<<4 - 1)) - rel.Len = uint8((ri.Addr >> 28) & (1<<2 - 1)) - rel.Pcrel = ri.Addr&(1<<30) != 0 - rel.Value = ri.Symnum - rel.Scattered = true - } else { - switch bo { - case binary.LittleEndian: - rel.Addr = ri.Addr - rel.Value = ri.Symnum & (1<<24 - 1) - rel.Pcrel = ri.Symnum&(1<<24) != 0 - rel.Len = uint8((ri.Symnum >> 25) & (1<<2 - 1)) - rel.Extern = ri.Symnum&(1<<27) != 0 - rel.Type = uint8((ri.Symnum >> 28) & (1<<4 - 1)) - case binary.BigEndian: - rel.Addr = ri.Addr - rel.Value = ri.Symnum >> 8 - rel.Pcrel = ri.Symnum&(1<<7) != 0 - rel.Len = uint8((ri.Symnum >> 5) & (1<<2 - 1)) - rel.Extern = ri.Symnum&(1<<4) != 0 - rel.Type = uint8(ri.Symnum & (1<<4 - 1)) - default: - panic("unreachable") - } - } - } - } - - return nil -} diff --git a/pkg/macho/fat.go b/pkg/macho/fat.go deleted file mode 100644 index 7a5f4d947..000000000 --- a/pkg/macho/fat.go +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package macho - -import ( - "encoding/binary" - "fmt" - "io" - "os" - - "github.com/blacktop/ipsw/pkg/macho/header" -) - -// A FatFile is a Mach-O universal binary that contains at least one architecture. -type FatFile struct { - Magic header.Magic - Arches []FatArch - closer io.Closer -} - -// A FatArchHeader represents a fat header for a specific image architecture. -type FatArchHeader struct { - CPU header.CPU - SubCPU header.CPUSubtype - Offset uint32 - Size uint32 - Align uint32 -} - -const fatArchHeaderSize = 5 * 4 - -// A FatArch is a Mach-O File inside a FatFile. -type FatArch struct { - FatArchHeader - *File -} - -// ErrNotFat is returned from NewFatFile or OpenFat when the file is not a -// universal binary but may be a thin binary, based on its magic number. -var ErrNotFat = &FormatError{0, "not a fat Mach-O file", nil} - -// NewFatFile creates a new FatFile for accessing all the Mach-O images in a -// universal binary. The Mach-O binary is expected to start at position 0 in -// the ReaderAt. -func NewFatFile(r io.ReaderAt) (*FatFile, error) { - var ff FatFile - sr := io.NewSectionReader(r, 0, 1<<63-1) - - // Read the fat_header struct, which is always in big endian. - // Start with the magic number. - err := binary.Read(sr, binary.BigEndian, &ff.Magic) - if err != nil { - return nil, &FormatError{0, "error reading magic number", nil} - } else if ff.Magic != header.MagicFat { - // See if this is a Mach-O file via its magic number. The magic - // must be converted to little endian first though. - var buf [4]byte - binary.BigEndian.PutUint32(buf[:], ff.Magic.Int()) - leMagic := binary.LittleEndian.Uint32(buf[:]) - if leMagic == header.Magic32.Int() || leMagic == header.Magic64.Int() { - return nil, ErrNotFat - } - return nil, &FormatError{0, "invalid magic number", nil} - - } - offset := int64(4) - - // Read the number of FatArchHeaders that come after the fat_header. - var narch uint32 - err = binary.Read(sr, binary.BigEndian, &narch) - if err != nil { - return nil, &FormatError{offset, "invalid fat_header", nil} - } - offset += 4 - - if narch < 1 { - return nil, &FormatError{offset, "file contains no images", nil} - } - - // Combine the Cpu and SubCpu (both uint32) into a uint64 to make sure - // there are not duplicate architectures. - seenArches := make(map[uint64]bool, narch) - // Make sure that all images are for the same MH_ type. - var machoType header.Type - - // Following the fat_header comes narch fat_arch structs that index - // Mach-O images further in the file. - ff.Arches = make([]FatArch, narch) - for i := uint32(0); i < narch; i++ { - fa := &ff.Arches[i] - err = binary.Read(sr, binary.BigEndian, &fa.FatArchHeader) - if err != nil { - return nil, &FormatError{offset, "invalid fat_arch header", nil} - } - offset += fatArchHeaderSize - - fr := io.NewSectionReader(r, int64(fa.Offset), int64(fa.Size)) - fa.File, err = NewFile(fr) - if err != nil { - return nil, err - } - - // Make sure the architecture for this image is not duplicate. - seenArch := (uint64(fa.CPU) << 32) | uint64(fa.SubCPU) - if o, k := seenArches[seenArch]; o || k { - return nil, &FormatError{offset, fmt.Sprintf("duplicate architecture cpu=%v, subcpu=%#x", fa.CPU, fa.SubCPU), nil} - } - seenArches[seenArch] = true - - // Make sure the Mach-O type matches that of the first image. - if i == 0 { - machoType = fa.Type - } else { - if fa.Type != machoType { - return nil, &FormatError{offset, fmt.Sprintf("Mach-O type for architecture #%d (type=%#x) does not match first (type=%#x)", i, fa.Type, machoType), nil} - } - } - } - - return &ff, nil -} - -// OpenFat opens the named file using os.Open and prepares it for use as a Mach-O -// universal binary. -func OpenFat(name string) (*FatFile, error) { - f, err := os.Open(name) - if err != nil { - return nil, err - } - ff, err := NewFatFile(f) - if err != nil { - f.Close() - return nil, err - } - ff.closer = f - return ff, nil -} - -// Close with close the Mach-O Fat file. -func (ff *FatFile) Close() error { - var err error - if ff.closer != nil { - err = ff.closer.Close() - ff.closer = nil - } - return err -} diff --git a/pkg/macho/file.go b/pkg/macho/file.go deleted file mode 100644 index e8be665b6..000000000 --- a/pkg/macho/file.go +++ /dev/null @@ -1,1183 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package macho implements access to Mach-O object files. -package macho - -// High level access to low level data structures. - -import ( - "bytes" - "compress/zlib" - "debug/dwarf" - "encoding/binary" - "fmt" - "io" - "os" - "strings" - - "github.com/apex/log" - "github.com/blacktop/ipsw/pkg/macho/commands" - "github.com/blacktop/ipsw/pkg/macho/header" - "github.com/blacktop/ipsw/pkg/macho/types" -) - -type sections []*Section - -// A File represents an open Mach-O file. -type File struct { - header.FileHeader - ByteOrder binary.ByteOrder - Loads []Load - // Sections []*Section - Sections sections - - Symtab *Symtab - Dysymtab *Dysymtab - - closer io.Closer -} - -// A Load represents any Mach-O load command. -type Load interface { - Raw() []byte -} - -// A LoadBytes is the uninterpreted bytes of a Mach-O load command. -type LoadBytes []byte - -func (b LoadBytes) Raw() []byte { return b } - -// A SegmentHeader is the header for a Mach-O 32-bit or 64-bit load segment command. -type SegmentHeader struct { - Cmd commands.LoadCmd - Len uint32 - Name string - Addr uint64 - Memsz uint64 - Offset uint64 - Filesz uint64 - Maxprot types.VmProtection - Prot types.VmProtection - Nsect uint32 - Flag commands.SegFlag -} - -// A Segment represents a Mach-O 32-bit or 64-bit load segment command. -type Segment struct { - LoadBytes - SegmentHeader - - // Embed ReaderAt for ReadAt method. - // Do not embed SectionReader directly - // to avoid having Read and Seek. - // If a client wants Read and Seek it must use - // Open() to avoid fighting over the seek offset - // with other clients. - io.ReaderAt - sr *io.SectionReader -} - -// Data reads and returns the contents of the segment. -func (s *Segment) Data() ([]byte, error) { - dat := make([]byte, s.sr.Size()) - n, err := s.sr.ReadAt(dat, 0) - if n == len(dat) { - err = nil - } - return dat[0:n], err -} - -// Open returns a new ReadSeeker reading the segment. -func (s *Segment) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) } - -type SectionHeader struct { - Name string - Seg string - Addr uint64 - Size uint64 - Offset uint32 - Align uint32 - Reloff uint32 - Nreloc uint32 - Flags commands.SectionFlag -} - -// A Reloc represents a Mach-O relocation. -type Reloc struct { - Addr uint32 - Value uint32 - // when Scattered == false && Extern == true, Value is the symbol number. - // when Scattered == false && Extern == false, Value is the section number. - // when Scattered == true, Value is the value that this reloc refers to. - Type uint8 - Len uint8 // 0=byte, 1=word, 2=long, 3=quad - Pcrel bool - Extern bool // valid if Scattered == false - Scattered bool -} - -type Section struct { - SectionHeader - Relocs []Reloc - - // Embed ReaderAt for ReadAt method. - // Do not embed SectionReader directly - // to avoid having Read and Seek. - // If a client wants Read and Seek it must use - // Open() to avoid fighting over the seek offset - // with other clients. - io.ReaderAt - sr *io.SectionReader -} - -// Data reads and returns the contents of the Mach-O section. -func (s *Section) Data() ([]byte, error) { - dat := make([]byte, s.sr.Size()) - n, err := s.sr.ReadAt(dat, 0) - if n == len(dat) { - err = nil - } - return dat[0:n], err -} - -// Open returns a new ReadSeeker reading the Mach-O section. -func (s *Section) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) } - -type ( - // A Symtab represents a Mach-O symbol table command. - Symtab struct { - LoadBytes - commands.SymtabCmd - Syms []Symbol - } - // A Symbol is a Mach-O 32-bit or 64-bit symbol table entry. - Symbol struct { - Name string - Type types.NLType - Sect uint8 - Desc uint16 - Value uint64 - } - // #define LC_SYMSEG 0x3 /* link-edit gdb symbol table info (obsolete) */ - // #define LC_THREAD 0x4 /* thread */ - // A UnixThread represents a Mach-O unix thread command. - UnixThread struct { - LoadBytes - } - // #define LC_LOADFVMLIB 0x6 /* load a specified fixed VM shared library */ - // #define LC_IDFVMLIB 0x7 /* fixed VM shared library identification */ - // #define LC_IDENT 0x8 /* object identification info (obsolete) */ - // #define LC_FVMFILE 0x9 /* fixed VM file inclusion (internal use) */ - // #define LC_PREPAGE 0xa /* prepage command (internal use) */ - // A Dysymtab represents a Mach-O dynamic symbol table command. - Dysymtab struct { - LoadBytes - commands.DysymtabCmd - IndirectSyms []uint32 // indices into Symtab.Syms - } - // A Dylib represents a Mach-O load dynamic library command. - Dylib struct { - LoadBytes - Name string - Time uint32 - CurrentVersion string - CompatVersion string - } - // A DylibID represents a Mach-O load dynamic library ident command. - DylibID Dylib - // #define LC_LOAD_DYLINKER 0xe /* load a dynamic linker */ - // #define LC_ID_DYLINKER 0xf /* dynamic linker identification */ - // #define LC_PREBOUND_DYLIB 0x10 /* modules prebound for a dynamically */ - // /* linked shared library */ - // #define LC_ROUTINES 0x11 /* image routines */ - - SubFramework struct { - LoadBytes - Framework string - } - // #define LC_SUB_UMBRELLA 0x13 /* sub umbrella */ - // A SubClient is a Mach-O dynamic sub client command. - SubClient struct { - LoadBytes - Name string - } - - // #define LC_SUB_LIBRARY 0x15 /* sub library */ - // #define LC_TWOLEVEL_HINTS 0x16 /* two-level namespace lookup hints */ - // #define LC_PREBIND_CKSUM 0x17 /* prebind checksum */ - - // A WeakDylib represents a Mach-O load weak dynamic library command. - WeakDylib Dylib - - Routines64 struct { - LoadBytes - InitAddress uint64 - InitModule uint64 - } - // A uuid represents a Mach-O uuid command. - UUID struct { - LoadBytes - ID string - } - // A Rpath represents a Mach-O rpath command. - Rpath struct { - LoadBytes - Path string - } - // #define LC_CODE_SIGNATURE 0x1d /* local of code signature */ - CodeSignature struct { - LoadBytes - Offset uint32 - Size uint32 - } - // #define LC_SEGMENT_SPLIT_INFO 0x1e /* local of info to split segments */ - SplitInfo struct { - LoadBytes - Offset uint32 - Size uint32 - } - - ReExportDylib Dylib - // #define LC_LAZY_LOAD_DYLIB 0x20 /* delay load of dylib until first use */ - // #define LC_ENCRYPTION_INFO 0x21 /* encrypted segment information */ - - // A DyldInfo represents a Mach-O id dyld info command. - DyldInfo struct { - LoadBytes - RebaseOff uint32 // file offset to rebase info - RebaseSize uint32 // size of rebase info - BindOff uint32 // file offset to binding info - BindSize uint32 // size of binding info - WeakBindOff uint32 // file offset to weak binding info - WeakBindSize uint32 // size of weak binding info - LazyBindOff uint32 // file offset to lazy binding info - LazyBindSize uint32 // size of lazy binding info - ExportOff uint32 // file offset to export info - ExportSize uint32 // size of export info - } - - // #define LC_DYLD_INFO_ONLY (0x22|LC_REQ_DYLD) /* compressed dyld information only */ - - // A UpwardDylib represents a Mach-O load upward dylib command. - UpwardDylib Dylib - // #define LC_VERSION_MIN_MACOSX 0x24 /* build for MacOSX min OS version */ - VersionMinMacosx struct { - LoadBytes - Version string - Sdk string - } - // #define LC_VERSION_MIN_IPHONEOS 0x25 /* build for iPhoneOS min OS version */ - VersionMinIphoneos struct { - LoadBytes - Version string - Sdk string - } - // A FunctionStarts represents a Mach-O function starts command. - FunctionStarts struct { - LoadBytes - Offset uint32 - Size uint32 - } - // #define LC_DYLD_ENVIRONMENT 0x27 /* string for dyld to treat - // like environment variable */ - // #define LC_MAIN (0x28|LC_REQ_DYLD) /* replacement for LC_UNIXTHREAD */ - - // A DataInCode represents a Mach-O data in code command. - DataInCode struct { - LoadBytes - Entries []types.DataInCodeEntry - } - - // A SourceVersion represents a Mach-O source version. - SourceVersion struct { - LoadBytes - Version string - } - // #define LC_DYLIB_CODE_SIGN_DRS 0x2B /* Code signing DRs copied from linked dylibs */ - // #define LC_ENCRYPTION_INFO_64 0x2C /* 64-bit encrypted segment information */ - // #define LC_LINKER_OPTION 0x2D /* linker options in MH_OBJECT files */ - // #define LC_LINKER_OPTIMIZATION_HINT 0x2E /* optimization hints in MH_OBJECT files */ - // #define LC_VERSION_MIN_TVOS 0x2F /* build for AppleTV min OS version */ - // #define LC_VERSION_MIN_WATCHOS 0x30 /* build for Watch min OS version */ - // #define LC_NOTE 0x31 /* arbitrary data included within a Mach-O file */ - - // A BuildVersion represents a Mach-O build for platform min OS version. - BuildVersion struct { - LoadBytes - Platform string /* platform */ - Minos string /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ - Sdk string /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ - NumTools uint32 /* number of tool entries following this */ - Tool string - ToolVersion string - } - -// #define LC_DYLD_EXPORTS_TRIE (0x33 | LC_REQ_DYLD) /* used with linkedit_data_command, payload is trie */ -// #define LC_DYLD_CHAINED_FIXUPS (0x34 | LC_REQ_DYLD) /* used with linkedit_data_command */ -) - -// A LinkEditData represents a Mach-O linkedit data command. -type LinkEditData struct { - LoadBytes - Offset uint32 - Size uint32 -} - -/* - * Mach-O reader - */ - -// FormatError is returned by some operations if the data does -// not have the correct format for an object file. -type FormatError struct { - off int64 - msg string - val interface{} -} - -func (e *FormatError) Error() string { - msg := e.msg - if e.val != nil { - msg += fmt.Sprintf(" '%v'", e.val) - } - msg += fmt.Sprintf(" in record at byte %#x", e.off) - return msg -} - -// Open opens the named file using os.Open and prepares it for use as a Mach-O binary. -func Open(name string) (*File, error) { - f, err := os.Open(name) - if err != nil { - return nil, err - } - ff, err := NewFile(f) - if err != nil { - f.Close() - return nil, err - } - ff.closer = f - return ff, nil -} - -// Close closes the File. -// If the File was created using NewFile directly instead of Open, -// Close has no effect. -func (f *File) Close() error { - var err error - if f.closer != nil { - err = f.closer.Close() - f.closer = nil - } - return err -} - -// NewFile creates a new File for accessing a Mach-O binary in an underlying reader. -// The Mach-O binary is expected to start at position 0 in the ReaderAt. -func NewFile(r io.ReaderAt) (*File, error) { - f := new(File) - sr := io.NewSectionReader(r, 0, 1<<63-1) - - // Read and decode Mach magic to determine byte order, size. - // Magic32 and Magic64 differ only in the bottom bit. - var ident [4]byte - if _, err := r.ReadAt(ident[0:], 0); err != nil { - return nil, err - } - be := binary.BigEndian.Uint32(ident[0:]) - le := binary.LittleEndian.Uint32(ident[0:]) - switch header.Magic32.Int() &^ 1 { - case be &^ 1: - f.ByteOrder = binary.BigEndian - f.Magic = header.Magic(be) - case le &^ 1: - f.ByteOrder = binary.LittleEndian - f.Magic = header.Magic(le) - default: - return nil, &FormatError{0, "invalid magic number", nil} - } - - // Read entire file header. - if err := binary.Read(sr, f.ByteOrder, &f.FileHeader); err != nil { - return nil, err - } - - // Then load commands. - offset := int64(header.FileHeaderSize32) - if f.Magic == header.Magic64 { - offset = header.FileHeaderSize64 - } - dat := make([]byte, f.Cmdsz) - if _, err := r.ReadAt(dat, offset); err != nil { - return nil, err - } - f.Loads = make([]Load, f.Ncmd) - bo := f.ByteOrder - for i := range f.Loads { - // Each load command begins with uint32 command and length. - if len(dat) < 8 { - return nil, &FormatError{offset, "command block too small", nil} - } - cmd, siz := commands.LoadCmd(bo.Uint32(dat[0:4])), bo.Uint32(dat[4:8]) - if siz < 8 || siz > uint32(len(dat)) { - return nil, &FormatError{offset, "invalid command block size", nil} - } - var cmddat []byte - cmddat, dat = dat[0:siz], dat[siz:] - offset += int64(siz) - var s *Segment - switch cmd { - default: - log.Warnf("found NEW load command: %s", cmd) - f.Loads[i] = LoadBytes(cmddat) - case commands.LoadCmdSegment: - var seg32 commands.Segment32 - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &seg32); err != nil { - return nil, err - } - s = new(Segment) - s.LoadBytes = cmddat - s.Cmd = cmd - s.Len = siz - s.Name = cstring(seg32.Name[0:]) - s.Addr = uint64(seg32.Addr) - s.Memsz = uint64(seg32.Memsz) - s.Offset = uint64(seg32.Offset) - s.Filesz = uint64(seg32.Filesz) - s.Maxprot = seg32.Maxprot - s.Prot = seg32.Prot - s.Nsect = seg32.Nsect - s.Flag = seg32.Flag - f.Loads[i] = s - for i := 0; i < int(s.Nsect); i++ { - var sh32 commands.Section32 - if err := binary.Read(b, bo, &sh32); err != nil { - return nil, err - } - sh := new(Section) - sh.Name = cstring(sh32.Name[0:]) - sh.Seg = cstring(sh32.Seg[0:]) - sh.Addr = uint64(sh32.Addr) - sh.Size = uint64(sh32.Size) - sh.Offset = sh32.Offset - sh.Align = sh32.Align - sh.Reloff = sh32.Reloff - sh.Nreloc = sh32.Nreloc - sh.Flags = sh32.Flags - if err := f.pushSection(sh, r); err != nil { - return nil, err - } - } - case commands.LoadCmdSegment64: - var seg64 commands.Segment64 - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &seg64); err != nil { - return nil, err - } - s = new(Segment) - s.LoadBytes = cmddat - s.Cmd = cmd - s.Len = siz - s.Name = cstring(seg64.Name[0:]) - s.Addr = seg64.Addr - s.Memsz = seg64.Memsz - s.Offset = seg64.Offset - s.Filesz = seg64.Filesz - s.Maxprot = seg64.Maxprot - s.Prot = seg64.Prot - s.Nsect = seg64.Nsect - s.Flag = seg64.Flag - f.Loads[i] = s - for i := 0; i < int(s.Nsect); i++ { - var sh64 commands.Section64 - if err := binary.Read(b, bo, &sh64); err != nil { - return nil, err - } - sh := new(Section) - sh.Name = cstring(sh64.Name[0:]) - sh.Seg = cstring(sh64.Seg[0:]) - sh.Addr = sh64.Addr - sh.Size = sh64.Size - sh.Offset = sh64.Offset - sh.Align = sh64.Align - sh.Reloff = sh64.Reloff - sh.Nreloc = sh64.Nreloc - sh.Flags = sh64.Flags - if err := f.pushSection(sh, r); err != nil { - return nil, err - } - } - case commands.LoadCmdSymtab: - var hdr commands.SymtabCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &hdr); err != nil { - return nil, err - } - strtab := make([]byte, hdr.Strsize) - if _, err := r.ReadAt(strtab, int64(hdr.Stroff)); err != nil { - return f, nil - // return nil, err - } - var symsz int - if f.Magic == header.Magic64 { - symsz = 16 - } else { - symsz = 12 - } - symdat := make([]byte, int(hdr.Nsyms)*symsz) - if _, err := r.ReadAt(symdat, int64(hdr.Symoff)); err != nil { - return nil, err - } - st, err := f.parseSymtab(symdat, strtab, cmddat, &hdr, offset) - if err != nil { - return nil, err - } - f.Loads[i] = st - f.Symtab = st - // case commands.LoadCmdSymseg: - // case commands.LoadCmdThread: - case commands.LoadCmdUnixThread: - var ut commands.UnixThreadCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &ut); err != nil { - return nil, err - } - l := new(UnixThread) - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - // case commands.LoadCmdLoadfvmlib: - // case commands.LoadCmdIdfvmlib: - // case commands.LoadCmdIdent: - // case commands.LoadCmdFvmfile: - // case commands.LoadCmdPrepage: - case commands.LoadCmdDysymtab: - var hdr commands.DysymtabCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &hdr); err != nil { - return nil, err - } - dat := make([]byte, hdr.Nindirectsyms*4) - if _, err := r.ReadAt(dat, int64(hdr.Indirectsymoff)); err != nil { - return nil, err - } - x := make([]uint32, hdr.Nindirectsyms) - if err := binary.Read(bytes.NewReader(dat), bo, x); err != nil { - return nil, err - } - st := new(Dysymtab) - st.LoadBytes = LoadBytes(cmddat) - st.DysymtabCmd = hdr - st.IndirectSyms = x - f.Loads[i] = st - f.Dysymtab = st - case commands.LoadCmdDylib: - var hdr commands.DylibCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &hdr); err != nil { - return nil, err - } - l := new(Dylib) - if hdr.Name >= uint32(len(cmddat)) { - return nil, &FormatError{offset, "invalid name in dynamic library command", hdr.Name} - } - l.Name = cstring(cmddat[hdr.Name:]) - l.Time = hdr.Time - l.CurrentVersion = hdr.CurrentVersion.String() - l.CompatVersion = hdr.CompatVersion.String() - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - case commands.LoadCmdDylibID: - var hdr commands.DylibCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &hdr); err != nil { - return nil, err - } - l := new(DylibID) - if hdr.Name >= uint32(len(cmddat)) { - return nil, &FormatError{offset, "invalid name in dynamic library ident command", hdr.Name} - } - l.Name = cstring(cmddat[hdr.Name:]) - l.Time = hdr.Time - l.CurrentVersion = hdr.CurrentVersion.String() - l.CompatVersion = hdr.CompatVersion.String() - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - // case commands.LoadCmdDylinker: - // case commands.LoadCmdDylinkerID: - // case commands.LoadCmdPreboundDylib: - // case commands.LoadCmdRoutines: - case commands.LoadCmdSubFramework: - var sf commands.SubFrameworkCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &sf); err != nil { - return nil, err - } - l := new(SubFramework) - if sf.Framework >= uint32(len(cmddat)) { - return nil, &FormatError{offset, "invalid framework in subframework command", sf.Framework} - } - l.Framework = cstring(cmddat[sf.Framework:]) - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - // case commands.LoadCmdSubUmbrella: - case commands.LoadCmdSubClient: - var sc commands.SubClientCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &sc); err != nil { - return nil, err - } - l := new(SubClient) - if sc.Client >= uint32(len(cmddat)) { - return nil, &FormatError{offset, "invalid path in sub client command", sc.Client} - } - l.Name = cstring(cmddat[sc.Client:]) - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - // case commands.LoadCmdSubLibrary: - // case commands.LoadCmdTwolevelHints: - // case commands.LoadCmdPrebindCksum: - case commands.LoadCmdLoadWeakDylib: - var hdr commands.DylibCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &hdr); err != nil { - return nil, err - } - l := new(WeakDylib) - if hdr.Name >= uint32(len(cmddat)) { - return nil, &FormatError{offset, "invalid name in weak dynamic library command", hdr.Name} - } - l.Name = cstring(cmddat[hdr.Name:]) - l.Time = hdr.Time - l.CurrentVersion = hdr.CurrentVersion.String() - l.CompatVersion = hdr.CompatVersion.String() - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - case commands.LoadCmdRoutines64: - var r64 commands.Routines64Cmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &r64); err != nil { - return nil, err - } - l := new(Routines64) - l.InitAddress = r64.InitAddress - l.InitModule = r64.InitModule - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - case commands.LoadCmdUUID: - var u commands.UUIDCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &u); err != nil { - return nil, err - } - l := new(UUID) - l.ID = u.UUID.String() - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - case commands.LoadCmdRpath: - var hdr commands.RpathCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &hdr); err != nil { - return nil, err - } - l := new(Rpath) - if hdr.Path >= uint32(len(cmddat)) { - return nil, &FormatError{offset, "invalid path in rpath command", hdr.Path} - } - l.Path = cstring(cmddat[hdr.Path:]) - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - case commands.LoadCmdCodeSignature: - var hdr commands.CodeSignatureCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &hdr); err != nil { - return nil, err - } - l := new(CodeSignature) - l.Offset = hdr.Offset - l.Size = hdr.Size - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - case commands.LoadCmdSegmentSplitInfo: - var hdr commands.SegmentSplitInfoCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &hdr); err != nil { - return nil, err - } - l := new(SplitInfo) - l.Offset = hdr.Offset - l.Size = hdr.Size - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - case commands.LoadCmdReexportDylib: - var hdr commands.ReExportDylibCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &hdr); err != nil { - return nil, err - } - l := new(ReExportDylib) - if hdr.Name >= uint32(len(cmddat)) { - return nil, &FormatError{offset, "invalid name in dynamic library command", hdr.Name} - } - l.Name = cstring(cmddat[hdr.Name:]) - l.Time = hdr.Time - l.CurrentVersion = hdr.CurrentVersion.String() - l.CompatVersion = hdr.CompatVersion.String() - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - // case commands.LoadCmdLazyLoadDylib: - // case commands.LoadCmdEncryptionInfo: - case commands.LoadCmdDyldInfo: - case commands.LoadCmdDyldInfoOnly: - var info commands.DyldInfoCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &info); err != nil { - return nil, err - } - l := new(DyldInfo) - l.RebaseOff = info.RebaseOff - l.RebaseSize = info.RebaseSize - l.BindOff = info.BindOff - l.BindSize = info.BindSize - l.WeakBindOff = info.WeakBindOff - l.WeakBindSize = info.WeakBindSize - l.LazyBindOff = info.LazyBindOff - l.LazyBindSize = info.LazyBindSize - l.ExportOff = info.ExportOff - l.ExportSize = info.ExportSize - f.Loads[i] = l - case commands.LoadCmdLoadUpwardDylib: - var hdr commands.UpwardDylibCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &hdr); err != nil { - return nil, err - } - l := new(UpwardDylib) - if hdr.Name >= uint32(len(cmddat)) { - return nil, &FormatError{offset, "invalid name in load upwardl dylib command", hdr.Name} - } - l.Name = cstring(cmddat[hdr.Name:]) - l.Time = hdr.Time - l.CurrentVersion = hdr.CurrentVersion.String() - l.CompatVersion = hdr.CompatVersion.String() - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - case commands.LoadCmdVersionMinMacosx: - var verMin commands.VersionMinMacOSCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &verMin); err != nil { - return nil, err - } - l := new(VersionMinMacosx) - l.Version = verMin.Version.String() - l.Sdk = verMin.Sdk.String() - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - case commands.LoadCmdVersionMinIphoneos: - var verMin commands.VersionMinIPhoneOSCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &verMin); err != nil { - return nil, err - } - l := new(VersionMinIphoneos) - l.Version = verMin.Version.String() - l.Sdk = verMin.Sdk.String() - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - case commands.LoadCmdFunctionStarts: - var led commands.LinkEditDataCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &led); err != nil { - return nil, err - } - l := new(FunctionStarts) - l.Offset = led.Offset - l.Size = led.Size - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - // case commands.LoadCmdDyldEnvironment: - // case commands.LoadCmdMain: - case commands.LoadCmdDataInCode: - var led commands.LinkEditDataCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &led); err != nil { - return nil, err - } - l := new(DataInCode) - // var e DataInCodeEntry - - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - case commands.LoadCmdSourceVersion: - var sv commands.SourceVersionCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &sv); err != nil { - return nil, err - } - l := new(SourceVersion) - l.Version = sv.Version.String() - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - // case commands.LoadCmdDylibCodeSignDrs: - // case commands.LoadCmdEncryptionInfo64: - // case commands.LoadCmdLinkerOption: - // case commands.LoadCmdLinkerOptimizationHint: - // case commands.LoadCmdVersionMinTvos: - // case commands.LoadCmdVersionMinWatchos: - // case commands.LoadCmdNote: - case commands.LoadCmdBuildVersion: - var build commands.BuildVersionCmd - var buildTool types.BuildToolVersion - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &build); err != nil { - return nil, err - } - l := new(BuildVersion) - l.Platform = build.Platform.String() - l.Minos = build.Minos.String() - l.Sdk = build.Sdk.String() - l.NumTools = build.NumTools - if build.NumTools > 0 { - if err := binary.Read(b, bo, &buildTool); err != nil { - return nil, err - } - l.Tool = buildTool.Tool.String() - l.ToolVersion = buildTool.Version.String() - } - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - // case commands.LoadCmdDyldExportsTrie: - // case commands.LoadCmdDyldChainedFixups: - } - if s != nil { - s.sr = io.NewSectionReader(r, int64(s.Offset), int64(s.Filesz)) - s.ReaderAt = s.sr - } - } - return f, nil -} - -func (f *File) parseSymtab(symdat, strtab, cmddat []byte, hdr *commands.SymtabCmd, offset int64) (*Symtab, error) { - bo := f.ByteOrder - symtab := make([]Symbol, hdr.Nsyms) - b := bytes.NewReader(symdat) - for i := range symtab { - var n types.Nlist64 - if f.Magic == header.Magic64 { - if err := binary.Read(b, bo, &n); err != nil { - return nil, err - } - } else { - var n32 types.Nlist32 - if err := binary.Read(b, bo, &n32); err != nil { - return nil, err - } - n.Name = n32.Name - n.Type = n32.Type - n.Sect = n32.Sect - n.Desc = n32.Desc - n.Value = uint64(n32.Value) - } - sym := &symtab[i] - if n.Name >= uint32(len(strtab)) { - continue // TODO: remove this - return nil, &FormatError{offset, "invalid name in symbol table", n.Name} - } - // We add "_" to Go symbols. Strip it here. See issue 33808. - name := cstring(strtab[n.Name:]) - if strings.Contains(name, ".") && name[0] == '_' { - name = name[1:] - } - sym.Name = name - sym.Type = n.Type - sym.Sect = n.Sect - sym.Desc = n.Desc - sym.Value = n.Value - } - st := new(Symtab) - st.LoadBytes = LoadBytes(cmddat) - st.Syms = symtab - return st, nil -} - -type relocInfo struct { - Addr uint32 - Symnum uint32 -} - -func (f *File) pushSection(sh *Section, r io.ReaderAt) error { - f.Sections = append(f.Sections, sh) - sh.sr = io.NewSectionReader(r, int64(sh.Offset), int64(sh.Size)) - sh.ReaderAt = sh.sr - - if sh.Nreloc > 0 { - reldat := make([]byte, int(sh.Nreloc)*8) - if _, err := r.ReadAt(reldat, int64(sh.Reloff)); err != nil { - return err - } - b := bytes.NewReader(reldat) - - bo := f.ByteOrder - - sh.Relocs = make([]Reloc, sh.Nreloc) - for i := range sh.Relocs { - rel := &sh.Relocs[i] - - var ri relocInfo - if err := binary.Read(b, bo, &ri); err != nil { - return err - } - - if ri.Addr&(1<<31) != 0 { // scattered - rel.Addr = ri.Addr & (1<<24 - 1) - rel.Type = uint8((ri.Addr >> 24) & (1<<4 - 1)) - rel.Len = uint8((ri.Addr >> 28) & (1<<2 - 1)) - rel.Pcrel = ri.Addr&(1<<30) != 0 - rel.Value = ri.Symnum - rel.Scattered = true - } else { - switch bo { - case binary.LittleEndian: - rel.Addr = ri.Addr - rel.Value = ri.Symnum & (1<<24 - 1) - rel.Pcrel = ri.Symnum&(1<<24) != 0 - rel.Len = uint8((ri.Symnum >> 25) & (1<<2 - 1)) - rel.Extern = ri.Symnum&(1<<27) != 0 - rel.Type = uint8((ri.Symnum >> 28) & (1<<4 - 1)) - case binary.BigEndian: - rel.Addr = ri.Addr - rel.Value = ri.Symnum >> 8 - rel.Pcrel = ri.Symnum&(1<<7) != 0 - rel.Len = uint8((ri.Symnum >> 5) & (1<<2 - 1)) - rel.Extern = ri.Symnum&(1<<4) != 0 - rel.Type = uint8(ri.Symnum & (1<<4 - 1)) - default: - panic("unreachable") - } - } - } - } - - return nil -} - -func cstring(b []byte) string { - i := bytes.IndexByte(b, 0) - if i == -1 { - i = len(b) - } - return string(b[0:i]) -} - -// Segment returns the first Segment with the given name, or nil if no such segment exists. -func (f *File) Segment(name string) *Segment { - for _, l := range f.Loads { - if s, ok := l.(*Segment); ok && s.Name == name { - return s - } - } - return nil -} - -// Segments returns all Segments. -func (f *File) Segments() []*Segment { - var segs []*Segment - for _, l := range f.Loads { - if s, ok := l.(*Segment); ok { - segs = append(segs, s) - } - } - return segs -} - -// Section returns the first section with the given name, or nil if no such -// section exists. -func (f *File) Section(name string) *Section { - for _, s := range f.Sections { - if s.Name == name { - return s - } - } - return nil -} - -// UUID returns the UUID load command, or nil if no UUID exists. -func (f *File) UUID() *UUID { - for _, l := range f.Loads { - if u, ok := l.(*UUID); ok { - return u - } - } - return nil -} - -// DylibID returns the dylib ID load command, or nil if no dylib ID exists. -func (f *File) DylibID() *DylibID { - for _, l := range f.Loads { - if s, ok := l.(*DylibID); ok { - return s - } - } - return nil -} - -// DyldInfo returns the dyld info load command, or nil if no dyld info exists. -func (f *File) DyldInfo() *DyldInfo { - for _, l := range f.Loads { - if s, ok := l.(*DyldInfo); ok { - return s - } - } - return nil -} - -// SourceVersion returns the source version load command, or nil if no source version exists. -func (f *File) SourceVersion() *SourceVersion { - for _, l := range f.Loads { - if s, ok := l.(*SourceVersion); ok { - return s - } - } - return nil -} - -// BuildVersion returns the build version load command, or nil if no build version exists. -func (f *File) BuildVersion() *BuildVersion { - for _, l := range f.Loads { - if s, ok := l.(*BuildVersion); ok { - return s - } - } - return nil -} - -// DWARF returns the DWARF debug information for the Mach-O file. -func (f *File) DWARF() (*dwarf.Data, error) { - dwarfSuffix := func(s *Section) string { - switch { - case strings.HasPrefix(s.Name, "__debug_"): - return s.Name[8:] - case strings.HasPrefix(s.Name, "__zdebug_"): - return s.Name[9:] - default: - return "" - } - - } - sectionData := func(s *Section) ([]byte, error) { - b, err := s.Data() - if err != nil && uint64(len(b)) < s.Size { - return nil, err - } - - if len(b) >= 12 && string(b[:4]) == "ZLIB" { - dlen := binary.BigEndian.Uint64(b[4:12]) - dbuf := make([]byte, dlen) - r, err := zlib.NewReader(bytes.NewBuffer(b[12:])) - if err != nil { - return nil, err - } - if _, err := io.ReadFull(r, dbuf); err != nil { - return nil, err - } - if err := r.Close(); err != nil { - return nil, err - } - b = dbuf - } - return b, nil - } - - // There are many other DWARF sections, but these - // are the ones the debug/dwarf package uses. - // Don't bother loading others. - var dat = map[string][]byte{"abbrev": nil, "info": nil, "str": nil, "line": nil, "ranges": nil} - for _, s := range f.Sections { - suffix := dwarfSuffix(s) - if suffix == "" { - continue - } - if _, ok := dat[suffix]; !ok { - continue - } - b, err := sectionData(s) - if err != nil { - return nil, err - } - dat[suffix] = b - } - - d, err := dwarf.New(dat["abbrev"], nil, nil, dat["info"], dat["line"], nil, dat["ranges"], dat["str"]) - if err != nil { - return nil, err - } - - // Look for DWARF4 .debug_types sections. - for i, s := range f.Sections { - suffix := dwarfSuffix(s) - if suffix != "types" { - continue - } - - b, err := sectionData(s) - if err != nil { - return nil, err - } - - err = d.AddTypes(fmt.Sprintf("types-%d", i), b) - if err != nil { - return nil, err - } - } - - return d, nil -} - -// ImportedSymbols returns the names of all symbols -// referred to by the binary f that are expected to be -// satisfied by other libraries at dynamic load time. -func (f *File) ImportedSymbols() ([]string, error) { - if f.Dysymtab == nil || f.Symtab == nil { - return nil, &FormatError{0, "missing symbol table", nil} - } - - st := f.Symtab - dt := f.Dysymtab - var all []string - for _, s := range st.Syms[dt.Iundefsym : dt.Iundefsym+dt.Nundefsym] { - all = append(all, s.Name) - } - return all, nil -} - -// ImportedLibraries returns the paths of all libraries -// referred to by the binary f that are expected to be -// linked with the binary at dynamic link time. -func (f *File) ImportedLibraries() ([]string, error) { - var all []string - for _, l := range f.Loads { - if lib, ok := l.(*Dylib); ok { - all = append(all, lib.Name) - } - } - return all, nil -} - -func (f *File) FindSymbolAddress(symbol string) (uint64, error) { - for _, sym := range f.Symtab.Syms { - if strings.EqualFold(sym.Name, symbol) { - return sym.Value, nil - } - } - return 0, fmt.Errorf("symbol not found in macho symtab") -} - -func (f *File) FindAddressSymbol(addr uint64) (string, error) { - for _, sym := range f.Symtab.Syms { - if sym.Value == addr { - return sym.Name, nil - } - } - return "", fmt.Errorf("symbol not found in macho symtab") -} diff --git a/pkg/macho/header/cpu.go b/pkg/macho/header/cpu.go deleted file mode 100644 index 9029e3d35..000000000 --- a/pkg/macho/header/cpu.go +++ /dev/null @@ -1,123 +0,0 @@ -package header - -import "github.com/blacktop/ipsw/pkg/macho/utils" - -// A CPU is a Mach-O cpu type. -type CPU uint32 - -const ( - cpuArch64 = 0x01000000 // 64 bit ABI - cpuArch6432 = 0x02000000 // ABI for 64-bit hardware with 32-bit types; LP32 -) - -const ( - CPU386 CPU = 7 - CPUAmd64 CPU = CPU386 | cpuArch64 - CPUArm CPU = 12 - CPUArm64 CPU = CPUArm | cpuArch64 - CPUArm6432 = CPUArm | cpuArch6432 - CPUPpc CPU = 18 - CPUPpc64 CPU = CPUPpc | cpuArch64 -) - -var cpuStrings = []utils.IntName{ - {uint32(CPU386), "i386"}, - {uint32(CPUAmd64), "Amd64"}, - {uint32(CPUArm), "ARM"}, - {uint32(CPUArm64), "AARCH64"}, - {uint32(CPUPpc), "PowerPC"}, - {uint32(CPUPpc64), "PowerPC 64"}, -} - -func (i CPU) String() string { return utils.StringName(uint32(i), cpuStrings, false) } -func (i CPU) GoString() string { return utils.StringName(uint32(i), cpuStrings, true) } - -type CPUSubtype uint32 - -// X86 subtypes -const ( - // CPUSubtypeX86All CPUSubtype = 3 - CPUSubtypeX8664All CPUSubtype = 3 - CPUSubtypeX86Arch1 CPUSubtype = 4 - CPUSubtypeX86_64H CPUSubtype = 8 -) - -// ARM subtypes -const ( - CPUSubtypeArmAll CPUSubtype = 0 - CPUSubtypeArmV4T CPUSubtype = 5 - CPUSubtypeArmV6 CPUSubtype = 6 - CPUSubtypeArmV5Tej CPUSubtype = 7 - CPUSubtypeArmXscale CPUSubtype = 8 - CPUSubtypeArmV7 CPUSubtype = 9 - CPUSubtypeArmV7F CPUSubtype = 10 - CPUSubtypeArmV7S CPUSubtype = 11 - CPUSubtypeArmV7K CPUSubtype = 12 - CPUSubtypeArmV8 CPUSubtype = 13 - CPUSubtypeArmV6M CPUSubtype = 14 - CPUSubtypeArmV7M CPUSubtype = 15 - CPUSubtypeArmV7Em CPUSubtype = 16 - CPUSubtypeArmV8M CPUSubtype = 17 -) - -// ARM64 subtypes -const ( - CPUSubtypeArm64All CPUSubtype = 0 - CPUSubtypeArm64V8 CPUSubtype = 1 - CPUSubtypeArm64E CPUSubtype = 2 -) - -var cpuSubtypeX86Strings = []utils.IntName{ - // {uint32(CPUSubtypeX86All), "x86"}, - {uint32(CPUSubtypeX8664All), "x86_64"}, - {uint32(CPUSubtypeX86Arch1), "x86 Arch1"}, - {uint32(CPUSubtypeX86_64H), "x86_64 (Haswell)"}, -} -var cpuSubtypeArmStrings = []utils.IntName{ - {uint32(CPUSubtypeArmAll), "ArmAll"}, - {uint32(CPUSubtypeArmV4T), "ArmV4T"}, - {uint32(CPUSubtypeArmV6), "ArmV6"}, - {uint32(CPUSubtypeArmV5Tej), "ArmV5Tej"}, - {uint32(CPUSubtypeArmXscale), "ArmXscale"}, - {uint32(CPUSubtypeArmV7), "ArmV7"}, - {uint32(CPUSubtypeArmV7F), "ArmV7F"}, - {uint32(CPUSubtypeArmV7S), "ArmV7S"}, - {uint32(CPUSubtypeArmV7K), "ArmV7K"}, - {uint32(CPUSubtypeArmV8), "ArmV8"}, - {uint32(CPUSubtypeArmV6M), "rmV6M"}, - {uint32(CPUSubtypeArmV7M), "ArmV7M"}, - {uint32(CPUSubtypeArmV7Em), "ArmV7Em"}, - {uint32(CPUSubtypeArmV8M), "ArmV8M"}, -} -var cpuSubtypeArm64Strings = []utils.IntName{ - {uint32(CPUSubtypeArm64All), "ARM64"}, - {uint32(CPUSubtypeArm64V8), "ARM64 (ARMv8)"}, - {uint32(CPUSubtypeArm64E), "ARM64e (ARMv8.3)"}, -} - -func (st CPUSubtype) String(cpu CPU) string { - switch cpu { - case CPU386: - case CPUAmd64: - // TODO: this is a hack and this should be fully fleshed out - return utils.StringName(uint32(st&0xFF), cpuSubtypeX86Strings, false) - case CPUArm: - return utils.StringName(uint32(st), cpuSubtypeArmStrings, false) - case CPUArm64: - return utils.StringName(uint32(st), cpuSubtypeArm64Strings, false) - } - return "" -} - -func (st CPUSubtype) GoString(cpu CPU) string { - switch cpu { - case CPU386: - case CPUAmd64: - return utils.StringName(uint32(st), cpuSubtypeX86Strings, true) - case CPUArm: - return utils.StringName(uint32(st), cpuSubtypeArmStrings, true) - case CPUArm64: - return utils.StringName(uint32(st), cpuSubtypeArm64Strings, true) - } - return "" -} diff --git a/pkg/macho/header/flags.go b/pkg/macho/header/flags.go deleted file mode 100644 index ab8e86bd8..000000000 --- a/pkg/macho/header/flags.go +++ /dev/null @@ -1,239 +0,0 @@ -package header - -import ( - "fmt" - "strings" -) - -type Flag uint32 - -const ( - NoUndefs Flag = 0x1 - IncrLink Flag = 0x2 - DyldLink Flag = 0x4 - BindAtLoad Flag = 0x8 - Prebound Flag = 0x10 - SplitSegs Flag = 0x20 - LazyInit Flag = 0x40 - TwoLevel Flag = 0x80 - ForceFlat Flag = 0x100 - NoMultiDefs Flag = 0x200 - NoFixPrebinding Flag = 0x400 - Prebindable Flag = 0x800 - AllModsBound Flag = 0x1000 - SubsectionsViaSymbols Flag = 0x2000 - Canonical Flag = 0x4000 - WeakDefines Flag = 0x8000 - BindsToWeak Flag = 0x10000 - AllowStackExecution Flag = 0x20000 - RootSafe Flag = 0x40000 - SetuidSafe Flag = 0x80000 - NoReexportedDylibs Flag = 0x100000 - PIE Flag = 0x200000 - DeadStrippableDylib Flag = 0x400000 - HasTLVDescriptors Flag = 0x800000 - NoHeapExecution Flag = 0x1000000 - AppExtensionSafe Flag = 0x2000000 - NlistOutofsyncWithDyldinfo Flag = 0x4000000 - SimSupport Flag = 0x8000000 - DylibInCache Flag = 0x80000000 -) - -///GETTERS -func (f Flag) NoUndefs() bool { - return (f & NoUndefs) != 0 -} -func (f Flag) IncrLink() bool { - return (f & IncrLink) != 0 -} -func (f Flag) DyldLink() bool { - return (f & DyldLink) != 0 -} -func (f Flag) BindAtLoad() bool { - return (f & BindAtLoad) != 0 -} -func (f Flag) Prebound() bool { - return (f & Prebound) != 0 -} -func (f Flag) SplitSegs() bool { - return (f & SplitSegs) != 0 -} -func (f Flag) LazyInit() bool { - return (f & LazyInit) != 0 -} -func (f Flag) TwoLevel() bool { - return (f & TwoLevel) != 0 -} -func (f Flag) ForceFlat() bool { - return (f & ForceFlat) != 0 -} -func (f Flag) NoMultiDefs() bool { - return (f & NoMultiDefs) != 0 -} -func (f Flag) NoFixPrebinding() bool { - return (f & NoFixPrebinding) != 0 -} -func (f Flag) Prebindable() bool { - return (f & Prebindable) != 0 -} -func (f Flag) AllModsBound() bool { - return (f & AllModsBound) != 0 -} -func (f Flag) SubsectionsViaSymbols() bool { - return (f & SubsectionsViaSymbols) != 0 -} -func (f Flag) Canonical() bool { - return (f & Canonical) != 0 -} -func (f Flag) WeakDefines() bool { - return (f & WeakDefines) != 0 -} -func (f Flag) BindsToWeak() bool { - return (f & BindsToWeak) != 0 -} -func (f Flag) AllowStackExecution() bool { - return (f & AllowStackExecution) != 0 -} -func (f Flag) RootSafe() bool { - return (f & RootSafe) != 0 -} -func (f Flag) SetuidSafe() bool { - return (f & SetuidSafe) != 0 -} -func (f Flag) NoReexportedDylibs() bool { - return (f & NoReexportedDylibs) != 0 -} -func (f Flag) PIE() bool { - return (f & PIE) != 0 -} -func (f Flag) DeadStrippableDylib() bool { - return (f & DeadStrippableDylib) != 0 -} -func (f Flag) HasTLVDescriptors() bool { - return (f & HasTLVDescriptors) != 0 -} -func (f Flag) NoHeapExecution() bool { - return (f & NoHeapExecution) != 0 -} -func (f Flag) AppExtensionSafe() bool { - return (f & AppExtensionSafe) != 0 -} -func (f Flag) NlistOutofsyncWithDyldinfo() bool { - return (f & NlistOutofsyncWithDyldinfo) != 0 -} -func (f Flag) SimSupport() bool { - return (f & SimSupport) != 0 -} -func (f Flag) DylibInCache() bool { - return (f & DylibInCache) != 0 -} - -///SETTER -func (f *Flag) Set(flag Flag, set bool) { - if set { - *f = (*f | flag) - } else { - *f = (*f ^ flag) - } -} - -// List returns a string array of flag names -func (f Flag) List() []string { - var flags []string - if f.NoUndefs() { - flags = append(flags, NoUndefs.String()) - } - if f.IncrLink() { - flags = append(flags, IncrLink.String()) - } - if f.DyldLink() { - flags = append(flags, DyldLink.String()) - } - if f.BindAtLoad() { - flags = append(flags, BindAtLoad.String()) - } - if f.Prebound() { - flags = append(flags, Prebound.String()) - } - if f.SplitSegs() { - flags = append(flags, SplitSegs.String()) - } - if f.LazyInit() { - flags = append(flags, LazyInit.String()) - } - if f.TwoLevel() { - flags = append(flags, TwoLevel.String()) - } - if f.ForceFlat() { - flags = append(flags, ForceFlat.String()) - } - if f.NoMultiDefs() { - flags = append(flags, NoMultiDefs.String()) - } - if f.NoFixPrebinding() { - flags = append(flags, NoFixPrebinding.String()) - } - if f.Prebindable() { - flags = append(flags, Prebindable.String()) - } - if f.AllModsBound() { - flags = append(flags, AllModsBound.String()) - } - if f.SubsectionsViaSymbols() { - flags = append(flags, SubsectionsViaSymbols.String()) - } - if f.Canonical() { - flags = append(flags, Canonical.String()) - } - if f.WeakDefines() { - flags = append(flags, WeakDefines.String()) - } - if f.BindsToWeak() { - flags = append(flags, BindsToWeak.String()) - } - if f.AllowStackExecution() { - flags = append(flags, AllowStackExecution.String()) - } - if f.RootSafe() { - flags = append(flags, RootSafe.String()) - } - if f.SetuidSafe() { - flags = append(flags, SetuidSafe.String()) - } - if f.NoReexportedDylibs() { - flags = append(flags, NoReexportedDylibs.String()) - } - if f.PIE() { - flags = append(flags, PIE.String()) - } - if f.DeadStrippableDylib() { - flags = append(flags, DeadStrippableDylib.String()) - } - if f.HasTLVDescriptors() { - flags = append(flags, HasTLVDescriptors.String()) - } - if f.NoHeapExecution() { - flags = append(flags, NoHeapExecution.String()) - } - if f.AppExtensionSafe() { - flags = append(flags, AppExtensionSafe.String()) - } - if f.NlistOutofsyncWithDyldinfo() { - flags = append(flags, NlistOutofsyncWithDyldinfo.String()) - } - if f.SimSupport() { - flags = append(flags, SimSupport.String()) - } - if f.DylibInCache() { - flags = append(flags, DylibInCache.String()) - } - return flags -} - -func (f Flag) Flags() string { - var fStr string - for _, attr := range f.List() { - fStr += fmt.Sprintf("%s, ", attr) - } - return strings.TrimSuffix(fStr, ", ") -} diff --git a/pkg/macho/header/header.go b/pkg/macho/header/header.go deleted file mode 100644 index 7f2fd86ee..000000000 --- a/pkg/macho/header/header.go +++ /dev/null @@ -1,58 +0,0 @@ -package header - -import ( - "fmt" - - "github.com/blacktop/ipsw/pkg/macho/utils" -) - -// A FileHeader represents a Mach-O file header. -type FileHeader struct { - Magic Magic - CPU CPU - SubCPU CPUSubtype - Type Type - Ncmd uint32 - Cmdsz uint32 - Flags Flag -} - -const ( - FileHeaderSize32 = 7 * 4 - FileHeaderSize64 = 8 * 4 -) - -type Magic uint32 - -const ( - Magic32 Magic = 0xfeedface - Magic64 Magic = 0xfeedfacf - MagicFat Magic = 0xcafebabe -) - -var magicStrings = []utils.IntName{ - {uint32(Magic32), "32-bit MachO"}, - {uint32(Magic64), "64-bit MachO"}, - {uint32(MagicFat), "Fat MachO"}, -} - -func (i Magic) Int() uint32 { return uint32(i) } -func (i Magic) String() string { return utils.StringName(uint32(i), magicStrings, false) } -func (i Magic) GoString() string { return utils.StringName(uint32(i), magicStrings, true) } - -func (h FileHeader) String() string { - - return fmt.Sprintf( - "Magic = %s\n"+ - "Type = %s\n"+ - "CPU = %s, %s\n"+ - "Commands = %d (Size: %d)\n"+ - "Flags = %s\n", - h.Magic, - h.Type, - h.CPU, h.SubCPU.String(h.CPU), - h.Ncmd, - h.Cmdsz, - h.Flags.Flags(), - ) -} diff --git a/pkg/macho/header/header_string.go b/pkg/macho/header/header_string.go deleted file mode 100644 index aea0b0017..000000000 --- a/pkg/macho/header/header_string.go +++ /dev/null @@ -1,109 +0,0 @@ -// Code generated by "stringer -type=Type,Flag -output header_string.go"; DO NOT EDIT. - -package header - -import "strconv" - -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[Obj-1] - _ = x[Exec-2] - _ = x[FVMLib-3] - _ = x[Core-4] - _ = x[Preload-5] - _ = x[Dylib-6] - _ = x[Dylinker-7] - _ = x[Bundle-8] - _ = x[DylibStub-9] - _ = x[Dsym-10] - _ = x[KextBundle-11] -} - -const _Type_name = "ObjExecFVMLibCorePreloadDylibDylinkerBundleDylibStubDsymKextBundle" - -var _Type_index = [...]uint8{0, 3, 7, 13, 17, 24, 29, 37, 43, 52, 56, 66} - -func (i Type) String() string { - i -= 1 - if i >= Type(len(_Type_index)-1) { - return "Type(" + strconv.FormatInt(int64(i+1), 10) + ")" - } - return _Type_name[_Type_index[i]:_Type_index[i+1]] -} -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[NoUndefs-1] - _ = x[IncrLink-2] - _ = x[DyldLink-4] - _ = x[BindAtLoad-8] - _ = x[Prebound-16] - _ = x[SplitSegs-32] - _ = x[LazyInit-64] - _ = x[TwoLevel-128] - _ = x[ForceFlat-256] - _ = x[NoMultiDefs-512] - _ = x[NoFixPrebinding-1024] - _ = x[Prebindable-2048] - _ = x[AllModsBound-4096] - _ = x[SubsectionsViaSymbols-8192] - _ = x[Canonical-16384] - _ = x[WeakDefines-32768] - _ = x[BindsToWeak-65536] - _ = x[AllowStackExecution-131072] - _ = x[RootSafe-262144] - _ = x[SetuidSafe-524288] - _ = x[NoReexportedDylibs-1048576] - _ = x[PIE-2097152] - _ = x[DeadStrippableDylib-4194304] - _ = x[HasTLVDescriptors-8388608] - _ = x[NoHeapExecution-16777216] - _ = x[AppExtensionSafe-33554432] - _ = x[NlistOutofsyncWithDyldinfo-67108864] - _ = x[SimSupport-134217728] - _ = x[DylibInCache-2147483648] -} - -const _Flag_name = "NoUndefsIncrLinkDyldLinkBindAtLoadPreboundSplitSegsLazyInitTwoLevelForceFlatNoMultiDefsNoFixPrebindingPrebindableAllModsBoundSubsectionsViaSymbolsCanonicalWeakDefinesBindsToWeakAllowStackExecutionRootSafeSetuidSafeNoReexportedDylibsPIEDeadStrippableDylibHasTLVDescriptorsNoHeapExecutionAppExtensionSafeNlistOutofsyncWithDyldinfoSimSupportDylibInCache" - -var _Flag_map = map[Flag]string{ - 1: _Flag_name[0:8], - 2: _Flag_name[8:16], - 4: _Flag_name[16:24], - 8: _Flag_name[24:34], - 16: _Flag_name[34:42], - 32: _Flag_name[42:51], - 64: _Flag_name[51:59], - 128: _Flag_name[59:67], - 256: _Flag_name[67:76], - 512: _Flag_name[76:87], - 1024: _Flag_name[87:102], - 2048: _Flag_name[102:113], - 4096: _Flag_name[113:125], - 8192: _Flag_name[125:146], - 16384: _Flag_name[146:155], - 32768: _Flag_name[155:166], - 65536: _Flag_name[166:177], - 131072: _Flag_name[177:196], - 262144: _Flag_name[196:204], - 524288: _Flag_name[204:214], - 1048576: _Flag_name[214:232], - 2097152: _Flag_name[232:235], - 4194304: _Flag_name[235:254], - 8388608: _Flag_name[254:271], - 16777216: _Flag_name[271:286], - 33554432: _Flag_name[286:302], - 67108864: _Flag_name[302:328], - 134217728: _Flag_name[328:338], - 2147483648: _Flag_name[338:350], -} - -func (i Flag) String() string { - if str, ok := _Flag_map[i]; ok { - return str - } - return "Flag(" + strconv.FormatInt(int64(i), 10) + ")" -} diff --git a/pkg/macho/header/types.go b/pkg/macho/header/types.go deleted file mode 100644 index 928b594ce..000000000 --- a/pkg/macho/header/types.go +++ /dev/null @@ -1,20 +0,0 @@ -package header - -//go:generate stringer -type=Type,Flag -output header_string.go - -// A Type is the Mach-O file type, e.g. an object file, executable, or dynamic library. -type Type uint32 - -const ( - Obj Type = 1 - Exec Type = 2 - FVMLib Type = 3 - Core Type = 4 - Preload Type = 5 /* preloaded executable file */ - Dylib Type = 6 /* dynamically bound shared library */ - Dylinker Type = 7 /* dynamic link editor */ - Bundle Type = 8 - DylibStub Type = 0x9 /* shared library stub for static */ - Dsym Type = 0xa /* companion file with only debug */ - KextBundle Type = 0xb /* x86_64 kexts */ -) diff --git a/pkg/macho/macho.go b/pkg/macho/macho.go deleted file mode 100644 index 1b507ff19..000000000 --- a/pkg/macho/macho.go +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Mach-O header data structures -// Originally at: -// http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html (since deleted by Apply) -// Archived copy at: -// https://web.archive.org/web/20090819232456/http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachORuntime/index.html -// For cloned PDF see: -// https://github.com/aidansteele/osx-abi-macho-file-format-reference - -package macho - -// 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 -} - -// RegsARM is the Mach-O ARM register structure. -type RegsARM struct { - R0 uint32 - R1 uint32 - R2 uint32 - R3 uint32 - R4 uint32 - R5 uint32 - R6 uint32 - R7 uint32 - R8 uint32 - R9 uint32 - R10 uint32 - R11 uint32 - R12 uint32 - SP uint32 - LR uint32 - PC uint32 - CPSR uint32 -} - -// RegsARM64 is the Mach-O ARM 64 register structure. -type RegsARM64 struct { - X0 uint64 - X1 uint64 - X2 uint64 - X3 uint64 - X4 uint64 - X5 uint64 - X6 uint64 - X7 uint64 - X8 uint64 - X9 uint64 - X10 uint64 - X11 uint64 - X12 uint64 - X13 uint64 - X14 uint64 - X15 uint64 - X16 uint64 - X17 uint64 - X18 uint64 - X19 uint64 - X20 uint64 - X21 uint64 - X22 uint64 - X23 uint64 - X24 uint64 - X25 uint64 - X26 uint64 - X27 uint64 - X28 uint64 - FP uint64 - LR uint64 - SP uint64 - PC uint64 - CPSR uint32 - PAD uint32 -} diff --git a/pkg/macho/types/codesign.go b/pkg/macho/types/codesign.go deleted file mode 100644 index 336be80c7..000000000 --- a/pkg/macho/types/codesign.go +++ /dev/null @@ -1,120 +0,0 @@ -package types - -const ( - // Magic numbers used by Code Signing - CSMAGIC_REQUIREMENT = 0xfade0c00 // single Requirement blob - CSMAGIC_REQUIREMENTS = 0xfade0c01 // Requirements vector (internal requirements) - CSMAGIC_CODEDIRECTORY = 0xfade0c02 // CodeDirectory blob - CSMAGIC_EMBEDDED_SIGNATURE = 0xfade0cc0 // embedded form of signature data - CSMAGIC_DETACHED_SIGNATURE = 0xfade0cc1 // multi-arch collection of embedded signatures - CSMAGIC_BLOBWRAPPER = 0xfade0b01 // used for the cms blob -) - -const ( - CS_PAGE_SIZE = 4096 - - CS_HASHTYPE_SHA1 = 1 - CS_HASHTYPE_SHA256 = 2 - CS_HASHTYPE_SHA256_TRUNCATED = 3 - CS_HASHTYPE_SHA384 = 4 - - CS_HASH_SIZE_SHA1 = 20 - CS_HASH_SIZE_SHA256 = 32 - CS_HASH_SIZE_SHA256_TRUNCATED = 20 - - CSSLOT_CODEDIRECTORY = 0 - CSSLOT_INFOSLOT = 1 - CSSLOT_REQUIREMENTS = 2 - CSSLOT_RESOURCEDIR = 3 - CSSLOT_APPLICATION = 4 - CSSLOT_ENTITLEMENTS = 5 - CSSLOT_ALTERNATE_CODEDIRECTORIES = 0x1000 - CSSLOT_ALTERNATE_CODEDIRECTORY_MAX = 5 - CSSLOT_ALTERNATE_CODEDIRECTORY_LIMIT = CSSLOT_ALTERNATE_CODEDIRECTORIES + CSSLOT_ALTERNATE_CODEDIRECTORY_MAX - CSSLOT_CMS_SIGNATURE = 0x10000 - - kSecCodeSignatureAdhoc = 2 -) - -const CS_REQUIRE_LV = 0x0002000 // require library validation - -// Structure of a SuperBlob -type CsBlobIndex struct { - Type uint32 // type of entry - Offset uint32 // offset of entry -} - -type CsSuperBlob struct { - Magic uint32 // magic number - Length uint32 // total length of SuperBlob - Count uint32 // number of index entries following - // Index []CsBlobIndex // (count) entries - // followed by Blobs in no particular order as indicated by offsets in index -} - -// type CsSuperBlob struct { -// Magic uint32 // magic number -// Length uint32 // total length of SuperBlob -// Count uint32 // number of index entries following -// Index []CsBlobIndex // (count) entries -// // followed by Blobs in no particular order as indicated by offsets in index -// } - -// C form of a CodeDirectory. -type CsCodeDirectory struct { - Magic uint32 // magic number (CSMAGIC_CODEDIRECTORY) */ - Length uint32 // total length of CodeDirectory blob - Version uint32 // compatibility version - Flags uint32 // setup and mode flags - HashOffset uint32 // offset of hash slot element at index zero - IdentOffset uint32 // offset of identifier string - NSpecialSlots uint32 // number of special hash slots - NCodeSlots uint32 // number of ordinary (code) hash slots - CodeLimit uint32 // limit to main image signature range - HashSize uint8 // size of each hash in bytes - HashType uint8 // type of hash (cdHashType* constants) - Platform uint8 // platform identifier zero if not platform binary - PageSize uint8 // log2(page size in bytes) 0 => infinite - Spare2 uint32 // unused (must be zero) - - EndEarliest [0]uint8 - - /* Version 0x20100 */ - ScatterOffset uint32 /* offset of optional scatter vector */ - EndWithScatter [0]uint8 - - /* Version 0x20200 */ - TeamOffset uint32 /* offset of optional team identifier */ - EndWithTeam [0]uint8 - - /* Version 0x20300 */ - Spare3 uint32 /* unused (must be zero) */ - CodeLimit64 uint64 /* limit to main image signature range, 64 bits */ - EndWithCodeLimit64 [0]uint8 - - /* Version 0x20400 */ - ExecSegBase uint64 /* offset of executable segment */ - ExecSegLimit uint64 /* limit of executable segment */ - ExecSegFlags uint64 /* exec segment flags */ - EndWithExecSeg [0]uint8 - - /* followed by dynamic content as located by offset fields above */ -} - -type CsBlob struct { - Magic uint32 // magic number - Length uint32 // total length of blob -} - -type CsRequirementsBlob struct { - Magic uint32 // magic number - Length uint32 // total length of blob - Data uint32 // zero for dyld shared cache -} - -type CsScatter struct { - Count uint32 // number of pages zero for sentinel (only) - Base uint32 // first page number - TargetOffset uint64 // byte offset in target - Spare uint64 // reserved (must be zero) -} diff --git a/pkg/macho/types/nlist.go b/pkg/macho/types/nlist.go deleted file mode 100644 index 674ef9b2c..000000000 --- a/pkg/macho/types/nlist.go +++ /dev/null @@ -1,262 +0,0 @@ -package types - -import "strings" - -import "fmt" - -// An Nlist32 is a Mach-O 32-bit symbol table entry. -type Nlist32 struct { - Name uint32 - Type NLType - Sect uint8 - Desc uint16 - Value uint32 -} - -// An Nlist64 is a Mach-O 64-bit symbol table entry. -type Nlist64 struct { - Name uint32 - Type NLType - Sect uint8 - Desc uint16 - Value uint64 -} - -type NLType uint8 - -/* - * The n_type field really contains four fields: - * unsigned char N_STAB:3, - * N_PEXT:1, - * N_TYPE:3, - * N_EXT:1; - * which are used via the following masks. - */ -const ( - N_STAB NLType = 0xe0 /* if any of these bits set, a symbolic debugging entry */ - N_PEXT NLType = 0x10 /* private external symbol bit */ - N_TYPE NLType = 0x0e /* mask for the type bits */ - N_EXT NLType = 0x01 /* external symbol bit, set for external symbols */ -) - -/* - * Values for N_TYPE bits of the n_type field. - */ -const ( - N_UNDF NLType = 0x0 /* undefined, n_sect == NO_SECT */ - N_ABS NLType = 0x2 /* absolute, n_sect == NO_SECT */ - N_SECT NLType = 0xe /* defined in section number n_sect */ - N_PBUD NLType = 0xc /* prebound undefined (defined in a dylib) */ - N_INDR NLType = 0xa /* indirect */ -) - -func (t NLType) IsDebugSym() bool { - return (t & N_STAB) != 0 -} - -func (t NLType) IsPrivateExternalSym() bool { - return (t & N_PEXT) != 0 -} - -func (t NLType) IsExternalSym() bool { - return (t & N_EXT) != 0 -} - -func (t NLType) IsUndefinedSym() bool { - return (t & N_TYPE) == N_UNDF -} -func (t NLType) IsAbsoluteSym() bool { - return (t & N_TYPE) == N_ABS -} -func (t NLType) IsDefinedInSection() bool { - return (t & N_TYPE) == N_SECT -} -func (t NLType) IsPreboundUndefinedSym() bool { - return (t & N_TYPE) == N_PBUD -} -func (t NLType) IsIndirectSym() bool { - return (t & N_TYPE) == N_INDR -} - -func (t NLType) String(secName string) string { - var tStr string - if t.IsDebugSym() { - tStr += "debug|" - } - if t.IsPrivateExternalSym() { - tStr += "private_external|" - } - if t.IsExternalSym() { - tStr += "external|" - } - if t.IsUndefinedSym() { - tStr += "undefined|" - } - if t.IsAbsoluteSym() { - tStr += "absolute|" - } - if t.IsDefinedInSection() { - tStr += fmt.Sprintf("%s|", secName) - } - if t.IsPreboundUndefinedSym() { - tStr += "prebound_undefined|" - } - if t.IsIndirectSym() { - tStr += "indirect|" - } - return strings.TrimSuffix(tStr, "|") -} - -type nListDesc uint16 - -func (d nListDesc) GetCommAlign() nListDesc { - return (d >> 8) & 0x0f -} - -const REFERENCE_TYPE nListDesc = 0x7 - -const ( - /* types of references */ - REFERENCE_FLAG_UNDEFINED_NON_LAZY nListDesc = 0 - REFERENCE_FLAG_UNDEFINED_LAZY nListDesc = 1 - REFERENCE_FLAG_DEFINED nListDesc = 2 - REFERENCE_FLAG_PRIVATE_DEFINED nListDesc = 3 - REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY nListDesc = 4 - REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY nListDesc = 5 -) - -func (d nListDesc) IsUndefinedNonLazy() bool { - return (d & REFERENCE_TYPE) == REFERENCE_FLAG_UNDEFINED_NON_LAZY -} -func (d nListDesc) IsUndefinedLazy() bool { - return (d & REFERENCE_TYPE) == REFERENCE_FLAG_UNDEFINED_LAZY -} -func (d nListDesc) IsDefined() bool { - return (d & REFERENCE_TYPE) == REFERENCE_FLAG_DEFINED -} -func (d nListDesc) IsPrivateDefined() bool { - return (d & REFERENCE_TYPE) == REFERENCE_FLAG_PRIVATE_DEFINED -} -func (d nListDesc) IsPrivateUndefinedNonLazy() bool { - return (d & REFERENCE_TYPE) == REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY -} -func (d nListDesc) IsPrivateUndefinedLazy() bool { - return (d & REFERENCE_TYPE) == REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY -} - -func (d nListDesc) GetLibraryOrdinal() nListDesc { - return (d >> 8) & 0xff -} - -const ( - SELF_LIBRARY_ORDINAL nListDesc = 0x0 - MAX_LIBRARY_ORDINAL nListDesc = 0xfd - DYNAMIC_LOOKUP_ORDINAL nListDesc = 0xfe - EXECUTABLE_ORDINAL nListDesc = 0xff -) - -const ( - /* - * The N_NO_DEAD_STRIP bit of the n_desc field only ever appears in a - * relocatable .o file (MH_OBJECT filetype). And is used to indicate to the - * static link editor it is never to dead strip the symbol. - */ - NO_DEAD_STRIP nListDesc = 0x0020 /* symbol is not to be dead stripped */ - - /* - * The N_DESC_DISCARDED bit of the n_desc field never appears in linked image. - * But is used in very rare cases by the dynamic link editor to mark an in - * memory symbol as discared and longer used for linking. - */ - DESC_DISCARDED nListDesc = 0x0020 /* symbol is discarded */ - - /* - * The N_WEAK_REF bit of the n_desc field indicates to the dynamic linker that - * the undefined symbol is allowed to be missing and is to have the address of - * zero when missing. - */ - WEAK_REF nListDesc = 0x0040 /* symbol is weak referenced */ - - /* - * The N_WEAK_DEF bit of the n_desc field indicates to the static and dynamic - * linkers that the symbol definition is weak, allowing a non-weak symbol to - * also be used which causes the weak definition to be discared. Currently this - * is only supported for symbols in coalesed sections. - */ - WEAK_DEF nListDesc = 0x0080 /* coalesed symbol is a weak definition */ - - /* - * The N_REF_TO_WEAK bit of the n_desc field indicates to the dynamic linker - * that the undefined symbol should be resolved using flat namespace searching. - */ - REF_TO_WEAK nListDesc = 0x0080 /* reference to a weak symbol */ - - /* - * The N_ARM_THUMB_DEF bit of the n_desc field indicates that the symbol is - * a defintion of a Thumb function. - */ - ARM_THUMB_DEF nListDesc = 0x0008 /* symbol is a Thumb function (ARM) */ - - /* - * The N_SYMBOL_RESOLVER bit of the n_desc field indicates that the - * that the function is actually a resolver function and should - * be called to get the address of the real function to use. - * This bit is only available in .o files (MH_OBJECT filetype) - */ - SYMBOL_RESOLVER nListDesc = 0x0100 - - /* - * The N_ALT_ENTRY bit of the n_desc field indicates that the - * symbol is pinned to the previous content. - */ - ALT_ENTRY nListDesc = 0x0200 - - /* - * The N_COLD_FUNC bit of the n_desc field indicates that the symbol is used - * infrequently and the linker should order it towards the end of the section. - */ - N_COLD_FUNC nListDesc = 0x0400 -) - -/* - * Symbolic debugger symbols. - */ -const ( - N_GSYM = 0x20 /* global symbol: name,,NO_SECT,type,0 */ - N_FNAME = 0x22 /* procedure name (f77 kludge): name,,NO_SECT,0,0 */ - N_FUN = 0x24 /* procedure: name,,n_sect,linenumber,address */ - N_STSYM = 0x26 /* static symbol: name,,n_sect,type,address */ - N_LCSYM = 0x28 /* .lcomm symbol: name,,n_sect,type,address */ - N_BNSYM = 0x2e /* begin nsect sym: 0,,n_sect,0,address */ - N_AST = 0x32 /* AST file path: name,,NO_SECT,0,0 */ - N_OPT = 0x3c /* emitted with gcc2_compiled and in gcc source */ - N_RSYM = 0x40 /* register sym: name,,NO_SECT,type,register */ - N_SLINE = 0x44 /* src line: 0,,n_sect,linenumber,address */ - N_ENSYM = 0x4e /* end nsect sym: 0,,n_sect,0,address */ - N_SSYM = 0x60 /* structure elt: name,,NO_SECT,type,struct_offset */ - N_SO = 0x64 /* source file name: name,,n_sect,0,address */ - N_OSO = 0x66 /* object file name: name,,(see below),0,st_mtime */ - /* historically N_OSO set n_sect to 0. The N_OSO - * n_sect may instead hold the low byte of the - * cpusubtype value from the Mach-O header. */ - N_LSYM = 0x80 /* local sym: name,,NO_SECT,type,offset */ - N_BINCL = 0x82 /* include file beginning: name,,NO_SECT,0,sum */ - N_SOL = 0x84 /* #included file name: name,,n_sect,0,address */ - N_PARAMS = 0x86 /* compiler parameters: name,,NO_SECT,0,0 */ - N_VERSION = 0x88 /* compiler version: name,,NO_SECT,0,0 */ - N_OLEVEL = 0x8A /* compiler -O level: name,,NO_SECT,0,0 */ - N_PSYM = 0xa0 /* parameter: name,,NO_SECT,type,offset */ - N_EINCL = 0xa2 /* include file end: name,,NO_SECT,0,0 */ - N_ENTRY = 0xa4 /* alternate entry: name,,n_sect,linenumber,address */ - N_LBRAC = 0xc0 /* left bracket: 0,,NO_SECT,nesting level,address */ - N_EXCL = 0xc2 /* deleted include file: name,,NO_SECT,0,sum */ - N_RBRAC = 0xe0 /* right bracket: 0,,NO_SECT,nesting level,address */ - N_BCOMM = 0xe2 /* begin common: name,,NO_SECT,0,0 */ - N_ECOMM = 0xe4 /* end common: name,,n_sect,0,0 */ - N_ECOML = 0xe8 /* end common (local name): 0,,n_sect,0,address */ - N_LENG = 0xfe /* second stab entry with length information */ - /* - * for the berkeley pascal compiler, pc(1): - */ - N_PC = 0x30 /* global pascal symbol: name,,NO_SECT,subtype,line */ -) diff --git a/pkg/macho/types/reloc.go b/pkg/macho/types/reloc.go deleted file mode 100644 index 466bc0cee..000000000 --- a/pkg/macho/types/reloc.go +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package types - -//go:generate stringer -type=RelocTypeGeneric,RelocTypeX86_64,RelocTypeARM,RelocTypeARM64 -output reloc_string.go - -type RelocTypeGeneric int - -const ( - GENERIC_RELOC_VANILLA RelocTypeGeneric = 0 - GENERIC_RELOC_PAIR RelocTypeGeneric = 1 - GENERIC_RELOC_SECTDIFF RelocTypeGeneric = 2 - GENERIC_RELOC_PB_LA_PTR RelocTypeGeneric = 3 - GENERIC_RELOC_LOCAL_SECTDIFF RelocTypeGeneric = 4 - GENERIC_RELOC_TLV RelocTypeGeneric = 5 -) - -func (r RelocTypeGeneric) GoString() string { return "macho." + r.String() } - -type RelocTypeX86_64 int - -const ( - X86_64_RELOC_UNSIGNED RelocTypeX86_64 = 0 - X86_64_RELOC_SIGNED RelocTypeX86_64 = 1 - X86_64_RELOC_BRANCH RelocTypeX86_64 = 2 - X86_64_RELOC_GOT_LOAD RelocTypeX86_64 = 3 - X86_64_RELOC_GOT RelocTypeX86_64 = 4 - X86_64_RELOC_SUBTRACTOR RelocTypeX86_64 = 5 - X86_64_RELOC_SIGNED_1 RelocTypeX86_64 = 6 - X86_64_RELOC_SIGNED_2 RelocTypeX86_64 = 7 - X86_64_RELOC_SIGNED_4 RelocTypeX86_64 = 8 - X86_64_RELOC_TLV RelocTypeX86_64 = 9 -) - -func (r RelocTypeX86_64) GoString() string { return "macho." + r.String() } - -type RelocTypeARM int - -const ( - ARM_RELOC_VANILLA RelocTypeARM = 0 - ARM_RELOC_PAIR RelocTypeARM = 1 - ARM_RELOC_SECTDIFF RelocTypeARM = 2 - ARM_RELOC_LOCAL_SECTDIFF RelocTypeARM = 3 - ARM_RELOC_PB_LA_PTR RelocTypeARM = 4 - ARM_RELOC_BR24 RelocTypeARM = 5 - ARM_THUMB_RELOC_BR22 RelocTypeARM = 6 - ARM_THUMB_32BIT_BRANCH RelocTypeARM = 7 - ARM_RELOC_HALF RelocTypeARM = 8 - ARM_RELOC_HALF_SECTDIFF RelocTypeARM = 9 -) - -func (r RelocTypeARM) GoString() string { return "macho." + r.String() } - -type RelocTypeARM64 int - -const ( - ARM64_RELOC_UNSIGNED RelocTypeARM64 = 0 - ARM64_RELOC_SUBTRACTOR RelocTypeARM64 = 1 - ARM64_RELOC_BRANCH26 RelocTypeARM64 = 2 - ARM64_RELOC_PAGE21 RelocTypeARM64 = 3 - ARM64_RELOC_PAGEOFF12 RelocTypeARM64 = 4 - ARM64_RELOC_GOT_LOAD_PAGE21 RelocTypeARM64 = 5 - ARM64_RELOC_GOT_LOAD_PAGEOFF12 RelocTypeARM64 = 6 - ARM64_RELOC_POINTER_TO_GOT RelocTypeARM64 = 7 - ARM64_RELOC_TLVP_LOAD_PAGE21 RelocTypeARM64 = 8 - ARM64_RELOC_TLVP_LOAD_PAGEOFF12 RelocTypeARM64 = 9 - ARM64_RELOC_ADDEND RelocTypeARM64 = 10 -) - -func (r RelocTypeARM64) GoString() string { return "macho." + r.String() } diff --git a/pkg/macho/types/reloc_string.go b/pkg/macho/types/reloc_string.go deleted file mode 100644 index 3a552154f..000000000 --- a/pkg/macho/types/reloc_string.go +++ /dev/null @@ -1,107 +0,0 @@ -// Code generated by "stringer -type=RelocTypeGeneric,RelocTypeX86_64,RelocTypeARM,RelocTypeARM64 -output reloc_string.go"; DO NOT EDIT. - -package types - -import "strconv" - -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[GENERIC_RELOC_VANILLA-0] - _ = x[GENERIC_RELOC_PAIR-1] - _ = x[GENERIC_RELOC_SECTDIFF-2] - _ = x[GENERIC_RELOC_PB_LA_PTR-3] - _ = x[GENERIC_RELOC_LOCAL_SECTDIFF-4] - _ = x[GENERIC_RELOC_TLV-5] -} - -const _RelocTypeGeneric_name = "GENERIC_RELOC_VANILLAGENERIC_RELOC_PAIRGENERIC_RELOC_SECTDIFFGENERIC_RELOC_PB_LA_PTRGENERIC_RELOC_LOCAL_SECTDIFFGENERIC_RELOC_TLV" - -var _RelocTypeGeneric_index = [...]uint8{0, 21, 39, 61, 84, 112, 129} - -func (i RelocTypeGeneric) String() string { - if i < 0 || i >= RelocTypeGeneric(len(_RelocTypeGeneric_index)-1) { - return "RelocTypeGeneric(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _RelocTypeGeneric_name[_RelocTypeGeneric_index[i]:_RelocTypeGeneric_index[i+1]] -} -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[X86_64_RELOC_UNSIGNED-0] - _ = x[X86_64_RELOC_SIGNED-1] - _ = x[X86_64_RELOC_BRANCH-2] - _ = x[X86_64_RELOC_GOT_LOAD-3] - _ = x[X86_64_RELOC_GOT-4] - _ = x[X86_64_RELOC_SUBTRACTOR-5] - _ = x[X86_64_RELOC_SIGNED_1-6] - _ = x[X86_64_RELOC_SIGNED_2-7] - _ = x[X86_64_RELOC_SIGNED_4-8] - _ = x[X86_64_RELOC_TLV-9] -} - -const _RelocTypeX86_64_name = "X86_64_RELOC_UNSIGNEDX86_64_RELOC_SIGNEDX86_64_RELOC_BRANCHX86_64_RELOC_GOT_LOADX86_64_RELOC_GOTX86_64_RELOC_SUBTRACTORX86_64_RELOC_SIGNED_1X86_64_RELOC_SIGNED_2X86_64_RELOC_SIGNED_4X86_64_RELOC_TLV" - -var _RelocTypeX86_64_index = [...]uint8{0, 21, 40, 59, 80, 96, 119, 140, 161, 182, 198} - -func (i RelocTypeX86_64) String() string { - if i < 0 || i >= RelocTypeX86_64(len(_RelocTypeX86_64_index)-1) { - return "RelocTypeX86_64(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _RelocTypeX86_64_name[_RelocTypeX86_64_index[i]:_RelocTypeX86_64_index[i+1]] -} -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[ARM_RELOC_VANILLA-0] - _ = x[ARM_RELOC_PAIR-1] - _ = x[ARM_RELOC_SECTDIFF-2] - _ = x[ARM_RELOC_LOCAL_SECTDIFF-3] - _ = x[ARM_RELOC_PB_LA_PTR-4] - _ = x[ARM_RELOC_BR24-5] - _ = x[ARM_THUMB_RELOC_BR22-6] - _ = x[ARM_THUMB_32BIT_BRANCH-7] - _ = x[ARM_RELOC_HALF-8] - _ = x[ARM_RELOC_HALF_SECTDIFF-9] -} - -const _RelocTypeARM_name = "ARM_RELOC_VANILLAARM_RELOC_PAIRARM_RELOC_SECTDIFFARM_RELOC_LOCAL_SECTDIFFARM_RELOC_PB_LA_PTRARM_RELOC_BR24ARM_THUMB_RELOC_BR22ARM_THUMB_32BIT_BRANCHARM_RELOC_HALFARM_RELOC_HALF_SECTDIFF" - -var _RelocTypeARM_index = [...]uint8{0, 17, 31, 49, 73, 92, 106, 126, 148, 162, 185} - -func (i RelocTypeARM) String() string { - if i < 0 || i >= RelocTypeARM(len(_RelocTypeARM_index)-1) { - return "RelocTypeARM(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _RelocTypeARM_name[_RelocTypeARM_index[i]:_RelocTypeARM_index[i+1]] -} -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[ARM64_RELOC_UNSIGNED-0] - _ = x[ARM64_RELOC_SUBTRACTOR-1] - _ = x[ARM64_RELOC_BRANCH26-2] - _ = x[ARM64_RELOC_PAGE21-3] - _ = x[ARM64_RELOC_PAGEOFF12-4] - _ = x[ARM64_RELOC_GOT_LOAD_PAGE21-5] - _ = x[ARM64_RELOC_GOT_LOAD_PAGEOFF12-6] - _ = x[ARM64_RELOC_POINTER_TO_GOT-7] - _ = x[ARM64_RELOC_TLVP_LOAD_PAGE21-8] - _ = x[ARM64_RELOC_TLVP_LOAD_PAGEOFF12-9] - _ = x[ARM64_RELOC_ADDEND-10] -} - -const _RelocTypeARM64_name = "ARM64_RELOC_UNSIGNEDARM64_RELOC_SUBTRACTORARM64_RELOC_BRANCH26ARM64_RELOC_PAGE21ARM64_RELOC_PAGEOFF12ARM64_RELOC_GOT_LOAD_PAGE21ARM64_RELOC_GOT_LOAD_PAGEOFF12ARM64_RELOC_POINTER_TO_GOTARM64_RELOC_TLVP_LOAD_PAGE21ARM64_RELOC_TLVP_LOAD_PAGEOFF12ARM64_RELOC_ADDEND" - -var _RelocTypeARM64_index = [...]uint16{0, 20, 42, 62, 80, 101, 128, 158, 184, 212, 243, 261} - -func (i RelocTypeARM64) String() string { - if i < 0 || i >= RelocTypeARM64(len(_RelocTypeARM64_index)-1) { - return "RelocTypeARM64(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _RelocTypeARM64_name[_RelocTypeARM64_index[i]:_RelocTypeARM64_index[i+1]] -} diff --git a/pkg/macho/types/types.go b/pkg/macho/types/types.go deleted file mode 100644 index af9c5d688..000000000 --- a/pkg/macho/types/types.go +++ /dev/null @@ -1,115 +0,0 @@ -package types - -//go:generate stringer -type=Platform,Tool,DiceKind -output types_string.go - -import ( - "encoding/binary" - "fmt" -) - -type VmProtection int32 - -func (v VmProtection) Read() bool { - return (v & 0x01) != 0 -} - -func (v VmProtection) Write() bool { - return (v & 0x02) != 0 -} - -func (v VmProtection) Execute() bool { - return (v & 0x04) != 0 -} - -func (v VmProtection) String() string { - var protStr string - if v.Read() { - protStr += "r" - } else { - protStr += "-" - } - if v.Write() { - protStr += "w" - } else { - protStr += "-" - } - if v.Execute() { - protStr += "x" - } else { - protStr += "-" - } - return protStr -} - -// UUID is a macho uuid object -type UUID [16]byte - -func (u UUID) String() string { - return fmt.Sprintf("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", - u[0], u[1], u[2], u[3], u[4], u[5], u[6], u[7], u[8], u[9], u[10], u[11], u[12], u[13], u[14], u[15]) -} - -// Platform is a macho platform object -type Platform uint32 - -const ( - unknown Platform = 0 - macOS Platform = 1 // PLATFORM_MACOS - iOS Platform = 2 // PLATFORM_IOS - tvOS Platform = 3 // PLATFORM_TVOS - watchOS Platform = 4 // PLATFORM_WATCHOS - bridgeOS Platform = 5 // PLATFORM_BRIDGEOS - macCatalyst Platform = 6 // PLATFORM_MACCATALYST - iOSSimulator Platform = 7 // PLATFORM_IOSSIMULATOR - tvOSSimulator Platform = 8 // PLATFORM_TVOSSIMULATOR - watchOSSimulator Platform = 9 // PLATFORM_WATCHOSSIMULATOR - driverKit Platform = 10 // PLATFORM_DRIVERKIT -) - -type Version uint32 - -func (v Version) String() string { - s := make([]byte, 4) - binary.BigEndian.PutUint32(s, uint32(v)) - return fmt.Sprintf("%d.%d.%d", binary.BigEndian.Uint16(s[:2]), s[2], s[3]) -} - -type SrcVersion uint64 - -func (sv SrcVersion) String() string { - a := sv >> 40 - b := (sv >> 30) & 0x3ff - c := (sv >> 20) & 0x3ff - d := (sv >> 10) & 0x3ff - e := sv & 0x3ff - return fmt.Sprintf("%d.%d.%d.%d.%d", a, b, c, d, e) -} - -type Tool uint32 - -const ( - clang Tool = 1 // TOOL_CLANG - swift Tool = 2 // TOOL_SWIFT - ld Tool = 3 // TOOL_LD -) - -type BuildToolVersion struct { - Tool Tool /* enum for the tool */ - Version Version /* version number of the tool */ -} - -type DataInCodeEntry struct { - Offset uint32 - Length uint16 - Kind DiceKind -} - -type DiceKind uint16 - -const ( - KindData DiceKind = 0x0001 - KindJumpTable8 DiceKind = 0x0002 - KindJumpTable16 DiceKind = 0x0003 - KindJumpTable32 DiceKind = 0x0004 - KindAbsJumpTable32 DiceKind = 0x0005 -) diff --git a/pkg/macho/types/types_string.go b/pkg/macho/types/types_string.go deleted file mode 100644 index 2e42f611d..000000000 --- a/pkg/macho/types/types_string.go +++ /dev/null @@ -1,75 +0,0 @@ -// Code generated by "stringer -type=Platform,Tool,DiceKind -output types_string.go"; DO NOT EDIT. - -package types - -import "strconv" - -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[unknown-0] - _ = x[macOS-1] - _ = x[iOS-2] - _ = x[tvOS-3] - _ = x[watchOS-4] - _ = x[bridgeOS-5] - _ = x[macCatalyst-6] - _ = x[iOSSimulator-7] - _ = x[tvOSSimulator-8] - _ = x[watchOSSimulator-9] - _ = x[driverKit-10] -} - -const _Platform_name = "unknownmacOSiOStvOSwatchOSbridgeOSmacCatalystiOSSimulatortvOSSimulatorwatchOSSimulatordriverKit" - -var _Platform_index = [...]uint8{0, 7, 12, 15, 19, 26, 34, 45, 57, 70, 86, 95} - -func (i Platform) String() string { - if i >= Platform(len(_Platform_index)-1) { - return "Platform(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _Platform_name[_Platform_index[i]:_Platform_index[i+1]] -} -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[clang-1] - _ = x[swift-2] - _ = x[ld-3] -} - -const _Tool_name = "clangswiftld" - -var _Tool_index = [...]uint8{0, 5, 10, 12} - -func (i Tool) String() string { - i -= 1 - if i >= Tool(len(_Tool_index)-1) { - return "Tool(" + strconv.FormatInt(int64(i+1), 10) + ")" - } - return _Tool_name[_Tool_index[i]:_Tool_index[i+1]] -} -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[KindData-1] - _ = x[KindJumpTable8-2] - _ = x[KindJumpTable16-3] - _ = x[KindJumpTable32-4] - _ = x[KindAbsJumpTable32-5] -} - -const _DiceKind_name = "KindDataKindJumpTable8KindJumpTable16KindJumpTable32KindAbsJumpTable32" - -var _DiceKind_index = [...]uint8{0, 8, 22, 37, 52, 70} - -func (i DiceKind) String() string { - i -= 1 - if i >= DiceKind(len(_DiceKind_index)-1) { - return "DiceKind(" + strconv.FormatInt(int64(i+1), 10) + ")" - } - return _DiceKind_name[_DiceKind_index[i]:_DiceKind_index[i+1]] -} diff --git a/pkg/macho/utils/utils.go b/pkg/macho/utils/utils.go deleted file mode 100644 index faef30588..000000000 --- a/pkg/macho/utils/utils.go +++ /dev/null @@ -1,20 +0,0 @@ -package utils - -import "strconv" - -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) -}