2010-05-12 2 views
1

для Microsoft PE/COFF SPEC (v8, раздел 5.4.4) говорит, что, когда символ имеет:Хотите узнать больше о COFF экстернов

класс
  1. хранилищем IMAGE_SYM_CLASS_EXTERNAL
  2. и раздел число 0 (IMAGE_SYM_UNDEFINED)

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

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

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

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

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

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

Update:

Пожалуйста, обратите внимание, что это не так, по крайней мере, не всегда, как представляется, размер символа. В случаях, которые я наблюдал, VALUE ВСЕГДА 0, отсюда и вопрос.

+0

Значит, вы в своем «Обновить», что pSymbolTable-> SectionNumber> 0 (всегда ** NOT ** 0)? Декодирование pSymbolTable в случае (pSymbolTable-> StorageClass == IMAGE_SYM_CLASS_EXTERNAL && pSymbolTable-> SectionNumber> 0) не является проблемой. Проблема заключается только в том, что pSymbolTable-> SectionNumber == 0, то есть IMAGE_SYM_UNDEFINED. – Oleg

ответ

1

Как насчет экстерном декларации для массива, объявляющего размер:

a.cpp:

extern int example[42]; 

б.cpp:

int example[13]; 

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

+0

Спасибо за предложение. В этом случае компилятор все равно испускает 0 для поля Значение. Если компилятор устанавливает его в 0, это не значит, что он не используется, хотя .... –

+0

Да, я так не думал. Вам, вероятно, придется использовать какой-то другой язык, например, Fortran, чтобы он привык. –

+0

Еще раз спасибо. Я надеялся, что смогу найти информацию о том, как компоновщик интерпретирует значение (более того, чем его компилятор). Похоже, мне просто придется испытать, как сумасшедший, чтобы понять это. Я бы хотел, чтобы документы PE/COFF не сосали так много ... После тестирования, чтобы выяснить, что это такое, мне нужно написать, чтобы затем я мог выяснить, что мне нужно для тестирования, - это именно тот вид ситуации, которую мне нравится избегать. Вздох ..... –

0

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

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

+0

Нет! Это не размер структуры данных, на которую ссылается этот символ. По крайней мере, не всегда. Например, если я создаю внешнее поле типа класса, поле Значение в объектном файле заканчивается 0, а не sizeof (FooBar). Кроме того, компоновщику не нужно знать размер со ссылочного сайта. Он должен знать размер раздела, который содержит символ, и смещение (из файла определяющего объекта) и необходимые исправления перемещения (с сайта использования символа), но он не заботится о размере символа. –

0

У вас очень экзотический, но интересный вопрос. Правильно ли это, что единственная возможность создавать таблицу символов внутри 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) с относительно линкера переключателя/СИЛЫ (/ СИЛЫ: неразрешенные или/СИЛЫ: Multiple) и неразрешенного символа либо/INCLUDE: dummySymbol или/NODEFAULTLIB. Моя проблема заключается в том, что создать таблицу символов внутри COFF непросто. Где вы получаете тестовые ПЭ?

+0

Я думаю, вы смешиваете таблицу символов с информацией об отладке COFF. Вы правы, что Visual Studio не производит записи номера строки COFF (отладочная информация), но создает таблицы символов. Компилятор не мог функционировать без них. В любом случае класс хранения символов, о котором идет речь, является внешним, а номер раздела равен 0. Вопрос, который у меня есть, заключается в том, как следует интерпретировать поле Значение. Спектр говорит «размер», за исключением того, что значение равно 0, поэтому это не размер. –

2

Mr.Wisniewski, я считаю, что нашел ответ. Я студент, и я попытался написать собственный линкер. Самая первая его версия может связывать OBJ файлы и сбрасывать их в мой собственный двоичный формат. Но вскоре я понял, что многие C++ языки функции не поддерживаются без LIBCMT.LIB. Итак, сначала я закодировал библиотечный парсер ... и застрял при попытке связать 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++ компилятор места uninitilized данных в раздел .bss и отмечает его IMAGE_SCN_CNT_UNINITIALIZED_DATA, но Чистый компилятор C ведет себя по-другому (libcmt был написан на 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 разделе.

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

Смежные вопросы