github.com/Rookout/GoSDK@v0.1.48/pkg/services/instrumentation/module/module1.18.go (about)

     1  //go:build go1.18 && !go1.20
     2  // +build go1.18,!go1.20
     3  
     4  package module
     5  
     6  import (
     7  	"runtime"
     8  	"unsafe"
     9  )
    10  
    11  
    12  
    13  type funcFlag uint8
    14  
    15  type functab struct {
    16  	entryoff uint32 
    17  	funcoff  uint32
    18  }
    19  
    20  type textsect struct {
    21  	vaddr    uintptr 
    22  	end      uintptr 
    23  	baseaddr uintptr 
    24  }
    25  
    26  type _func struct {
    27  	entryoff uint32 
    28  	nameoff  int32  
    29  
    30  	args        int32  
    31  	deferreturn uint32 
    32  
    33  	pcsp      uint32
    34  	pcfile    uint32
    35  	pcln      uint32
    36  	npcdata   uint32
    37  	cuOffset  uint32 
    38  	funcID    FuncID 
    39  	flag      funcFlag
    40  	_         [1]byte 
    41  	nfuncdata uint8   
    42  }
    43  
    44  type pcHeader struct {
    45  	magic          uint32  
    46  	pad1, pad2     uint8   
    47  	minLC          uint8   
    48  	ptrSize        uint8   
    49  	nfunc          int     
    50  	nfiles         uint    
    51  	textStart      uintptr 
    52  	funcnameOffset uintptr 
    53  	cuOffset       uintptr 
    54  	filetabOffset  uintptr 
    55  	pctabOffset    uintptr 
    56  	pclnOffset     uintptr 
    57  }
    58  
    59  type moduledata struct {
    60  	pcHeader     *pcHeader
    61  	funcnametab  []byte
    62  	cutab        []uint32
    63  	filetab      []byte
    64  	pctab        []byte
    65  	pclntable    []byte
    66  	ftab         []functab
    67  	findfunctab  uintptr
    68  	minpc, maxpc uintptr
    69  
    70  	text, etext           uintptr
    71  	noptrdata, enoptrdata uintptr
    72  	data, edata           uintptr
    73  	bss, ebss             uintptr
    74  	noptrbss, enoptrbss   uintptr
    75  	end, gcdata, gcbss    uintptr
    76  	types, etypes         uintptr
    77  	rodata                uintptr
    78  	gofunc                uintptr // go.func.*
    79  
    80  	textsectmap []textsect
    81  	typelinks   []int32 
    82  	itablinks   []*itab
    83  
    84  	ptab []ptabEntry
    85  
    86  	pluginpath string
    87  	pkghashes  []modulehash
    88  
    89  	modulename   string
    90  	modulehashes []modulehash
    91  
    92  	hasmain uint8 
    93  
    94  	gcdatamask, gcbssmask bitvector
    95  
    96  	typemap map[TypeOff]*_type 
    97  
    98  	bad bool 
    99  
   100  	next *moduledata
   101  }
   102  
   103  func getPCTab(m *moduledata) []byte {
   104  	return m.pctab
   105  }
   106  
   107  func (f *FuncInfo) getEntry() uintptr {
   108  	entry, _ := f.datap.textAddr(f.entryoff)
   109  	return entry
   110  }
   111  
   112  
   113  func findFuncOffsetInModule(pc uintptr, datap *moduledata) (uintptr, bool) {
   114  	if datap == nil {
   115  		return 0, false
   116  	}
   117  	const nsub = uintptr(len(findfuncbucket{}.subbuckets))
   118  
   119  	pcOff, ok := datap.textOff(pc)
   120  	if !ok {
   121  		return 0, false
   122  	}
   123  
   124  	x := uintptr(pcOff) + datap.text - datap.minpc
   125  	b := x / pcbucketsize
   126  	i := x % pcbucketsize / (pcbucketsize / nsub)
   127  
   128  	ffb := (*findfuncbucket)(add(unsafe.Pointer(datap.findfunctab), b*unsafe.Sizeof(findfuncbucket{})))
   129  	idx := ffb.idx + uint32(ffb.subbuckets[i])
   130  
   131  	
   132  	for datap.ftab[idx+1].entryoff <= pcOff {
   133  		idx++
   134  	}
   135  
   136  	funcoff := uintptr(datap.ftab[idx].funcoff)
   137  	if funcoff == ^uintptr(0) {
   138  		
   139  		
   140  		
   141  		
   142  		return 0, false
   143  	}
   144  
   145  	return funcoff, true
   146  }
   147  
   148  
   149  func (md *moduledata) textOff(pc uintptr) (uint32, bool) {
   150  	res := uint32(pc - md.text)
   151  	if len(md.textsectmap) > 1 {
   152  		for i, sect := range md.textsectmap {
   153  			if sect.baseaddr > pc {
   154  				
   155  				return 0, false
   156  			}
   157  			end := sect.baseaddr + (sect.end - sect.vaddr)
   158  			
   159  			if i == len(md.textsectmap) {
   160  				end++
   161  			}
   162  			if pc < end {
   163  				res = uint32(pc - sect.baseaddr + sect.vaddr)
   164  				break
   165  			}
   166  		}
   167  	}
   168  	return res, true
   169  }
   170  
   171  
   172  func (md *moduledata) textAddr(off32 uint32) (uintptr, bool) {
   173  	off := uintptr(off32)
   174  	res := md.text + off
   175  	if len(md.textsectmap) > 1 {
   176  		for i, sect := range md.textsectmap {
   177  			
   178  			if off >= sect.vaddr && off < sect.end || (i == len(md.textsectmap)-1 && off == sect.end) {
   179  				res = sect.baseaddr + off - sect.vaddr
   180  				break
   181  			}
   182  		}
   183  		if res > md.etext && runtime.GOARCH != "wasm" { 
   184  			println("runtime: textAddr", hex(res), "out of range", hex(md.text), "-", hex(md.etext))
   185  			return 0, false
   186  		}
   187  	}
   188  	return res, true
   189  }
   190  
   191  type hex uint64
   192  
   193  func (md *moduledata) GetTypeMap() map[TypeOff]uintptr {
   194  	typemap := make(map[TypeOff]uintptr)
   195  	for k, v := range md.typemap {
   196  		typemap[k] = uintptr(unsafe.Pointer(v))
   197  	}
   198  	return typemap
   199  }