我试图找出一种在 Linux 上的 C/C++ 可执行文件和库中存储和检索版本信息的好方法。我正在为我的 C 和 C++ 程序使用 GCC 编译器。
存储部分非常简单;声明这样的变量将其存储在输出文件的 .rodata 部分中:
const char MY_VERSION[] = "some_version_information";
但是,我在从外部程序中检索信息时遇到了难以置信的困难。dlopen
使用共享库,使用和加载库和查找符号相当容易dlsym
,但这可能不是最好的方法,而且它根本不适用于可执行文件。另外,如果可能的话,我希望它可以与为不同架构构建的可执行文件和库一起使用。
我认为由于共享库和可执行文件都使用 ELF 格式,因此使用知道如何读取 ELF 文件的库是有意义的。我能找到的两个是 libelf 和 BFD;我正在努力为每个人找到合适的文档。是否有更好的库可以使用?
到目前为止,这是我使用 BFD 所拥有的:
#include <stdio.h> [6/1356]
#include <string.h>
#include <bfd.h>
int main(int argc, char* argv[])
{
const char *filename;
int i;
size_t storage;
bfd *b = NULL;
asymbol **symbol_table;
long num_symbols;
if(argc != 2) return 1; // todo: print a useful message
else filename = argv[1];
b = bfd_openr(filename, NULL);
if(b == NULL){
fprintf(stderr, "Error: failed to open %s\n", filename);
return 1;
}
// make sure we're opening a file that BFD understands
if(!bfd_check_format(b, bfd_object)){
fprintf(stderr, "Error: unrecognized format\n");
return 1;
}
// how much memory is needed to store the symbol table
storage = bfd_get_symtab_upper_bound(b);
if(storage < 0){
fprintf(stderr, "Error: unable to find storage bound of symbol table\n");
return 1;
} else if((symbol_table = malloc(storage)) == NULL){
fprintf(stderr, "Error: failed to allocate memory for symbol table\n");
return 1;
} else {
num_symbols = bfd_canonicalize_symtab(b, symbol_table);
}
for(i = 0; i < num_symbols; i++){
if(strcmp(symbol_table[i]->name, "MY_VERSION") == 0){
fprintf(stderr, "found MY_VERSION\n");
// todo: print the string?
}
}
return 0;
}
我意识到由于 ELF 格式,打印字符串可能不是很简单。
是否有一种直接的方法来打印存储在 ELF 文件中的字符串符号?