Неожиданное значение символа для неинициализированных массивов размером более 64 КБ в объектных файлах COFF - PullRequest
0 голосов
/ 16 января 2019

РЕДАКТИРОВАТЬ: я сделал ошибку при тестировании с компилятором clang. Это работает, как и ожидалось с Clang. Неожиданные результаты получены в Visual Studio 2015. Мой вывод заключается в том, что в Visual Studio 2015 есть что-то подозрительное.

Я сделал замечание, которое не могу объяснить относительно значения символов объектного файла, которые представляют неинициализированные массивы C в объектных файлах COFF, созданных Visual Studio 2015. Это значение должно представлять размер массива в байтах, но это не то, что я наблюдаю. Я надеюсь, что кто-то может объяснить, что здесь происходит.

Рассмотрим исходный файл testdata_works.c

  char testb[0x10002];

Рассмотрим исходный файл testdata_fails.c:

  char testa[0x10001];
  char testb[0x10002];

Теперь скомпилируйте:

cl -c testdata_works.c
cl -c testdata_fails.c

Теперь запустите «dumpbin / symbols» для обоих объектных файлов и обратите внимание на то, как Значение символа «testb» отличается между двумя объектными файлами (!) См. ниже для кровавых подробностей.

dumpbin /symbols testdata_works.obj

006 00010002 UNDEF  notype       External     | testb

Теперь для testdata_fails.obj

dumpbin /symbols testdata_fails.obj

006 00010001 UNDEF  notype       External     | testa
007 00010041 UNDEF  notype       External     | testb

Заметим, что символ testb имеет ожидаемое значение 0x10002 в testdata_works.obj, но имеет неожиданное значение 0x10041 в testdata_fails.obj.

Я сохранил действительно странную часть последней, которая может вызвать Поговорка «а-ха» у тех, кто хорошо разбирается в объектном файле COFF Формат:

Уменьшите размер массивов в testdata_fails.c ниже 0x10000, например:

  char testa[0x0001];
  char testb[0x0002];

и скомпилировать

cl -c testdata_fails.c

Команда dumpbin теперь выдает ожидаемые результаты для символов testa и testb:

006 00000001 UNDEF  notype       External     | testa
007 00000002 UNDEF  notype       External     | testb

Есть ли какие-либо предложения относительно того, что здесь происходит и как это исправить, чтобы получить ожидаемые результаты для значений символов, превышающих 64 КБ?

Заключительные замечания:

Я воспроизвел это, используя clang / llvm-nm 7.0.1 вместо Visual Studio 2015 / dumpbin, так что может быть связано с форматом COFF?

Вы можете справедливо спросить, как я наткнулся на это. Я изучал BSD Ядро genassym.sh и решил написать небольшую программу на C ++ STL, которая достиг той же задачи из любого формата объектного файла, который может быть прочитан библиотеками LLVM. Я построил эту программу, но она не работает должным образом, потому что данные в объектных файлах не соответствуют ожиданиям.

1 Ответ

0 голосов
/ 16 января 2019

COFF не сохраняет размеры массива. Значение, связанное с символом массива, является его начальным адресом. Чтобы вывести размер массива dumpbin, необходимо использовать некоторую эвристику, например, глядя на соседние символы, конец раздела и т. д. По-видимому, эвристический сбой. Только компилятор знает, почему BSS больше, чем можно было бы ожидать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...