github.com/pkujhd/goloader@v0.0.0-20240411034752-1a28096bd7bd/ld.go (about)

     1  package goloader
     2  
     3  import (
     4  	"cmd/objfile/sys"
     5  	"encoding/binary"
     6  	"errors"
     7  	"fmt"
     8  	"runtime"
     9  	"strings"
    10  	"sync"
    11  	"unsafe"
    12  
    13  	"github.com/pkujhd/goloader/constants"
    14  	"github.com/pkujhd/goloader/obj"
    15  	"github.com/pkujhd/goloader/objabi/funcalign"
    16  	"github.com/pkujhd/goloader/objabi/symkind"
    17  	"github.com/pkujhd/goloader/stackobject"
    18  )
    19  
    20  // ourself defined struct
    21  // code segment
    22  type codeSeg struct {
    23  	codeByte []byte
    24  	codeBase int
    25  	length   int
    26  	maxLen   int
    27  	codeOff  int
    28  }
    29  
    30  // data segment
    31  type dataSeg struct {
    32  	dataByte     []byte
    33  	dataBase     int
    34  	length       int
    35  	maxLen       int
    36  	dataLen      int
    37  	noptrdataLen int
    38  	bssLen       int
    39  	noptrbssLen  int
    40  	dataOff      int
    41  }
    42  
    43  type segment struct {
    44  	codeSeg
    45  	dataSeg
    46  }
    47  
    48  type gcData struct {
    49  	gcdata []byte
    50  	gcbss  []byte
    51  }
    52  
    53  type CodeModule struct {
    54  	segment
    55  	gcData
    56  	Syms      map[string]uintptr
    57  	stringMap map[string]*string
    58  	module    *moduledata
    59  }
    60  
    61  type LinkerData struct {
    62  	Code      []byte
    63  	Data      []byte
    64  	Noptrdata []byte
    65  	Bss       []byte
    66  	Noptrbss  []byte
    67  }
    68  
    69  type Linker struct {
    70  	LinkerData
    71  	SymMap        map[string]*obj.Sym
    72  	ObjSymbolMap  map[string]*obj.ObjSymbol
    73  	NameMap       map[string]int
    74  	StringMap     map[string]*string
    75  	Filetab       []uint32
    76  	Pclntable     []byte
    77  	Funcs         []*_func
    78  	Packages      []*obj.Pkg
    79  	Arch          *sys.Arch
    80  	CUOffset      int32
    81  	AdaptedOffset bool
    82  }
    83  
    84  var (
    85  	modules     = make(map[interface{}]bool)
    86  	modulesLock sync.Mutex
    87  )
    88  
    89  // initialize Linker
    90  func initLinker() *Linker {
    91  	linker := &Linker{
    92  		SymMap:        make(map[string]*obj.Sym),
    93  		ObjSymbolMap:  make(map[string]*obj.ObjSymbol),
    94  		NameMap:       make(map[string]int),
    95  		StringMap:     make(map[string]*string),
    96  		CUOffset:      0,
    97  		AdaptedOffset: false,
    98  	}
    99  	linker.Pclntable = make([]byte, PCHeaderSize)
   100  	return linker
   101  }
   102  
   103  func (linker *Linker) initPcHeader() {
   104  	pcheader := (*pcHeader)(unsafe.Pointer(&linker.Pclntable[0]))
   105  	pcheader.magic = magic
   106  	pcheader.minLC = uint8(linker.Arch.MinLC)
   107  	pcheader.ptrSize = uint8(linker.Arch.PtrSize)
   108  }
   109  
   110  func (linker *Linker) addFiles(files []string) {
   111  	linker.CUOffset += int32(len(files))
   112  	for _, fileName := range files {
   113  		if offset, ok := linker.NameMap[fileName]; !ok {
   114  			linker.Filetab = append(linker.Filetab, (uint32)(len(linker.Pclntable)))
   115  			linker.NameMap[fileName] = len(linker.Pclntable)
   116  			fileName = strings.TrimPrefix(fileName, FileSymPrefix)
   117  			linker.Pclntable = append(linker.Pclntable, []byte(fileName)...)
   118  			linker.Pclntable = append(linker.Pclntable, ZeroByte)
   119  		} else {
   120  			linker.Filetab = append(linker.Filetab, uint32(offset))
   121  		}
   122  	}
   123  }
   124  
   125  func (linker *Linker) addSymbols() error {
   126  	//static_tmp is 0, golang compile not allocate memory.
   127  	linker.Noptrdata = append(linker.Noptrdata, make([]byte, IntSize)...)
   128  	for _, objSym := range linker.ObjSymbolMap {
   129  		if objSym.Kind == symkind.STEXT && objSym.DupOK == false {
   130  			if _, err := linker.addSymbol(objSym.Name, nil); err != nil {
   131  				return err
   132  			}
   133  		}
   134  	}
   135  	for _, pkg := range linker.Packages {
   136  		initFuncName := getInitFuncName(pkg.PkgPath)
   137  		if _, ok := linker.ObjSymbolMap[initFuncName]; ok {
   138  			if _, err := linker.addSymbol(initFuncName, nil); err != nil {
   139  				return err
   140  			}
   141  		}
   142  	}
   143  	return nil
   144  }
   145  
   146  func (linker *Linker) adaptSymbolOffset() {
   147  	if linker.AdaptedOffset == false {
   148  		for _, sym := range linker.SymMap {
   149  			offset := 0
   150  			switch sym.Kind {
   151  			case symkind.SNOPTRDATA, symkind.SRODATA:
   152  				if !strings.HasPrefix(sym.Name, constants.TypeStringPrefix) {
   153  					offset += len(linker.Data)
   154  				}
   155  			case symkind.SBSS:
   156  				offset += len(linker.Data) + len(linker.Noptrdata)
   157  			case symkind.SNOPTRBSS:
   158  				offset += len(linker.Data) + len(linker.Noptrdata) + len(linker.Bss)
   159  			}
   160  			if sym.Offset != InvalidOffset {
   161  				sym.Offset += offset
   162  			}
   163  			if offset != 0 {
   164  				for index := range sym.Reloc {
   165  					if sym.Reloc[index].Offset != InvalidOffset {
   166  						sym.Reloc[index].Offset += offset
   167  					}
   168  				}
   169  			}
   170  		}
   171  		linker.AdaptedOffset = true
   172  	}
   173  }
   174  
   175  func (linker *Linker) addSymbol(name string, symPtr map[string]uintptr) (symbol *obj.Sym, err error) {
   176  	if symbol, ok := linker.SymMap[name]; ok {
   177  		return symbol, nil
   178  	}
   179  	objsym := linker.ObjSymbolMap[name]
   180  	symbol = &obj.Sym{Name: objsym.Name, Kind: objsym.Kind}
   181  	linker.SymMap[symbol.Name] = symbol
   182  	if symPtr != nil {
   183  		if _, ok := symPtr[name]; ok {
   184  			symbol.Offset = InvalidOffset
   185  			return symbol, nil
   186  		}
   187  	}
   188  	switch symbol.Kind {
   189  	case symkind.STEXT:
   190  		symbol.Offset = len(linker.Code)
   191  		linker.Code = append(linker.Code, objsym.Data...)
   192  		expandFunc(linker, objsym, symbol)
   193  		if len(linker.Code)-symbol.Offset < minfunc {
   194  			linker.Code = append(linker.Code, createArchNops(linker.Arch, minfunc-(len(linker.Code)-symbol.Offset))...)
   195  		}
   196  		bytearrayAlignNops(linker.Arch, &linker.Code, funcalign.GetFuncAlign(linker.Arch))
   197  		symbol.Func = &obj.Func{}
   198  		if err := linker.readFuncData(linker.ObjSymbolMap[name], symbol.Offset, symPtr); err != nil {
   199  			return nil, err
   200  		}
   201  	case symkind.SDATA:
   202  		symbol.Offset = len(linker.Data)
   203  		linker.Data = append(linker.Data, objsym.Data...)
   204  		bytearrayAlign(&linker.Data, PtrSize)
   205  	case symkind.SNOPTRDATA, symkind.SRODATA:
   206  		//because golang string assignment is pointer assignment, so store go.string constants in heap.
   207  		if strings.HasPrefix(symbol.Name, constants.TypeStringPrefix) {
   208  			data := make([]byte, len(objsym.Data))
   209  			copy(data, objsym.Data)
   210  			stringVal := string(data)
   211  			linker.StringMap[symbol.Name] = &stringVal
   212  		} else {
   213  			symbol.Offset = len(linker.Noptrdata)
   214  			linker.Noptrdata = append(linker.Noptrdata, objsym.Data...)
   215  			bytearrayAlign(&linker.Noptrdata, PtrSize)
   216  		}
   217  	case symkind.SBSS:
   218  		symbol.Offset = len(linker.Bss)
   219  		linker.Bss = append(linker.Bss, objsym.Data...)
   220  		bytearrayAlign(&linker.Bss, PtrSize)
   221  	case symkind.SNOPTRBSS:
   222  		symbol.Offset = len(linker.Noptrbss)
   223  		linker.Noptrbss = append(linker.Noptrbss, objsym.Data...)
   224  		bytearrayAlign(&linker.Noptrbss, PtrSize)
   225  	default:
   226  		return nil, fmt.Errorf("invalid symbol:%s kind:%d", symbol.Name, symbol.Kind)
   227  	}
   228  
   229  	for _, loc := range objsym.Reloc {
   230  		reloc := loc
   231  		reloc.Offset += symbol.Offset
   232  		if reloc.Epilogue.Offset != 0 {
   233  			reloc.Epilogue.Offset += symbol.Offset
   234  		}
   235  		if _, ok := linker.ObjSymbolMap[reloc.SymName]; ok {
   236  			relocSym, err := linker.addSymbol(reloc.SymName, symPtr)
   237  			if err != nil {
   238  				return nil, err
   239  			}
   240  			if relocSym != nil && len(linker.ObjSymbolMap[reloc.SymName].Data) == 0 && reloc.Size > 0 {
   241  				//static_tmp is 0, golang compile not allocate memory.
   242  				//goloader add IntSize bytes on linker.Noptrdata[0]
   243  				if reloc.Size <= IntSize {
   244  					relocSym.Offset = 0
   245  				} else {
   246  					return nil, fmt.Errorf("Symbol:%s size:%d>IntSize:%d\n", relocSym.Name, reloc.Size, IntSize)
   247  				}
   248  			}
   249  		} else {
   250  			if _, ok := linker.SymMap[reloc.SymName]; !ok && reloc.SymName != EmptyString {
   251  				relocSym := &obj.Sym{Name: reloc.SymName, Offset: InvalidOffset}
   252  				if strings.HasPrefix(reloc.SymName, constants.TypeImportPathPrefix) {
   253  					path := strings.Trim(strings.TrimPrefix(reloc.SymName, constants.TypeImportPathPrefix), ".")
   254  					relocSym.Kind = symkind.SNOPTRDATA
   255  					relocSym.Offset = len(linker.Noptrdata)
   256  					//name memory layout
   257  					//name { tagLen(byte), len(uint16), str*}
   258  					nameLen := []byte{0, 0, 0}
   259  					binary.BigEndian.PutUint16(nameLen[1:], uint16(len(path)))
   260  					linker.Noptrdata = append(linker.Noptrdata, nameLen...)
   261  					linker.Noptrdata = append(linker.Noptrdata, path...)
   262  					linker.Noptrdata = append(linker.Noptrdata, ZeroByte)
   263  					bytearrayAlign(&linker.Noptrbss, PtrSize)
   264  				}
   265  				if ispreprocesssymbol(reloc.SymName) {
   266  					bytes := make([]byte, UInt64Size)
   267  					if err := preprocesssymbol(linker.Arch.ByteOrder, reloc.SymName, bytes); err != nil {
   268  						return nil, err
   269  					} else {
   270  						relocSym.Kind = symkind.SNOPTRDATA
   271  						relocSym.Offset = len(linker.Noptrdata)
   272  						linker.Noptrdata = append(linker.Noptrdata, bytes...)
   273  						bytearrayAlign(&linker.Noptrbss, PtrSize)
   274  					}
   275  				}
   276  				if reloc.Size > 0 {
   277  					linker.SymMap[reloc.SymName] = relocSym
   278  				}
   279  			}
   280  		}
   281  		symbol.Reloc = append(symbol.Reloc, reloc)
   282  	}
   283  
   284  	if objsym.Type != EmptyString {
   285  		if _, ok := linker.SymMap[objsym.Type]; !ok {
   286  			if _, ok := linker.ObjSymbolMap[objsym.Type]; !ok {
   287  				linker.SymMap[objsym.Type] = &obj.Sym{Name: objsym.Type, Offset: InvalidOffset}
   288  			} else {
   289  				linker.addSymbol(objsym.Type, symPtr)
   290  			}
   291  		}
   292  	}
   293  	return symbol, nil
   294  }
   295  
   296  func (linker *Linker) readFuncData(symbol *obj.ObjSymbol, codeLen int, symPtr map[string]uintptr) (err error) {
   297  	nameOff := len(linker.Pclntable)
   298  	if offset, ok := linker.NameMap[symbol.Name]; !ok {
   299  		linker.NameMap[symbol.Name] = len(linker.Pclntable)
   300  		linker.Pclntable = append(linker.Pclntable, []byte(symbol.Name)...)
   301  		linker.Pclntable = append(linker.Pclntable, ZeroByte)
   302  	} else {
   303  		nameOff = offset
   304  	}
   305  
   306  	adaptePCFile(linker, symbol)
   307  	for _, reloc := range symbol.Reloc {
   308  		if reloc.Epilogue.Size > 0 {
   309  			patchPCValues(linker, &symbol.Func.PCSP, reloc)
   310  			patchPCValues(linker, &symbol.Func.PCFile, reloc)
   311  			patchPCValues(linker, &symbol.Func.PCLine, reloc)
   312  			for i := range symbol.Func.PCData {
   313  				patchPCValues(linker, &symbol.Func.PCData[i], reloc)
   314  			}
   315  		}
   316  	}
   317  	pcspOff := len(linker.Pclntable)
   318  	linker.Pclntable = append(linker.Pclntable, symbol.Func.PCSP...)
   319  
   320  	pcfileOff := len(linker.Pclntable)
   321  	linker.Pclntable = append(linker.Pclntable, symbol.Func.PCFile...)
   322  
   323  	pclnOff := len(linker.Pclntable)
   324  	linker.Pclntable = append(linker.Pclntable, symbol.Func.PCLine...)
   325  
   326  	_func := initfunc(symbol, nameOff, pcspOff, pcfileOff, pclnOff, int(symbol.Func.CUOffset))
   327  	linker.Funcs = append(linker.Funcs, &_func)
   328  	Func := linker.SymMap[symbol.Name].Func
   329  	for _, pcdata := range symbol.Func.PCData {
   330  		if len(pcdata) == 0 {
   331  			Func.PCData = append(Func.PCData, 0)
   332  		} else {
   333  			Func.PCData = append(Func.PCData, uint32(len(linker.Pclntable)))
   334  			linker.Pclntable = append(linker.Pclntable, pcdata...)
   335  		}
   336  	}
   337  
   338  	for _, name := range symbol.Func.FuncData {
   339  		if name == EmptyString {
   340  			Func.FuncData = append(Func.FuncData, (uintptr)(0))
   341  		} else {
   342  			if _, ok := linker.SymMap[name]; !ok {
   343  				if _, ok := linker.ObjSymbolMap[name]; ok {
   344  					if _, err = linker.addSymbol(name, symPtr); err != nil {
   345  						return err
   346  					}
   347  				} else {
   348  					return errors.New("unknown gcobj:" + name)
   349  				}
   350  			}
   351  			if sym, ok := linker.SymMap[name]; ok {
   352  				Func.FuncData = append(Func.FuncData, (uintptr)(sym.Offset))
   353  			} else {
   354  				Func.FuncData = append(Func.FuncData, (uintptr)(0))
   355  			}
   356  		}
   357  	}
   358  
   359  	if err = linker.addInlineTree(&_func, symbol); err != nil {
   360  		return err
   361  	}
   362  
   363  	grow(&linker.Pclntable, alignof(len(linker.Pclntable), PtrSize))
   364  	return
   365  }
   366  
   367  func (linker *Linker) addSymbolMap(symPtr map[string]uintptr, codeModule *CodeModule) (symbolMap map[string]uintptr, err error) {
   368  	symbolMap = make(map[string]uintptr)
   369  	segment := &codeModule.segment
   370  	for name, sym := range linker.SymMap {
   371  		if sym.Offset == InvalidOffset {
   372  			if ptr, ok := symPtr[sym.Name]; ok {
   373  				symbolMap[name] = ptr
   374  			} else if addr, ok := symPtr[strings.TrimSuffix(name, GOTPCRELSuffix)]; ok && strings.HasSuffix(name, GOTPCRELSuffix) {
   375  				symbolMap[name] = uintptr(segment.dataBase) + uintptr(segment.dataOff)
   376  				putAddressAddOffset(linker.Arch.ByteOrder, segment.dataByte, &segment.dataOff, uint64(addr))
   377  			} else {
   378  				symbolMap[name] = InvalidHandleValue
   379  				return nil, fmt.Errorf("unresolve external:%s", sym.Name)
   380  			}
   381  		} else if sym.Kind == symkind.STEXT {
   382  			symbolMap[name] = uintptr(sym.Offset + segment.codeBase)
   383  			codeModule.Syms[sym.Name] = symbolMap[name]
   384  		} else if strings.HasPrefix(name, constants.TypeStringPrefix) {
   385  			symbolMap[name] = (*stringHeader)(unsafe.Pointer(linker.StringMap[name])).Data
   386  		} else if name == getInitFuncName(DefaultPkgPath) ||
   387  			strings.HasPrefix(name, constants.TypePrefix) {
   388  			symbolMap[name] = uintptr(sym.Offset + segment.dataBase)
   389  		} else if _, ok := symPtr[name]; ok {
   390  			symbolMap[name] = symPtr[name]
   391  		} else {
   392  			symbolMap[name] = uintptr(sym.Offset + segment.dataBase)
   393  		}
   394  		//fill itablinks
   395  		if strings.HasPrefix(name, constants.ItabPrefix) {
   396  			codeModule.module.itablinks = append(codeModule.module.itablinks, (*itab)(adduintptr(symbolMap[name], 0)))
   397  		}
   398  	}
   399  	return symbolMap, err
   400  }
   401  
   402  func (linker *Linker) addFuncTab(module *moduledata, _func *_func, symbolMap map[string]uintptr) (err error) {
   403  	funcname := getfuncname(_func, module)
   404  	setfuncentry(_func, symbolMap[funcname], module.text)
   405  	Func := linker.SymMap[funcname].Func
   406  
   407  	if err = stackobject.AddStackObject(funcname, linker.SymMap, symbolMap, module.noptrdata); err != nil {
   408  		return err
   409  	}
   410  	if err = linker.addDeferReturn(_func, module); err != nil {
   411  		return err
   412  	}
   413  
   414  	append2Slice(&module.pclntable, uintptr(unsafe.Pointer(_func)), _FuncSize)
   415  
   416  	if _func.Npcdata > 0 {
   417  		append2Slice(&module.pclntable, uintptr(unsafe.Pointer(&(Func.PCData[0]))), Uint32Size*int(_func.Npcdata))
   418  	}
   419  
   420  	if _func.Nfuncdata > 0 {
   421  		addfuncdata(module, Func, _func)
   422  	}
   423  
   424  	return err
   425  }
   426  
   427  func (linker *Linker) buildModule(codeModule *CodeModule, symbolMap map[string]uintptr) (err error) {
   428  	segment := &codeModule.segment
   429  	module := codeModule.module
   430  	module.pclntable = append(module.pclntable, linker.Pclntable...)
   431  	module.minpc = uintptr(segment.codeBase)
   432  	module.maxpc = uintptr(segment.codeBase + segment.codeOff)
   433  	module.text = uintptr(segment.codeBase)
   434  	module.etext = module.maxpc
   435  	module.data = uintptr(segment.dataBase)
   436  	module.edata = uintptr(segment.dataBase) + uintptr(segment.dataLen)
   437  	module.noptrdata = module.edata
   438  	module.enoptrdata = module.noptrdata + uintptr(segment.noptrdataLen)
   439  	module.bss = module.enoptrdata
   440  	module.ebss = module.bss + uintptr(segment.bssLen)
   441  	module.noptrbss = module.ebss
   442  	module.enoptrbss = module.noptrbss + uintptr(segment.noptrbssLen)
   443  	module.end = module.enoptrbss
   444  	module.types = module.data
   445  	module.etypes = module.enoptrbss
   446  	initmodule(codeModule.module, linker)
   447  
   448  	module.ftab = append(module.ftab, initfunctab(module.minpc, uintptr(len(module.pclntable)), module.text))
   449  	for index, _func := range linker.Funcs {
   450  		funcname := getfuncname(_func, module)
   451  		module.ftab = append(module.ftab, initfunctab(symbolMap[funcname], uintptr(len(module.pclntable)), module.text))
   452  		if err = linker.addFuncTab(module, linker.Funcs[index], symbolMap); err != nil {
   453  			return err
   454  		}
   455  	}
   456  	module.ftab = append(module.ftab, initfunctab(module.maxpc, uintptr(len(module.pclntable)), module.text))
   457  
   458  	// see:^src/cmd/link/internal/ld/pcln.go findfunctab
   459  	funcbucket := []findfuncbucket{}
   460  	for k := 0; k < len(linker.Funcs); k++ {
   461  		lEntry := int(getfuncentry(linker.Funcs[k], module.text) - module.text)
   462  		lb := lEntry / pcbucketsize
   463  		li := lEntry % pcbucketsize / (pcbucketsize / nsub)
   464  
   465  		entry := int(module.maxpc - module.text)
   466  		if k < len(linker.Funcs)-1 {
   467  			entry = int(getfuncentry(linker.Funcs[k+1], module.text) - module.text)
   468  		}
   469  		b := entry / pcbucketsize
   470  		i := entry % pcbucketsize / (pcbucketsize / nsub)
   471  
   472  		for m := b - len(funcbucket); m >= 0; m-- {
   473  			funcbucket = append(funcbucket, findfuncbucket{idx: uint32(k)})
   474  		}
   475  		if lb < b {
   476  			i = nsub - 1
   477  		}
   478  		for n := li + 1; n <= i; n++ {
   479  			if funcbucket[lb].subbuckets[n] == 0 {
   480  				funcbucket[lb].subbuckets[n] = byte(k - int(funcbucket[lb].idx))
   481  			}
   482  		}
   483  	}
   484  	length := len(funcbucket) * FindFuncBucketSize
   485  	append2Slice(&module.pclntable, uintptr(unsafe.Pointer(&funcbucket[0])), length)
   486  	module.findfunctab = (uintptr)(unsafe.Pointer(&module.pclntable[len(module.pclntable)-length]))
   487  
   488  	if err = linker.addgcdata(codeModule, symbolMap); err != nil {
   489  		return err
   490  	}
   491  	for name, addr := range symbolMap {
   492  		if strings.HasPrefix(name, constants.TypePrefix) &&
   493  			!strings.HasPrefix(name, constants.TypeDoubleDotPrefix) &&
   494  			addr >= module.types && addr < module.etypes {
   495  			module.typelinks = append(module.typelinks, int32(addr-module.types))
   496  		}
   497  	}
   498  
   499  	modulesLock.Lock()
   500  	addModule(codeModule.module)
   501  	modulesLock.Unlock()
   502  	moduledataverify1(codeModule.module)
   503  	modulesinit()
   504  	typelinksinit()
   505  	additabs(codeModule.module)
   506  
   507  	return err
   508  }
   509  
   510  func Load(linker *Linker, symPtr map[string]uintptr) (codeModule *CodeModule, err error) {
   511  	codeModule = &CodeModule{
   512  		Syms:   make(map[string]uintptr),
   513  		module: &moduledata{typemap: nil},
   514  	}
   515  
   516  	//init code segment
   517  	codeSeg := &codeModule.segment.codeSeg
   518  	codeSeg.length = len(linker.Code)
   519  	codeSeg.maxLen = alignof((codeSeg.length)*2, PageSize)
   520  	codeByte, err := Mmap(codeSeg.maxLen)
   521  	if err != nil {
   522  		return nil, err
   523  	}
   524  	codeSeg.codeByte = codeByte
   525  	codeSeg.codeBase = int((*sliceHeader)(unsafe.Pointer(&codeByte)).Data)
   526  	copy(codeSeg.codeByte, linker.Code)
   527  	codeSeg.codeOff = codeSeg.length
   528  
   529  	//init data segment
   530  	dataSeg := &codeModule.segment.dataSeg
   531  	dataSeg.dataLen = len(linker.Data)
   532  	dataSeg.noptrdataLen = len(linker.Noptrdata)
   533  	dataSeg.bssLen = len(linker.Bss)
   534  	dataSeg.noptrbssLen = len(linker.Noptrbss)
   535  	dataSeg.length = dataSeg.dataLen + dataSeg.noptrdataLen + dataSeg.bssLen + dataSeg.noptrbssLen
   536  	dataSeg.maxLen = alignof((dataSeg.length)*2, PageSize)
   537  	dataSeg.dataOff = 0
   538  	dataByte, err := MmapData(dataSeg.maxLen)
   539  	if err != nil {
   540  		Munmap(dataSeg.dataByte)
   541  		return nil, err
   542  	}
   543  	dataSeg.dataByte = dataByte
   544  	dataSeg.dataBase = int((*sliceHeader)(unsafe.Pointer(&dataByte)).Data)
   545  	copy(dataSeg.dataByte[dataSeg.dataOff:], linker.Data)
   546  	dataSeg.dataOff = dataSeg.dataLen
   547  	copy(dataSeg.dataByte[dataSeg.dataOff:], linker.Noptrdata)
   548  	dataSeg.dataOff += dataSeg.noptrdataLen
   549  	copy(dataSeg.dataByte[dataSeg.dataOff:], linker.Bss)
   550  	dataSeg.dataOff += dataSeg.bssLen
   551  	copy(dataSeg.dataByte[dataSeg.dataOff:], linker.Noptrbss)
   552  	dataSeg.dataOff += dataSeg.noptrbssLen
   553  
   554  	codeModule.stringMap = linker.StringMap
   555  
   556  	linker.adaptSymbolOffset()
   557  
   558  	var symbolMap map[string]uintptr
   559  	if symbolMap, err = linker.addSymbolMap(symPtr, codeModule); err == nil {
   560  		if err = linker.relocate(codeModule, symbolMap, symPtr); err == nil {
   561  			if err = linker.buildModule(codeModule, symbolMap); err == nil {
   562  				MakeThreadJITCodeExecutable(uintptr(codeModule.codeBase), codeSeg.maxLen)
   563  				if err = linker.doInitialize(symPtr, symbolMap); err == nil {
   564  					return codeModule, err
   565  				}
   566  			}
   567  		}
   568  	}
   569  	return nil, err
   570  }
   571  
   572  func UnresolvedSymbols(linker *Linker, symPtr map[string]uintptr) []string {
   573  	unresolvedSymbols := make([]string, 0)
   574  	for name, sym := range linker.SymMap {
   575  		if sym.Offset == InvalidOffset {
   576  			if _, ok := symPtr[sym.Name]; !ok {
   577  				nName := strings.TrimSuffix(name, GOTPCRELSuffix)
   578  				if name != nName {
   579  					if _, ok := symPtr[nName]; !ok {
   580  						unresolvedSymbols = append(unresolvedSymbols, nName)
   581  					}
   582  				} else {
   583  					unresolvedSymbols = append(unresolvedSymbols, name)
   584  				}
   585  			}
   586  		}
   587  	}
   588  	return unresolvedSymbols
   589  }
   590  
   591  func (cm *CodeModule) Unload() {
   592  	removeitabs(cm.module)
   593  	runtime.GC()
   594  	modulesLock.Lock()
   595  	removeModule(cm.module)
   596  	modulesLock.Unlock()
   597  	modulesinit()
   598  	Munmap(cm.codeByte)
   599  	Munmap(cm.dataByte)
   600  }