Хотите знать о COFF Externs - PullRequest
1 голос
/ 13 мая 2010

Microsoft PE / COFF SPEC (v8, раздел 5.4.4) говорит, что когда символ имеет:

  1. Класс хранения IMAGE_SYM_CLASS_EXTERNAL
  2. И номер раздела 0 (IMAGE_SYM_UNDEFINED)

Это поле «значение» (в таблице символов), которое «указывает размер».

Это смущает меня. В частности, мне интересно, «указывает размер чего?».

Как правило, IMAGE_SYM_CLASS_EXTERNAL и IMAGE_SYM_UNDEFINED используются CL (Visual C ++) для представления внешних объектов.

Почему компоновщик должен знать или заботиться о размере символа? Разве ему просто не нужно знать имя, это extern и иметь соответствующие записи перемещения? Ничто из этого не должно зависеть от размера. По общему признанию, компилятор должен знать это, но он получит эту информацию из файла заголовка, а не из объектного файла.

Я рассмотрел несколько простых примеров externs, скомпилированных CL, и поле Value всегда кажется нулевым. Таким образом, он явно не используется для кодирования размера поля.

Кто-нибудь знает, на какой «размер» ссылается спецификация? Есть ли в них какие-либо сценарии, в которых компоновщик Visual Studio может использовать это поле, или это явная ошибка в спецификации? Мой ограниченный мозг не может придумать ни одного такого сценария.

* * 1023 Обновление: 1025 **

Обратите внимание, что это, по крайней мере, не всегда, размер символа. В тех случаях, когда я наблюдал, ЗНАЧЕНИЕ ВСЕГДА 0 , отсюда и вопрос.

Ответы [ 4 ]

2 голосов
/ 13 декабря 2010

Мистер Вишневский, я думаю, что нашел ответ. Я студент, и я пытался написать свой собственный компоновщик. Самая первая его версия может связывать OBJ файлы и выводить их в мой собственный двоичный формат. Но вскоре я понял, что многие C ++ язык функции не поддерживаются без LIBCMT.LIB . Итак, сначала я закодировал lib parser ... и застрял при попытке связать CRT . Во втором компоновщике члена файла LIBCMT.LIB было указано, что объектный файл crt0.obj (внутри libcmt ) содержит символ __ acmdln (глобальный указатель на командная строка) ... но мне не удалось найти его там! Я был очень расстроен ... Символ имел IMAGE_SYM_CLASS_EXTERNAL и раздел IMAGE_SYM_UNDEFINED, но почему? В исходном файле crt0.c есть объявление:

#ifdef WPRFLAG
wchar_t *_wcmdln;           /* points to wide command line */
#else  /* WPRFLAG */
char *_acmdln;              /* points to command line */
#endif  /* WPRFLAG */

Мое расследование было довольно длительным, и результат таков:

Компилятор C ++ помещает неинициализированные данные в раздел .bss и помечает их IMAGE_SCN_CNT_UNINITIALIZED_DATA, но чистый компилятор C ведет себя по-другому ( libcmt был написан на C).

В обязанности линкера входит размещение неинициализированных данных в разделах. Если компилятор C выдает символ без секции (0) и помечается как внешний, и если это поле значения равно нулю , тогда оно объявляется где-либо еще, но если поле значения не равно нулю , то означает, что данный OBJ файл действительно содержит этот символ, но он не инициализирован. Поэтому компоновщик должен зарезервировать для него место в разделе .bss . МЕСТО РАЗМЕЩЕНИЯ. И когда вы измените эти строки на:

#ifdef WPRFLAG
wchar_t *_wcmdln = 0xCCCCCCCC; /* points to wide command line */
#else  /* WPRFLAG */
char *_acmdln = 0xCCCCCCCC; /* points to command line */
#endif  /* WPRFLAG */

Будет поле с нулевым значением, и оба они будут помещены в секцию .data .

Удачи и извините за мой плохой английский.

1 голос
/ 19 мая 2010

Как насчет объявления extern для массива, который объявляет размер:

a.cpp:

 extern int example[42];

b.cpp:

 int example[13];

Тот факт, что компоновщик не улавливает это несоответствие, предполагает, однако, что Value не используется. У меня нет простого способа увидеть это.

0 голосов
/ 18 мая 2010

У вас очень экзотический, но интересный вопрос. Это верно, что единственная возможность создать таблицу символов внутри COFF - это использование переключателя компилятора / Zd, который поддерживается до Visual C ++ 6.0 и использовать старый переключатель компоновщика / debugtype: coff (см. http://www.debuginfo.com/articles/gendebuginfo.html#gendebuginfovc6)? Есть ли какая-либо возможность создать таблицу символов внутри COFF хотя бы с Visual Studio 2008?

Моя идея состоит в том, чтобы попытаться создать PE с таблицей символов класса хранения IMAGE_SYM_CLASS_EXTERNAL и номером раздела 0 (IMAGE_SYM_UNDEFINED) относительно переключателя компоновщика / FORCE (/ FORCE: UNRESOLVED или / FORCE: MULTIPLE) и неразрешенного символа либо с помощью / INCLUDE: dummySymbol или / NODEFAULTLIB. Моя проблема в том, что не так просто создать таблицу символов внутри COFF. Где вы получаете тест PE?

0 голосов
/ 17 мая 2010

Это размер структуры данных, обозначаемой символом.

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

...