summaryrefslogtreecommitdiff
path: root/symbol.go
diff options
context:
space:
mode:
authorJacob McDonnell <jacob@jacobmcdonnell.com>2024-05-23 18:12:40 -0400
committerJacob McDonnell <jacob@jacobmcdonnell.com>2024-05-23 18:12:40 -0400
commit05d10fb3a941aa384340d2999033aacb31e5f32f (patch)
tree5394fca3789e880babf9ece152a43c1ebf26a509 /symbol.go
parentf3a84599a7034c2e746b952cd4bc9aa5967e4083 (diff)
Initial Implementation of ELF
Diffstat (limited to 'symbol.go')
-rwxr-xr-xsymbol.go154
1 files changed, 141 insertions, 13 deletions
diff --git a/symbol.go b/symbol.go
index f63bb8e..5a71473 100755
--- a/symbol.go
+++ b/symbol.go
@@ -2,15 +2,34 @@ package main
import (
"bufio"
+ "encoding/binary"
"os"
"regexp"
+ "strconv"
"strings"
)
+type PosPair struct {
+ pos uint
+ section uint8
+}
+
// Map for labels and their addresses
-var labels map[string]uint = make(map[string]uint)
+var labels map[string]PosPair = make(map[string]PosPair)
+
+var SectionPos [4]uint
+
+const (
+ TEXT = 0
+ DATA = 1
+ RODATA = 2
+ BSS = 3
+)
+
+func LabelFind(path string, dTemp, rTemp *os.File) {
+ // This will track the current section, default is .text
+ var Section uint8 = TEXT
-func LabelFind(path string) {
file, err := os.Open(path)
if err != nil {
panic(err)
@@ -18,23 +37,31 @@ func LabelFind(path string) {
defer file.Close()
input := bufio.NewScanner(file)
-
- for i := 0; input.Scan(); i += 4 {
- k := input.Text()
- if k == "" {
- i -= 4
+ for input.Scan() {
+ i := &SectionPos[Section]
+ switch input.Text() {
+ case "":
+ continue
+ case ".text":
+ Section = TEXT
+ continue
+ case ".data":
+ Section = DATA
+ continue
+ case ".rodata":
+ Section = RODATA
continue
- } else if k == ".text" || k == ".data" {
- i += 4
+ case ".bss":
+ Section = BSS
continue
}
- s, err := Parse(k)
+
+ s, err := Parse(input.Text())
if err != nil {
panic(err)
}
if len(s) == 1 && s[0] == "" {
- i -= 4
continue
}
@@ -43,10 +70,111 @@ func LabelFind(path string) {
panic(err)
}
if hasLabel {
- labels[strings.ReplaceAll(s[0], ":", "")] = uint(i)
+ labels[strings.ReplaceAll(s[0], ":", "")] = PosPair{*i, Section}
if len(s) == 1 {
- i -= 4
+ continue
+ } else {
+ s = s[1:]
+ }
+ }
+
+ offset, err := CalcOffset(s, Section, dTemp, rTemp)
+ if err != nil {
+ panic(err)
+ }
+ *i += offset
+ }
+}
+
+func CalcOffset(s []string, Section uint8, dTemp, rTemp *os.File) (uint, error) {
+ var offset uint
+ if Section != TEXT {
+ b, err := EncodeData(s)
+ if err != nil {
+ return 0, err
+ }
+ if Section == DATA {
+ _, err := dTemp.Write(b)
+ if err != nil {
+ return 0, err
+ }
+ } else if Section == RODATA {
+ _, err := rTemp.Write(b)
+ if err != nil {
+ return 0, err
+ }
+ }
+ offset = uint(len(b))
+ } else {
+ offset = 4
+ }
+ return offset, nil
+}
+
+func EncodeData(line []string) ([]byte, error) {
+ var size int
+ var err error = nil
+ var data int64
+ isString := false
+ isData := false
+ nullTerm := false
+
+ line[1] = strings.ReplaceAll(line[1], "\"", "")
+
+ switch line[0] {
+ case ".space":
+ size, err = strconv.Atoi(line[1])
+ case ".word":
+ size = 4
+ isData = true
+ case ".byte":
+ size = 1
+ isData = true
+ case ".half":
+ size = 2
+ isData = true
+ case ".asciiz":
+ size = len(line[1]) + 1
+ isString = true
+ nullTerm = true
+ case ".ascii":
+ size = len(line[1])
+ isString = true
+ }
+ if err != nil {
+ return nil, err
+ }
+ bytes := make([]byte, size)
+
+ if isData {
+ if strings.Contains(line[1], "0x") {
+ line[1] = strings.ReplaceAll(line[1], "0x", "")
+ var t uint64
+ t, err = strconv.ParseUint(line[1], 16, size*8)
+ data = int64(t)
+ } else {
+ data, err = strconv.ParseInt(line[1], 10, size*8)
+ }
+ if err != nil {
+ return nil, err
+ }
+ switch size {
+ case 1:
+ bytes[0] = uint8(data)
+ case 2:
+ binary.NativeEndian.PutUint16(bytes, uint16(data))
+ case 4:
+ binary.NativeEndian.PutUint32(bytes, uint32(data))
+ }
+ } else if isString {
+ if nullTerm {
+ for i, b := range []byte(line[1]) {
+ bytes[i] = b
}
+ bytes[size-1] = 0
+ } else {
+ bytes = []byte(line[1])
}
}
+ return bytes, nil
}