Skip to content

Commit

Permalink
Fix 1.21 and 1.22 moduledata, add basic 1.22 support
Browse files Browse the repository at this point in the history
  • Loading branch information
stevemk14ebr committed Feb 8, 2024
1 parent d75fbb4 commit a2567ab
Show file tree
Hide file tree
Showing 5 changed files with 247 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
uses: actions/checkout@v4
- uses: actions/setup-go@v4
with:
go-version: '>=1.21.0'
go-version: '>=1.22.0'
- run: go version
- name: GoReSym Build
run: |
Expand Down
2 changes: 1 addition & 1 deletion build_test_files.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash
trap "exit" INT
sudo rm -rf $(pwd)/test/build
versions=("1.21" "1.20" "1.19" "1.18" "1.17" "1.16" "1.15" "1.14" "1.13" "1.12" "1.11" "1.10" "1.9" "1.8" "1.7" "1.6" "1.5")
versions=("1.22" "1.21" "1.20" "1.19" "1.18" "1.17" "1.16" "1.15" "1.14" "1.13" "1.12" "1.11" "1.10" "1.9" "1.8" "1.7" "1.6" "1.5")
for v in "${versions[@]}"
do
GO_TAG=$v
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/mandiant/GoReSym

go 1.21
go 1.22

require (
github.com/elliotchance/orderedmap v1.4.0
Expand Down
120 changes: 120 additions & 0 deletions objfile/internals.go
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,126 @@ func (moduledata *ModuleData120_32) parse(rawData []byte, littleEndian bool) err
return binary.Read(srcBytes, byteOrder, moduledata)
}

type ModuleData121_64 struct {
PcHeader pvoid64
Funcnametab GoSlice64
Cutab GoSlice64
Filetab GoSlice64
Pctab GoSlice64
Pclntable GoSlice64
Ftab GoSlice64
Findfunctab pvoid64
Minpc pvoid64
Maxpc pvoid64
Text pvoid64
Etext pvoid64
Noptrdata pvoid64
Enoptrdata pvoid64
Data pvoid64
Edata pvoid64
Bss pvoid64
Ebss pvoid64
Noptrbss pvoid64
Enoptrbss pvoid64
Covctrs pvoid64
Ecovctrs pvoid64
End pvoid64
Gcdata pvoid64
Gcbss pvoid64
Types pvoid64
Etypes pvoid64
Rodata pvoid64
Gofunc pvoid64
Textsectmap GoSlice64
Typelinks GoSlice64
Itablinks GoSlice64
Ptab GoSlice64
Pluginpath GoString64
Pkghashes GoSlice64
InitTasks GoSlice64
Modulename GoString64
Modulehashes GoSlice64
Hasmain bool
Gcdatamask GoBitVector64
Gcbssmask GoBitVector64
Typemap pvoid64
Badload bool
Next pvoid64
}

func (moduledata *ModuleData121_64) parse(rawData []byte, littleEndian bool) error {
srcBytes := bytes.NewBuffer(rawData)

var byteOrder binary.ByteOrder
if littleEndian {
byteOrder = binary.LittleEndian
} else {
byteOrder = binary.BigEndian
}

return binary.Read(srcBytes, byteOrder, moduledata)
}

type ModuleData121_32 struct {
PcHeader pvoid32
Funcnametab GoSlice32
Cutab GoSlice32
Filetab GoSlice32
Pctab GoSlice32
Pclntable GoSlice32
Ftab GoSlice32
Findfunctab pvoid32
Minpc pvoid32
Maxpc pvoid32
Text pvoid32
Etext pvoid32
Noptrdata pvoid32
Enoptrdata pvoid32
Data pvoid32
Edata pvoid32
Bss pvoid32
Ebss pvoid32
Noptrbss pvoid32
Enoptrbss pvoid32
Covctrs pvoid32
Ecovctrs pvoid32
End pvoid32
Gcdata pvoid32
Gcbss pvoid32
Types pvoid32
Etypes pvoid32
Rodata pvoid32
Gofunc pvoid32
Textsectmap GoSlice32
Typelinks GoSlice32
Itablinks GoSlice32
Ptab GoSlice32
Pluginpath GoString32
Pkghashes GoSlice32
InitTasks GoSlice32
Modulename GoString32
Modulehashes GoSlice32
Hasmain bool
Gcdatamask GoBitVector32
Gcbssmask GoBitVector32
Typemap pvoid32
Badload bool
Next pvoid32
}

func (moduledata *ModuleData121_32) parse(rawData []byte, littleEndian bool) error {
srcBytes := bytes.NewBuffer(rawData)

var byteOrder binary.ByteOrder
if littleEndian {
byteOrder = binary.LittleEndian
} else {
byteOrder = binary.BigEndian
}

return binary.Read(srcBytes, byteOrder, moduledata)
}

type Textsect_64 struct {
Vaddr pvoid64 // prelinked section vaddr
End pvoid64 // vaddr + section length
Expand Down
125 changes: 124 additions & 1 deletion objfile/objfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,123 @@ func (e *Entry) ModuleDataTable(pclntabVA uint64, runtimeVersion string, version
// there's really only 3 main versions for these internal runtime changes 1.2 (<= 1.15), 1.16 (<= 1.17), 1.18 (>= 1.18)
// this routine needs the pclntab version, NOT the go runtime version (ex: go 1.15 generates 1.2 style tables)
switch version {
case "1.21":
case "1.22":
fallthrough
case "1.21":
if is64bit {
var module ModuleData121_64
err := module.parse(moduleDataCandidate.Moduledata, littleendian)
if err != nil {
return 0, nil, err
}

var firstFunc FuncTab118
ftab_raw, err := e.raw.read_memory(uint64(module.Ftab.Data), uint64(unsafe.Sizeof(firstFunc)))
if err != nil {
return 0, nil, err
}

err = firstFunc.parse(ftab_raw, littleendian)
if err != nil {
return 0, nil, err
}

// prevent loop on invalid modules with bogus length
if module.Textsectmap.Len > 0x100 {
continue
}

var textsectmap []Textsect_64
for i := 0; i < int(module.Textsectmap.Len); i++ {
var textsect Textsect_64
var sectSize = uint64(unsafe.Sizeof(textsect))
textsec_raw, err := e.raw.read_memory(uint64(module.Textsectmap.Data)+uint64(i)*sectSize, sectSize)
if err != nil {
continue
}

err = textsect.parse(textsec_raw, littleendian)
if err != nil {
continue
}
textsectmap = append(textsectmap, textsect)
}

// functab's first function should equal the minpc value of moduledata. If not, parse failed, or we found wrong moduledata
// https://github.com/golang/go/blob/9ecb853cf2252f3cd9ed2e7b3401d17df2d1ab06/src/runtime/symtab.go#L630-L632
if textAddr64(uint64(firstFunc.Entryoffset), uint64(module.Text), textsectmap) != uint64(module.Minpc) {
// wrong moduledata, try next
ignorelist = append(ignorelist, moduleDataCandidate.ModuledataVA)
continue
}

moduleData.VA = moduleDataCandidate.ModuledataVA
moduleData.TextVA = uint64(module.Text)
moduleData.Types = uint64(module.Types)
moduleData.ETypes = uint64(module.Etypes)
moduleData.Typelinks = module.Typelinks
moduleData.ITablinks = module.Itablinks
return secStart, moduleData, err
} else {
var module ModuleData121_32
err := module.parse(moduleDataCandidate.Moduledata, littleendian)
if err != nil {
return 0, nil, err
}

var firstFunc FuncTab118
ftab_raw, err := e.raw.read_memory(uint64(module.Ftab.Data), uint64(unsafe.Sizeof(firstFunc)))
if err != nil {
return 0, nil, err
}

err = firstFunc.parse(ftab_raw, littleendian)
if err != nil {
return 0, nil, err
}

// prevent loop on invalid modules with bogus length
if module.Textsectmap.Len > 0x100 {
continue
}

var textsectmap []Textsect_32
for i := 0; i < int(module.Textsectmap.Len); i++ {
var textsect Textsect_32
var sectSize = uint64(unsafe.Sizeof(textsect))
textsec_raw, err := e.raw.read_memory(uint64(module.Textsectmap.Data)+uint64(i)*sectSize, sectSize)
if err != nil {
continue
}

err = textsect.parse(textsec_raw, littleendian)
if err != nil {
continue
}
textsectmap = append(textsectmap, textsect)
}

// functab's first function should equal the minpc value of moduledata. If not, parse failed, or we found wrong moduledata
// https://github.com/golang/go/blob/9ecb853cf2252f3cd9ed2e7b3401d17df2d1ab06/src/runtime/symtab.go#L630-L632
if textAddr32(uint64(firstFunc.Entryoffset), uint64(module.Text), textsectmap) != uint64(module.Minpc) {
// wrong moduledata, try next
ignorelist = append(ignorelist, moduleDataCandidate.ModuledataVA)
continue
}

moduleData.VA = moduleDataCandidate.ModuledataVA
moduleData.TextVA = uint64(module.Text)
moduleData.Types = uint64(module.Types)
moduleData.ETypes = uint64(module.Etypes)
moduleData.Typelinks.Data = pvoid64(module.Typelinks.Data)
moduleData.Typelinks.Len = uint64(module.Typelinks.Len)
moduleData.Typelinks.Capacity = uint64(module.Typelinks.Capacity)

moduleData.ITablinks.Data = pvoid64(module.Itablinks.Data)
moduleData.ITablinks.Len = uint64(module.Itablinks.Len)
moduleData.ITablinks.Capacity = uint64(module.Itablinks.Capacity)
return secStart, moduleData, err
}
case "1.20":
if is64bit {
var module ModuleData120_64
Expand Down Expand Up @@ -937,6 +1052,8 @@ func (e *Entry) readRTypeName(runtimeVersion string, typeFlags tflag, namePtr ui
case "1.20":
fallthrough
case "1.21":
fallthrough
case "1.22":
varint_len, namelen, err := e.readVarint(namePtr + 1)
if err != nil {
return "", fmt.Errorf("Failed to read name")
Expand Down Expand Up @@ -1184,6 +1301,8 @@ func (e *Entry) ParseType_impl(runtimeVersion string, moduleData *ModuleData, ty
case "1.20":
fallthrough
case "1.21":
fallthrough
case "1.22":
if is64bit {
var rtype Rtype114_115_116_117_118_64
rtype_raw, err := e.raw.read_memory(typeAddress, uint64(unsafe.Sizeof(rtype)))
Expand Down Expand Up @@ -1513,6 +1632,8 @@ func (e *Entry) ParseType_impl(runtimeVersion string, moduleData *ModuleData, ty
case "1.20":
fallthrough
case "1.21":
fallthrough
case "1.22":
var methodsStartAddr uint64 = typeAddress + uint64(_type.baseSize) + ptrSize
var methods GoSlice64 = GoSlice64{}
if is64bit {
Expand Down Expand Up @@ -1676,6 +1797,8 @@ func (e *Entry) ParseType_impl(runtimeVersion string, moduleData *ModuleData, ty
case "1.20":
fallthrough
case "1.21":
fallthrough
case "1.22":
// type structType struct {
// rtype
// pkgPath name // pointer
Expand Down

0 comments on commit a2567ab

Please sign in to comment.