Перейти к содержанию
    

а в качестве эксперемента можете подсунуть "руками" memset/memcpy/memmove? чтоб результат погдядеть...

Подсунул, это не сложно - там всего три функции. Результата не вышло - улетает сразу в hardfault.

 

По всему он скомпилировал какую-то полную хрень в memset:

post-39839-1494830632_thumb.png

Из-за чего начинается рекурсивный вызов ее, выход стека за границы ОЗУ и hardfault.

 

Собственно до main не доходит, можете поэкспериментировать - вот код, memmove и memset стандартные из исходников libgcc:

void Reset_Handler(void)
{
 /* Initialize data */
 memmove(&_data_start, &_data_start_flash, &_data_end - &_data_start);

 /* Initialize settings with default values */
 memmove(&_settings_start, &_settings_start_flash, &_settings_end - &_settings_start);

 /* Initialize service with default values */
 memmove(&_service_start, &_service_start_flash, &_service_end - &_service_start);

 /* Initialize nvram with default values */
 memmove(&_nvram_start, &_nvram_start_flash, &_nvram_end - &_nvram_start);

 /* Initialize bss */
 memset(&_bss_start, 0, &_bss_end - &_bss_start);

 /* Zero fill sram1/sram2*/
 memset(&_sram1_start, 0, &_sram1_end - &_sram1_start);
 memset(&_sram2_start, 0, &_sram2_end - &_sram2_start);

 /* Call the application's entry point.*/
 main();
}

 

я к счастью ничем внешним не пользуюсь, даже libc и libm свои "местные" в исхниках, в связи с чем никакие либы кроме libgcc самого компиллера в проект не линкуются

Я использую только memmove, memcpy и memset. И они есть в libgcc, если мне память не изменяет. Все остальное, кроме FatFS, тоже свое.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2_Шаманъ

все это подозрительно...

проверил у себя - в libgcc нет этих функций в libgcc.

klen@ubuntu:/opt/arm-kgp-eabi-8/lib/gcc/arm-kgp-eabi/8.0.0$ arm-kgp-eabi-objdump libgcc.a -t | grep memset

00000000 *UND* 00000000 memset

klen@ubuntu:/opt/arm-kgp-eabi-8/lib/gcc/arm-kgp-eabi/8.0.0$ arm-kgp-eabi-objdump libgcc.a -t | grep memmov

klen@ubuntu:/opt/arm-kgp-eabi-8/lib/gcc/arm-kgp-eabi/8.0.0$ arm-kgp-eabi-objdump libgcc.a -t | grep memcpy

00000000 *UND* 00000000 memcpy

00000000 *UND* 00000000 memcpy

klen@ubuntu:/opt/arm-kgp-eabi-8/lib/gcc/arm-kgp-eabi/8.0.0$

 

они внешние..

у меня работает, у Вас нет - а где разница, вот в чем вопрос..

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

проверил у себя - в libgcc нет этих функций в libgcc.

ну я просто из исходников libgcc.a от 6.3.1 закинул себе в проект все три функции, потому предположил, что они там должны быть.

 

у меня работает, у Вас нет - а где разница, вот в чем вопрос..

Вы видели код memset? Как Вы думаете это похоже на нормальный код?

 

Вот исходник memset (взят из исходников libgcc.a от 6.3.1, но это никакого значения не имеет), что сгенерировал GCC 8.0.0 Вы можете посмотреть выше:

/* Public domain.  */
#include <stddef.h>

void *
memset (void *dest, int val, size_t len)
{
 unsigned char *ptr = dest;
 while (len-- > 0)
   *ptr++ = val;
 return dest;
}

 

У меня тоже работает все, причем под любой версией "штатного" GCC. Могу еще попробовать собрать 8.0.0, но без -flto.

 

все это подозрительно...

Скомпилировал проект без -flto, и что Вы думаете...вот, так с точки зрения GCC 8.0.0 должны выглядеть функция memse (исходник см. выше), та же беда, что и с -flto:

  2:memset.c      **** #include <stddef.h>
  3:memset.c      **** 
  4:memset.c      **** void *
  5:memset.c      **** memset (void *dest, int val, size_t len)
  6:memset.c      **** {
 28              		.loc 1 6 0
 29              		.cfi_startproc
 30              		@ args = 0, pretend = 0, frame = 0
 31              		@ frame_needed = 0, uses_anonymous_args = 0
 32              	.LVL0:
 33 0000 10B5     		push	{r4, lr}
 34              		.cfi_def_cfa_offset 8
 35              		.cfi_offset 4, -8
 36              		.cfi_offset 14, -4
 37              		.loc 1 6 0
 38 0002 0446     		mov	r4, r0
 39              	.LVL1:
  7:memset.c      ****   unsigned char *ptr = dest;
  8:memset.c      ****   while (len-- > 0)
 40              		.loc 1 8 0
 41 0004 12B1     		cbz	r2, .L4
 42 0006 C9B2     		uxtb	r1, r1
 43              	.LVL2:
 44 0008 FFF7FEFF 		bl	memset
 45              	.LVL3:
 46              	.L4:
  9:memset.c      ****     *ptr++ = val;
 10:memset.c      ****   return dest;
 11:memset.c      **** }
 47              		.loc 1 11 0
 48 000c 2046     		mov	r0, r4
 49 000e 10BD     		pop	{r4, pc}
 50              		.cfi_endproc
 51              	.LFE0:
 52              		.size	memset, .-memset

 

klen, tсть какие-нибудь соображения?

Изменено пользователем Шаманъ

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

......

47 .loc 1 11 0

48 000c 2046 mov r0, r4

49 000e 10BD pop {r4, pc}

50 .cfi_endproc

.....

 

прикольнинько! он тупо врапер вставил :) халявщик! кода memset мы так и не увидели

идей море, будем их исключать.

 

такое поведение как мне кажется абсалютно нормально - мы где то не нормально что то объяснили компиллеру в коде! всегда так бывает. пока природа косяка не ясна но мы ее исследуем.

 

шаг номер нуль.

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

 

в атаче libklibc.a - моя реализация libc, совместимая с хидерами от newlib. ничего не меняя нужно его добавить для линковки. в частности там внутри реализации

00000000 g F .text.memcpy 000001b0 memcpy

00000000 g F .text.memccpy 00000136 memccpy

00000000 g F .text.memchr 000000f6 memchr

00000000 g F .text.memset 00000068 memset

00000000 g F .text.memcmp 000000e6 memcmp

00000000 g F .text.memmove 00000270 memmove

00000000 g F .text.strlen 00000016 strlen

00000000 g F .text.strncpy 0000011a strncpy

00000000 g F .text.strcpy 00000010 strcpy

00000000 g F .text.strcmp 00000020 strcmp

00000000 g F .text.strncmp 0000003a strncmp

00000000 g F .text.strchr 00000022 strchr

00000000 g F .text.strspn 00000034 strspn

00000000 g F .text.strpbrk 0000002c strpbrk

00000000 g F .text.strcoll 00000020 strcoll

00000000 g F .text.strstr 00000042 strstr

00000000 g F .text.strcat 00000028 strcat

00000000 g F .text.strlcat 000001f0 strlcat

00000000 g F .text.strcspn 00000034 strcspn

00000000 g F .text.strerror 00000004 strerror

00000000 g F .text.strncat 00000110 strncat

00000000 g F .text.strtok 00000070 strtok

00000000 *UND* 00000000 reentrant

00000000 g F .text.strxfrm 00000172 strxfrm

00000000 g F .text.strrchr 00000022 strrchr

00000000 w F .text.strrchr 00000022 rindex

.

собрано с ключами :

-mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -Ofast -fomit-frame-pointer -finline-functions -ffunction-sections -fdata-sections -fgraphite -funroll-loops -flto=8 -ffat-lto-objects -ggdb3 -fverbose-asm

должно линковатся без проблем с LTO и без него

если у Вас не-cotex-m4 приложу другую версию.

libklibc.a.tar.7z

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

прикольнинько! он тупо заглушку вставил :) халявщик!

идей море, будем их исключать.

Не, там похоже все печальнее, ибо кроме "заглушки" есть еще остатки цикла и, главное, рекурсия. Что никак нормальным быть не может:

 

.LVL0:

33 0000 10B5 push {r4, lr}

38 0002 0446 mov r4, r0

41 0004 12B1 cbz r2, .L4

42 0006 C9B2 uxtb r1, r1

44 0008 FFF7FEFF bl memset

46 .L4:

48 000c 2046 mov r0, r4

49 000e 10BD pop {r4, pc}

 

шаг номер нуль.

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

Не вопрос, но у меня cortex-m7 (stm32f746). Да, memmove, memset и memcpy достаточно.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2_Шаманъ

>Не, там похоже все печальнее, ибо кроме "заглушки" есть еще остатки цикла и, главное, рекурсия. Что никак нормальным быть не может:

есть мнение что эта рекурсия или "всегда" или "никогда", то есть тривиальный неправильный код

 

>Не вопрос, но у меня cortex-m7 (stm32f746). Да, memmove, memset и memcpy достаточно.

во первых бинарно m4-код по определению подходит к m7 ибо набор инструкций первого есть подмножество второго набора.

во вторых... но может линкер не пропустить по "политическим" соображениям :) в ELF заголовке объектников есть флаги архитектуры которые линкер проверяет и решает "да" или "нет"

 

поэтому версия для m7 :

 

 

в результате вызваться должен код:

 

Дизассемблирование раздела .text.memset:

00000000 <memset>:
   0:    b3c2          cbz    r2, 74 <memset+0x74>
   2:    b2c9          uxtb    r1, r1
   4:    4603          mov    r3, r0
   6:    b410          push    {r4}
   8:    1884          adds    r4, r0, r2
   a:    f012 0207     ands.w    r2, r2, #7
   e:    d019          beq.n    44 <memset+0x44>
  10:    2a01          cmp    r2, #1
  12:    d013          beq.n    3c <memset+0x3c>
  14:    2a02          cmp    r2, #2
  16:    d00f          beq.n    38 <memset+0x38>
  18:    2a03          cmp    r2, #3
  1a:    d00b          beq.n    34 <memset+0x34>
  1c:    2a04          cmp    r2, #4
  1e:    d007          beq.n    30 <memset+0x30>
  20:    2a05          cmp    r2, #5
  22:    d003          beq.n    2c <memset+0x2c>
  24:    2a06          cmp    r2, #6
  26:    d122          bne.n    6e <memset+0x6e>
  28:    7019          strb    r1, [r3, #0]
  2a:    3301          adds    r3, #1
  2c:    7019          strb    r1, [r3, #0]
  2e:    3301          adds    r3, #1
  30:    7019          strb    r1, [r3, #0]
  32:    3301          adds    r3, #1
  34:    7019          strb    r1, [r3, #0]
  36:    3301          adds    r3, #1
  38:    7019          strb    r1, [r3, #0]
  3a:    3301          adds    r3, #1
  3c:    7019          strb    r1, [r3, #0]
  3e:    3301          adds    r3, #1
  40:    42a3          cmp    r3, r4
  42:    d011          beq.n    68 <memset+0x68>
  44:    7019          strb    r1, [r3, #0]
  46:    3308          adds    r3, #8
  48:    f803 1c07     strb.w    r1, [r3, #-7]
  4c:    f803 1c06     strb.w    r1, [r3, #-6]
  50:    f803 1c05     strb.w    r1, [r3, #-5]
  54:    f803 1c04     strb.w    r1, [r3, #-4]
  58:    f803 1c03     strb.w    r1, [r3, #-3]
  5c:    f803 1c02     strb.w    r1, [r3, #-2]
  60:    f803 1c01     strb.w    r1, [r3, #-1]
  64:    42a3          cmp    r3, r4
  66:    d1ed          bne.n    44 <memset+0x44>
  68:    f85d 4b04     ldr.w    r4, [sp], #4
  6c:    4770          bx    lr
  6e:    1c43          adds    r3, r0, #1
  70:    7001          strb    r1, [r0, #0]
  72:    e7d9          b.n    28 <memset+0x28>
  74:    4770          bx    lr
  76:    bf00          nop

 

просьба не пугатся на длинну кода :) это "оптимальный" по скорости код в версии критерия -Ofast оптимальноси GCC 8.0.0 c участием графита - тоесть циклы разверныты в максимум чтоб с экономить скорость на переходах. соответственно размер какой угодно и флеш не экономится - принимается что пирог из жирафа длинный и поэтому риса в него напихать можно столько сколько хочется!

 

для сравнения все тоже самое но с -Os

Дизассемблирование раздела .text.memset:

00000000 <memset>:
   0:    4402          add    r2, r0
   2:    4603          mov    r3, r0
   4:    b2c9          uxtb    r1, r1
   6:    4293          cmp    r3, r2
   8:    d100          bne.n    c <memset+0xc>
   a:    4770          bx    lr
   c:    7019          strb    r1, [r3, #0]
   e:    3301          adds    r3, #1
  10:    e7f9          b.n    6 <memset+0x6>

 

что быстрее первое или второе большой вопрос, поскольку это зависит от "окружающего вызывающего кода", оптимизатор, в частности LTO-фаза, в итоге все сваливает в общий котел и что на выходе получится заранее трудно предсказуемо. у меня обычно -Ofast немного быстрее а -Os всегда много меньше. другие оптимизации проигрывают практически всегда и во всем.

libklibc_m7.a.tar.7z

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

есть мнение что эта рекурсия или "всегда" или "никогда", то есть тривиальный неправильный код

Рекурсия там есть - именно из-за нее в HardFault выпадает программа. Что неправильно - тут и обсуждать особенно нечего.

 

во вторых...

С этой версией без -flto запустилось. Загрузка процессора в среднем больше на 2%, чем на 6.3.1, код больше на 6кБ. Сейчас с -flto соберу посмотрю.

 

Мда... с -flto полная лажа - загрузка процессора больше в 2.5раза. Картина такая же, как на 6.3.1 при включении -flto и -ggdb3 :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Рекурсия там есть - именно из-за нее в HardFault выпадает программа. Что неправильно - тут и обсуждать особенно нечего.

 

 

С этой версией без -flto запустилось. Загрузка процессора в среднем больше на 2%, чем на 6.3.1, код больше на 6кБ. Сейчас с -flto соберу посмотрю.

 

Мда... с -flto полная лажа - загрузка процессора больше в 2.5раза. Картина такая же, как на 6.3.1 при включении -flto и -ggdb3 :(

 

ничего страшного,

.. шорты превращаются... превращаются... извините, мелкие технические неполадки

 

наверно по смыслу мне нужно собрать два релизных 6.3 и 7.1 - для сравнения c "конкурентами" нужно?

и все таки меня терзают смутные сомнения..

к следующему разу сделаю сборку по иному и попробуем еще эксперимент .... сомнения.. все ли мы правильно делаем? .... правильно ли мы интерпретируем увиденное ....

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

наверно по смыслу мне нужно собрать два релизных 6.3 и 7.1 - для сравнения c "конкурентами" нужно?

А в чем смысл? В середине июня обещали вроде обновление "конкурентов" до 7 версии GCC.

 

и все таки меня терзают смутные сомнения..

к следующему разу сделаю сборку по иному и попробуем еще эксперимент .... сомнения.. все ли мы правильно делаем? .... правильно ли мы интерпретируем увиденное ....

А как еще можно интерпретировать проблему с генерацией кода и показания загрузки процессора?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А как еще можно интерпретировать проблему с генерацией кода и показания загрузки процессора?

а как интерпретировать то что у меня все наоборот? это означает как минимум что все оказывается более разнообразно чем то что мы видим.

наверно ситуация все таки рулится - нужно найти руль, и не ехать по дефолтной траектории.

в любом случае спасибо - косяки нужно знать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Снова попробовал последний свежак и споткнулся об memset :)

 

size_t init_memory_pool(size_t mem_pool_size, void *mem_pool)
{
/******************************************************************/
    tlsf_t *tlsf;
    bhdr_t *b, *ib;

...

    /* Zeroing the memory pool */
    memset(mem_pool, 0, sizeof(tlsf_t));

 

ругань:

.../tlsf/tlsf.c:480:5: warning: 'memset' writing 3180 bytes into a region of size 4 overflows the destination [-Wstringop-overflow=]
     memset((char*)mem_pool, 0, sizeof(tlsf_t));
     ^
/tmp/ccutHzBY.s: Assembler messages:
/tmp/ccutHzBY.s:3170: Error: offset out of range
lto-wrapper: fatal error: /opt/arm-kgp-eabi/bin/arm-kgp-eabi-g++ returned 1 exit status

 

mem_pool "достаётся" здесь:

    unsigned long* p = &__heap_start__;
    *p = 0;
    unsigned long* e = &__heap_end__;
    unsigned long len = (char*) e - (char*) p;

    pool = p;

    init_memory_pool(len, pool);

 

__heap_start__ и __heap_end__ из .ld

 

Без lto собирается, но не влезает.

 

P. S. на такой же memset вставленный перед вызовом init_memory_pool, не ругается.

Изменено пользователем Terminator

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

и споткнулся об memset :)

Интересно, а смотрели, что там компилятор нагенерировал в memset?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

свежак

 

www.klen.org/Files/DevTools/x86_64-kgp-linux-gnu/arm-kgp-eabi_@_x86_64-kgp-linux-gnu_20170625_PATENS.7z

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Коллеги, хотелось бы взглянуть на качество кода околопоследних версий или последней обсуждаемого компилятора для таргетов ARM v4/v5 (32bit), ARM v6M, ARM v7M. Может ли кто-то выложить хексы любых исходников (С,С++), размером 8..30 КБ бинарного кода (в переводе на кекс будет 20..100 КБ) для обозначенных таргетов. В архиве zip/rar.

Изменено пользователем GetSmart

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

могу дамп одного из проектов дать, там в перемешку строки исходников и асм. видно что из чего получается. видно хорошо вышло или не очень.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...