Skip to content

Commit

Permalink
parse field tag
Browse files Browse the repository at this point in the history
  • Loading branch information
virusdefender committed Sep 20, 2023
1 parent 944c2b7 commit 8b3bd0e
Showing 1 changed file with 74 additions and 30 deletions.
104 changes: 74 additions & 30 deletions objfile/objfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ package objfile
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"io"
"os"
Expand Down Expand Up @@ -839,7 +840,7 @@ func (e *Entry) readVarint(address uint64) (int, int, error) {
}
}

func (e *Entry) readRTypeName(runtimeVersion string, typeFlags tflag, namePtr uint64, is64bit bool, littleendian bool) (name string, err error) {
func (e *Entry) readRTypeName(runtimeVersion string, typeFlags tflag, namePtr uint64, is64bit bool, littleendian bool) (name string, tag string, err error) {
// name str (for <= 1.16 encodes length like this, beyond it uses a varint encoding)
// The first byte is a bit field containing:
//
Expand Down Expand Up @@ -872,23 +873,24 @@ func (e *Entry) readRTypeName(runtimeVersion string, typeFlags tflag, namePtr ui
case "1.5":
fallthrough
case "1.6":
// TODO: parse field tag
// pointer to GoString
nameLen, err := e.ReadPointerSizeMem(namePtr+ptrSize, is64bit, littleendian)
if err != nil {
return "", fmt.Errorf("Failed to read name")
return "", "", fmt.Errorf("Failed to read name")
}

deref, err := e.ReadPointerSizeMem(namePtr, is64bit, littleendian)
if err != nil {
return "", fmt.Errorf("Failed to read name")
return "", "", fmt.Errorf("Failed to read name")
}

name_raw, err := e.raw.read_memory(deref, nameLen)
if err != nil {
return "", fmt.Errorf("Failed to read name")
return "", "", fmt.Errorf("Failed to read name")
}

return string(name_raw), nil
return string(name_raw), "", nil
case "1.7": // types flags exists >= 1.7
fallthrough
case "1.8": // type flag tflagExtraStart exists >= 1.8
Expand All @@ -908,22 +910,41 @@ func (e *Entry) readRTypeName(runtimeVersion string, typeFlags tflag, namePtr ui
case "1.15":
fallthrough
case "1.16":
name_len_raw, err := e.raw.read_memory(namePtr, 3)
flag, err := e.raw.read_memory(namePtr, 1)
if err != nil {
return "", fmt.Errorf("Failed to read name")
return "", "", errors.New("Failed to read flag")
}

name_len := uint16(uint16(name_len_raw[1])<<8 | uint16(name_len_raw[2]))
name_len_raw, err := e.raw.read_memory(namePtr+1, 2)
if err != nil {
return "", "", fmt.Errorf("Failed to read name")
}

name_len := uint16(uint16(name_len_raw[0])<<8 | uint16(name_len_raw[1]))
name_raw, err := e.raw.read_memory(namePtr+3, uint64(name_len))
if err != nil {
return "", fmt.Errorf("Failed to read name")
return "", "", fmt.Errorf("Failed to read name")
}

name := string(name_raw)

if flag[0] == 3 {
tag_len_raw, err := e.raw.read_memory(namePtr+3+uint64(name_len), 2)
if err != nil {
return "", "", errors.New("Failed to read tag")
}

tag_len := uint16(uint16(tag_len_raw[0])<<8 | uint16(tag_len_raw[1]))
tag_raw, err := e.raw.read_memory(namePtr+3+uint64(name_len)+2, uint64(tag_len))
if err != nil {
return "", "", errors.New("Failed to read tag")
}
tag = string(tag_raw)
}
if typeFlags&tflagExtraStar != 0 {
return name[1:], nil
return name[1:], tag, nil
} else {
return name, nil
return name, tag, nil
}
case "1.17":
fallthrough
Expand All @@ -932,24 +953,39 @@ func (e *Entry) readRTypeName(runtimeVersion string, typeFlags tflag, namePtr ui
case "1.19":
fallthrough
case "1.20":
flag, err := e.raw.read_memory(namePtr, 1)
if err != nil {
return "", "", errors.New("Failed to read flag")
}
varint_len, namelen, err := e.readVarint(namePtr + 1)
if err != nil {
return "", fmt.Errorf("Failed to read name")
// TODO: replace all misuses of fmt.Errorf to errors.New
return "", "", fmt.Errorf("Failed to read name")
}

name_raw, err := e.raw.read_memory(namePtr+1+uint64(varint_len), uint64(namelen))
if err != nil {
return "", fmt.Errorf("Failed to read name")
return "", "", fmt.Errorf("Failed to read name")
}

name := string(name_raw)

if flag[0] == 3 {
varint_len, taglen, err := e.readVarint(namePtr + 1 + uint64(varint_len) + uint64(namelen))
if err != nil {
return "", "", errors.New("Failed to read tag")
}
tag_raw, err := e.raw.read_memory(namePtr+1+uint64(varint_len)+uint64(namelen)+uint64(varint_len), uint64(taglen))
if err != nil {
return "", "", errors.New("Failed to read tag")
}
tag = string(tag_raw)
}
if typeFlags&tflagExtraStar != 0 {
return name[1:], nil
return name[1:], tag, nil
} else {
return name, nil
return name, tag, nil
}
}
return "", fmt.Errorf("Failed to read name")
return "", "", fmt.Errorf("Failed to read name")
}

func decodePtrSizeBytes(data []byte, is64bit bool, littleendian bool) (result uint64) {
Expand Down Expand Up @@ -1056,7 +1092,7 @@ func (e *Entry) ParseType_impl(runtimeVersion string, moduleData *ModuleData, ty
return parsedTypesIn, fmt.Errorf("Failed to parse type")
}

name, err := e.readRTypeName(runtimeVersion, 0, uint64(rtype.Str), is64bit, littleendian)
name, _, err := e.readRTypeName(runtimeVersion, 0, uint64(rtype.Str), is64bit, littleendian)
if err != nil {
return parsedTypesIn, fmt.Errorf("Failed to read type name")
}
Expand All @@ -1074,7 +1110,7 @@ func (e *Entry) ParseType_impl(runtimeVersion string, moduleData *ModuleData, ty
return parsedTypesIn, fmt.Errorf("Failed to parse type")
}

name, err := e.readRTypeName(runtimeVersion, 0, uint64(rtype.Str), is64bit, littleendian)
name, _, err := e.readRTypeName(runtimeVersion, 0, uint64(rtype.Str), is64bit, littleendian)
if err != nil {
return parsedTypesIn, fmt.Errorf("Failed to read type name")
}
Expand All @@ -1093,7 +1129,7 @@ func (e *Entry) ParseType_impl(runtimeVersion string, moduleData *ModuleData, ty
return parsedTypesIn, fmt.Errorf("Failed to parse type")
}

name, err := e.readRTypeName(runtimeVersion, 0, uint64(rtype.Str), is64bit, littleendian)
name, _, err := e.readRTypeName(runtimeVersion, 0, uint64(rtype.Str), is64bit, littleendian)
if err != nil {
return parsedTypesIn, fmt.Errorf("Failed to read type name")
}
Expand All @@ -1110,7 +1146,7 @@ func (e *Entry) ParseType_impl(runtimeVersion string, moduleData *ModuleData, ty
return parsedTypesIn, fmt.Errorf("Failed to parse type")
}

name, err := e.readRTypeName(runtimeVersion, 0, uint64(rtype.Str), is64bit, littleendian)
name, _, err := e.readRTypeName(runtimeVersion, 0, uint64(rtype.Str), is64bit, littleendian)
if err != nil {
return parsedTypesIn, fmt.Errorf("Failed to read type name")
}
Expand Down Expand Up @@ -1140,7 +1176,7 @@ func (e *Entry) ParseType_impl(runtimeVersion string, moduleData *ModuleData, ty
return parsedTypesIn, fmt.Errorf("Failed to parse type")
}
name_ptr := moduleData.Types + uint64(rtype.Str)
name, err := e.readRTypeName(runtimeVersion, rtype.Tflag, name_ptr, is64bit, littleendian)
name, _, err := e.readRTypeName(runtimeVersion, rtype.Tflag, name_ptr, is64bit, littleendian)
if err != nil {
return parsedTypesIn, fmt.Errorf("Failed to read type name")
}
Expand All @@ -1156,7 +1192,7 @@ func (e *Entry) ParseType_impl(runtimeVersion string, moduleData *ModuleData, ty
return parsedTypesIn, fmt.Errorf("Failed to parse type")
}
name_ptr := moduleData.Types + uint64(rtype.Str)
name, err := e.readRTypeName(runtimeVersion, rtype.Tflag, name_ptr, is64bit, littleendian)
name, _, err := e.readRTypeName(runtimeVersion, rtype.Tflag, name_ptr, is64bit, littleendian)
if err != nil {
return parsedTypesIn, fmt.Errorf("Failed to read type name")
}
Expand Down Expand Up @@ -1186,7 +1222,7 @@ func (e *Entry) ParseType_impl(runtimeVersion string, moduleData *ModuleData, ty
return parsedTypesIn, fmt.Errorf("Failed to parse type")
}
name_ptr := moduleData.Types + uint64(rtype.Str)
name, err := e.readRTypeName(runtimeVersion, rtype.Tflag, name_ptr, is64bit, littleendian)
name, _, err := e.readRTypeName(runtimeVersion, rtype.Tflag, name_ptr, is64bit, littleendian)
if err != nil {
return parsedTypesIn, fmt.Errorf("Failed to read type name")
}
Expand All @@ -1202,7 +1238,7 @@ func (e *Entry) ParseType_impl(runtimeVersion string, moduleData *ModuleData, ty
return parsedTypesIn, fmt.Errorf("Failed to parse type")
}
name_ptr := moduleData.Types + uint64(rtype.Str)
name, err := e.readRTypeName(runtimeVersion, rtype.Tflag, name_ptr, is64bit, littleendian)
name, _, err := e.readRTypeName(runtimeVersion, rtype.Tflag, name_ptr, is64bit, littleendian)
if err != nil {
return parsedTypesIn, fmt.Errorf("Failed to read type name")
}
Expand Down Expand Up @@ -1597,9 +1633,13 @@ func (e *Entry) ParseType_impl(runtimeVersion string, moduleData *ModuleData, ty
field, found := parsedTypesIn.Get(typeAddr)
if found {
typeNameAddr := decodePtrSizeBytes(data[0:ptrSize], is64bit, littleendian)
typeName, err := e.readRTypeName(runtimeVersion, 0, typeNameAddr, is64bit, littleendian)
typeName, tag, err := e.readRTypeName(runtimeVersion, 0, typeNameAddr, is64bit, littleendian)
if err == nil {
structDef += fmt.Sprintf("\n %-10s %s", typeName, field.(Type).Str)
if tag != "" {
structDef += fmt.Sprintf("\n %-10s %s `%s`", typeName, field.(Type).Str, tag)
} else {
structDef += fmt.Sprintf("\n %-10s %s", typeName, field.(Type).Str)
}
cstructDef += fmt.Sprintf(" %-10s %s;\n", field.(Type).CStr, replace_cpp_keywords(typeName))
}
}
Expand Down Expand Up @@ -1690,9 +1730,13 @@ func (e *Entry) ParseType_impl(runtimeVersion string, moduleData *ModuleData, ty
field, found := parsedTypesIn.Get(typeAddr)
if found {
typeNameAddr := decodePtrSizeBytes(data[0:ptrSize], is64bit, littleendian)
typeName, err := e.readRTypeName(runtimeVersion, 0, typeNameAddr, is64bit, littleendian)
typeName, tag, err := e.readRTypeName(runtimeVersion, 0, typeNameAddr, is64bit, littleendian)
if err == nil {
structDef += fmt.Sprintf("\n %-10s %s", typeName, field.(Type).Str)
if tag != "" {
structDef += fmt.Sprintf("\n %-10s %s `%s`", typeName, field.(Type).Str, tag)
} else {
structDef += fmt.Sprintf("\n %-10s %s", typeName, field.(Type).Str)
}
cstructDef += fmt.Sprintf(" %-10s %s;\n", field.(Type).CStr, replace_cpp_keywords(typeName))
}
}
Expand Down

0 comments on commit 8b3bd0e

Please sign in to comment.