Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add LinkMode() to binary implementation #2797

Merged
merged 1 commit into from
Dec 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions pkg/binary/binary.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,10 @@ type Options struct {
Path string
}

// DefaultOptions set of options
var DefaultOptions = &Options{}

// New creates a new binary instance.
func New(filePath string) (bin *Binary, err error) {
// Get the right implementation for the specified file
return NewWithOptions(filePath, DefaultOptions)
return NewWithOptions(filePath, &Options{Path: filePath})
}

// NewWithOptions creates a new binary with the specified options
Expand Down Expand Up @@ -121,6 +118,9 @@ type binaryImplementation interface {

// GetOS Returns a string with the GOOS of the binary
OS() string

// LinkMode returns the linking mode of the binary.
LinkMode() (LinkMode, error)
}

// SetImplementation sets the implementation to handle this sort of executable
Expand All @@ -138,6 +138,20 @@ func (b *Binary) OS() string {
return b.binaryImplementation.OS()
}

// LinkMode is the enum for all available linking modes.
type LinkMode string

const (
LinkModeUnknown LinkMode = "unknown"
LinkModeStatic LinkMode = "static"
LinkModeDynamic LinkMode = "dynamic"
)

// LinkMode returns the linking mode of the binary.
func (b *Binary) LinkMode() (LinkMode, error) {
return b.binaryImplementation.LinkMode()
}

// ContainsStrings searches the printable strings un a binary file
func (b *Binary) ContainsStrings(s ...string) (match bool, err error) {
// We cannot search for 0 items:
Expand Down
72 changes: 72 additions & 0 deletions pkg/binary/binaryfakes/fake_binary_implementation.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 27 additions & 1 deletion pkg/binary/elf.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package binary

import (
"bufio"
debugelf "debug/elf"
"encoding/binary"
"fmt"
"os"
Expand Down Expand Up @@ -55,7 +56,8 @@ func NewELFBinary(filePath string, opts *Options) (*ELFBinary, error) {
}

return &ELFBinary{
Header: header,
Header: header,
Options: opts,
}, nil
}

Expand Down Expand Up @@ -170,3 +172,27 @@ func (elf *ELFBinary) Arch() string {
func (elf *ELFBinary) OS() string {
return LINUX
}

// LinkMode returns the linking mode of the binary.
func (elf *ELFBinary) LinkMode() (LinkMode, error) {
file, err := os.Open(elf.Options.Path)
if err != nil {
return LinkModeUnknown, fmt.Errorf("open binary path: %w", err)
}

elfFile, err := debugelf.NewFile(file)
if err != nil {
return LinkModeUnknown, fmt.Errorf("unable to parse elf: %w", err)
}

for _, programHeader := range elfFile.Progs {
// If the elf program header refers to an interpreter, then the binary
// is not statically linked. See `file` implementation reference:
// https://github.com/file/file/blob/FILE5_36/src/readelf.c#L1581
if programHeader.Type == debugelf.PT_INTERP {
return LinkModeDynamic, nil
}
}

return LinkModeStatic, nil
}
5 changes: 5 additions & 0 deletions pkg/binary/mach-o.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,8 @@ func (macho *MachOBinary) Arch() string {
func (macho *MachOBinary) OS() string {
return DARWIN
}

// LinkMode returns the linking mode of the binary.
func (macho *MachOBinary) LinkMode() (LinkMode, error) {
return LinkModeUnknown, nil
}
5 changes: 5 additions & 0 deletions pkg/binary/windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,8 @@ func (pe *PEBinary) Arch() string {
func (pe *PEBinary) OS() string {
return WIN
}

// LinkMode returns the linking mode of the binary.
func (pe *PEBinary) LinkMode() (LinkMode, error) {
return LinkModeUnknown, nil
}
9 changes: 9 additions & 0 deletions pkg/release/binaries.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,15 @@ func (impl *defaultArtifactCheckerImpl) CheckVersionArch(
binData.Path, binData.Arch, binData.Platform, bin.Arch(), bin.OS(),
)
}

linkMode, err := bin.LinkMode()
if err != nil {
logrus.Warnf("Unable to get linkmode from binary %s: %v", binData.Path, err)
} else if linkMode == binary.LinkModeDynamic {
// TODO: fail hard if not all binaries are static (or unknown)
// Ref: https://github.com/kubernetes/release/issues/2786
logrus.Warnf("Binary is dynamically linked, which should be nothing we release: %s", binData.Path)
}
}
return nil
}