Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support metadata for symbol lookup #15

Merged
merged 2 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions rvgo/cmd/load_elf.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ func LoadELF(ctx *cli.Context) error {
if err != nil {
return fmt.Errorf("failed to patch VM")
}
meta, err := MakeMetadata(elfProgram)
if err != nil {
return fmt.Errorf("failed to compute program metadata: %w", err)
}
if err := jsonutil.WriteJSON[*Metadata](ctx.Path(cannon.LoadELFMetaFlag.Name), meta, OutFilePerm); err != nil {
return fmt.Errorf("failed to output metadata: %w", err)
}
return jsonutil.WriteJSON[*fast.VMState](ctx.Path(cannon.LoadELFOutFlag.Name), state, OutFilePerm)
}

Expand All @@ -38,5 +45,6 @@ var LoadELFCommand = &cli.Command{
Flags: []cli.Flag{
cannon.LoadELFPathFlag,
cannon.LoadELFOutFlag,
cannon.LoadELFMetaFlag,
},
}
66 changes: 66 additions & 0 deletions rvgo/cmd/metadata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package cmd

import (
"debug/elf"
"fmt"
"sort"
)

type Symbol struct {
Name string `json:"name"`
Start uint64 `json:"start"`
Size uint64 `json:"size"`
}

type Metadata struct {
Symbols []Symbol `json:"symbols"`
}

func MakeMetadata(elfProgram *elf.File) (*Metadata, error) {
syms, err := elfProgram.Symbols()
if err != nil {
return nil, fmt.Errorf("failed to load symbols table: %w", err)
}
// Make sure the table is sorted, Go outputs mostly sorted data, except some internal functions
sort.Slice(syms, func(i, j int) bool {
return syms[i].Value < syms[j].Value
})
out := &Metadata{Symbols: make([]Symbol, len(syms))}
for i, s := range syms {
out.Symbols[i] = Symbol{Name: s.Name, Start: s.Value, Size: s.Size}
}
return out, nil
}

func (m *Metadata) LookupSymbol(addr uint64) string {
if len(m.Symbols) == 0 {
return "!unknown"
}
// find first symbol with higher start. Or n if no such symbol exists
i := sort.Search(len(m.Symbols), func(i int) bool {
return m.Symbols[i].Start > addr
})
if i == 0 {
return "!start"
}
out := &m.Symbols[i-1]
if out.Start+out.Size < addr { // addr may be pointing to a gap between symbols
return "!gap"
}
return out.Name
}

func (m *Metadata) SymbolMatcher(name string) func(addr uint64) bool {
for _, s := range m.Symbols {
if s.Name == name {
start := s.Start
end := s.Start + s.Size
return func(addr uint64) bool {
return addr >= start && addr < end
}
}
}
return func(addr uint64) bool {
return false
}
}
4 changes: 0 additions & 4 deletions rvgo/cmd/process_preimage_oracle.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,6 @@ func (p *ProcessPreimageOracle) GetPreimage(k [32]byte) []byte {
return p.pCl.Get(rawKey(k))
}

func (p *ProcessPreimageOracle) GetCmd() *exec.Cmd {
return p.cmd
}

func (p *ProcessPreimageOracle) Start() error {
if p.cmd == nil {
return nil
Expand Down
18 changes: 15 additions & 3 deletions rvgo/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,25 @@ func Run(ctx *cli.Context) error {
snapshotAt := ctx.Generic(cannon.RunSnapshotAtFlag.Name).(*cannon.StepMatcherFlag).Matcher()
infoAt := ctx.Generic(cannon.RunInfoAtFlag.Name).(*cannon.StepMatcherFlag).Matcher()

var meta *Metadata
if metaPath := ctx.Path(cannon.RunMetaFlag.Name); metaPath == "" {
l.Info("no metadata file specified, defaulting to empty metadata")
meta = &Metadata{Symbols: nil} // provide empty metadata by default
} else {
if m, err := jsonutil.LoadJSON[Metadata](metaPath); err != nil {
return fmt.Errorf("failed to load metadata: %w", err)
} else {
meta = m
}
}

us := fast.NewInstrumentedState(state, po, outLog, errLog)
proofFmt := ctx.String(cannon.RunProofFmtFlag.Name)
snapshotFmt := ctx.String(cannon.RunSnapshotFmtFlag.Name)

stepFn := us.Step
poCmd := po.GetCmd()
if poCmd != nil {
stepFn = Guard(poCmd.ProcessState, stepFn)
if po.cmd != nil {
stepFn = Guard(po.cmd.ProcessState, stepFn)
}

start := time.Now()
Expand All @@ -148,6 +159,7 @@ func Run(ctx *cli.Context) error {
"ips", float64(step-startStep)/(float64(delta)/float64(time.Second)),
"pages", state.Memory.PageCount(),
"mem", state.Memory.Usage(),
"name", meta.LookupSymbol(state.PC),
)
}

Expand Down
Loading