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 path handle on multi platform #81

Merged
merged 5 commits into from
Jan 31, 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
15 changes: 9 additions & 6 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: build
name: Build and tests

on:
push:
Expand All @@ -7,23 +7,26 @@ on:
branches: [ develop, master ]

jobs:

build:
runs-on: ubuntu-latest
build_and_tests:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
submodules: true

- name: Set up Go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: ">=1.21.0"

- name: Build
run: go build -o a

- name: Test
shell: bash
run: go test -timeout 1800s -v -race -coverprofile=coverage.txt -covermode=atomic -tags slow_test

- name: Codecov
Expand Down
20 changes: 10 additions & 10 deletions file.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
"fmt"
"io"
"os"
"path/filepath"
"path"
"sort"
"sync"
)
Expand Down Expand Up @@ -237,7 +237,7 @@ func (f *GoFile) enumPackages() error {
p, ok := packages[n.PackageName()]
if !ok {
p = &Package{
Filepath: filepath.Dir(n.BaseName()),
Filepath: "", // to be filled later by dir(PCToLine())
Functions: make([]*Function, 0),
Methods: make([]*Method, 0),
}
Expand All @@ -258,11 +258,6 @@ func (f *GoFile) enumPackages() error {
}

p.Methods = append(p.Methods, m)

if !ok && needFilepath {
fp, _, _ := tab.PCToLine(m.Offset)
p.Filepath = filepath.Dir(fp)
}
} else {
f := &Function{
Name: n.BaseName(),
Expand All @@ -271,10 +266,15 @@ func (f *GoFile) enumPackages() error {
PackageName: n.PackageName(),
}
p.Functions = append(p.Functions, f)
}

if !ok && needFilepath {
fp, _, _ := tab.PCToLine(f.Offset)
p.Filepath = filepath.Dir(fp)
if needFilepath {
fp, _, _ := tab.PCToLine(n.Entry)
switch fp {
case "<autogenerated>", "":
p.Filepath = fp
default:
p.Filepath = path.Dir(fp)
}
}
}
Expand Down
31 changes: 18 additions & 13 deletions goroot.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package gore

import (
"bytes"
"errors"
"fmt"
"reflect"
"strings"
Expand All @@ -28,7 +29,7 @@ import (
)

func tryFromGOROOT(f *GoFile) (string, error) {
// Check for non supported architectures.
// Check for non-supported architectures.
if f.FileInfo.Arch != Arch386 && f.FileInfo.Arch != ArchAMD64 {
return "", nil
}
Expand Down Expand Up @@ -59,9 +60,9 @@ pkgLoop:
}
}

// Check if the functions was found
// Check if the functions were found
if fcn == nil {
// If we can't find the function there is nothing to do.
// If we can't find the function, there is nothing to do.
return "", ErrNoGoRootFound
}
// Get the raw hex.
Expand Down Expand Up @@ -92,13 +93,13 @@ pkgLoop:
}
arg := inst.Args[1].(x86asm.Mem)

// First assume that the address is a direct addressing.
// First, assume that the address is a direct addressing.
addr := arg.Disp
if arg.Base == x86asm.EIP || arg.Base == x86asm.RIP {
// If the addressing is based on the instruction pointer, fix the address.
addr = addr + int64(fcn.Offset) + int64(s)
} else if arg.Base == 0 && arg.Disp > 0 {
// In order to support x32 direct addressing
// To support x32 direct addressing
} else {
continue
}
Expand Down Expand Up @@ -182,7 +183,7 @@ pkgLoop:
}
addr = addr + fcn.Offset + uint64(s)
} else if arg.Base == 0 && arg.Disp > 0 {
// In order to support x32 direct addressing
// To support x32 direct addressing
} else {
continue
}
Expand All @@ -208,7 +209,7 @@ pkgLoop:
}

func tryFromTimeInit(f *GoFile) (string, error) {
// Check for non supported architectures.
// Check for non-supported architectures.
if f.FileInfo.Arch != Arch386 && f.FileInfo.Arch != ArchAMD64 {
return "", nil
}
Expand Down Expand Up @@ -239,7 +240,7 @@ pkgLoop:
}
}

// Check if the functions was found
// Check if the functions were found
if fcn == nil {
// If we can't find the function there is nothing to do.
return "", ErrNoGoRootFound
Expand Down Expand Up @@ -276,13 +277,13 @@ pkgLoop:
}
arg := inst.Args[1].(x86asm.Mem)

// First assume that the address is a direct addressing.
// First, assume that the address is a direct addressing.
addr := arg.Disp
if arg.Base == x86asm.EIP || arg.Base == x86asm.RIP {
// If the addressing is based on the instruction pointer, fix the address.
addr = addr + int64(fcn.Offset) + int64(s)
} else if arg.Base == 0 && arg.Disp > 0 {
// In order to support x32 direct addressing
// To support x32 direct addressing
} else {
continue
}
Expand Down Expand Up @@ -332,19 +333,19 @@ func findGoRootPath(f *GoFile) (string, error) {
if goroot != "" {
return goroot, nil
}
if err != nil && err != ErrNoGoRootFound {
if err != nil && !errors.Is(err, ErrNoGoRootFound) {
return "", err
}

goroot, err = tryFromTimeInit(f)
if goroot != "" {
return goroot, nil
}
if err != nil && err != ErrNoGoRootFound {
if err != nil && !errors.Is(err, ErrNoGoRootFound) {
return "", err
}

// Try determine from std lib package paths.
// Try to determine from std lib package paths.
pkg, err := f.GetSTDLib()
if err != nil {
return "", fmt.Errorf("error when getting standard library packages: %w", err)
Expand All @@ -358,6 +359,10 @@ func findGoRootPath(f *GoFile) (string, error) {
if strings.HasSuffix(v.Filepath, subpath) {
return strings.TrimSuffix(v.Filepath, subpath), nil
}
subpathWin := fmt.Sprintf("\\src\\%s", v.Name)
if strings.HasSuffix(v.Filepath, subpathWin) {
return strings.TrimSuffix(v.Filepath, subpathWin), nil
}
}

return "", ErrNoGoRootFound
Expand Down
4 changes: 3 additions & 1 deletion goroot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ func TestExtractGoRoot(t *testing.T) {
// Golden folder does not exist
t.Skip("No golden files")
}
var expectGoRoot string = "/usr/local/go"

const expectGoRoot = "/usr/local/go"

for _, test := range goldFiles {
t.Run("get goroot form "+test, func(t *testing.T) {
r := require.New(t)
Expand Down
47 changes: 27 additions & 20 deletions package.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package gore

import (
"fmt"
"path/filepath"
"path"
"runtime/debug"
"sort"
"strings"
Expand Down Expand Up @@ -50,7 +50,7 @@ func (f *GoFile) GetSourceFiles(p *Package) []*SourceFile {
getSourceFile := func(fileName string) *SourceFile {
sf, ok := tmp[fileName]
if !ok {
return &SourceFile{Name: filepath.Base(fileName)}
return &SourceFile{Name: path.Base(fileName)}
}
return sf
}
Expand Down Expand Up @@ -118,8 +118,8 @@ type PackageClassifier interface {
func NewPathPackageClassifier(mainPkgFilepath string) *PathPackageClassifier {
return &PathPackageClassifier{
mainFilepath: mainPkgFilepath, mainFolders: []string{
filepath.Dir(mainPkgFilepath),
mainPkgFilepath,
path.Dir(mainPkgFilepath),
path.Clean(mainPkgFilepath),
},
}
}
Expand Down Expand Up @@ -160,11 +160,11 @@ func (c *PathPackageClassifier) Classify(pkg *Package) PackageClass {
return ClassVendor
}

parentFolder := filepath.Dir(pkg.Filepath)
parentFolder := path.Dir(pkg.Filepath)

if strings.HasPrefix(pkg.Filepath, c.mainFilepath+"/vendor/") ||
strings.HasPrefix(pkg.Filepath, filepath.Dir(c.mainFilepath)+"/vendor/") ||
strings.HasPrefix(pkg.Filepath, filepath.Dir(filepath.Dir(c.mainFilepath))+"/vendor/") {
strings.HasPrefix(pkg.Filepath, path.Dir(c.mainFilepath)+"/vendor/") ||
strings.HasPrefix(pkg.Filepath, path.Dir(path.Dir(c.mainFilepath))+"/vendor/") {
return ClassVendor
}

Expand All @@ -186,14 +186,13 @@ func (c *PathPackageClassifier) Classify(pkg *Package) PackageClass {
}
}

// If the path does not contain the "vendor" in path but has the main package folder name, assume part of main.
// If the path does not contain the "vendor" in a path but has the main package folder name, assume part of main.
if !strings.Contains(pkg.Filepath, "vendor/") &&
(filepath.Base(filepath.Dir(pkg.Filepath)) == filepath.Base(c.mainFilepath)) {
(path.Base(path.Dir(pkg.Filepath)) == path.Base(c.mainFilepath)) {
return ClassMain
}

// Special case for entry point package.
if pkg.Name == "" && filepath.Base(pkg.Filepath) == "runtime" {
if pkg.Name == "" && path.Base(pkg.Filepath) == "runtime" {
return ClassSTD
}

Expand All @@ -203,12 +202,12 @@ func (c *PathPackageClassifier) Classify(pkg *Package) PackageClass {
}

// Check if it's the main parent package.
if pkg.Name != "" && !strings.Contains(pkg.Name, "/") && strings.Contains(c.mainFilepath, pkg.Name) {
if pkg.Name != "" && (!strings.Contains(pkg.Name, "/") && strings.Contains(c.mainFilepath, pkg.Name)) {
return ClassMain
}

// At this point, if the main package has a file path of "command-line-arguments" and we haven't figured out
// what class it is. We assume it being part of the main package.
// what class it is. We assume it is part of the main package.
if c.mainFilepath == "command-line-arguments" {
return ClassMain
}
Expand All @@ -220,23 +219,31 @@ func (c *PathPackageClassifier) Classify(pkg *Package) PackageClass {
// Otherwise, false is retuned.
func IsStandardLibrary(pkg string) bool {
_, ok := stdPkgs[pkg]
return ok
if ok {
return true
}

// Detect regexp.(*onePassInst).regexp/syntax type packages
tmp := strings.Split(pkg, ".")[0]
if len(tmp) < len(pkg) && IsStandardLibrary(tmp) {
return true
}

return false
}

func isGeneratedPackage(pkg *Package) bool {
// Detect regexp.(*onePassInst).regexp/syntax type packages
tmp := strings.Split(pkg.Name, ".")[0]
if len(tmp) < len(pkg.Name) && IsStandardLibrary(tmp) {
if pkg.Filepath == "<autogenerated>" {
return true
}

// Special case for no package name and path of ".".
if pkg.Name == "" && pkg.Filepath == "." {
// Special case for no package name and path of "".
if pkg.Name == "" && pkg.Filepath == "" {
return true
}

// Some internal stuff, classify it as Generated
if pkg.Filepath == "." && (pkg.Name == "__x86" || pkg.Name == "__i686") {
if pkg.Filepath == "" && (pkg.Name == "__x86" || pkg.Name == "__i686") {
return true
}

Expand Down
Loading