diff --git a/CMakeLists.txt b/CMakeLists.txt index 719a017..faa8520 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -275,6 +275,19 @@ if (LIBDISPATCH) target_link_libraries(objc ${LIBDISPATCH}) endif () +# Enable .type and .section assembly directives on platforms other than OS X +if (NOT APPLE) + add_definitions(-DHAS_SECTION_DIRECTIVE=1 -DHAS_TYPE_DIRECTIVE=1) +endif () + +# Make weak symbols work on OS X +if (APPLE) + set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS + "${CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS} -undefined dynamic_lookup") + set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,-undefined,dynamic_lookup") + set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -Wl,-undefined,dynamic_lookup") +endif () + # # Installation # diff --git a/block_trampolines.S b/block_trampolines.S index 879e9a7..2955787 100644 --- a/block_trampolines.S +++ b/block_trampolines.S @@ -1,3 +1,5 @@ +#include "common.S" + # # This file defines some trampolines for calling blocks. A block function # looks like this: @@ -15,33 +17,33 @@ .file "block_trampolines.S" #if __arm__ .syntax unified -.globl __objc_block_trampoline_sret - .type __objc_block_trampoline_sret, %function -.globl __objc_block_trampoline_end_sret -.globl __objc_block_trampoline - .type __objc_block_trampoline, %function -.globl __objc_block_trampoline_end +.globl CDECL(__objc_block_trampoline_sret) +TYPE_DIRECTIVE(CDECL(__objc_block_trampoline_sret), %function) +.globl CDECL(__objc_block_trampoline_end_sret) +.globl CDECL(__objc_block_trampoline) +TYPE_DIRECTIVE(CDECL(__objc_block_trampoline), %function) +.globl CDECL(__objc_block_trampoline_end) #else -.globl __objc_block_trampoline_sret - .type __objc_block_trampoline_sret, @function -.globl __objc_block_trampoline_end_sret -.globl __objc_block_trampoline - .type __objc_block_trampoline, @function -.globl __objc_block_trampoline_end +.globl CDECL(__objc_block_trampoline_sret) +TYPE_DIRECTIVE(CDECL(__objc_block_trampoline_sret), @function) +.globl CDECL(__objc_block_trampoline_end_sret) +.globl CDECL(__objc_block_trampoline) +TYPE_DIRECTIVE(CDECL(__objc_block_trampoline), @function) +.globl CDECL(__objc_block_trampoline_end) #endif #if __x86_64 -__objc_block_trampoline: +CDECL(__objc_block_trampoline): mov -15(%rip), %rsi # Load the block pointer into the second argument xchg %rdi, %rsi # Swap the first and second arguments jmp *-32(%rip) # Call the block function -__objc_block_trampoline_end: -__objc_block_trampoline_sret: +CDECL(__objc_block_trampoline_end): +CDECL(__objc_block_trampoline_sret): mov -15(%rip), %rdx # Load the block pointer into the second argument xchg %rdx, %rsi # Swap the first and second arguments jmp *-32(%rip) # Call the block function -__objc_block_trampoline_end_sret: +CDECL(__objc_block_trampoline_end_sret): #elif __i386 -__objc_block_trampoline: +CDECL(__objc_block_trampoline): call next_line # Store the instruction pointer on the stack next_line: pop %eax # Load the old instruction pointer @@ -50,8 +52,8 @@ next_line: mov -9(%eax), %ebx # Load the block pointer to %ebx mov %ebx, 4(%esp) # Store the block pointer in the first argument jmp *-13(%eax) # Call the block function -__objc_block_trampoline_end: -__objc_block_trampoline_sret: +CDECL(__objc_block_trampoline_end): +CDECL(__objc_block_trampoline_sret): call next_line2 # Store the instruction pointer on the stack next_line2: pop %eax # Load the old instruction pointer @@ -60,51 +62,53 @@ next_line2: mov -9(%eax), %ebx # Load the block pointer to %ebx mov %ebx, 8(%esp) # Store the block pointer in the first argument jmp *-13(%eax) # Call the block function -__objc_block_trampoline_end_sret: +CDECL(__objc_block_trampoline_end_sret): #elif __mips__ # ifdef _ABI64 -__objc_block_trampoline: +CDECL(__objc_block_trampoline): move $a1, $a0 ld $a0, -16($25) ld $25, -8($25) jr $25 -__objc_block_trampoline_end: -__objc_block_trampoline_sret: +CDECL(__objc_block_trampoline_end): +CDECL(__objc_block_trampoline_sret): move $a2, $a1 ld $a1, -16($25) ld $25, -8($25) jr $25 -__objc_block_trampoline_end_sret: +CDECL(__objc_block_trampoline_end_sret): # else -__objc_block_trampoline: +CDECL(__objc_block_trampoline): move $a1, $a0 lw $a0, -8($25) lw $25, -4($25) jr $25 -__objc_block_trampoline_end: -__objc_block_trampoline_sret: +CDECL(__objc_block_trampoline_end): +CDECL(__objc_block_trampoline_sret): move $a2, $a1 lw $a1, -8($25) lw $25, -4($25) jr $25 -__objc_block_trampoline_end_sret: +CDECL(__objc_block_trampoline_end_sret): # endif #elif __arm__ -__objc_block_trampoline: +CDECL(__objc_block_trampoline): mov r1, r0 // Move self over _cmd ldr r0, [pc, #-16] // Load the block pointer over self ldr pc, [pc, #-24] // Jump to the block function -__objc_block_trampoline_end: -__objc_block_trampoline_sret: +CDECL(__objc_block_trampoline_end): +CDECL(__objc_block_trampoline_sret): mov r2, r1 // Move self over _cmd ldr r1, [pc, #-16] // Load the block pointer over self ldr pc, [pc, #-24] // Jump to the block function -__objc_block_trampoline_end_sret: +CDECL(__objc_block_trampoline_end_sret): #else #warning imp_implementationWithBlock() not implemented for your architecture -__objc_block_trampoline: -__objc_block_trampoline_end: -__objc_block_trampoline_sret: -__objc_block_trampoline_end_sret: +CDECL(__objc_block_trampoline): +CDECL(__objc_block_trampoline_end): +CDECL(__objc_block_trampoline_sret): +CDECL(__objc_block_trampoline_end_sret): #endif +#if HAS_SECTION_DIRECTIVE .section .note.GNU-stack,"",%progbits +#endif diff --git a/common.S b/common.S new file mode 100644 index 0000000..521e65d --- /dev/null +++ b/common.S @@ -0,0 +1,12 @@ +#if defined(__WIN32__) || defined(__APPLE__) +#define CDECL(symbol) _##symbol +#else +#define CDECL(symbol) symbol +#endif + +#if HAS_TYPE_DIRECTIVE +#define TYPE_DIRECTIVE(symbol, symboltype) .type symbol, symboltype +#else +#define TYPE_DIRECTIVE(symbol, symboltype) +#endif + diff --git a/objc_msgSend.S b/objc_msgSend.S index 8f3a004..3cdf15f 100644 --- a/objc_msgSend.S +++ b/objc_msgSend.S @@ -1,3 +1,4 @@ +#include "common.S" #if __x86_64 #include "objc_msgSend.x86-64.S" #elif __i386 @@ -9,4 +10,6 @@ #else #warning objc_msgSend() not implemented for your architecture #endif +#if HAS_SECTION_DIRECTIVE .section .note.GNU-stack,"",%progbits +#endif diff --git a/objc_msgSend.arm.S b/objc_msgSend.arm.S index 9ec7f4b..d0cd25d 100644 --- a/objc_msgSend.arm.S +++ b/objc_msgSend.arm.S @@ -77,7 +77,7 @@ .save {\receiver} mov r1, \sel - bl slowMsgLookup(PLT) // This is the only place where the CFI directives have to be accurate... + bl CDECL(slowMsgLookup)(PLT) // This is the only place where the CFI directives have to be accurate... mov ip, r0 // IMP -> ip pop {r5} // restore (modified) self to r5 @@ -87,16 +87,16 @@ .fnend .endm -.globl objc_msgSend_fpret - .type objc_msgSend_fpret, %function -.globl objc_msgSend - .type objc_msgSend, %function -objc_msgSend: -objc_msgSend_fpret: +.globl CDECL(objc_msgSend_fpret) +TYPE_DIRECTIVE(CDECL(objc_msgSend_fpret), %function) +.globl CDECL(objc_msgSend) +TYPE_DIRECTIVE(CDECL(objc_msgSend), %function) +CDECL(objc_msgSend): +CDECL(objc_msgSend_fpret): MSGSEND r0, r1 -.globl objc_msgSend_stret - .type objc_msgSend_stret, %function -objc_msgSend_stret: +.globl CDECL(objc_msgSend_stret) +TYPE_DIRECTIVE(CDECL(objc_msgSend_stret), %function) +CDECL(objc_msgSend_stret): MSGSEND r1, r2 LSmallIntClass: diff --git a/objc_msgSend.mips.S b/objc_msgSend.mips.S index 1aafc12..c33baaa 100644 --- a/objc_msgSend.mips.S +++ b/objc_msgSend.mips.S @@ -127,7 +127,7 @@ lw $zero, ($zero) # MIPS implementations. # Note: A better linker ought to be able to turn this into a single # jump-immediate, so revisit this decision later... - LP $25, %got_disp(slowMsgLookup)($t8) + LP $25, %got_disp(CDECL(slowMsgLookup))($t8) daddiu $sp, $sp, -SAVE_SIZE # We need to preserve all registers that may contain arguments: @@ -193,24 +193,24 @@ lw $zero, ($zero) 6: # smallObject: #if _ABI64 dsll $t4, $t4, 3 # Convert tag to pointer offset - LP $t6, %got_disp(SmallObjectClasses)($t8) # Load small object classes array address + LP $t6, %got_disp(CDECL(SmallObjectClasses))($t8) # Load small object classes array address daddu $t4, $t4, $t6 # Add the base address to the offset b 1b # Return to the normal path LP $t4, ($t4) # Load the class (in delay slot) #else b 1b - LP $t4, %got_disp(SmallIntClass)($t8) + LP $t4, %got_disp(CDECL(SmallIntClass))($t8) #endif .cfi_endproc .endm -.globl objc_msgSend - .type objc_msgSend, @function -.globl objc_msgSend_fpret - .type objc_msgSend_fpret, @function -objc_msgSend_fpret: -objc_msgSend: +.globl CDECL(objc_msgSend) +TYPE_DIRECTIVE(CDECL(objc_msgSend), @function) +.globl CDECL(objc_msgSend_fpret) +TYPE_DIRECTIVE(CDECL(objc_msgSend_fpret), @function) +CDECL(objc_msgSend_fpret): +CDECL(objc_msgSend): MSGSEND $a0, $a1 -.globl objc_msgSend_stret - .type objc_msgSend_stret, @function -objc_msgSend_stret: +.globl CDECL(objc_msgSend_stret) +TYPE_DIRECTIVE(CDECL(objc_msgSend_stret), @function) +CDECL(objc_msgSend_stret): MSGSEND $a1, $a2 diff --git a/objc_msgSend.x86-32.S b/objc_msgSend.x86-32.S index 8e9f8f6..2b5406f 100644 --- a/objc_msgSend.x86-32.S +++ b/objc_msgSend.x86-32.S @@ -87,15 +87,15 @@ jmp 1b .cfi_endproc .endm -.globl objc_msgSend_fpret - .type objc_msgSend_fpret, @function -objc_msgSend_fpret: +.globl CDECL(objc_msgSend_fpret) +TYPE_DIRECTIVE(CDECL(objc_msgSend_fpret), @function) +CDECL(objc_msgSend_fpret): MSGSEND 4, 8, 1 -.globl objc_msgSend - .type objc_msgSend, @function -objc_msgSend: +.globl CDECL(objc_msgSend) +TYPE_DIRECTIVE(CDECL(objc_msgSend), @function) +CDECL(objc_msgSend): MSGSEND 4, 8, 0 -.globl objc_msgSend_stret - .type objc_msgSend_stret, @function -objc_msgSend_stret: +.globl CDECL(objc_msgSend_stret) +TYPE_DIRECTIVE(CDECL(objc_msgSend_stret), @function) +CDECL(objc_msgSend_stret): MSGSEND 8, 12, 0 diff --git a/objc_msgSend.x86-64.S b/objc_msgSend.x86-64.S index f519bf3..4be831b 100644 --- a/objc_msgSend.x86-64.S +++ b/objc_msgSend.x86-64.S @@ -234,7 +234,7 @@ .endif .cfi_adjust_cfa_offset 0xD8 - call slowMsgLookup # Call the slow lookup function + call CDECL(slowMsgLookup) # Call the slow lookup function mov %rax, %r10 # Load the returned IMP pop %rdx @@ -260,20 +260,20 @@ 6: # smallObject: and \receiver, %r10 # Find the small int type shll $3, %r10d - lea SmallObjectClasses(%rip), %r11 + lea CDECL(SmallObjectClasses)(%rip), %r11 add %r11, %r10 mov (%r10), %r10 jmp 1b .cfi_endproc .endm -.globl objc_msgSend - .type objc_msgSend, @function -.globl objc_msgSend_fpret - .type objc_msgSend_fpret, @function -objc_msgSend_fpret: -objc_msgSend: +.globl CDECL(objc_msgSend) +TYPE_DIRECTIVE(CDECL(objc_msgSend), @function) +.globl CDECL(objc_msgSend_fpret) +TYPE_DIRECTIVE(CDECL(objc_msgSend_fpret), @function) +CDECL(objc_msgSend_fpret): +CDECL(objc_msgSend): MSGSEND %rdi, %rsi -.globl objc_msgSend_stret - .type objc_msgSend_stret, @function -objc_msgSend_stret: +.globl CDECL(objc_msgSend_stret) +TYPE_DIRECTIVE(CDECL(objc_msgSend_stret), @function) +CDECL(objc_msgSend_stret): MSGSEND %rsi, %rdx