mirror of
https://github.com/containers/podman.git
synced 2025-12-05 21:32:22 +08:00
Add podman farm build command that sends out builds to nodes defined in the farm, builds the images on the farm nodes, and pulls them back to the local machine to create a manifest list. Signed-off-by: Urvashi Mohnani <umohnani@redhat.com>
222 lines
6.1 KiB
Go
222 lines
6.1 KiB
Go
//go:build !remote
|
|
// +build !remote
|
|
|
|
package emulation
|
|
|
|
import (
|
|
"debug/elf"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"sync"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
type elfPlatform struct {
|
|
platform string
|
|
osabi []elf.OSABI
|
|
class elf.Class
|
|
data elf.Data
|
|
alsoNone bool // also try with data=none,version=0
|
|
machine elf.Machine
|
|
flags []uint32
|
|
}
|
|
|
|
var (
|
|
// knownELFPlatformHeaders is a mapping from target platform names and
|
|
// plausible headers for the binaries built for those platforms. Call
|
|
// getKnownELFPlatformHeaders() instead of reading this map directly.
|
|
knownELFPlatformHeaders = make(map[string][][]byte)
|
|
knownELFPlatformHeadersOnce sync.Once
|
|
// knownELFPlatforms is a table of target platforms that we built a
|
|
// trivial program for, and the other fields are filled in based on
|
|
// what we got when we ran eu-readelf -h against the results.
|
|
knownELFPlatforms = []elfPlatform{
|
|
{
|
|
platform: "linux/386",
|
|
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
|
|
class: elf.ELFCLASS32,
|
|
data: elf.ELFDATA2LSB,
|
|
alsoNone: true,
|
|
machine: elf.EM_386,
|
|
},
|
|
{
|
|
platform: "linux/amd64",
|
|
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
|
|
class: elf.ELFCLASS64,
|
|
data: elf.ELFDATA2LSB,
|
|
alsoNone: true,
|
|
machine: elf.EM_X86_64,
|
|
},
|
|
{
|
|
platform: "linux/arm",
|
|
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
|
|
class: elf.ELFCLASS32,
|
|
data: elf.ELFDATA2LSB,
|
|
machine: elf.EM_ARM,
|
|
},
|
|
{
|
|
platform: "linux/arm64",
|
|
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
|
|
class: elf.ELFCLASS64,
|
|
data: elf.ELFDATA2LSB,
|
|
machine: elf.EM_AARCH64,
|
|
},
|
|
{
|
|
platform: "linux/arm64be",
|
|
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
|
|
class: elf.ELFCLASS64,
|
|
data: elf.ELFDATA2MSB,
|
|
machine: elf.EM_AARCH64,
|
|
},
|
|
{
|
|
platform: "linux/loong64",
|
|
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
|
|
class: elf.ELFCLASS64,
|
|
data: elf.ELFDATA2LSB,
|
|
machine: elf.EM_LOONGARCH,
|
|
},
|
|
{
|
|
platform: "linux/mips",
|
|
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
|
|
class: elf.ELFCLASS32,
|
|
data: elf.ELFDATA2MSB,
|
|
machine: elf.EM_MIPS,
|
|
flags: []uint32{0, 2}, // elf.EF_MIPS_PIC set, or not
|
|
},
|
|
{
|
|
platform: "linux/mipsle",
|
|
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
|
|
class: elf.ELFCLASS32,
|
|
data: elf.ELFDATA2LSB,
|
|
machine: elf.EM_MIPS_RS3_LE,
|
|
flags: []uint32{0, 2}, // elf.EF_MIPS_PIC set, or not
|
|
},
|
|
{
|
|
platform: "linux/mips64",
|
|
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
|
|
class: elf.ELFCLASS64,
|
|
data: elf.ELFDATA2MSB,
|
|
machine: elf.EM_MIPS,
|
|
flags: []uint32{0, 2}, // elf.EF_MIPS_PIC set, or not
|
|
},
|
|
{
|
|
platform: "linux/mips64le",
|
|
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
|
|
class: elf.ELFCLASS64,
|
|
data: elf.ELFDATA2LSB,
|
|
machine: elf.EM_MIPS_RS3_LE,
|
|
flags: []uint32{0, 2}, // elf.EF_MIPS_PIC set, or not
|
|
},
|
|
{
|
|
platform: "linux/ppc",
|
|
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
|
|
class: elf.ELFCLASS32,
|
|
data: elf.ELFDATA2MSB,
|
|
machine: elf.EM_PPC,
|
|
},
|
|
{
|
|
platform: "linux/ppc64",
|
|
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
|
|
class: elf.ELFCLASS64,
|
|
data: elf.ELFDATA2MSB,
|
|
machine: elf.EM_PPC64,
|
|
},
|
|
{
|
|
platform: "linux/ppc64le",
|
|
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
|
|
class: elf.ELFCLASS64,
|
|
data: elf.ELFDATA2LSB,
|
|
machine: elf.EM_PPC64,
|
|
},
|
|
{
|
|
platform: "linux/riscv32",
|
|
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
|
|
class: elf.ELFCLASS32,
|
|
data: elf.ELFDATA2LSB,
|
|
machine: elf.EM_RISCV,
|
|
},
|
|
{
|
|
platform: "linux/riscv64",
|
|
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
|
|
class: elf.ELFCLASS64,
|
|
data: elf.ELFDATA2LSB,
|
|
machine: elf.EM_RISCV,
|
|
},
|
|
{
|
|
platform: "linux/s390x",
|
|
osabi: []elf.OSABI{elf.ELFOSABI_NONE, elf.ELFOSABI_LINUX},
|
|
class: elf.ELFCLASS64,
|
|
data: elf.ELFDATA2MSB,
|
|
machine: elf.EM_S390,
|
|
},
|
|
}
|
|
)
|
|
|
|
// header generates an approximation of what the initial N bytes of a binary
|
|
// built for a given target looks like
|
|
func (e *elfPlatform) header() ([][]byte, error) {
|
|
var headers [][]byte
|
|
osabi := e.osabi
|
|
if len(osabi) == 0 {
|
|
osabi = []elf.OSABI{elf.ELFOSABI_NONE}
|
|
}
|
|
for i := range osabi {
|
|
flags := e.flags
|
|
if len(flags) == 0 {
|
|
flags = []uint32{0}
|
|
}
|
|
for f := range flags {
|
|
var endian binary.ByteOrder
|
|
var entrySize, phoffSize, shoffSize int
|
|
header := make([]byte, 40)
|
|
copy(header, elf.ELFMAG)
|
|
switch e.class {
|
|
case elf.ELFCLASS32:
|
|
entrySize, phoffSize, shoffSize = 2, 2, 2
|
|
case elf.ELFCLASS64:
|
|
entrySize, phoffSize, shoffSize = 4, 4, 4
|
|
}
|
|
switch e.data {
|
|
case elf.ELFDATA2LSB:
|
|
endian = binary.LittleEndian
|
|
case elf.ELFDATA2MSB:
|
|
endian = binary.BigEndian
|
|
default:
|
|
return nil, fmt.Errorf("internal error in entry for %q", e.platform)
|
|
}
|
|
header[elf.EI_OSABI] = byte(osabi[i])
|
|
header[elf.EI_CLASS] = byte(e.class)
|
|
header[elf.EI_DATA] = byte(e.data)
|
|
header[elf.EI_VERSION] = byte(elf.EV_CURRENT)
|
|
header[elf.EI_ABIVERSION] = 0
|
|
endian.PutUint16(header[16:], uint16(elf.ET_EXEC))
|
|
endian.PutUint16(header[18:], uint16(e.machine))
|
|
endian.PutUint32(header[20:], uint32(elf.EV_CURRENT))
|
|
endian.PutUint32(header[24+entrySize+phoffSize+shoffSize:], flags[f])
|
|
headers = append(headers, append([]byte{}, header...))
|
|
if e.alsoNone {
|
|
header[elf.EI_DATA] = byte(elf.ELFDATANONE)
|
|
header[elf.EI_VERSION] = byte(elf.EV_NONE)
|
|
endian.PutUint32(header[20:], uint32(elf.EV_NONE))
|
|
headers = append(headers, append([]byte{}, header...))
|
|
}
|
|
}
|
|
}
|
|
return headers, nil
|
|
}
|
|
|
|
func getKnownELFPlatformHeaders() map[string][][]byte {
|
|
knownELFPlatformHeadersOnce.Do(func() {
|
|
for _, p := range knownELFPlatforms {
|
|
headerList, err := p.header()
|
|
if err != nil {
|
|
logrus.Errorf("generating headers for %q: %v\n", p.platform, err)
|
|
continue
|
|
}
|
|
knownELFPlatformHeaders[p.platform] = headerList
|
|
}
|
|
})
|
|
return knownELFPlatformHeaders
|
|
}
|