From af893c8a7b58060faaafaa545ac4d1e8874a3b44 Mon Sep 17 00:00:00 2001 From: Craig Hesling Date: Wed, 25 Apr 2018 01:29:49 -0400 Subject: [PATCH 1/3] Fixes the edge case on the last function symbol that has a nil datap --- forceexport.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/forceexport.go b/forceexport.go index 73714af..5b911e5 100644 --- a/forceexport.go +++ b/forceexport.go @@ -59,6 +59,21 @@ func FindFuncWithName(name string) (uintptr, error) { for moduleData := &Firstmoduledata; moduleData != nil; moduleData = moduleData.next { for _, ftab := range moduleData.ftab { f := (*runtime.Func)(unsafe.Pointer(&moduleData.pclntable[ftab.funcoff])) + + // (*Func).Name() assumes that the *Func was created by some exported + // method that would have returned a nil *Func pointer IF the + // desired function's datap resolves to nil. + // (a.k.a. if findmoduledatap(pc) returns nil) + // Since the last element of the moduleData.ftab has a datap of nil + // (from experimentation), .Name() Seg Faults on the last element. + // + // If we instead ask the external function FuncForPc to fetch + // our *Func object, it will check the datap first and give us + // a proper nil *Func, that .Name() understands. + // The down side of doing this is that internally, the + // findmoduledatap(pc) function is called twice for every element + // we loop over. + f = runtime.FuncForPC(f.Entry()) if f.Name() == name { return f.Entry(), nil } From c453a2d8bacf5220393a99021007d7e40a4cb821 Mon Sep 17 00:00:00 2001 From: Craig Hesling Date: Wed, 25 Apr 2018 01:30:41 -0400 Subject: [PATCH 2/3] Updated Moduledata to look more like go 1.10's ModuleData --- forceexport.go | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/forceexport.go b/forceexport.go index 5b911e5..23dfda7 100644 --- a/forceexport.go +++ b/forceexport.go @@ -101,19 +101,50 @@ type Moduledata struct { bss, ebss uintptr noptrbss, enoptrbss uintptr end, gcdata, gcbss uintptr + types, etypes uintptr - // Original type was []*_type - typelinks []interface{} + textsectmap []Textsect + typelinks []int32 // offsets from types + // Original type was []*itab + itablinks []*struct{} + + ptab []PtabEntry + + pluginpath string + // Original type was []modulehash + pkghashes []interface{} modulename string // Original type was []modulehash modulehashes []interface{} + hasmain uint8 // 1 if module contains the main function, 0 otherwise + gcdatamask, gcbssmask Bitvector + // Original type was map[typeOff]*_type + typemap map[typeOff]*struct{} + + bad bool // module failed to load and should be ignored + next *Moduledata } +type Textsect struct { + vaddr uintptr // prelinked section vaddr + length uintptr // section length + baseaddr uintptr // relocated section address +} + +type nameOff int32 +type typeOff int32 +type textOff int32 + +type PtabEntry struct { + name nameOff + typ typeOff +} + type Functab struct { entry uintptr funcoff uintptr From 37ebe5b408f3c0e25d88a4b7980d633b88cb84a0 Mon Sep 17 00:00:00 2001 From: Craig Hesling Date: Wed, 25 Apr 2018 01:34:03 -0400 Subject: [PATCH 3/3] Updated README.MD to indicate working status on GNU/Linux Go 1.10rc2 --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7e415e0..2c6aa04 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,10 @@ by name. As you might expect, this library is **unsafe** and **fragile** and probably shouldn't be used in production. See "Use cases and pitfalls" below. -It has only been tested on Mac OS X with Go 1.6. If you find that it works or -breaks on other platforms, feel free to submit a pull request with a fix and/or -an update to this paragraph. +It has only been tested on Mac OS X with Go 1.6 and on GNU/Linux with +Go 1.10rc2. +If you find that it works or breaks on other platforms, feel free to submit +a pull request with a fix and/or an update to this paragraph. ## Installation