Why doesn't a linked binary file's _size symbol work correctly?

橙三吉。 提交于 2020-05-15 17:53:27

问题


I use 'ld -r -b binary -o binary.o foo.jpeg' to embed resources in my program. Works awesomely. I just wonder why the int _binary_size symbol never reads correctly, negative or too large a number, but stays the same between program runs. I always gotta do _binary_end - _binary_start, which works flawlessly. It's seems it works for no one... like here .... why is that?

There is no reason not to use end-start as it replaces the size symbol, but it still leaves me curious.

edit: code example.

extern const unsigned char _binary_scna4_jpg_start;
extern const unsigned char _binary_scna4_jpg_end;
extern const int _binary_scna4_jpg_size;

int size = &_binary_scna4_jpg_end - &_binary_scna4_jpg_start;
printf("Size is %d vs %d \n", size, _binary_scna4_jpg_size);

this prints:

Size is 1192071 vs -385906356 

First number is the correct size of the binary and all my images read flawlessly.

Output of nm for good measure:

0000000000123087 D _binary_scna4_jpg_end
0000000000123087 A _binary_scna4_jpg_size
0000000000000000 D _binary_scna4_jpg_start

回答1:


The problem arises because of Position-Independent Executables (PIE). Earlier executables were loaded at the same memory addresses (which were determined at compile/link time) which led to possible attacks because the attacker knew at which address specific parts of programs were. Therefore Address Space Layout Randomization was implemented. This has the side effect that the size symbols being defined as absolute addresses (the _binary_scna4_jpg_size is not an integer value, it's a "pointer" just like _start and _end) also get relocated when they are loaded.

If you compile your code with option -no-pie you can disable position-independence and the _binary_scna4_jpg_size will output the correct value since it will not be relocated. Since PIE is on by default these days the value of the pointer is basically garbage. You could also use it if you knew the beginning of the relocated memory, but since you already have _binary_scna4_jpg_start and _binary_scna4_jpg_end it's the same thing to use them.




回答2:


Your _binary_scna4_jpg_size symbol is not an integer. It's an absolute address symbol. In order to get the size, you would need to take the address of it and cast to an appropriate integral type:

printf("The real size is %td\n", (ptrdiff_t) &_binary_scna4_jpg_size);

This however only works when disabling PIE (gcc -fPIC -no-pie) or linking statically (gcc -static).



来源:https://stackoverflow.com/questions/54844677/why-doesnt-a-linked-binary-files-size-symbol-work-correctly

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!