-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
adding most of work to generate assembly and run tests - need to fix …
…a bug in gosmeagle to load corpus Signed-off-by: vsoch <vsoch@users.noreply.github.com>
- Loading branch information
Showing
31 changed files
with
921 additions
and
192 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
smeagleasm | ||
test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
FROM golang:bullseye as gobase | ||
# docker build -t ghcr.io/buildsi/smeagleasm . | ||
FROM ghcr.io/buildsi/smeagle | ||
COPY --from=gobase /usr/local/go/ /usr/local/go/ | ||
WORKDIR /src/ | ||
COPY . /src/ | ||
ENV PATH /usr/local/go/bin:/code/build/standalone:${PATH} | ||
RUN make | ||
ENTRYPOINT ["/bin/bash"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
all: | ||
gofmt -s -w . | ||
go build -o smeagleasm | ||
|
||
build: | ||
go build -o smeagleasm | ||
|
||
run: | ||
go run main.go |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package asm | ||
|
||
import ( | ||
"fmt" | ||
"math/rand" | ||
"strings" | ||
|
||
"github.com/vsoch/gosmeagle/corpus" | ||
) | ||
|
||
// Generate assembly from a smeagle output json | ||
func Generate(jsonFile string) string { | ||
|
||
// This is output generated from CPP smeagle | ||
c := corpus.Load(jsonFile) | ||
return generateAssembly(&c) | ||
} | ||
|
||
// generateAssembly for a corpus, assumed to be a main function for this simple program! | ||
func generateAssembly(c *corpus.LoadedCorpus) string { | ||
|
||
output := "" | ||
|
||
// This seems to always be printed at the start of main | ||
output += "endbr64\n" | ||
for _, loc := range c.Functions { | ||
|
||
// Allocate space on the stack all at once for local variables | ||
spaceBytes := int64(0) | ||
for _, param := range loc.Parameters { | ||
spaceBytes += param.GetSize() | ||
} | ||
output += fmt.Sprintf("subq $%d, %%rsp # Allocate %d bytes of space on the stack for local variables\n", spaceBytes, spaceBytes) | ||
for _, param := range loc.Parameters { | ||
if param.GetClass() == "Integer" { | ||
constant := rand.Intn(100) | ||
// Move constant into rbp+ frameoffset | ||
// mov $0x55 8(%rbp) - 8 changes relative to constant in smeagle fact | ||
// going to be 8 bytes off | ||
if strings.HasPrefix(param.GetLocation(), "framebase") { | ||
output += fmt.Sprintf("pushq $0x%d\n", constant) | ||
} else { | ||
output += fmt.Sprintf("mov $0x%d,%s\n", constant, param.GetLocation()) | ||
} | ||
} | ||
} | ||
output += fmt.Sprintf("callq %s\n", loc.Name) | ||
} | ||
return output | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package asm | ||
|
||
import ( | ||
"bytes" | ||
"github.com/buildsi/smeagleasm/utils" | ||
"html/template" | ||
"log" | ||
"os" | ||
) | ||
|
||
// WriteTemplate to a filepath | ||
func WriteTemplate(path string, t *template.Template, content *TemplateContent) { | ||
|
||
var buf bytes.Buffer | ||
if err := t.Execute(&buf, content); err != nil { | ||
log.Fatalf("Cannot write template to buffer: %x", err) | ||
} | ||
utils.WriteFile(path, buf.String()) | ||
} | ||
|
||
// WriteFile and some content to the filesystem | ||
func WriteFile(path string, content string) error { | ||
|
||
filey, err := os.Create(path) | ||
if err != nil { | ||
return err | ||
} | ||
defer filey.Close() | ||
|
||
_, err = filey.WriteString(content) | ||
if err != nil { | ||
return err | ||
} | ||
err = filey.Sync() | ||
return nil | ||
} | ||
|
||
type TemplateContent struct { | ||
Call string | ||
} | ||
|
||
// Template with empty "main" function to generate | ||
func getTemplate() string { | ||
return `.file "test.c" | ||
.text | ||
.globl main | ||
.type main, @function | ||
main: | ||
.LFB0: | ||
endbr64 | ||
pushq %rbp | ||
movq %rsp, %rbp | ||
{{ .Call }} | ||
addq $16, %rsp | ||
movl $0, %eax | ||
leave | ||
ret | ||
.LFE0: | ||
.size main, .-main | ||
.ident "Dinosaur Produced"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package asm | ||
|
||
import ( | ||
"fmt" | ||
"html/template" | ||
"io/ioutil" | ||
"log" | ||
// "os" | ||
"path/filepath" | ||
|
||
"github.com/buildsi/codegen/generate" | ||
"github.com/buildsi/smeagleasm/utils" | ||
) | ||
|
||
// Run tests with a codegen.yaml | ||
func RunTests(jsonYaml string, n int) { | ||
|
||
// Crete temporary outdir in /tmp | ||
tmpdir, err := ioutil.TempDir("", "smeagle-asm") | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
fmt.Printf("Writing tests to %s\n", tmpdir) | ||
//defer os.RemoveAll(tmpdir) | ||
|
||
// generate code in output directory | ||
generate.Generate(jsonYaml, tmpdir, "random") | ||
|
||
// If we don't have a Makefile, cannot build | ||
testdir := filepath.Join(tmpdir, "1") | ||
makefile := filepath.Join(testdir, "Makefile") | ||
if !utils.Exists(makefile) { | ||
log.Fatalf("Cannot build tests without Makefile, %s does not exist!\n", makefile) | ||
} | ||
|
||
// System commands to run makefile, changing to testdir | ||
_, err = utils.RunCommand([]string{"make"}, []string{}, testdir, "") | ||
if err != nil { | ||
log.Fatalf("Error compiling Makefile for test: %s\n", err) | ||
} | ||
|
||
// A binary must exist named binary | ||
binary := filepath.Join(testdir, "binary") | ||
libfoo := filepath.Join(testdir, "libfoo.so") | ||
if !utils.Exists(binary) || !utils.Exists(libfoo) { | ||
log.Fatalf("Expected output binary 'binary' or 'libfoo.so' does not exist!\n") | ||
} | ||
|
||
// generate smeagle output for the binary (Smeagle must be on path!) | ||
outfile := filepath.Join(testdir, "smeagle-output.json") | ||
_, err = utils.RunCommand([]string{"Smeagle", "-l", libfoo}, []string{}, testdir, outfile) | ||
if err != nil { | ||
log.Fatalf("Error running Smeagle!: %s!\n", err) | ||
} | ||
|
||
// Read in smeagle output and generate assembly | ||
assembly := Generate(outfile) | ||
content := TemplateContent{assembly} | ||
|
||
// Template a second binary, compile again | ||
t := template.Must(template.New("binary").Parse(getTemplate())) | ||
|
||
assemblyFile := filepath.Join(testdir, "binary.s") | ||
WriteTemplate(assemblyFile, t, &content) | ||
if !utils.Exists(assemblyFile) { | ||
log.Fatalf("Cannot write template to assembly file!\n") | ||
} | ||
|
||
// Compile again | ||
_, err = utils.RunCommand([]string{"g++", "binary.s", "-L.", "-ltest", "-o", "edits"}, []string{}, testdir, "") | ||
if err != nil { | ||
log.Fatalf("Error compiling second assembly file: %s\n", err) | ||
} | ||
|
||
// Run both and compare result - should run in container at this point | ||
resOriginal, err := utils.RunCommand([]string{"./binary"}, []string{}, testdir, "") | ||
if err != nil { | ||
log.Fatalf("Issue running original binary %x\n", err) | ||
} | ||
|
||
resEdited, err := utils.RunCommand([]string{"./edits"}, []string{}, testdir, "") | ||
if err != nil { | ||
log.Fatalf("Issue running assembly-generated binary %x\n", err) | ||
} | ||
|
||
// print result here / calculate metrics! | ||
fmt.Println(resOriginal, resEdited) | ||
|
||
// Can we generate smeagle assembly again? | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package cli | ||
|
||
import ( | ||
"github.com/DataDrake/cli-ng/v2/cmd" | ||
"github.com/buildsi/smeagleasm/version" | ||
) | ||
|
||
// GlobalFlags contains the flags for commands. | ||
type GlobalFlags struct{} | ||
|
||
// Root is the main command. | ||
var Root *cmd.Root | ||
|
||
// init create the root command and creates subcommands | ||
func init() { | ||
Root = &cmd.Root{ | ||
Name: "smeagleasm", | ||
Short: "Testing utility for Smeagle to generate assembly via Go", | ||
Version: version.Version, | ||
Copyright: "© 2021 Vanessa Sochat <@vsoch>", | ||
License: "Licensed under a combined LICENSE", | ||
} | ||
cmd.Register(&cmd.Help) | ||
cmd.Register(&cmd.Version) | ||
cmd.Register(&cmd.GenManPages) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package cli | ||
|
||
import ( | ||
"fmt" | ||
"github.com/DataDrake/cli-ng/v2/cmd" | ||
"github.com/buildsi/smeagleasm/asm" | ||
) | ||
|
||
// Args and flags for generate | ||
type GenArgs struct { | ||
JsonFile []string `desc:"smeagle json to generate assembly for"` | ||
} | ||
|
||
type GenFlags struct{} | ||
|
||
// Parser looks at symbols and ABI in Go | ||
var Generator = cmd.Sub{ | ||
Name: "gen", | ||
Alias: "g", | ||
Short: "generate assembly from smeagle output", | ||
Flags: &GenFlags{}, | ||
Args: &GenArgs{}, | ||
Run: RunGen, | ||
} | ||
|
||
func init() { | ||
cmd.Register(&Generator) | ||
} | ||
|
||
// RunParser reads a file and creates a corpus | ||
func RunGen(r *cmd.Root, c *cmd.Sub) { | ||
args := c.Args.(*GenArgs) | ||
assembly := asm.Generate(args.JsonFile[0]) | ||
fmt.Println(assembly) | ||
} |
Oops, something went wrong.