Skip to content

Commit

Permalink
starting refactor to use logic similar to C++ smeagle
Browse files Browse the repository at this point in the history
Signed-off-by: vsoch <vsoch@users.noreply.github.com>
  • Loading branch information
vsoch committed Sep 22, 2021
1 parent 0397314 commit 38cf7f9
Show file tree
Hide file tree
Showing 50 changed files with 426 additions and 7,823 deletions.
38 changes: 4 additions & 34 deletions cli/parse.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package cli

import (
"fmt"
"log"

"github.com/DataDrake/cli-ng/v2/cmd"
"github.com/vsoch/gosmeagle/gosrc/cmd/objfile"
"github.com/vsoch/gosmeagle/corpus"
)

// Args and flags for generate
Expand All @@ -28,36 +25,9 @@ func init() {
cmd.Register(&Parser)
}

// RunDockerfile updates one or more Dockerfile
// RunParser reads a file and creates a corpus
func RunParser(r *cmd.Root, c *cmd.Sub) {

args := c.Args.(*ParserArgs)

f, err := objfile.Open(args.Binary[0])
if err != nil {
log.Fatal(err)
}
defer f.Close()

// Try looping through entries
for _, entry := range f.Entries() {
fmt.Println(entry)
symbols, err := entry.Symbols()
if err != nil {
log.Fatalf("Issue retriving symbols from %s", args.Binary[0])
}
for _, symbol := range symbols {
fmt.Println("Name:", symbol.Name)
fmt.Println("Address:", symbol.Addr)
fmt.Println("Size:", symbol.Size)
fmt.Println("Code:", symbol.Code)
fmt.Println("Type:", symbol.Type)
fmt.Println("Binding:", symbol.Binding)
fmt.Println("Relocs:", symbol.Relocs)
}
}

// Trying looking at DWARF
// TODO how to parse this?
// fmt.Println(f.DWARF())
corpus := corpus.GetCorpus(args.Binary[0])
corpus.ToJson()
}
137 changes: 137 additions & 0 deletions corpus/corpus.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package corpus

import (
"debug/dwarf"
// "encoding/json"
"fmt"
"github.com/vsoch/gosmeagle/descriptor"
"github.com/vsoch/gosmeagle/parsers/file"
"github.com/vsoch/gosmeagle/parsers/x86_64"
"log"
)

// A corpus holds a library name, a list of Functions and variables
type Corpus struct {
Library string `json:"library"`
Functions []descriptor.FunctionDescription `json:"functions"`
Variables []string `json:"variables"`
}

// Get a corpus from a filename
func GetCorpus(filename string) Corpus {

corpus := Corpus{Library: filename}

f, err := file.Open(filename)
if err != nil {
log.Fatal(err)
}
defer f.Close()

// Populate the corpus depending on the Architecture
corpus.Parse(f)
return corpus
}

func (c *Corpus) Parse(f *file.File) {

// Parse entries based on type (function or variable)
for _, e := range f.Entries {

// These are dynamic symbol table symbols
symbols, err := e.Symbols()
if err != nil {
log.Fatalf("Issue retriving symbols from %s", c.Library)
}
for _, symbol := range symbols {

// If we have a function, parse function
if symbol.Type == "STT_FUNC" {
c.parseFunction(f, symbol)
}

// TODO if it's a variable AND has global linkage, parse

//fmt.Println("Name:", symbol.Name)
//fmt.Println("Address:", symbol.Address)
//fmt.Println("Size:", symbol.Size)
//fmt.Println("Code:", symbol.Code)
//fmt.Println("Type:", symbol.Type)
//fmt.Println("Binding:", symbol.Binding)
//fmt.Println("Relocs:", symbol.Relocations)
}

dwf, err := e.Dwarf()
rdr := dwf.Reader()
for entry, err := rdr.Next(); entry != nil; entry, err = rdr.Next() {
if err != nil {
log.Fatalf("error reading DWARF: %v", err)
}
switch entry.Tag {
case dwarf.TagTypedef:
if _, ok := entry.Val(dwarf.AttrName).(string); ok {
//fmt.Println(name)
}
}
}
}
}

// parse a dynamic function symbol
func (c *Corpus) parseFunction(f *file.File, symbol file.Symbol) {

fmt.Println(symbol)
switch f.GoArch() {
case "amd64":
{
c.Functions = append(c.Functions, x86_64.ParseFunction(f, symbol))
// c.Functions = append(c.Functions, x86.ParseReturnValue(symbol)
}
default:
fmt.Printf("Unsupported architecture %s\n", f.GoArch())
}
}

// Serialize corpus to json
func (c *Corpus) ToJson() {

//outJson, _ := json.Marshal(c)
//output := string(outJson)
//fmt.Println(output)
}

/* parse a function for parameters and abi location
void Corpus::parseFunctionABILocation(Dyninst::SymtabAPI::Symbol *symbol,
Dyninst::Architecture arch) {
switch (arch) {
case Dyninst::Architecture::Arch_x86_64:
break;
case Dyninst::Architecture::Arch_aarch64:
break;
case Dyninst::Architecture::Arch_ppc64:
break;
default:
throw std::runtime_error{"Unsupported architecture: " + std::to_string(arch)};
break;
}
}
// parse a variable (global) for parameters and abi location
void Corpus::parseVariableABILocation(Dyninst::SymtabAPI::Symbol *symbol,
Dyninst::Architecture arch) {
switch (arch) {
case Dyninst::Architecture::Arch_x86_64:
variables.emplace_back(x86_64::parse_variable(symbol));
break;
case Dyninst::Architecture::Arch_aarch64:
break;
case Dyninst::Architecture::Arch_ppc64:
break;
default:
throw std::runtime_error{"Unsupported architecture: " + std::to_string(arch)};
break;
}
}
}*/
24 changes: 24 additions & 0 deletions descriptor/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package descriptor

// A Parameter interface must implement these functions

type Parameter interface {
Name() string
TypeName() string
ClassName() string
Direction() string
Location() string
SizeBytes() int
ToJson()
}

type FunctionDescription struct {
Parameters []Parameter
ReturnValue Parameter
Name string `json:"name"`
}

type VariableDescription struct {
Name string `json:"name"`
Type string `json:"type"`
}

0 comments on commit 38cf7f9

Please sign in to comment.