间接函数调用使用奇数地址 [英] Indirect function call uses odd address

查看:23
本文介绍了间接函数调用使用奇数地址的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当 ARM Cortex-M3 的 GCC 4.7.3 (20121207) 获取函数的地址时,它不会获取函数的确切地址.我可以在那个指针中看到一个一个.

When the GCC 4.7.3 (20121207) for ARM Cortex-M3 takes the address of a function it doesn't get the exact address of the function. I can see an off-by-one in that pointer.

// assume at address 0x00001204;
int foo() {
  return 42;
}

void bar() {
  int(*p)() = &foo;  // p = 0x1205;
  p();               // executed successfully
  foo();             // assembly: "bl 0x00001204;"
}

虽然指针指向奇数地址,但执行成功.我希望在这一点上有一个例外.为什么它需要那个奇怪的地址,为什么它没有伤害.

Although the pointer points to an odd address, the execution is successful. I would expect an exception at this point. Why does it takes that strange address and why doesn't it hurt.

编辑

  • SO 文章 描述了拇指模式和 ARM 模式之间的区别.为什么CPU在同一个模式下直接调用函数时,偏移量是不可见的?
  • 应该保留奇数地址还是重置位 0 会导致困难?(直到现在我才看到)
  • The SO article describes a difference between thumb and ARM mode. Why is that offset not visible when the function is called directly although the CPU is in the same mode?
  • Should the odd address be kept or would resetting the bit 0 cause hard? (what I could not see until now)

推荐答案

我从我的一个示例中拼凑了一些东西来快速演示正在发生的事情.

I cobbled up something from one of my examples to quickly demonstrate what is going on.

vectors.s:

/* vectors.s */
.cpu cortex-m3
.thumb

.word   0x20002000  /* stack top address */
.word   _start      /* 1 Reset */
.word   hang        /* 2 NMI */
.word   hello       /* 3 HardFault */
.word   hang        /* 4 MemManage */
.word   hang        /* 5 BusFault */
.word   hang        /* 6 UsageFault */
.word   hang        /* 7 RESERVED */
.word   hang        /* 8 RESERVED */
.word   hang        /* 9 RESERVED*/
.word   hang        /* 10 RESERVED */
.word   hang        /* 11 SVCall */
.word   hang        /* 12 Debug Monitor */
.word   hang        /* 13 RESERVED */
.word   hang        /* 14 PendSV */
.word   hang        /* 15 SysTick */
.word   hang        /* 16 External Interrupt(0) */
.word   hang        /* 17 External Interrupt(1) */
.word   hang        /* 18 External Interrupt(2) */
.word   hang        /* 19 ...   */

.thumb_func
.global _start
_start:
    /*ldr r0,stacktop */
    /*mov sp,r0*/
    bl notmain
    ldr r0,=notmain
    mov lr,pc
    bx r0
    b hang

.thumb_func
hang:   b .

hello: b .

.thumb_func
.globl PUT32
PUT32:
    str r1,[r0]
    bx lr

.end

blinker01.c:

extern void PUT32 ( unsigned int, unsigned int );

int notmain ( void )
{
    PUT32(0x12345678,0xAABBCCDD);
    return(0);
}

生成文件:

#ARMGNU = arm-none-eabi
ARMGNU = arm-none-linux-gnueabi

AOPS = --warn --fatal-warnings 
COPS = -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding 


all : blinker01.gcc.thumb.bin 

vectors.o : vectors.s
    $(ARMGNU)-as vectors.s -o vectors.o

blinker01.gcc.thumb.o : blinker01.c
    $(ARMGNU)-gcc $(COPS) -mthumb -c blinker01.c -o blinker01.gcc.thumb.o

blinker01.gcc.thumb2.o : blinker01.c
    $(ARMGNU)-gcc $(COPS) -mthumb -mcpu=cortex-m3 -march=armv7-m -c blinker01.c -o blinker01.gcc.thumb2.o

blinker01.gcc.thumb.bin : memmap vectors.o blinker01.gcc.thumb.o
    $(ARMGNU)-ld -o blinker01.gcc.thumb.elf -T memmap vectors.o blinker01.gcc.thumb.o
    $(ARMGNU)-objdump -D blinker01.gcc.thumb.elf > blinker01.gcc.thumb.list
    $(ARMGNU)-objcopy blinker01.gcc.thumb.elf blinker01.gcc.thumb.bin -O binary

拆解:

Disassembly of section .text:

08000000 <_start-0x50>:
 8000000:   20002000    andcs   r2, r0, r0
 8000004:   08000051    stmdaeq r0, {r0, r4, r6}
 8000008:   0800005d    stmdaeq r0, {r0, r2, r3, r4, r6}
 800000c:   0800005e    stmdaeq r0, {r1, r2, r3, r4, r6}
 8000010:   0800005d    stmdaeq r0, {r0, r2, r3, r4, r6}
 8000014:   0800005d    stmdaeq r0, {r0, r2, r3, r4, r6}
 8000018:   0800005d    stmdaeq r0, {r0, r2, r3, r4, r6}
 800001c:   0800005d    stmdaeq r0, {r0, r2, r3, r4, r6}
 8000020:   0800005d    stmdaeq r0, {r0, r2, r3, r4, r6}
 8000024:   0800005d    stmdaeq r0, {r0, r2, r3, r4, r6}
 8000028:   0800005d    stmdaeq r0, {r0, r2, r3, r4, r6}
 800002c:   0800005d    stmdaeq r0, {r0, r2, r3, r4, r6}
 8000030:   0800005d    stmdaeq r0, {r0, r2, r3, r4, r6}
 8000034:   0800005d    stmdaeq r0, {r0, r2, r3, r4, r6}
 8000038:   0800005d    stmdaeq r0, {r0, r2, r3, r4, r6}
 800003c:   0800005d    stmdaeq r0, {r0, r2, r3, r4, r6}
 8000040:   0800005d    stmdaeq r0, {r0, r2, r3, r4, r6}
 8000044:   0800005d    stmdaeq r0, {r0, r2, r3, r4, r6}
 8000048:   0800005d    stmdaeq r0, {r0, r2, r3, r4, r6}
 800004c:   0800005d    stmdaeq r0, {r0, r2, r3, r4, r6}

08000050 <_start>:
 8000050:   f000 f80a   bl  8000068 <notmain>
 8000054:   4803        ldr r0, [pc, #12]   ; (8000064 <PUT32+0x4>)
 8000056:   46fe        mov lr, pc
 8000058:   4700        bx  r0
 800005a:   e7ff        b.n 800005c <hang>

0800005c <hang>:
 800005c:   e7fe        b.n 800005c <hang>

0800005e <hello>:
 800005e:   e7fe        b.n 800005e <hello>

08000060 <PUT32>:
 8000060:   6001        str r1, [r0, #0]
 8000062:   4770        bx  lr
 8000064:   08000069    stmdaeq r0, {r0, r3, r5, r6}

08000068 <notmain>:
 8000068:   b508        push    {r3, lr}
 800006a:   4803        ldr r0, [pc, #12]   ; (8000078 <notmain+0x10>)
 800006c:   4903        ldr r1, [pc, #12]   ; (800007c <notmain+0x14>)
 800006e:   f7ff fff7   bl  8000060 <PUT32>
 8000072:   2000        movs    r0, #0
 8000074:   bd08        pop {r3, pc}
 8000076:   46c0        nop         ; (mov r8, r8)
 8000078:   12345678    eorsne  r5, r4, #120, 12    ; 0x7800000
 800007c:   aabbccdd    bge 6ef33f8 <_start-0x110cc58>

首先要注意hang vs hello,这是一个gnuism,你需要在汇编中将标签声明为thumb 函数才能使其实际工作对于这种事情.hang 正确声明,向量表正确使用奇数地址,hello 未正确声明,偶数地址放在那里.C 编译代码会自动正确执行此操作.

First off note hang vs hello, this is a gnuism you need to, in assembly, declare a label to be a thumb function in order for it to actually work for this kind of thing. hang is properly declared and the vector table properly uses the odd address, hello is not properly declared and the even address is put in there. C compiled code automatically does this properly.

这是您要问的一个主要示例,bl 到 C 函数 notmain 不会,也不能使用奇数地址.但是要使用 bx 你需要函数 main 的地址,如果你做了一个 maincode>bx 到 ARMvsometingT 上的 0x800068 它会切换到 arm 模式并最终崩溃,如果它在 cortex-m 上击中拇指模式(希望崩溃而不是绊倒)一个 bx 到甚至地址都应该立即出错.

Here is a prime example of what you are asking though, bl to the C function notmain does not, cannot, use an odd address. But to use bx you ask for the address to the function main and that address is provided to the code as 0x8000069 for for a function at address 0x8000068, if you did a bx to 0x800068 on an ARMvsometingT it would switch to arm mode and crash eventually if it hit thumb mode (hopefully crash and not stumble along) on a cortex-m a bx to an even address should fault immediately.

08000050 <_start>:
 8000050:   f000 f80a   bl  8000068 <notmain>
 8000054:   4803        ldr r0, [pc, #12]   ; (8000064 <PUT32+0x4>)
 8000056:   46fe        mov lr, pc
 8000058:   4700        bx  r0
 800005a:   e7ff        b.n 800005c <hang>
 8000064:   08000069    stmdaeq r0, {r0, r3, r5, r6}

为什么 bl 不能是奇数?看看上面的编码 bl 从 0x8000050 到 0x8000068,pc 前面两个所以 4 字节所以取 0x8000068 - 0x8000054 = 0x14 除以 2,你得到 0x00A.那是 pc 的偏移量,这就是指令中编码的内容(指令后半部分的 0A).除以二是基于拇指指令总是 2 字节(当时很好)的知识,因此如果他们将偏移量放在 2 字节指令而不是字节中,它们可以达到两倍.因此 lsbit 丢失了两者之间的增量,因此由硬件控制.

Why can't bl be odd? Look at the encoding above bl from 0x8000050 to 0x8000068, the pc is two ahead so 4 byte so take 0x8000068 - 0x8000054 = 0x14 divide that by 2 and you get 0x00A. That is the offset to the pc and that is what is encoded in the instructions (the 0A in the second half of the instruction). The divide by two is based on knowledge that thumb instructions are always 2 bytes (well at the time) and so they can reach twice as far if they put the offset in 2 byte instructions rather than in bytes. So the lsbit is lost of the delta between the two, so controlled by the hardware.

您的代码所做的是在一个地方您要求提供奇数地址的拇指函数的地址,另一种情况是查看始终为偶数的分支链接的反汇编.

What your code did was in one place you asked for the address of a thumb function which gives the odd address, the other case was looking at the disassembly of a branch link which is always even.

这篇关于间接函数调用使用奇数地址的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆