summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2019-03-14 19:05:55 +0000
committerZachary Turner <zturner@google.com>2019-03-14 19:05:55 +0000
commitbb26a7eb113c5a013f4e5d40f72846194dadefeb (patch)
tree9857669080166aa5704b78921f914182252b9e45 /lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
parent2d7458a3514ec2ee2dead0477f5032ef09937a47 (diff)
downloadbcm5719-llvm-bb26a7eb113c5a013f4e5d40f72846194dadefeb.tar.gz
bcm5719-llvm-bb26a7eb113c5a013f4e5d40f72846194dadefeb.zip
Return llvm::Error and llvm::Expected from DWARF parsing code.
The goal here is to improve our error handling and error recovery while parsing DWARF, while at the same time getting us closer to being able to merge LLDB's DWARF parser with LLVM's. To this end, I've udpated several of the low-level parsing functions in LLDB to return llvm::Error and llvm::Expected. For now, this only updates LLDB parsing functions and not LLVM. In some ways, this actually gets us *farther* from parity with the two interfaces, because prior to this patch, at least the parsing interfaces were the same (i.e. they all just returned bools, and now with this patch they're diverging). But, I chose to do this for two primary reasons. LLDB has error logging code engrained deep within some of its parsing functions. We don't want to lose this logging information, but obviously LLVM has no logging mechanism at all. So if we're to merge the interfaces, we have to find a way to still allow LLDB to properly report parsing errors while not having the reporting code be inside of LLVM. LLDB (and indeed, LLVM) overload the meaning of the false return value from all of these extraction functions to mean both "We reached the null entry at the end of a list of items, therefore everything was successful" as well as "something bad and unrecoverable happened during parsing". So you would have a lot code that would do something like: while (foo.extract(...)) { ... } But when the loop stops, why did it stop? Did it stop because it finished parsing, or because there was an error? Because of this, in some cases we don't always know whether it is ok to proceed, or how to proceed, but we were doing it anyway. In this patch, I solve the second problem by introducing an enumeration called DWARFEnumState which has two values MoreItems and Complete. Both of these indicate success, but the latter indicates that we reached the null entry. Then, I return this value instead of bool, and convey parsing failure separately. To solve the first problem (and convey parsing failure) these functions now return either llvm::Error or llvm::Expected<DWARFEnumState>. Having this extra bit of information allows us to properly convey all 3 of "error, bail out", "success, call this function again", and "success, don't call this function again". In subsequent patches I plan to extend this pattern to the rest of the parsing interfaces, which will ultimately get all of the log statements and error reporting out of the low level parsing code and into the high level parsing code (e.g. SymbolFileDWARF, DWARFASTParserClang, etc). Eventually, these same changes will have to be backported to LLVM's DWARF parser, but diverging in the short term is the easiest way to converge in the long term. Differential Revision: https://reviews.llvm.org/D59370 llvm-svn: 356190
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp')
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp71
1 files changed, 40 insertions, 31 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
index c384baafa1a..7f073cbc2a6 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
@@ -11,6 +11,8 @@
#include "lldb/Core/dwarf.h"
#include "lldb/Utility/Stream.h"
+#include "llvm/Object/Error.h"
+
#include "DWARFFormValue.h"
using namespace lldb_private;
@@ -23,41 +25,48 @@ DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration(dw_tag_t tag,
: m_code(InvalidCode), m_tag(tag), m_has_children(has_children),
m_attributes() {}
-bool DWARFAbbreviationDeclaration::Extract(const DWARFDataExtractor &data,
- lldb::offset_t *offset_ptr) {
- return Extract(data, offset_ptr, data.GetULEB128(offset_ptr));
-}
+llvm::Expected<DWARFEnumState>
+DWARFAbbreviationDeclaration::extract(const DWARFDataExtractor &data,
+ lldb::offset_t *offset_ptr) {
+ m_code = data.GetULEB128(offset_ptr);
+ if (m_code == 0)
+ return DWARFEnumState::Complete;
-bool DWARFAbbreviationDeclaration::Extract(const DWARFDataExtractor &data,
- lldb::offset_t *offset_ptr,
- dw_uleb128_t code) {
- m_code = code;
m_attributes.clear();
- if (m_code) {
- m_tag = data.GetULEB128(offset_ptr);
- m_has_children = data.GetU8(offset_ptr);
-
- while (data.ValidOffset(*offset_ptr)) {
- dw_attr_t attr = data.GetULEB128(offset_ptr);
- dw_form_t form = data.GetULEB128(offset_ptr);
- DWARFFormValue::ValueType val;
-
- if (form == DW_FORM_implicit_const)
- val.value.sval = data.GetULEB128(offset_ptr);
-
- if (attr && form)
- m_attributes.push_back(DWARFAttribute(attr, form, val));
- else
- break;
- }
-
- return m_tag != 0;
- } else {
- m_tag = 0;
- m_has_children = 0;
+ m_tag = data.GetULEB128(offset_ptr);
+ if (m_tag == DW_TAG_null) {
+ // FIXME: According to the DWARF spec this may actually be malformed.
+ // Should this return an error instead?
+ return DWARFEnumState::Complete;
+ }
+
+ m_has_children = data.GetU8(offset_ptr);
+
+ while (data.ValidOffset(*offset_ptr)) {
+ dw_attr_t attr = data.GetULEB128(offset_ptr);
+ dw_form_t form = data.GetULEB128(offset_ptr);
+
+ // This is the last attribute for this abbrev decl, but there may still be
+ // more abbrev decls, so return MoreItems to indicate to the caller that
+ // they should call this function again.
+ if (!attr && !form)
+ return DWARFEnumState::MoreItems;
+
+ if (!attr || !form)
+ return llvm::make_error<llvm::object::GenericBinaryError>(
+ "malformed abbreviation declaration attribute");
+
+ DWARFFormValue::ValueType val;
+
+ if (form == DW_FORM_implicit_const)
+ val.value.sval = data.GetULEB128(offset_ptr);
+
+ m_attributes.push_back(DWARFAttribute(attr, form, val));
}
- return false;
+ return llvm::make_error<llvm::object::GenericBinaryError>(
+ "abbreviation declaration attribute list not terminated with a null "
+ "entry");
}
void DWARFAbbreviationDeclaration::Dump(Stream *s) const {
OpenPOWER on IntegriCloud