LINUX.ORG.RU

ld

 ,


1

1

Как известно, с помощью ld и objcopy можно линковать произвольные блобы в ELF (примерно так:

$ ld -r -b binary blob.bin -o blob.o
$ objcopy --rename-section .data=.rodata,contents,alloc,load,data blob.o
$ objdump -x blob.o

blob.o:     file format elf64-x86-64
blob.o
architecture: i386:x86-64, flags 0x00000010:
HAS_SYMS
start address 0x0000000000000000

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .rodata       00000100  0000000000000000  0000000000000000  00000040  2**0
                  CONTENTS, ALLOC, LOAD, DATA
SYMBOL TABLE:
0000000000000000 l    d  .rodata	0000000000000000 .rodata
0000000000000000 g       .rodata	0000000000000000 _binary_blob_bin_start
0000000000000100 g       *ABS*	0000000000000000 _binary_blob_bin_size
0000000000000100 g       .rodata	0000000000000000 _binary_blob_bin_end
). Если сослаться на него в C так:
extern const char _binary_blob_bin_start[];
, то всё будет хорошо, а если так:
extern const char *_binary_blob_bin_start;
, то будет сегфолт. Вопрос: где это задокументировано?

Пока нашел http://en.cppreference.com/w/c/language/type#Compatible_types

If two declarations refer to the same object or function and do not use compatible types, the behavior of the program is undefined.

Но это про то, когда у нас в одном исходнике int var[];, а в другом extern int *var;. А у меня вместо первого исходника блоб.

deadNightTiger ★★★★ ()
Ответ на: комментарий от quiet_readonly

Они же - одно и то же в C

Нет. Первое будет ссылкой на массив в блобе, второе ссылка на указатель на const char* в блобе. Т.е. во второом случае прочитает sizeof(char*) байт из этого массива и сделает из них указатель.

mashina ★★★★★ ()

у тебя данные в .rodata, то есть они константные. а указатель сам по себе константный, но не на константные данные. думаю, ему не нравится, что ты пытаешься обращаться к данным в .rodata, как к сегменту .data. попробуй так, например:

extern const char * const _binary_blob_bin_start;

Iron_Bug ★★★★★ ()
Ответ на: комментарий от deadNightTiger

Это как раз полный аналог ситуации.

Что означает char * _binary_blob_bin_start (всякую фигню типа const забудем)? Это означает что где-то есть 8 байт (так как адрес 64 бита в нашем случае), которые составляют оный адрес. Т.е. по адресу, который есть в соответствующей таблицы символов, с именем _binary_blob_bin_start находим 8 байт и используем их как адрес для обращения к какому-то массиву. Так как там реально данные блоба, то получаем скорее всего отлуп.

Что означает char _binary_blob_bin_start[]? То что _binary_blob_bin_start взятый из таблицы символов уже сам является адресом данных и обращения в память за адресом не требуется.

Так как массивы (как объект весьма неопределенной длины) сами по себе не копируются, то вот почти только в качестве аргументов процедур они и не отличимы от указателей. А при появлении в качестве объектов внутри структуры или самостоятельного глобального объекта - грабли видны достаточно отчетливо и можно бы пройти мимо.

Вот перестали лет дцать-дцать тратить время на обучения хотя бы минимальному пониманию соотвествия между реальным кодом машины и языком программирования и тю-тю. В подобные грабли иногда втыкатся люди с неплохим опытом в несколько лет - фантастика.

io ★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.