Subject: Re: help with inline assembly code?

From: "Chris Friesen" <[email-masked]>
Date: Fri, 24 Apr 2009 12:06:16 -0600

Scott Wood wrote:
> Chris Friesen wrote:
>> I've got a function that is used to overwrite opcodes in order to create 
>> self-modifying code.  It worked just fine with previous compilers, but 
>> with gcc 4.3 it seems like it sometimes (but not always) causes problems 
>> when inlined.  If I force it to never be inlined, it works fine.
>>
>> First, here's the code:
>>
>> void alter_opcode(unsigned long *addr, unsigned long opcode)
>> {
>>     asm volatile(
>>                 "stw    %1,0(%0)    \n\t"
>>                 "dcbf   0,%0        \n\t"
>>                 "sync            \n\t"
>>                 "icbi   0,%0,        \n\t"
>>                 "isync            \n\t"
>>                     :: "r" (addr), "r" (opcode): "memory");
>> }
>>
>> The symptom of the problem is a segfault on the "stw" instruction.  I've 
>> verified that the address it's trying to write to is the expected 
>> address, 
> 
> Verified by looking at the address in "addr", or by looking at the 
> reported faulting address?

Verified by running it in userspace under gdb, then looking at the 
registers listed in the disassembly and comparing it to the process maps.

>> and that the opcode being written is the expected opcode.
>>
>> I assume I've mixed up the registers or constraints or 
>> something...anyone want to take a crack at it?
> 
> Is the compiler assigning r0 to addr?  That will be treated as a literal 
> zero instead.  Try changing "r" (addr) to "b" (addr), or use stwx.

Bingo!  Is there a constraint to tell the compiler to not use r0 for addr?

Chris