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

     1  package goloader
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/pkujhd/goloader/obj"
     7  )
     8  
     9  func Parse(file, pkgpath string) ([]string, error) {
    10  	pkg := obj.Pkg{Syms: make(map[string]*obj.ObjSymbol, 0), File: file, PkgPath: pkgpath}
    11  	if err := pkg.Symbols(); err != nil {
    12  		return nil, err
    13  	}
    14  	symbols := make([]string, 0)
    15  	for _, sym := range pkg.Syms {
    16  		symbols = append(symbols, sym.Name)
    17  	}
    18  	return symbols, nil
    19  }
    20  
    21  func (linker *Linker) readObj(file, pkgpath string) error {
    22  	pkg := obj.Pkg{Syms: make(map[string]*obj.ObjSymbol, 0), File: file, PkgPath: pkgpath}
    23  	if pkg.PkgPath == EmptyString {
    24  		pkg.PkgPath = DefaultPkgPath
    25  	}
    26  	if err := pkg.Symbols(); err != nil {
    27  		return fmt.Errorf("read error: %v", err)
    28  	}
    29  	if linker.Arch != nil && linker.Arch.Name != pkg.Arch {
    30  		return fmt.Errorf("read obj error: Arch %s != Arch %s", linker.Arch.Name, pkg.Arch)
    31  	} else {
    32  		linker.Arch = getArch(pkg.Arch)
    33  	}
    34  
    35  	for _, sym := range pkg.Syms {
    36  		for index, loc := range sym.Reloc {
    37  			sym.Reloc[index].SymName = obj.ReplacePkgPath(loc.SymName, pkg.PkgPath)
    38  		}
    39  		if sym.Type != EmptyString {
    40  			sym.Type = obj.ReplacePkgPath(sym.Type, pkg.PkgPath)
    41  		}
    42  		if sym.Func != nil {
    43  			for index, FuncData := range sym.Func.FuncData {
    44  				sym.Func.FuncData[index] = obj.ReplacePkgPath(FuncData, pkg.PkgPath)
    45  			}
    46  			sym.Func.CUOffset += linker.CUOffset
    47  		}
    48  		sym.Name = obj.ReplacePkgPath(sym.Name, pkg.PkgPath)
    49  		linker.ObjSymbolMap[sym.Name] = sym
    50  	}
    51  	linker.addFiles(pkg.CUFiles)
    52  	linker.Packages = append(linker.Packages, &pkg)
    53  	return nil
    54  }
    55  
    56  func ReadObj(file, pkgpath string) (*Linker, error) {
    57  	linker := initLinker()
    58  	if err := linker.readObj(file, pkgpath); err != nil {
    59  		return nil, err
    60  	}
    61  	linker.initPcHeader()
    62  	if err := linker.addSymbols(); err != nil {
    63  		return nil, err
    64  	}
    65  	return linker, nil
    66  }
    67  
    68  func ReadObjs(files []string, pkgPaths []string) (*Linker, error) {
    69  	linker := initLinker()
    70  	for i, file := range files {
    71  		if err := linker.readObj(file, pkgPaths[i]); err != nil {
    72  			return nil, err
    73  		}
    74  	}
    75  	linker.initPcHeader()
    76  	if err := linker.addSymbols(); err != nil {
    77  		return nil, err
    78  	}
    79  	return linker, nil
    80  }
    81  
    82  func (linker *Linker) ReadDependPkg(file, pkgPath string, symbolNames []string, symPtr map[string]uintptr) error {
    83  	if linker.AdaptedOffset {
    84  		return fmt.Errorf("already adapted symbol offset, don't add new symbols")
    85  	}
    86  	//only add unresolved symbol in ObjSymbolMap. use temporary map store read symbols
    87  	objSymbolMap := linker.ObjSymbolMap
    88  	linker.ObjSymbolMap = make(map[string]*obj.ObjSymbol)
    89  	if err := linker.readObj(file, pkgPath); err != nil {
    90  		return err
    91  	}
    92  	initFuncName := getInitFuncName(pkgPath)
    93  	if _, ok := linker.ObjSymbolMap[initFuncName]; ok {
    94  		if _, err := linker.addSymbol(initFuncName, nil); err != nil {
    95  			return err
    96  		}
    97  	}
    98  	for _, name := range symbolNames {
    99  		if _, ok := linker.ObjSymbolMap[name]; ok {
   100  			delete(linker.SymMap, name)
   101  			_, err := linker.addSymbol(name, symPtr)
   102  			if err != nil {
   103  				return err
   104  			}
   105  		}
   106  	}
   107  	for name, sym := range linker.ObjSymbolMap {
   108  		if _, ok := linker.SymMap[name]; ok {
   109  			objSymbolMap[name] = sym
   110  		}
   111  	}
   112  	linker.ObjSymbolMap = objSymbolMap
   113  	return nil
   114  }