简体   繁体   English

如何在不使用标准C库的情况下使用编译器内置函数

[英]How to use compiler builtin functions without Standard C library

I know that some functions like sin cos min max memcpy may be treated not as normal functions but may be replaced by built-in functions (which may be more optimal than merely inline function calls, when the replacement is (an) actual processor instruction(s), such as directly calling the FSIN instruction for standard sin function when compiled for an x86 with a floating point unit). 我知道有些函数如sin cos min max memcpy可能不会被视为普通函数,而是可能被内置函数取代(当替换是实际处理器指令时,这可能比仅内联函数调用更为优化( s),例如,为带有浮点单元的x86编译时,直接为标准sin函数调用FSIN指令)。

The question I would like to use power of built-in functions (in C/C++ mostly in mingw/gcc maybe other compiler) but I do not want to link to libc, the Standard C Library). 我想使用内置函数的功能(在C / C ++中主要是在mingw / gcc或其他编译器中),但我不想链接到标准C库libc。

  • Is it possible to use builtins with not linking to libc? 是否可以在不链接到libc的情况下使用内建函数?
  • Are they any command line flags needed to optimize those symbols as a built-ins? 它们是否有任何将这些符号作为内置符号进行优化所需的命令行标志?

    (Related to previous, but rephrased) (与以前有关,但改写为)

  • Will they be automatically recognized by name, or are compiler flag(s) necessary to enable usage of built-ins? 它们会被名称自动识别,还是启用内置功能所必需的编译器标志?

@randomusername has already explained the usage of the __builtin_ prefix for many common Standard C Library functions. @randomusername已经解释了许多常见的标准C库函数使用__builtin_前缀的情况。 I recommend using #define to make the change, while keeping your code clean. 我建议使用#define进行更改,同时保持代码干净。

#include <math.h>

#define  cos   __builtin_cos
#define  sin   __builtin_sin
#define  printf __builtin_printf

...
   printf("Distance is %f\n", cos(M_PI/4.0) * 7);
...

No Standard C Library 没有标准C库

Now to not use the Standard C Library, which means not linking to it, or including the typical startup and exit code stubs, well, with GCC that is possible with the -nostdlib which is equivalent to -nostartfiles and -nodefaultlibs . 现在不要使用 Standard C库,这意味着不使用它,或者不使用典型的启动和退出代码存根,使用-nostdlib可能与-nostartfiles-nodefaultlibs等效的GCC可以。

The issue is that you then have to replace all the library functions you would normally use, including system calls (or their wrappers / macros from glibc) for any kernel based functions. 问题是您必须替换所有通常使用的库函数,包括任何基于内核的函数的系统调用 (或glibc的包装器 /宏)。

I don't know of a portable or robust method that works across processors or even necessarily different families (sysenter vs. syscall ( instruction ) vs. int 0x80 for various 32 and 64-bit x86 processors). 我不知道的便携式跨处理器,甚至工作或可靠的方法必然不同家庭 (SYSENTER与系统调用( 指令 )对int 0x80各种32位和64位x86处理器)。 There is issues with ELF Auxiliary Vectors ( Elf32_auxv_t ) and vDSO ( virtual ELF dynamic shared object ) that may be possible to address and create a portable solution, I don't know. 我不知道, ELF辅助向量Elf32_auxv_t )和vDSO虚拟ELF动态共享对象 )可能存在一些问题,这些问题可能会解决并创建一个便携式解决方案。

Entry Point 入口点

I believe all GCC environments use the same default entry point, which is the label/function _start . 我相信所有GCC环境都使用相同的默认入口点,即标签/函数_start This is normally included in the "Startup files" and then calls the traditional C/C++ entry point of main . 通常将其包含在“启动文件”中,然后调用main的传统C / C ++入口点。 So you would need to replace it with a minimal stub of your own (which can be in C). 因此,您需要用自己的最小存根(可以在C中)替换它。

Program termination 程序终止

I don't know how to replace _exit(rc) or similar function required to correct terminate the program, in a portable fashion. 我不知道如何以可移植的方式替换_exit(rc)或纠正终止程序所需的类似功能。 For example in a Linux environment it needs to make a system call to the kernel function SYS_exit (aka __NR_exit or sys_exit ) 例如,在Linux环境中,它需要对内核函数SYS_exit (aka __NR_exitsys_exit )进行系统调用。

void _start(void) {
    int rc;
    /* Get command line arguments if necessary */
    rc = main(0, NULL);
    your_exit_replacement(rc);
}

Alternatives 备择方案

Normally user processes ie application programs, as opposed to Operating System kernels or drivers, accept the overhead of linking the Startup Files and the necessary overhead to enable dynamic linking to the Startard C Library, as memory is considered cheap and readily available that for any real (actually does something) application the memory saving is not worthwhile. 通常, 用户进程(即应用程序)(而不是操作系统内核或驱动程序)接受链接启动文件的开销和启用动态链接到Startard C库的必要开销,因为内存被认为是廉价的且对于任何实际应用而言都是可用的(实际上是在做某事)应用程序,节省内存是不值得的。 In embedded domain, where it is not as acceptable to just assume plenty of memory is available, the alternative is the use a minimal libc replacement. 在嵌入式域中,仅仅假设有足够的可用内存是不可接受的,替代方法是使用最少的libc替换。 For Linux there are several available (eg musl, uClibc, dietlibc), I don't know if there is one available for mingw or Windows-compatible open source replacements (ReactOS, and Wine). 对于Linux,有几种可用的方法(例如musl,uClibc,dietlibc),我不知道是否有一种可用于mingw或Windows兼容的开放源代码替代品(ReactOS和Wine)。

Further 进一步

For further information, from a Linux platform point of view, there is a nice introduction "Hello from a libc-free world!" 有关更多信息,从Linux平台的角度来看,有一个不错的介绍“来自无libc的世界,您好!” Part 1 and Part 2 by Jessica McKellar blogging at Oracle. Jessica McKellar在Oracle博客上撰写的第1部分第2部分 There are also a number of related questions, and some (partial in some cases) answers here at stackoverflow about using -nostdlib in various circumstances. 还有许多相关的问题,在stackoverflow上 ,有一些(在某些情况下是部分回答) 有关在各种情况下使用-nostdlib的问题。

Where to go from here depends on your goals: education, embedded, tiny program (Linux ELF executable) or Windows PE executable competitions. 从何而来取决于您的目标:教育,嵌入式, 微型程序 (Linux ELF可执行文件)或Windows PE可执行文件竞赛。

Microsoft Windows 微软Windows

There are various articles for a Microsoft Windows environment dealing with .COM and .EXE executables, and Windows PE but using Microsoft's Visual Studio environment or assembly typically. 对于Microsoft Windows环境,涉及.COM和.EXE可执行文件以及Windows PE,但通常使用Microsoft的Visual Studio环境或程序集的文章很多。 The "classics" are Matt Pietrek's Under the Hood column "Reduce EXE and DLL Size with LIBCTINY.LIB" (January 2001 issue of MSDN Magazine) and "Remove Fatty Deposits from Your Applications Using Our 32-Bit Liposuction Tools" from October 1996 Microsoft Systems Journal. Microsoft的“经典”是Matt Pietrek的Under the Hood栏“使用LIBCTINY.LIB减少EXE和DLL大小” (MSDN杂志2001年1月发行)和“使用32位抽脂工具应用程序中删除脂肪沉积” (1996年10月,Microsoft)系统杂志。 Another article, but I haven't read myself, that appears to have include explanations is "Reducing Executable Size" . 另一篇文章,但我还没有读完自己,似乎其中包括了“减小可执行大小”的说明

Lets say you wanted to replace the function cos , all you have to do is replace every occurance of cos in your code with __builtin_cos . 假设您要替换函数cos ,您要做的就是用__builtin_cos替换代码中每次出现的cos The same goes for any other function that you can replace with the compiler's version. 您可以用编译器版本替换的任何其他函数也是如此。 Just prepend __builtin_ to the name. 只需在名称前加__builtin_

For more information consult the gcc manual . 有关更多信息,请参阅gcc手册

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM