Unaligned pointer as function parameter

Asked by adaub

Hi,

i am currently porting software to the arm architecture using the gnu arm embedded toolchain. I have some problems with unaligned pointers as function parameters. Unaligned access itself is working as intended but when a pointer to an unaligned structure is passed to a function i get an abort exception.

Consider the following code:

typedef struct secondstruct
{
  int dummy1;
  int dummy2;
  int dummy3;
  int dummy4;
}secondstruct;

typedef struct __attribute__ ((packed)) firststruct
{
  char a;
  secondstruct b;
}firststruct;

int global;

void callingFunction(void)
{
  firststruct firstStruct;
  secondstruct secondStruct;
  secondStruct.dummy1 = 0x1;
  secondStruct.dummy2 = 0x2;
  secondStruct.dummy3 = 0x3;
  secondStruct.dummy4 = 0x4;
  firstStruct.b = secondStruct; <- unaligned acces but still working since compiler is aware of it
  myFunction(&firstStruct.b); <- calling with unaligned pointer
}

void myFunction(secondstruct* testPointer)
{
  secondstruct secondStruct;
  secondStruct = *testPointer; <- Exception since ldm / stm on unaligned pointer
  global = secondStruct.dummy1 + secondStruct.dummy2;
}

In myFunction the unaligned pointer is used to fill the local variable. The compiler does not know that the pointer is unaligned and tries to fill the local variable with ldm and stm instructions. Since the pointer is unaligned these instructions are not allowed and result in an abort expcetion.

Is this a bug in the compiler or do i have to be aware of every unalinged pointer as function parameter and handle it manually?

Question information

Language:
English Edit question
Status:
Answered
For:
GNU Arm Embedded Toolchain Edit question
Assignee:
No assignee Edit question
Last query:
Last reply:
Revision history for this message
Thomas Preud'homme (thomas-preudhomme) said :
#1

Hi Adaub,

The problem is in the declaration of myFunction. Type secondstruct * indicates that this is a regular pointer to a secondstruct object which should be aligned. I'm not sure how you would tell the compiler that a pointer is not aligned, the aligned attribute can only increase alignment.

Best regards.

Revision history for this message
adaub (adaub) said :
#2

Hi Thomas,

yes i understand that the compiler does not see the unalignement if he only evaluates the definition of secondstruct. But if you use packed structures it is a common case, that itself aligned structs starting on unaligned addresses. In such a case the compiler can not expect a pointer to a struct to be aligned, if he fully supports unalgined memory access.

I can handle such situation manually and use memcpy instead of the direct assignment, but the question is if there is a way that the compiler handles such situation by itself?

Revision history for this message
Leo Havmøller (leh-p) said :
#3

The KEIL ARM compiler can do this: http://www.keil.com/support/man/docs/armcc/armcc_chr1359124230476.htm
Unfortunately gcc doesn't have anything similar.

If the struct is resonably short, you can just memcpy it to a local variable, like your own example.

But the usual solution is to have a set of macros/functions like get_le32/set_le32 etc, which access the individual struct fields. These macros/function are then implemented differently depending on the CPU. E.g. for Cortex-M0, they would use byte acces, but for Cortex-M3 the would just cast and let the CPU handle the unaligned access.

Revision history for this message
sephamorr (alexanderdewing) said :
#4

In GCC, to convert an unaligned pointer to an aligned one, I use something like this:

typedef struct unaligned_int_s{
    int i;
} __attribute((__packed__)) unaligned_int_t;
void set(int* potentially_unaligned)
{
    unaligned_int_t* i=(unaligned_int_t*)potentially_unaligned;
    i->i=7; //i->i can be safely accessed as the compiler treats all entries in a packed struct as unaligned.
}
int get(int* potentially_unaligned)
{
    unaligned_int_t* i=(unaligned_int_t*)potentially_unaligned;
    return i->i; //i->i can be safely accessed as the compiler treats all entries in a packed struct as unaligned.
}

See https://godbolt.org/g/WoXsdV
Under cortex-m4, the LDR thumb2 instruction can be unaligned. See (http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0290g/Cdfigfbe.html)
Change the compiler option to -mcpu=cortex-m0 and you'll see that the cortex m0 requires bytewise code generation.
Sorry to necro this thread, thought I should present a solution for GCC.

Can you help with this problem?

Provide an answer of your own, or ask adaub for more information if necessary.

To post a message you must log in.