如何在编译时检测ABI?

时间:2017-11-05 09:22:15

标签: c++ c abi

有没有办法在编译时检测C / C ++中的ABI?我知道有OS和CPU架构的宏。 ABI是否有类似的宏(或其他方式)?

1 个答案:

答案 0 :(得分:9)

ABI的概念不为C11或C ++ 14等标准规范所知。这是一个实现的事情。

您可以在Linux上使用feature_test_macros(7)

您可以考虑改进构建过程(例如您的Makefile等)。您可能会运行一些shell脚本检测功能(例如autoconf生成的configure脚本)。请注意,某些C或C ++代码(例如头文件等)可能在构建时生成(例如:bisonmoc,{{3 ,},rpcgen,...),也许是您自己的实用程序或脚本。使用足够好的swig工具(谨慎,build automationGNU make能够处理生成的C ++或C代码并管理其生成和依赖项。)

不要将编译与ninja混淆;运行build的编译命令只是构建过程的部分

某些平台接受多个 ABI。例如。我的带有Linux 4.13内核的Linux / Debian / Sid / x86-64桌面可以运行x86 32位compiler可执行文件,x86-64 64位ELF,可能是20世纪80年代的一些旧ELF格式,也是a.out ABI。使用x32我可以添加更多ABI。有关几个ABI文档的列表,请参阅binfmt_misc

顺便说一句,目前的趋势是尝试编写x86 psABI代码。也许使用portableQtPOCO(以及许多其他)等框架可以将ABI详细信息隐藏到您的应用程序中。

在某些情况下,Glib也可能会有所帮助。

一般而言,一旦了解了自己的操作系统和架构,就可以在大部分时间内推断出ABI。

如果您真的想要您的ABI ,那么可能的Linux特定方式可能是在当前可执行文件上运行libffi我不建议这样做,但您可以尝试(使用file(1)获取可执行文件):

 /// return a heap allocated string describing the ABI of current executable
 //// I don't recommend using this
 const char*getmyabi(void) {
   char mycmdname[80];
   int sz = snprintf(mycmdname, sizeof(mycmdname), 
                     "/usr/bin/file -L /proc/%d/exe",
                     getpid());
   assert (sz < (int) sizeof(mycmdname));
   FILE*f = popen(mycmdname, "r");
   if (!f) { 
      perror(mycmdname); exit(EXIT_FAILURE);
   };
   char* restr = NULL;
   size_t siz = 0;
   getline(&restr, &siz, f);
   if (pclose(f)) { perror("pclose"); exit(EXIT_FAILURE); };
   return restr;
 } // end of getmyabi
 /// the code above in untested

你可以得到一个字符串:

 "ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked,"
 " interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32,"
 "BuildID[sha1]=deca50aa4d3df4d57bacc464aa1e8790449ebf8e, stripped"

然后你需要解析它。您还可能希望在可执行文件,ELF解释器proc(5)等上解析ldd(1)objdump(1)的输出(或者使用一些ELF解析库)。

我不知道getmyabi功能有多大用处。我不知道file给出的精确输出(在各种ABI的所有奇怪情况下)。我让你去测试它(确保用你系统上安装的所有ABI编译你的测试程序,所以gcc -m32gcc -m64gcc -mx32等......);如果可能的话,测试一些非x86 Linux系统。

如果您只需要在构建时获取ABI,请考虑编译一些hello-world可执行文件,然后在其上运行file(和ldd)。有适当的构建规则(Makefile规则),并解析那些fileldd命令的输出。

(我很惊讶你的问题;什么样的应用程序需要知道ABI;大多数需要编译器的软件......;对精确ABI的强烈依赖可能是{{3}的症状}。)

也许给出ld-linux(8)的提示可能适用于您的情况(只是盲目猜测)。

如果您正在编写某些编译器,请考虑其中的undefined behavior,然后在生成的C代码上使用一些现有的C编译器,或者使用here或{{3}等良好的generating some C code库}}。他们会处理ABI特定方面(更重要的是低级优化和代码生成)。

如果您单独编写编译器并且不想使用外部工具,那么实际上您应该将自己局限于一个或几个ABI和平台。 生命短暂。

PS。我完全不确定ABI是否具有确切含义。它更像是一个规范文档,而不是某个系统(或某些可执行文件)的定义特征。 IIUC,ABI规范确实发展了(15年前可能并非完全)。