[HN Gopher] ARM Assembly: [?] Ways to Return (2017)
       ___________________________________________________________________
        
       ARM Assembly: [?] Ways to Return (2017)
        
       Author : quantum5
       Score  : 29 points
       Date   : 2023-02-09 06:29 UTC (1 days ago)
        
 (HTM) web link (quantum5.ca)
 (TXT) w3m dump (quantum5.ca)
        
       | Olipro wrote:
       | For older architectures, you really want to use the BX
       | instruction unless you can guarantee you're not switching
       | execution mode.
       | 
       | as a bit of pointless trivia, MOV PC, PC does not cause an
       | infinite loop - it skips the instruction immediately following.
        
       | ksherlock wrote:
       | Early versions of ARM (ARM 1/2, optional in 3/4) had a combined
       | program counter / status register; since there was only a 26-bit
       | address space and instructions are always 32-bit word aligned,
       | the top 6 and bottom 2 bits were used for the status register.
       | 
       | So, if you're still developing for an ARM1, not all of these are
       | equivalent. MOV/POP/etc will set the PC and the status register;
       | B/BL will leave the status register bits alone.
       | 
       | * edit: MOV/MOVS determined if the status bits are written to
       | R15.
        
       | garbagecoder wrote:
       | fwiw, if you're using ARM assembly on an Apple device there are a
       | few differences and one of them is how you pass arguments.
       | 
       | https://developer.apple.com/documentation/xcode/writing-arm6...
        
         | wk_end wrote:
         | The article is describing classic ARM. (Modern) Apple devices
         | are all ARM64, which doesn't have the PC as a GPR.
         | 
         | The article is also entirely about how the PC is a general-
         | purpose register on 32-bit ARM machines. No idea if the 1st gen
         | iPhones or whatever used an idiosyncratic calling
         | convention...but it's moot in the context of this post, because
         | argument passing isn't covered here!
         | 
         | This post really is just about the observation that the PC is a
         | GPR implies that there's a bunch of different ways to get data
         | into it. It's pretty airy. The author was admittedly a first or
         | second year university student at the time, so it's hard to be
         | too mad though.
        
           | flykespice wrote:
           | The only one getting mad here is you for no reason.
        
       | klodolph wrote:
       | Thankfully, PC is no longer a GPR in ARM64. Making PC a GPR seems
       | elegant at first glance, but when you actually dive into it and
       | see how it affects processor implementations and how it affects
       | the code you write, it turns out to be extremely messy and
       | inconvenient. Good riddance PC as GPR, don't let the door hit you
       | on the way out.
        
         | crest wrote:
         | It's neat when writing assembler e.g. add a scaled byte value
         | to the PC to implement a jump table or perform a scaled and
         | indexed load to the PC. In ARM it also produced a neat short
         | and fast function prologue/epilogue. In my opinion the worst
         | problem causes are the 1001 and one special cases it adds in an
         | optimised out of order implementation. The Thumb interworking
         | makes it more worse, but is useful to increase code density in
         | ARM v6-M and can even increase performance (per clock) of ARM
         | v7-M cores. I don't expect it causes too much problems in
         | single-issue in-order implementations like the Cortex M3 and
         | M4. I would like to know how much design time and core area is
         | spend on this in the M7 and M85 cores.
        
       | Dwedit wrote:
       | Method 1 (popping PC off the stack) and Method 3 (mov pc,lr) do
       | not work on the earliest ARM processors that support THUMB, as it
       | will not switch to THUMB mode without executing a BX instruction.
       | 
       | Checking reference manuals:
       | 
       | ARMV4T (ARM7TDMI/ARM9TDMI): Does NOT switch to THUMB mode
       | automatically
       | 
       | ARMV5: Does NOT switch to THUMB mode automatically
       | 
       | ARMV7: Does switch to THUMB mode automatically
        
         | benj111 wrote:
         | I thought it switched to thumb based on odd/ evenness.
         | 
         | Plus if you don't want to switch to thumb, this still works?
        
           | pm215 wrote:
           | It is based on whether the low bit of the jump target is 0 or
           | 1, but the first version of Thumb only did that check-and-
           | switch-mode on a small set of jump instructions, not on every
           | way you could alter the program counter. For the others you
           | got the same behaviour you always had for an attempt to jump
           | to an unaligned address, which is to say the low bit was just
           | ignored. The compiler had to generate slightly different code
           | if you wanted your function to support interworking. In the
           | versions of Thumb starting with IIRC Armv5t or maybe v6t2,
           | more instructions did the mode switch check, and codegen got
           | a bit simpler.
        
           | Dwedit wrote:
           | It does work if you intend to stay in ARM mode only, and will
           | crash if THUMB-mode code calls the function. ARMV7 will do
           | the mode switch automatically and not crash.
        
       | derf_ wrote:
       | In 2010, I tried to use callgrind to profile a project on Arm,
       | after having used it to great effect on x86, and discovered that
       | because of the variety of ways to return (and call!) functions on
       | Arm, callgrind was unable to reliably identify function call and
       | return sites. It created cycles in the call graph and even failed
       | to record a function's self measurements correctly (because it
       | could not tell when you left that function).
       | 
       | The problem boiled down to the valgrind frontend code that splits
       | things up into basic blocks being incapable of having an
       | instruction be both a conditional jump and a function call /
       | return at the same time. That never happens on x86, but of course
       | this is possible (and totally normal) on 32-bit Arm. Sadly, I ran
       | out of time to try to re-architect this code and had to move on
       | to other projects.
       | 
       | Over 12 years later, it looks like it never did get fixed:
       | https://bugs.kde.org/show_bug.cgi?id=252091
        
         | Dwedit wrote:
         | I use stuff like "bxeq lr" all the time. There's your
         | conditional return instruction.
        
       | not2b wrote:
       | As other commenters have mentioned, exploiting this will confuse
       | other tools and debuggers. Also it tends to play havoc with
       | branch prediction meaning that there may be performance
       | penalties.
        
       ___________________________________________________________________
       (page generated 2023-02-10 23:01 UTC)