如何提取自己的符号表

时间:2017-03-02 11:58:17

标签: go reflection symbols

我正在查看类型为debug/gosym的包gosym.Table,据称是Go可执行文件的符号表。不幸的是,我没有看到任何从正在运行的程序中提取sysmbol表的方法(缺少Go反射,我需要的信息比它提供的更多,特别是导出符号的名称)。

如果这种情况一般不可能,但可以在Linux / ELF二进制文件上完成,那也是一种选择。

2 个答案:

答案 0 :(得分:0)

要获取当前进程的符号表,可以使用我的Elfie软件包。它提供了一个Table函数,该函数将从内存中解析符号表并为您提供一个gosym.Table来使用。它目前仅适用于ELF二进制文件,并且非常不安全,但是请尝试一下!

答案 1 :(得分:0)

要获取go(Linux)中当前正在运行的进程的符号表:

var symTable *gosym.Table
var symTableLoadFailed bool

func loadSymbolTableLinux() {
    if symTable != nil || symTableLoadFailed {
        return
    }

    // Try to load from memory first
    const elfStartAddress = uintptr(0x400000)
    const maxSize = 0x10000000
    processMemory := (*[maxSize]byte)(unsafe.Pointer(elfStartAddress))[:maxSize:maxSize]
    exe, err := elf.NewFile(bytes.NewReader(processMemory))
    if err != nil {
        // Failing that, load a copy from disk
        exePath, err := os.Executable()
        if err != nil {
            symTableLoadFailed = true
            log.Printf("subvert: Error finding executable: %v", err)
            return
        }

        exe, err = elf.Open(exePath)
        if err != nil {
            symTableLoadFailed = true
            log.Printf("subvert: Error opening %v: %v", exePath, err)
            return
        }
    }
    defer exe.Close()

    lineTableData, err := exe.Section(".gopclntab").Data()
    if err != nil {
        symTableLoadFailed = true
        log.Printf("subvert: Error reading .gopclntab data: %v", err)
        return
    }

    addr := exe.Section(".text").Addr
    lineTable := gosym.NewLineTable(lineTableData, addr)
    symTable, err = gosym.NewTable([]byte{}, lineTable)
    if err != nil {
        symTableLoadFailed = true
        log.Printf("subvert: Error creating symbol table: %v", err)
        symTable = nil
    }
}

也在此处实现:https://github.com/kstenerud/go-subvert/blob/master/subvert.go#L165