golang从编译文件中获取所有文件包

时间:2016-05-16 09:52:45

标签: go refactoring runtime

我正在尝试获取编译期间使用的所有源文件。 函数runtime.Caller()和panic及其stacktrace显示此信息。

我需要这样的东西

func fetchUsedFiles() []string {
    ....
}
func main() {
    log.Println("Used Files",fetchUsedFiles())
}

UPD:

所有我需要的是以某种方式读取“runtime.firstmoduledata”变量内容。但它不是导出变量。

1 个答案:

答案 0 :(得分:1)

实际上我已经将VonC答案和我的运行时approcah结合起来了。

所有需要的数据存储在runtime.firstmoduledata - struct但不会导出。为了从那里读取数据,我再次读取了我的可执行文件(仅针对ELF实现),找到此符号并执行其他部分,如runtime.Caller()函数。此方法不可移植,可以通过运行时库中的更改来解决,但它可以正常工作。

selfReflect函数使用运行时lib

中的私有类型的副本

https://github.com/martende/restartable/blob/master/restartable.go#L208

func selfReflect(filename string) ([]string,error) {
    f,err := elf.Open(filename)
    if err != nil {
        return nil,err
    }
    defer f.Close()
    syms,err := f.Symbols()
    if err != nil {
        return nil,err
    }
    var modSym elf.Symbol
    var modSymFound = false
    for _,v := range syms {
        if v.Name == "runtime.firstmoduledata" {
            modSym = v
            modSymFound = true
            break
        }
    }
    if ! modSymFound {
        return nil,errors.New("elfparse:nosym")
    }

    var datap = (*moduledata)(unsafe.Pointer(uintptr(modSym.Value)))

    files := make([]string,0)
    for i := range datap.filetab {
        bp := &datap.pclntable[datap.filetab[i]]
        file := C.GoString( (*C.char) (unsafe.Pointer(bp))  )
        if file != "<autogenerated>" && file != "@" {
            if _, err := os.Stat(file); err == nil {
                files = append(files ,file)
            }
        }
    }


    return files,nil
}