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

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