diff --git a/file.go b/file.go index 79ba854..1163a54 100644 --- a/file.go +++ b/file.go @@ -29,6 +29,9 @@ import ( "path" "sort" "sync" + + macho2 "github.com/blacktop/go-macho" + "github.com/blacktop/go-macho/pkg/fixupchains" ) var ( @@ -416,6 +419,16 @@ func (f *GoFile) PCLNTab() (*gosym.Table, error) { // Since the moduledata starts with the address to the pclntab, we can use this to find the moduledata structure. runtimeText, err := f.findRuntimeText(textStart, textStart+uint64(len(textData)), f.pclntabAddr, moddataSection) if err != nil { + if f.FileInfo.OS == "macOS" && f.FileInfo.Arch == ArchARM64 { + t, err := f.findRuntimeTextMachoChainedFixups(f.pclntabAddr) + if err != nil { + f.pclntabError = fmt.Errorf("failed to find runtime.text symbol: %w", err) + return + } + f.runtimeText = t + return + } + f.pclntabError = fmt.Errorf("failed to find runtime.text symbol: %w", err) return } @@ -428,6 +441,45 @@ func (f *GoFile) PCLNTab() (*gosym.Table, error) { return gosym.NewTable(make([]byte, 0), gosym.NewLineTable(f.pclntabBytes, f.runtimeText)) } +func (f *GoFile) findRuntimeTextMachoChainedFixups(pclntabAddr uint64) (uint64, error) { + of := f.fh.getFile() + _, err := of.Seek(0, io.SeekStart) + if err != nil { + return 0, err + } + + f2, err := macho2.NewFile(of) + if err != nil { + return 0, err + } + fixups, err := f2.DyldChainedFixups() + if err != nil { + return 0, err + } + baseAddr := f2.GetBaseAddress() + var rebases []fixupchains.Rebase + for _, start := range fixups.Starts { + rebases = append(rebases, start.Rebases()...) + } + + // First, we need to find the start of the moduledata + var moduledataAddr uint64 + for _, rb := range rebases { + if rb.Target()+baseAddr == pclntabAddr { + moduledataAddr = baseAddr + rb.Offset() + break + } + } + // then, find field 22 + addr22 := moduledataAddr + 22*8 + for _, rb := range rebases { + if rb.Offset()+baseAddr == addr22 { + return baseAddr + rb.Target(), nil + } + } + return 0, fmt.Errorf("failed to find runtime.text symbol") +} + func (f *GoFile) findRuntimeText(textStart, textEnd, pclntabAddr uint64, modSectiondata []byte) (uint64, error) { var text, etext uint64 magic := buildPclnTabAddrBinary(f.FileInfo.WordSize, f.FileInfo.ByteOrder, pclntabAddr) diff --git a/go.mod b/go.mod index d86c5e9..08c0bf7 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/goretk/gore go 1.21 require ( + github.com/blacktop/go-macho v1.1.232 github.com/go-git/go-git/v5 v5.11.0 github.com/stretchr/testify v1.8.4 golang.org/x/arch v0.7.0 @@ -12,6 +13,7 @@ require ( dario.cat/mergo v1.0.0 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/ProtonMail/go-crypto v1.0.0 // indirect + github.com/blacktop/go-dwarf v1.0.10 // indirect github.com/cloudflare/circl v1.3.7 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/davecgh/go-spew v1.1.1 // indirect diff --git a/go.sum b/go.sum index ba1c0e4..cdb295f 100644 --- a/go.sum +++ b/go.sum @@ -9,6 +9,10 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/blacktop/go-dwarf v1.0.10 h1:i9zYgcIROETsNZ6V+zZn3uDH21FCG5BLLZ837GitxS0= +github.com/blacktop/go-dwarf v1.0.10/go.mod h1:4W2FKgSFYcZLDwnR7k+apv5i3nrau4NGl9N6VQ9DSTo= +github.com/blacktop/go-macho v1.1.232 h1:9spphgi1rVnhW1HnBXaPaa75t1Rb1FlgL27IUHEYWSc= +github.com/blacktop/go-macho v1.1.232/go.mod h1:dtlW2AJKQpFzImBVPWiUKZ6OxrQ2MLfWi/BPPe0EONE= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=