Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Непонятки с функцией memcpy
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Harvester
Добрый день.
Процессор ARM11, компилятор ADS 1.2
Имеется следующая функция:
Код
UCHAR RFC4357_KeyUnwrap(GOST28147_BCTX_PTR pX,
                        RFC4357_WRAPPED_KEY_PTR pWrappedKey,
                        PUCHAR pUnwrappingKey,
                        PUCHAR pUnwrappedKey) {
  UCHAR kd[32];
  UCHAR ke[32];

  /* calc diversified key */
  memcpy(kd, pUnwrappingKey, 32);
...
  /* decrypt key */
  memcpy(ke, pWrappedKey->KEY, 32);
...
}

Во время второго вызова memcpy() возникает исключение Misaligned. И действительно, перед вызовом функции R1 = 010CF0BA.
Из листинга видно, что при первом вызове вызывается функция __rt_memcpy, а при втором - __rt_memcpy_w.
Собственно, вопросы:
1. Из каких соображений компилятор в 1-м случае поставил функцию побайтного копирования, а во 2-м - пословного?
2. Как сказать компилятору, чтобы он во 2-м случае тоже использовал __rt_memcpy?
aaarrr
Цитата(Harvester @ Aug 13 2015, 11:23) *
1. Из каких соображений компилятор в 1-м случае поставил функцию побайтного копирования, а во 2-м - пословного?
2. Как сказать компилятору, чтобы он во 2-м случае тоже использовал __rt_memcpy?

1. Руководствуясь типом RFC4357_WRAPPED_KEY_PTR
2. Тут лучше как раз наоборот - чтобы pWrappedKey передавался с корректным выравниванием

То есть виноват тот, кто вызывает RFC4357_KeyUnwrap с некорректным значением pWrappedKey.
Harvester
Цитата(aaarrr @ Aug 13 2015, 11:29) *
То есть виноват тот, кто вызывает RFC4357_KeyUnwrap с некорректным значением pWrappedKey.

А что делать, если pWrappedKey - указатель на массив во входных данных, который не выровнен по-определению (ну, вот так сложилось исторически).
aaarrr
Код
UCHAR RFC4357_KeyUnwrap(GOST28147_BCTX_PTR pX,
                         __packed RFC4357_WRAPPED_KEY_PTR pWrappedKey,
                         PUCHAR pUnwrappingKey,
                         PUCHAR pUnwrappedKey)

И так везде. Но лучше бы выровнять.
Golikov A.
я бы __packed под typdef сразу запихал бы...
Harvester
Цитата(aaarrr @ Aug 13 2015, 11:40) *
Код
UCHAR RFC4357_KeyUnwrap(GOST28147_BCTX_PTR pX,
                         __packed RFC4357_WRAPPED_KEY_PTR pWrappedKey,
                         PUCHAR pUnwrappingKey,
                         PUCHAR pUnwrappedKey)

И так везде. Но лучше бы выровнять.

Не прокатило sad.gif .
Нашел вот-такой документ: How do the ARM Compilers handle memcpy()?
Попробовал с промежуточным указателем на char - помогло, __rt_memcpy_w превратилась в __rt_memcpy.
Но все-таки логика компилятора мне непонятна. Дело в том, что ниже в функции есть вызов memcpy(pX->ectx.N, pWrappedKey->UKM, 8) - он транслируется в __rt_memcpy без всяких ухищрений.
aaarrr
Цитата(Harvester @ Aug 13 2015, 12:26) *
Не прокатило sad.gif .

Не прокатило в каком смысле - компилятор __packed не понимает, или все равно оставил __rt_memcpy_w?

Цитата(Harvester @ Aug 13 2015, 12:26) *
Но все-таки логика компилятора мне непонятна. Дело в том, что ниже в функции есть вызов memcpy(pX->ectx.N, pWrappedKey->UKM, 8) - он транслируется в __rt_memcpy без всяких ухищрений.

А какая связь между этим memcpy и первым?
Harvester
Цитата(aaarrr @ Aug 13 2015, 12:44) *
Не прокатило в каком смысле - компилятор __packed не понимает, или все равно оставил __rt_memcpy_w?


А какая связь между этим memcpy и первым?

1. Оставил __rt_memcpy_w
2. И там и там 2-м параметром используется невыровненный указатель (входной параметр функции)
scifi
Цитата(Harvester @ Aug 13 2015, 12:26) *
Нашел вот-такой документ: How do the ARM Compilers handle memcpy()?

Кстати, там в примере перед передачей __packed указателя в memcpy() сначала делается явное приведение (void*). Не очень понятно, почему, но возможно, что такой взмах бубном необходим.

Цитата(Harvester @ Aug 13 2015, 13:00) *
2. И там и там 2-м параметром используется невыровненный указатель (входной параметр функции)

Вы бы привели описание типов RFC4357_WRAPPED_KEY_PTR и GOST28147_BCTX_PTR, если это не военная тайна, конечно. Не исключено, что тогда сразу станет ясно, почему по-разному срабатывает memcpy().
Golikov A.
Цитата
1. Оставил __rt_memcpy_w

а как вы написали? при передаче или при вызове тип указателя преобразовали?
я бы в объявление RFC4357_WRAPPED_KEY_PTR все же добавил __packed

Harvester
Цитата(scifi @ Aug 13 2015, 13:08) *
Кстати, там в примере перед передачей __packed указателя в memcpy() сначала делается явное приведение (void*). Не очень понятно, почему, но возможно, что такой взмах бубном необходим.

Действительно, проверю.
Цитата(scifi @ Aug 13 2015, 13:08) *
Вы бы привели описание типов RFC4357_WRAPPED_KEY_PTR и GOST28147_BCTX_PTR, если это не военная тайна, конечно. Не исключено, что тогда сразу станет ясно, почему по-разному срабатывает memcpy().

Да не вопрос.
Код
typedef struct RFC4357_WRAPPED_KEY_tag {
  UCHAR UKM[8];
  UCHAR KEY[GOST28147_KEY_SIZE];
  ULONG CRC;
} RFC4357_WRAPPED_KEY, *RFC4357_WRAPPED_KEY_PTR;


Код
#if defined(__ICCARM__) || defined(__ICCAVR__)          // IAR
#pragma pack(ALIGNMENT)            // IAR
#define __attribute__(...) // IAR
#endif            

#if !defined(__ARMCC_VERSION)
#pragma pack (push, 4)
#endif
...
typedef struct GOST28147_BCTX_tag {
  GOST28147_CTX ectx;
  ULONG cbInbuf;
  UCHAR buf[GOST28147_BLOCK_SIZE];
  ULONG KeyMeshingBlocks;
  GOST28147_KM_PROC KeyMeshingProc;
  ULONG KeyMeshingBlocksRemain;
  UCHAR BufferedKey[GOST28147_KEY_SIZE];
#if defined(__ICCARM__) || defined(__ICCAVR__)
}__attribute__ ((packed)) GOST28147_BCTX, *GOST28147_BCTX_PTR;
#else
} GOST28147_BCTX, *GOST28147_BCTX_PTR;
#endif //

#if !defined(__ARMCC_VERSION)
#pragma pack (pop)
#endif

#if defined(__ICCARM__) || defined(__ICCAVR__)          // IAR
#pragma pack()             // IAR
#endif                     // IAR

Какая-то странная мешанина директив.
aaarrr
Цитата(Harvester @ Aug 13 2015, 13:00) *
1. Оставил __rt_memcpy_w
2. И там и там 2-м параметром используется невыровненный указатель (входной параметр функции)

1. Если структура объявлена как
Код
typedef struct
{
} RFC4357_WRAPPED_KEY, *RFC4357_WRAPPED_KEY_PTR;

то вполне возможно такое поведение. Тогда надо:
Код
UCHAR RFC4357_KeyUnwrap(GOST28147_BCTX_PTR pX,
                         __packed RFC4357_WRAPPED_KEY *pWrappedKey,
                         PUCHAR pUnwrappingKey,
                         PUCHAR pUnwrappedKey)


2. В первом случае компилятор считает указатель выровненным.
scifi
Цитата(Harvester @ Aug 13 2015, 12:26) *
Но все-таки логика компилятора мне непонятна. Дело в том, что ниже в функции есть вызов memcpy(pX->ectx.N, pWrappedKey->UKM, 8) - он транслируется в __rt_memcpy без всяких ухищрений.

После того, как вы привели объявление типа, стало понятно. Дело в том, что pX уже упакованный, так как указывает на упакованную структуру (см. объявление соответствующего типа).

Цитата(Harvester @ Aug 13 2015, 13:30) *
Какая-то странная мешанина директив.

Ничего странного. Просто упаковывают структуру разными способами в зависимости от применяемого компилятора.
Harvester
Цитата(aaarrr @ Aug 13 2015, 13:31) *
1. Если структура объявлена как
Код
typedef struct
{
} RFC4357_WRAPPED_KEY, *RFC4357_WRAPPED_KEY_PTR;

то вполне возможно такое поведение. Тогда надо:
Код
UCHAR RFC4357_KeyUnwrap(GOST28147_BCTX_PTR pX,
                         __packed RFC4357_WRAPPED_KEY *pWrappedKey,
                         PUCHAR pUnwrappingKey,
                         PUCHAR pUnwrappedKey)

Именно это не прокатило - компилятор оставил __rt_memcpy_w (это было первое, что предложили).
aaarrr
Цитата(Harvester @ Aug 13 2015, 13:49) *
это было первое, что предложили

Нет, первое было:
Код
UCHAR RFC4357_KeyUnwrap(GOST28147_BCTX_PTR pX,
                         __packed RFC4357_WRAPPED_KEY_PTR pWrappedKey,
                         PUCHAR pUnwrappingKey,
                         PUCHAR pUnwrappedKey)
Harvester
Цитата(scifi @ Aug 13 2015, 13:40) *
Ничего странного. Просто упаковывают структуру разными способами в зависимости от применяемого компилятора.

ЧТО директивы делают я понимаю, я просто не могу понять смысла их комбинации:
Код
#if defined(__ICCARM__) || defined(__ICCAVR__)
#pragma pack(ALIGNMENT)            // Если IAR - последующие объявления пакуются по ALIGNMENT (4)
#define __attribute__(...) // ??? возможно это отмена ключевого слова attribute - но зачем?
#endif            

#if !defined(__ARMCC_VERSION)
#pragma pack (push, 4)  // Если не ARMCC, снова приказываем паковать по 4 с сохранением текущего уровня упаковки
#endif
typedef struct GOST28147_BCTX_tag {
...
#if defined(__ICCARM__) || defined(__ICCAVR__)
}__attribute__ ((packed)) GOST28147_BCTX, *GOST28147_BCTX_PTR; // Если IAR - используем (отмененное?) ключевое слово
#else
} GOST28147_BCTX, *GOST28147_BCTX_PTR;

#if !defined(__ARMCC_VERSION)
#pragma pack (pop) // Если не ARMCC - возвращаем уровень упаковки
#endif

#if defined(__ICCARM__) || defined(__ICCAVR__)
#pragma pack()             // Если IAR - ставим уровень упаковки по умолчанию
#endif

Т.е. если я правильно разобрал, в случае компилятора IAR явная упаковка указывается 2 раза, а для других компиляторов - ни одного. Наверное, стоит добавить условие упаковки для ARMCC?

Цитата(aaarrr @ Aug 13 2015, 13:58) *
Нет, первое было:
Код
UCHAR RFC4357_KeyUnwrap(GOST28147_BCTX_PTR pX,
                         __packed RFC4357_WRAPPED_KEY_PTR pWrappedKey,
                         PUCHAR pUnwrappingKey,
                         PUCHAR pUnwrappedKey)

Мне кажется, что с точки зрения языка оба объявления тождественны. Но проверю sm.gif

Хм, забавно.
__packed RFC4357_WRAPPED_KEY_PTR pWrappedKey - ничего не дает, а
__packed RFC4357_WRAPPED_KEY *pWrappedKey выдает ошибку "Error: C2510E: Definition of 'struct RFC4357_WRAPPED_KEY_tag' not '__packed': qualifier ignored". Получается, если параметр функции указан как __packed, то тип должен быть упакован явно.
aaarrr
Цитата(Harvester @ Aug 13 2015, 14:21) *
Получается, если параметр функции указан как __packed, то тип должен быть упакован явно.

Да, не умеет он указатели на "абстрактно" упакованные структуры делать, это только для базовых типов проходит.

Остается или "упаковать" typedef или выровнять структуру.
Golikov A.
указатель, а не структуру предлагаютsm.gif ... но все же учитывая историю со 2 структурой, лучше и первую попаковать при объявлении сразу!

А вообще корректно не пакованную структуру пытаться запихать куда-то как пакованную? Или мы просто хотим чтобы он к ней относился как к пакованной, опять же тоже не есть корректно.... ИМХО
aaarrr
Цитата(Golikov A. @ Aug 13 2015, 14:38) *
А вообще корректно не пакованную структуру пытаться запихать куда-то как пакованную? Или мы просто хотим чтобы он к ней относился как к пакованной, опять же тоже не есть корректно.... ИМХО

От структуры зависит. Но раз уж не хочет компилятор делать указатель на упакованную структуру на базе описания не упакованной, то и фиг с ним.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.