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

     1  //go:build go1.16 && !go1.23
     2  // +build go1.16,!go1.23
     3  
     4  package obj
     5  
     6  import (
     7  	"cmd/objfile/archive"
     8  	"cmd/objfile/goobj"
     9  	"cmd/objfile/objabi"
    10  	"fmt"
    11  	"os"
    12  	"path/filepath"
    13  )
    14  
    15  func (pkg *Pkg) Symbols() error {
    16  	file, err := os.Open(pkg.File)
    17  	if err != nil {
    18  		return err
    19  	}
    20  	defer file.Close()
    21  	a, err := archive.Parse(file, false)
    22  	if err != nil {
    23  		return err
    24  	}
    25  	for _, e := range a.Entries {
    26  		switch e.Type {
    27  		case archive.EntryPkgDef:
    28  			//nothing todo
    29  		case archive.EntryGoObj:
    30  			b := make([]byte, e.Obj.Size)
    31  			_, err := file.ReadAt(b, e.Obj.Offset)
    32  			if err != nil {
    33  				return err
    34  			}
    35  			r := goobj.NewReaderFromBytes(b, false)
    36  			// Name of referenced indexed symbols.
    37  			nrefName := r.NRefName()
    38  			refNames := make(map[goobj.SymRef]string, nrefName)
    39  			for i := 0; i < nrefName; i++ {
    40  				rn := r.RefName(i)
    41  				refNames[rn.Sym()] = rn.Name(r)
    42  			}
    43  			for i := 0; i < r.NFile(); i++ {
    44  				pkg.CUFiles = append(pkg.CUFiles, r.File(i))
    45  			}
    46  			pkg.Arch = e.Obj.Arch
    47  			nsym := r.NSym() + r.NHashed64def() + r.NHasheddef() + r.NNonpkgdef()
    48  			for i := 0; i < nsym; i++ {
    49  				pkg.addSym(r, uint32(i), &refNames)
    50  			}
    51  			for _, importPkg := range r.Autolib() {
    52  				path := importPkg.Pkg
    53  				path = path[:len(path)-len(filepath.Ext(path))]
    54  				pkg.ImportPkgs = append(pkg.ImportPkgs, path)
    55  			}
    56  		default:
    57  			return fmt.Errorf("Parse open %s: unrecognized archive member %s\n", file.Name(), e.Name)
    58  		}
    59  	}
    60  	return nil
    61  }
    62  
    63  func resolveSymRef(s goobj.SymRef, r *goobj.Reader, refNames *map[goobj.SymRef]string) (string, uint32) {
    64  	i := InvalidIndex
    65  	switch p := s.PkgIdx; p {
    66  	case goobj.PkgIdxInvalid:
    67  		if s.SymIdx != 0 {
    68  			panic("bad sym ref")
    69  		}
    70  		return EmptyString, i
    71  	case goobj.PkgIdxHashed64:
    72  		i = s.SymIdx + uint32(r.NSym())
    73  	case goobj.PkgIdxHashed:
    74  		i = s.SymIdx + uint32(r.NSym()+r.NHashed64def())
    75  	case goobj.PkgIdxNone:
    76  		i = s.SymIdx + uint32(r.NSym()+r.NHashed64def()+r.NHasheddef())
    77  	case goobj.PkgIdxBuiltin:
    78  		name, _ := goobj.BuiltinName(int(s.SymIdx))
    79  		return name, i
    80  	case goobj.PkgIdxSelf:
    81  		i = s.SymIdx
    82  	default:
    83  		return (*refNames)[s], i
    84  	}
    85  	return r.Sym(i).Name(r), i
    86  }
    87  
    88  func (pkg *Pkg) addSym(r *goobj.Reader, index uint32, refNames *map[goobj.SymRef]string) {
    89  	s := r.Sym(index)
    90  	symbol := ObjSymbol{Name: s.Name(r), Kind: int(s.Type()), DupOK: s.Dupok(), Size: (int64)(s.Siz()), Func: &FuncInfo{}}
    91  	if _, ok := pkg.Syms[symbol.Name]; ok {
    92  		return
    93  	}
    94  	if objabi.SymKind(symbol.Kind) == objabi.Sxxx || symbol.Name == EmptyString {
    95  		return
    96  	}
    97  	if symbol.Size > 0 {
    98  		symbol.Data = r.Data(index)
    99  		Grow(&symbol.Data, (int)(symbol.Size))
   100  	} else {
   101  		symbol.Data = make([]byte, 0)
   102  	}
   103  
   104  	pkg.Syms[symbol.Name] = &symbol
   105  
   106  	auxs := r.Auxs(index)
   107  	for k := 0; k < len(auxs); k++ {
   108  		name, index := resolveSymRef(auxs[k].Sym(), r, refNames)
   109  		switch auxs[k].Type() {
   110  		case goobj.AuxGotype:
   111  			symbol.Type = name
   112  		case goobj.AuxFuncInfo:
   113  			funcInfo := goobj.FuncInfo{}
   114  			readFuncInfo(&funcInfo, r.Data(index), symbol.Func)
   115  			symbol.Func.CUOffset = 0
   116  			for _, index := range funcInfo.File {
   117  				symbol.Func.File = append(symbol.Func.File, r.File(int(index)))
   118  			}
   119  			for _, inl := range funcInfo.InlTree {
   120  				funcname, _ := resolveSymRef(inl.Func, r, refNames)
   121  				funcname = ReplacePkgPath(funcname, pkg.PkgPath)
   122  				inlNode := InlTreeNode{
   123  					Parent:   int64(inl.Parent),
   124  					File:     r.File(int(inl.File)),
   125  					Line:     int64(inl.Line),
   126  					Func:     funcname,
   127  					ParentPC: int64(inl.ParentPC),
   128  				}
   129  				symbol.Func.InlTree = append(symbol.Func.InlTree, inlNode)
   130  			}
   131  		case goobj.AuxFuncdata:
   132  			symbol.Func.FuncData = append(symbol.Func.FuncData, name)
   133  		case goobj.AuxDwarfInfo:
   134  		case goobj.AuxDwarfLoc:
   135  		case goobj.AuxDwarfRanges:
   136  		case goobj.AuxDwarfLines:
   137  		case goobj.AuxPcsp:
   138  			symbol.Func.PCSP = r.Data(index)
   139  		case goobj.AuxPcfile:
   140  			symbol.Func.PCFile = r.Data(index)
   141  		case goobj.AuxPcline:
   142  			symbol.Func.PCLine = r.Data(index)
   143  		case goobj.AuxPcinline:
   144  			symbol.Func.PCInline = r.Data(index)
   145  		case goobj.AuxPcdata:
   146  			symbol.Func.PCData = append(symbol.Func.PCData, r.Data(index))
   147  		}
   148  		if _, ok := pkg.Syms[name]; !ok && index != InvalidIndex {
   149  			pkg.addSym(r, index, refNames)
   150  		}
   151  	}
   152  
   153  	relocs := r.Relocs(index)
   154  	for k := 0; k < len(relocs); k++ {
   155  		symbol.Reloc = append(symbol.Reloc, Reloc{})
   156  		symbol.Reloc[k].Add = int(relocs[k].Add())
   157  		symbol.Reloc[k].Offset = int(relocs[k].Off())
   158  		symbol.Reloc[k].Size = int(relocs[k].Siz())
   159  		symbol.Reloc[k].Type = int(relocs[k].Type())
   160  		name, index := resolveSymRef(relocs[k].Sym(), r, refNames)
   161  		symbol.Reloc[k].SymName = name
   162  		if _, ok := pkg.Syms[name]; !ok && index != InvalidIndex {
   163  			pkg.addSym(r, index, refNames)
   164  		}
   165  	}
   166  }