From aa0778c0d89f9f0722428e419866ff3aedf06bf2 Mon Sep 17 00:00:00 2001 From: Tat-Chee Wan (USM) Date: Wed, 5 Sep 2012 14:12:13 +0800 Subject: updated arm function label declarations to use .type directive for interworking Newer binutils (>2.21) does not handle interworking correctly if the .type directive is not used for ARM functions. The fix is to add a private copy of the arm_interwork macro to the debugger stub to avoid this issue when calling ARM routines from Thumb (used by NIF). --- Debugger/abort_handler.S | 6 ++---- Debugger/debug_comm.S | 15 +++++---------- Debugger/debug_runlooptasks.S | 24 ++++++++++-------------- Debugger/debug_stub.S | 21 +++++++-------------- Debugger/debug_stub.h | 14 ++++++++++++++ Debugger/debug_test.S | 21 +++++++++++---------- Debugger/undef_handler.S | 13 +++++-------- 7 files changed, 54 insertions(+), 60 deletions(-) diff --git a/Debugger/abort_handler.S b/Debugger/abort_handler.S index f4d1bd0..dab25d1 100644 --- a/Debugger/abort_handler.S +++ b/Debugger/abort_handler.S @@ -55,10 +55,8 @@ .extern default_prefetch_abort_handler .extern default_data_abort_handler - .global prefetch_abort_handler - .global data_abort_handler -prefetch_abort_handler: + dbg_interwork prefetch_abort_handler ldr sp, =__debugger_stack__ stmfd sp, {r0-r15}^ /* Save workspace, previous mode's pc via 'S' flag, R13-R15: placeholders */ mov r2, #PREFETCH_OFFSET @@ -66,7 +64,7 @@ prefetch_abort_handler: mov r5, #DBG_ABORT_PREFETCH /* Debugger Abort Type */ b _common_abort_handler -data_abort_handler: + dbg_interwork data_abort_handler ldr sp, =__debugger_stack__ stmfd sp, {r0-r15}^ /* Save workspace, previous mode's pc via 'S' flag, R13-R15: placeholders */ mov r2, #DATA_OFFSET diff --git a/Debugger/debug_comm.S b/Debugger/debug_comm.S index 4c23912..b4590eb 100644 --- a/Debugger/debug_comm.S +++ b/Debugger/debug_comm.S @@ -146,7 +146,6 @@ nxt_commcmd_header: * in the last segment) */ - .global dbg__comm_init /* dbg__comm_init * Initialize communications channel. * On Entry: @@ -154,7 +153,7 @@ nxt_commcmd_header: * R1: MSG Tx Buf Pointer */ -dbg__comm_init: + dbg_interwork dbg__comm_init stmfd sp!, {lr} ldr r2, =debug_msgRxBufPtr stmia r2!, {r0, r1} /* debug_msgRxBufPtr and debug_msgTxBufPtr */ @@ -172,7 +171,6 @@ _dbg__comm_readbuf_reset: str r0, [r1] /* Clear Received Comm Message Length */ bx lr - .global dbg__copyNxtDebugMsg /* dbg__copyNxtDebugMsg * Copy NXT Debug Message to our own Buffers, indicate Msg Received status. * Note: This routine is now used by both NXT Firmware and NxOS @@ -183,7 +181,7 @@ _dbg__comm_readbuf_reset: * On Exit: * R0-R3: Destroyed */ -dbg__copyNxtDebugMsg: + dbg_interwork dbg__copyNxtDebugMsg ldr r3, =debug_nxtMsgLength str r1, [r3, #NXTCOMMCHANNEL_OFFSET] /* save Communications Channel first */ ldr r1, [r3] /* Check if there's an unread message in the buffer */ @@ -307,7 +305,6 @@ _msgbuf_checksum: and r1, #BYTE0 /* Modulo 256 */ mov pc, lr - .global dbg__getDebugMsg /* dbg__getDebugMsg * Retrieve pending Debugger Message if available (Non-Blocking). * On entry: @@ -319,7 +316,7 @@ _msgbuf_checksum: * r2, r3: Destroyed * Note: If GDB Message were returned, it is ASCIIZ terminated, does not include '#' and checksum */ -dbg__getDebugMsg: + dbg_interwork dbg__getDebugMsg stmfd sp!, {r4,r5,lr} bl _dbg__commHasMsg /* r0: message length, r1: segment number */ teq r0, #0 @@ -468,7 +465,6 @@ _exit_copy_msg_to_commbuf: sub r0, r5, r6 /* Return calculated cummulative message length (R0) */ ldmfd sp!, {r1,r4,r5,r6,pc} /* Return segment number in R1 */ - .global dbg__putDebugMsg /* dbg__putDebugMsg * Sends Debugger Message from calling routine after appending checksum (Blocking) . * On entry: @@ -478,7 +474,7 @@ _exit_copy_msg_to_commbuf: * Note: GDB Message to be sent must be ASCIIZ terminated, does not include '#' and checksum * Response packets start with '+' followed by '$' (2 bytes prefix) */ -dbg__putDebugMsg: + dbg_interwork dbg__putDebugMsg stmfd sp!, {r4,r5,lr} /* Perform Checksum Calculation */ ldr r5, =debug_msgTxBufPtr /* R5: data structure base pointer */ @@ -527,7 +523,6 @@ exit_dbg__putMsgError: exit_dbg__putDebugMsg: ldmfd sp!, {r4,r5,pc} - .global dbg__sendAckOrNak /* dbg__sendAckOrNak * Send Ack (for successful receipt of message) * or Nak (for Retransmission due to received message Checksum error) (Blocking) . @@ -539,7 +534,7 @@ exit_dbg__putDebugMsg: * Note: An Ack Or Nak is indicated by '+' or '-', which is prepended with the Comm header and sent (without checksum) * Sending Ack is only done for Continue and Step commands, where GDB does not expect any replies. */ -dbg__sendAckOrNak: + dbg_interwork dbg__sendAckOrNak stmfd sp!, {lr} ldr r1, =debug_msgTxBufPtr /* R2: data structure base pointer */ ldr r0, [r1] /* Tx buffer Start Address */ diff --git a/Debugger/debug_runlooptasks.S b/Debugger/debug_runlooptasks.S index 3bcf35a..a9eb50a 100644 --- a/Debugger/debug_runlooptasks.S +++ b/Debugger/debug_runlooptasks.S @@ -78,10 +78,6 @@ .code 32 .align 4 - .global dbg__runloopTasks - .global dbg__reboot - .global dbg__display_abort_info - .global dbg__sendCommMsg #ifdef __NXOS__ /**************************************************************************** @@ -89,7 +85,7 @@ * NxOS Run Loop * ****************************************************************************/ -dbg__runloopTasks: + dbg_interwork dbg__runloopTasks /* Currently, there's nothing that needs to be done in the NxOS Run Loop */ push {lr} mov r0, #1 /* 1 ms delay */ @@ -102,7 +98,7 @@ dbg__runloopTasks: * NXT Firmware Run Loop * ****************************************************************************/ -dbg__runloopTasks: + dbg_interwork dbg__runloopTasks push {lr} /* FIXME: Add necessary cXXXCtrl calls here */ bl cCommCtrl @@ -116,7 +112,7 @@ dbg__runloopTasks: * NxOS Reboot Routine * ****************************************************************************/ - dbg__reboot: + dbg_interwork dbg__reboot #ifdef REBOOT_POWERDOWN b nx_core_halt /* Shutdown Brick, won't return */ #else @@ -129,7 +125,7 @@ dbg__runloopTasks: * NXT Firmware Reboot Routine * ****************************************************************************/ -dbg__reboot: + dbg_interwork dbg__reboot /* Powerdown Sequence dIOCtrlSetPower((POWERDOWN>>8)); dIOCtrlTransfer(); @@ -180,7 +176,7 @@ _dbg__reboot_wait: * On exit: * r0-r3: destroyed */ -dbg__display_abort_info: + dbg_interwork dbg__display_abort_info push {lr} _getdbgregister DBGSTACK_USERPC_INDEX, r1 /* Retrieve User PC into R2 */ _getdbgregister DBGSTACK_USERCPSR_INDEX, r2 /* Retrieve User CPSR into R2 */ @@ -193,7 +189,7 @@ dbg__display_abort_info: * NXT Firmware Abort Info LCD Display Routine * ****************************************************************************/ -dbg__display_abort_info: + dbg_interwork dbg__display_abort_info /* FIXME: Inteface with NXT Firmware LCD Display routines */ push {lr} pop {pc} @@ -214,7 +210,7 @@ dbg__display_abort_info: * R0: Tx Status (TRUE if data sent) * R1-R3: Destroyed */ -dbg__sendCommMsg: + dbg_interwork dbg__sendCommMsg stmfd sp!, {r4, lr} mov r4, r0 /* Keep Comm Buffer length in R4 */ /* Check USB bus status, transmit message if possible */ @@ -258,7 +254,7 @@ exit_dbg__sendCommMsg: * On exit: R0: Tx Status (TRUE if data sent) */ -dbg__sendCommMsg: + dbg_interwork dbg__sendCommMsg stmfd sp!, {r4, lr} mov r4, r0 /* Keep Comm Buffer length in R4 */ ldr r0, =debug_nxtCommChannel @@ -311,7 +307,6 @@ exit_dbg__sendCommMsg: .extern dbg__install_singlestep .extern dbg__activate_singlestep .extern irq_stack_frame_address - .global nxos__handleDebug /* nxos__handleDebug * Prepare to switch to Debug Mode * int nxos__handleDebug(U8 *buffer, comm_chan_t channel, U32 length); @@ -330,7 +325,7 @@ exit_dbg__sendCommMsg: * If we're operating in normal NxOS mode, return True (!0) * If we're already in Debugger Mode, return False (0) */ -nxos__handleDebug: + dbg_interwork nxos__handleDebug push {lr} /* This routine is called from nx__irq_handler() via fantom_filter_packet(). * The operating mode should already have been configured by the IRQ interrupt handler. @@ -379,6 +374,7 @@ exit_nxos__handleDebug: .extern dbg__copyNxtDebugMsg .global cCommHandleDebug .thumb_func + .type cCommHandleDebug, %function /* cCommHandleDebug * Switch Mode to Debugger. * Used by NXT Firmware only diff --git a/Debugger/debug_stub.S b/Debugger/debug_stub.S index 51bb0c6..a7b2d56 100644 --- a/Debugger/debug_stub.S +++ b/Debugger/debug_stub.S @@ -370,8 +370,7 @@ debug_cmdJumpTable: * On exit: * r0-r3: destroyed */ - .global dbg__bkpt_init -dbg__bkpt_init: + dbg_interwork dbg__bkpt_init push {lr} bl _dbg__clear_breakpoints mov r2, #0 @@ -415,8 +414,7 @@ _dbg__switch2undefmode: * On exit: * routine does not 'exit' in the normal sense */ - .global dbg__abort_exception_handler -dbg__abort_exception_handler: + dbg_interwork dbg__abort_exception_handler _dbg_set_bkpt_type r0 /* Set Breakpoint Type given value in R0 */ b dbg__bkpt_waitCMD @@ -427,8 +425,7 @@ dbg__abort_exception_handler: * On exit: * routine does not 'exit' in the normal sense */ - .global dbg__thumb_bkpt_handler -dbg__thumb_bkpt_handler: + dbg_interwork dbg__thumb_bkpt_handler /* On entry, r0 contains breakpoint index value */ _dbg_setcurrbkpt_index r0 /* keep current breakpoint index in memory */ ldr r1, =BKPT16_MANUAL_BKPT @@ -450,8 +447,7 @@ _process_normal_breakpoint_thumb: * On exit: * routine does not 'exit' in the normal sense */ - .global dbg__arm_bkpt_handler -dbg__arm_bkpt_handler: + dbg_interwork dbg__arm_bkpt_handler /* On entry, r0 contains breakpoint index value */ _dbg_setcurrbkpt_index r0 /* keep current breakpoint index in memory */ ldr r1, =BKPT32_MANUAL_BKPT @@ -479,7 +475,6 @@ dbg__bkpt_inactive: dbg__bkpt_offset_outofrange: /* b dbg__bkpt_waitCMD */ - .global dbg__bkpt_waitCMD /* dbg__bkpt_waitCMD * GDB Stub Remote Command Handler */ @@ -489,7 +484,7 @@ dbg__bkpt_offset_outofrange: * GDB Server Command Processing Routines * ****************************************************************************/ -dbg__bkpt_waitCMD: + dbg_interwork dbg__bkpt_waitCMD /* We enter this code section when a Breakpoint Triggers */ _dbg_setmode TRUE /* Debug Mode = True */ msr cpsr_c, #(MODE_ABT) /* Re-enable Interrupts */ @@ -1395,7 +1390,6 @@ _dbg__clear_breakpoints: blo 3b ldmfd sp!, {pc} - .global dbg__install_singlestep /* dbg__install_singlestep * Install the Single Step Breakpoint * @@ -1407,7 +1401,7 @@ _dbg__clear_breakpoints: * R2: Breakpoint Instruction * R3: Breakpoint Entry address */ -dbg__install_singlestep: + dbg_interwork dbg__install_singlestep mov r0, #0 /* b _dbg__install_one_breakpoint */ @@ -1486,7 +1480,6 @@ _dbg__restore_breakpoints: ldr r6, =_dbg__restore_one_breakpoint b __dbg__iterate_breakpoint_array - .global dbg__activate_singlestep /* dbg__activate_singlestep * Activate the single step breakpoint to memory * @@ -1495,7 +1488,7 @@ _dbg__restore_breakpoints: * On exit: * R0-R3: Destroyed */ -dbg__activate_singlestep: + dbg_interwork dbg__activate_singlestep mov r0, #0 /* single step breakpoint index */ _index2bkptindex_addr r0, r1 /* Calculate Single Step Breakpoint Entry Address */ ldm r1, {r1, r2} /* r1: Breakpoint Address, r2: Breakpoint Instruction */ diff --git a/Debugger/debug_stub.h b/Debugger/debug_stub.h index 6807ac1..2430e77 100644 --- a/Debugger/debug_stub.h +++ b/Debugger/debug_stub.h @@ -145,6 +145,20 @@ static inline void dbg_breakpoint_thumb(void) { asm volatile (".hword 0xBE7F" /* .hword (BKPT16_INSTR | BKPT16_MANUAL_BKPT) .endm +/** Macro to declare Interworking ARM Routine + * + * dbg_interwork + * + * Note: declared as a private macro since ARMDEBUG is also used by NIF + */ + .macro dbg_interwork arm_routine + .align 4 + .arm + .type \arm_routine, %function @ Needed by new binutils (>2.21) + .global \arm_routine +\arm_routine: + .endm + #endif /*@}*/ diff --git a/Debugger/debug_test.S b/Debugger/debug_test.S index 7f8c85f..2cb87a0 100644 --- a/Debugger/debug_test.S +++ b/Debugger/debug_test.S @@ -23,8 +23,7 @@ * dbg__test_arm_bkpt Test Routine * */ - .global dbg__test_arm_bkpt -dbg__test_arm_bkpt: + dbg_interwork dbg__test_arm_bkpt stmfd sp!,{lr} dbg__bkpt_arm /* Trigger ARM Manual Breakpoint */ ldmfd sp!,{pc} @@ -38,8 +37,7 @@ dbg__test_arm_bkpt: * In addition, conditional instructions are also evaluated. * */ - .global dbg__test_arm_instrstep -dbg__test_arm_instrstep: + dbg_interwork dbg__test_arm_instrstep stmfd sp!, {lr} bl dbg__test_arm_instr_sub1 ldr r1, =test_arm_3 /* R1: pointer to test_arm_3 */ @@ -85,8 +83,7 @@ dbg__test_arm_instr_sub2: * dbg__test_thumb_bkpt Test Routine * */ - .global dbg__test_thumb_bkpt -dbg__test_thumb_bkpt: + dbg_interwork dbg__test_thumb_bkpt stmfd sp!,{lr} /* ldr r0, =_thumb_entry orr r0, r0, #1 @ Set Thumb mode @@ -97,7 +94,8 @@ dbg__test_thumb_bkpt: ldmfd sp!,{pc} .code 16 -.thumb_func + .thumb_func + .type _thumb_entry, %function _thumb_entry: dbg__bkpt_thumb bx lr @@ -109,7 +107,8 @@ _thumb_entry: * */ .global dbg__test_thumb_instrstep -.thumb_func + .thumb_func + .type dbg__test_thumb_instrstep, %function dbg__test_thumb_instrstep: push {lr} bl dbg__test_thumb_instr_sub1 @@ -145,12 +144,14 @@ exit_dbg__test_thumb_instrstep: pop {r1} bx r1 -.thumb_func + .thumb_func + .type dbg__test_thumb_instr_sub1, %function dbg__test_thumb_instr_sub1: mov r0, #0x0F bx lr -.thumb_func + .thumb_func + .type dbg__test_thumb_instr_sub2, %function dbg__test_thumb_instr_sub2: push {lr} mov r1, #FALSE diff --git a/Debugger/undef_handler.S b/Debugger/undef_handler.S index 412fd18..cfbaae3 100644 --- a/Debugger/undef_handler.S +++ b/Debugger/undef_handler.S @@ -21,16 +21,14 @@ .extern dbg__arm_bkpt_handler .extern default_undef_handler - .global undef_handler - -undef_handler: /* Remote GDB Debugger relies on BKPT instruction being trapped here * In ARMv4t, it is an Illegal (Undefined) Instruction. * On triggering, lr (R14) contains the previous mode's pc (R15). * Based on example in Hohl, "ARM Assembly Language: Fundamentals and Techniques" * Chapter 11, Example 11.1. */ - /* We assume that the DEBUG stack holds only one stack frame and we will overwrite it. + /** undef_handler + * We assume that the DEBUG stack holds only one stack frame and we will overwrite it. * On entry, LR_undef points to one instruction past the UNDEF instruction. * * For the purpose of Debugging, the stack frame should present the PC (R15) as the address @@ -48,6 +46,7 @@ undef_handler: * R2: Mode * R3: Debug Stack Pointer (for Banked R13-R14 update) */ + dbg_interwork undef_handler ldr sp, =__debugger_stack__ stmfd sp, {r0-r15}^ /* Save workspace, previous mode's pc via 'S' flag, R13-R15: placeholders */ mov r3, sp /* Use R3 to write Banked R13-R14, and actual PC of UNDEF instruction */ @@ -103,10 +102,7 @@ _exit_undef_handler: bic sp, sp, #7 mov pc, r2 /* Invoke Debugger */ - .global resume_execution - -resume_execution: -/* +/** resume_execution * This routine is called by the Debugger prior to returning control to * the executing program. * It updates the SPSR_UNDEF with the Debug Stack value, and @@ -119,6 +115,7 @@ resume_execution: * reexecuted, it should be placed in the Next Instruction Address slot * by ABORT mode before coming here */ + dbg_interwork resume_execution ldr lr, =__debugger_stack_bottom__ /* Use LR(undef) for Debug Stack Access */ add r1, lr, #(DBGSTACK_USERSP_INDEX*4) /* Use R1 for Previous Mode SP (R13) and LR (R14) access */ ldr r0, [lr, #(DBGSTACK_USERCPSR_INDEX*4)]! /* LR updated, Retrieve SPSR into R0 */ -- cgit v1.2.3