github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/boot/purgatory/genpurg.go (about)

     1  // Copyright 2022 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build ignore
     6  
     7  package main
     8  
     9  import (
    10  	"bytes"
    11  	"encoding/hex"
    12  	"fmt"
    13  	"io"
    14  	"io/ioutil"
    15  	"log"
    16  	"os"
    17  	"os/exec"
    18  	"path/filepath"
    19  )
    20  
    21  func main() {
    22  	f, err := os.Create("asm.go")
    23  	if err != nil {
    24  		log.Fatal(err)
    25  	}
    26  	defer func() {
    27  		if err := f.Close(); err != nil {
    28  			log.Fatal("Closing %v: %v", f.Name(), err)
    29  		}
    30  	}()
    31  
    32  	if _, err := fmt.Fprintf(f, "// Copyright 2022 the u-root Authors. All rights reserved\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n"); err != nil {
    33  		log.Fatal(err)
    34  	}
    35  	if _, err := fmt.Fprintf(f, "package purgatory\nvar Purgatories = map[string]*Purgatory {\n"); err != nil {
    36  		log.Fatal(err)
    37  	}
    38  	d, err := ioutil.TempDir("", "kexecgen")
    39  	if err != nil {
    40  		log.Fatalf("%v", err)
    41  	}
    42  	defer os.RemoveAll(d)
    43  
    44  	for _, asm := range asms {
    45  		// assemble, then create the hexdump of the elf.
    46  		src := filepath.Join(d, asm.name) + ".S"
    47  		dst := filepath.Join(d, asm.name) + ".o"
    48  		out := filepath.Join(d, asm.name) + ".out"
    49  		if err := ioutil.WriteFile(src, []byte(asm.code), 0666); err != nil {
    50  			log.Fatal(err)
    51  		}
    52  
    53  		if out, err := exec.Command(asm.cc[0], append(asm.cc[1:], "-nostdinc", "-nostdlib", "-o", dst, src)...).CombinedOutput(); err != nil {
    54  			log.Printf("%s, %s: %v, %v", src, asm.code, string(out), err)
    55  			continue
    56  		}
    57  		if out, err := exec.Command(asm.ld[0], append(asm.ld[1:], "-nostdlib", "-o", out, dst)...).CombinedOutput(); err != nil {
    58  			log.Printf("%s, %s: %v, %v", dst, asm.code, string(out), err)
    59  			continue
    60  		}
    61  		code, err := ioutil.ReadFile(out)
    62  		if err != nil {
    63  			log.Fatal(err)
    64  		}
    65  		if len(code) == 0 {
    66  			log.Fatalf("%s: no output: dir %v", asm.name, d)
    67  		}
    68  		codehex := "\t[]byte{\n"
    69  		var i int
    70  		for i < len(code) {
    71  			codehex += "\t"
    72  			for j := 0; j < 16 && i < len(code); j++ {
    73  				codehex = codehex + fmt.Sprintf("%#02x, ", code[i])
    74  				i++
    75  			}
    76  			codehex += "\n"
    77  		}
    78  		codehex += "\n},\t\n"
    79  
    80  		var buf bytes.Buffer
    81  		if _, err := io.Copy(hex.Dumper(&buf), bytes.NewBuffer(code)); err != nil {
    82  			log.Fatal(err)
    83  		}
    84  		b := buf.Bytes()
    85  		for i := range b {
    86  			if b[i] == '`' {
    87  				b[i] = '.'
    88  			}
    89  		}
    90  		if _, err := fmt.Fprintf(f, "\t\"%s\": &Purgatory{\n\tName: \"%s\",\n\tHexdump: \n`%s\n`,\n\tCode: %s\n},\n", asm.name, asm.name, string(b), codehex); err != nil {
    91  			log.Fatal(err)
    92  		}
    93  	}
    94  	if _, err := fmt.Fprintf(f, "}\n"); err != nil {
    95  		log.Printf("Writing final brace: %v", err)
    96  	}
    97  }