From: "Paulo Alcantara" <pcacjr@zytor.com>
To: "Brian J. Johnson" <brian.johnson@hpe.com>
Cc: edk2-devel@lists.01.org
Subject: Re: [RFC v2 1/3] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support
Date: Thu, 16 Nov 2017 20:19:55 -0200 [thread overview]
Message-ID: <00db3b32bf95eb26032a81d109708898.squirrel@www.zytor.com> (raw)
In-Reply-To: <abc0a77a-f212-8bcb-e87b-d778c66bebff@hpe.com>
Hi Brijan,
On Thu, November 16, 2017 1:43 pm, Brian J. Johnson
>
> (These comments apply to patch 3/3 as well.)
>
> Typo: UnwondStacksCount should be UnwoundStacksCount
Fixed in v3. Thanks!
>
> It's good to check the alignment of the stack, as you're doing. But
> I'll reiterate that you absolutely need some better sanity checking of
> the stack and IP addresses before you dereference them. Remember that
> they could be absolutely *anything* at the entry to this code.
> Something caused an error, and it may have been one of those registers.
Yes - you're absolutely right. I currently have no idea how to validate
those values as well as didn't have time to do so. Sorry. I hope to get to
it ASAP or someone could help me with that.
>
> Also, if the code was built with a compiler which isn't using RBP as a
> base pointer, RBP is unlikely to contain a stack address. That will
> cause issues if you use it for unwinding without a sanity check.
Yes. I haven't figured out how to do that yet. It's also in my TODO list.
Thank you very much for the suggestions!
Paulo
>
> Thanks,
> Brian
>
>> ---
>> UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c |
>> 369 +++++++++++++++++++-
>> 1 file changed, 367 insertions(+), 2 deletions(-)
>>
>> diff --git
>> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
>> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
>> index 65f0cff680..11cd7c9e1c 100644
>> ---
>> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
>> +++
>> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
>> @@ -14,6 +14,11 @@
>>
>> #include "CpuExceptionCommon.h"
>>
>> +//
>> +// Unknown PDB file name
>> +//
>> +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mUnknownPdbFileName =
>> "????";
>> +
>> /**
>> Return address map of exception handler template so that C code can
>> generate
>> exception tables.
>> @@ -242,6 +247,350 @@ DumpCpuContext (
>> );
>> }
>>
>> +/**
>> + 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 = PeCoffLoaderGetPdbPointer ((VOID *)ImageBase);
>> + if (PdbPointer == NULL) {
>> + //
>> + // No PDB file name found. Set it to an unknown file name.
>> + //
>> + *PdbFileName = (CHAR8 *)mUnknownPdbFileName;
>> + if (PdbAbsoluteFilePath != NULL) {
>> + *PdbAbsoluteFilePath = NULL;
>> + }
>> + } else {
>> + //
>> + // Get file name portion out of PDB file in PE/COFF image
>> + //
>> + Str = (CHAR8 *)((UINTN)PdbPointer +
>> + AsciiStrLen ((CHAR8 *)PdbPointer) - sizeof *Str);
>> + for (; *Str != '/' && *Str != '\\'; Str--) {
>> + ;
>> + }
>> +
>> + //
>> + // Set PDB file name (also skip trailing path separator: '/' or
>> '\\')
>> + //
>> + *PdbFileName = Str + 1;
>> +
>> + if (PdbAbsoluteFilePath != NULL) {
>> + //
>> + // Set absolute file path of PDB file
>> + //
>> + *PdbAbsoluteFilePath = PdbPointer;
>> + }
>> + }
>> +}
>> +
>> +/**
>> + Dump stack contents.
>> +
>> + @param[in] CurrentRsp Current stack pointer address.
>> + @param[in] UnwondStacksCount Count of unwond stack frames.
>> +**/
>> +STATIC
>> +VOID
>> +DumpStackContents (
>> + IN UINT64 CurrentRsp,
>> + IN INTN UnwondStacksCount
>> + )
>> +{
>> + //
>> + // Check for proper stack pointer alignment
>> + //
>> + if (((UINTN)CurrentRsp & (CPU_STACK_ALIGNMENT - 1)) != 0) {
>> + InternalPrintMessage ("!!!! Unaligned stack pointer. !!!!\n");
>> + return;
>> + }
>> +
>> + //
>> + // Dump out stack contents
>> + //
>> + InternalPrintMessage ("\nStack dump:\n");
>> + while (UnwondStacksCount-- > 0) {
>> + InternalPrintMessage (
>> + "0x%016lx: %016lx %016lx\n",
>> + CurrentRsp,
>> + *(UINT64 *)CurrentRsp,
>> + *(UINT64 *)((UINTN)CurrentRsp + 8)
>> + );
>> +
>> + //
>> + // Point to next stack
>> + //
>> + CurrentRsp += 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;
>> +
>> + //
>> + // Set current RIP address
>> + //
>> + Rip = SystemContext.SystemContextX64->Rip;
>> +
>> + //
>> + // Set current frame pointer address
>> + //
>> + Rbp = SystemContext.SystemContextX64->Rbp;
>> +
>> + //
>> + // Check for proper frame pointer alignment
>> + //
>> + if (((UINTN)Rbp & (CPU_STACK_ALIGNMENT - 1)) != 0) {
>> + InternalPrintMessage ("!!!! Unaligned frame pointer. !!!!\n");
>> + return;
>> + }
>> +
>> + //
>> + // Get initial PE/COFF image base address from current RIP
>> + //
>> + ImageBase = PeCoffSearchImageBase (Rip);
>> + if (ImageBase == 0) {
>> + InternalPrintMessage ("!!!! Could not find image module names.
>> !!!!");
>> + return;
>> + }
>> +
>> + //
>> + // Get initial PE/COFF image's entry point
>> + //
>> + Status = PeCoffLoaderGetEntryPoint ((VOID *)ImageBase, &EntryPoint);
>> + if (EFI_ERROR (Status)) {
>> + EntryPoint = 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 != NULL) {
>> + InternalPrintMessage (
>> + "\n%a (ImageBase=0x%016lx, EntryPoint=0x%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 = *(UINT64 *)((UINTN)Rbp + 8);
>> +
>> + //
>> + // If RIP is zero, then stop unwinding the stack
>> + //
>> + if (Rip == 0) {
>> + break;
>> + }
>> +
>> + //
>> + // Check if RIP is within another PE/COFF image base address
>> + //
>> + if (Rip < ImageBase) {
>> + //
>> + // Search for the respective PE/COFF image based on RIP
>> + //
>> + ImageBase = PeCoffSearchImageBase (Rip);
>> + if (ImageBase == 0) {
>> + //
>> + // Stop stack trace
>> + //
>> + break;
>> + }
>> +
>> + //
>> + // Get PE/COFF image's entry point
>> + //
>> + Status = PeCoffLoaderGetEntryPoint ((VOID *)ImageBase,
>> &EntryPoint);
>> + if (EFI_ERROR (Status)) {
>> + EntryPoint = NULL;
>> + }
>> +
>> + //
>> + // Get file name and absolute path of PDB file
>> + //
>> + GetPdbFileName (ImageBase, &PdbAbsoluteFilePath, &PdbFileName);
>> +
>> + //
>> + // Print out image module name (if any)
>> + //
>> + if (PdbAbsoluteFilePath != NULL) {
>> + InternalPrintMessage (
>> + "%a (ImageBase=0x%016lx, EntryPoint=0x%016lx):\n",
>> + PdbFileName,
>> + ImageBase,
>> + (UINTN)EntryPoint
>> + );
>> + InternalPrintMessage ("%a\n", PdbAbsoluteFilePath);
>> + }
>> + }
>> +
>> + //
>> + // Unwind the stack
>> + //
>> + Rbp = *(UINT64 *)(UINTN)Rbp;
>> + }
>> +}
>> +
>> +/**
>> + Dump stack trace.
>> +
>> + @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT.
>> + @param[out] UnwondStacksCount Count of unwond stack frames.
>> +**/
>> +STATIC
>> +VOID
>> +DumpStackTrace (
>> + IN EFI_SYSTEM_CONTEXT SystemContext,
>> + OUT INTN *UnwondStacksCount
>> + )
>> +{
>> + UINT64 Rip;
>> + UINT64 Rbp;
>> + UINTN ImageBase;
>> + CHAR8 *PdbFileName;
>> +
>> + //
>> + // Set current RIP address
>> + //
>> + Rip = SystemContext.SystemContextX64->Rip;
>> +
>> + //
>> + // Set current frame pointer address
>> + //
>> + Rbp = SystemContext.SystemContextX64->Rbp;
>> +
>> + //
>> + // Get initial PE/COFF image base address from current RIP
>> + //
>> + ImageBase = PeCoffSearchImageBase (Rip);
>> + if (ImageBase == 0) {
>> + InternalPrintMessage ("!!!! Could not find backtrace information.
>> !!!!");
>> + return;
>> + }
>> +
>> + //
>> + // Get PDB file name from initial PE/COFF image
>> + //
>> + GetPdbFileName (ImageBase, NULL, &PdbFileName);
>> +
>> + //
>> + // Initialize count of unwond stacks
>> + //
>> + *UnwondStacksCount = 1;
>> +
>> + //
>> + // Print out back trace
>> + //
>> + InternalPrintMessage ("\nCall trace:\n");
>> +
>> + for (;;) {
>> + //
>> + // Print stack frame in the following format:
>> + //
>> + // # <RIP> @ <ImageBase>+<RelOffset> (RBP) in [<ModuleName> | ????]
>> + //
>> + InternalPrintMessage (
>> + "%d 0x%016lx @ 0x%016lx+0x%x (0x%016lx) in %a\n",
>> + *UnwondStacksCount - 1,
>> + Rip,
>> + ImageBase,
>> + Rip - ImageBase - 1,
>> + Rbp,
>> + PdbFileName
>> + );
>> +
>> + //
>> + // Set RIP with return address from current stack frame
>> + //
>> + Rip = *(UINT64 *)((UINTN)Rbp + 8);
>> +
>> + //
>> + // If RIP is zero, then stop unwinding the stack
>> + //
>> + if (Rip == 0) {
>> + break;
>> + }
>> +
>> + //
>> + // Check if RIP is within another PE/COFF image base address
>> + //
>> + if (Rip < ImageBase) {
>> + //
>> + // Search for the respective PE/COFF image based on RIP
>> + //
>> + ImageBase = PeCoffSearchImageBase (Rip);
>> + if (ImageBase == 0) {
>> + //
>> + // Stop stack trace
>> + //
>> + break;
>> + }
>> +
>> + //
>> + // Get PDB file name
>> + //
>> + GetPdbFileName (ImageBase, NULL, &PdbFileName);
>> + }
>> +
>> + //
>> + // Unwind the stack
>> + //
>> + Rbp = *(UINT64 *)(UINTN)Rbp;
>> +
>> + //
>> + // Increment count of unwond stacks
>> + //
>> + (*UnwondStacksCount)++;
>> + }
>> +}
>> +
>> /**
>> Display CPU information.
>>
>> @@ -254,9 +603,25 @@ DumpImageAndCpuContent (
>> IN EFI_SYSTEM_CONTEXT SystemContext
>> )
>> {
>> + INTN UnwondStacksCount;
>> +
>> + //
>> + // Dump CPU context
>> + //
>> DumpCpuContext (ExceptionType, SystemContext);
>> +
>> + //
>> + // Dump stack trace
>> + //
>> + DumpStackTrace (SystemContext, &UnwondStacksCount);
>> +
>> + //
>> + // 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,
>> UnwondStacksCount);
>> }
>>
>
>
> --
> Brian J. Johnson
> Enterprise X86 Lab
>
> Hewlett Packard Enterprise
>
> brian.johnson@hpe.com
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
>
--
Paulo Alcantara, HP Inc.
Speaking for myself only.
next prev parent reply other threads:[~2017-11-16 22:16 UTC|newest]
Thread overview: 82+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-11-14 12:47 [RFC 0/1] Stack trace support in X64 exception handling Paulo Alcantara
2017-11-14 12:47 ` [RFC 1/1] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support Paulo Alcantara
2017-11-14 14:01 ` Andrew Fish
2017-11-14 14:26 ` 答复: " Fan Jeff
2017-11-14 14:38 ` Andrew Fish
2017-11-14 15:30 ` Paulo Alcantara
2017-11-14 16:51 ` Brian J. Johnson
2017-12-29 3:48 ` [RFC v4 0/6] Stack trace support in X64 exception handling Paulo Alcantara
2017-12-29 4:39 ` [RFC v4 1/6] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support Paulo Alcantara
2018-01-03 8:53 ` 答复: " Fan Jeff
2018-01-03 14:51 ` Paulo Alcantara
2017-12-29 4:39 ` [RFC v4 2/6] UefiCpuPkg/CpuExceptionHandlerLib: Export GetPdbFileName() Paulo Alcantara
2017-12-29 4:39 ` [RFC v4 3/6] UefiCpuPkg/CpuExceptionHandlerLib/Ia32: Add stack trace support Paulo Alcantara
2017-12-29 4:39 ` [RFC v4 4/6] UefiCpuPkg/CpuExceptionHandlerLib: Add helper to valid memory addresses Paulo Alcantara
2018-01-03 8:42 ` 答复: " Fan Jeff
2018-01-03 14:45 ` Paulo Alcantara
2018-01-03 16:59 ` Brian J. Johnson
2018-01-04 13:03 ` Paulo Alcantara
2018-01-04 1:36 ` Yao, Jiewen
2018-01-04 1:58 ` Yao, Jiewen
2018-01-04 13:29 ` Paulo Alcantara
2018-01-04 14:35 ` Yao, Jiewen
2018-01-04 15:15 ` Paulo Alcantara
2018-01-04 13:18 ` Paulo Alcantara
2017-12-29 4:39 ` [RFC v4 5/6] UefiCpuPkg/CpuExceptionHandlerLib: Ensure valid frame/stack pointers Paulo Alcantara
2018-01-03 8:45 ` 答复: " Fan Jeff
2018-01-03 14:48 ` Paulo Alcantara
2018-01-04 1:07 ` Yao, Jiewen
2017-12-29 4:39 ` [RFC v4 6/6] UefiCpuPkg/CpuExceptionHandlerLib: Correctly print IP addresses Paulo Alcantara
2018-01-03 8:46 ` 答复: " Fan Jeff
2018-01-04 0:59 ` [RFC v4 0/6] Stack trace support in X64 exception handling Yao, Jiewen
2018-01-04 13:36 ` Paulo Alcantara
2018-01-15 0:23 ` [RFC v5 0/8] " Paulo Alcantara
2018-01-15 0:23 ` [RFC v5 1/8] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support Paulo Alcantara
2018-01-15 0:23 ` [RFC v5 2/8] UefiCpuPkg/CpuExceptionHandlerLib: Export GetPdbFileName() Paulo Alcantara
2018-01-15 0:23 ` [RFC v5 3/8] UefiCpuPkg/CpuExceptionHandlerLib/Ia32: Add stack trace support Paulo Alcantara
2018-01-15 0:23 ` [RFC v5 4/8] UefiCpuPkg/CpuExceptionHandlerLib: Add helper to validate memory addresses Paulo Alcantara
2018-01-15 0:23 ` [RFC v5 5/8] UefiCpuPkg/CpuExceptionHandlerLib: Ensure valid frame/stack pointers Paulo Alcantara
2018-01-15 0:23 ` [RFC v5 6/8] UefiCpuPkg/CpuExceptionHandlerLib: Correctly print IP addresses Paulo Alcantara
2018-01-15 0:23 ` [RFC v5 7/8] UefiCpuPkg/CpuExceptionHandlerLib: Validate memory address ranges Paulo Alcantara
2018-01-15 0:23 ` [RFC v5 8/8] UefiCpuPkg/CpuExceptionHandlerLib: Add early check in DumpStackContents Paulo Alcantara
2018-01-17 12:57 ` [RFC v5 0/8] Stack trace support in X64 exception handling Yao, Jiewen
2018-01-17 22:48 ` Yao, Jiewen
2018-01-19 0:09 ` Paulo Alcantara
2018-01-19 0:02 ` Paulo Alcantara
2018-01-19 0:15 ` Paulo Alcantara
2018-01-29 13:38 ` Paulo Alcantara
2018-01-31 5:56 ` Yao, Jiewen
2018-01-31 19:05 ` Paulo Alcantara
2017-11-14 13:21 ` [RFC 0/1] " Paulo Alcantara
2017-11-14 14:03 ` 答复: " Fan Jeff
2017-11-14 14:12 ` 答复: " Fan Jeff
2017-11-14 15:37 ` Paulo Alcantara
2017-11-14 16:33 ` Brian J. Johnson
2017-11-14 17:23 ` Andrew Fish
2017-11-14 17:41 ` Brian J. Johnson
2017-11-14 17:56 ` Paulo Alcantara
2017-11-15 13:21 ` 答复: 答复: " Fan Jeff
2017-11-15 14:41 ` Paulo Alcantara
2017-11-15 14:52 ` 答复: " Fan Jeff
2017-11-16 1:18 ` [RFC v2 0/3] " Paulo Alcantara
2017-11-16 1:18 ` [RFC v2 1/3] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support Paulo Alcantara
2017-11-16 1:57 ` Yao, Jiewen
2017-11-16 22:13 ` Paulo Alcantara
2017-11-17 3:43 ` Yao, Jiewen
2017-11-20 14:51 ` Paulo Alcantara
2017-11-16 15:43 ` Brian J. Johnson
2017-11-16 22:19 ` Paulo Alcantara [this message]
2017-11-16 1:18 ` [RFC v2 2/3] UefiCpuPkg/CpuExceptionHandlerLib: Export GetPdbFileName() Paulo Alcantara
2017-11-16 1:18 ` [RFC v2 3/3] UefiCpuPkg/CpuExceptionHandlerLib/Ia32: Add stack trace support Paulo Alcantara
2017-11-16 1:46 ` [RFC v2 0/3] Stack trace support in X64 exception handling Paulo Alcantara
2017-11-16 5:01 ` Andrew Fish
2017-11-16 22:02 ` Paulo Alcantara
2017-11-16 21:56 ` [RFC v3 " Paulo Alcantara
2017-11-16 21:56 ` [RFC v3 1/3] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support Paulo Alcantara
2017-11-17 7:24 ` 答复: " Fan Jeff
2017-11-20 14:59 ` Paulo Alcantara
2017-11-23 14:27 ` 答复: " Fan Jeff
2017-11-23 18:34 ` Andrew Fish
2017-11-23 19:49 ` Fan Jeff
2017-11-16 21:56 ` [RFC v3 2/3] UefiCpuPkg/CpuExceptionHandlerLib: Export GetPdbFileName() Paulo Alcantara
2017-11-16 21:56 ` [RFC v3 3/3] UefiCpuPkg/CpuExceptionHandlerLib/Ia32: Add stack trace support Paulo Alcantara
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=00db3b32bf95eb26032a81d109708898.squirrel@www.zytor.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox