How can I check the DMD version in compile-time? - version

I can test that DMD is compiling the given code using version(DMD){}, but how can I check which version of it? (2.66/2.65 etc)
More concisely, I want to check that the #nogc modifier exists,
and if not - define a dummy one.
I came up with a workaround:
static if(!__traits(compiles, ()#nogc{}))
{
struct nogc;
}
but is there a better way? for example even checking directly for the existence of that specific modifier?

You can use the predefined __VERSION__ constant.
See also the std.compiler module (version_major and version_minor, specifically) for an easier way to use it.
However, your workaround might be a better approach. It will allow the code to work correctly even for compiler builds between released versions.

Related

C/pre-processor: detect if a __builtin function is available

Is it possible to somehow determine whether an intrinsic function, such as __builtin_bswap16 is provided by the compiler? Preferably, I would like to be able to determine whether this function exists using just preprocessor.
In my particular case, I was using __builtin_bswap16 / 32 / 64 functions in my code which worked fine with GCC 4.x when compiling for 32-bit. Later I switched to a 64-bit Linux and noticed that __builtin_bswap16 suddenly disappeared - I received a linker error:
"undefined reference to `__builtin_bswap16'".
I guess this has something to do with the availability of certain ASM operations in 64-bit mode.
On a later occasion I was trying to compile this code on a different machine where unfortunately only an older version of GCC is installed and does not support these functions at all.
I would like to make this code compilable everywhere, using __builtin_bswap functions if provided, and fall back to hand-coded byteswap routine if not. Is it possible to achieve this somehow with just preprocessor?
My obvious attempt, e.g.:
...
#define MYBSWAP16(v) (v>>8)|(v<<8)
#ifdef __builtin_bswap16
printf("bswap16 is defined : %04x\n", __builtin_bswap16(0x1234));
#else
printf("bswap16 is not defined : %04x\n", MYBSWAP16(0x1234) );
#endif
...
was not successful, as __builtin_bswap16/32/64 are always evaluated to be undefined. Is there any way to make it work automatically within the C source, or is the only way to manually define constants in the Makefile, e.g. HAVE_BSWAP and pass them via -D option?
Please note that my question is not necessarily specific to __builtin_bswap, I'm looking for a general way to detect if the certain functions are available.
Unavailability of __builtin_bswap16 is a gcc bug which was fixed in gcc 4.8.
Sincw it is missing from some versions of gcc you can always add it to your code yourself :
static inline unsigned short __builtin_bswap16(unsigned short a)
{
return (a<<8)|(a>>8);
}

How to automatically call all functions in C source code

have you ever heard about automatic C code generators?
I have to do a kind of strange API functionality research which includes at least one attempt of every function execution. It may lead to crushes, segmentation faults - no matter. I just need to register every function call.
So i got a long list (several hundreds) of functions from sources using
ctags -x --c-kinds=f *.c
Can i use any tool to generate code calling every of them? Thanks a lot.
UPD: thanks for all your answers.
You could also consider customizing the GCC compiler, e.g. with a MELT extension (which e.g. would generate the testing during some customized compilation). Then you might even define your own #pragma or __attribute__ to parameterize these functions (enabling their auto-testing, giving default arguments for testing, etc etc).
However, I'm not sure it is the right approach for unit testing. There are many unit testing frameworks (but I am not very familiar with them).
Maybe something like autoconf could help you with that: as described here. In particular check for AC_CHECK_FUNCS. Autoconf creates small programs to test the existence of registered functions.

How to check if the function is available on compiler?

Is there a way to detect in compilation-time, if a function is built-in on compiler?
e.g, something like this:
#ifndef ITOA_FUNCTION
#define itoa myitoaimplementation
#endif
Thanks in advance.
No, there's not anything direct. About the best you can do is guess from things like the platform, compiler version, etc.
In most cases, I'd prefer one of two other routes though. One is to just give your own implementation a name different from what the compilers use, and always use it whether the compiler provides something similar or not.
The second is to put your implementations of functions like this into a separate file, and deal with the presence/absence in the makefile, just deciding whether to include that file in the project or not.

Is there a list of minimum gcc version supporting each __attribute__?

The official documentation here only lists the minimum required version for a very small number of attributes:
http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
Is there a complete list of which version each attribute was added in? Even better would be a list that also shows which ones are compatible with pcc and tcc.
For gcc versions:
http://www.ohse.de/uwe/articles/gcc-attributes.html
For pcc:
http://pcc.ludd.ltu.se/fisheye/browse/~raw,r=HEAD/pcc/pcc/cc/ccom/gcc_compat.c
For tcc:
??
For a lot of the useful ones you can copy the gcc version tests from glib's gmacros.h:
http://git.gnome.org/browse/glib/tree/glib/gmacros.h
Depending on your project you may also be able to just use GLib, and then use G_GNUC_NORETURN or whatever instead of the __attribute__ directly.
It probably would be better in principle to do HAVE_GCC_ATTRIBUTE_NORETURN as Juliano suggests, but it may also be YAGNI work, depending on your project.
I found this link which is slightly newer than the accepted answer:
https://patchwork.ozlabs.org/project/gcc/patch/20170706132518.GO3988#redhat.com/
Apparently up to 8.1.0. Not sure it is complete though.
Do yourself a favor and don't do that.
Perhaps your software has some pre-compilation configuration/setup phase (like the autoconf team... ugh! (shivers) or something more sane like CMake), use that.
Write small tests (autoconf macros) that check if the compiler accepts the __attribute__ you are interested in and if it works as expected. If successful, write a HAVE_GCC_ATTRIBUTE_XXX macro in a config.h file which is included from your source.
Then use that macro with #ifdef to test if you should put or not the attribute in the function, or perhaps if you should use another hack to emulate the lack of the attribute.

Change library load order at run time (like LD_PRELOAD but during execution)

How do I change the library a function loads from during run time?
For example, say I want to replace the standard printf function with something new, I can write my own version and compile it into a shared library, then put "LD_PRELOAD=/my/library.so" in the environment before running my executable.
But let's say that instead, I want to change that linkage from within the program itself. Surely that must be possible... right?
EDIT
And no, the following doesn't work (but if you can tell me how to MAKE it work, then that would be sufficient).
void* mylib = dlopen("/path/to/library.so",RTLD_NOW);
printf = dlsym(mylib,"printf");
AFAIK, that is not possible. The general rule is that if the same symbol appears in two libraries, ld.so will favor the library that was loaded first. LD_PRELOAD works by making sure the specified libraries are loaded before any implicitly loaded libraries.
So once execution has started, all implicitly loaded libraries will have been loaded and therefore it's too late to load your library before them.
There is no clean solution but it is possible. I see two options:
Overwrite printf function prolog with jump to your replacement function.
It is quite popular solution for function hooking in MS Windows. You can find examples of function hooking by code rewriting in Google.
Rewrite ELF relocation/linkage tables.
See this article on codeproject that does almost exactly what you are asking but only in a scope of dlopen()'ed modules. In your case you want to also edit your main (typically non-PIC) module. I didn't try it, but maybe its as simple as calling provided code with:
void* handle = dlopen(NULL, RTLD_LAZY);
void* original;
original = elf_hook(argv[0], LIBRARY_ADDRESS_BY_HANDLE(handle), printf, my_printf);
If that fails you'll have to read source of your dynamic linker to figure out what needs to be adapted.
It should be said that trying to replace functions from the libc in your application has undefined behavior as per ISO C/POSIX, regardless of whether you do it statically or dynamically. It may work (and largely will work on GNU/Linux), but it's unwise to rely on it working. If you just want to use the name "printf" but have it do something nonstandard in your program, the best way to do this is to #undef printf and #define printf my_printf AFTER including any system headers. This way you don't interfere with any internal use of the function by libraries you're using...and your implementation of my_printf can even call the system printf if/when it needs to.
On the other hand, if your goal is to interfere with what libraries are doing, somewhere down the line you're probably going to run into compatibility issues. A better approach would probably be figuring out why the library won't do what you want without redefining the functions it uses, patching it, and submitting patches upstream if they're appropriate.
You can't change that. In general *NIX linking concept (or rather lack of concept) symbol is picked from first object where it is found. (Except for oddball AIX which works more like OS/2 by default.)
Programmatically you can always try dlsym(RTLD_DEFAULT) and dlsym(RTLD_NEXT). man dlsym for more. Though it gets out of hand quite quickly. Why is rarely used.
there is an environment variable LD_LIBRARY_PATH where the linker searches for shred libraries, prepend your path to LD_LIBRARY_PATH, i hope that would work
Store the dlsym() result in a lookup table (array, hash table, etc). Then #undef print and #define print to use your lookup table version.

Resources