feat(binana): change tool to deposit generated files into an 'artifacts' folder that isn't retained by repository history

This commit is contained in:
phaneron 2026-02-28 02:34:20 -05:00
parent 68f52b8efd
commit 47b08df145
44 changed files with 904 additions and 622 deletions

11
go/app/app.go Normal file
View file

@ -0,0 +1,11 @@
package app
import (
"fmt"
"os"
)
func Fatal(args ...any) {
fmt.Fprintln(os.Stderr, args...)
os.Exit(1)
}

17
go/app/cmd/execute.go Normal file
View file

@ -0,0 +1,17 @@
package cmd
import (
_ "github.com/thunderbrewhq/binana/go/app/cmd/lint"
_ "github.com/thunderbrewhq/binana/go/app/cmd/make"
_ "github.com/thunderbrewhq/binana/go/app/cmd/tidy"
"github.com/thunderbrewhq/binana/go/app"
"github.com/thunderbrewhq/binana/go/app/cmd/root"
)
func Execute() {
err := root.RootCmd.Execute()
if err != nil {
app.Fatal(err)
}
}

43
go/app/cmd/lint/lint.go Normal file
View file

@ -0,0 +1,43 @@
package cmd
import (
"github.com/spf13/cobra"
"github.com/thunderbrewhq/binana/go/app"
"github.com/thunderbrewhq/binana/go/app/profile"
)
var lint_cmd = cobra.Command{
Use: "lint profile",
Short: "show warnings and coverage for a profile",
Run: lint_func,
}
func init() {
f := lint_cmd.Flags()
f.Bool("bounds", false, "check for bad function boundaries")
f.Bool("constructors", false, "check for outdated class constructor names")
}
func lint_func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
cmd.Help()
return
}
f := cmd.Flags()
var params profile.LintParams
params.Profile = args[0]
var err error
params.Constructors, err = f.GetBool("constructors")
if err != nil {
app.Fatal(err)
}
params.Bounds, err = f.GetBool("bounds")
if err != nil {
app.Fatal(err)
}
profile.Lint(&params)
}

32
go/app/cmd/make/make.go Normal file
View file

@ -0,0 +1,32 @@
package make
import (
"github.com/spf13/cobra"
"github.com/thunderbrewhq/binana/go/app/cmd/root"
"github.com/thunderbrewhq/binana/go/app/profile"
)
func mk_func(cmd *cobra.Command, args []string) {
compress, err := cmd.Flags().GetBool("compress")
if err != nil {
panic(err)
}
var params profile.MakeParams
params.Profile = args[0]
params.CompressX64dbgDatabase = compress
profile.Make(&params)
}
var mk_cmd = cobra.Command{
Use: "mk profile",
Args: cobra.MinimumNArgs(1),
Short: "Convert source files into various tool formats",
Run: mk_func,
}
func init() {
f := mk_cmd.Flags()
f.BoolP("compress", "c", true, "enable/disable compression of the x64dbg database file")
root.RootCmd.AddCommand(&mk_cmd)
}

8
go/app/cmd/root/root.go Normal file
View file

@ -0,0 +1,8 @@
package root
import "github.com/spf13/cobra"
var RootCmd = cobra.Command{
Use: "bna",
Short: "Binana helper tool",
}

25
go/app/cmd/tidy/tidy.go Normal file
View file

@ -0,0 +1,25 @@
package tidy
import (
"github.com/spf13/cobra"
"github.com/thunderbrewhq/binana/go/app/cmd/root"
"github.com/thunderbrewhq/binana/go/app/profile"
)
var tidy_cmd = cobra.Command{
Use: "tidy profile",
Short: "sort all symbol files in a profile",
Args: cobra.MinimumNArgs(1),
Run: tidy_func,
}
func init() {
//f := tidy_cmd.Flags()
root.RootCmd.AddCommand(&tidy_cmd)
}
func tidy_func(cmd *cobra.Command, args []string) {
var params profile.TidyParams
params.Profile = args[0]
profile.Tidy(&params)
}

65
go/app/profile/lint.go Normal file
View file

@ -0,0 +1,65 @@
package profile
import (
"fmt"
"strings"
"github.com/fatih/color"
"github.com/thunderbrewhq/binana/go/symbols"
)
type linter struct {
warnings uint64
named_functions_count uint64
}
func (linter *linter) warn(s *symbols.TableEntry, f string, args ...any) {
linter.warnings++
color.Set(color.FgRed)
fmt.Printf(" warning: ")
color.Unset()
fmt.Printf(" in %s:%d: %s", s.Filename, s.Linenumber, s.Symbol.Name)
fmt.Printf(f, args...)
}
type LintParams struct {
Profile string
Constructors bool
Bounds bool
}
func Lint(params *LintParams) {
Open(params.Profile)
defer Close()
var linter linter
for entry := range Profile.Symbols.Entries() {
sn := entry.Symbol.Name
if entry.Symbol.Kind == symbols.Function {
linter.named_functions_count++
if params.Constructors {
//
b, a, found := strings.Cut(sn, "__")
if found {
if b == a {
linter.warn(entry, "this style of naming a constructor function is preferred: ClassName__constructor\n")
}
}
}
if params.Bounds {
if entry.Symbol.EndAddress == 0 {
linter.warn(entry, "does not have an end address\n")
}
}
}
}
if Profile.Info.FunctionCount != 0 {
ratio := float64(linter.named_functions_count) / float64(Profile.Info.FunctionCount)
fmt.Printf("%d out of %d functions named (%f%%)\n", linter.named_functions_count, Profile.Info.FunctionCount, ratio*100.0)
fmt.Printf("%d warnings generated\n", linter.warnings)
}
}

20
go/app/profile/make.go Normal file
View file

@ -0,0 +1,20 @@
package profile
import (
"github.com/thunderbrewhq/binana/go/app"
"github.com/thunderbrewhq/binana/go/profile"
)
type MakeParams struct {
Profile string
profile.CompileArtifactsParams
}
func Make(params *MakeParams) {
Open(params.Profile)
defer Close()
if err := Profile.CompileArtifacts(&params.CompileArtifactsParams); err != nil {
app.Fatal(err)
}
}

26
go/app/profile/profile.go Normal file
View file

@ -0,0 +1,26 @@
package profile
import (
"path/filepath"
"github.com/thunderbrewhq/binana/go/app"
"github.com/thunderbrewhq/binana/go/profile"
)
var Profile profile.Profile
func Open(profile_name string) {
if profile_name == "" {
app.Fatal("no profile selected")
}
if err := Profile.Open(
filepath.Join("profile", profile_name),
filepath.Join("artifacts", profile_name),
); err != nil {
app.Fatal(err)
}
}
func Close() {
//Profile.Close()
}

61
go/app/profile/tidy.go Normal file
View file

@ -0,0 +1,61 @@
package profile
import (
"os"
"path/filepath"
"github.com/thunderbrewhq/binana/go/app"
"github.com/thunderbrewhq/binana/go/symbols"
)
type TidyParams struct {
Profile string
}
func tidy_symbol_file(name string, params *TidyParams) (err error) {
var symbol_table symbols.Table
symbol_table.Init()
if err = symbol_table.Load(name); err != nil {
return
}
var f *os.File
f, err = os.Create(name)
if err != nil {
return
}
if _, err = symbol_table.WriteTo(f); err != nil {
f.Close()
return
}
err = f.Close()
return
}
func tidy_symbol_directory(name string, params *TidyParams) (err error) {
var contents []os.DirEntry
contents, err = os.ReadDir(name)
if err != nil {
return
}
for _, content := range contents {
if content.IsDir() {
if err = tidy_symbol_directory(filepath.Join(name, content.Name()), params); err != nil {
return
}
} else {
if err = tidy_symbol_file(filepath.Join(name, content.Name()), params); err != nil {
return
}
}
}
return
}
func Tidy(params *TidyParams) {
// tidy symbols
profile_symbols := filepath.Join("profile", params.Profile, "symbol")
if err := tidy_symbol_directory(profile_symbols, params); err != nil {
app.Fatal(err)
}
}