Skip to content

Commit

Permalink
fix: throw weak disasm result when conflict
Browse files Browse the repository at this point in the history
  • Loading branch information
Zxilly committed Apr 22, 2024
1 parent 395c46d commit 84e7259
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 68 deletions.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ require (
github.com/schollz/progressbar/v3 v3.14.2
go4.org/intern v0.0.0-20230525184215-6c62f75575cb
golang.org/x/arch v0.7.0
golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f
)

require (
Expand All @@ -27,4 +27,4 @@ require (
golang.org/x/term v0.18.0 // indirect
)

replace github.com/goretk/gore v0.11.5 => github.com/Zxilly/gore v0.0.0-20240318154146-c4adda6837cf
replace github.com/goretk/gore v0.11.5 => github.com/Zxilly/gore v0.0.0-20240422132935-dedfb5d7e0cf
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
github.com/Zxilly/gore v0.0.0-20240318154146-c4adda6837cf h1:7j4UDU64LA8HztL1Yq4sEVTFd74Y7aI7JIljNXMkiLA=
github.com/Zxilly/gore v0.0.0-20240318154146-c4adda6837cf/go.mod h1:+HNdF7hbFCpnde7NyUqAxtkJxSY5T0Aip2te6Ecb4yQ=
github.com/Zxilly/gore v0.0.0-20240422132935-dedfb5d7e0cf h1:XwTMa7QFoxZTxgRzKeWnukI5AoWaMrnrk4Q1k+rrgWg=
github.com/Zxilly/gore v0.0.0-20240422132935-dedfb5d7e0cf/go.mod h1:+HNdF7hbFCpnde7NyUqAxtkJxSY5T0Aip2te6Ecb4yQ=
github.com/ZxillyFork/go-flags v0.0.0-20240325132113-057f93e1e1ff h1:OuVeRrJ/P1D9Ihxre9+V0ZMg0BTqNwA+f8rMPp5GuWQ=
github.com/ZxillyFork/go-flags v0.0.0-20240325132113-057f93e1e1ff/go.mod h1:OGK3qX78jYPhFhhyc+QIabXoZhWm8TcpSJNHJM2qo+E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down Expand Up @@ -39,8 +39,8 @@ go4.org/unsafe/assume-no-moving-gc v0.0.0-20231121144256-b99613f794b6 h1:lGdhQUN
go4.org/unsafe/assume-no-moving-gc v0.0.0-20231121144256-b99613f794b6/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc=
golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81 h1:6R2FC06FonbXQ8pK11/PDFY6N6LWlf9KlzibaCapmqc=
golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ=
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY=
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
Expand Down
4 changes: 2 additions & 2 deletions internal/collect.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ func NewKnownInfo(file *gore.GoFile) (*KnownInfo, error) {

k.LoadSectionMap()

err := k.LoadPackages(file)
err := k.LoadPackages()
if err != nil {
return nil, err
}

err = k.AnalyzeSymbol(file)
err = k.AnalyzeSymbol()
if err != nil {
if errors.Is(err, wrapper.ErrNoSymbolTable) {
slog.Warn("Warning: no symbol table found, this can lead to inaccurate results")
Expand Down
4 changes: 4 additions & 0 deletions internal/disasm.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ func (k *KnownInfo) Disasm() error {
possibles := lo.Flatten(lop.Map(fns, func(fn *entity.Function, index int) []result {
candidates := e.Extract(fn.Addr, fn.Addr+fn.Size)
candidates = lo.Filter(candidates, func(p disasm.PossibleStr, _ int) bool {
if p.Size <= 2 {
return false
}

return e.AddrIsString(p.Addr, int64(p.Size))
})
_ = pb.Add(1)
Expand Down
92 changes: 60 additions & 32 deletions internal/entity/coverage.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,59 +3,87 @@ package entity
import (
"cmp"
"fmt"
"github.com/samber/lo"
"slices"
)

// AddrCoverage is a list of AddrPos, describe the disAsmCoverage of the address space
type AddrCoverage []AddrPos
type AddrCoverage []*CoveragePart

// CleanCoverage merge the overlapped AddrPos
func CleanCoverage(dirty AddrCoverage) AddrCoverage {
dirty = lo.Uniq(dirty)
type CoveragePart struct {
Pos AddrPos
Addrs []*Addr
}

type ErrAddrCoverageConflict struct {
Addr uint64
Pos1 *CoveragePart
Pos2 *CoveragePart
}

func (e ErrAddrCoverageConflict) Error() string {
return fmt.Sprintf("addr %x pos %#v and %#v conflict", e.Addr, e.Pos1, e.Pos2)
}

// MergeCoverage merge multiple AddrCoverage
func MergeCoverage(coves []AddrCoverage) (AddrCoverage, *ErrAddrCoverageConflict) {
size := 0
for _, cov := range coves {
size += len(cov)
}

dirty := make(AddrCoverage, 0, size)
for _, cov := range coves {
dirty = append(dirty, cov...)
}

slices.SortFunc(dirty, func(a, b AddrPos) int {
if a.Addr != b.Addr {
return cmp.Compare(a.Addr, b.Addr)
slices.SortFunc(dirty, func(a, b *CoveragePart) int {
if a.Pos.Addr != b.Pos.Addr {
return cmp.Compare(a.Pos.Addr, b.Pos.Addr)
}
return cmp.Compare(a.Size, b.Size)
return cmp.Compare(a.Pos.Size, a.Pos.Size)
})

cover := make([]AddrPos, 0)
cover := make(AddrCoverage, 0)
for _, pos := range dirty {
if len(cover) == 0 {
cover = append(cover, pos)
continue
}

last := &cover[len(cover)-1]
if last.Addr+last.Size >= pos.Addr {
last := cover[len(cover)-1]
lastPos := last.Pos
cur := pos.Pos

if cur.Addr < lastPos.Addr+lastPos.Size {
// merge
if last.Type != pos.Type {
panic(fmt.Errorf("addr %x type %s and %s conflict", pos.Addr, last.Type, pos.Type))
if lastPos.Type != pos.Pos.Type {
// if any is disasm, throw it
if last.Addrs[len(last.Addrs)-1].SourceType == AddrSourceDisasm {
cover = cover[:len(cover)-1]
}
if pos.Addrs[0].SourceType == AddrSourceDisasm {
continue
}

return nil, &ErrAddrCoverageConflict{
Addr: pos.Pos.Addr,
Pos1: last,
Pos2: pos,
}
}

if last.Addr+last.Size < pos.Addr+pos.Size {
last.Size = pos.Addr + pos.Size - last.Addr
curEnd := pos.Pos.Addr + pos.Pos.Size
if lastPos.Addr+lastPos.Size < curEnd {
lastPos.Size = curEnd - lastPos.Addr
last.Addrs = append(last.Addrs, pos.Addrs...)
}
} else {
cover = append(cover, pos)
cover = append(cover, &CoveragePart{
Pos: pos.Pos,
Addrs: pos.Addrs,
})
}
}

return cover
}

func MergeCoverage(coves ...AddrCoverage) AddrCoverage {
size := 0
for _, cov := range coves {
size += len(cov)
}

ranges := make([]AddrPos, 0, size)
for _, cov := range coves {
ranges = append(ranges, cov...)
}

return CleanCoverage(ranges)
return cover, nil
}
18 changes: 9 additions & 9 deletions internal/entity/knownaddr.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import (
type KnownAddr struct {
Pclntab AddrSpace

symbol AddrSpace
SymbolCoverage []AddrPos
Symbol AddrSpace
SymbolCoverage AddrCoverage
}

func NewKnownAddr() *KnownAddr {
return &KnownAddr{
Pclntab: make(map[uint64]*Addr),
symbol: make(map[uint64]*Addr),
Symbol: make(map[uint64]*Addr),
}
}

Expand Down Expand Up @@ -54,19 +54,19 @@ func (f *KnownAddr) InsertSymbol(entry uint64, size uint64, p *Package, typ Addr
return
}
}
f.symbol.Insert(&cur)
f.Symbol.Insert(&cur)
}

func (f *KnownAddr) BuildSymbolCoverage() {
f.SymbolCoverage = f.symbol.ToCoverage()
f.SymbolCoverage = f.Symbol.ToDirtyCoverage()
}

func (f *KnownAddr) SymbolCovHas(entry uint64, size uint64) (AddrType, bool) {
c, ok := slices.BinarySearchFunc(f.SymbolCoverage, AddrPos{Addr: entry}, func(cur AddrPos, target AddrPos) int {
if cur.Addr+cur.Size <= target.Addr {
c, ok := slices.BinarySearchFunc(f.SymbolCoverage, &CoveragePart{Pos: AddrPos{Addr: entry}}, func(cur *CoveragePart, target *CoveragePart) int {
if cur.Pos.Addr+cur.Pos.Size <= target.Pos.Addr {
return -1
}
if cur.Addr >= target.Addr+size {
if cur.Pos.Addr >= target.Pos.Addr+size {
return 1
}
return 0
Expand All @@ -75,7 +75,7 @@ func (f *KnownAddr) SymbolCovHas(entry uint64, size uint64) (AddrType, bool) {
return "", false
}

return f.SymbolCoverage[c].Type, ok
return f.SymbolCoverage[c].Pos.Type, ok
}

func (f *KnownAddr) InsertDisasm(entry uint64, size uint64, fn *Function) {
Expand Down
5 changes: 3 additions & 2 deletions internal/entity/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,11 +207,12 @@ func (p *Package) GetAddrSpace() AddrSpace {

func (p *Package) GetCoverage() AddrCoverage {
p.disAsmCoverage.Do(func() {
this := p.GetAddrSpace().ToCoverage()
this := p.GetAddrSpace().ToDirtyCoverage()
subs := lo.Map(maps.Values(p.SubPackages), func(p *Package, _ int) AddrCoverage {
return p.GetCoverage()
})
p.disAsmCoverage.Set(MergeCoverage(append([]AddrCoverage{this}, subs...)...))
merged, _ := MergeCoverage(append(subs, this))
p.disAsmCoverage.Set(merged)
})
return p.disAsmCoverage.Get()
}
11 changes: 7 additions & 4 deletions internal/entity/space.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,12 @@ func MergeAddrSpace(others ...AddrSpace) AddrSpace {
return ret
}

// ToCoverage get the disAsmCoverage of the current address space
func (a AddrSpace) ToCoverage() AddrCoverage {
return lo.MapToSlice(a, func(k uint64, v *Addr) AddrPos {
return v.AddrPos
// ToDirtyCoverage get the disAsmCoverage of the current address space
func (a AddrSpace) ToDirtyCoverage() AddrCoverage {
return lo.MapToSlice(a, func(k uint64, v *Addr) *CoveragePart {
return &CoveragePart{
Pos: v.AddrPos,
Addrs: []*Addr{v},
}
})
}
33 changes: 20 additions & 13 deletions internal/knowninfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package internal

import (
"debug/gosym"
"fmt"
"github.com/Zxilly/go-size-analyzer/internal/entity"
"github.com/Zxilly/go-size-analyzer/internal/utils"
"github.com/Zxilly/go-size-analyzer/internal/wrapper"
Expand Down Expand Up @@ -45,7 +46,7 @@ func (k *KnownInfo) LoadSectionMap() {
return
}

func (k *KnownInfo) AnalyzeSymbol(file *gore.GoFile) error {
func (k *KnownInfo) AnalyzeSymbol() error {
slog.Info("Analyzing symbols...")

err := k.wrapper.LoadSymbols(k.MarkSymbol)
Expand Down Expand Up @@ -95,41 +96,41 @@ func (k *KnownInfo) ExtractPackageFromSymbol(s string) string {
return utils.UglyGuess(pn)
}

func (k *KnownInfo) LoadPackages(file *gore.GoFile) error {
func (k *KnownInfo) LoadPackages() error {
slog.Info("Loading packages...")

pkgs := NewDependencies(k)
k.Deps = pkgs

pclntab, err := file.PCLNTab()
pclntab, err := k.gore.PCLNTab()
if err != nil {
return err
}

self, err := file.GetPackages()
self, err := k.gore.GetPackages()
if err != nil {
return err
}
for _, p := range self {
pkgs.Add(p, entity.PackageTypeMain, pclntab)
}

grStd, _ := file.GetSTDLib()
grStd, _ := k.gore.GetSTDLib()
for _, p := range grStd {
pkgs.Add(p, entity.PackageTypeStd, pclntab)
}

grVendor, _ := file.GetVendors()
grVendor, _ := k.gore.GetVendors()
for _, p := range grVendor {
pkgs.Add(p, entity.PackageTypeVendor, pclntab)
}

grGenerated, _ := file.GetGeneratedPackages()
grGenerated, _ := k.gore.GetGeneratedPackages()
for _, p := range grGenerated {
pkgs.Add(p, entity.PackageTypeGenerated, pclntab)
}

grUnknown, _ := file.GetUnknown()
grUnknown, _ := k.gore.GetUnknown()
for _, p := range grUnknown {
pkgs.Add(p, entity.PackageTypeUnknown, pclntab)
}
Expand Down Expand Up @@ -161,24 +162,30 @@ func (k *KnownInfo) RequireModInfo() {

func (k *KnownInfo) CollectCoverage() {
// load coverage for pclntab and symbol
pclntabCov := k.KnownAddr.Pclntab.ToCoverage()
pclntabCov := k.KnownAddr.Pclntab.ToDirtyCoverage()

// merge all
covs := make([]entity.AddrCoverage, 0, len(k.Deps.topPkgs)+2)
for _, p := range k.Deps.topPkgs {
covs = append(covs, p.GetCoverage())
}
covs = append(covs, pclntabCov, k.KnownAddr.SymbolCoverage)
k.Coverage = entity.MergeCoverage(covs...)

var err *entity.ErrAddrCoverageConflict
k.Coverage, err = entity.MergeCoverage(covs)
if err != nil {
slog.Error(fmt.Sprintf("Fatal error: %s", err.Error()))
os.Exit(1)
}
}

func (k *KnownInfo) CalculateSectionSize() {
for _, section := range k.Sects.Sections {
size := uint64(0)
for _, addr := range k.Coverage {
// calculate the overlapped size
start := max(section.Addr, addr.Addr)
end := min(section.Addr+section.Size, addr.Addr+addr.Size)
start := max(section.Addr, addr.Pos.Addr)
end := min(section.Addr+section.Size, addr.Pos.Addr+addr.Pos.Size)
if start < end {
size += end - start
}
Expand All @@ -192,7 +199,7 @@ func (k *KnownInfo) CalculatePackageSize() {
size := uint64(0)

for _, addr := range p.GetCoverage() {
size += addr.Size
size += addr.Pos.Size
}
for _, fn := range p.GetFunctions(true) {
size += fn.Size
Expand Down

0 comments on commit 84e7259

Please sign in to comment.