• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Default exception handler
3 
4   Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
5 
6   This program and the accompanying materials
7   are licensed and made available under the terms and conditions of the BSD License
8   which accompanies this distribution.  The full text of the license may be found at
9   http://opensource.org/licenses/bsd-license.php
10 
11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 #include <Base.h>
17 #include <Library/BaseLib.h>
18 #include <Library/PrintLib.h>
19 #include <Library/ArmDisassemblerLib.h>
20 
21 CHAR8 *gCondition[] = {
22   "EQ",
23   "NE",
24   "CS",
25   "CC",
26   "MI",
27   "PL",
28   "VS",
29   "VC",
30   "HI",
31   "LS",
32   "GE",
33   "LT",
34   "GT",
35   "LE",
36   "",
37   "2"
38 };
39 
40 #define COND(_a)  gCondition[((_a) >> 28)]
41 
42 CHAR8 *gReg[] = {
43   "r0",
44   "r1",
45   "r2",
46   "r3",
47   "r4",
48   "r5",
49   "r6",
50   "r7",
51   "r8",
52   "r9",
53   "r10",
54   "r11",
55   "r12",
56   "sp",
57   "lr",
58   "pc"
59 };
60 
61 CHAR8 *gLdmAdr[] = {
62   "DA",
63   "IA",
64   "DB",
65   "IB"
66 };
67 
68 CHAR8 *gLdmStack[] = {
69   "FA",
70   "FD",
71   "EA",
72   "ED"
73 };
74 
75 #define LDM_EXT(_reg, _off) ((_reg == 13) ? gLdmStack[(_off)] : gLdmAdr[(_off)])
76 
77 
78 #define SIGN(_U)  ((_U) ? "" : "-")
79 #define WRITE(_W) ((_W) ? "!" : "")
80 #define BYTE(_B)  ((_B) ? "B":"")
81 #define USER(_B)  ((_B) ? "^" : "")
82 
83 CHAR8 mMregListStr[4*15 + 1];
84 
85 CHAR8 *
MRegList(UINT32 OpCode)86 MRegList (
87   UINT32  OpCode
88   )
89 {
90   UINTN     Index, Start, End;
91   BOOLEAN   First;
92 
93   mMregListStr[0] = '\0';
94   AsciiStrCatS (mMregListStr, sizeof mMregListStr, "{");
95   for (Index = 0, First = TRUE; Index <= 15; Index++) {
96     if ((OpCode & (1 << Index)) != 0) {
97       Start = End = Index;
98       for (Index++; ((OpCode & (1 << Index)) != 0) && Index <= 15; Index++) {
99         End = Index;
100       }
101 
102       if (!First) {
103         AsciiStrCatS (mMregListStr, sizeof mMregListStr, ",");
104       } else {
105         First = FALSE;
106       }
107 
108       if (Start == End) {
109         AsciiStrCatS (mMregListStr, sizeof mMregListStr, gReg[Start]);
110         AsciiStrCatS (mMregListStr, sizeof mMregListStr, ", ");
111       } else {
112         AsciiStrCatS (mMregListStr, sizeof mMregListStr, gReg[Start]);
113         AsciiStrCatS (mMregListStr, sizeof mMregListStr, "-");
114         AsciiStrCatS (mMregListStr, sizeof mMregListStr, gReg[End]);
115       }
116     }
117   }
118   if (First) {
119     AsciiStrCatS (mMregListStr, sizeof mMregListStr, "ERROR");
120   }
121   AsciiStrCatS (mMregListStr, sizeof mMregListStr, "}");
122 
123   // BugBug: Make caller pass in buffer it is cleaner
124   return mMregListStr;
125 }
126 
127 CHAR8 *
FieldMask(IN UINT32 Mask)128 FieldMask (
129   IN  UINT32  Mask
130   )
131 {
132   return "";
133 }
134 
135 UINT32
RotateRight(IN UINT32 Op,IN UINT32 Shift)136 RotateRight (
137   IN UINT32 Op,
138   IN UINT32 Shift
139   )
140 {
141   return (Op >> Shift) | (Op << (32 - Shift));
142 }
143 
144 
145 /**
146   Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to
147   point to next instructin.
148 
149   We cheat and only decode instructions that access
150   memory. If the instruction is not found we dump the instruction in hex.
151 
152   @param  OpCodePtr   Pointer to pointer of ARM instruction to disassemble.
153   @param  Buf         Buffer to sprintf disassembly into.
154   @param  Size        Size of Buf in bytes.
155   @param  Extended    TRUE dump hex for instruction too.
156 
157 **/
158 VOID
DisassembleArmInstruction(IN UINT32 ** OpCodePtr,OUT CHAR8 * Buf,OUT UINTN Size,IN BOOLEAN Extended)159 DisassembleArmInstruction (
160   IN  UINT32    **OpCodePtr,
161   OUT CHAR8     *Buf,
162   OUT UINTN     Size,
163   IN  BOOLEAN   Extended
164   )
165 {
166   UINT32    OpCode = **OpCodePtr;
167   CHAR8     *Type, *Root;
168   BOOLEAN   I, P, U, B, W, L, S, H;
169   UINT32    Rn, Rd, Rm;
170   UINT32    imode, offset_8, offset_12;
171   UINT32    Index;
172   UINT32    shift_imm, shift;
173 
174   I = (OpCode & BIT25) == BIT25;
175   P = (OpCode & BIT24) == BIT24;
176   U = (OpCode & BIT23) == BIT23;
177   B = (OpCode & BIT22) == BIT22;  // Also called S
178   W = (OpCode & BIT21) == BIT21;
179   L = (OpCode & BIT20) == BIT20;
180   S = (OpCode & BIT6) == BIT6;
181   H = (OpCode & BIT5) == BIT5;
182   Rn = (OpCode >> 16) & 0xf;
183   Rd = (OpCode >> 12) & 0xf;
184   Rm = (OpCode & 0xf);
185 
186 
187   if (Extended) {
188     Index = AsciiSPrint (Buf, Size, "0x%08x   ", OpCode);
189     Buf += Index;
190     Size -= Index;
191   }
192 
193   // LDREX, STREX
194   if ((OpCode  & 0x0fe000f0) == 0x01800090) {
195     if (L) {
196       // A4.1.27  LDREX{<cond>} <Rd>, [<Rn>]
197       AsciiSPrint (Buf, Size, "LDREX%a %a, [%a]", COND (OpCode), gReg[Rd], gReg[Rn]);
198     } else {
199      // A4.1.103  STREX{<cond>} <Rd>, <Rm>, [<Rn>]
200       AsciiSPrint (Buf, Size, "STREX%a %a, %a, [%a]", COND (OpCode), gReg[Rd], gReg[Rn], gReg[Rn]);
201     }
202     return;
203   }
204 
205   // LDM/STM
206   if ((OpCode  & 0x0e000000) == 0x08000000) {
207     if (L) {
208       // A4.1.20 LDM{<cond>}<addressing_mode> <Rn>{!}, <registers>
209       // A4.1.21 LDM{<cond>}<addressing_mode> <Rn>, <registers_without_pc>^
210       // A4.1.22 LDM{<cond>}<addressing_mode> <Rn>{!}, <registers_and_pc>^
211       AsciiSPrint (Buf, Size, "LDM%a%a, %a%a, %a", COND (OpCode), LDM_EXT (Rn ,(OpCode >> 23) & 3), gReg[Rn], WRITE (W), MRegList (OpCode), USER (B));
212     } else {
213       // A4.1.97 STM{<cond>}<addressing_mode> <Rn>{!}, <registers>
214       // A4.1.98 STM{<cond>}<addressing_mode> <Rn>, <registers>^
215       AsciiSPrint (Buf, Size, "STM%a%a, %a%a, %a", COND (OpCode), LDM_EXT (Rn ,(OpCode >> 23) & 3), gReg[Rn], WRITE (W), MRegList (OpCode), USER (B));
216     }
217     return;
218   }
219 
220   // LDR/STR Address Mode 2
221   if ( ((OpCode  & 0x0c000000) == 0x04000000) || ((OpCode & 0xfd70f000 ) == 0xf550f000) ) {
222     offset_12 = OpCode & 0xfff;
223     if ((OpCode & 0xfd70f000 ) == 0xf550f000) {
224       Index = AsciiSPrint (Buf, Size, "PLD");
225     } else {
226       Index = AsciiSPrint (Buf, Size, "%a%a%a%a %a, ", L ? "LDR" : "STR", COND (OpCode), BYTE (B), (!(P) && W) ? "T":"", gReg[Rd]);
227     }
228     if (P) {
229       if (!I) {
230         // A5.2.2 [<Rn>, #+/-<offset_12>]
231         // A5.2.5 [<Rn>, #+/-<offset_12>]
232         AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a0x%x]%a", gReg[Rn], SIGN (U), offset_12, WRITE (W));
233       } else if ((OpCode & 0x03000ff0) == 0x03000000) {
234         // A5.2.3 [<Rn>, +/-<Rm>]
235         // A5.2.6 [<Rn>, +/-<Rm>]!
236         AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a%a]%a", gReg[Rn], SIGN (U), WRITE (W));
237       } else {
238         // A5.2.4 [<Rn>, +/-<Rm>, LSL #<shift_imm>]
239         // A5.2.7 [<Rn>, +/-<Rm>, LSL #<shift_imm>]!
240         shift_imm = (OpCode >> 7) & 0x1f;
241         shift = (OpCode >> 5) & 0x3;
242         if (shift == 0x0) {
243           Type = "LSL";
244         } else if (shift == 0x1) {
245           Type = "LSR";
246           if (shift_imm == 0) {
247             shift_imm = 32;
248           }
249         } else if (shift == 0x12) {
250           Type = "ASR";
251         } else if (shift_imm == 0) {
252           AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a%a, %a, RRX]%a", gReg[Rn], SIGN (U), gReg[Rm], WRITE (W));
253           return;
254         } else {
255           Type = "ROR";
256         }
257 
258         AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a%a, %a, #%d]%a", gReg[Rn], SIGN (U), gReg[Rm], Type, shift_imm, WRITE (W));
259       }
260     } else {  // !P
261       if (!I) {
262         // A5.2.8  [<Rn>], #+/-<offset_12>
263         AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a0x%x", gReg[Rn], SIGN (U), offset_12);
264       } else if ((OpCode & 0x03000ff0) == 0x03000000) {
265         // A5.2.9  [<Rn>], +/-<Rm>
266         AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%a", gReg[Rn], SIGN (U), gReg[Rm]);
267       } else {
268         // A5.2.10 [<Rn>], +/-<Rm>, LSL #<shift_imm>
269         shift_imm = (OpCode >> 7) & 0x1f;
270         shift = (OpCode >> 5) & 0x3;
271 
272         if (shift == 0x0) {
273           Type = "LSL";
274         } else if (shift == 0x1) {
275           Type = "LSR";
276           if (shift_imm == 0) {
277             shift_imm = 32;
278           }
279         } else if (shift == 0x12) {
280           Type = "ASR";
281         } else if (shift_imm == 0) {
282           AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%a, %a, RRX", gReg[Rn], SIGN (U), gReg[Rm]);
283           // FIx me
284           return;
285         } else {
286           Type = "ROR";
287         }
288 
289         AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%a, %a, #%d", gReg[Rn], SIGN (U), gReg[Rm], Type, shift_imm);
290       }
291     }
292     return;
293   }
294 
295   if ((OpCode  & 0x0e000000) == 0x00000000) {
296     // LDR/STR address mode 3
297     // LDR|STR{<cond>}H|SH|SB|D <Rd>, <addressing_mode>
298     if (L) {
299       if (!S) {
300         Root = "LDR%aH %a, ";
301       } else if (!H) {
302         Root = "LDR%aSB %a, ";
303       } else {
304         Root = "LDR%aSH %a, ";
305       }
306     } else {
307       if (!S) {
308         Root = "STR%aH %a ";
309       } else if (!H) {
310         Root = "LDR%aD %a ";
311       } else {
312         Root = "STR%aD %a ";
313       }
314     }
315 
316     Index = AsciiSPrint (Buf, Size, Root, COND (OpCode), gReg[Rd]);
317 
318     S = (OpCode & BIT6) == BIT6;
319     H = (OpCode & BIT5) == BIT5;
320     offset_8 = ((OpCode >> 4) | (OpCode * 0xf)) & 0xff;
321     if (P & !W) {
322       // Immediate offset/index
323       if (B) {
324         // A5.3.2  [<Rn>, #+/-<offset_8>]
325         // A5.3.4  [<Rn>, #+/-<offset_8>]!
326         AsciiSPrint  (&Buf[Index], Size - Index, "[%a, #%a%d]%a", gReg[Rn], SIGN (U), offset_8, WRITE (W));
327       } else {
328         // A5.3.3  [<Rn>, +/-<Rm>]
329         // A5.3.5  [<Rn>, +/-<Rm>]!
330         AsciiSPrint  (&Buf[Index], Size - Index, "[%a, #%a%]a", gReg[Rn], SIGN (U), gReg[Rm], WRITE (W));
331       }
332     } else {
333       // Register offset/index
334       if (B) {
335         // A5.3.6 [<Rn>], #+/-<offset_8>
336         AsciiSPrint  (&Buf[Index], Size - Index, "[%a], #%a%d", gReg[Rn], SIGN (U), offset_8);
337       } else {
338         // A5.3.7 [<Rn>], +/-<Rm>
339         AsciiSPrint  (&Buf[Index], Size - Index, "[%a], #%a%a", gReg[Rn], SIGN (U), gReg[Rm]);
340       }
341     }
342     return;
343   }
344 
345   if ((OpCode  & 0x0fb000f0) == 0x01000050) {
346     // A4.1.108  SWP   SWP{<cond>}B <Rd>, <Rm>, [<Rn>]
347     // A4.1.109  SWPB  SWP{<cond>}B <Rd>, <Rm>, [<Rn>]
348     AsciiSPrint (Buf, Size, "SWP%a%a %a, %a, [%a]", COND (OpCode), BYTE (B), gReg[Rd], gReg[Rm], gReg[Rn]);
349     return;
350   }
351 
352   if ((OpCode  & 0xfe5f0f00) == 0xf84d0500) {
353     // A4.1.90 SRS SRS<addressing_mode> #<mode>{!}
354     AsciiSPrint (Buf, Size, "SRS%a #0x%x%a", gLdmStack[(OpCode >> 23) & 3], OpCode & 0x1f, WRITE (W));
355     return;
356   }
357 
358   if ((OpCode  & 0xfe500f00) == 0xf8100500) {
359     // A4.1.59 RFE<addressing_mode> <Rn>{!}
360     AsciiSPrint (Buf, Size, "RFE%a %a", gLdmStack[(OpCode >> 23) & 3], gReg[Rn], WRITE (W));
361     return;
362   }
363 
364   if ((OpCode  & 0xfff000f0) == 0xe1200070) {
365     // A4.1.7 BKPT <immed_16>
366     AsciiSPrint (Buf, Size, "BKPT %x", ((OpCode >> 8) | (OpCode & 0xf)) & 0xffff);
367     return;
368   }
369 
370   if ((OpCode  & 0xfff10020) == 0xf1000000) {
371     // A4.1.16 CPS<effect> <iflags> {, #<mode>}
372     if (((OpCode >> 6) & 0x7) == 0) {
373       AsciiSPrint (Buf, Size, "CPS #0x%x", (OpCode & 0x2f));
374     } else {
375       imode = (OpCode >> 18) & 0x3;
376       Index = AsciiSPrint (Buf, Size, "CPS%a %a%a%a", (imode == 3) ? "ID":"IE", (OpCode & BIT8) ? "A":"", (OpCode & BIT7) ? "I":"", (OpCode & BIT6) ? "F":"");
377       if ((OpCode & BIT17) != 0) {
378         AsciiSPrint (&Buf[Index], Size - Index, ", #0x%x", OpCode & 0x1f);
379       }
380     }
381     return;
382   }
383 
384   if ((OpCode  & 0x0f000000) == 0x0f000000) {
385     // A4.1.107 SWI{<cond>} <immed_24>
386     AsciiSPrint (Buf, Size, "SWI%a %x", COND (OpCode), OpCode & 0x00ffffff);
387     return;
388   }
389 
390   if ((OpCode  & 0x0fb00000) == 0x01000000) {
391     // A4.1.38 MRS{<cond>} <Rd>, CPSR  MRS{<cond>} <Rd>, SPSR
392     AsciiSPrint (Buf, Size, "MRS%a %a, %a", COND (OpCode), gReg[Rd], B ? "SPSR" : "CPSR");
393     return;
394   }
395 
396 
397   if ((OpCode  & 0x0db00000) == 0x03200000) {
398     // A4.1.38 MSR{<cond>} CPSR_<fields>, #<immediate> MSR{<cond>} CPSR_<fields>, <Rm>
399     if (I) {
400       // MSR{<cond>} CPSR_<fields>, #<immediate>
401       AsciiSPrint (Buf, Size, "MRS%a %a_%a, #0x%x", COND (OpCode),  B ? "SPSR" : "CPSR", FieldMask ((OpCode >> 16) & 0xf), RotateRight (OpCode & 0xf, ((OpCode >> 8) & 0xf) *2));
402     } else {
403       // MSR{<cond>} CPSR_<fields>, <Rm>
404       AsciiSPrint (Buf, Size, "MRS%a %a_%a, %a", COND (OpCode), B ? "SPSR" : "CPSR", gReg[Rd]);
405     }
406     return;
407   }
408 
409   if ((OpCode  & 0xff000010) == 0xfe000000) {
410     // A4.1.13 CDP{<cond>} <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
411     AsciiSPrint (Buf, Size, "CDP%a 0x%x, 0x%x, CR%d, CR%d, CR%d, 0x%x", COND (OpCode), (OpCode >> 8) & 0xf, (OpCode >> 20) & 0xf, Rn, Rd, Rm, (OpCode >> 5) &0x7);
412     return;
413   }
414 
415   if ((OpCode  & 0x0e000000) == 0x0c000000) {
416     // A4.1.19 LDC and A4.1.96 SDC
417     if ((OpCode & 0xf0000000) == 0xf0000000) {
418       Index = AsciiSPrint (Buf, Size, "%a2 0x%x, CR%d, ", L ? "LDC":"SDC", (OpCode >> 8) & 0xf, Rd);
419     } else {
420       Index = AsciiSPrint (Buf, Size, "%a%a 0x%x, CR%d, ",  L ? "LDC":"SDC", COND (OpCode), (OpCode >> 8) & 0xf, Rd);
421     }
422 
423     if (!P) {
424       if (!W) {
425         // A5.5.5.5 [<Rn>], <option>
426       AsciiSPrint (&Buf[Index], Size - Index, "[%a], {0x%x}", gReg[Rn], OpCode & 0xff);
427       } else {
428         // A.5.5.4  [<Rn>], #+/-<offset_8>*4
429       AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a0x%x*4", gReg[Rn], SIGN (U), OpCode & 0xff);
430       }
431     } else {
432       // A5.5.5.2 [<Rn>, #+/-<offset_8>*4 ]!
433       AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a0x%x*4]%a", gReg[Rn], SIGN (U), OpCode & 0xff, WRITE (W));
434     }
435 
436   }
437 
438   if ((OpCode  & 0x0f000010) == 0x0e000010) {
439     // A4.1.32 MRC2, MCR2
440     AsciiSPrint (Buf, Size, "%a%a 0x%x, 0x%x, %a, CR%d, CR%d, 0x%x", L ? "MRC":"MCR", COND (OpCode), (OpCode >> 8) & 0xf, (OpCode >> 20) & 0xf, gReg[Rd], Rn, Rm, (OpCode >> 5) &0x7);
441     return;
442   }
443 
444   if ((OpCode  & 0x0ff00000) == 0x0c400000) {
445     // A4.1.33 MRRC2, MCRR2
446     AsciiSPrint (Buf, Size, "%a%a 0x%x, 0x%x, %a, %a, CR%d", L ? "MRRC":"MCRR", COND (OpCode), (OpCode >> 4) & 0xf, (OpCode >> 20) & 0xf, gReg[Rd], gReg[Rn], Rm);
447     return;
448   }
449 
450   AsciiSPrint (Buf, Size, "Faulting OpCode 0x%08x", OpCode);
451 
452   *OpCodePtr += 1;
453   return;
454 }
455 
456