From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: 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 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 8525121CB2E3D for ; Wed, 3 Jan 2018 06:46:49 -0800 (PST) Received: from localhost (localhost [127.0.0.1]) by mail.paulo.ac (Postfix) with ESMTP id 25623C78F5B; Wed, 3 Jan 2018 14:51:52 +0000 (UTC) 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 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 NEzpI5IBQ_6X; Wed, 3 Jan 2018 14:51:48 +0000 (UTC) Received: from [10.10.25.209] (unknown [15.65.243.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.paulo.ac (Postfix) with ESMTPSA id 5CFF3C790F7; Wed, 3 Jan 2018 14:51:47 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 mail.paulo.ac 5CFF3C790F7 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=paulo.ac; s=default; t=1514991108; bh=QlDNTbmJoX4ZmnQO1jpnmX4d8lV+cadbPUqLeXbov5o=; h=Subject:To:Cc:References:From:Date:In-Reply-To:From; b=FI9uGZtv2OVYGRsyN7IcNCz+WmWv4v+Fa/Hoha+o4FlVQZWrcUhSgRSNGzrUqUGcb h1pttoH8IWhP0aZRZ+r12CevZciM6sUEdnJ2yuw7//D+KJ7CQkGGnzNMZBxkLuuNOk +EydgHRKxQfc4QjAH1FVsMntURqZOl7CPfgfU5SQ= To: Fan Jeff , "edk2-devel@lists.01.org" Cc: Laszlo Ersek , Eric Dong References: From: Paulo Alcantara Message-ID: <1c658d2f-561e-4377-8940-51d7c7086161@paulo.ac> Date: Wed, 3 Jan 2018 12:51:45 -0200 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.5.0 MIME-Version: 1.0 In-Reply-To: Subject: =?UTF-8?B?UmU6IOetlOWkjTogW1JGQyB2NCAxLzZdIFVlZmlDcHVQa2cvQ3B1RXhjZXB0aW9uSGFuZGxlckxpYi9YNjQ6IEFkZCBzdGFjayB0cmFjZSBzdXBwb3J0?= 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: , X-List-Received-Date: Wed, 03 Jan 2018 14:46:50 -0000 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 8bit Hi Jeff, On 1/3/2018 6:53 AM, Fan Jeff wrote: > Paulo, > > I did not receive your #0 patch. So, I reply #1 here. > > Your serial of patches should work for IA32/X64 GCC and IA32 MSFT. I > suggest you could push this serial of patches as soon as pass UefiCpuPkg > owner/reviewers’ review and validation, OK - That would be really appreciable if you could test it with IA32 MSFT toolchain and see if the stacktrace is printed out correctly when passing the '/Oy-' compile option. > > And then I could send my x64 MSFT support later. Cool. Thanks Paulo > ------------------------------------------------------------------------ > *From:* edk2-devel on behalf of Paulo > Alcantara > *Sent:* Friday, December 29, 2017 12:39:34 PM > *To:* edk2-devel@lists.01.org > *Cc:* Laszlo Ersek; Eric Dong > *Subject:* [edk2] [RFC v4 1/6] 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 1dcf4277de..19bfaa329a 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. > @@ -398,6 +403,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. > > @@ -410,9 +766,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