From nobody Mon Apr 29 03:27:36 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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 1510869557536237.0337826110756; Thu, 16 Nov 2017 13:59:17 -0800 (PST) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id CBE89202E5E5D; Thu, 16 Nov 2017 13:55:05 -0800 (PST) Received: from mail.zytor.com (terminus.zytor.com [65.50.211.136]) (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 701C121B00DC1 for ; Thu, 16 Nov 2017 13:55:05 -0800 (PST) Received: from thor.domain.name ([IPv6:2804:7f4:c480:16bd:0:0:0:1]) (authenticated bits=0) by mail.zytor.com (8.15.2/8.15.2) with ESMTPSA id vAGLupRe002460 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 Nov 2017 13:57:00 -0800 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=65.50.211.136; helo=mail.zytor.com; envelope-from=pcacjr@zytor.com; receiver=edk2-devel@lists.01.org From: Paulo Alcantara To: edk2-devel@lists.01.org Date: Thu, 16 Nov 2017 19:56:30 -0200 Message-Id: <86955028c6e8f82de1dc1e8206d2b5441cbbf33c.1510868616.git.pcacjr@zytor.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: References: In-Reply-To: References: Subject: [edk2] [RFC v3 1/3] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 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: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" This patch adds stack trace support during a X64 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/X64/ArchExceptionHandler.c | 376= +++++++++++++++++++- 1 file changed, 374 insertions(+), 2 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHan= dler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler= .c index 65f0cff680..fe776ccc2d 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c @@ -14,6 +14,11 @@ =20 #include "CpuExceptionCommon.h" =20 +// +// Unknown PDB file name +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mUnknownPdbFileName =3D "????"; + /** Return address map of exception handler template so that C code can gene= rate exception tables. @@ -242,6 +247,357 @@ DumpCpuContext ( ); } =20 +/** + Get absolute path and file name of PDB file in PE/COFF image. + + @param[in] ImageBase Base address of PE/COFF image. + @param[out] PdbAbsoluteFilePath Absolute path of PDB file. + @param[out] PdbFileName File name of PDB file. +**/ +STATIC +VOID +GetPdbFileName ( + IN UINTN ImageBase, + OUT CHAR8 **PdbAbsoluteFilePath, + OUT CHAR8 **PdbFileName + ) +{ + VOID *PdbPointer; + CHAR8 *Str; + + // + // Get PDB file name from PE/COFF image + // + PdbPointer =3D PeCoffLoaderGetPdbPointer ((VOID *)ImageBase); + if (PdbPointer =3D=3D NULL) { + // + // No PDB file name found. Set it to an unknown file name. + // + *PdbFileName =3D (CHAR8 *)mUnknownPdbFileName; + if (PdbAbsoluteFilePath !=3D NULL) { + *PdbAbsoluteFilePath =3D NULL; + } + } else { + // + // Get file name portion out of PDB file in PE/COFF image + // + Str =3D (CHAR8 *)((UINTN)PdbPointer + + AsciiStrLen ((CHAR8 *)PdbPointer) - sizeof *Str); + for (; *Str !=3D '/' && *Str !=3D '\\'; Str--) { + ; + } + + // + // Set PDB file name (also skip trailing path separator: '/' or '\\') + // + *PdbFileName =3D Str + 1; + + if (PdbAbsoluteFilePath !=3D NULL) { + // + // Set absolute file path of PDB file + // + *PdbAbsoluteFilePath =3D PdbPointer; + } + } +} + +/** + Dump stack contents. + + @param[in] CurrentRsp Current stack pointer address. + @param[in] UnwoundStacksCount Count of unwound stack frames. +**/ +STATIC +VOID +DumpStackContents ( + IN UINT64 CurrentRsp, + IN INTN UnwoundStacksCount + ) +{ + // + // Check for proper stack pointer alignment + // + if (((UINTN)CurrentRsp & (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%016lx: %016lx %016lx\n", + CurrentRsp, + *(UINT64 *)CurrentRsp, + *(UINT64 *)((UINTN)CurrentRsp + 8) + ); + + // + // Point to next stack + // + CurrentRsp +=3D CPU_STACK_ALIGNMENT; + } +} + +/** + Dump all image module names from call stack. + + @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT. +**/ +STATIC +VOID +DumpImageModuleNames ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + EFI_STATUS Status; + UINT64 Rip; + UINTN ImageBase; + VOID *EntryPoint; + CHAR8 *PdbAbsoluteFilePath; + CHAR8 *PdbFileName; + UINT64 Rbp; + UINTN LastImageBase; + + // + // Set current RIP address + // + Rip =3D SystemContext.SystemContextX64->Rip; + + // + // Set current frame pointer address + // + Rbp =3D SystemContext.SystemContextX64->Rbp; + + // + // Check for proper frame pointer alignment + // + if (((UINTN)Rbp & (CPU_STACK_ALIGNMENT - 1)) !=3D 0) { + InternalPrintMessage ("!!!! Unaligned frame pointer. !!!!\n"); + return; + } + + // + // Get initial PE/COFF image base address from current RIP + // + ImageBase =3D PeCoffSearchImageBase (Rip); + 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%016lx, EntryPoint=3D0x%016lx):\n", + PdbFileName, + ImageBase, + (UINTN)EntryPoint + ); + InternalPrintMessage ("%a\n", PdbAbsoluteFilePath); + } + + // + // Walk through call stack and find next module names + // + for (;;) { + // + // Set RIP with return address from current stack frame + // + Rip =3D *(UINT64 *)((UINTN)Rbp + 8); + + // + // If RIP is zero, then stop unwinding the stack + // + if (Rip =3D=3D 0) { + break; + } + + // + // Search for the respective PE/COFF image based on RIP + // + ImageBase =3D PeCoffSearchImageBase (Rip); + if (ImageBase =3D=3D 0) { + // + // Stop stack trace + // + break; + } + + // + // If RIP 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%016lx, EntryPoint=3D0x%016lx):\n", + PdbFileName, + ImageBase, + (UINTN)EntryPoint + ); + InternalPrintMessage ("%a\n", PdbAbsoluteFilePath); + } + + // + // Save last PE/COFF image base address + // + LastImageBase =3D ImageBase; + } + + // + // Unwind the stack + // + Rbp =3D *(UINT64 *)(UINTN)Rbp; + } +} + +/** + Dump stack trace. + + @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT. + @param[out] UnwoundStacksCount Count of unwound stack frames. +**/ +STATIC +VOID +DumpStackTrace ( + IN EFI_SYSTEM_CONTEXT SystemContext, + OUT INTN *UnwoundStacksCount + ) +{ + UINT64 Rip; + UINT64 Rbp; + UINTN ImageBase; + CHAR8 *PdbFileName; + + // + // Set current RIP address + // + Rip =3D SystemContext.SystemContextX64->Rip; + + // + // Set current frame pointer address + // + Rbp =3D SystemContext.SystemContextX64->Rbp; + + // + // Get initial PE/COFF image base address from current RIP + // + ImageBase =3D PeCoffSearchImageBase (Rip); + 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: + // + // # @ + (RBP) in [ | ????] + // + InternalPrintMessage ( + "%d 0x%016lx @ 0x%016lx+0x%x (0x%016lx) in %a\n", + *UnwoundStacksCount - 1, + Rip, + ImageBase, + Rip - ImageBase - 1, + Rbp, + PdbFileName + ); + + // + // Set RIP with return address from current stack frame + // + Rip =3D *(UINT64 *)((UINTN)Rbp + 8); + + // + // If RIP is zero, then stop unwinding the stack + // + if (Rip =3D=3D 0) { + break; + } + + // + // Search for the respective PE/COFF image based on RIP + // + ImageBase =3D PeCoffSearchImageBase (Rip); + if (ImageBase =3D=3D 0) { + // + // Stop stack trace + // + break; + } + + // + // Get PDB file name + // + GetPdbFileName (ImageBase, NULL, &PdbFileName); + + // + // Unwind the stack + // + Rbp =3D *(UINT64 *)(UINTN)Rbp; + + // + // Increment count of unwound stacks + // + (*UnwoundStacksCount)++; + } +} + /** Display CPU information. =20 @@ -254,9 +610,25 @@ DumpImageAndCpuContent ( IN EFI_SYSTEM_CONTEXT SystemContext ) { + INTN UnwoundStacksCount; + + // + // Dump CPU context + // DumpCpuContext (ExceptionType, SystemContext); + + // + // Dump stack trace + // + DumpStackTrace (SystemContext, &UnwoundStacksCount); + + // + // Dump image module names + // + DumpImageModuleNames (SystemContext); + // - // Dump module image base and module entry point by RIP + // Dump stack contents // - DumpModuleImageInfo (SystemContext.SystemContextX64->Rip); + DumpStackContents (SystemContext.SystemContextX64->Rsp, UnwoundStacksCou= nt); } --=20 2.14.3 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel From nobody Mon Apr 29 03:27:36 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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 1510869561401997.9202382865872; Thu, 16 Nov 2017 13:59:21 -0800 (PST) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 1502820349DAB; Thu, 16 Nov 2017 13:55:10 -0800 (PST) Received: from mail.zytor.com (terminus.zytor.com [65.50.211.136]) (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 08FFD21B00DDB for ; Thu, 16 Nov 2017 13:55:08 -0800 (PST) Received: from thor.domain.name ([IPv6:2804:7f4:c480:16bd:0:0:0:1]) (authenticated bits=0) by mail.zytor.com (8.15.2/8.15.2) with ESMTPSA id vAGLupRf002460 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 Nov 2017 13:57:03 -0800 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=65.50.211.136; helo=mail.zytor.com; envelope-from=pcacjr@zytor.com; receiver=edk2-devel@lists.01.org From: Paulo Alcantara To: edk2-devel@lists.01.org Date: Thu, 16 Nov 2017 19:56:31 -0200 Message-Id: <068f2589af4ee6656685519b6ed4cedba9a2c9f6.1510868616.git.pcacjr@zytor.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: References: In-Reply-To: References: Subject: [edk2] [RFC v3 2/3] UefiCpuPkg/CpuExceptionHandlerLib: Export GetPdbFileName() X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 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: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" This function will be used by both IA32 and X64 exception handling in order to print out image module names during stack unwinding. Cc: Eric Dong Cc: Laszlo Ersek Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara --- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c | 60 = +++++++++++++++++++- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h | 14 = +++++ UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 59 = ------------------- 3 files changed, 73 insertions(+), 60 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c= b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c index dbfaae1d30..f62ab8c48c 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c @@ -54,6 +54,11 @@ CONST CHAR8 *mExceptionNameStr[] =3D { =20 #define EXCEPTION_KNOWN_NAME_NUM (sizeof (mExceptionNameStr) / sizeof (CH= AR8 *)) =20 +// +// Unknown PDB file name +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mUnknownPdbFileName =3D "????"; + /** Get ASCII format string exception name by exception type. =20 @@ -177,4 +182,57 @@ ReadAndVerifyVectorInfo ( VectorInfo ++; } return EFI_SUCCESS; -} \ No newline at end of file +} + +/** + Get absolute path and file name of PDB file in PE/COFF image. + + @param[in] ImageBase Base address of PE/COFF image. + @param[out] PdbAbsoluteFilePath Absolute path of PDB file. + @param[out] PdbFileName File name of PDB file. +**/ +VOID +GetPdbFileName ( + IN UINTN ImageBase, + OUT CHAR8 **PdbAbsoluteFilePath, + OUT CHAR8 **PdbFileName + ) +{ + VOID *PdbPointer; + CHAR8 *Str; + + // + // Get PDB file name from PE/COFF image + // + PdbPointer =3D PeCoffLoaderGetPdbPointer ((VOID *)ImageBase); + if (PdbPointer =3D=3D NULL) { + // + // No PDB file name found. Set it to an unknown file name. + // + *PdbFileName =3D (CHAR8 *)mUnknownPdbFileName; + if (PdbAbsoluteFilePath !=3D NULL) { + *PdbAbsoluteFilePath =3D NULL; + } + } else { + // + // Get file name portion out of PDB file in PE/COFF image + // + Str =3D (CHAR8 *)((UINTN)PdbPointer + + AsciiStrLen ((CHAR8 *)PdbPointer) - sizeof *Str); + for (; *Str !=3D '/' && *Str !=3D '\\'; Str--) { + ; + } + + // + // Set PDB file name (also skip trailing path separator: '/' or '\\') + // + *PdbFileName =3D Str + 1; + + if (PdbAbsoluteFilePath !=3D NULL) { + // + // Set absolute file path of PDB file + // + *PdbAbsoluteFilePath =3D PdbPointer; + } + } +} diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h= b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h index 740a58828b..042207025e 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h @@ -288,5 +288,19 @@ CommonExceptionHandlerWorker ( IN EXCEPTION_HANDLER_DATA *ExceptionHandlerData ); =20 +/** + Get absolute path and file name of PDB file in PE/COFF image. + + @param[in] ImageBase Base address of PE/COFF image. + @param[out] PdbAbsoluteFilePath Absolute path of PDB file. + @param[out] PdbFileName File name of PDB file. +**/ +VOID +GetPdbFileName ( + IN UINTN ImageBase, + OUT CHAR8 **PdbAbsoluteFilePath, + OUT CHAR8 **PdbFileName + ); + #endif =20 diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHan= dler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler= .c index fe776ccc2d..7f8ec65e1d 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c @@ -14,11 +14,6 @@ =20 #include "CpuExceptionCommon.h" =20 -// -// Unknown PDB file name -// -GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mUnknownPdbFileName =3D "????"; - /** Return address map of exception handler template so that C code can gene= rate exception tables. @@ -247,60 +242,6 @@ DumpCpuContext ( ); } =20 -/** - Get absolute path and file name of PDB file in PE/COFF image. - - @param[in] ImageBase Base address of PE/COFF image. - @param[out] PdbAbsoluteFilePath Absolute path of PDB file. - @param[out] PdbFileName File name of PDB file. -**/ -STATIC -VOID -GetPdbFileName ( - IN UINTN ImageBase, - OUT CHAR8 **PdbAbsoluteFilePath, - OUT CHAR8 **PdbFileName - ) -{ - VOID *PdbPointer; - CHAR8 *Str; - - // - // Get PDB file name from PE/COFF image - // - PdbPointer =3D PeCoffLoaderGetPdbPointer ((VOID *)ImageBase); - if (PdbPointer =3D=3D NULL) { - // - // No PDB file name found. Set it to an unknown file name. - // - *PdbFileName =3D (CHAR8 *)mUnknownPdbFileName; - if (PdbAbsoluteFilePath !=3D NULL) { - *PdbAbsoluteFilePath =3D NULL; - } - } else { - // - // Get file name portion out of PDB file in PE/COFF image - // - Str =3D (CHAR8 *)((UINTN)PdbPointer + - AsciiStrLen ((CHAR8 *)PdbPointer) - sizeof *Str); - for (; *Str !=3D '/' && *Str !=3D '\\'; Str--) { - ; - } - - // - // Set PDB file name (also skip trailing path separator: '/' or '\\') - // - *PdbFileName =3D Str + 1; - - if (PdbAbsoluteFilePath !=3D NULL) { - // - // Set absolute file path of PDB file - // - *PdbAbsoluteFilePath =3D PdbPointer; - } - } -} - /** Dump stack contents. =20 --=20 2.14.3 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel From nobody Mon Apr 29 03:27:36 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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 1510869562582742.5414660174104; Thu, 16 Nov 2017 13:59:22 -0800 (PST) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 4E0AA21B00DE2; Thu, 16 Nov 2017 13:55:10 -0800 (PST) Received: from mail.zytor.com (terminus.zytor.com [65.50.211.136]) (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 0CCFA21B00DD6 for ; Thu, 16 Nov 2017 13:55:08 -0800 (PST) Received: from thor.domain.name ([IPv6:2804:7f4:c480:16bd:0:0:0:1]) (authenticated bits=0) by mail.zytor.com (8.15.2/8.15.2) with ESMTPSA id vAGLupRg002460 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 16 Nov 2017 13:57:06 -0800 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=65.50.211.136; helo=mail.zytor.com; envelope-from=pcacjr@zytor.com; receiver=edk2-devel@lists.01.org From: Paulo Alcantara To: edk2-devel@lists.01.org Date: Thu, 16 Nov 2017 19:56:32 -0200 Message-Id: <02c1d36c3c84fab2cbfa3f34e15e5bdfb7bf8c15.1510868616.git.pcacjr@zytor.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: References: In-Reply-To: References: Subject: [edk2] [RFC v3 3/3] UefiCpuPkg/CpuExceptionHandlerLib/Ia32: Add stack trace support X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 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: 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 | 31= 0 +++++++++++++++++++- 3 files changed, 308 insertions(+), 55 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c= b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c index f62ab8c48c..867c5c01d6 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 "); - 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 042207025e..478374d003 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h @@ -119,17 +119,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 f2c39eb193..db8013a5af 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c @@ -210,6 +210,296 @@ DumpCpuContext ( ); } =20 +/** + Dump stack trace. + + @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT. + @param[out] UnwoundStacksCount Count of unwound stack frames. +**/ +STATIC +VOID +DumpStackTrace ( + IN EFI_SYSTEM_CONTEXT SystemContext, + OUT INTN *UnwoundStacksCount + ) +{ + UINT32 Eip; + UINT32 Ebp; + UINTN ImageBase; + CHAR8 *PdbFileName; + + // + // Set current EIP address + // + 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] SystemContext Pointer to EFI_SYSTEM_CONTEXT. +**/ +STATIC +VOID +DumpImageModuleNames ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + EFI_STATUS Status; + UINT32 Eip; + UINT32 Ebp; + UINTN ImageBase; + VOID *EntryPoint; + CHAR8 *PdbAbsoluteFilePath; + CHAR8 *PdbFileName; + UINTN LastImageBase; + + // + // Set current EIP address + // + 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. =20 @@ -222,9 +512,25 @@ DumpImageAndCpuContent ( IN EFI_SYSTEM_CONTEXT SystemContext ) { + INTN UnwoundStacksCount; + + // + // Dump CPU context + // DumpCpuContext (ExceptionType, SystemContext); + + // + // Dump stack trace + // + DumpStackTrace (SystemContext, &UnwoundStacksCount); + + // + // Dump image module names + // + DumpImageModuleNames (SystemContext); + // - // Dump module image base and module entry point by EIP + // Dump stack contents // - DumpModuleImageInfo (SystemContext.SystemContextIa32->Eip); + 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