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

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