[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"`
|
StatsFile string `arg:"--stats" help:"file to write some statistics to"`
|
||||||
LabelFile string `arg:"--labels" help:"file containing address/label pairs"`
|
LabelFile string `arg:"--labels" help:"file containing address/label pairs"`
|
||||||
CDL string `arg:"--cdl" help:"CodeDataLog json file"`
|
CDL string `arg:"--cdl" help:"CodeDataLog json file"`
|
||||||
|
CDLOutput string `arg:"--cdl-output"`
|
||||||
Smart bool `arg:"--smart"`
|
Smart bool `arg:"--smart"`
|
||||||
|
|
||||||
start int
|
start int
|
||||||
|
@ -103,10 +104,6 @@ func run(args *Arguments) error {
|
||||||
return 0
|
return 0
|
||||||
})
|
})
|
||||||
|
|
||||||
//for _, lbl := range scr.Labels {
|
|
||||||
// fmt.Println(lbl)
|
|
||||||
//}
|
|
||||||
|
|
||||||
for _, token := range scr.Tokens {
|
for _, token := range scr.Tokens {
|
||||||
fmt.Fprintln(outfile, token.String(scr.Labels))
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"strconv"
|
"strconv"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CodeDataLog struct {
|
type CodeDataLog struct {
|
||||||
|
@ -28,8 +29,101 @@ var (
|
||||||
cdlUnknown cdlBit = 0x00
|
cdlUnknown cdlBit = 0x00
|
||||||
cdlCode cdlBit = 0x01
|
cdlCode cdlBit = 0x01
|
||||||
cdlData cdlBit = 0x02
|
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) {
|
func (cdl *CodeDataLog) setData(scriptOffset int) {
|
||||||
if cdl.cache == nil {
|
if cdl.cache == nil {
|
||||||
err := cdl.doCache()
|
err := cdl.doCache()
|
||||||
|
|
|
@ -45,8 +45,6 @@ func SmartParse(rawinput []byte, startAddr int, cdl *CodeDataLog) (*Script, erro
|
||||||
}
|
}
|
||||||
|
|
||||||
p := &Parser{
|
p := &Parser{
|
||||||
// Don't use CDL that was passed in
|
|
||||||
cdl: &CodeDataLog{},
|
|
||||||
|
|
||||||
script: &Script{
|
script: &Script{
|
||||||
Tokens: []*Token{},
|
Tokens: []*Token{},
|
||||||
|
@ -54,12 +52,18 @@ func SmartParse(rawinput []byte, startAddr int, cdl *CodeDataLog) (*Script, erro
|
||||||
StackAddress: (int(rawinput[1])<<8) | int(rawinput[0]),
|
StackAddress: (int(rawinput[1])<<8) | int(rawinput[0]),
|
||||||
StartAddress: startAddr,
|
StartAddress: startAddr,
|
||||||
Labels: make(map[int]*Label), // map[location]name
|
Labels: make(map[int]*Label), // map[location]name
|
||||||
|
|
||||||
|
CDL: cdl,
|
||||||
},
|
},
|
||||||
|
|
||||||
rawinput: rawinput,
|
rawinput: rawinput,
|
||||||
startAddr: startAddr,
|
startAddr: startAddr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if p.script.CDL == nil {
|
||||||
|
p.script.CDL = &CodeDataLog{}
|
||||||
|
}
|
||||||
|
|
||||||
tokenMap := make(map[int]*Token)
|
tokenMap := make(map[int]*Token)
|
||||||
|
|
||||||
// starting point is the third byte in the script.
|
// 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{}))
|
//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 {
|
if raw < 0x80 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -181,21 +185,21 @@ func Parse(rawinput []byte, startAddr int, cdl *CodeDataLog) (*Script, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
p := &Parser{
|
p := &Parser{
|
||||||
cdl: cdl,
|
|
||||||
script: &Script{
|
script: &Script{
|
||||||
Tokens: []*Token{},
|
Tokens: []*Token{},
|
||||||
Warnings: []string{},
|
Warnings: []string{},
|
||||||
StackAddress: (int(rawinput[1])<<8) | int(rawinput[0]),
|
StackAddress: (int(rawinput[1])<<8) | int(rawinput[0]),
|
||||||
StartAddress: startAddr,
|
StartAddress: startAddr,
|
||||||
Labels: make(map[int]*Label), // map[location]name
|
Labels: make(map[int]*Label), // map[location]name
|
||||||
|
CDL: cdl,
|
||||||
},
|
},
|
||||||
rawinput: rawinput,
|
rawinput: rawinput,
|
||||||
startAddr: startAddr,
|
startAddr: startAddr,
|
||||||
}
|
}
|
||||||
tokenMap := make(map[int]*Token)
|
tokenMap := make(map[int]*Token)
|
||||||
|
|
||||||
if p.cdl == nil {
|
if p.script.CDL == nil {
|
||||||
p.cdl = &CodeDataLog{}
|
p.script.CDL = &CodeDataLog{}
|
||||||
}
|
}
|
||||||
|
|
||||||
//earliestVar := len(p.rawinput)-2
|
//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)
|
p.script.Tokens = append(p.script.Tokens, token)
|
||||||
tokenMap[token.Offset] = token
|
tokenMap[token.Offset] = token
|
||||||
|
|
||||||
if raw < 0x80 || p.cdl.IsData(p.current+startAddr) { // || p.current >= earliestVar {
|
if raw < 0x80 || p.script.CDL.IsData(p.current+startAddr) { // || p.current >= earliestVar {
|
||||||
if p.cdl.IsData(p.current+startAddr) {
|
if p.script.CDL.IsData(p.current+startAddr) {
|
||||||
token.IsData = true
|
token.IsData = true
|
||||||
//fmt.Print(".")
|
//fmt.Print(".")
|
||||||
//fmt.Printf("%#v\n", token)
|
//fmt.Printf("%#v\n", token)
|
||||||
|
@ -321,6 +325,7 @@ func (p *Parser) parseToken(token *Token, raw byte) error {
|
||||||
switch op.OpCount {
|
switch op.OpCount {
|
||||||
case -1: // null terminated
|
case -1: // null terminated
|
||||||
for ; p.current < len(p.rawinput); p.current++ {
|
for ; p.current < len(p.rawinput); p.current++ {
|
||||||
|
p.script.CDL.setCode(p.current)
|
||||||
val := ByteVal(p.rawinput[p.current])
|
val := ByteVal(p.rawinput[p.current])
|
||||||
args = append(args, val)
|
args = append(args, val)
|
||||||
if p.rawinput[p.current] == 0x00 {
|
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??
|
// FIXME: wtf makes this different from -3??
|
||||||
p.current++
|
p.current++
|
||||||
l := int(p.rawinput[p.current])
|
l := int(p.rawinput[p.current])
|
||||||
|
p.script.CDL.setCode(p.current)
|
||||||
args = append(args, ByteVal(l))
|
args = append(args, ByteVal(l))
|
||||||
p.current++
|
p.current++
|
||||||
for c := 0; c < l; c++ {
|
for c := 0; c < l; c++ {
|
||||||
|
@ -349,6 +355,7 @@ func (p *Parser) parseToken(token *Token, raw byte) error {
|
||||||
p.current++
|
p.current++
|
||||||
l := int(p.rawinput[p.current])
|
l := int(p.rawinput[p.current])
|
||||||
args = append(args, ByteVal(l))
|
args = append(args, ByteVal(l))
|
||||||
|
p.script.CDL.setCode(p.current)
|
||||||
p.current++
|
p.current++
|
||||||
for c := 0; c < l; c++ {
|
for c := 0; c < l; c++ {
|
||||||
args = append(args, WordVal([2]byte{p.rawinput[p.current], p.rawinput[p.current+1]}))
|
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:
|
case 2:
|
||||||
args = append(args, WordVal([2]byte{p.rawinput[p.current+1], p.rawinput[p.current+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
|
p.current+=2
|
||||||
|
|
||||||
//fmt.Printf("var at $%04X\n", val.Int())
|
//fmt.Printf("var at $%04X\n", val.Int())
|
||||||
//if val.Int() > p.startAddr && val.Int() < p.startAddr+len(p.rawinput) && p.earliestVar > 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())
|
// fmt.Printf("new earliest: $%04X\n", val.Int())
|
||||||
|
@ -367,6 +377,7 @@ func (p *Parser) parseToken(token *Token, raw byte) error {
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
p.current++
|
p.current++
|
||||||
|
p.script.CDL.setCode(p.current)
|
||||||
args = append(args, ByteVal(p.rawinput[p.current]))
|
args = append(args, ByteVal(p.rawinput[p.current]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ type Script struct {
|
||||||
StackAddress int
|
StackAddress int
|
||||||
|
|
||||||
Labels map[int]*Label
|
Labels map[int]*Label
|
||||||
|
CDL *CodeDataLog
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Script) Stats() Stats {
|
func (s *Script) Stats() Stats {
|
||||||
|
|
Loading…
Reference in New Issue