Added raw syscall shim `_memfd_secret()` and testing func `_has_memfd_secret()`. Added passthu resolver target for when enabled, started re-write `memfd_create()` shim polyfil resolver target.
Initial commit Fortune for memfd_secret-shim's current commit: Future small blessing − 末小吉master
commit
b8c2a2c3d6
@ -0,0 +1,9 @@
|
||||
obj/
|
||||
prof/
|
||||
perf/
|
||||
*.a
|
||||
*.o
|
||||
*-debug
|
||||
*-release
|
||||
*.so
|
||||
*.gch
|
@ -0,0 +1,323 @@
|
||||
# Generic C and C++ Makefile project template
|
||||
# Contains targets for `release', `debug', and `clean'.
|
||||
PROJECT=memfd_secret-shim
|
||||
AUTHOR=Avril (Flanchan) <flanchan@cumallover.me>
|
||||
DESCRIPTION=
|
||||
VERSION=0.0.0
|
||||
|
||||
SRC = src
|
||||
|
||||
SRC_C = $(shell find $(SRC)/ -type f -name \*.c)
|
||||
SRC_CXX = $(shell find -O2 $(SRC)/ -type f -name \*.cpp -or -name \*.cxx)
|
||||
|
||||
INCLUDE=include
|
||||
# If PCH should be auto-included for all TUs, set to 1.
|
||||
INCLUDE_PCH_GLOBAL?=0
|
||||
# Files to be auto-included by all TUs (after PCH global, if `INCLUDE_PCH_GLOBAL == 1`.)
|
||||
INCLUDE_GLOBAL=
|
||||
|
||||
# Link to these libraries dynamicalls
|
||||
SHARED_LIBS=fmt
|
||||
# Link to these libraries statically
|
||||
STATIC_LIBS=
|
||||
|
||||
# Pre-compile these headers
|
||||
PCH_HEADERS+=
|
||||
# PCH_HEADERS depend on these header files
|
||||
PCH_INCLUDES+=
|
||||
|
||||
# Link executable statically (in release builds only.)
|
||||
STATIC?=no
|
||||
|
||||
# Compile-time default program features (see `Features application` below.)
|
||||
FEATURES?=
|
||||
|
||||
# Build constants
|
||||
CONSTANTS+=_GNU_SOURCE
|
||||
|
||||
override __COMMA=,
|
||||
override __VERSION_SPLIT:= $(subst ., ,$(VERSION))
|
||||
override __VERSION_REVISION:=$(word 3,$(__VERSION_SPLIT)) 0
|
||||
override __VERSION_SPLIT:= MAJOR:$(word 1,$(__VERSION_SPLIT)) MINOR:$(word 2,$(__VERSION_SPLIT)) BUGFIX:$(word 1,$(subst r, ,$(__VERSION_REVISION))) REVISION:$(word 2,$(subst r, ,$(__VERSION_REVISION))) REVISION_STRING:$(word 3,$(__VERSION_SPLIT))
|
||||
|
||||
COMMON_FLAGS+= -W -Wall
|
||||
COMMON_FLAGS+= $(addprefix -D,$(CONSTANTS))
|
||||
COMMON_FLAGS+= -pipe -Wstrict-aliasing -fno-strict-aliasing $(addprefix -I,$(INCLUDE))
|
||||
COMMON_FLAGS+= $(addprefix -D_VERSION_,$(subst :,=,$(__VERSION_SPLIT))) '-D_VERSION="$(VERSION)"'
|
||||
|
||||
# PCH targets for `%_p.hh` -> `%_p.hh.gch`, add `-include $(PCH_HEADERS)` to general `COMMON_FLAGS`, and add $(PCH_OUT) as a requirement for all `%.c/pp` targets as well. (where `PCH_OUT= $(addsuffix .gch,$(PCH_HEADERS))`.)
|
||||
|
||||
# Target arch & CPU. Set to blank for generic
|
||||
ARCH?=native
|
||||
CPU?=native
|
||||
# Enable OpenMP and loop parallelisation? (dyn-links to openmp)
|
||||
PARALLEL?=yes
|
||||
# Enable CPU-specific features
|
||||
CPU_FLAGS?=
|
||||
|
||||
OPT_FLAGS?= -fgraphite \
|
||||
-floop-interchange -ftree-loop-distribution -floop-strip-mine -floop-block \
|
||||
-fno-stack-check
|
||||
|
||||
# Features application
|
||||
|
||||
## Tell program which features are enabled via `FEATURE_<feature name in UPPER_SNAKE_CASE>`.
|
||||
override __FEATURES=$(shell echo "$(FEATURES)" | tr '[:lower:]' '[:upper:]' | tr '-' '_')
|
||||
COMMON_FLAGS+=$(addsuffix =1,$(addprefix -DFEATURE_,$(__FEATURES)))
|
||||
|
||||
## Specific feature additions
|
||||
|
||||
# ## Example:
|
||||
#ifneq (,$(findstring fast-math,$(FEATURES)))
|
||||
# # fast-math feature: Apply `-ffast-math`
|
||||
# COMMON_FLAGS+=-ffast-math
|
||||
#endif
|
||||
|
||||
# Arch and optimisation
|
||||
ifneq ($(ARCH),)
|
||||
OPT_FLAGS+= $(addprefix -march=,$(ARCH))
|
||||
endif
|
||||
|
||||
ifneq ($(CPU),)
|
||||
OPT_FLAGS+= $(addprefix -mtune=,$(CPU))
|
||||
endif
|
||||
|
||||
ifeq ($(PARALLEL),yes)
|
||||
OPT_FLAGS+= -fopenmp -floop-parallelize-all -ftree-parallelize-loops=4
|
||||
endif
|
||||
|
||||
COMMON_FLAGS+=$(addprefix -m,$(CPU_FLAGS))
|
||||
|
||||
CXX_OPT_FLAGS?= $(OPT_FLAGS) -felide-constructors
|
||||
|
||||
CSTD?=gnu2x
|
||||
CXXSTD?=gnu++23
|
||||
|
||||
# Build Options
|
||||
|
||||
STRIP=strip
|
||||
|
||||
RELEASE_COMMON_FLAGS+= -fno-bounds-check
|
||||
DEBUG_COMMON_FLAGS+= -ggdb -gz -ftrapv -fbounds-check
|
||||
|
||||
ifneq ($(TARGET_SPEC_FLAGS),no)
|
||||
RELEASE_CFLAGS?= -O3 -flto $(OPT_FLAGS)
|
||||
RELEASE_CXXFLAGS?= -O3 -flto $(CXX_OPT_FLAGS)
|
||||
RELEASE_LDFLAGS?= -Wl,-O3 -Wl,-flto -fuse-linker-plugin
|
||||
|
||||
DEBUG_CFLAGS?= -Og
|
||||
DEBUG_CXXFLAGS?= -Og
|
||||
|
||||
DEBUG_LDFLAGS?=
|
||||
endif
|
||||
|
||||
ifeq ($(STATIC),yes)
|
||||
RELEASE_LDFLAGS+=-static
|
||||
endif
|
||||
|
||||
DEBUG_CFLAGS+=-DDEBUG $(DEBUG_COMMON_FLAGS)
|
||||
DEBUG_CXXFLAGS+=-DDEBUG $(DEBUG_COMMON_FLAGS) -fasynchronous-unwind-tables
|
||||
|
||||
RELEASE_CFLAGS+=-DRELEASE $(RELEASE_COMMON_FLAGS)
|
||||
RELEASE_CXXFLAGS+=-DRELEASE $(RELEASE_COMMON_FLAGS)
|
||||
|
||||
# Objects
|
||||
|
||||
OBJ_C = $(addprefix obj/c/,$(SRC_C:.c=.o))
|
||||
OBJ_CXX = $(addprefix obj/cxx/,$(SRC_CXX:.cpp=.o))
|
||||
OBJ = $(OBJ_C) $(OBJ_CXX)
|
||||
|
||||
# Pre-compiled header objects
|
||||
|
||||
PCH_HEADERS+=$(shell find -O2 $(INCLUDE) -type f -name \*_p.hh -or -name \*_p.h)
|
||||
|
||||
PCH_OUTPUT_LOCATION=
|
||||
PCH_OUTPUT=$(addprefix $(PCH_OUTPUT_LOCATION),$(addsuffix .gch,$(PCH_HEADERS)))
|
||||
|
||||
PCH_BUILD_COMMON_FLAGS+=-H
|
||||
#-D_PCH_BUILD=1
|
||||
|
||||
PCH_BUILD_CFLAGS+= -x c-header $(PCH_BUILD_COMMON_FLAGS)
|
||||
PCH_BUILD_CXXFLAGS+= -x c++-header $(PCH_BUILD_COMMON_FLAGS)
|
||||
|
||||
PCH_CHEADERS=$(filter %.h,$(PCH_HEADERS))
|
||||
PCH_CXXHEADERS=$(filter %.hh,$(PCH_HEADERS))
|
||||
|
||||
PCH_USE_COMMON_FLAGS+=-Winvalid-pch
|
||||
|
||||
ifeq ($(INCLUDE_PCH_GLOBAL),1)
|
||||
# Globally included
|
||||
PCH_USE_CFLAGS+= $(addprefix -include ,$(realpath $(PCH_CHEADERS)))
|
||||
PCH_USE_CXXFLAGS+= $(addprefix -include ,$(realpath $(PCH_CXXHEADERS)))
|
||||
else
|
||||
# Seperately include them
|
||||
ifneq ($(PCH_OUTPUT_LOCATION),)
|
||||
override PCH_OUTPUT_LOCATION:=$(dir $(PCH_OUTPUT_LOCATION))
|
||||
# XXX: We don't wan't to be using PCH_OUTPUT_LOCATION really...
|
||||
COMMON_FLAGS:= $(addprefix -I,$(dir $(shell find -O3 $(PCH_OUTPUT_LOCATION) -mindepth 1 -type d -printf %p/ ))) $(COMMON_FLAGS)
|
||||
endif
|
||||
endif
|
||||
|
||||
COMMON_FLAGS+=$(addprefix -include ,$(INCLUDE_GLOBAL))
|
||||
|
||||
PCH_USE_CFLAGS+= $(PCH_USE_COMMON_FLAGS)
|
||||
PCH_USE_CXXFLAGS+= $(PCH_USE_COMMON_FLAGS)
|
||||
|
||||
# Compiler Flags
|
||||
|
||||
CFLAGS += $(COMMON_FLAGS) --std=$(CSTD)
|
||||
CXXFLAGS += $(COMMON_FLAGS) --std=$(CXXSTD)
|
||||
LDFLAGS += $(addsuffix .a,$(addprefix -l:lib,$(STATIC_LIBS))) $(addprefix -l,$(SHARED_LIBS))
|
||||
|
||||
# PGO
|
||||
|
||||
PROF_FLAGS= -D_PGO_GEN -fprofile-generate
|
||||
PGO_OBJ_C= $(addprefix prof/c/,$(SRC_C:.c=.o))
|
||||
PGO_OBJ_CXX= $(addprefix prof/cxx/,$(SRC_CXX:.c=.o))
|
||||
PGO_OBJ= $(PGO_OBJ_C) $(PGO_OBJ_CXX)
|
||||
|
||||
PROF_ITERATIONS=10
|
||||
PROF_LOCATION?=/tmp/$(PROJECT)-pgo
|
||||
PROF_LARGE_BOUND= 10240
|
||||
PROF_SMALL_BOUND= 1024
|
||||
|
||||
# Phonies
|
||||
|
||||
# XXX: This doesn't force them to run in series for some reason?
|
||||
.PHONY: release
|
||||
release: | dirs $(PROJECT)-release
|
||||
|
||||
.PHONY: debug
|
||||
debug: | dirs $(PROJECT)-debug
|
||||
|
||||
.PHONY: pgo
|
||||
pgo: | dirs $(PROJECT)-pgo
|
||||
|
||||
# Targets
|
||||
|
||||
.PHONY: pch
|
||||
pch: | dirs $(PROJECT)-pch
|
||||
@echo 'WARNING: When building target $(PROJECT)-pch, the PCH file(s) will not be built with the default auto-opts enabled by targets of kind `debug` or `release`. This should only be used when full manually overriding all compile and linker flags' >&2
|
||||
|
||||
$(PROJECT)-pch: $(PCH_OUTPUT)
|
||||
@echo ""
|
||||
@echo 'PCH: $(PCH_OUTPUT)' '<-' '$(PCH_HEADERS)'
|
||||
@echo " with: $(PCH_INCLUDES)"
|
||||
@echo 'C: $(PCH_CHEADERS)'
|
||||
@echo 'C++: $(PCH_CXXHEADERS)'
|
||||
# Invoking target `pch` itself is not necissary, they are build automatically where they are used.
|
||||
|
||||
dirs:
|
||||
@mkdir -p $(addprefix {obj$(__COMMA)prof}/c{$(__COMMA)xx}/,$(shell find $(SRC)/ -type d))
|
||||
|
||||
|
||||
$(PCH_OUTPUT_LOCATION)%.hh.gch: CXXFLAGS+=$(PCH_BUILD_CXXFLAGS)
|
||||
$(PCH_OUTPUT_LOCATION)%.hh.gch: %.hh $(PCH_INCLUDES)
|
||||
@mkdir -p $(dir $@)
|
||||
$(CXX) $(CXXFLAGS) -o $@ -c $<
|
||||
|
||||
$(PCH_OUTPUT_LOCATION)%.h.gch: CFLAGS+=$(PCH_BUILD_CFLAGS)
|
||||
$(PCH_OUTPUT_LOCATION)%.h.gch: %.h $(PCH_INCLUDES)
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
obj/c/%.o: CFLAGS+= $(PCH_USE_CFLAGS)
|
||||
obj/c/%.o: %.c $(PCH_OUTPUT)
|
||||
$(CC) -c $< $(CFLAGS) -o $@
|
||||
|
||||
obj/cxx/%.o: CXXFLAGS+= $(PCH_USE_CXXFLAGS)
|
||||
obj/cxx/%.o: %.cpp $(PCH_OUTPUT)
|
||||
$(CXX) -c $< $(CXXFLAGS) -o $@
|
||||
|
||||
prof/c/%.o: CFLAGS+= $(PCH_USE_CFLAGS)
|
||||
prof/c/%.o: %.c $(PCH_OUTPUT)
|
||||
$(CC) -c $< $(CFLAGS) -o $@ $(PROF_FLAGS)
|
||||
#$(LDFLAGS)
|
||||
|
||||
prof/cxx/%.o: CXXFLAGS+= $(PCH_USE_CXXFLAGS)
|
||||
prof/cxx/%.o: %.cpp $(PCH_OUTPUT)
|
||||
$(CXX) -c $< $(CXXFLAGS) -o $@ $(PROF_FLAGS)
|
||||
#$(LDFLAGS)
|
||||
|
||||
$(PROJECT)-release: CFLAGS+= $(RELEASE_CFLAGS) $(PCH_USE_CFLAGS)
|
||||
$(PROJECT)-release: CXXFLAGS += $(RELEASE_CXXFLAGS) $(PCH_USE_CXXFLAGS)
|
||||
$(PROJECT)-release: LDFLAGS += $(RELEASE_LDFLAGS)
|
||||
$(PROJECT)-release: $(OBJ)
|
||||
$(CXX) $^ $(CXXFLAGS) -o $@ $(LDFLAGS)
|
||||
$(STRIP) $@
|
||||
|
||||
$(PROJECT)-debug: CFLAGS+= $(DEBUG_CFLAGS) $(PCH_USE_CFLAGS)
|
||||
$(PROJECT)-debug: CXXFLAGS += $(DEBUG_CXXFLAGS) $(PCH_USE_CXXFLAGS)
|
||||
$(PROJECT)-debug: LDFLAGS += $(DEBUG_LDFLAGS)
|
||||
$(PROJECT)-debug: $(OBJ)
|
||||
$(CXX) $^ $(CXXFLAGS) -o $@ $(LDFLAGS)
|
||||
|
||||
pgo-reset:
|
||||
find -O3 prof -type f -name \*.gcda -exec rm {} +
|
||||
|
||||
pgo-generate: CFLAGS+= $(RELEASE_CFLAGS) $(PCH_USE_CFLAGS)
|
||||
pgo-generate: CXXFLAGS+= $(RELEASE_CXXFLAGS) $(PCH_USE_CXXFLAGS)
|
||||
pgo-generate: LDFLAGS+= $(RELEASE_LDFLAGS)
|
||||
pgo-generate: $(PGO_OBJ)
|
||||
$(CXX) $^ $(CXXFLAGS) $(PROF_FLAGS) -o $@ $(LDFLAGS) $(PROF_FLAGS)
|
||||
|
||||
pgo-profile: | pgo-generate pgo-reset
|
||||
set -e errexit && shopt -s inherit_errexit && set -eo pipefail; \
|
||||
rm -rf $(PROF_LOCATION); \
|
||||
for i in {0..$(PROF_ITERATIONS)}; do \
|
||||
>&2 printf ">>> Iteration $$i \b\b"; \
|
||||
mkdir -p $(PROF_LOCATION)/{direct,indirect}; \
|
||||
for j in {0..$(PROF_LARGE_BOUND)}; do \
|
||||
./pgo-generate; \
|
||||
done > $(PROF_LOCATION)/full; \
|
||||
for j in {0..$(PROF_SMALL_BOUND)}; do \
|
||||
./pgo-generate > $(PROF_LOCATION)/direct/$$j; \
|
||||
done; \
|
||||
for j in {0..$(PROF_SMALL_BOUND)}; do \
|
||||
./pgo-generate >> $(PROF_LOCATION)/indirect/$$i; \
|
||||
done; \
|
||||
for j in {0..$(PROF_SMALL_BOUND)}; do \
|
||||
./pgo-generate > $(PROF_LOCATION)/direct/$$i-$$j & : ; \
|
||||
done; \
|
||||
for j in {0..$(PROF_SMALL_BOUND)}; do \
|
||||
./pgo-generate >> $(PROF_LOCATION)/indirect/$$i-$$j & : ; \
|
||||
done; \
|
||||
for j in {0..$(PROF_SMALL_BOUND)}; do \
|
||||
./pgo-generate >/dev/null & : ; \
|
||||
done; \
|
||||
wait; \
|
||||
rm -rf $(PROF_LOCATION)/{direct,indirect,full}; \
|
||||
>&2 printf "OK\r"; \
|
||||
done
|
||||
@echo ""
|
||||
rm -rf $(PROF_LOCATION)
|
||||
rm pgo-generate
|
||||
|
||||
pgo-use: CFLAGS+= $(RELEASE_CFLAGS) $(PCH_USE_CFLAGS)
|
||||
pgo-use: CXXFLAGS+= $(RELEASE_CXXFLAGS) $(PCH_USE_CXXFLAGS)
|
||||
pgo-use: LDFLAGS+= $(RELEASE_LDFLAGS)
|
||||
pgo-use: PROF_FLAGS = -fprofile-use -fprofile-correction
|
||||
pgo-use: $(PGO_OBJ)
|
||||
$(CXX) $^ $(CXXFLAGS) $(PROF_FLAGS) -o $@ $(LDFLAGS) $(PROF_FLAGS)
|
||||
|
||||
$(PROJECT)-pgo: CFLAGS+= $(RELEASE_CFLAGS) $(PCH_USE_CFLAGS)
|
||||
$(PROJECT)-pgo: CXXFLAGS+= $(RELEASE_CXXFLAGS) $(PCH_USE_CXXFLAGS)
|
||||
$(PROJECT)-pgo: LDFLAGS+= $(RELEASE_LDFLAGS)
|
||||
$(PROJECT)-pgo: pgo-profile
|
||||
find -O3 ./prof -type f -name \*.o -exec rm {} +
|
||||
$(MAKE) pgo-use
|
||||
mv pgo-use $@
|
||||
strip $@
|
||||
|
||||
clean-source:
|
||||
find -O2 {obj,prof}/ -type f -exec rm {} +
|
||||
|
||||
clean-rebuild: clean-source
|
||||
find $(INCLUDE) $(PCH_OUTPUT_LOCATION) -type f -name \*.gch -exec rm {} +
|
||||
|
||||
|
||||
clean: clean-rebuild
|
||||
rm -f $(PROJECT)-{release,debug,pgo}
|
||||
|
||||
clean-full: clean
|
||||
rm -rf {obj,prof}
|
@ -0,0 +1,23 @@
|
||||
#ifndef __MEMFD_SECRET_SHIM_H
|
||||
#define __MEMFD_SECRET_SHIM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// Explicit wrapper
|
||||
int _memfd_secret(unsigned int flags);
|
||||
|
||||
/// Returns nonzero if `memfd_secret()` syscall (and `_memfd_secret()` wrapper func.) is available on this device.
|
||||
int _has_memfd_secret();
|
||||
|
||||
/// `ifunc` wrapper.
|
||||
///
|
||||
/// Falls back to `memfd_create()` on failure.
|
||||
int memfd_secret(unsigned int flags);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __MEMFD_SECRET_SHIM_H */
|
@ -0,0 +1,11 @@
|
||||
#ifndef _IT_IFUNC_H
|
||||
#define _IT_IFUNC_H
|
||||
//! ifunc helpers
|
||||
|
||||
#define IFUNC_NAME(name, ver) _impl__ ## name ## __ ## ver
|
||||
#define IFUNC_IMPL(name, ver) __attribute__((copy(name))) IFUNC_NAME(name, ver)
|
||||
#define IFUNC_RESOLVER_A(attr, name) __attribute__((returns_nonnull)) (* __attribute__(attr) _ifun__ ## name (void)) // When the ifunc resolver wants to return a function pointer that has attributes on it, the attribute inner list (e.g. `(returns_nonnull, const, nonnull)') can be provided as the first argument
|
||||
#define IFUNC_RESOLVER(name) IFUNC_RESOLVER_A((copy(name)), name)
|
||||
#define IFUNC_DEF(name, params) name params __attribute__((__ifunc__("_ifun__" #name)))
|
||||
|
||||
#endif /* _IT_IFUNC_H */
|
@ -0,0 +1,75 @@
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "ifunc.h"
|
||||
|
||||
#include <memfd_secret.h>
|
||||
|
||||
#define READ_ONCE(slot) ((__typeof__(slot))(*(const volatile __typeof__(slot)*)(slot)))
|
||||
#define WRITE_ONCE(slot, value) (*((volatile __typeof__(slot)*)(slot)) = (value))
|
||||
|
||||
__attribute__((gnu_inline))
|
||||
static inline
|
||||
int _memfd_secret_raw(unsigned int flags)
|
||||
{
|
||||
return syscall(SYS_memfd_secret, flags);
|
||||
}
|
||||
|
||||
int _memfd_secret(unsigned int flags)
|
||||
{
|
||||
return _memfd_secret_raw(flags);
|
||||
}
|
||||
|
||||
__attribute__((gnu_inline))
|
||||
static inline
|
||||
int _has_memfd_secret_raw()
|
||||
{
|
||||
int fd = _memfd_secret(FD_CLOEXEC);
|
||||
|
||||
// If failure to create new fd was caused by `ENOSYS`, it is not available.
|
||||
if(fd < 0 && errno == ENOSYS)
|
||||
return 0;
|
||||
// If `fd` returned was valid, close it.
|
||||
else if(fd >= 0) close(fd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _$has_memfd_secret = -1; //XXX: I don't think this needs to be _Atomic... But it might... (TODO: Maybe change this to use `call_once()` instead?)
|
||||
// NOTE: Making this `static` visible to TU allows IFUNC resolver to also set it, and therefore `_has_memfd_secret_raw()` may never need to be called. (XXX: Unless resolver itself calls `_has_memfd_secret()` (below V) in which case the exposure isn't needed and this can be moved back to the function body as `has` to de-clutter TU namespace a bit.)
|
||||
|
||||
int _has_memfd_secret() {
|
||||
#define has _$has_memfd_secret
|
||||
int ok;
|
||||
if(__builtin_expect( (ok = READ_ONCE(has)) == -1, 0)) {
|
||||
ok = _has_memfd_secret_raw();
|
||||
WRITE_ONCE(has, ok);
|
||||
//TODO: How to add memory barrier after `WRITE_ONCE()` call? Look up GCC's memory barrier builtin. (XXX: If we're doing that, we may as well do as said above and change this to use `call_once()` to set or a `relaxed` atomic, idk... This function shouldn't be called much anyway, so.
|
||||
return ok;
|
||||
}
|
||||
#undef has
|
||||
return ok;
|
||||
}
|
||||
|
||||
/// Set as IFUNC target for systems with `memfd_secret()` support enabled.
|
||||
__attribute__((visibility("hidden"))) //XXX: `hidden` is the "can only be accessed outside .so from returned internal function pointer", right? and `internal` is "can *never* be accessed outside of .so"? (TODO: Check. Idk if this is the other way around.)
|
||||
int memfd_secret_$enabled(unsigned int flags)
|
||||
{
|
||||
return _memfd_secret_raw(flags);
|
||||
}
|
||||
|
||||
/// Set as IFUNC target for systems *without* `memfd_secret()` support enabled.
|
||||
///
|
||||
/// The call is forwarded to `memfd_create()` instead.
|
||||
__attribute__((visibility("hidden")))
|
||||
int memfd_secret_$disabled(unsigned int flags)
|
||||
{
|
||||
if( FD_CLOEXEC != MEMFD_CLOEXEC ) { // NOTE: This is a constant expression, and this code will be removed if they are equal.
|
||||
//TODO: Translate mask `flags`, from `FD_CLOEXEC` (if it is set) -> `MEMFD_CLOEXEC`.
|
||||
}
|
||||
return memfd_create("memfd_secret@?", flags);
|
||||
}
|
||||
|
||||
//TODO: IFUNC resolver for `memfd_secret()` (Above two targets^^)
|
||||
//TODO: Use `ifunc.h`'s macros for defining the ifunc instead of manually, it de-clutters shit and removed repetition.
|
Loading…
Reference in new issue