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 }