.text ; The functionfoo .align 2 .globl _foo _foo: mflr r0 ; move the link register into r0 stw r0,8(r1) ; save the link register valueonthestack stwu r1,-64(r1) ; set up the frame onthestack bl L_bar$stub ; branch and link tothe symbol stub for_bar lwz r0,72(r1) ; loadthe link register valuefromthe stack addi r1,r1,64 ; removed the frame fromthe stack mtlr r0 ; restore the link register blr ; branch tothe link register toreturn
.symbol_stub ; the standard symbol stub section L_bar$stub: .indirect_symbol _bar ; identify this symbol stub forthe ; symbol _bar lis r11,ha16(L_bar$lazy_ptr) ; load r11 withthe high 16 bits ofthe ; address of bar’s lazy pointer lwz r12,lo16(L_bar$lazy_ptr)(r11) ; loadthevalueof bar’s lazy pointer ; into r12 mtctr r12 ; move r12 tothe count register addi r11,r11,lo16(L_bar$lazy_ptr) ; load r11 withthe address of bars lazy ; pointer bctr ; jump tothevaluein bar’s lazy pointer
.lazy_symbol_pointer ; the lazy pointer section L_bar$lazy_ptr: .indirect_symbol _bar ; identify this lazy pointer for symbol ; _bar .long dyld_stub_binding_helper ; initialize the lazy pointer tothe stub ; binding helper address
Listing 3 Example of a position-independent, indirect function call
.text ; The function foo .align2 .globl _foo _foo: mflr r0 ; move the link register into r0 stw r0,8(r1) ; save the link register value on the stack stwu r1,-80(r1) ; set up the frame on the stack bl L_bar$stub ; branch and link to the symbol stub for _bar lwz r0,88(r1) ; load the link register value from the stack addi r1,r1,80; removed the frame from the stack mtlr r0 ; restore the link register blr ; branch to the link register to return
.picsymbol_stub ; the standard pic symbol stub section L_bar$stub: .indirect_symbol _bar ; identify this symbol stub for the symbol _bar mflr r0 ; save the link register (LR) bcl 20,31,L0$_bar ; Use the branch-always instruction that does not ; affect the link register stack to get the ; address of L0$_bar into the LR. L0$_bar: mflr r11 ; then move LR to r11 ; bar’s lazy pointer is located at ; L0$_bar + distance addis r11,r11,ha16(L_bar$lazy_ptr-L0$_bar); L0$_bar plus high 16 bits of ; distance mtlr r0 ; restore the previous LR lwz r12,lo16(L_bar$lazy_ptr-L0$_bar)(r11); ...plus low 16 of distance mtctr r12 ; move r12 to the count register addi r11,r11,lo16(L_bar$lazy_ptr-L0$_bar); load r11 with the address of bar’s ; lazy pointer bctr ; jump to the value in bar’s lazy ; pointer
.lazy_symbol_pointer ; the lazy pointer section L_bar$lazy_ptr: .indirect_symbol _bar ; identify this lazy pointer for symbol bar .long dyld_stub_binding_helper ; initialize the lazy pointer to the stub ; binding helper address.
在IA-32架构中,symbol引用被作为一个symbol stub和一个lazy symbol指针结合进一个JMP指令来实现,这样的指令指向了动态链接器。当动态链接器遇到这样的指令时,它定位了被引用的symbol并且修改JMP指令去直接指向这个symbol。因此,接下来的JMP执行指令直接跳转到被应用的symbol。 Listing 4 C program using an imported symbol