github.com/Rookout/GoSDK@v0.1.48/pkg/services/instrumentation/binary_info/constants.go (about)

     1  // The MIT License (MIT)
     2  
     3  // Copyright (c) 2014 Derek Parker
     4  
     5  // Permission is hereby granted, free of charge, to any person obtaining a copy of
     6  // this software and associated documentation files (the "Software"), to deal in
     7  // the Software without restriction, including without limitation the rights to
     8  // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
     9  // the Software, and to permit persons to whom the Software is furnished to do so,
    10  // subject to the following conditions:
    11  
    12  // The above copyright notice and this permission notice shall be included in all
    13  // copies or substantial portions of the Software.
    14  
    15  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    16  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
    17  // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
    18  // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
    19  // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
    20  // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    21  
    22  package binary_info
    23  
    24  import (
    25  	"sort"
    26  	"strings"
    27  
    28  	"github.com/Rookout/GoSDK/pkg/services/instrumentation/dwarf/godwarf"
    29  )
    30  
    31  type constantsMap map[dwarfRef]*constantType
    32  
    33  type constantType struct {
    34  	initialized bool
    35  	values      []constantValue
    36  }
    37  
    38  type constantValue struct {
    39  	name      string
    40  	fullName  string
    41  	value     int64
    42  	singleBit bool
    43  }
    44  
    45  type constantValuesByValue []constantValue
    46  
    47  func (v constantValuesByValue) Len() int               { return len(v) }
    48  func (v constantValuesByValue) Less(i int, j int) bool { return v[i].value < v[j].value }
    49  func (v constantValuesByValue) Swap(i int, j int)      { v[i], v[j] = v[j], v[i] }
    50  
    51  func (cm constantsMap) Get(typ godwarf.Type) *constantType {
    52  	ctyp := cm[dwarfRef{typ.Common().Index, typ.Common().Offset}]
    53  	if ctyp == nil {
    54  		return nil
    55  	}
    56  	typepkg := packageName(typ.String()) + "."
    57  	if !ctyp.initialized {
    58  		ctyp.initialized = true
    59  		sort.Sort(constantValuesByValue(ctyp.values))
    60  		for i := range ctyp.values {
    61  			if strings.HasPrefix(ctyp.values[i].name, typepkg) {
    62  				ctyp.values[i].name = ctyp.values[i].name[len(typepkg):]
    63  			}
    64  			if Popcnt(uint64(ctyp.values[i].value)) == 1 {
    65  				ctyp.values[i].singleBit = true
    66  			}
    67  		}
    68  	}
    69  	return ctyp
    70  }
    71  
    72  
    73  
    74  
    75  func Popcnt(x uint64) int {
    76  	const m0 = 0x5555555555555555 
    77  	const m1 = 0x3333333333333333 
    78  	const m2 = 0x0f0f0f0f0f0f0f0f 
    79  	const m = 1<<64 - 1
    80  	x = x>>1&(m0&m) + x&(m0&m)
    81  	x = x>>2&(m1&m) + x&(m1&m)
    82  	x = (x>>4 + x) & (m2 & m)
    83  	x += x >> 8
    84  	x += x >> 16
    85  	x += x >> 32
    86  	return int(x) & (1<<7 - 1)
    87  }
    88  
    89  func packageName(name string) string {
    90  	pathend := strings.LastIndex(name, "/")
    91  	if pathend < 0 {
    92  		pathend = 0
    93  	}
    94  
    95  	if i := strings.Index(name[pathend:], "."); i != -1 {
    96  		return name[:pathend+i]
    97  	}
    98  	return ""
    99  }
   100  
   101  func (ctyp *constantType) Describe(n int64) string {
   102  	for _, val := range ctyp.values {
   103  		if val.value == n {
   104  			return val.name
   105  		}
   106  	}
   107  
   108  	if n == 0 {
   109  		return ""
   110  	}
   111  
   112  	
   113  	
   114  
   115  	fields := []string{}
   116  	for _, val := range ctyp.values {
   117  		if !val.singleBit {
   118  			continue
   119  		}
   120  		if n&val.value != 0 {
   121  			fields = append(fields, val.name)
   122  			n = n & ^val.value
   123  		}
   124  	}
   125  	if n == 0 {
   126  		return strings.Join(fields, "|")
   127  	}
   128  	return ""
   129  }