feat(go): generate multiple batch files

This commit is contained in:
phaneron 2024-11-01 03:52:22 -04:00
parent 34d16625b7
commit 77b03892b1
2 changed files with 114 additions and 34 deletions

View file

@ -9,64 +9,144 @@ import (
"github.com/thunderbrewhq/binana/go/symfile" "github.com/thunderbrewhq/binana/go/symfile"
) )
func (profile *Profile) generate_symbols_idc() (err error) { type idac_import_batch struct {
tab int
fd *os.File
}
// Include/import
func (b *idac_import_batch) I(global bool, filename string) (err error) {
var ( var (
f *os.File hq_global = [2]rune{'<', '>'}
hq_local = [2]rune{'"', '"'}
) )
f, err = os.Create(filepath.Join(profile.Directory, "ida", "import_symbols.idc")) hq := hq_local
if global {
hq = hq_global
}
_, err = fmt.Fprintf(b.fd, "#include %c%s%c\n", hq[0], filename, hq[1])
return
}
func (b *idac_import_batch) T(tabs int) {
b.tab = tabs
}
// Print
func (b *idac_import_batch) P(f string, list ...any) (err error) {
for range b.tab {
if _, err = fmt.Fprint(b.fd, "\t"); err != nil {
return
}
}
_, err = fmt.Fprintf(b.fd, f, list...)
if err != nil {
return
}
_, err = fmt.Fprint(b.fd, "\n")
return
}
// Newline n times
func (b *idac_import_batch) N(n int) (err error) {
for range n {
if _, err = fmt.Fprint(b.fd, "\n"); err != nil {
return
}
}
return
}
func (b *idac_import_batch) Close() (err error) {
err = b.fd.Close()
return
}
func (profile *Profile) create_idac_import_batch(name string) (b *idac_import_batch, err error) {
b = new(idac_import_batch)
b.fd, err = os.Create(filepath.Join(profile.Directory, "ida", "batch", name+".idc"))
if err != nil { if err != nil {
return return
} }
fmt.Fprintf(f, "#include <idc.idc>\n") return
fmt.Fprintf(f, "\n") }
fmt.Fprintf(f, "#include \"import_data_types.idc\"\n")
fmt.Fprintf(f, "static main() {\n")
fmt.Fprintf(f, " // Make names\n")
func (profile *Profile) generate_symbols_idc() (err error) {
// symbols
var b *idac_import_batch
b, err = profile.create_idac_import_batch("import_symbols")
if err != nil {
return
}
b.I(true, "idc.idc")
b.N(1)
b.P("static import_symbols() {")
b.T(1)
b.P("// Set/create names")
for _, symbol := range profile.SymbolTable.Entries { for _, symbol := range profile.SymbolTable.Entries {
quoted_name := strconv.Quote(symbol.Name) quoted_name := strconv.Quote(symbol.Name)
address := fmt.Sprintf("0x%08X", symbol.StartAddress) address := fmt.Sprintf("0x%08X", symbol.StartAddress)
fmt.Fprintf(f, " set_name(%s, %s);\n", address, quoted_name) b.P("set_name(%s, %s);", address, quoted_name)
} }
b.T(0)
b.P("}")
fmt.Fprintf(f, " // Make functions\n") b.Close()
for _, function_symbol := range profile.SymbolTable.Entries { // data label types
if function_symbol.Kind == symfile.Function { b, err = profile.create_idac_import_batch("import_data_types")
address := fmt.Sprintf("0x%08X", function_symbol.StartAddress)
fmt.Fprintf(f, " set_func_start(%s, %s);\n", address, address)
if function_symbol.EndAddress != 0 {
end_address := fmt.Sprintf("0x%08X", function_symbol.EndAddress)
fmt.Fprintf(f, " set_func_end(%s, %s);\n", address, end_address)
}
}
}
fmt.Fprintf(f, " // Apply data types\n")
fmt.Fprintf(f, " import_data_types();\n")
fmt.Fprintf(f, "}\n")
f.Close()
f, err = os.Create(filepath.Join(profile.Directory, "ida", "import_data_types.idc"))
if err != nil { if err != nil {
return return
} }
fmt.Fprintf(f, "#include <idc.idc>\n") b.I(true, "idc.idc")
fmt.Fprintf(f, "\n") b.N(1)
fmt.Fprintf(f, "static import_data_types() {\n") b.P("static import_data_types() {")
b.T(1)
b.P("// Give types to data labels")
for _, symbol := range profile.SymbolTable.Entries { for _, symbol := range profile.SymbolTable.Entries {
if symbol.DataType != "" { if symbol.DataType != "" {
quoted_data_type := strconv.Quote(symbol.DataType) quoted_data_type := strconv.Quote(symbol.DataType)
address := fmt.Sprintf("0x%08X", symbol.StartAddress) address := fmt.Sprintf("0x%08X", symbol.StartAddress)
fmt.Fprintf(f, " apply_type(%s, %s);\n", address, quoted_data_type) b.P("apply_type(%s, %s);", address, quoted_data_type)
} }
} }
b.T(0)
b.P("}")
b.Close()
// functions
b, err = profile.create_idac_import_batch("import_functions")
if err != nil {
return
}
fmt.Fprintf(f, "}\n") b.I(true, "idc.idc")
b.N(1)
b.P("static import_functions() {")
b.T(1)
b.P("// Import function addresses and comments")
b.P(`msg("Importing function addresses and comments");`)
for _, function_symbol := range profile.SymbolTable.Entries {
if function_symbol.Kind == symfile.Function {
address := fmt.Sprintf("0x%08X", function_symbol.StartAddress)
b.P("set_func_start(%s, %s);", address, address)
if function_symbol.EndAddress != 0 {
end_address := fmt.Sprintf("0x%08X", function_symbol.EndAddress)
b.P("set_func_end(%s, %s);", address, end_address)
}
if function_symbol.Comment != "" {
b.P("set_func_cmt(%s, %s, 0);", address, strconv.Quote(function_symbol.Comment))
}
}
}
b.T(0)
b.P("}")
b.Close()
return return
} }

View file

@ -150,7 +150,7 @@ func (graph *type_dependency_graph) Load(types *Types) (err error) {
dependency_type := graph.get(dependency_name) dependency_type := graph.get(dependency_name)
if dependency_type == nil { if dependency_type == nil {
err = fmt.Errorf("unknown dependency name %s", dependency_name) err = fmt.Errorf("unknown dependency name '%s' from type '%s'", dependency_name, t.t.GetName())
return return
} }