avr-ld buffer overflow

Дійсно прикра помилка в avr-ld (binutils-avr 2.25) — та, що спонукала мене до перевірки використання Raspberry Pi як комп’ютера для роботи, — виявилася доволі цікавою.

Почала вивалюватися вона у мене доволі давно, але я помилково вважав, що вона притаманна 64-бітній версії Ubuntu 16.04, бо на роботі в 32-бітній все працювало. Думав, що це якісь проблеми невраховування розмірів чи співвідношення розмірів змінних на зразок «подаруночка від FTDI». Чесно кажучи, у повідомлення не особливо і вчитувався — «та хай, це по роботі, то на роботі й зберу» і вдома більше не запускав аж до того, як нещодавно перезібрати знадобилося негайно, бо це зупиняло термінову роботу. Тоді ж ото зібрав на Raspberry й написав про все це.

Ну й на ключову фразу *** buffer overflow detected *** Іван у коментарях пояснив, як із цим можна боротися.
Докладніше читайте в його щоденнику «А щоб було», а коротко ситуація така: потрібно або прибрати генерацію map-файлу, або перемкнути мову середовища на англійську. На роботі ж у 32-бітній версії Ubuntu все працювало, бо там колись давно чи то через розповзання діалогів у якійсь GUI-програмі, чи то через карлючки в ній, та мову системи було перемкнуто на англійську і це забулося.

Ця інформація вкупі з нарешті уважно прочитаним логом помилки

*** buffer overflow detected ***: /usr/lib/gcc/avr/4.9.2/../../../avr/bin/ld terminated
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f1a3e9f17e5]
/lib/x86_64-linux-gnu/libc.so.6(__fortify_fail+0x5c)[0x7f1a3ea9315c]
/lib/x86_64-linux-gnu/libc.so.6(+0x117160)[0x7f1a3ea91160]
/lib/x86_64-linux-gnu/libc.so.6(+0x1166c9)[0x7f1a3ea906c9]
/lib/x86_64-linux-gnu/libc.so.6(_IO_default_xsputn+0x80)[0x7f1a3e9f56b0]
/lib/x86_64-linux-gnu/libc.so.6(_IO_vfprintf+0xd1)[0x7f1a3e9c7241]
/lib/x86_64-linux-gnu/libc.so.6(__vsprintf_chk+0x84)[0x7f1a3ea90754]
/lib/x86_64-linux-gnu/libc.so.6(__sprintf_chk+0x7d)[0x7f1a3ea906ad]
/usr/lib/gcc/avr/4.9.2/../../../avr/bin/ld[0x416c47]
/usr/lib/gcc/avr/4.9.2/../../../avr/bin/ld[0x488174]

дозволяє зробити висновок, що розмір буфера для sprintf (не snprintf! тоді б хоч не хряпалося так) у модулі генерування карти лінкера було вибрано в режимі «має вистачити всім»™, але під «всіма», схоже, мали на увазі лише ASCII-світ. Щойно у вас з’являться двобайтові UTF-8-символи, буфера вже не вистачає. Що цікаво, avr-as з того ж binutils-avr 2.25, а також make — ще жодного разу не падали, чудово видаючи повідомлення українською мовою.

Оскільки відмовлятися від map-файлу я не хочу, «відремонтувати» роботу avr-ld можу двома способами.
Або в універсальному gcc-avr.mak, який ходить з проекту в проект і підключається по include в проектні Makefile, перемкнути мову середовища для всього інструментарію (раптом ще десь вилізе, то щоб і не знати), замінивши у фрагменті

46
47
48
49
50
51
52
# Set default toolchain prefix if it does not defind in environment or project makefile
TOOL ?= avr-

# Set tool names
CC      := $(TOOL)gcc
AS      := $(TOOL)gcc -x assembler-with-cpp
BIN     := $(TOOL)objcopy

другий рядок на

47
TOOL ?= LANG=C avr-

або ж змінити мову лише для лінкування, додавши те ж саме LANG=C безпосередньо перед відповідною командою:

211
212
213
$(TRGELF) : $(OBJ)
        echo ====  Link to $(notdir $@) ;\
        LANG=C $(CC) $^ $(LIB) $(LDFLAGS) -o $@

Стосується ця помилка лише Ubuntu (болгари обговорювали теж Ubuntu, в інших системах могли не вмикати локалізацію) й чи присутня вона в binutils-avr 2.26, я не знаю, можливості перевірити ще не було.

p.s. Як з’ясувалося, у gcc-linaro-7.2.1-2017.11-x86_64_arm-{eabi,linux-gnueabihf} та ж сама біда, хоча binutils там вже 2.28.

6 Responses to “avr-ld buffer overflow”

  1. supaowl says:

    Я користуюся Eclipse, і при компіляції виникає дана помилка, оскільки консоль в ньому використовує локаль системи (в моєму випадку Українська). Два дні боровся я з даною проблемою, так і не знайшов як перемкнути локаль в консолі Eclipse на us_EN.
    Щоб не перемикали локаль на Англійську в цілій системі то відкриваю вікно терміналу, міняю локаль, а вже потім з цього терміналу запускаю Eclipse. Щоб не робити це постійно зроблю це у вигляді маленького скрипта і буде мені щастя 🙂 Можливо і Вам пригодиться.

  2. supaowl says:

    Доброго дня. Підкажіть де можна знайти цей універсальний gcc-avr.mak?
    Маю таку ж саму проблему. Версія Ubuntu 18.04 x64, binutils-avr останньої версії 2.26.20160125+Atmel3.6.0-1
    Дякую.

    • ReAl says:

      Та це я колись давно сам собі виділив спільне з усіх проектів — те, що у кожному файлі повторюється — у окремий файл.
      А змінна TOOL була у ньому заведена, щоб між кількома версіями WinAVR перемикатися (спробував свіжу, глючить, відкотився на стабільну). Якщо задана у Makefile проекту, то використовується персональне налаштування, якщо ні — спільне для всіх, перевірене (і задане через junction).

      Сьогодні вже не до того, завтра зроблю архів з тим файлом і прикладом використання.

    • ReAl says:

      Затримали неочікувані невідкладні справи.

      Зробив архів зі згаданим файлом і прикладом його використання, дивіться у новому дописові Універсальний gcc-avr.mak.
      Воно має працювати і з eclipse, але тоді eclipse втратить контроль над makefile, це може виявитися незручним.

      Можливо, десь всередині середовища eclipse можна щось налаштувати.

      • supaowl says:

        О, супер, обов’язково прочитаю, дякую.
        Щодо середовища Eclipse і makefile, довго шукав і в самих налаштуваннях і в усіх каталогах програми (можливо є якийсь конфігураційний файл), але так і нічого не знайшов.

        • ReAl says:

          О, я ж ще викладав колись реалістичніший проект «Використання секцій в GCC», там основне про те, що можна накрутити секціями і лінкерним скриптом, у самому дописові робота з Makefile і gcc-avr.mak згадані лише побіжно, але у прикріпленому архіві все те ж саме (хіба просто старіша версія) з розділенням мейк-файлів і «модулями».
          І попередній проект на ту ж тему «Секції .init в avr-gcc»

Leave a Reply

[flagcounter image]