From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: 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 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 0396620347137 for ; Mon, 20 Nov 2017 06:57:49 -0800 (PST) Received: from [10.26.0.110] (corporativo.static.gvt.net.br [177.135.97.54] (may be forged)) (authenticated bits=0) by mail.zytor.com (8.15.2/8.15.2) with ESMTPSA id vAKExldY012560 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO); Mon, 20 Nov 2017 06:59:49 -0800 To: Fan Jeff , "edk2-devel@lists.01.org" Cc: Laszlo Ersek , Eric Dong References: <86955028c6e8f82de1dc1e8206d2b5441cbbf33c.1510868616.git.pcacjr@zytor.com> From: Paulo Alcantara Message-ID: <2da80d1e-8b3a-f56b-6a34-871e32b8aba1@zytor.com> Date: Mon, 20 Nov 2017 12:59:41 -0200 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.4.0 MIME-Version: 1.0 In-Reply-To: Subject: =?UTF-8?B?UmU6IOetlOWkjTogW1JGQyB2MyAxLzNdIFVlZmlDcHVQa2cvQ3B1RXhjZXB0aW9uSGFuZGxlckxpYi9YNjQ6IEFkZCBzdGFjayB0cmFjZSBzdXBwb3J0?= 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: , X-List-Received-Date: Mon, 20 Nov 2017 14:57:50 -0000 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 8bit Hi Jeff, (sorry for the late response) On 11/17/2017 5:24 AM, Fan Jeff wrote: > Paulo, > > > I don't understand why you - 1 when calculating EIP offset in image, it > confused me. That's an offset relative to the PE/COFF image base: 0 - (ImageBase + ImageBaseSize - 1) Doesn't that look right to you? Thanks Paulo > > > +  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 > +      ); > + > > Jeff > > > > > ------------------------------------------------------------------------ > *发件人:* edk2-devel 代表 Paulo > Alcantara > *发送时间:* 2017年11月17日 5:56 > *收件人:* edk2-devel@lists.01.org > *抄送:* Laszlo Ersek; Eric Dong > *主题:* [edk2] [RFC v3 1/3] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add > stack trace support > 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/ArchExceptionHandler.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 @@ > >  #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,357 @@ 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]  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)) != 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 += 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 = 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; > +  } > + > +  // > +  // Set last PE/COFF image base address > +  // > +  LastImageBase = ImageBase; > + > +  // > +  // 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; > +    } > + > +    // > +    // Search for the respective PE/COFF image based on RIP > +    // > +    ImageBase = PeCoffSearchImageBase (Rip); > +    if (ImageBase == 0) { > +      // > +      // Stop stack trace > +      // > +      break; > +    } > + > +    // > +    // If RIP points to another PE/COFF image, then find its respective > PDB file > +    // name. > +    // > +    if (LastImageBase != ImageBase) { > +      // > +      // 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); > +      } > + > +      // > +      // Save last PE/COFF image base address > +      // > +      LastImageBase = ImageBase; > +    } > + > +    // > +    // Unwind the stack > +    // > +    Rbp = *(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 = 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 unwound stacks > +  // > +  *UnwoundStacksCount = 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 = *(UINT64 *)((UINTN)Rbp + 8); > + > +    // > +    // If RIP is zero, then stop unwinding the stack > +    // > +    if (Rip == 0) { > +      break; > +    } > + > +    // > +    // 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 unwound stacks > +    // > +    (*UnwoundStacksCount)++; > +  } > +} > + >  /** >    Display CPU information. > > @@ -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, > UnwoundStacksCount); >  } > -- > 2.14.3 > > _______________________________________________ > edk2-devel mailing list > edk2-devel@lists.01.org > https://lists.01.org/mailman/listinfo/edk2-devel > > edk2-devel Info Page - 01.org > > lists.01.org > Your email address: Your name (optional): You may enter a privacy > password below. This provides only mild security, but should prevent > others from messing ... > > >