On 08/25/18 19:38, H. Peter Anvin wrote:
>
> If it was worthwhile it would make more sense to at least force this
> into the rodata section with the string, something like the attached
> file for an example; however, I have a hunch it doesn't matter.
>
An even nuttier version which avoids the extra pointer indirection.
Read it and fear.
-hpa
#include <stddef.h>
#include <string.h>
#define _RET_IP_ ((unsigned long)__builtin_return_address(0))
#define no_inline __attribute__((noinline))
#define must_inline __attribute__((always_inline)) inline
struct myputs_string {
unsigned short len;
char str[0];
};
int _myputs_struct(const struct myputs_string * const strs);
int _myputs_string(const char *str);
int __myputs(unsigned long ip, const char *str, size_t len);
int no_inline _myputs_struct(const struct myputs_string * const strs)
{
return __myputs(_RET_IP_, strs->str, strs->len);
}
int no_inline _myputs_string(const char *str)
{
return __myputs(_RET_IP_, str, strlen(str)+1);
}
#define ifconst(x,y) __builtin_choose_expr(__builtin_constant_p(x),(x),(y))
#define myputs(s) \
({ \
int _rv; \
if (__builtin_constant_p(s) && \
__builtin_constant_p(strlen(s)) && \
strlen(s)+1 == sizeof(s) && \
sizeof(s) <= (size_t)65535) { \
static const struct { \
struct myputs_string _mps_hdr; \
char _mps_str[sizeof(s)]; \
} _mps = { \
._mps_hdr.len = sizeof(s), \
._mps_str = ifconst(s,""), \
}; \
_rv = _myputs_struct(&_mps._mps_hdr); \
} else { \
_rv = _myputs_string(s); \
} \
_rv; \
})
int test1(void);
int test2(const char *strx);
int test1(void)
{
return myputs("Foobar");
}
int test2(const char *strx)
{
return myputs(strx);
}