Skip to content
Open
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
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
50 changes: 48 additions & 2 deletions forceexport.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -86,19 +101,50 @@ type Moduledata struct {
bss, ebss uintptr
noptrbss, enoptrbss uintptr
end, gcdata, gcbss uintptr
types, etypes uintptr

textsectmap []Textsect
typelinks []int32 // offsets from types
// Original type was []*itab
itablinks []*struct{}

ptab []PtabEntry

// Original type was []*_type
typelinks []interface{}
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
Expand Down