Обзор «вспомогательных» утилит из GCC toolchain. Часть 2.



Данная статья является продолжением этой статьи. Предлагаю без лишних слов перейти к обзору оставшихся утилит.



objcopy

На самом деле, эта утилита не является «вспомогательной». В toolchain’ах она используется для формирования файла прошивки (в виде *.hex или *.bin).

Дело в том, что линкер (ld) формирует выходной (исполняемый) файл в формате ELF. Этот формат является стандартом исполняемых файлов в большинстве UNIX-подобных систем. Кроме, собственно, кода и данных (секций .text и .data и т. д) ELF-файл содержит кучу дополнительной информации (заголовок, сведения о динамических зависимостях, отладочную информацию и т. д.). В случае МК – нам нужна «голая» прошивка, без заголовков и отладочной информации.

Рассматриваемая утилита позволяет извлечь необходимые нам секции из ELF-файла.

В самом простом случае, это делается следующей командой:

arm-none-eabi-objcopy.exe -O ihex LcdTest.elf LcdTest.hex

ключ "–O" определяет формат выходного файла. Нам, прежде всего, интересны форматы «ihex» и «binary».

На самом деле, objcopy очень мощная утилита, которая позволяет производить множество манипуляций с объектными и ELF файлами. Можно удалять, добавлять, переименовывать секции, менять точку входа и т. д.

Например, можно «вытянуть» из ELF только секцию .data в бинарный файл.

arm-none-eabi-objcopy.exe -O binary -j .data LcdTest.elf LcdTest.bin

Но все эти возможности (IMHO) необходимы уж в очень специфических случаях, поэтому не вижу смысла разбирать все возможности утилиты.

objdump

Очень полезная утилита. Позволяет получить дательную информацию по внутренностям объектного файла, в т. ч дизассемблировать код.
Запустив утилиту с ключом «-x» (x – показать содержимое всех заголовков), мы получим огромною «простыню» текста, в котором содержится информация о секциях, символах, таблицах вызовов, и т. д

arm-none-eabi-objdump.exe -x LCD.o

Результат:


Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00000000  00000000  00000000  00000034  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         00000000  00000000  00000000  00000034  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  00000000  00000000  00000034  2**0
  
  ... очень много букв ...


Еще более полезной функцией данной утилиты является возможность дизассемблировать файл (ключ «–D»). Более того, если объектный файл содержит отладочную информацию – можно дополнительно указать ключ «-S», и утилита выдаст «смещанный код»: итроки исходного кода + соответствующее дизассемблированные команды.

Пример:

arm-none-eabi-objdump.exe -DS LCD.o

Результат:


Disassembly of section .text.ClrCS:

00000000 <ClrCS>:
//--------------------------------------------------------
static __inline void SetCS(void) {
        GPIO_SetBits(GPIOA , GPIO_Pin_1);
}

static __inline void ClrCS(void) {
   0:   b580            push    {r7, lr}
   2:   af00            add     r7, sp, #0
        GPIO_ResetBits(GPIOA , GPIO_Pin_1);
   4:   f44f 6000       mov.w   r0, #2048       ; 0x800
   8:   f2c4 0001       movt    r0, #16385      ; 0x4001
   c:   f04f 0102       mov.w   r1, #2
  10:   f7ff fffe       bl      0 <GPIO_ResetBits>
}
  14:   bd80            pop     {r7, pc}
  16:   bf00            nop 


ranlib
Утилита предназначена для индексирования содержимого статических библиотек (архивов, созданных утилитой ar). Утилита индексирует все символы всех объектных файлов внутри архива и помешает сам индекс в архив. Наличие такого индекса существенно уменьшает время линковки больших статических библиотек.

Пример:

arm-none-eabi-ranlib.exe liblcd.a

readelf

Утилита предназначена для получения информации по внутренностям ELF файла. Позволяет просмотреть информацию по секрециям, символам, динамическим зависимостям. В принципе, практически всю эту информацию можно получить с помощью «objdump -x».

Например, получение информации по секциям, содержащимся в ELF ( ключ «-S»):

arm-none-eabi-readelf.exe -S LcdTest.elf

Результат:


There are 18 section headers, starting at offset 0x220d0:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .isr_vector       PROGBITS        08000000 008000 0001d0 00   A  0   0  1
  [ 2] .text             PROGBITS        080001d0 0081d0 00b5cc 00  AX  0   0  8
  [ 3] .bss              NOBITS          20000000 018000 000c1c 00  WA  0   0  4
  [ 4] ._user_heap_stack NOBITS          20000c1c 018000 000080 00  WA  0   0  1
  [ 5] .ARM.attributes   ARM_ATTRIBUTES  00000000 01379c 00002f 00      0   0  1
  [ 6] .debug_info       PROGBITS        00000000 0137cb 0052f0 00      0   0  1
  [ 7] .debug_abbrev     PROGBITS        00000000 018abb 0011e7 00      0   0  1
  [ 8] .debug_loc        PROGBITS        00000000 019ca2 002392 00      0   0  1
  [ 9] .debug_aranges    PROGBITS        00000000 01c038 0006c0 00      0   0  8
  [10] .debug_ranges     PROGBITS        00000000 01c6f8 000588 00      0   0  8
  [11] .debug_line       PROGBITS        00000000 01cc80 002649 00      0   0  1
  [12] .debug_str        PROGBITS        00000000 01f2c9 0019f0 01  MS  0   0  1
  [13] .comment          PROGBITS        00000000 020cb9 000011 01  MS  0   0  1
  [14] .debug_frame      PROGBITS        00000000 020ccc 001340 00      0   0  4
  [15] .shstrtab         STRTAB          00000000 02200c 0000c3 00      0   0  1
  [16] .symtab           SYMTAB          00000000 0223a0 001220 10     17 164  4
  [17] .strtab           STRTAB          00000000 0235c0 00099d 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)



run

Это симулятор, который теоретически позволяет нам запускать прошивку на ПК. Но он умеет только интерпретировать определенный набор инструкций (например, Thumb). Периферию он не эмулирует, а без периферии наш МК будет глух и нем.

Использовать симулятор, теоретически, можно в связке с отладчиком gdb. Для этого в отладчике перед загрузкой программы нужно выполнить команду «target sim». Вот только без симуляции периферии он, IMHO, бесполезен (ну, разве что какие-то математические алгоритмы отлаживать).

Работа с симулятором выглядит как-то так:

(gdb) target sim
Connected to the simulator.
(gdb) load
Loading section startup, size 0x44 vma 0x100000
Loading section prog, size 0x23a1c vma 0x100044
Loading section .data, size 0xb10 vma 0x200000
Start address 0x117a34
Transfer rate: 1190784 bits in <1 sec.
(gdb) run
Starting program: C:\Projects\Eclipse\MultiLock\locker.elf


size

Простенькая, но очень полезная утилита, которая показывает размер секций .text, .data и .bss в объектном или ELF файле. Это позволяет узнать: сколько ПЗУ и ОЗУ занимает собранная прошивка.

Пример:

arm-none-eabi-size.exe LcdTest.elf

Результат:


   text    data     bss     dec     hex filename
  47004       0    3228   50232    c438 LcdTest.elf


47004 – размер кода (ПЗУ)
0 – размер инициализированных данных (ПЗУ и ОЗУ)
3228 – размер неинициализированных данных (ОЗУ)

strings

Утилита предназначена для поиска строковых констант в объектном, ELF или бинарном файле. Строковой константой утилита считает последовательность (4 и более) печатных (printable) символов, которая заканчивается непечатным символом (unprintable). На практике, наряду с действительно строковыми константами, утилита находит в файле кучу мусора, которые по логике утилиты «похожи» на стоковые константы.

Пример:

arm-none-eabi-strings.exe LcdTest.elf

Результат:


bE8?
Hello
x<x|px
`00000000
<000000



strip

Утилита позволяет удалить из объектного или ELF файла символы определенного типа. Например, можно удалить из собранного файла всю отладочную информацию:

arm-none-eabi-strip.exe –g LcdTest.elf

В нашем случае, толку от данного инструмента мало. Утилита objcopy, которая используется для поручения файла прошивки, автоматически обрезает всю отладочную и прочую «ненужную» информацию.

P.S. Все, со «вспомогательными» инструментами разобрались — можно переходить к «основным орудиям труда». Предложения по темам для дальнейших статей приветствуются :)
  • +5
  • 02 марта 2012, 14:08
  • e_mc2

Комментарии (20)

RSS свернуть / развернуть
По большей части все это подходит для всех GCС/BinUtils тулчейнов, так что я бы убрал из заголовков префиксы «arm-none-eabi-» и написал про них во вступлении (заодно можно упомянуть и другие префиксы — «avr-», например).
0
  • avatar
  • Vga
  • 02 марта 2012, 17:23
Ок, сделаю.
0
Кстати, на тему префиксов поддерживаю — очень интересно было бы расписать их семантику и возможные варианты. Например интересно, как штатное четырёх-словное название мимикрировало в трёх-словное — тупо выкидывают поле OS? Для каких камней нужно использовать softfloat? Что такое eabi и есть ли разница между eabi и gnueabi (я так понял, что eabi подразумевает использование в качестве libc библиотеки newlib, но не понял, чем оно отличается, например, от uclibc)? А ведь последним словом могут быть ещё просто gnu, а так же более понятные glibc, uclibc (и ещё какие-то варианты попадались). А в качестве первого слова попадаются некие «armeb», «armv5te» и «armv5tej» (про не ARM молчу). «Что всё это значит?» (C)
0
А в качестве первого слова попадаются некие «armeb», «armv5te» и «armv5tej» (про не ARM молчу).
Это варианты архитектуры ARM. eb — big endian, el — little endian, ARMv5/ARMv6/ARMv7 — ARM9/ARM11/Cortex соответсвенно, TE/TEJ — набор расширений (T — thumb, J — Jazelle, E — какой-то из наборов мультимедиа-инструкций).
Подробней есть в вики.
Хотя эти коды по моему не к компиляторам обычно прилагаются, а к скомпилированным под конкретную архитектуру исполняемым файлам.
0
Ага, с этим понятно, спасибо. Хотя соответствие этих индексов у АРМов меня всё время ставили в тупик =)
Особенно что Cortex M3 это такие мелкие простенькие контроллеры, а Cortex A8 — монстры, на уровне современных десктопных процов =). А между ними по моще ARM9 и ARM11, на которых уже запускается Linux но ещё нельзя играть в DOOM3 =)
0
Спасибо за статью.
Будет ли что нибудь про dbg?
0
Будет ли что нибудь про dbg?
Будет, раз эта тема интересна. Просто gdb в «голом» виде сейчас редко кто использует – намного удобнее прикрутить его к IDE и наслаждаться удобством GUI интерфейса. Но, думаю, небольшая обзорная статья по внутренностям gdb не помешает :)
0
Спасибо.
0
Про то как написать gdb-server и отлаживать через uart?
0
Для начала, просто о gdb – это очень мощный инструмент. Даже краткий обзор вполне достоин отдельного топика.

Про то как написать gdb-server и отлаживать через uart?

Не совсем понял – что конкретно Вас интересует. Для внутрисхемной отладки, обычно, используется специальный интерфейс (JTAG, SWD …). Я, честно говоря, не знаю МК, который бы позволял выполнять внутрисхемную отладку через UART (или я что-то пропустил в этой жизни?).
А gdb-server – это прослойка между gdb и конкретным интерфейсом/устройством. Зачем писать свой gdb-server если уже есть готовый (open source) сервер практически для каждой платформы. Или Вас интересует теория работы gdb-server’а?
+1
Сервер может быть реализован на МК и не быть прослойкой между gdb и jtag. То есть аппаратных возможностей отладки не нужно для этого способа, интерфейс отладки реализуется программно. Надо реализовать чтение/запись по указанному адресу и отлов некоторых прерываний. Но наверно будут проблемы с выполнением кода из flash (чтобы поставить точку останова надо перезаписать инструкции). Я до реализации не доходил, как-то всегда обхожусь printf, но кода там надо написать не много.
0
А, понял.
Теоретически можно хост написать – только вот с breakpoint’ами действительно непонятно как быть. А без них — толку от отладчика мало.
0
Если очень приспичит, то можно. На этапе подготовки прошивки заменить нужные команды прямо на брекпоинты или вставить их между ними.
Насколько я знаю, регистры отладки с железными брекпоинтами из кода недоступны.

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

Ещё вариант — отлаживать код на кристалле с большим количеством оперативки — куда можно запихать весь код и отлаживать его там, модифицируя как пожелается.

Но вот как заставить компилятор с гуёй так извращаться и генерировать подобный код — я не очень представляю =)

Так что я не думаю, что этим подобает заниматься. Дешевле купить канонный отладчик без всех этих вывертов.
0
Так gdb+binutils знают, что и как надо заменить для постановки брекпоинта. Проблема только в перезапись флеша при установке/снятии бряка, хотя это тоже можно сделать.

Большая проблема это увеличенная сложность, может оказатся не понятным, не работает отлаживаемый код или сам отладчик.
0
Угу, килобайт оперативки на буфер для IAP выделить можно без особых проблем.

Вот это да, будет весьма непросто. Я бы не стал заниматься именно таким вот отладчиком =)
0
Подскажите чего-нить путное по отладке в Eclipse. Вопрос задал на форуме: HappyJTAG2 + Eclipse (отладка)
0
  • avatar
  • uni
  • 08 марта 2012, 02:52
В Eclipse отладка как-бы запускается, но вылетает с ошибками. Попробовал вручную, но не знаю что дальше сделать, чтобы найти причину ошибки. Avarice пишет потом, что проблема в синхронизации. Старался настроить вот по этой доке: Debugging

Вот как это выглядит:
Отладка в Eclipse

Это в консоли:
...D:\Projects\IAR\Projects\PBIIDemo]$ avr-gdb gccout.elf
GNU gdb 6.8
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-pc-mingw32 --target=avr"...
(gdb) target remote localhost:4242
Remote debugging using localhost:4242
Ignoring packet error, continuing...
0x00010000 in ?? ()
(gdb) info program
Debugging a target over a serial line.
Program stopped at 0x10000.
It stopped with signal SIGTRAP, Trace/breakpoint trap.
(gdb) list
21
22      #include "Defines.h"
23      #include "PLC.h"
24      #include "MainUnit.h"
25
26      // Точка входа в основную программу
27      int main() {
28
29          // Настройка внутренних узлов платы
30          CPLC::Initialization();
(gdb)

Ошибка: Ignoring packet error, continuing...
0
Похоже, что проблемы на стороне JTAG/GDB сервера. Я с HappyJTAG2 не работал, и помочь, увы, не могу.

На это:

0x00010000 in ?? ()
(gdb) info program
Debugging a target over a serial line.
Program stopped at 0x10000.

не обращайте внимания, GDB может писать подобный бред при проблемах с сервером/отладчиком.
Например, а запускаю отладку, останавливаюсь в точке останова. Потом физически отключаю свое устройство от JTAG. Выполняю в GDB команду continue, получаю следующее:

Breakpoint 1, main () at C:\Utils\CoIDE\workspace\GdbDemo\main.c:7
//---- Здесь я отключаю девайс
(gdb) continue
Continuing.
Program received signal SIGTRAP, Trace/breakpoint trap.
0x00000734 in ?? () 

Адрес 0x00000734 бредовый, у меня флеш начинается с адреса 0x8000000. Получается, что GDB не видит, что устройство недоступно и показывает разный бред.
0
Справедливости ради, уточню, что виноват в таком поведении не сам GDB а GDB-сервер. GDB, в данном случае, просто визуализирует данные, полученные от сервера. А вот GDB-сервер при проблемах с интерфейсом отладки, вместо того чтобы сообщить об ошибке, возвращает всякий мусор.
0
Автор ответил:

Re: HappyJTAG2 v2.45 and debugging with avr-gdb

Hello,
gdb module is still not finished… and not tested properly in HappyJTAG2 software. I had intent to develope also this, but i did not found someone who would help me to test, identify bugs and who is experienced with gdb / target communication sequence and scenario ( its litlebit diferrent than internal avrstudio4x debug sequence… )…
I had no time to test and debug it, since I do not work with gdb and I do not have any experience with this type of interface. I was focused for direct AVRStudio4x connection and JtagIceII emulation…
My recommendation is to use debug without gdb for current version ( but there is change, that flash download will work in gdb interface )

Lubo


Вот так вот. Соблазнился я на фичу, а она только возможно в режиме заливки флеша работает (есть шанс). Так что либо надо помогать товарищу, либо ждать пока найдётся кто-то адекватно-опытный поставленной задаче.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.