当前位置: 首页 > 科技观察

Go语言程序符号重命名

时间:2023-03-12 19:44:50 科技观察

Go程序源码中,关键字、接口、类型、常量、变量、方法、函数、字段、标签等的名称都可以称为符号。在Go可执行程序中,符号表主要包含两类符号:数据对象(Dataobject)函数(Function)一般来说(不是绝对的),在将源代码编译成可执行程序的过程中,关键字,局部变量和标签将被转化为指令,数据或消失,而不是符号接口,类型和全局常量将被保存为不可变数据,而不是符号函数,方法,全局变量和全局常量将被重命名,存储在符号中table本文主要总结编译时函数、方法、全局变量的一般重命名规则,不讨论内联优化、闭包、非空接口、编译器生成等复杂情况。规则Go1.18之前符号重命名的常用规则列表如下:函数名.funcN.N包名.(*type).函数名包名.(*type).函数名.funcN包名.(*type).函数名.funcN.N模块名/包名.变量名模块名/包名.函数名模块名/包名.函数名.funcN模块名/包名.函数名.funcN.N模块名/包名.type.函数名模块名/包名.type.函数名.funcN模块名/packagename.type.functionname.funcN.Nmodulename/packagename.(*type).functionnamemodulename/packagename.(*type).函数名.funcN模块名/包名.(*type).函数名.funcN.N包名.init包名.init.N模块名/包名.init模块名/包名.init.N以上规则列出的太详细了,主要是包含了太多的匿名函数命名规则;本文将缩小分类粒度进行归纳:普通函数匿名函数方法全局常量模块初始化函数环境OS:Ubuntu20.04.2LTS;x86_64Go:goversiongo1.16.2linux/amd64代码清单完整代码已上传至Github仓库:https://github.com/fooree/go-names目录和文件结构如下:go.modmodulegithub.com/fooree/go-namesgo1.16main.gopackagemainimport("debug/elf""fmt""github.com/fooree/go-names/internal""github.com/fooree/go-names/internal/foo""github.com/fooree/go-names/internal/foo/ree""os""路径/filepath""reflect""sort""strings""time")//go:noinlinefuncanonymousType(){t:=reflect.TypeOf(struct{Namestring}{Name:"Jack",})fmt.Printf("name=%s,string=%s,addres=%p\n",t.Name(),t.String(),t)}funcmain(){anonymousType()ree.Run()foo.Y.Foo()internal.X.Foo()name,_:=filepath.Abs??(os.Args[0])file,err:=elf.Open(name)iferr!=nil{panic(err)}deferfunc(){_=file.Close()}()symbols,err:=file.Symbols()iferr!=nil{panic(err)}slice:=make([]string,0,100)for_,symbol:=rangesymbols{constmodule="github.com/fooree/go-names"constname="main"ifstrings.HasPrefix(symbol.Name,module)||strings.HasPrefix(symbol.Name,name){slice=append(slice,symbol.Name)}}gofunc(){sort.Slice(slice,func(i,jint)bool{returnsslice[i]