• 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   CHAR8     *Str;
92   BOOLEAN   First;
93 
94   Str = mMregListStr;
95   *Str = '\0';
96   AsciiStrCat  (Str, "{");
97   for (Index = 0, First = TRUE; Index <= 15; Index++) {
98     if ((OpCode & (1 << Index)) != 0) {
99       Start = End = Index;
100       for (Index++; ((OpCode & (1 << Index)) != 0) && Index <= 15; Index++) {
101         End = Index;
102       }
103 
104       if (!First) {
105         AsciiStrCat  (Str, ",");
106       } else {
107         First = FALSE;
108       }
109 
110       if (Start == End) {
111         AsciiStrCat  (Str, gReg[Start]);
112         AsciiStrCat  (Str, ", ");
113       } else {
114         AsciiStrCat  (Str, gReg[Start]);
115         AsciiStrCat  (Str, "-");
116         AsciiStrCat  (Str, gReg[End]);
117       }
118     }
119   }
120   if (First) {
121     AsciiStrCat  (Str, "ERROR");
122   }
123   AsciiStrCat  (Str, "}");
124 
125   // BugBug: Make caller pass in buffer it is cleaner
126   return mMregListStr;
127 }
128 
129 CHAR8 *
FieldMask(IN UINT32 Mask)130 FieldMask (
131   IN  UINT32  Mask
132   )
133 {
134   return "";
135 }
136 
137 UINT32
RotateRight(IN UINT32 Op,IN UINT32 Shift)138 RotateRight (
139   IN UINT32 Op,
140   IN UINT32 Shift
141   )
142 {
143   return (Op >> Shift) | (Op << (32 - Shift));
144 }
145 
146 
147 /**
148   Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to
149   point to next instructin.
150 
151   We cheat and only decode instructions that access
152   memory. If the instruction is not found we dump the instruction in hex.
153 
154   @param  OpCodePtr   Pointer to pointer of ARM instruction to disassemble.
155   @param  Buf         Buffer to sprintf disassembly into.
156   @param  Size        Size of Buf in bytes.
157   @param  Extended    TRUE dump hex for instruction too.
158 
159 **/
160 VOID
DisassembleArmInstruction(IN UINT32 ** OpCodePtr,OUT CHAR8 * Buf,OUT UINTN Size,IN BOOLEAN Extended)161 DisassembleArmInstruction (
162   IN  UINT32    **OpCodePtr,
163   OUT CHAR8     *Buf,
164   OUT UINTN     Size,
165   IN  BOOLEAN   Extended
166   )
167 {
168   UINT32    OpCode = **OpCodePtr;
169   CHAR8     *Type, *Root;
170   BOOLEAN   I, P, U, B, W, L, S, H;
171   UINT32    Rn, Rd, Rm;
172   UINT32    imode, offset_8, offset_12;
173   UINT32    Index;
174   UINT32    shift_imm, shift;
175 
176   I = (OpCode & BIT25) == BIT25;
177   P = (OpCode & BIT24) == BIT24;
178   U = (OpCode & BIT23) == BIT23;
179   B = (OpCode & BIT22) == BIT22;  // Also called S
180   W = (OpCode & BIT21) == BIT21;
181   L = (OpCode & BIT20) == BIT20;
182   S = (OpCode & BIT6) == BIT6;
183   H = (OpCode & BIT5) == BIT5;
184   Rn = (OpCode >> 16) & 0xf;
185   Rd = (OpCode >> 12) & 0xf;
186   Rm = (OpCode & 0xf);
187 
188 
189   if (Extended) {
190     Index = AsciiSPrint (Buf, Size, "0x%08x   ", OpCode);
191     Buf += Index;
192     Size -= Index;
193   }
194 
195   // LDREX, STREX
196   if ((OpCode  & 0x0fe000f0) == 0x01800090) {
197     if (L) {
198       // A4.1.27  LDREX{<cond>} <Rd>, [<Rn>]
199       AsciiSPrint (Buf, Size, "LDREX%a %a, [%a]", COND (OpCode), gReg[Rd], gReg[Rn]);
200     } else {
201      // A4.1.103  STREX{<cond>} <Rd>, <Rm>, [<Rn>]
202       AsciiSPrint (Buf, Size, "STREX%a %a, %a, [%a]", COND (OpCode), gReg[Rd], gReg[Rn], gReg[Rn]);
203     }
204     return;
205   }
206 
207   // LDM/STM
208   if ((OpCode  & 0x0e000000) == 0x08000000) {
209     if (L) {
210       // A4.1.20 LDM{<cond>}<addressing_mode> <Rn>{!}, <registers>
211       // A4.1.21 LDM{<cond>}<addressing_mode> <Rn>, <registers_without_pc>^
212       // A4.1.22 LDM{<cond>}<addressing_mode> <Rn>{!}, <registers_and_pc>^
213       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));
214     } else {
215       // A4.1.97 STM{<cond>}<addressing_mode> <Rn>{!}, <registers>
216       // A4.1.98 STM{<cond>}<addressing_mode> <Rn>, <registers>^
217       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));
218     }
219     return;
220   }
221 
222   // LDR/STR Address Mode 2
223   if ( ((OpCode  & 0x0c000000) == 0x04000000) || ((OpCode & 0xfd70f000 ) == 0xf550f000) ) {
224     offset_12 = OpCode & 0xfff;
225     if ((OpCode & 0xfd70f000 ) == 0xf550f000) {
226       Index = AsciiSPrint (Buf, Size, "PLD");
227     } else {
228       Index = AsciiSPrint (Buf, Size, "%a%a%a%a %a, ", L ? "LDR" : "STR", COND (OpCode), BYTE (B), (!(P) && W) ? "T":"", gReg[Rd]);
229     }
230     if (P) {
231       if (!I) {
232         // A5.2.2 [<Rn>, #+/-<offset_12>]
233         // A5.2.5 [<Rn>, #+/-<offset_12>]
234         AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a0x%x]%a", gReg[Rn], SIGN (U), offset_12, WRITE (W));
235       } else if ((OpCode & 0x03000ff0) == 0x03000000) {
236         // A5.2.3 [<Rn>, +/-<Rm>]
237         // A5.2.6 [<Rn>, +/-<Rm>]!
238         AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a%a]%a", gReg[Rn], SIGN (U), WRITE (W));
239       } else {
240         // A5.2.4 [<Rn>, +/-<Rm>, LSL #<shift_imm>]
241         // A5.2.7 [<Rn>, +/-<Rm>, LSL #<shift_imm>]!
242         shift_imm = (OpCode >> 7) & 0x1f;
243         shift = (OpCode >> 5) & 0x3;
244         if (shift == 0x0) {
245           Type = "LSL";
246         } else if (shift == 0x1) {
247           Type = "LSR";
248           if (shift_imm == 0) {
249             shift_imm = 32;
250           }
251         } else if (shift == 0x12) {
252           Type = "ASR";
253         } else if (shift_imm == 0) {
254           AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a%a, %a, RRX]%a", gReg[Rn], SIGN (U), gReg[Rm], WRITE (W));
255           return;
256         } else {
257           Type = "ROR";
258         }
259 
260         AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a%a, %a, #%d]%a", gReg[Rn], SIGN (U), gReg[Rm], Type, shift_imm, WRITE (W));
261       }
262     } else {  // !P
263       if (!I) {
264         // A5.2.8  [<Rn>], #+/-<offset_12>
265         AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a0x%x", gReg[Rn], SIGN (U), offset_12);
266       } else if ((OpCode & 0x03000ff0) == 0x03000000) {
267         // A5.2.9  [<Rn>], +/-<Rm>
268         AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%a", gReg[Rn], SIGN (U), gReg[Rm]);
269       } else {
270         // A5.2.10 [<Rn>], +/-<Rm>, LSL #<shift_imm>
271         shift_imm = (OpCode >> 7) & 0x1f;
272         shift = (OpCode >> 5) & 0x3;
273 
274         if (shift == 0x0) {
275           Type = "LSL";
276         } else if (shift == 0x1) {
277           Type = "LSR";
278           if (shift_imm == 0) {
279             shift_imm = 32;
280           }
281         } else if (shift == 0x12) {
282           Type = "ASR";
283         } else if (shift_imm == 0) {
284           AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%a, %a, RRX", gReg[Rn], SIGN (U), gReg[Rm]);
285           // FIx me
286           return;
287         } else {
288           Type = "ROR";
289         }
290 
291         AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%a, %a, #%d", gReg[Rn], SIGN (U), gReg[Rm], Type, shift_imm);
292       }
293     }
294     return;
295   }
296 
297   if ((OpCode  & 0x0e000000) == 0x00000000) {
298     // LDR/STR address mode 3
299     // LDR|STR{<cond>}H|SH|SB|D <Rd>, <addressing_mode>
300     if (L) {
301       if (!S) {
302         Root = "LDR%aH %a, ";
303       } else if (!H) {
304         Root = "LDR%aSB %a, ";
305       } else {
306         Root = "LDR%aSH %a, ";
307       }
308     } else {
309       if (!S) {
310         Root = "STR%aH %a ";
311       } else if (!H) {
312         Root = "LDR%aD %a ";
313       } else {
314         Root = "STR%aD %a ";
315       }
316     }
317 
318     Index = AsciiSPrint (Buf, Size, Root, COND (OpCode), gReg[Rd]);
319 
320     S = (OpCode & BIT6) == BIT6;
321     H = (OpCode & BIT5) == BIT5;
322     offset_8 = ((OpCode >> 4) | (OpCode * 0xf)) & 0xff;
323     if (P & !W) {
324       // Immediate offset/index
325       if (B) {
326         // A5.3.2  [<Rn>, #+/-<offset_8>]
327         // A5.3.4  [<Rn>, #+/-<offset_8>]!
328         AsciiSPrint  (&Buf[Index], Size - Index, "[%a, #%a%d]%a", gReg[Rn], SIGN (U), offset_8, WRITE (W));
329       } else {
330         // A5.3.3  [<Rn>, +/-<Rm>]
331         // A5.3.5  [<Rn>, +/-<Rm>]!
332         AsciiSPrint  (&Buf[Index], Size - Index, "[%a, #%a%]a", gReg[Rn], SIGN (U), gReg[Rm], WRITE (W));
333       }
334     } else {
335       // Register offset/index
336       if (B) {
337         // A5.3.6 [<Rn>], #+/-<offset_8>
338         AsciiSPrint  (&Buf[Index], Size - Index, "[%a], #%a%d", gReg[Rn], SIGN (U), offset_8);
339       } else {
340         // A5.3.7 [<Rn>], +/-<Rm>
341         AsciiSPrint  (&Buf[Index], Size - Index, "[%a], #%a%a", gReg[Rn], SIGN (U), gReg[Rm]);
342       }
343     }
344     return;
345   }
346 
347   if ((OpCode  & 0x0fb000f0) == 0x01000050) {
348     // A4.1.108  SWP   SWP{<cond>}B <Rd>, <Rm>, [<Rn>]
349     // A4.1.109  SWPB  SWP{<cond>}B <Rd>, <Rm>, [<Rn>]
350     AsciiSPrint (Buf, Size, "SWP%a%a %a, %a, [%a]", COND (OpCode), BYTE (B), gReg[Rd], gReg[Rm], gReg[Rn]);
351     return;
352   }
353 
354   if ((OpCode  & 0xfe5f0f00) == 0xf84d0500) {
355     // A4.1.90 SRS SRS<addressing_mode> #<mode>{!}
356     AsciiSPrint (Buf, Size, "SRS%a #0x%x%a", gLdmStack[(OpCode >> 23) & 3], OpCode & 0x1f, WRITE (W));
357     return;
358   }
359 
360   if ((OpCode  & 0xfe500f00) == 0xf8100500) {
361     // A4.1.59 RFE<addressing_mode> <Rn>{!}
362     AsciiSPrint (Buf, Size, "RFE%a %a", gLdmStack[(OpCode >> 23) & 3], gReg[Rn], WRITE (W));
363     return;
364   }
365 
366   if ((OpCode  & 0xfff000f0) == 0xe1200070) {
367     // A4.1.7 BKPT <immed_16>
368     AsciiSPrint (Buf, Size, "BKPT %x", ((OpCode >> 8) | (OpCode & 0xf)) & 0xffff);
369     return;
370   }
371 
372   if ((OpCode  & 0xfff10020) == 0xf1000000) {
373     // A4.1.16 CPS<effect> <iflags> {, #<mode>}
374     if (((OpCode >> 6) & 0x7) == 0) {
375       AsciiSPrint (Buf, Size, "CPS #0x%x", (OpCode & 0x2f));
376     } else {
377       imode = (OpCode >> 18) & 0x3;
378       Index = AsciiSPrint (Buf, Size, "CPS%a %a%a%a", (imode == 3) ? "ID":"IE", (OpCode & BIT8) ? "A":"", (OpCode & BIT7) ? "I":"", (OpCode & BIT6) ? "F":"");
379       if ((OpCode & BIT17) != 0) {
380         AsciiSPrint (&Buf[Index], Size - Index, ", #0x%x", OpCode & 0x1f);
381       }
382     }
383     return;
384   }
385 
386   if ((OpCode  & 0x0f000000) == 0x0f000000) {
387     // A4.1.107 SWI{<cond>} <immed_24>
388     AsciiSPrint (Buf, Size, "SWI%a %x", COND (OpCode), OpCode & 0x00ffffff);
389     return;
390   }
391 
392   if ((OpCode  & 0x0fb00000) == 0x01000000) {
393     // A4.1.38 MRS{<cond>} <Rd>, CPSR  MRS{<cond>} <Rd>, SPSR
394     AsciiSPrint (Buf, Size, "MRS%a %a, %a", COND (OpCode), gReg[Rd], B ? "SPSR" : "CPSR");
395     return;
396   }
397 
398 
399   if ((OpCode  & 0x0db00000) == 0x03200000) {
400     // A4.1.38 MSR{<cond>} CPSR_<fields>, #<immediate> MSR{<cond>} CPSR_<fields>, <Rm>
401     if (I) {
402       // MSR{<cond>} CPSR_<fields>, #<immediate>
403       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));
404     } else {
405       // MSR{<cond>} CPSR_<fields>, <Rm>
406       AsciiSPrint (Buf, Size, "MRS%a %a_%a, %a", COND (OpCode), B ? "SPSR" : "CPSR", gReg[Rd]);
407     }
408     return;
409   }
410 
411   if ((OpCode  & 0xff000010) == 0xfe000000) {
412     // A4.1.13 CDP{<cond>} <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
413     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);
414     return;
415   }
416 
417   if ((OpCode  & 0x0e000000) == 0x0c000000) {
418     // A4.1.19 LDC and A4.1.96 SDC
419     if ((OpCode & 0xf0000000) == 0xf0000000) {
420       Index = AsciiSPrint (Buf, Size, "%a2 0x%x, CR%d, ", L ? "LDC":"SDC", (OpCode >> 8) & 0xf, Rd);
421     } else {
422       Index = AsciiSPrint (Buf, Size, "%a%a 0x%x, CR%d, ",  L ? "LDC":"SDC", COND (OpCode), (OpCode >> 8) & 0xf, Rd);
423     }
424 
425     if (!P) {
426       if (!W) {
427         // A5.5.5.5 [<Rn>], <option>
428       AsciiSPrint (&Buf[Index], Size - Index, "[%a], {0x%x}", gReg[Rn], OpCode & 0xff);
429       } else {
430         // A.5.5.4  [<Rn>], #+/-<offset_8>*4
431       AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a0x%x*4", gReg[Rn], SIGN (U), OpCode & 0xff);
432       }
433     } else {
434       // A5.5.5.2 [<Rn>, #+/-<offset_8>*4 ]!
435       AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a0x%x*4]%a", gReg[Rn], SIGN (U), OpCode & 0xff, WRITE (W));
436     }
437 
438   }
439 
440   if ((OpCode  & 0x0f000010) == 0x0e000010) {
441     // A4.1.32 MRC2, MCR2
442     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);
443     return;
444   }
445 
446   if ((OpCode  & 0x0ff00000) == 0x0c400000) {
447     // A4.1.33 MRRC2, MCRR2
448     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);
449     return;
450   }
451 
452   AsciiSPrint (Buf, Size, "Faulting OpCode 0x%08x", OpCode);
453 
454   *OpCodePtr += 1;
455   return;
456 }
457 
458