如何提取自己的符号表

huangapple go评论72阅读模式
英文:

How to extract own symbol table

问题

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

如果一般情况下无法实现,但在Linux或ELF二进制文件上可以实现,那也是一个选择。

英文:

I'm looking at the package debug/gosym which has a type gosym.Table, allegedly a symbol table of a Go executable. Unfortunately, I don't see any ways of extracting the sysmbol table from the running program (Go reflection is lacking, and I need more info than it can provide, specifically, the names of exported symbols).

If this isn't possible generally, but can be done on Linux / for ELF binaries, that's an option too.

答案1

得分: 1

获取当前运行的进程的符号表在Go语言中(Linux):

var symTable *gosym.Table
var symTableLoadFailed bool

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

	// 首先尝试从内存中加载
	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 {
		// 如果失败,则从磁盘加载副本
		exePath, err := os.Executable()
		if err != nil {
			symTableLoadFailed = true
			log.Printf("subvert: 找不到可执行文件:%v", err)
			return
		}

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

	lineTableData, err := exe.Section(".gopclntab").Data()
	if err != nil {
		symTableLoadFailed = true
		log.Printf("subvert: 读取 .gopclntab 数据失败:%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: 创建符号表失败:%v", err)
		symTable = nil
	}
}

也可以在这里找到实现:https://github.com/kstenerud/go-subvert/blob/master/subvert.go#L165

英文:

To get the symbol table of the currently running process in 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
	}
}

Also implemented here: https://github.com/kstenerud/go-subvert/blob/master/subvert.go#L165

答案2

得分: 0

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

英文:

To get the symbol table of the current process you can use my Elfie package. It provides a Table function that will parse the symbol table from memory and provide you a gosym.Table to work with. It currently only works for ELF binaries, and is highly unsafe, but give it a shot!

huangapple
  • 本文由 发表于 2017年3月2日 19:58:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/42554900.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定