chore(binana): update files

This commit is contained in:
phaneron 2024-07-13 17:42:21 -04:00
parent 1400de8b1f
commit c30e1199d7
24 changed files with 35645 additions and 4286 deletions

139
go/symfile/loader.go Normal file
View 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
}

View 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
View 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
}