summaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
AgeCommit message (Collapse)Author
2025-06-02[lldb] Add filter option to AST dump command (#142164)Michael Buch
Depends on https://github.com/llvm/llvm-project/pull/142163 This patch makes the `-ast-dump-filter` Clang option available to the `target modules dump ast` command. This allows us to selectively dump parts of the AST by name. The AST can quickly grow way too large to skim on the console. This will aid in debugging AST related issues. Example: ``` (lldb) target modules dump ast --filter func Dumping clang ast for 48 modules. Dumping func: FunctionDecl 0xc4b785008 <<invalid sloc>> <invalid sloc> func 'void (int)' extern |-ParmVarDecl 0xc4b7853d8 <<invalid sloc>> <invalid sloc> x 'int' `-AsmLabelAttr 0xc4b785358 <<invalid sloc>> Implicit "_Z4funcIiEvT_" Dumping func<int>: FunctionDecl 0xc4b7850b8 <<invalid sloc>> <invalid sloc> func<int> 'void (int)' implicit_instantiation extern |-TemplateArgument type 'int' | `-BuiltinType 0xc4b85b110 'int' `-ParmVarDecl 0xc4b7853d8 <<invalid sloc>> <invalid sloc> x 'int' ``` The majority of this patch is adjust the `Dump` API. The main change in behaviour is in `TypeSystemClang::Dump`, where we now use the `ASTPrinter` for dumping the `TranslationUnitDecl`. This is where the `-ast-dump-filter` functionality lives in Clang.
2025-05-21[lldb] Add templated CompilerType::GetTypeSystem (NFC) (#140424)Dave Lee
Add an overloaded `GetTypeSystem` to specify the expected type system subclass. Changes code from `GetTypeSystem().dyn_cast_or_null<TypeSystemClang>()` to `GetTypeSystem<TypeSystemClang>()`.
2025-03-05[lldb] Upgrade CompilerType::GetBitSize to return llvm::Expected (#129601)Adrian Prantl
This patch pushes the error handling boundary for the GetBitSize() methods from Runtime into the Type and CompilerType APIs. This makes it easier to diagnose problems thanks to more meaningful error messages being available. GetBitSize() is often the first thing LLDB asks about a type, so this method is particularly important for a better user experience. rdar://145667239
2025-02-20[lldb] Renaissance LineTable sequences (#127800)Pavel Labath
LineSeqeunce is basically a vector, except that users aren't supposed to know that. This implements the same concept in a slightly simpler fashion.
2025-01-24[lldb] Use the first address range as the function address (#122440)Pavel Labath
This is the behavior expected by DWARF. It also requires some fixups to algorithms which were storing the addresses of some objects (Blocks and Variables) relative to the beginning of the function. There are plenty of things that still don't work in this setups, but this change is sufficient for the expression evaluator to correctly recognize the entry point of a function in this case.
2025-01-10[lldb] Add Function::GetAddress and redirect some uses (#115836)Pavel Labath
Many calls to Function::GetAddressRange() were not interested in the range itself. Instead they wanted to find the address of the function (its entry point) or the base address for relocation of function-scoped entities (technically, the two don't need to be the same, but there's isn't good reason for them not to be). This PR creates a separate function for retrieving this, and changes the existing (non-controversial) uses to call that instead.
2024-12-03Reapply "[lldb] Use the function block as a source for function ranges ↵Pavel Labath
(#117996)" This reverts commit 2526d5b1689389da9b194b5ec2878cfb2f4aca93, reapplying ba14dac481564000339ba22ab867617590184f4c after fixing the conflict with #117532. The change is that Function::GetAddressRanges now recomputes the returned value instead of returning the member. This means it now returns a value instead of a reference type.
2024-12-03Revert "[lldb] Use the function block as a source for function ranges (#117996)"Pavel Labath
This reverts commit ba14dac481564000339ba22ab867617590184f4c. I guess "has no conflicts" doesn't mean "it will build".
2024-12-03[lldb] Use the function block as a source for function ranges (#117996)Pavel Labath
This is a follow-up/reimplementation of #115730. While working on that patch, I did not realize that the correct (discontinuous) set of ranges is already stored in the block representing the whole function. The catch -- ranges for this block are only set later, when parsing all of the blocks of the function. This patch changes that by populating the function block ranges eagerly -- from within the Function constructor. This also necessitates a corresponding change in all of the symbol files -- so that they stop populating the ranges of that block. This allows us to avoid some unnecessary work (not parsing the function DW_AT_ranges twice) and also results in some simplification of the parsing code.
2024-11-27[lldb] Make sure Blocks always have a parent (#117683)Pavel Labath
It's basically true already (except for a brief time during construction). This patch makes sure the objects are constructed with a valid parent and enforces this in the type system, which allows us to get rid of some nullptr checks.
2024-11-26[lldb/NativePDB] Don't create parentless blocks (#117581)Pavel Labath
In case of an error GetBlock would return a reference to a Block without adding it to a parent. This doesn't seem like a good idea, and none of the other plugins do that. This patch fixes that by propagating errors (well, null pointers...) up the stack. I don't know of any specific problem that this solves, but given that this occurs only when something goes very wrong (e.g. a corrupted PDB file), it's quite possible noone has run into this situation, so we can't say the code is correct either. It also gets in the way of a refactor I'm contemplating.
2024-11-12[lldb] (Begin to) support discontinuous lldb_private::Functions (#115730)Pavel Labath
This is the beginning of a different, more fundamental approach to handling. This PR tries to tries to minimize functional changes. It only makes sure that we store the true set of ranges inside the function object, so that subsequent patches can make use of it.
2024-11-01[lldb][NativePDB] Parse global variables. (#114303)Zequan Wu
This doesn't parse S_CONSTANT case yet, because I found that the global variable `std::strong_ordering::equal` is a S_CONSTANT and has type of LF_STRUCTURE which is not currently handled when creating dwarf expression for the variable. Left a TODO for it to finish later. This makes `lldb/test/Shell/SymbolFile/PDB/ast-restore.test` and `lldb/test/Shell/SymbolFile/PDB/calling-conventions-x86.test` pass on windows with native pdb plugin only.
2024-02-19[Reland] Report only loaded debug info in statistics dump (#81706) (#82207)Wanyi
Updates: - The previous patch changed the default behavior to not load dwos in `DWARFUnit` ~~`SymbolFileDWARFDwo *GetDwoSymbolFile(bool load_all_debug_info = false);`~~ `SymbolFileDWARFDwo *GetDwoSymbolFile(bool load_all_debug_info = true);` - This broke some lldb-shell tests (see https://green.lab.llvm.org/green/view/LLDB/job/as-lldb-cmake/16273/) - TestDebugInfoSize.py - with symbol on-demand, by default statistics dump only reports skeleton debug info size - `statistics dump -f` will load all dwos. debug info = skeleton debug info + all dwo debug info Currently running `statistics dump` will trigger lldb to load debug info that's not yet loaded (eg. dwo files). Resulted in a delay in the command return, which, can be interrupting. This patch also added a new option `--load-all-debug-info` asking statistics to dump all possible debug info, which will force loading all debug info available if not yet loaded.
2024-02-17Revert "Report only loaded debug info in statistics dump (#81706)" (#82150)Jonas Devlieghere
This reverts commit 21ddd7ff2b166c5e133b460b1a09ee8adb786ccd because it breaks a bunch of tests: https://lab.llvm.org/buildbot/#/builders/68/builds/69018 https://green.lab.llvm.org/green/view/LLDB/job/as-lldb-cmake/16273
2024-02-17Report only loaded debug info in statistics dump (#81706)Wanyi
Currently running `statistics dump` will trigger lldb to load debug info that's not yet loaded (eg. dwo files). Resulted in a delay in the command return, which, can be interrupting. This patch also added a new option `--load-all-debug-info` asking statistics to dump all possible debug info, which will force loading all debug info available if not yet loaded.
2024-01-16[lldb] Store SupportFile in CompileUnit (NFC)Jonas Devlieghere
Store a SupportFile, rather than a FileSpec, in CompileUnit. This commit works towards having the SourceManager operate on SupportFiles so that it can (1) validate the Checksum and (2) materialize the content of inline source information.
2024-01-04[LLDB][NativePDB] Fix use-after-free error detected by asan.Zequan Wu
2024-01-04Add support for inline DWARF source files. (#75880)Adrian Prantl
LLVM supports DWARF 5 linetable extension to store source files inline in DWARF. This is particularly useful for compiler-generated source code. This implementation tries to materialize them as temporary files lazily, so SBAPI clients don't need to be aware of them. rdar://110926168
2023-12-16[lldb] Use StringRef::{starts,ends}_with (NFC)Kazu Hirata
This patch replaces uses of StringRef::{starts,ends}with with StringRef::{starts,ends}_with for consistency with std::{string,string_view}::{starts,ends}_with in C++20. I'm planning to deprecate and eventually remove StringRef::{starts,ends}with.
2023-12-12[lldb] Make only one function that needs to be implemented when searching ↵Greg Clayton
for types (#74786) This patch revives the effort to get this Phabricator patch into upstream: https://reviews.llvm.org/D137900 This patch was accepted before in Phabricator but I found some -gsimple-template-names issues that are fixed in this patch. A fixed up version of the description from the original patch starts now. This patch started off trying to fix Module::FindFirstType() as it sometimes didn't work. The issue was the SymbolFile plug-ins didn't do any filtering of the matching types they produced, and they only looked up types using the type basename. This means if you have two types with the same basename, your type lookup can fail when only looking up a single type. We would ask the Module::FindFirstType to lookup "Foo::Bar" and it would ask the symbol file to find only 1 type matching the basename "Bar", and then we would filter out any matches that didn't match "Foo::Bar". So if the SymbolFile found "Foo::Bar" first, then it would work, but if it found "Baz::Bar" first, it would return only that type and it would be filtered out. Discovering this issue lead me to think of the patch Alex Langford did a few months ago that was done for finding functions, where he allowed SymbolFile objects to make sure something fully matched before parsing the debug information into an AST type and other LLDB types. So this patch aimed to allow type lookups to also be much more efficient. As LLDB has been developed over the years, we added more ways to to type lookups. These functions have lots of arguments. This patch aims to make one API that needs to be implemented that serves all previous lookups: - Find a single type - Find all types - Find types in a namespace This patch introduces a `TypeQuery` class that contains all of the state needed to perform the lookup which is powerful enough to perform all of the type searches that used to be in our API. It contain a vector of CompilerContext objects that can fully or partially specify the lookup that needs to take place. If you just want to lookup all types with a matching basename, regardless of the containing context, you can specify just a single CompilerContext entry that has a name and a CompilerContextKind mask of CompilerContextKind::AnyType. Or you can fully specify the exact context to use when doing lookups like: CompilerContextKind::Namespace "std" CompilerContextKind::Class "foo" CompilerContextKind::Typedef "size_type" This change expands on the clang modules code that already used a vector<CompilerContext> items, but it modifies it to work with expression type lookups which have contexts, or user lookups where users query for types. The clang modules type lookup is still an option that can be enabled on the `TypeQuery` objects. This mirrors the most recent addition of type lookups that took a vector<CompilerContext> that allowed lookups to happen for the expression parser in certain places. Prior to this we had the following APIs in Module: ``` void Module::FindTypes(ConstString type_name, bool exact_match, size_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, TypeList &types); void Module::FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, TypeMap &types); void Module::FindTypesInNamespace(ConstString type_name, const CompilerDeclContext &parent_decl_ctx, size_t max_matches, TypeList &type_list); ``` The new Module API is much simpler. It gets rid of all three above functions and replaces them with: ``` void FindTypes(const TypeQuery &query, TypeResults &results); ``` The `TypeQuery` class contains all of the needed settings: - The vector<CompilerContext> that allow efficient lookups in the symbol file classes since they can look at basename matches only realize fully matching types. Before this any basename that matched was fully realized only to be removed later by code outside of the SymbolFile layer which could cause many types to be realized when they didn't need to. - If the lookup is exact or not. If not exact, then the compiler context must match the bottom most items that match the compiler context, otherwise it must match exactly - If the compiler context match is for clang modules or not. Clang modules matches include a Module compiler context kind that allows types to be matched only from certain modules and these matches are not needed when d oing user type lookups. - An optional list of languages to use to limit the search to only certain languages The `TypeResults` object contains all state required to do the lookup and store the results: - The max number of matches - The set of SymbolFile objects that have already been searched - The matching type list for any matches that are found The benefits of this approach are: - Simpler API, and only one API to implement in SymbolFile classes - Replaces the FindTypesInNamespace that used a CompilerDeclContext as a way to limit the search, but this only worked if the TypeSystem matched the current symbol file's type system, so you couldn't use it to lookup a type in another module - Fixes a serious bug in our FindFirstType functions where if we were searching for "foo::bar", and we found a "baz::bar" first, the basename would match and we would only fetch 1 type using the basename, only to drop it from the matching list and returning no results
2023-08-09[lldb] Sink StreamFile into lldbHostAlex Langford
StreamFile subclasses Stream (from lldbUtility) and is backed by a File (from lldbHost). It does not depend on anything from lldbCore or any of its sibling libraries, so I think it makes sense for this to live in lldbHost instead. Differential Revision: https://reviews.llvm.org/D157460
2023-08-09[lldb] Sink StreamBuffer into lldbUtilityAlex Langford
lldbUtility seems like a more suitable place for StreamBuffer. Differential Revision: https://reviews.llvm.org/D157463
2023-07-05[lldb] Fix incorrect uses of LLDB_LOG_ERRORJonas Devlieghere
Fix incorrect uses of LLDB_LOG_ERROR. The macro doesn't automatically inject the error in the log message: it merely passes the error as the first argument to formatv and therefore must be referenced with {0}. Thanks to Nicholas Allegra for collecting a list of places where the macro was misused. rdar://111581655 Differential revision: https://reviews.llvm.org/D154530
2023-04-20Reland: [Demangle] replace use of llvm::StringView w/ std::string_viewNick Desaulniers
This reverts commit d81cdb49d74064e88843733e7da92db865943509. This refactoring was waiting on converting LLVM to C++17. Leave StringView.h and cleanup around for subsequent cleanup. Additional fixes for missing std::string_view conversions for MSVC. Reviewed By: MaskRay, DavidSpickett, ayzhao Differential Revision: https://reviews.llvm.org/D148546
2023-04-14Revert D148384 "[Demangle] replace use of llvm::StringView w/ std::string_view"Fangrui Song
This reverts commit 3e559509b426b6aae735a7f57dbdaed1041d2622 and e0c4ffa796b553fa78c638a9584c05ac21fe07d5. This still breaks Windows builds. In addition, `#include <llvm/ADT/StringViewExtras.h>` in llvm/include/llvm/Demangle/ItaniumDemangle.h is a library layering violation (LLVMDemangle is the lowest LLVM library and cannot depend on LLVMSupport).
2023-04-14[Demangle] replace use of llvm::StringView w/ std::string_viewNick Desaulniers
This refactoring was waiting on converting LLVM to C++17. Leave StringView.h and cleanup around for subsequent cleanup. Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D148384
2023-04-14[lldb][ClangExpression] Filter out non-root namespaces in FindNamespaceMichael Buch
**Summary** In a program such as: ``` namespace A { namespace B { struct Bar {}; } } namespace B { struct Foo {}; } ``` ...LLDB would run into issues such as: ``` (lldb) expr ::B::Foo f error: expression failed to parse: error: <user expression 0>:1:6: no type named 'Foo' in namespace 'A::B' ::B::Foo f ~~~~~^ ``` This is because the `SymbolFileDWARF::FindNamespace` implementation will return *any* namespace it finds if the `parent_decl_ctx` provided is empty. In `FindExternalVisibleDecls` we use this API to find the namespace that symbol `B` refers to. If `A::B` happened to be the one that `SymbolFileDWARF::FindNamespace` looked at first, we would try to find `struct Foo` in `A::B`. Hence the error. This patch proposes a new `SymbolFileDWARF::FindNamespace` API that will only find a match for top-level namespaces, which is what `FindExternalVisibleDecls` is attempting anyway; it just never accounted for multiple namespaces of the same name. **Testing** * Added API test-case Differential Revision: https://reviews.llvm.org/D147436
2023-03-17[CodeView] Add source languages ObjC and ObjC++Stefan Gränitz
This patch adds llvm::codeview::SourceLanguage entries, DWARF translations, and PDB source file extensions in LLVM and allow LLDB's PDB parsers to recognize them correctly. The CV_CFL_LANG enum in the Visual Studio 2022 documentation https://learn.microsoft.com/en-us/visualstudio/debugger/debug-interface-access/cv-cfl-lang defines: ``` CV_CFL_OBJC = 0x11, CV_CFL_OBJCXX = 0x12, ``` Since the initial commit in D24317, ObjC was emitted as C language and ObjC++ as Masm. Reviewed By: DavidSpickett Differential Revision: https://reviews.llvm.org/D146221
2023-03-14[lldb] Use *{Set,Map}::contains (NFC)Kazu Hirata
2023-03-06[LLDB][NativePDB] Check string table in PDB files.Zequan Wu
Usually PDB files have a string table (aka: Named Stream "/names" ). PDB for some windows system libraries might not have that. This adds the check for it to avoid crash in the absence of string table. Reviewed By: labath Differential Revision: https://reviews.llvm.org/D145115
2023-01-17[lldb] Only allow SymbolFiles to construct TypesAugusto Noronha
SymbolFiles should own Types by keeping them in their TypeList. This patch privates the Type constructor to guarantee that every created Type is kept in the SymbolFile's type list.
2023-01-09[LLDB] Change formatting to use llvm::formatvAlexander Yermolovich
In preparation for eanbling 64bit support in LLDB switching to use llvm::formatv instead of format MACROs. Reviewed By: labath, JDevlieghere Differential Revision: https://reviews.llvm.org/D139955
2023-01-07[lldb] Use std::optional instead of llvm::Optional (NFC)Kazu Hirata
This patch replaces (llvm::|)Optional< with std::optional<. I'll post a separate patch to clean up the "using" declarations, #include "llvm/ADT/Optional.h", etc. This is part of an effort to migrate from llvm::Optional to std::optional: https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2023-01-07[lldb] Add #include <optional> (NFC)Kazu Hirata
This patch adds #include <optional> to those files containing llvm::Optional<...> or Optional<...>. I'll post a separate patch to actually replace llvm::Optional with std::optional. This is part of an effort to migrate from llvm::Optional to std::optional: https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2022-12-04[lldb] Use std::nullopt instead of None in comments (NFC)Kazu Hirata
This is part of an effort to migrate from llvm::Optional to std::optional: https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2022-12-04[lldb] Use std::nullopt instead of None (NFC)Kazu Hirata
This patch mechanically replaces None with std::nullopt where the compiler would warn if None were deprecated. The intent is to reduce the amount of manual work required in migrating from Optional to std::optional. This is part of an effort to migrate from llvm::Optional to std::optional: https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2022-11-16Make CompilerType safeAdrian Prantl
When a process gets restarted TypeSystem objects associated with it may get deleted, and any CompilerType objects holding on to a reference to that type system are a use-after-free in waiting. Because of the SBAPI, we don't have tight control over where CompilerTypes go and when they are used. This is particularly a problem in the Swift plugin, where the scratch TypeSystem can be restarted while the process is still running. The Swift plugin has a lock to prevent abuse, but where there's a lock there can be bugs. This patch changes CompilerType to store a std::weak_ptr<TypeSystem>. Most of the std::weak_ptr<TypeSystem>* uglyness is hidden by introducing a wrapper class CompilerType::WrappedTypeSystem that has a dyn_cast_or_null() method. The only sites that need to know about the weak pointer implementation detail are the ones that deal with creating TypeSystems. rdar://101505232 Differential Revision: https://reviews.llvm.org/D136650
2022-10-27[LLDB][NativePDB] Fix parameter size for member functions LF_MFUNCTIONZequan Wu
Fix the problem that it was treating member functions as non-member functions when trying to get the parameter size. This causes some non-parameter variables showing up in function signature. Suprisingly, `cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(...))` just sliently parse it without error and gave the wrong result. It's hard to test it. This only causes problem when `params_remaining` is larger than the real parameter size. If it's smaller, we also check individual local variable's attribute to see it's a parameter. When I trying to come up with a test, the parameter size is always 0 if we parse LF_MFUNCTION as LF_PROCEDURE. Reviewed By: labath Differential Revision: https://reviews.llvm.org/D136209
2022-09-27[LLDB][NativePDB] Let native pdb use class layout in debug info.Zequan Wu
Before, class layout in native pdb is not hooked up in [[https://github.com/llvm/llvm-project/blob/main/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp#L9375-L9380 | here]]. This changes hooked it up by refactoring SymbolFileNativePDB and PdbAstBuilder. PdbIndex (corresponds to a single pdb file) is removed from PdbAstBuilder, so it can only be accessed via SymbolFileNativePDB and we can construct PdbAstBuilder with just TypeSystemClang. Reviewed By: labath Differential Revision: https://reviews.llvm.org/D134509
2022-09-16[LLDB][NativePDB] ResolveSymbolContext should return the innermost blockZequan Wu
Before, it returns the outermost blocks if nested blocks have the same address range. That casuses lldb unable to find variables that are inside inner blocks. Reviewed By: labath Differential Revision: https://reviews.llvm.org/D133601
2022-09-12[LLDB][NativePDB] Add local variables with no location info.Zequan Wu
If we don't add local variables with no location info, when trying to print it, lldb won't find it in the its parent DeclContext, which makes lldb to spend more time to search all the way up in DeclContext hierarchy until found same name variable or failed. Dwarf plugin also add local vars even if they don't have location info. Differential Revision: https://reviews.llvm.org/D133626
2022-09-09[LLDB][NativePDB] Replace blocks.cpp with blocks.s so the test won't be ↵Zequan Wu
affected by codegen changes.
2022-09-08[LLDB][NativePDB] Set block address range.Zequan Wu
The block address range was missing before. Differential Revision: https://reviews.llvm.org/D133461
2022-08-17[LLDB][NativePDB] Switch to use DWARFLocationList.Zequan Wu
Before, NativePDB uses scoped range as a workaround for value range, that causes problems (e.g. a variable's value can only have one range, but usually a variable's value is located at different address ranges, each at different locations, in optimized build). This patch let NativePDB switch to DWARFLocationList so a variable's value can be described at multiple non-overlapped address ranges and each range maps to a location. Because overlapping ranges exists, here's peference when choosing ranges: 1. Always prefer whole value locations. Suppose a variable size is 8 bytes, one record is that for range [1, 5) first 4 bytes is at ecx, and another record is that for range [2, 8) the 8 bytes value is at rdx. This results: [1, 2) has first 4 bytes at ecx, [2, 8) has the whole value at rdx. 2. Always prefer the locations parsed later. Suppose first record is that for range [1, 5) value is at ecx, second record is that for range [2, 6) value is at eax. This results: [1, 2) -> ecx, [2, 6) -> eax. Differential Revision: https://reviews.llvm.org/D130796
2022-08-16[LLDB][NativePDB] Add nullptr checking.Zequan Wu
2022-08-16[LLDB][NativePDB] Add nullptr checking.Zequan Wu
2022-08-08[lldb] LLVM_FALLTHROUGH => [[fallthrough]]. NFCFangrui Song
2022-08-04Re-submit "[lldb] Filter DIEs based on qualified name where possible"Alex Langford
This reverts commit 967df65a3610f98a3bc0ec0f2303641d7bad176c. This fixes test/Shell/SymbolFile/NativePDB/find-functions.cpp. When looking up functions with the PDB plugins, if we are looking for a full function name, we should use `GetName` to populate the `name` field instead of `GetLookupName` since `GetName` has the more complete information.
2022-08-04Revert "[lldb] Filter DIEs based on qualified name where possible"Alex Langford
This reverts commit befa77e59a7760d8c4fdd177b234e4a59500f61c. Looks like this broke a SymbolFileNativePDB test. I'll investigate and resubmit with a fix soon.