mirror of
https://github.com/anchore/syft.git
synced 2026-02-12 02:26:42 +01:00
support universal (fat) mach-o binary files (#4278)
Signed-off-by: Joseph Shapiro <joeyashapiro@gmail.com>
This commit is contained in:
parent
07029ead8a
commit
31b2c4c090
@ -3,6 +3,7 @@ package executable
|
|||||||
import (
|
import (
|
||||||
"debug/macho"
|
"debug/macho"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/internal"
|
||||||
"github.com/anchore/syft/syft/file"
|
"github.com/anchore/syft/syft/file"
|
||||||
"github.com/anchore/syft/syft/internal/unionreader"
|
"github.com/anchore/syft/syft/internal/unionreader"
|
||||||
)
|
)
|
||||||
@ -19,20 +20,38 @@ const (
|
|||||||
func findMachoFeatures(data *file.Executable, reader unionreader.UnionReader) error {
|
func findMachoFeatures(data *file.Executable, reader unionreader.UnionReader) error {
|
||||||
// TODO: support security features
|
// TODO: support security features
|
||||||
|
|
||||||
// TODO: support multi-architecture binaries
|
// a universal binary may have multiple architectures, so we need to check each one
|
||||||
f, err := macho.NewFile(reader)
|
readers, err := unionreader.GetReaders(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
libs, err := f.ImportedLibraries()
|
var libs []string
|
||||||
if err != nil {
|
for _, r := range readers {
|
||||||
return err
|
f, err := macho.NewFile(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
rLibs, err := f.ImportedLibraries()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
libs = append(libs, rLibs...)
|
||||||
|
|
||||||
|
// TODO handle only some having entrypoints/exports? If that is even practical
|
||||||
|
// only check for entrypoint if we don't already have one
|
||||||
|
if !data.HasEntrypoint {
|
||||||
|
data.HasEntrypoint = machoHasEntrypoint(f)
|
||||||
|
}
|
||||||
|
// only check for exports if we don't already have them
|
||||||
|
if !data.HasExports {
|
||||||
|
data.HasExports = machoHasExports(f)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data.ImportedLibraries = libs
|
// de-duplicate libraries
|
||||||
data.HasEntrypoint = machoHasEntrypoint(f)
|
data.ImportedLibraries = internal.NewSet(libs...).ToSlice()
|
||||||
data.HasExports = machoHasExports(f)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/syft/file"
|
||||||
"github.com/anchore/syft/syft/internal/unionreader"
|
"github.com/anchore/syft/syft/internal/unionreader"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -83,3 +84,39 @@ func Test_machoHasExports(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_machoUniversal(t *testing.T) {
|
||||||
|
readerForFixture := func(t *testing.T, fixture string) unionreader.UnionReader {
|
||||||
|
t.Helper()
|
||||||
|
f, err := os.Open(filepath.Join("test-fixtures/shared-info", fixture))
|
||||||
|
require.NoError(t, err)
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fixture string
|
||||||
|
want file.Executable
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "universal lib",
|
||||||
|
fixture: "bin/libhello_universal.dylib",
|
||||||
|
want: file.Executable{HasExports: true, HasEntrypoint: false},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "universal application",
|
||||||
|
fixture: "bin/hello_mac_universal",
|
||||||
|
want: file.Executable{HasExports: false, HasEntrypoint: true},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
var data file.Executable
|
||||||
|
err := findMachoFeatures(&data, readerForFixture(t, tt.fixture))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, tt.want.HasEntrypoint, data.HasEntrypoint)
|
||||||
|
assert.Equal(t, tt.want.HasExports, data.HasExports)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
BIN=../../bin
|
BIN=../../bin
|
||||||
|
|
||||||
all: $(BIN)/hello_linux $(BIN)/hello.exe $(BIN)/hello_mac
|
all: $(BIN)/hello_linux $(BIN)/hello.exe $(BIN)/hello_mac $(BIN)/hello_mac_universal
|
||||||
|
|
||||||
linux: $(BIN)/libhello.so
|
linux: $(BIN)/libhello.so
|
||||||
|
|
||||||
windows: $(BIN)/libhello.dll
|
windows: $(BIN)/libhello.dll
|
||||||
|
|
||||||
mac: $(BIN)/libhello.dylib
|
mac: $(BIN)/libhello.dylib $(BIN)/hello_mac_universal
|
||||||
|
|
||||||
$(BIN)/hello_linux:
|
$(BIN)/hello_linux:
|
||||||
gcc hello.c -o $(BIN)/hello_linux
|
gcc hello.c -o $(BIN)/hello_linux
|
||||||
@ -19,5 +19,8 @@ $(BIN)/hello.exe:
|
|||||||
$(BIN)/hello_mac:
|
$(BIN)/hello_mac:
|
||||||
o64-clang hello.c -o $(BIN)/hello_mac
|
o64-clang hello.c -o $(BIN)/hello_mac
|
||||||
|
|
||||||
|
$(BIN)/hello_mac_universal:
|
||||||
|
o64-clang -arch arm64 -arch x86_64 hello.c -o $(BIN)/hello_mac_universal
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(BIN)/hello_linux $(BIN)/hello.exe $(BIN)/hello_mac
|
rm -f $(BIN)/hello_linux $(BIN)/hello.exe $(BIN)/hello_mac $(BIN)/hello_mac_universal
|
||||||
|
|||||||
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
BIN=../../bin
|
BIN=../../bin
|
||||||
|
|
||||||
all: $(BIN)/libhello.so $(BIN)/libhello.dll $(BIN)/libhello.dylib
|
all: $(BIN)/libhello.so $(BIN)/libhello.dll $(BIN)/libhello.dylib $(BIN)/libhello_universal.dylib
|
||||||
|
|
||||||
linux: $(BIN)/libhello.so
|
linux: $(BIN)/libhello.so
|
||||||
|
|
||||||
windows: $(BIN)/libhello.dll
|
windows: $(BIN)/libhello.dll
|
||||||
|
|
||||||
mac: $(BIN)/libhello.dylib
|
mac: $(BIN)/libhello.dylib $(BIN)/libhello_universal.dylib
|
||||||
|
|
||||||
$(BIN)/libhello.so:
|
$(BIN)/libhello.so:
|
||||||
gcc -shared -fPIC -o $(BIN)/libhello.so hello.c
|
gcc -shared -fPIC -o $(BIN)/libhello.so hello.c
|
||||||
@ -19,5 +19,8 @@ $(BIN)/libhello.dll:
|
|||||||
$(BIN)/libhello.dylib:
|
$(BIN)/libhello.dylib:
|
||||||
o64-clang -dynamiclib -o $(BIN)/libhello.dylib hello.c
|
o64-clang -dynamiclib -o $(BIN)/libhello.dylib hello.c
|
||||||
|
|
||||||
|
$(BIN)/libhello_universal.dylib:
|
||||||
|
o64-clang -dynamiclib -arch arm64 -arch x86_64 hello.c -o $(BIN)/libhello_universal.dylib
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(BIN)/libhello.so $(BIN)/hello.dll $(BIN)/libhello.dylib $(BIN)/libhello.a
|
rm -f $(BIN)/libhello.so $(BIN)/hello.dll $(BIN)/libhello.dylib $(BIN)/libhello.a $(BIN)/libhello_universal.dylib
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user