|
|
|
свежак KGP win32/arm/avr/mips/m68k, GNU tools chain |
|
|
|
May 15 2017, 06:47
|
Знающий
Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839
|
Цитата(klen @ May 15 2017, 01:11) а в качестве эксперемента можете подсунуть "руками" memset/memcpy/memmove? чтоб результат погдядеть... Подсунул, это не сложно - там всего три функции. Результата не вышло - улетает сразу в hardfault. По всему он скомпилировал какую-то полную хрень в memset:
Из-за чего начинается рекурсивный вызов ее, выход стека за границы ОЗУ и hardfault. Собственно до main не доходит, можете поэкспериментировать - вот код, memmove и memset стандартные из исходников libgcc: CODE 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, тоже свое.
|
|
|
|
|
May 16 2017, 18:18
|
бессмертным стать можно тремя способами
Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912
|
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$ они внешние.. у меня работает, у Вас нет - а где разница, вот в чем вопрос..
|
|
|
|
|
May 17 2017, 06:41
|
Знающий
Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839
|
Цитата(klen @ May 16 2017, 21:18) проверил у себя - в libgcc нет этих функций в libgcc. ну я просто из исходников libgcc.a от 6.3.1 закинул себе в проект все три функции, потому предположил, что они там должны быть. Цитата у меня работает, у Вас нет - а где разница, вот в чем вопрос.. Вы видели код memset? Как Вы думаете это похоже на нормальный код? Вот исходник memset (взят из исходников libgcc.a от 6.3.1, но это никакого значения не имеет), что сгенерировал GCC 8.0.0 Вы можете посмотреть выше: CODE /* 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. Цитата(klen @ May 16 2017, 21:18) все это подозрительно... Скомпилировал проект без -flto, и что Вы думаете...вот, так с точки зрения GCC 8.0.0 должны выглядеть функция memse (исходник см. выше), та же беда, что и с -flto: CODE 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сть какие-нибудь соображения?
Сообщение отредактировал Шаманъ - May 17 2017, 06:44
|
|
|
|
|
May 17 2017, 11:32
|
бессмертным стать можно тремя способами
Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912
|
Цитата(Шаманъ @ May 17 2017, 09:41) ...... 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 приложу другую версию.
|
|
|
|
|
May 17 2017, 11:48
|
Знающий
Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839
|
Цитата(klen @ May 17 2017, 14:32) прикольнинько! он тупо заглушку вставил халявщик! идей море, будем их исключать. Не, там похоже все печальнее, ибо кроме "заглушки" есть еще остатки цикла и, главное, рекурсия. Что никак нормальным быть не может: Цитата .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 достаточно.
|
|
|
|
|
May 17 2017, 12:29
|
бессмертным стать можно тремя способами
Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912
|
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 всегда много меньше. другие оптимизации проигрывают практически всегда и во всем.
|
|
|
|
|
May 17 2017, 13:54
|
Знающий
Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839
|
Цитата(klen @ May 17 2017, 15:29) есть мнение что эта рекурсия или "всегда" или "никогда", то есть тривиальный неправильный код Рекурсия там есть - именно из-за нее в HardFault выпадает программа. Что неправильно - тут и обсуждать особенно нечего. Цитата во вторых... С этой версией без -flto запустилось. Загрузка процессора в среднем больше на 2%, чем на 6.3.1, код больше на 6кБ. Сейчас с -flto соберу посмотрю. Мда... с -flto полная лажа - загрузка процессора больше в 2.5раза. Картина такая же, как на 6.3.1 при включении -flto и -ggdb3
|
|
|
|
|
May 17 2017, 14:52
|
бессмертным стать можно тремя способами
Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912
|
Цитата(Шаманъ @ May 17 2017, 16:54) Рекурсия там есть - именно из-за нее в HardFault выпадает программа. Что неправильно - тут и обсуждать особенно нечего. С этой версией без -flto запустилось. Загрузка процессора в среднем больше на 2%, чем на 6.3.1, код больше на 6кБ. Сейчас с -flto соберу посмотрю. Мда... с -flto полная лажа - загрузка процессора больше в 2.5раза. Картина такая же, как на 6.3.1 при включении -flto и -ggdb3 ничего страшного, .. шорты превращаются... превращаются... извините, мелкие технические неполадки наверно по смыслу мне нужно собрать два релизных 6.3 и 7.1 - для сравнения c "конкурентами" нужно? и все таки меня терзают смутные сомнения.. к следующему разу сделаю сборку по иному и попробуем еще эксперимент .... сомнения.. все ли мы правильно делаем? .... правильно ли мы интерпретируем увиденное ....
|
|
|
|
|
May 18 2017, 06:20
|
Знающий
Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839
|
Цитата(klen @ May 17 2017, 17:52) наверно по смыслу мне нужно собрать два релизных 6.3 и 7.1 - для сравнения c "конкурентами" нужно? А в чем смысл? В середине июня обещали вроде обновление "конкурентов" до 7 версии GCC. Цитата и все таки меня терзают смутные сомнения.. к следующему разу сделаю сборку по иному и попробуем еще эксперимент .... сомнения.. все ли мы правильно делаем? .... правильно ли мы интерпретируем увиденное .... А как еще можно интерпретировать проблему с генерацией кода и показания загрузки процессора?
|
|
|
|
|
May 24 2017, 10:53
|
Местный
Группа: Участник
Сообщений: 209
Регистрация: 7-12-04
Из: Томск
Пользователь №: 1 382
|
Снова попробовал последний свежак и споткнулся об 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 - May 24 2017, 10:55
|
|
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|