1// Package attr provides attributes for text and data sections. 2package attr 3 4import ( 5 "fmt" 6 "math/bits" 7 "strings" 8) 9 10// Attribute represents TEXT or DATA flags. 11type Attribute uint16 12 13// Reference: https://github.com/golang/go/blob/aafe257390cc9048e8b5df898fabd79a9e0d4c39/src/runtime/textflag.h#L11-L37 14// 15// // Don't profile the marked routine. This flag is deprecated. 16// #define NOPROF 1 17// // It is ok for the linker to get multiple of these symbols. It will 18// // pick one of the duplicates to use. 19// #define DUPOK 2 20// // Don't insert stack check preamble. 21// #define NOSPLIT 4 22// // Put this data in a read-only section. 23// #define RODATA 8 24// // This data contains no pointers. 25// #define NOPTR 16 26// // This is a wrapper function and should not count as disabling 'recover'. 27// #define WRAPPER 32 28// // This function uses its incoming context register. 29// #define NEEDCTXT 64 30// // Allocate a word of thread local storage and store the offset from the 31// // thread local base to the thread local storage in this variable. 32// #define TLSBSS 256 33// // Do not insert instructions to allocate a stack frame for this function. 34// // Only valid on functions that declare a frame size of 0. 35// // TODO(mwhudson): only implemented for ppc64x at present. 36// #define NOFRAME 512 37// // Function can call reflect.Type.Method or reflect.Type.MethodByName. 38// #define REFLECTMETHOD 1024 39// // Function is the top of the call stack. Call stack unwinders should stop 40// // at this function. 41// #define TOPFRAME 2048 42// 43const ( 44 NOPROF Attribute = 1 << iota 45 DUPOK 46 NOSPLIT 47 RODATA 48 NOPTR 49 WRAPPER 50 NEEDCTXT 51 _ 52 TLSBSS 53 NOFRAME 54 REFLECTMETHOD 55 TOPFRAME 56) 57 58// Asm returns a representation of the attributes in assembly syntax. This may use macros from "textflags.h"; see ContainsTextFlags() to determine if this header is required. 59func (a Attribute) Asm() string { 60 parts, rest := a.split() 61 if len(parts) == 0 || rest != 0 { 62 parts = append(parts, fmt.Sprintf("%d", rest)) 63 } 64 return strings.Join(parts, "|") 65} 66 67// ContainsTextFlags returns whether the Asm() representation requires macros in "textflags.h". 68func (a Attribute) ContainsTextFlags() bool { 69 flags, _ := a.split() 70 return len(flags) > 0 71} 72 73// split splits a into known flags and any remaining bits. 74func (a Attribute) split() ([]string, Attribute) { 75 var flags []string 76 var rest Attribute 77 for a != 0 { 78 i := uint(bits.TrailingZeros16(uint16(a))) 79 bit := Attribute(1) << i 80 if flag := attrname[bit]; flag != "" { 81 flags = append(flags, flag) 82 } else { 83 rest |= bit 84 } 85 a ^= bit 86 } 87 return flags, rest 88} 89 90var attrname = map[Attribute]string{ 91 NOPROF: "NOPROF", 92 DUPOK: "DUPOK", 93 NOSPLIT: "NOSPLIT", 94 RODATA: "RODATA", 95 NOPTR: "NOPTR", 96 WRAPPER: "WRAPPER", 97 NEEDCTXT: "NEEDCTXT", 98 TLSBSS: "TLSBSS", 99 NOFRAME: "NOFRAME", 100 REFLECTMETHOD: "REFLECTMETHOD", 101 TOPFRAME: "TOPFRAME", 102} 103