📄 dabort.s
字号:
[ HandlerSL = ""
INFO ERROR, \
"'HandlerSL' has not been specified."
]
[ ((HandlerSL:LEFT:1) = VBar) \
:LEOR: ((HandlerSL:RIGHT:1) = VBar)
INFO ERROR, \
"Vertical bar error in 'HandlerSL'"
]
[ (HandlerSL:LEFT:1) <> VBar
HandlerSL SETS VBar:CC:HandlerSL:CC:VBar
]
|
[ HandlerSL <> ""
INFO WARNING, \
"'HandlerSL' will not be used."
]
]
; * The parameter-passing options 'PassSPSR', 'PassInstrAddr',
; 'PassRegDumpAddr' and 'PassXferAddr' all default to {FALSE}.
[ :LNOT::DEF:PassSPSR
GBLL PassSPSR
PassSPSR SETL {FALSE}
]
[ :LNOT::DEF:PassInstrAddr
GBLL PassInstrAddr
PassInstrAddr SETL {FALSE}
]
[ :LNOT::DEF:PassRegDumpAddr
GBLL PassRegDumpAddr
PassRegDumpAddr SETL {FALSE}
]
[ :LNOT::DEF:PassXferAddr
GBLL PassXferAddr
PassXferAddr SETL {FALSE}
]
; * The 'allowed return values' options all default to not allowing
; the return value, but some must be specified, including at least
; one that is legitimate when an error occurs.
[ :LNOT::DEF:ReturnNormal
GBLL ReturnNormal
ReturnNormal SETL {FALSE}
]
[ :LNOT::DEF:ReturnUndef
GBLS ReturnUndef
ReturnUndef SETS ""
]
[ (ReturnUndef <> "") :LAND: ((ReturnUndef:LEFT:2) <> "0x")
[ ((ReturnUndef:LEFT:1) = VBar) \
:LEOR: ((ReturnUndef:RIGHT:1) = VBar)
INFO ERROR, \
"Vertical bar error in 'ReturnUndef'"
]
[ (ReturnUndef:LEFT:1) <> VBar
ReturnUndef SETS VBar:CC:ReturnUndef:CC:VBar
]
]
[ :LNOT::DEF:ReturnToNext
GBLS ReturnToNext
ReturnToNext SETS ""
]
[ ReturnToNext <> ""
[ ((ReturnToNext:LEFT:1) = VBar) \
:LEOR: ((ReturnToNext:RIGHT:1) = VBar)
INFO ERROR, \
"Vertical bar error in 'ReturnToNext'"
]
[ (ReturnToNext:LEFT:1) <> VBar
ReturnToNext SETS VBar:CC:ReturnToNext:CC:VBar
]
]
[ :LNOT::DEF:ReturnAddress
GBLL ReturnAddress
ReturnAddress SETL {FALSE}
]
[ (ReturnUndef = "") :LAND: (:LNOT:ReturnAddress)
INFO ERROR, \
"No legitimate return value for errors."
]
; * 'SuptThumb' defaults to {TRUE}.
[ :LNOT::DEF:SuptThumb
GBLL SuptThumb
SuptThumb SETL {TRUE}
]
; * 'StrictErrors' defaults to {TRUE}.
[ :LNOT::DEF:StrictErrors
GBLL StrictErrors
StrictErrors SETL {TRUE}
]
; * The defined-but-not-implemented options 'SuptBaseEqIndex' and
; 'SuptLoadBaseWB' get their default values, with errors/warnings if
; the as-yet-unsupported option is chosen.
[ :LNOT::DEF:SuptBaseEqIndex
GBLL SuptBaseEqIndex
SuptBaseEqIndex SETL {FALSE}
]
[ SuptBaseEqIndex
INFO ERROR, \
"'SuptBaseEqIndex' option not yet implemented"
]
[ :LNOT::DEF:SuptLoadBaseWB
GBLL SuptLoadBaseWB
SuptLoadBaseWB SETL {FALSE}
]
[ SuptLoadBaseWB
INFO ERROR, \
"'SuptLoadBaseWB' option not yet implemented"
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Definitions that depend on assembly-time options
; ================================================
;
; The following macro does the final stages of the call to the
; OS-specific handler.
MACRO
$label HandlerInternalMacro
ALIGN
$label
[ HandlerCallStd = "APCS_MACRO"
$HandlerName
|
[ HandlerCallStd = "APCS_SWST"
LDR R10, =$HandlerSL
]
IMPORT $HandlerName
BL $HandlerName
]
MEND
; Specific return values allowed from OS-specific handler. These
; definitions are made dependent on the relevant assembly-time option
; in order to catch coding errors.
[ ReturnNormal
DABORT_RETVAL_NORMAL EQU 0x0
]
[ ReturnUndef <> ""
DABORT_RETVAL_UNDEF EQU 0x4
]
[ ReturnToNext <> ""
DABORT_RETVAL_TONEXT EQU 0x10
]
; Error codes.
DABORT_ERROR_BAD_REQUEST EQU -1
DABORT_ERROR_NONE EQU 0
DABORT_ERROR_BASEEQINDEX_PRE EQU 1
DABORT_ERROR_BASEEQINDEX_POST EQU 2
DABORT_ERROR_R15_WB EQU 3
DABORT_ERROR_BASE_R15 EQU 4
DABORT_ERROR_INDEX_R15 EQU 5
DABORT_ERROR_LOAD_WB EQU 6
DABORT_ERROR_LDMSTM_EMPTY EQU 7
DABORT_ERROR_USERBANK_WB EQU 8
DABORT_ERROR_BAD_INSTR EQU 9
; Abort models.
[ BaseRestored
DABORT_MODEL_BASERESTORED EQU 0
]
[ EarlyAbort
DABORT_MODEL_EARLYABORT EQU 1
]
[ BaseUpdated
DABORT_MODEL_BASEUPDATED EQU 3
]
[ AbortModelInit <> ""
DABORT_MODEL_INITIALISATION EQU 0x40000000 ; And higher
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Start of generated code
; =======================
;
; Start by declaring the area.
AREA $AreaName, CODE
; The main entry point
; ====================
$VeneerEntry
EXPORT $VeneerEntry
; First thing the code must do is set up its register dump. This has
; to be done carefully, to ensure that the correct mode's registers
; are stored. We start by reserving the right amount of space and
; dumping the unbanked registers, to give ourselves some space to work
; in. We also get the return link and SPSR into callee-saved registers
; at this point, adjusting the return link to point to the aborting
; instruction in the process.
SUB R13, R13, #15*4
STMIA R13, {R0-R7}
SUB R4, R14, #PCOffset_DAbort
MRS R5, SPSR
; Now do the rest of the registers. This usually involves switching to
; the mode concerned (or strictly speaking, to its 32-bit equivalent),
; dumping the registers and switching back. However, if the mode
; concerned is a user mode, we must instead use a "user bank" STM, to
; avoid getting trapped in user mode.
ADD R0, R13, #8*4 ; Place to dump registers
ANDS R1, R5, #Mode_MainMask
ASSERT (Mode_User:AND:Mode_MainMask) = 0
STMEQIA R0, {R8-R14}^
BEQ RegsDumped
MRS R2, CPSR
BIC R3, R2, #Mode_MainMask
ORR R1, R3, R1
MSR CPSR$all_fields, R1
STMIA R0, {R8-R14}
MSR CPSR$all_fields, R2
RegsDumped
; *** Live register values at this point are:
; R4: Pointer to aborting instruction
; R5: SPSR value
; R13: Stack pointer (pointing to register dump)
;
; Find out what abort model we're using (if relevant) and initialise
; the error code.
[ AbortModelVar <> ""
IMPORT $AbortModelVar
LDR R6, =$AbortModelVar
LDR R8, [R6]
[ AbortModelInit <> ""
CMP R8, #DABORT_MODEL_INITIALISATION
BHS Initialisation_Handler
]
]
MOV R6, #DABORT_ERROR_NONE
; We need to obtain and analyse the aborting instruction in any of the
; following circumstances:
;
; * If "StrictErrors" is set.
;
; * If we're expected to pass the instruction's transfer address as a
; parameter to the OS-specific handler.
;
; * If we're dealing with anything other than the Base Restored Abort
; Model.
[ StrictErrors \
:LOR: PassXferAddr \
:LOR: (:LNOT:BaseRestored) \
:LOR: (AbortModelCount > 1)
[ (:LNOT:StrictErrors) \
:LAND: (:LNOT:PassXferAddr) \
:LAND: BaseRestored
ASSERT AbortModelVar <> "" ; So R8 was loaded
CMP R8, #DABORT_MODEL_BASERESTORED
BEQ CallOSHandlerWithError
]
[ SuptThumb
; Test for whether the instruction is a Thumb instruction, and branch
; off to separate code to handle it if so.
TST R5, #T_bit
BNE ThumbInstruction
]
ARMInstruction
; ARM instruction analysis
; ========================
;
; Get the instruction. We can use a normal LDR instruction to do this,
; not an LDRT, even if we were invoked from user mode, because:
;
; * The fact that a data abort occurred on the offending instruction,
; not a prefetch abort, indicates that the instruction was
; accessible from user mode.
;
; * User mode programs cannot fake a data abort vector entry in order
; to create a security loophole. (They can branch to location 0x10,
; but cannot also get into a privileged mode unless they take the
; data abort trap.)
LDR R0, [R4]
; *** Live register values at this point are:
; R0: Aborting instruction
; R4: Pointer to aborting instruction
; R5: SPSR value
; R6: Error code
; R8: Abort model (if relevant)
; R13: Stack pointer (pointing to register dump)
;
; Now start analysing the instruction. The objective of this stage is
; to end up with:
;
; R0: M bit (bit 27) indicating multiple vs. single transfer.
; P bit (bit 24) indicating pre- vs. post-indexing.
; U bit (bit 23) indicating whether indexing is up or down.
; W bit (bit 21) indicating whether base register writeback
; is required.
; L bit (bit 20) indicating whether a load or a store, at least
; when writeback is involved or there is a potential "user bank"
; LDM.
; R1: Number of base register, still in instruction position.
; R2: Offset value.
; R3: Number of destination register, still in instruction
; position (for all but LDM/STM/LDC/STC).
;
; In many cases, R0 will be the unchanged instruction; however, it
; does get changed in some circumstances to "standardise" the meanings
; of the bits.
;
; R1 and R3 are particularly simple, since the base register field is
; in the same position for all ARM load/store instructions, and the
; destination field is in the same position for all single load
; instructions.
AND R1, R0, #ARM_Rn_mask
AND R3, R0, #ARM_Rd_mask
; Now split according to the major class of the instruction - i.e.
; bits 27:25.
AND R2, R0, #(0x7:SHL:25)
ADD PC, PC, R2, LSR #23
NOP ;Branch table padding
B ARM_Odds_And_Ends ;SWP, LDRH, etc.
B ARM_Should_Not_Happen ;(Data processing)
B ARM_LDR_STR_Immed
B ARM_LDR_STR_Reg
B ARM_LDM_STM
B ARM_Should_Not_Happen ;(B/BL)
B ARM_LDC_STC
ARM_Should_Not_Happen ;(CDP/MRC/MCR/SWI)
MOV R6, #DABORT_ERROR_BAD_INSTR
B CallOSHandlerWithError
; Analysis of ARM SWP/SWPB/LDRH/LDRSB/LDRSH/STRH instructions
; -----------------------------------------------------------
;
; Start by distinguishing SWP instructions from the rest.
ARM_Odds_And_Ends
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -