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

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

问题描述

当为的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.

修改


  • 的<一个href=\"http://stackoverflow.com/questions/14120711/linux-kernel-why-a-functions-address-in-system-map-is-one-byte-before-its-add\">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

/* 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

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>

第一关注挂VS你好,这是你需要,组装,声明一个标签是为了一个拇指功能,为它实际上是这种事情工作gnuism。挂起是正确申报和向量表正确使用奇数地址,你好未正确申报和偶数地址被摆在那里。 ç编译code自动执行此操作正常。

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函数和地址在地址0x8000068提供给code为0x8000069为一个功能,如果你在一个ARMvsometingT做了BX到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 = 0×14除以2,你会得到0x00A被偏移到PC,这就是为EN codeD中的说明(在指令的下半年0A)。由两个分频是基于知识拇指指令总是2字节(以及在时间)等,如果他们把2字节指令而不是字节偏移他们可以达到两倍远。所以,所以LSb丢失两者之间的增量,由硬件这样控制的

why cant 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.

您code所做的是在一个地方,你问一个拇指功能,使奇数地址的地址是什么,另一种情况是在寻找一个分支链接,总是偶数的拆卸。

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天全站免登陆