mirror of
https://github.com/thunderbrewhq/binana.git
synced 2025-12-12 09:52:28 +00:00
chore(binana): update files
This commit is contained in:
parent
1400de8b1f
commit
c30e1199d7
24 changed files with 35645 additions and 4286 deletions
139
go/symfile/loader.go
Normal file
139
go/symfile/loader.go
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
package symfile
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const min_columns = 3
|
||||
|
||||
type loader struct {
|
||||
input *bufio.Reader
|
||||
table Table
|
||||
line_number int
|
||||
}
|
||||
|
||||
func (l *loader) read_line() (line string, err error) {
|
||||
l.line_number++
|
||||
line, err = l.input.ReadString('\n')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
line = strings.TrimRight(line, "\r\n")
|
||||
return
|
||||
}
|
||||
|
||||
func (l *loader) parse_line(line string) (err error) {
|
||||
// trim extraneous whitespace
|
||||
line = strings.Trim(line, " \t")
|
||||
|
||||
// split into columns
|
||||
columns := strings.Split(line, " ")
|
||||
|
||||
// validate
|
||||
if len(columns) < min_columns {
|
||||
// this line is discarded but not in error
|
||||
return
|
||||
}
|
||||
var (
|
||||
start_address uint64
|
||||
comment_text string
|
||||
)
|
||||
|
||||
// get name of symbol
|
||||
name_column := columns[0]
|
||||
if name_column == "" {
|
||||
return fmt.Errorf("symfile: (*loader).parse_line: line %d: entry has invalid name '%s", l.line_number, name_column)
|
||||
}
|
||||
|
||||
start_address, err = strconv.ParseUint(columns[1], 16, 64)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
kind_column := columns[2]
|
||||
if len(kind_column) != 1 {
|
||||
return fmt.Errorf("symfile: (*loader).parse_line: line %d: entry has invalid kind", l.line_number)
|
||||
}
|
||||
|
||||
kind := EntryKind(kind_column[0])
|
||||
|
||||
if !slices.Contains(valid_kinds, kind) {
|
||||
return fmt.Errorf("symfile: (*loader).parse_line: line %d: entry has invalid kind", l.line_number)
|
||||
}
|
||||
|
||||
// find index of comment column
|
||||
index_of_comment := slices.Index(columns, ";")
|
||||
|
||||
var num_semantic_columns int
|
||||
|
||||
if index_of_comment != -1 {
|
||||
num_semantic_columns = index_of_comment
|
||||
comment_text_columns := columns[index_of_comment+1:]
|
||||
comment_text = strings.Join(comment_text_columns, " ")
|
||||
} else {
|
||||
num_semantic_columns = len(columns)
|
||||
}
|
||||
|
||||
// Start to build entry
|
||||
var entry Entry
|
||||
entry.Name = name_column
|
||||
entry.StartAddress = start_address
|
||||
entry.Kind = kind
|
||||
entry.Comment = comment_text
|
||||
|
||||
// build attributes
|
||||
if num_semantic_columns > 3 {
|
||||
for _, column := range columns[3:] {
|
||||
key, value, found := strings.Cut(column, "=")
|
||||
if found {
|
||||
switch key {
|
||||
case "end":
|
||||
entry.EndAddress, err = strconv.ParseUint(value, 16, 64)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("symfile: (*loader).parse_line: line %d: unknown attribute '%s'", l.line_number, key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = l.table.Insert(&entry)
|
||||
return
|
||||
}
|
||||
|
||||
func load(text io.Reader, table Table) (err error) {
|
||||
l := new(loader)
|
||||
|
||||
l.input = bufio.NewReader(text)
|
||||
l.table = table
|
||||
|
||||
var (
|
||||
line string
|
||||
)
|
||||
|
||||
for {
|
||||
line, err = l.read_line()
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
err = nil
|
||||
break
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err = l.parse_line(line); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
29
go/symfile/memory_table.go
Normal file
29
go/symfile/memory_table.go
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package symfile
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// Most tables are reasonably-sized and can be kept in memory
|
||||
type InMemoryTable struct {
|
||||
Entries []Entry
|
||||
}
|
||||
|
||||
func (t *InMemoryTable) Insert(entry *Entry) (err error) {
|
||||
i := sort.Search(len(t.Entries), func(i int) bool {
|
||||
return t.Entries[i].StartAddress >= entry.StartAddress
|
||||
})
|
||||
|
||||
if i < len(t.Entries) {
|
||||
t.Entries = slices.Insert(t.Entries, i, *entry)
|
||||
} else {
|
||||
t.Entries = append(t.Entries, *entry)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (t *InMemoryTable) Len() int {
|
||||
return len(t.Entries)
|
||||
}
|
||||
44
go/symfile/symfile.go
Normal file
44
go/symfile/symfile.go
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
package symfile
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// What kind of Entry is this?
|
||||
type EntryKind uint8
|
||||
|
||||
const (
|
||||
// Something that can be executed
|
||||
Function EntryKind = 'f'
|
||||
// Something that is read or written to
|
||||
DataLabel EntryKind = 'l'
|
||||
)
|
||||
|
||||
var (
|
||||
valid_kinds = []EntryKind{Function, DataLabel}
|
||||
)
|
||||
|
||||
// An entry in the table
|
||||
type Entry struct {
|
||||
// Undecorated, raw name
|
||||
Name string
|
||||
// Offset to the start of the function or data
|
||||
StartAddress uint64
|
||||
// What kind of Entry is this?
|
||||
Kind EntryKind
|
||||
// Any table entry can have a comment after a ';' column
|
||||
Comment string
|
||||
// Attributes
|
||||
// end=AABBCCEEDD
|
||||
EndAddress uint64
|
||||
}
|
||||
|
||||
type Table interface {
|
||||
Insert(entry *Entry) (err error)
|
||||
// Find() (iter func() (entry *Entry, err error))
|
||||
}
|
||||
|
||||
func Load(table Table, text io.Reader) (err error) {
|
||||
err = load(text, table)
|
||||
return
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue