Getting the value of *ABS* symbols from C

2019-08-16 18:40发布

问题:

What is the proper way of accessing the actual value of an *ABS* (absolute, not-to-be-relocated) symbol from C?

I'm using ld to embed data (... a HTML template) in an executable (... following the method described in https://csl.name/post/embedding-binary-data/). As in:

ld -r -b binary [the_file_to_be_embedded] -o [some_object.o]

Then, I'm using

const char _some_object_start;
const char _some_object_end;
const int _some_object_size;

in the actual code. The actual linked text works nicely by getting char pointers with &_some_object_start; reading the size keeps breaking in interesting, platform-dependent ways though: on ARM64, (long) &_some_object_size actually ends up being the size, but on x64 the compiler is trying to make it PC-relative and doesn't end up with the right thing.

For reference, this is how the actual symbol table looks like:

SYMBOL TABLE:
00000000 l    d  .data  00000000 .data
0000000d g       .data  00000000 _binary_hello_world_txt_end
0000000d g       *ABS*  00000000 _binary_hello_world_txt_size
00000000 g       .data  00000000 _binary_hello_world_txt_start

(obtained by objdump -x.)

I presume ld adds size data assuming that there is some reasonable way for code linked with it to read it, therefore the question.

(... which is more on the theoretical side, as &_obj_end - &obj_start does still resolve to the actual data length; I'm curious specifically about _obj_size though.)

回答1:

The value of a symbol is its address, so &symbol_name should retrieve it.

example.c

#include <stdio.h>
extern char abs_sym;
int main() { printf("%p\n", (void*)&abs_sym); }

run example:

$ gcc ldabs.c  -no-pie -Wl,--defsym=abs_sym=0xab && ./a.out
  0xab


标签: c ld