From nobody Mon Dec 23 17:06:55 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 151597585077915.990203778791852; Sun, 14 Jan 2018 16:24:10 -0800 (PST) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 62A0D222DDBED; Sun, 14 Jan 2018 16:18:46 -0800 (PST) Received: from mail.paulo.ac (mail.paulo.ac [34.238.86.106]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 39AB2222DDBE5 for ; Sun, 14 Jan 2018 16:18:44 -0800 (PST) Received: from localhost (localhost [127.0.0.1]) by mail.paulo.ac (Postfix) with ESMTP id 2E331C08893; Mon, 15 Jan 2018 00:24:01 +0000 (UTC) Received: from mail.paulo.ac ([127.0.0.1]) by localhost (mail.paulo.ac [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id P1aQb0cpkZiu; Mon, 15 Jan 2018 00:23:58 +0000 (UTC) Received: from thor.domain.name (177.204.15.215.dynamic.adsl.gvt.net.br [177.204.15.215]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.paulo.ac (Postfix) with ESMTPSA id AA86FC08890; Mon, 15 Jan 2018 00:23:55 +0000 (UTC) X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=34.238.86.106; helo=mail.paulo.ac; envelope-from=paulo@paulo.ac; receiver=edk2-devel@lists.01.org X-Virus-Scanned: amavisd-new at paulo.ac X-Spam-Flag: NO X-Spam-Score: -1.099 X-Spam-Level: X-Spam-Status: No, score=-1.099 tagged_above=-999 required=6.31 tests=[ALL_TRUSTED=-1, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no Authentication-Results: mail.paulo.ac (amavisd-new); dkim=pass (1024-bit key) header.d=paulo.ac DKIM-Filter: OpenDKIM Filter v2.11.0 mail.paulo.ac AA86FC08890 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=paulo.ac; s=default; t=1515975837; bh=ahvsruYTlD3CjLl3PcPmIkMlwdmY5YCFxaHi6mY0XRI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:In-Reply-To: References:From; b=I1ky0sjSYKurKwObi9DgiPz6vA11iFWJc90g+NIgWzOZhTnzIm7c8oPP51oiQJ290 idlq3vsVElV4QLNjhOcdKBZGIPjTMokQyIBreM0SpW+mvJIU95IBs5pR0l2O9Bvsoe UO2i0MbEZSbpQQ9HB3y03bLgPuEU9AfKRDlozGLE= From: Paulo Alcantara To: edk2-devel@lists.01.org Date: Sun, 14 Jan 2018 22:23:31 -0200 Message-Id: <457cabcc8075d638e5a27eb7794736cde02a6bdf.1515974582.git.paulo@paulo.ac> X-Mailer: git-send-email 2.14.3 In-Reply-To: References: In-Reply-To: References: Subject: [edk2] [RFC v5 3/8] UefiCpuPkg/CpuExceptionHandlerLib/Ia32: Add stack trace support X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Laszlo Ersek , Eric Dong MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" This patch adds stack trace support during a IA32 CPU exception. It will dump out back trace, stack contents as well as image module names that were part of the call stack. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong Cc: Laszlo Ersek Signed-off-by: Paulo Alcantara --- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c | 4= 2 --- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h | 1= 1 - UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c | 33= 5 +++++++++++++++++++- 3 files changed, 327 insertions(+), 61 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c= b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c index d9abbd772d..66892320c8 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c @@ -109,48 +109,6 @@ InternalPrintMessage ( SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer)); } =20 -/** - Find and display image base address and return image base and its entry = point. - - @param CurrentEip Current instruction pointer. - -**/ -VOID -DumpModuleImageInfo ( - IN UINTN CurrentEip - ) -{ - EFI_STATUS Status; - UINTN Pe32Data; - VOID *PdbPointer; - VOID *EntryPoint; - - Pe32Data =3D PeCoffSearchImageBase (CurrentEip); - if (Pe32Data =3D=3D 0) { - InternalPrintMessage ("!!!! Can't find image information. !!!!\n"); - } else { - // - // Find Image Base entry point - // - Status =3D PeCoffLoaderGetEntryPoint ((VOID *) Pe32Data, &EntryPoint); - if (EFI_ERROR (Status)) { - EntryPoint =3D NULL; - } - InternalPrintMessage ("!!!! Find image based on IP(0x%x) ", CurrentEip= ); - PdbPointer =3D PeCoffLoaderGetPdbPointer ((VOID *) Pe32Data); - if (PdbPointer !=3D NULL) { - InternalPrintMessage ("%a", PdbPointer); - } else { - InternalPrintMessage ("(No PDB) " ); - } - InternalPrintMessage ( - " (ImageBase=3D%016lp, EntryPoint=3D%016p) !!!!\n", - (VOID *) Pe32Data, - EntryPoint - ); - } -} - /** Read and save reserved vector information =20 diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h= b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h index 64c7094513..ec46c2d9d3 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h @@ -130,17 +130,6 @@ InternalPrintMessage ( ... ); =20 -/** - Find and display image base address and return image base and its entry = point. - - @param CurrentEip Current instruction pointer. - -**/ -VOID -DumpModuleImageInfo ( - IN UINTN CurrentEip - ); - /** Display CPU information. =20 diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHa= ndler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandl= er.c index 04f2ab593c..c5d6ea0939 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c @@ -399,20 +399,156 @@ DumpCpuContext ( } =20 /** - Display CPU information. + Dump stack trace. =20 - @param ExceptionType Exception type. - @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. + @param[in] ExceptionType Exception type. + @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT. + @param[out] UnwoundStacksCount Count of unwound stack frames. **/ +STATIC VOID -DumpImageAndCpuContent ( +DumpStacktrace ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN EFI_SYSTEM_CONTEXT SystemContext, + OUT INTN *UnwoundStacksCount + ) +{ + UINT32 Eip; + UINT32 Ebp; + UINTN ImageBase; + CHAR8 *PdbFileName; + + // + // Set current EIP address + // + if ((ExceptionType =3D=3D EXCEPT_IA32_PAGE_FAULT) && + ((SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_ID) != =3D 0)) { + // + // The EIP in SystemContext could not be used + // if it is page fault with I/D set. + // + Eip =3D *(UINT32 *)(UINTN)SystemContext.SystemContextIa32->Esp; + } else { + Eip =3D SystemContext.SystemContextIa32->Eip; + } + + // + // Set current frame pointer address + // + Ebp =3D SystemContext.SystemContextIa32->Ebp; + + // + // Check for proper frame pointer alignment + // + if (((UINTN)Ebp & (CPU_STACK_ALIGNMENT - 1)) !=3D 0) { + InternalPrintMessage ("!!!! Unaligned frame pointer. !!!!\n"); + return; + } + + // + // Get initial PE/COFF image base address from current EIP + // + ImageBase =3D PeCoffSearchImageBase (Eip); + if (ImageBase =3D=3D 0) { + InternalPrintMessage ("!!!! Could not find backtrace information. !!!!= "); + return; + } + + // + // Get PDB file name from initial PE/COFF image + // + GetPdbFileName (ImageBase, NULL, &PdbFileName); + + // + // Initialize count of unwound stacks + // + *UnwoundStacksCount =3D 1; + + // + // Print out back trace + // + InternalPrintMessage ("\nCall trace:\n"); + + for (;;) { + // + // Print stack frame in the following format: + // + // # @ + (EBP) in [ | ????] + // + InternalPrintMessage ( + "%d 0x%08x @ 0x%08x+0x%x (0x%08x) in %a\n", + *UnwoundStacksCount - 1, + Eip, + ImageBase, + Eip - ImageBase - 1, + Ebp, + PdbFileName + ); + + // + // Set EIP with return address from current stack frame + // + Eip =3D *(UINT32 *)((UINTN)Ebp + 4); + + // + // If EIP is zero, then stop unwinding the stack + // + if (Eip =3D=3D 0) { + break; + } + + // + // Search for the respective PE/COFF image based on EIP + // + ImageBase =3D PeCoffSearchImageBase (Eip); + if (ImageBase =3D=3D 0) { + // + // Stop stack trace + // + break; + } + + // + // Get PDB file name + // + GetPdbFileName (ImageBase, NULL, &PdbFileName); + + // + // Unwind the stack + // + Ebp =3D *(UINT32 *)(UINTN)Ebp; + + // + // Increment count of unwound stacks + // + (*UnwoundStacksCount)++; + } +} + +/** + Dump all image module names from call stack. + + @param[in] ExceptionType Exception type. + @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT. +**/ +STATIC +VOID +DumpImageModuleNames ( IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext ) { - DumpCpuContext (ExceptionType, SystemContext); + EFI_STATUS Status; + UINT32 Eip; + UINT32 Ebp; + UINTN ImageBase; + VOID *EntryPoint; + CHAR8 *PdbAbsoluteFilePath; + CHAR8 *PdbFileName; + UINTN LastImageBase; + // - // Dump module image base and module entry point by EIP + // Set current EIP address // if ((ExceptionType =3D=3D EXCEPT_IA32_PAGE_FAULT) && ((SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_ID) != =3D 0)) { @@ -420,8 +556,191 @@ DumpImageAndCpuContent ( // The EIP in SystemContext could not be used // if it is page fault with I/D set. // - DumpModuleImageInfo ((*(UINTN *)(UINTN)SystemContext.SystemContextIa32= ->Esp)); + Eip =3D *(UINT32 *)(UINTN)SystemContext.SystemContextIa32->Esp; } else { - DumpModuleImageInfo (SystemContext.SystemContextIa32->Eip); + Eip =3D SystemContext.SystemContextIa32->Eip; + } + + // + // Set current frame pointer address + // + Ebp =3D SystemContext.SystemContextIa32->Ebp; + + // + // Get initial PE/COFF image base address from current EIP + // + ImageBase =3D PeCoffSearchImageBase (Eip); + if (ImageBase =3D=3D 0) { + InternalPrintMessage ("!!!! Could not find image module names. !!!!"); + return; } + + // + // Set last PE/COFF image base address + // + LastImageBase =3D ImageBase; + + // + // Get initial PE/COFF image's entry point + // + Status =3D PeCoffLoaderGetEntryPoint ((VOID *)ImageBase, &EntryPoint); + if (EFI_ERROR (Status)) { + EntryPoint =3D NULL; + } + + // + // Get file name and absolute path of initial PDB file + // + GetPdbFileName (ImageBase, &PdbAbsoluteFilePath, &PdbFileName); + + // + // Print out initial image module name (if any) + // + if (PdbAbsoluteFilePath !=3D NULL) { + InternalPrintMessage ( + "\n%a (ImageBase=3D0x%08x, EntryPoint=3D0x%08x):\n", + PdbFileName, + ImageBase, + (UINTN)EntryPoint + ); + InternalPrintMessage ("%a\n", PdbAbsoluteFilePath); + } + + // + // Walk through call stack and find next module names + // + for (;;) { + // + // Set EIP with return address from current stack frame + // + Eip =3D *(UINT32 *)((UINTN)Ebp + 4); + + // + // Search for the respective PE/COFF image based on Eip + // + ImageBase =3D PeCoffSearchImageBase (Eip); + if (ImageBase =3D=3D 0) { + // + // Stop stack trace + // + break; + } + + // + // If EIP points to another PE/COFF image, then find its respective PD= B file + // name. + // + if (LastImageBase !=3D ImageBase) { + // + // Get PE/COFF image's entry point + // + Status =3D PeCoffLoaderGetEntryPoint ((VOID *)ImageBase, &EntryPoint= ); + if (EFI_ERROR (Status)) { + EntryPoint =3D NULL; + } + + // + // Get file name and absolute path of PDB file + // + GetPdbFileName (ImageBase, &PdbAbsoluteFilePath, &PdbFileName); + + // + // Print out image module name (if any) + // + if (PdbAbsoluteFilePath !=3D NULL) { + InternalPrintMessage ( + "%a (ImageBase=3D0x%08x, EntryPoint=3D0x%08x):\n", + PdbFileName, + ImageBase, + (UINTN)EntryPoint + ); + InternalPrintMessage ("%a\n", PdbAbsoluteFilePath); + } + + // + // Save last PE/COFF image base address + // + LastImageBase =3D ImageBase; + } + + // + // Unwind the stack + // + Ebp =3D *(UINT32 *)(UINTN)Ebp; + } +} + +/** + Dump stack contents. + + @param[in] CurrentEsp Current stack pointer address. + @param[in] UnwoundStacksCount Count of unwound stack frames. +**/ +STATIC +VOID +DumpStackContents ( + IN UINT32 CurrentEsp, + IN INTN UnwoundStacksCount + ) +{ + // + // Check for proper stack alignment + // + if (((UINTN)CurrentEsp & (CPU_STACK_ALIGNMENT - 1)) !=3D 0) { + InternalPrintMessage ("!!!! Unaligned stack pointer. !!!!\n"); + return; + } + + // + // Dump out stack contents + // + InternalPrintMessage ("\nStack dump:\n"); + while (UnwoundStacksCount-- > 0) { + InternalPrintMessage ( + "0x%08x: %08x %08x\n", + CurrentEsp, + *(UINT32 *)CurrentEsp, + *(UINT32 *)((UINTN)CurrentEsp + 4) + ); + + // + // Point to next stack + // + CurrentEsp +=3D CPU_STACK_ALIGNMENT; + } +} + +/** + Display CPU information. + + @param ExceptionType Exception type. + @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. +**/ +VOID +DumpImageAndCpuContent ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + INTN UnwoundStacksCount; + + // + // Dump CPU context + // + DumpCpuContext (ExceptionType, SystemContext); + + // + // Dump stack trace + // + DumpStacktrace (ExceptionType, SystemContext, &UnwoundStacksCount); + + // + // Dump image module names + // + DumpImageModuleNames (ExceptionType, SystemContext); + + // + // Dump stack contents + // + DumpStackContents (SystemContext.SystemContextIa32->Esp, UnwoundStacksCo= unt); } --=20 2.14.3 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel