pr0gma pr0gma - 1 year ago 55
C Question

Referencing external global variables fails miserably

I'm trying to embed binary file

B
into executable
A
at linking time, on Linux (64bit).

B
is a simple text file...


Hi, I'm a text file in plain ASCII.


...which is turned into a relocatable object with
ld -r -bbinary -oB.o B
. Its
symtab
reports three global variables, the names of which are pretty self-explanatory:


  1. _binary_B_start

  2. _binary_B_end

  3. _binary_B_size



This is
A.c
...


#include <stdio.h>

extern const size_t _binary_B_size;

int main(int argc, char * * argv)
{
printf("size: %zu\n", _binary_B_size);
return 0;
}


...which is compiled and linked with
B.o
:
gcc -oA A.c B.o
.
Unfortunately, as soon as executable
A
tries to access
_binary_B_size
, it gets abruptly terminated with a
SIGSEGV
.

What am I doing wrong?

AnT AnT
Answer Source

Apparently you are misunderstanding the semantics of _binary_B_size. It is not a size_t lvalue, as you seem to believe. It is a zero size absolutely positioned section (a label), whose address equals the size of your binary blob data. Try objdump -t on your file an you will see *ABS* in the corresponding column.

So the proper usage would be

extern unsigned char _binary_B_size[];

int main()
{
    printf("size: %zu\n", (size_t) _binary_B_size);
}

You can also use end - start method and get the same result

extern unsigned char _binary_B_start[];
extern unsigned char _binary_B_end[];

int main()
{
    printf("size: %zu\n", (size_t) (_binary_B_end - _binary_B_start));
}

Basically, the main consideration here is that there's no reason for _binary_B_size to be a size_t lvalue. It is effectively a constant with value pre-determined at compile time. There's no reason for it to occupy storage. And what you see above is one way to encode such constant values in object files.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download