[script] Improve CDL logic
- CDL data can now be output to a file. If --cdl-output isn't given, but --cdl is given, the input file is overwritten with the new data. If no CDL file is given no data is written. - Count arguments as "Code" - The SmartParse function no longer creates a new CDL. It will use and update what it was given. - The just-stats command does not write CDL data even though it generates it. Variable length arguments are not properly handled yet. Currently, just the OP code and first argument (length) are set at Code. The rest are ignored.
This commit is contained in:
parent
11cfad1e1a
commit
bfc7beb382
|
@ -21,6 +21,7 @@ type Arguments struct {
|
|||
StatsFile string `arg:"--stats" help:"file to write some statistics to"`
|
||||
LabelFile string `arg:"--labels" help:"file containing address/label pairs"`
|
||||
CDL string `arg:"--cdl" help:"CodeDataLog json file"`
|
||||
CDLOutput string `arg:"--cdl-output"`
|
||||
Smart bool `arg:"--smart"`
|
||||
|
||||
start int
|
||||
|
@ -103,10 +104,6 @@ func run(args *Arguments) error {
|
|||
return 0
|
||||
})
|
||||
|
||||
//for _, lbl := range scr.Labels {
|
||||
// fmt.Println(lbl)
|
||||
//}
|
||||
|
||||
for _, token := range scr.Tokens {
|
||||
fmt.Fprintln(outfile, token.String(scr.Labels))
|
||||
}
|
||||
|
@ -124,6 +121,22 @@ func run(args *Arguments) error {
|
|||
}
|
||||
}
|
||||
|
||||
if scr.CDL != nil {
|
||||
cdlout := args.CDL
|
||||
if args.CDLOutput != "" {
|
||||
cdlout = args.CDLOutput
|
||||
}
|
||||
|
||||
if cdlout == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
err = scr.CDL.WriteToFile(cdlout)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error writing CDL file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"encoding/json"
|
||||
"strconv"
|
||||
"fmt"
|
||||
"slices"
|
||||
)
|
||||
|
||||
type CodeDataLog struct {
|
||||
|
@ -28,8 +29,101 @@ var (
|
|||
cdlUnknown cdlBit = 0x00
|
||||
cdlCode cdlBit = 0x01
|
||||
cdlData cdlBit = 0x02
|
||||
//cdlOpCode cdlBit = 0x04
|
||||
)
|
||||
|
||||
func (cdl *CodeDataLog) WriteToFile(filename string) error {
|
||||
file, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, werr := cdl.WriteTo(file)
|
||||
err = file.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return werr
|
||||
}
|
||||
|
||||
func getRanges(list []int) []CdlRange {
|
||||
//fmt.Printf("getRanges(%v)\n", list)
|
||||
data := []CdlRange{}
|
||||
|
||||
start := -1
|
||||
//end := -1
|
||||
prev := -1
|
||||
for _, addr := range list {
|
||||
if start == -1 {
|
||||
start = addr
|
||||
}
|
||||
|
||||
if prev != -1 && prev != addr-1 {
|
||||
data = append(data, CdlRange{
|
||||
Start: fmt.Sprintf("0x%X", start),
|
||||
End: fmt.Sprintf("0x%X", prev),
|
||||
})
|
||||
|
||||
//fmt.Printf("start: 0x%X end: 0x%X\n", start, prev)
|
||||
|
||||
start = addr
|
||||
}
|
||||
|
||||
prev = addr
|
||||
}
|
||||
|
||||
if start != -1 && prev != -1 {
|
||||
data = append(data, CdlRange{
|
||||
Start: fmt.Sprintf("0x%X", start),
|
||||
End: fmt.Sprintf("0x%X", prev),
|
||||
})
|
||||
|
||||
//fmt.Println("start:", start, "end:", prev)
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
func (cdl *CodeDataLog) WriteTo(w io.Writer) (int64, error) {
|
||||
clean := &CodeDataLog{
|
||||
Code: []CdlRange{},
|
||||
Data: []CdlRange{},
|
||||
}
|
||||
|
||||
keys := []int{}
|
||||
for k, _ := range cdl.cache {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
|
||||
slices.Sort(keys)
|
||||
|
||||
code := []int{}
|
||||
data := []int{}
|
||||
|
||||
for _, k := range keys {
|
||||
b := cdl.cache[k]
|
||||
if b & cdlCode == cdlCode {
|
||||
code = append(code, k)
|
||||
}
|
||||
|
||||
if b & cdlData == cdlData {
|
||||
data = append(data, k)
|
||||
}
|
||||
}
|
||||
|
||||
clean.Code = getRanges(code)
|
||||
clean.Data = getRanges(data)
|
||||
|
||||
raw, err := json.MarshalIndent(clean, "", "\t")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
n, err := w.Write(raw)
|
||||
return int64(n), err
|
||||
}
|
||||
|
||||
func (cdl *CodeDataLog) setData(scriptOffset int) {
|
||||
if cdl.cache == nil {
|
||||
err := cdl.doCache()
|
||||
|
|
|
@ -45,8 +45,6 @@ func SmartParse(rawinput []byte, startAddr int, cdl *CodeDataLog) (*Script, erro
|
|||
}
|
||||
|
||||
p := &Parser{
|
||||
// Don't use CDL that was passed in
|
||||
cdl: &CodeDataLog{},
|
||||
|
||||
script: &Script{
|
||||
Tokens: []*Token{},
|
||||
|
@ -54,12 +52,18 @@ func SmartParse(rawinput []byte, startAddr int, cdl *CodeDataLog) (*Script, erro
|
|||
StackAddress: (int(rawinput[1])<<8) | int(rawinput[0]),
|
||||
StartAddress: startAddr,
|
||||
Labels: make(map[int]*Label), // map[location]name
|
||||
|
||||
CDL: cdl,
|
||||
},
|
||||
|
||||
rawinput: rawinput,
|
||||
startAddr: startAddr,
|
||||
}
|
||||
|
||||
if p.script.CDL == nil {
|
||||
p.script.CDL = &CodeDataLog{}
|
||||
}
|
||||
|
||||
tokenMap := make(map[int]*Token)
|
||||
|
||||
// starting point is the third byte in the script.
|
||||
|
@ -95,7 +99,7 @@ INNER:
|
|||
|
||||
//fmt.Printf("{$%04X} %s\n", token.Offset, token.String(map[int]*Label{}))
|
||||
|
||||
p.cdl.setCode(p.current)
|
||||
p.script.CDL.setCode(p.current)
|
||||
if raw < 0x80 {
|
||||
continue
|
||||
}
|
||||
|
@ -181,21 +185,21 @@ func Parse(rawinput []byte, startAddr int, cdl *CodeDataLog) (*Script, error) {
|
|||
}
|
||||
|
||||
p := &Parser{
|
||||
cdl: cdl,
|
||||
script: &Script{
|
||||
Tokens: []*Token{},
|
||||
Warnings: []string{},
|
||||
StackAddress: (int(rawinput[1])<<8) | int(rawinput[0]),
|
||||
StartAddress: startAddr,
|
||||
Labels: make(map[int]*Label), // map[location]name
|
||||
CDL: cdl,
|
||||
},
|
||||
rawinput: rawinput,
|
||||
startAddr: startAddr,
|
||||
}
|
||||
tokenMap := make(map[int]*Token)
|
||||
|
||||
if p.cdl == nil {
|
||||
p.cdl = &CodeDataLog{}
|
||||
if p.script.CDL == nil {
|
||||
p.script.CDL = &CodeDataLog{}
|
||||
}
|
||||
|
||||
//earliestVar := len(p.rawinput)-2
|
||||
|
@ -217,8 +221,8 @@ func Parse(rawinput []byte, startAddr int, cdl *CodeDataLog) (*Script, error) {
|
|||
p.script.Tokens = append(p.script.Tokens, token)
|
||||
tokenMap[token.Offset] = token
|
||||
|
||||
if raw < 0x80 || p.cdl.IsData(p.current+startAddr) { // || p.current >= earliestVar {
|
||||
if p.cdl.IsData(p.current+startAddr) {
|
||||
if raw < 0x80 || p.script.CDL.IsData(p.current+startAddr) { // || p.current >= earliestVar {
|
||||
if p.script.CDL.IsData(p.current+startAddr) {
|
||||
token.IsData = true
|
||||
//fmt.Print(".")
|
||||
//fmt.Printf("%#v\n", token)
|
||||
|
@ -321,6 +325,7 @@ func (p *Parser) parseToken(token *Token, raw byte) error {
|
|||
switch op.OpCount {
|
||||
case -1: // null terminated
|
||||
for ; p.current < len(p.rawinput); p.current++ {
|
||||
p.script.CDL.setCode(p.current)
|
||||
val := ByteVal(p.rawinput[p.current])
|
||||
args = append(args, val)
|
||||
if p.rawinput[p.current] == 0x00 {
|
||||
|
@ -332,6 +337,7 @@ func (p *Parser) parseToken(token *Token, raw byte) error {
|
|||
// FIXME: wtf makes this different from -3??
|
||||
p.current++
|
||||
l := int(p.rawinput[p.current])
|
||||
p.script.CDL.setCode(p.current)
|
||||
args = append(args, ByteVal(l))
|
||||
p.current++
|
||||
for c := 0; c < l; c++ {
|
||||
|
@ -349,6 +355,7 @@ func (p *Parser) parseToken(token *Token, raw byte) error {
|
|||
p.current++
|
||||
l := int(p.rawinput[p.current])
|
||||
args = append(args, ByteVal(l))
|
||||
p.script.CDL.setCode(p.current)
|
||||
p.current++
|
||||
for c := 0; c < l; c++ {
|
||||
args = append(args, WordVal([2]byte{p.rawinput[p.current], p.rawinput[p.current+1]}))
|
||||
|
@ -358,7 +365,10 @@ func (p *Parser) parseToken(token *Token, raw byte) error {
|
|||
|
||||
case 2:
|
||||
args = append(args, WordVal([2]byte{p.rawinput[p.current+1], p.rawinput[p.current+2]}))
|
||||
p.script.CDL.setCode(p.current+1)
|
||||
p.script.CDL.setCode(p.current+2)
|
||||
p.current+=2
|
||||
|
||||
//fmt.Printf("var at $%04X\n", val.Int())
|
||||
//if val.Int() > p.startAddr && val.Int() < p.startAddr+len(p.rawinput) && p.earliestVar > val.Int() {
|
||||
// fmt.Printf("new earliest: $%04X\n", val.Int())
|
||||
|
@ -367,6 +377,7 @@ func (p *Parser) parseToken(token *Token, raw byte) error {
|
|||
|
||||
case 1:
|
||||
p.current++
|
||||
p.script.CDL.setCode(p.current)
|
||||
args = append(args, ByteVal(p.rawinput[p.current]))
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ type Script struct {
|
|||
StackAddress int
|
||||
|
||||
Labels map[int]*Label
|
||||
CDL *CodeDataLog
|
||||
}
|
||||
|
||||
func (s *Script) Stats() Stats {
|
||||
|
|
Loading…
Reference in New Issue