diff options
| author | Evgenii Stepanov <eugenis@google.com> | 2019-11-20 17:02:17 -0800 | 
|---|---|---|
| committer | Evgenii Stepanov <eugenis@google.com> | 2019-11-25 15:06:07 -0800 | 
| commit | 9f60820d8416a3e6839624839301a491ddb5d2a0 (patch) | |
| tree | 16112da56ebc1efb8886147bcdb37d3df4e0073a /llvm/lib/DebugInfo | |
| parent | 1c33d7130ef3eec81651d0eaa19bcce8d12c3fb4 (diff) | |
| download | bcm5719-llvm-9f60820d8416a3e6839624839301a491ddb5d2a0.tar.gz bcm5719-llvm-9f60820d8416a3e6839624839301a491ddb5d2a0.zip  | |
llvm-symbolizer: Support loclist in FRAME.
Summary:
Support location lists in FRAME command.
These are used for the majority of local variables in optimized code.
Also support DW_OP_breg in addition to DW_OP_fbreg when it refers to the
same register as DW_AT_frame_base.
Reviewers: pcc, jdoerfert
Subscribers: srhines, hiraditya, rupprecht, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D70629
Diffstat (limited to 'llvm/lib/DebugInfo')
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFContext.cpp | 60 | 
1 files changed, 56 insertions, 4 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp index 012bab35460..0084d3167d5 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -1043,6 +1043,52 @@ static Optional<uint64_t> getTypeSize(DWARFDie Type, uint64_t PointerSize) {    return Optional<uint64_t>();  } +static Optional<int64_t> +getExpressionFrameOffset(ArrayRef<uint8_t> Expr, +                         Optional<unsigned> FrameBaseReg) { +  if (!Expr.empty() && +      (Expr[0] == DW_OP_fbreg || +       (FrameBaseReg && Expr[0] == DW_OP_breg0 + *FrameBaseReg))) { +    unsigned Count; +    int64_t Offset = decodeSLEB128(Expr.data() + 1, &Count, Expr.end()); +    // A single DW_OP_fbreg or DW_OP_breg. +    if (Expr.size() == Count + 1) +      return Offset; +    // Same + DW_OP_deref (Fortran arrays look like this). +    if (Expr.size() == Count + 2 && Expr[Count + 1] == DW_OP_deref) +      return Offset; +    // Fallthrough. Do not accept ex. (DW_OP_breg W29, DW_OP_stack_value) +  } +  return None; +} + +static Optional<int64_t> +getLocationFrameOffset(DWARFCompileUnit *CU, DWARFFormValue &FormValue, +                       Optional<unsigned> FrameBaseReg) { +  if (Optional<ArrayRef<uint8_t>> Location = FormValue.getAsBlock()) { +    return getExpressionFrameOffset(*Location, FrameBaseReg); +  } else if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) { +    uint64_t Offset = *FormValue.getAsSectionOffset(); +    const DWARFLocationTable &LocTable = CU->getLocationTable(); +    Optional<int64_t> FrameOffset; +    Error E = LocTable.visitLocationList( +        &Offset, [&](const DWARFLocationEntry &Entry) { +          if (Entry.Kind == dwarf::DW_LLE_base_address || +              Entry.Kind == dwarf::DW_LLE_base_addressx || +              Entry.Kind == dwarf::DW_LLE_end_of_list) { +            return true; +          } +          if ((FrameOffset = getExpressionFrameOffset(Entry.Loc, FrameBaseReg))) +            return false; +          return true; +        }); +    if (E) +      return None; +    return FrameOffset; +  } +  return None; +} +  void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram,                                     DWARFDie Die, std::vector<DILocal> &Result) {    if (Die.getTag() == DW_TAG_variable || @@ -1051,11 +1097,17 @@ void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram,      if (auto NameAttr = Subprogram.find(DW_AT_name))        if (Optional<const char *> Name = NameAttr->getAsCString())          Local.FunctionName = *Name; + +    Optional<unsigned> FrameBaseReg; +    if (auto FrameBase = Subprogram.find(DW_AT_frame_base)) +      if (Optional<ArrayRef<uint8_t>> Expr = FrameBase->getAsBlock()) +        if (!Expr->empty() && (*Expr)[0] >= DW_OP_reg0 && +            (*Expr)[0] <= DW_OP_reg31) { +          FrameBaseReg = (*Expr)[0] - DW_OP_reg0; +        }      if (auto LocationAttr = Die.find(DW_AT_location)) -      if (Optional<ArrayRef<uint8_t>> Location = LocationAttr->getAsBlock()) -        if (!Location->empty() && (*Location)[0] == DW_OP_fbreg) -          Local.FrameOffset = -              decodeSLEB128(Location->data() + 1, nullptr, Location->end()); +      Local.FrameOffset = getLocationFrameOffset(CU, *LocationAttr, FrameBaseReg); +      if (auto TagOffsetAttr = Die.find(DW_AT_LLVM_tag_offset))        Local.TagOffset = TagOffsetAttr->getAsUnsignedConstant();  | 

