Получение GCC для компиляции без вставки вызова в memcpy

В настоящее время я использую GCC 4.5.3, скомпилированный для PowerPC 440, и компилирую некоторый код, который не требует libc. У меня нет прямых вызовов memcpy(), но компилятор, кажется, вставляет один во время сборки.

Существуют опции компоновщика, такие как -nostdlib, -nostartfiles, -nodefaultlibs, но я не могу их использовать, так как не выполняю фазу линковки. Я только компилирую. С чем-то вроде этого:

$ powerpc-440-eabi-gcc -O2 -g -c -o output.o input.c

Если я проверяю output.o с помощью nm, я вижу ссылку на memcpy:

$ powerpc-440-eabi-nm output.o | grep memcpy
     U memcpy
$ 

Страница руководства GCC проясняет, как удалять вызовы memcpy и другие вызовы libc с помощью компоновщика, но я не хочу, чтобы компилятор вставлял их в первую очередь, так как я использую совершенно другой компоновщик (не ld GNU и он не знает о libc).

Спасибо за любую помощь, которую вы можете предоставить.

5 ответов

Решение

Вам нужно отключить эту оптимизацию с помощью -fno-builtin. У меня была эта проблема однажды, когда я пытался скомпилировать memcpy для библиотеки C. Это называло себя. К сожалению!

Там нет необходимости -fno-builtins или же -ffreestanding поскольку они будут без необходимости отключать многие важные оптимизации

Это на самом деле "оптимизировано" шаблонами gcc tree-loop-distribution-pattern, поэтому для отключения нежелательного поведения при сохранении полезных встроенных возможностей вы можете просто использовать:

-fno-tree-loop-distribute-patterns

Musl-libc использует этот флаг для своей сборки и имеет следующее примечание в своем скрипте configure (я просмотрел исходный код и не нашел никаких макросов, поэтому этого должно быть достаточно)

# Проверьте параметры, которые могут потребоваться для предотвращения компиляции
# создание самореферентных версий memcpy, memmove, memcmp,
# и memset. На самом деле, мы должны добавить проверку, чтобы определить, если это
Опция # достаточна, и если нет, добавьте макрос для
# работает с volatile...
# tryflag CFLAGS_MEMOPS -fno-дерево-петля-распространять-шаблоны

Вы также можете добавить это как атрибут к отдельным функциям в gcc, используя его атрибут optimize, чтобы другие функции могли извлечь выгоду из вызова mem*()

Gcc в некоторых случаях отправляет вызов memcpy, например, если вы копируете структуру. Нет способа изменить поведение GCC, но вы можете попытаться избежать этого, изменив свой код, чтобы избежать такого копирования. Лучше всего посмотреть на сборку, чтобы выяснить, почему gcc выпустил memcpy, и попытаться обойти ее. Это будет раздражать, так как вам нужно понять, как работает gcc.

Выдержка из http://gcc.gnu.org/onlinedocs/gcc/Standards.html:

Большинство подпрограмм поддержки компилятора, используемых GCC, присутствуют в libgcc, но есть несколько исключений. GCC требует, чтобы автономная среда предоставляла memcpy, memmove, memset и memcmp. Наконец, если используется __builtin_trap, а цель не реализует шаблон прерывания, то GCC будет выдавать вызов для прерывания.

Вы также можете сделать свой двоичный файл "автономным":

Стандарт ISO C определяет (в разделе 4) два класса соответствующей реализации. Соответствующая размещенная реализация поддерживает весь стандарт [...]; соответствующая отдельно стоящая реализация требуется только для предоставления определенных библиотечных средств: тех, которые находятся в,, и; начиная с AMD1, также и в; и в C99, также в и. [...].

Стандарт также определяет две среды для программ: автономную среду, требуемую для всех реализаций и которая может не иметь библиотечных средств, кроме тех, которые требуются для автономных реализаций, где обработка запуска и завершения программы определяется реализацией, и размещенная среда, которая не требуется, в котором предоставляются все возможности библиотеки, а запуск осуществляется через функцию int main (void) или int main (int, char *[]).

Ядро ОС будет автономной средой; программа, использующая возможности операционной системы, обычно находится в размещенной реализации.

(пункт добавлен мной)

Больше здесь. И соответствующий параметр gcc /s (ключевые слова -freestanding или же -fno-builtin) можно найти здесь.

Это довольно старый вопрос, но я столкнулся с той же проблемой, и ни одно из решений здесь не сработало.

Итак, я определил эту функцию:

      static __attribute__((always_inline)) inline void* imemcpy (void *dest, const void *src, size_t len) {
  char *d = dest;
  const char *s = src;
  while (len--)
    *d++ = *s++;
  return dest;
}

А потом использовал его вместо memcpy. Это решило проблему встраивания для меня навсегда. Не очень полезно, если вы компилируете какую-то библиотеку.

Другие вопросы по тегам