This repository has been archived by the owner on Jun 14, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
symbol.go
122 lines (103 loc) · 3.76 KB
/
symbol.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package main
import (
"fmt"
"strconv"
"strings"
)
type Symbol struct {
Id int // unique label ID
Name string // Label
AddrSize string // absolute, zeropage, etc
Parent string // Parent label name. blank if non-local label
Defined []int // "def"
References []int // "ref"
Value int // Address of label
Segment int // ID of segment
}
func (s *Symbol) String() string {
d := []string{}
if len(s.Defined) > 0 {
for _, i := range s.Defined {
d = append(d, fmt.Sprintf("%d", i))
}
}
r := []string{}
if len(s.References) > 0 {
for _, i := range s.References {
r = append(r, fmt.Sprintf("%d", i))
}
}
return fmt.Sprintf("[%d] %s Parent:%s AddrSize:%s Defined:%s References:%s Value:$%X Segment:%d",
s.Id, s.Name, s.Parent, s.AddrSize, d, r, s.Value, s.Segment)
}
// IsSymbol returns true if the given line describes a symbol (Label)
func IsSymbol(line string) bool {
if line[0:4] == "sym\t" {
return true
}
return false
}
// ParseSymbol returns a *Symbol of the given line
func ParseSymbol(line string) (*Symbol, error) {
if len(line) < 4 || line[0:4] != "sym\t" {
return nil, fmt.Errorf("Invalid symbol line: %q", line)
}
items := strings.Split(line[4:], ",")
sym := &Symbol{Segment: -1}
for _, item := range items {
keyval := strings.SplitN(item, "=", 2)
switch keyval[0] {
// Not really needed, but parsed anyway.
case "id":
val, err := strconv.ParseInt(keyval[1], 10, 32)
if err != nil {
return nil, fmt.Errorf("Invalid symbol Id: %q: %s", keyval[1], err)
}
sym.Id = int(val)
// The label name that we need
case "name":
sym.Name = keyval[1][1:len(keyval[1]) - 1]
// Not really needed, but parsed anyway.
case "addrsize":
sym.AddrSize = keyval[1]
// These are both lists of numbers delemited by a plus sign. Aren't
// needed for my purposes, but I parse it anyway.
case "ref", "def":
vals := strings.Split(keyval[1], "+")
if len(vals) > 0 {
lst := []int{}
for _, v := range vals {
val, err := strconv.ParseInt(v, 10, 32)
if err != nil {
return nil, fmt.Errorf("Invalid symbol Reference value: %q: %s", v, err)
}
lst = append(lst, int(val))
}
if keyval[0] == "ref" {
sym.References = lst
} else {
sym.Defined = lst
}
}
// Address of the label
case "val":
val, err := strconv.ParseInt(keyval[1], 0, 32)
if err != nil {
return nil, fmt.Errorf("Invalid symbol Value value: %q: %s", keyval[1], err)
}
sym.Value = int(val)
// Segment that the label belongs to
case "seg":
val, err := strconv.ParseInt(keyval[1], 10, 32)
if err != nil {
return nil, fmt.Errorf("Invalid symbol Segment value: %q: %s", keyval[1], err)
}
sym.Segment = int(val)
}
}
return sym, nil
}
type SymbolSlice []*Symbol
func (ss SymbolSlice) Len() int { return len(ss) }
func (ss SymbolSlice) Swap(i, j int) { ss[i], ss[j] = ss[j], ss[i] }
func (ss SymbolSlice) Less(i, j int) bool { return ss[i].Value < ss[j].Value }