GCC: как сказать GCC поместить «основную» функцию в начало раздела .text?

Я только начал изучать программирование на ARM и столкнулся с немного раздражающей проблемой. Набор инструментов, который я использую для компиляции своих исходных кодов, называется Sourcery CodeBench Lite 2013.05-23 (можно найти здесь: https://sourcery.mentor.com/GNUToolchain/release2449)

Что мне нужно, так это сказать GCC, LD или OBJCOPY, чтобы поместить скомпилированный байт-код «основной» функции в начало раздела .text.

Есть ли способ добиться этого? (может быть, через скрипт компоновщика?)

Спасибо


person Zuzu Corneliu    schedule 19.10.2013    source источник


Ответы (3)


Решил проблему. Для тех, кто с этим сталкивается:

  • При компиляции с помощью GCC добавьте параметр -ffunction-sections в командную строку. Это укажет GCC поместить каждую функцию в отдельный раздел. Формат имени раздела будет .text.#имя функции# без # (то есть, если функция принадлежит к разделу .text [ который по умолчанию правда ]).
  • Во-вторых, используйте скрипт компоновщика, чтобы расположить эти «функциональные разделы» в последнем большом разделе .text. Например, если поместить функцию main в начало раздела .text, LD-скрипт будет выглядеть примерно так:

    ENTRY(main)
    SECTIONS
    {
        .text :
        {
            *(.text.main);
            *(.text*);
        }
    }
    
person Zuzu Corneliu    schedule 22.10.2013
comment
Вы также можете использовать: 'int main(int argc, char **argv) __attribute__((section(.text.main)));' а остальные оставьте в разделе по умолчанию. - person Goswin von Brederlow; 28.02.2015

Во-первых, посмотрите, как раздел .text определен в вашем скрипте компоновщика gcc по умолчанию (так что вам не нужно создавать свой собственный), вызвав его как:

gcc -Wl,-verbose

который распечатает сценарий компоновщика по умолчанию. Мой показывает это для раздела .text:

/* text: Program code section */
  .text : 
  {
    *(.text)
    *(.text.*)
    *(.gnu.linkonce.t.*)
  }

Таким образом, чтобы функция «main» была первой в разделе .text (а остальные были непрерывными), вы должны установить атрибут «section» для всех остальных функций. Например:

void main(void);
void funct1(....) __attribute__ ((section (".text.A")));
void funct2(....) __attribute__ ((section (".text.A")));
void funct3(....) __attribute__ ((section (".text.A")));

Достаточно «атрибутировать» прототипы функций. Таким образом, когда вы сейчас скомпилируете, «основная» функция будет первой в разделе «.text», а все остальные будут следовать сразу же по последовательным адресам.

Если вы хотите разместить раздел «.text» (т. е. «основную» функцию) по определенному адресу (например, 0x1000), не забудьте связать его с:

gcc .... -Wl,-Ttext=0x1000
person Galland    schedule 21.01.2015
comment
Хотя это будет работать, добавление раздела ко всем другим функциям - далеко не самый простой способ - см. принятый ответ для более простого решения. - person mdma; 11.02.2015

Вы также можете просто поместить «main» в отдельный раздел, используя __attribute__:

int main (void) __attribute__ ((section ("entry")));

а затем в файле ld:

ENTRY(main)
SECTIONS
{
    .text :
    {
        *(main)
        *(.text)
    }
}

Есть много других интересных __attributes__, подробнее о них читайте здесь: http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

person ordahan    schedule 08.11.2013
comment
Правильный тип возвращаемого значения для mainint, а не void. (void main(void) может быть разрешено некоторыми компиляторами; int main(void) является универсальным для размещенных реализаций.) - person Keith Thompson; 09.11.2013
comment
Был просто пример использования __attributes__ - не знаю, как выглядит его main :) - person ordahan; 09.11.2013
comment
Тогда вы должны были выбрать одну из двух допустимых подписей для main. clang отказывается компилировать void main(). - person Peter Cordes; 25.08.2018
comment
@PeterCordes: это не единственные две действительные подписи. Если кто-то строит в автономной (не размещенной) среде (что может быть в случае с этим вопросом - это понятно). Я ожидаю, что CLANG позволит скомпилировать его при использовании -ffreestanding - person Michael Petch; 25.08.2018
comment
@MichaelPetch: хороший момент. Да, это касается gcc и clang. godbolt.org/z/l5JGTu. (Оказывается, и gcc, и clang reject void main() теперь находятся в режиме хостинга по умолчанию. Я все еще думаю, что это хорошее редактирование, хотя этот конкретный вопрос, скорее всего, будет касаться автономного кода. - person Peter Cordes; 25.08.2018
comment
@PeterCordes: вообще не сомневаюсь в редактировании. Также можно использовать подпись, которая работает в обоих случаях, поэтому я поддерживаю это изменение. Я только сделал замечание о действительных подписях в целом. - person Michael Petch; 25.08.2018