2019-01-05 18:18:49 -08:00
// Package attr provides attributes for text and data sections.
package attr
2018-12-30 19:57:01 -08:00
import (
"fmt"
"math/bits"
"strings"
)
// Attribute represents TEXT or DATA flags.
type Attribute uint16
2019-09-27 13:11:50 +09:00
// Reference: https://github.com/golang/go/blob/aafe257390cc9048e8b5df898fabd79a9e0d4c39/src/runtime/textflag.h#L11-L37
2018-12-30 19:57:01 -08:00
//
// // Don't profile the marked routine. This flag is deprecated.
// #define NOPROF 1
// // It is ok for the linker to get multiple of these symbols. It will
// // pick one of the duplicates to use.
// #define DUPOK 2
// // Don't insert stack check preamble.
// #define NOSPLIT 4
// // Put this data in a read-only section.
// #define RODATA 8
// // This data contains no pointers.
// #define NOPTR 16
// // This is a wrapper function and should not count as disabling 'recover'.
// #define WRAPPER 32
// // This function uses its incoming context register.
// #define NEEDCTXT 64
// // Allocate a word of thread local storage and store the offset from the
// // thread local base to the thread local storage in this variable.
// #define TLSBSS 256
// // Do not insert instructions to allocate a stack frame for this function.
// // Only valid on functions that declare a frame size of 0.
// // TODO(mwhudson): only implemented for ppc64x at present.
// #define NOFRAME 512
// // Function can call reflect.Type.Method or reflect.Type.MethodByName.
2019-01-05 00:31:46 -08:00
// #define REFLECTMETHOD 1024
2019-09-27 13:11:50 +09:00
// // Function is the top of the call stack. Call stack unwinders should stop
// // at this function.
// #define TOPFRAME 2048
2018-12-30 19:57:01 -08:00
//
const (
NOPROF Attribute = 1 << iota
DUPOK
NOSPLIT
RODATA
NOPTR
WRAPPER
NEEDCTXT
_
TLSBSS
NOFRAME
REFLECTMETHOD
2019-09-27 13:11:50 +09:00
TOPFRAME
2018-12-30 19:57:01 -08:00
)
// 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.
func ( a Attribute ) Asm ( ) string {
parts , rest := a . split ( )
if len ( parts ) == 0 || rest != 0 {
parts = append ( parts , fmt . Sprintf ( "%d" , rest ) )
}
return strings . Join ( parts , "|" )
}
2019-01-05 00:31:46 -08:00
// ContainsTextFlags returns whether the Asm() representation requires macros in "textflags.h".
2018-12-30 19:57:01 -08:00
func ( a Attribute ) ContainsTextFlags ( ) bool {
flags , _ := a . split ( )
return len ( flags ) > 0
}
// split splits a into known flags and any remaining bits.
func ( a Attribute ) split ( ) ( [ ] string , Attribute ) {
var flags [ ] string
var rest Attribute
for a != 0 {
i := uint ( bits . TrailingZeros16 ( uint16 ( a ) ) )
2018-12-30 21:45:35 -08:00
bit := Attribute ( 1 ) << i
2018-12-30 19:57:01 -08:00
if flag := attrname [ bit ] ; flag != "" {
flags = append ( flags , flag )
} else {
rest |= bit
}
a ^ = bit
}
return flags , rest
}
var attrname = map [ Attribute ] string {
2019-09-27 13:11:50 +09:00
NOPROF : "NOPROF" ,
DUPOK : "DUPOK" ,
NOSPLIT : "NOSPLIT" ,
RODATA : "RODATA" ,
NOPTR : "NOPTR" ,
WRAPPER : "WRAPPER" ,
NEEDCTXT : "NEEDCTXT" ,
TLSBSS : "TLSBSS" ,
NOFRAME : "NOFRAME" ,
REFLECTMETHOD : "REFLECTMETHOD" ,
TOPFRAME : "TOPFRAME" ,
2018-12-30 19:57:01 -08:00
}