Move ARM disassembler into a library.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9902 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
andrewfish
2010-02-01 18:25:18 +00:00
parent cb6cb44c1a
commit 097bd461c4
9 changed files with 180 additions and 48 deletions

View File

@ -36,7 +36,8 @@
SemihostLib|Include/Library/Semihosting.h SemihostLib|Include/Library/Semihosting.h
UncachedMemoryAllocationLib|Include/Library/UncachedMemoryAllocationLib.h UncachedMemoryAllocationLib|Include/Library/UncachedMemoryAllocationLib.h
DefaultExceptioHandlerLib|Include/Library/DefaultExceptioHandlerLib.h DefaultExceptioHandlerLib|Include/Library/DefaultExceptioHandlerLib.h
ArmDisassemblerLib|Include/Library/ArmDisassemblerLib.h
[Guids.common] [Guids.common]
gArmTokenSpaceGuid = { 0xBB11ECFE, 0x820F, 0x4968, { 0xBB, 0xA6, 0xF7, 0x6A, 0xFE, 0x30, 0x25, 0x96 } } gArmTokenSpaceGuid = { 0xBB11ECFE, 0x820F, 0x4968, { 0xBB, 0xA6, 0xF7, 0x6A, 0xFE, 0x30, 0x25, 0x96 } }

View File

@ -52,6 +52,7 @@
ArmLib|ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLib.inf ArmLib|ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLib.inf
CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
ArmDisassemblerLib|ArmPkg/Library/ArmDisassemblerLib/ArmDisassemblerLib.inf
[LibraryClasses.ARM] [LibraryClasses.ARM]
NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf

View File

@ -0,0 +1,39 @@
/** @file
Copyright (c) 2008-2010 Apple Inc. All rights reserved.<BR>
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __ARM_DISASSEBLER_LIB_H__
#define __ARM_DISASSEBLER_LIB_H__
/**
Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to
point to next instructin.
We cheat and only decode instructions that access
memory. If the instruction is not found we dump the instruction in hex.
@param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble.
@param Thumb TRUE for Thumb(2), FALSE for ARM instruction stream
@param Buf Buffer to sprintf disassembly into.
@param Size Size of Buf in bytes.
**/
VOID
DisassembleInstruction (
IN UINT8 **OpCodePtr,
IN BOOLEAN Thumb,
OUT CHAR8 *Buf,
OUT UINTN Size
);
#endif

View File

@ -15,9 +15,8 @@
#include <Base.h> #include <Base.h>
#include <Library/BaseLib.h> #include <Library/BaseLib.h>
#include <Library/UefiLib.h>
#include <Library/PrintLib.h> #include <Library/PrintLib.h>
#include <Library/ArmDisassemblerLib.h>
CHAR8 *gCondition[] = { CHAR8 *gCondition[] = {
"EQ", "EQ",
@ -146,20 +145,25 @@ RotateRight (
/** /**
DEBUG print the faulting instruction. We cheat and only decode instructions that access Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to
point to next instructin.
We cheat and only decode instructions that access
memory. If the instruction is not found we dump the instruction in hex. memory. If the instruction is not found we dump the instruction in hex.
@param Insturction ARM instruction to disassemble. @param OpCodePtr Pointer to pointer of ARM instruction to disassemble.
@param Buf Buffer to sprintf disassembly into.
@param Size Size of Buf in bytes.
**/ **/
VOID VOID
DisassembleArmInstruction ( DisassembleArmInstruction (
IN UINT32 *OpCodePtr, IN UINT32 **OpCodePtr,
OUT CHAR8 *Buf, OUT CHAR8 *Buf,
OUT UINTN Size OUT UINTN Size
) )
{ {
UINT32 OpCode = *OpCodePtr; UINT32 OpCode = **OpCodePtr;
CHAR8 *Type, *Root; CHAR8 *Type, *Root;
BOOLEAN I, P, U, B, W, L, S, H; BOOLEAN I, P, U, B, W, L, S, H;
UINT32 Rn, Rd, Rm; UINT32 Rn, Rd, Rm;
@ -437,6 +441,8 @@ DisassembleArmInstruction (
} }
AsciiSPrint (Buf, Size, "Faulting OpCode 0x%08x", OpCode); AsciiSPrint (Buf, Size, "Faulting OpCode 0x%08x", OpCode);
*OpCodePtr += 1;
return; return;
} }

View File

@ -0,0 +1,40 @@
#/** @file
# Semihosting serail port lib
#
# Copyright (c) 2008, Apple Inc.
#
# All rights reserved. This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
#
#**/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = SemiHostingSerialPortLib
FILE_GUID = 7ACEC173-F15D-426C-8F2F-BD86B4183EF1
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = ArmDisassemblerLib
[Sources.common]
ArmDisassembler.c
ThumbDisassembler.c
[Packages]
MdePkg/MdePkg.dec
ArmPkg/ArmPkg.dec
[LibraryClasses]
UefiLib
BaseLib
PrintLib
DebugLib
PeCoffGetEntryPointLib

View File

@ -50,7 +50,7 @@ typedef struct {
UINT32 AddressMode; UINT32 AddressMode;
} THUMB_INSTRUCTIONS; } THUMB_INSTRUCTIONS;
THUMB_INSTRUCTIONS gOp[] = { THUMB_INSTRUCTIONS gOpThumb[] = {
// Thumb 16-bit instrucitons // Thumb 16-bit instrucitons
// Op Mask Format // Op Mask Format
{ "ADC" , 0x4140, 0xffc0, DATA_FORMAT5 }, { "ADC" , 0x4140, 0xffc0, DATA_FORMAT5 },
@ -144,8 +144,10 @@ THUMB_INSTRUCTIONS gOp[] = {
{ "TST" , 0x4200, 0xffc0, DATA_FORMAT5 }, { "TST" , 0x4200, 0xffc0, DATA_FORMAT5 },
{ "UXTB", 0xb2c0, 0xffc0, DATA_FORMAT5 }, { "UXTB", 0xb2c0, 0xffc0, DATA_FORMAT5 },
{ "UXTH", 0xb280, 0xffc0, DATA_FORMAT5 } { "UXTH", 0xb280, 0xffc0, DATA_FORMAT5 }
};
#if 0 #if 0
THUMB_INSTRUCTIONS gOpThumb2[] = {
, ,
// 32-bit Thumb instructions op1 01 // 32-bit Thumb instructions op1 01
@ -193,9 +195,8 @@ THUMB_INSTRUCTIONS gOp[] = {
// 1111 1 011 0xxx xxxx xxxx xxxx xxxx xxxx Multiply // 1111 1 011 0xxx xxxx xxxx xxxx xxxx xxxx Multiply
// 1111 1 011 1xxx xxxx xxxx xxxx xxxx xxxx Long Multiply // 1111 1 011 1xxx xxxx xxxx xxxx xxxx xxxx Long Multiply
// 1111 1 1xx xxxx xxxx xxxx xxxx xxxx xxxx Coprocessor // 1111 1 1xx xxxx xxxx xxxx xxxx xxxx xxxx Coprocessor
#endif
}; };
#endif
CHAR8 mThumbMregListStr[4*15 + 1]; CHAR8 mThumbMregListStr[4*15 + 1];
@ -253,20 +254,27 @@ SignExtend (
} }
/** /**
DEBUG print the faulting instruction. We cheat and only decode instructions that access Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to
point to next instructin.
We cheat and only decode instructions that access
memory. If the instruction is not found we dump the instruction in hex. memory. If the instruction is not found we dump the instruction in hex.
@param Insturction ARM instruction to disassemble. @param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble.
@param Buf Buffer to sprintf disassembly into.
@param Size Size of Buf in bytes.
**/ **/
VOID VOID
DisassembleThumbInstruction ( DisassembleThumbInstruction (
IN UINT16 *OpCodePtr, IN UINT16 **OpCodePtrPtr,
OUT CHAR8 *Buf, OUT CHAR8 *Buf,
OUT UINTN Size OUT UINTN Size
) )
{ {
UINT16 OpCode = *OpCodePtr; UINT16 *OpCodePtr;
UINT16 OpCode;
UINT16 OpCode32;
UINT32 Index; UINT32 Index;
UINT32 Offset; UINT32 Offset;
UINT16 Rd, Rn, Rm; UINT16 Rd, Rn, Rm;
@ -274,6 +282,12 @@ DisassembleThumbInstruction (
BOOLEAN H1, H2, imod; BOOLEAN H1, H2, imod;
UINT32 PC; UINT32 PC;
OpCodePtr = *OpCodePtrPtr;
OpCode = **OpCodePtrPtr;
// Thumb2 is a stream of 16-bit instructions not a 32-bit instruction.
OpCode32 = (OpCode << 16) | *(OpCodePtr + 1);
// These register names match branch form, but not others // These register names match branch form, but not others
Rd = OpCode & 0x7; Rd = OpCode & 0x7;
Rn = (OpCode >> 3) & 0x7; Rn = (OpCode >> 3) & 0x7;
@ -283,10 +297,13 @@ DisassembleThumbInstruction (
imod = (OpCode & BIT4) != 0; imod = (OpCode & BIT4) != 0;
PC = (UINT32)(UINTN)*OpCodePtr; PC = (UINT32)(UINTN)*OpCodePtr;
for (Index = 0; Index < sizeof (gOp)/sizeof (THUMB_INSTRUCTIONS); Index++) { // Increment by the minimum instruction size, Thumb2 could be bigger
if ((OpCode & gOp[Index].Mask) == gOp[Index].OpCode) { *OpCodePtrPtr += 1;
Offset = AsciiSPrint (Buf, Size, "%a", gOp[Index].Start);
switch (gOp[Index].AddressMode) { for (Index = 0; Index < sizeof (gOpThumb)/sizeof (THUMB_INSTRUCTIONS); Index++) {
if ((OpCode & gOpThumb[Index].Mask) == gOpThumb[Index].OpCode) {
Offset = AsciiSPrint (Buf, Size, "%a", gOpThumb[Index].Start);
switch (gOpThumb[Index].AddressMode) {
case LOAD_STORE_FORMAT1: case LOAD_STORE_FORMAT1:
// A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>] // A6.5.1 <Rd>, [<Rn>, #<5_bit_offset>]
AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d #0x%x]", Rd, (OpCode >> 7) & 7, (OpCode >> 6) & 0x1f); AsciiSPrint (&Buf[Offset], Size - Offset, " r%d, [r%d #0x%x]", Rd, (OpCode >> 7) & 7, (OpCode >> 6) & 0x1f);
@ -392,8 +409,54 @@ DisassembleThumbInstruction (
} }
} }
} }
#if 0
// Thumb2 are 32-bit instructions
*OpCodePtrPtr += 1;
for (Index = 0; Index < sizeof (gOpThumb2)/sizeof (THUMB_INSTRUCTIONS); Index++) {
if ((OpCode32 & gOpThumb2[Index].Mask) == gOpThumb2[Index].OpCode) {
}
}
#endif
// Unknown instruction is 16-bits
*OpCodePtrPtr -= 1;
AsciiSPrint (Buf, Size, "0x%04x", OpCode);
} }
VOID
DisassembleArmInstruction (
IN UINT32 **OpCodePtr,
OUT CHAR8 *Buf,
OUT UINTN Size
);
/**
Place a dissasembly of of **OpCodePtr into buffer, and update OpCodePtr to
point to next instructin.
We cheat and only decode instructions that access
memory. If the instruction is not found we dump the instruction in hex.
@param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble.
@param Thumb TRUE for Thumb(2), FALSE for ARM instruction stream
@param Buf Buffer to sprintf disassembly into.
@param Size Size of Buf in bytes.
**/
VOID
DisassembleInstruction (
IN UINT8 **OpCodePtr,
IN BOOLEAN Thumb,
OUT CHAR8 *Buf,
OUT UINTN Size
)
{
if (Thumb) {
DisassembleThumbInstruction ((UINT16 **)OpCodePtr, Buf, Size);
} else {
DisassembleArmInstruction ((UINT32 **)OpCodePtr, Buf, Size);
}
}

View File

@ -18,27 +18,13 @@
#include <Library/BaseLib.h> #include <Library/BaseLib.h>
#include <Library/DebugLib.h> #include <Library/DebugLib.h>
#include <Library/PeCoffGetEntryPointLib.h> #include <Library/PeCoffGetEntryPointLib.h>
#include <Library/ArmDisassemblerLib.h>
#include <Guid/DebugImageInfoTable.h> #include <Guid/DebugImageInfoTable.h>
#include <Protocol/DebugSupport.h> #include <Protocol/DebugSupport.h>
#include <Protocol/LoadedImage.h> #include <Protocol/LoadedImage.h>
VOID
DisassembleArmInstruction (
IN UINT32 *OpCodePtr,
OUT CHAR8 *Buf,
OUT UINTN Size
);
VOID
DisassembleThumbInstruction (
IN UINT16 *OpCodePtr,
OUT CHAR8 *Buf,
OUT UINTN Size
);
EFI_DEBUG_IMAGE_INFO_TABLE_HEADER *gDebugImageTableHeader = NULL; EFI_DEBUG_IMAGE_INFO_TABLE_HEADER *gDebugImageTableHeader = NULL;
@ -248,6 +234,7 @@ DefaultExceptionHandler (
UINT32 Offset; UINT32 Offset;
CHAR8 CpsrStr[32]; // char per bit. Lower 5-bits are mode that is a 3 char string CHAR8 CpsrStr[32]; // char per bit. Lower 5-bits are mode that is a 3 char string
CHAR8 Buffer[80]; CHAR8 Buffer[80];
UINT8 *DisAsm;
CpsrString (SystemContext.SystemContextArm->CPSR, CpsrStr); CpsrString (SystemContext.SystemContextArm->CPSR, CpsrStr);
DEBUG ((EFI_D_ERROR, "%a\n", CpsrStr)); DEBUG ((EFI_D_ERROR, "%a\n", CpsrStr));
@ -268,15 +255,10 @@ DefaultExceptionHandler (
DEBUG ((EFI_D_ERROR, "loaded at 0x%08x (PE/COFF offset) 0x%x (ELF or Mach-O offset) 0x%x", ImageBase, Offset, Offset - PeCoffSizeOfHeader)); DEBUG ((EFI_D_ERROR, "loaded at 0x%08x (PE/COFF offset) 0x%x (ELF or Mach-O offset) 0x%x", ImageBase, Offset, Offset - PeCoffSizeOfHeader));
// If we come from an image it is safe to show the instruction. We know it should not fault // If we come from an image it is safe to show the instruction. We know it should not fault
if ((SystemContext.SystemContextArm->CPSR & 0x20) == 0) { DisAsm = (UINT8 *)(UINTN)SystemContext.SystemContextArm->PC;
// ARM DisassembleInstruction (&DisAsm, (SystemContext.SystemContextArm->CPSR & BIT5) == BIT5, Buffer, sizeof (Buffer));
DisassembleArmInstruction ((UINT32 *)(UINTN)SystemContext.SystemContextArm->PC, Buffer, sizeof (Buffer)); DEBUG ((EFI_D_ERROR, "\n%a", Buffer));
DEBUG ((EFI_D_ERROR, "\n%a", Buffer));
} else {
// Thumb
DisassembleThumbInstruction ((UINT16 *)(UINTN)SystemContext.SystemContextArm->PC, Buffer, sizeof (Buffer));
DEBUG ((EFI_D_ERROR, "\n%a", Buffer));
}
} }
DEBUG_CODE_END (); DEBUG_CODE_END ();
DEBUG ((EFI_D_ERROR, "\n R0 0x%08x R1 0x%08x R2 0x%08x R3 0x%08x\n", SystemContext.SystemContextArm->R0, SystemContext.SystemContextArm->R1, SystemContext.SystemContextArm->R2, SystemContext.SystemContextArm->R3)); DEBUG ((EFI_D_ERROR, "\n R0 0x%08x R1 0x%08x R2 0x%08x R3 0x%08x\n", SystemContext.SystemContextArm->R0, SystemContext.SystemContextArm->R1, SystemContext.SystemContextArm->R2, SystemContext.SystemContextArm->R3));

View File

@ -15,7 +15,7 @@
[Defines] [Defines]
INF_VERSION = 0x00010005 INF_VERSION = 0x00010005
BASE_NAME = SemiHostingSerialPortLib BASE_NAME = DefaultExceptionHandlerLib
FILE_GUID = EACDB354-DF1A-4AF9-A171-499737ED818F FILE_GUID = EACDB354-DF1A-4AF9-A171-499737ED818F
MODULE_TYPE = UEFI_DRIVER MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0 VERSION_STRING = 1.0
@ -25,8 +25,6 @@
[Sources.common] [Sources.common]
DefaultExceptionHandler.c DefaultExceptionHandler.c
ArmDisassembler.c
ThumbDisassembler.c
[Packages] [Packages]
MdePkg/MdePkg.dec MdePkg/MdePkg.dec
@ -38,5 +36,6 @@
PrintLib PrintLib
DebugLib DebugLib
PeCoffGetEntryPointLib PeCoffGetEntryPointLib
ArmDisassemblerLib

View File

@ -110,6 +110,7 @@
EblNetworkLib|EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.inf EblNetworkLib|EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.inf
GdbSerialLib|Omap35xxPkg/Library/GdbSerialLib/GdbSerialLib.inf GdbSerialLib|Omap35xxPkg/Library/GdbSerialLib/GdbSerialLib.inf
ArmDisassemblerLib|ArmPkg/Library/ArmDisassemblerLib/ArmDisassemblerLib.inf
[LibraryClasses.common.SEC] [LibraryClasses.common.SEC]