|
From: | Andy H |
Subject: | [avr-gcc-list] Re: Patch Fix PR35013, PR27192 |
Date: | Tue, 15 Apr 2008 23:02:13 -0400 |
User-agent: | Thunderbird 2.0.0.12 (Windows/20080213) |
RFC A problem has come up trying to fix function pointer arthmetic bugs.
I created patch to solve this, but Anatoly has found a problem. Without patch we had &func returning word address and (&func + 2) returning byte address. This occurred because AVR backend did not recognise (func+2) as program memory and did not use linker directive gs(func+2). With patch we get &func and &func+2 both returning word address. Which solved the bugs reported. Now if such a word pointer undergoes further arithmetic in c, then it will, of course, be adjusting it by words. The problem that Anatoly discovered is that optimization can break this. His example involved volatile pointers but it will happen on more realistic cases. For example if we create pointers to Foo, Foo+2, Foo+4, optimization will try and use one pointer to create values of other pointers. So we will get word address of Foo offset by words - or word address of Foo offset by bytes! This just depends if the offset calculation is done in gcc or the linker. Aghhhh! To fix is not simple. The following are ideas only - please add some more 1) One way to to get linker to perform maths on gs() using word offsets. gs(foo+2) would be word address of foo+ 2 words. Then it would not matter if gcc or linker performed maths. I do not know if this is possible or what problems this might create. 2) We could avoid using gs() and get function address as byte address + byte offset. This would require extra run-time code for function pointer calls (to divide by two). It is useful in that same pointers could be used to read bytes from program memory. 3) Give up and dont permit any arithmetic. (Perhaps error or warning would still be needed) 4) Like (1) but use new directive gsw() to permit this method? 5) Like (2) but use attribute to permit this method? 6) Get gcc to recognize constant pointer maths and exclude it from linker gs() 7) Get gcc to recognize constant pointer maths and pass to linker as gs(Foo) + n instead of gs(Foo+n) - if this is possible. Please add to discussion. Anatoly Sokolov wrote: Hi, Andy. This patch don't solve all problems with addition and subtraction operations on function pointers. Test case: void (* p) (void); char *e; void bar (void) { asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); } int main (void) { p = &bar; p = p + 4; p(); return 0; } avr-gcc ... -Os ... asm: ldi r30,lo8(gs(bar+4)) ldi r31,hi8(gs(bar+4)) sts (p)+1,r31 sts p,r30 icall In this case the pointer increases on 4 bytes, and the "p();" go to on third 'nop' in 'bar' function. If 'p' variable to declare as volatile (disable optimization), then the pointer increases on 4 words, and the "p();" go to on fifth 'nop' in 'bar' function. void (* volatile p) (void); ... asm: ldi r24,lo8(gs(bar)) ldi r25,hi8(gs(bar)) sts (p)+1,r25 sts p,r24 lds r24,p lds r25,(p)+1 adiw r24,4 sts (p)+1,r25 sts p,r24 lds r30,p lds r31,(p)+1 icall I think it is necessary to document, that arithmetic operations on function pointers don't supported for avr target. Anatoly. |
[Prev in Thread] | Current Thread | [Next in Thread] |