brintos

brintos / llvm-project-archived public Read only

0
0
Text · 35.8 KiB · 6c66d86 Raw
1146 lines · cpp
1//===-- PdbUtil.cpp -------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "PdbUtil.h"10 11#include "DWARFLocationExpression.h"12#include "PdbIndex.h"13#include "PdbSymUid.h"14 15#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"16#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"17#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"18#include "llvm/DebugInfo/PDB/Native/DbiStream.h"19#include "llvm/DebugInfo/PDB/Native/TpiStream.h"20 21#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"22#include "Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h"23#include "lldb/Symbol/Block.h"24#include "lldb/Utility/LLDBAssert.h"25#include "lldb/Utility/LLDBLog.h"26#include "lldb/lldb-enumerations.h"27 28using namespace lldb_private;29using namespace lldb_private::npdb;30using namespace llvm::codeview;31using namespace llvm::pdb;32 33// The returned range list is guaranteed to be sorted and no overlaps between34// adjacent ranges because fields in LocalVariableAddrGap are unsigned integers.35static Variable::RangeList36MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range,37              llvm::ArrayRef<LocalVariableAddrGap> gaps) {38  lldb::addr_t start =39      index.MakeVirtualAddress(range.ISectStart, range.OffsetStart);40  if (start == LLDB_INVALID_ADDRESS)41    return {};42  lldb::addr_t end = start + range.Range;43 44  Variable::RangeList result;45  while (!gaps.empty()) {46    const LocalVariableAddrGap &gap = gaps.front();47    lldb::addr_t gap_start = start + gap.GapStartOffset;48    result.Append(start, gap_start - start);49    start = gap_start + gap.Range;50    gaps = gaps.drop_front();51  }52 53  result.Append(start, end - start);54  return result;55}56 57namespace {58struct MemberLocations {59  std::map<uint64_t, MemberValLocation> offset_to_location;60  DWARFExpression expr;61  bool is_dwarf = false;62 63  MemberLocations() = default;64  MemberLocations(const DWARFExpression &expr) : expr(expr), is_dwarf(true) {}65  MemberLocations(uint64_t offset, const MemberValLocation &member_loc) {66    insert(offset, member_loc);67  }68 69  void insert(uint64_t offset, const MemberValLocation &member_loc) {70    offset_to_location[offset] = member_loc;71  }72 73  struct Comparator {74  public:75    bool operator()(const MemberLocations &, const MemberLocations &) const {76      return false;77    }78  };79};80 81// A range map with address ranges to a map of pair of offset and locaitons.82typedef RangeDataVector<lldb::addr_t, lldb::addr_t, MemberLocations, 0,83                        MemberLocations::Comparator>84    RangeMap;85 86void AddMemberLocationRanges(RangeMap &location_map, uint64_t offset,87                             MemberValLocation member_loc,88                             const Variable::RangeList &ranges) {89  RangeMap new_location_map;90  auto add_overlap_region = [&](lldb::addr_t base, lldb::addr_t end,91                                RangeMap::Entry *entry) {92    RangeMap::Entry overlap_region = {base, end - base, entry->data};93    overlap_region.data.insert(offset, member_loc);94    new_location_map.Append(overlap_region);95  };96 97  for (const auto &range : ranges) {98    lldb::addr_t base = range.GetRangeBase();99    lldb::addr_t end = range.GetRangeEnd();100    uint32_t base_idx = location_map.FindEntryIndexThatContainsOrFollows(base);101    while (auto *entry = location_map.GetMutableEntryAtIndex(base_idx)) {102      if (base >= end || entry->base >= end)103        break;104      if (entry->data.is_dwarf)105        base = entry->GetRangeEnd();106      else {107        lldb::addr_t entry_end = entry->GetRangeEnd();108        if (base > entry->base) {109          if (end < entry_end)110            new_location_map.Append({end, entry_end - end, entry->data});111          add_overlap_region(base, end < entry_end ? end : entry_end, entry);112          entry->SetRangeEnd(base);113        } else if (base < entry->base) {114          new_location_map.Append(115              {base, entry->base - base, {offset, member_loc}});116          if (entry_end == end)117            entry->data.insert(offset, member_loc);118          else {119            add_overlap_region(entry->base, end, entry);120            entry->ShrinkFront(end - entry->base);121          }122        } else {123          if (end < entry_end) {124            new_location_map.Append({end, entry_end, entry->data});125            entry->SetRangeEnd(end);126          }127          entry->data.insert(offset, member_loc);128        }129        base = entry_end;130      }131      ++base_idx;132    }133    if (base >= end)134      continue;135    new_location_map.Append({base, end - base, {offset, member_loc}});136  }137  for (const auto &entry : new_location_map)138    location_map.Append(entry);139  if (!new_location_map.IsEmpty())140    location_map.Sort();141}142 143void AddDwarfRange(RangeMap &location_map, const DWARFExpression &expr,144                   const Variable::RangeList &ranges) {145  if (!expr.IsValid())146    return;147  RangeMap new_location_map;148  for (const auto &range : ranges) {149    lldb::addr_t base = range.GetRangeBase();150    lldb::addr_t end = range.GetRangeEnd();151    uint32_t base_idx = location_map.FindEntryIndexThatContains(base);152    uint32_t end_idx = location_map.FindEntryIndexThatContains(end - 1);153    // range is within an entry.154    if (base_idx == end_idx && base_idx != UINT32_MAX) {155      auto *entry = location_map.GetMutableEntryAtIndex(base_idx);156      if (base > entry->base) {157        new_location_map.Append({entry->base, base - entry->base, entry->data});158        entry->ShrinkFront(base - entry->base);159      }160      if (end == entry->GetRangeEnd())161        entry->data = expr;162      else {163        entry->ShrinkFront(end - base);164        new_location_map.Append({base, end - base, expr});165      }166      continue;167    }168    base_idx = location_map.FindEntryIndexThatContainsOrFollows(base);169    if (auto *entry = location_map.GetMutableEntryAtIndex(base_idx)) {170      if (entry->Contains(base) && entry->base != base) {171        entry->SetRangeEnd(base);172        ++base_idx;173      }174    }175    end_idx = location_map.FindEntryIndexThatContainsOrFollows(end - 1);176    if (auto *entry = location_map.GetMutableEntryAtIndex(end_idx)) {177      if (entry->Contains(end - 1)) {178        if (entry->GetRangeEnd() == end)179          ++end_idx;180        else181          entry->ShrinkFront(end - entry->base);182      }183    }184 185    if (end_idx == UINT32_MAX)186      end_idx = location_map.GetSize();187    // Erase existing ranges covered by new range.188    location_map.Erase(base_idx, end_idx);189    new_location_map.Append({base, end - base, expr});190  }191 192  for (const auto &entry : new_location_map)193    location_map.Append(entry);194  location_map.Sort();195}196} // namespace197 198CVTagRecord CVTagRecord::create(CVType type) {199  assert(IsTagRecord(type) && "type is not a tag record!");200  switch (type.kind()) {201  case LF_CLASS:202  case LF_STRUCTURE:203  case LF_INTERFACE: {204    ClassRecord cr;205    llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(type, cr));206    return CVTagRecord(std::move(cr));207  }208  case LF_UNION: {209    UnionRecord ur;210    llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(type, ur));211    return CVTagRecord(std::move(ur));212  }213  case LF_ENUM: {214    EnumRecord er;215    llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(type, er));216    return CVTagRecord(std::move(er));217  }218  default:219    llvm_unreachable("Unreachable!");220  }221}222 223CVTagRecord::CVTagRecord(ClassRecord &&c)224    : cvclass(std::move(c)),225      m_kind(cvclass.Kind == TypeRecordKind::Struct ? Struct : Class) {}226CVTagRecord::CVTagRecord(UnionRecord &&u)227    : cvunion(std::move(u)), m_kind(Union) {}228CVTagRecord::CVTagRecord(EnumRecord &&e) : cvenum(std::move(e)), m_kind(Enum) {}229 230PDB_SymType lldb_private::npdb::CVSymToPDBSym(SymbolKind kind) {231  switch (kind) {232  case S_COMPILE3:233  case S_OBJNAME:234    return PDB_SymType::CompilandDetails;235  case S_ENVBLOCK:236    return PDB_SymType::CompilandEnv;237  case S_THUNK32:238  case S_TRAMPOLINE:239    return PDB_SymType::Thunk;240  case S_COFFGROUP:241    return PDB_SymType::CoffGroup;242  case S_EXPORT:243    return PDB_SymType::Export;244  case S_LPROC32:245  case S_GPROC32:246  case S_LPROC32_DPC:247    return PDB_SymType::Function;248  case S_PUB32:249    return PDB_SymType::PublicSymbol;250  case S_INLINESITE:251    return PDB_SymType::InlineSite;252  case S_LOCAL:253  case S_BPREL32:254  case S_REGREL32:255  case S_MANCONSTANT:256  case S_CONSTANT:257  case S_LDATA32:258  case S_GDATA32:259  case S_LMANDATA:260  case S_GMANDATA:261  case S_LTHREAD32:262  case S_GTHREAD32:263    return PDB_SymType::Data;264  case S_BLOCK32:265    return PDB_SymType::Block;266  case S_LABEL32:267    return PDB_SymType::Label;268  case S_CALLSITEINFO:269    return PDB_SymType::CallSite;270  case S_HEAPALLOCSITE:271    return PDB_SymType::HeapAllocationSite;272  case S_CALLEES:273    return PDB_SymType::Callee;274  case S_CALLERS:275    return PDB_SymType::Caller;276  default:277    lldbassert(false && "Invalid symbol record kind!");278  }279  return PDB_SymType::None;280}281 282PDB_SymType lldb_private::npdb::CVTypeToPDBType(TypeLeafKind kind) {283  switch (kind) {284  case LF_ARRAY:285    return PDB_SymType::ArrayType;286  case LF_ARGLIST:287    return PDB_SymType::FunctionSig;288  case LF_BCLASS:289    return PDB_SymType::BaseClass;290  case LF_BINTERFACE:291    return PDB_SymType::BaseInterface;292  case LF_CLASS:293  case LF_STRUCTURE:294  case LF_INTERFACE:295  case LF_UNION:296    return PDB_SymType::UDT;297  case LF_POINTER:298    return PDB_SymType::PointerType;299  case LF_ENUM:300    return PDB_SymType::Enum;301  case LF_PROCEDURE:302    return PDB_SymType::FunctionSig;303  case LF_BITFIELD:304    return PDB_SymType::BuiltinType;305  default:306    lldbassert(false && "Invalid type record kind!");307  }308  return PDB_SymType::None;309}310 311bool lldb_private::npdb::SymbolHasAddress(const CVSymbol &sym) {312  switch (sym.kind()) {313  case S_GPROC32:314  case S_LPROC32:315  case S_GPROC32_ID:316  case S_LPROC32_ID:317  case S_LPROC32_DPC:318  case S_LPROC32_DPC_ID:319  case S_THUNK32:320  case S_TRAMPOLINE:321  case S_COFFGROUP:322  case S_BLOCK32:323  case S_LABEL32:324  case S_CALLSITEINFO:325  case S_HEAPALLOCSITE:326  case S_LDATA32:327  case S_GDATA32:328  case S_LMANDATA:329  case S_GMANDATA:330  case S_LTHREAD32:331  case S_GTHREAD32:332    return true;333  default:334    return false;335  }336}337 338bool lldb_private::npdb::SymbolIsCode(const CVSymbol &sym) {339  switch (sym.kind()) {340  case S_GPROC32:341  case S_LPROC32:342  case S_GPROC32_ID:343  case S_LPROC32_ID:344  case S_LPROC32_DPC:345  case S_LPROC32_DPC_ID:346  case S_THUNK32:347  case S_TRAMPOLINE:348  case S_COFFGROUP:349  case S_BLOCK32:350    return true;351  default:352    return false;353  }354}355 356template <typename RecordT> RecordT createRecord(const CVSymbol &sym) {357  RecordT record(static_cast<SymbolRecordKind>(sym.kind()));358  cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record));359  return record;360}361 362template <typename RecordT>363static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) {364  RecordT record = createRecord<RecordT>(sym);365  return {record.Segment, record.CodeOffset};366}367 368template <>369SegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) {370  TrampolineSym record = createRecord<TrampolineSym>(sym);371  return {record.ThunkSection, record.ThunkOffset};372}373 374template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) {375  Thunk32Sym record = createRecord<Thunk32Sym>(sym);376  return {record.Segment, record.Offset};377}378 379template <>380SegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) {381  CoffGroupSym record = createRecord<CoffGroupSym>(sym);382  return {record.Segment, record.Offset};383}384 385template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) {386  DataSym record = createRecord<DataSym>(sym);387  return {record.Segment, record.DataOffset};388}389 390template <>391SegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) {392  ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym);393  return {record.Segment, record.DataOffset};394}395 396SegmentOffset lldb_private::npdb::GetSegmentAndOffset(const CVSymbol &sym) {397  switch (sym.kind()) {398  case S_GPROC32:399  case S_LPROC32:400  case S_GPROC32_ID:401  case S_LPROC32_ID:402  case S_LPROC32_DPC:403  case S_LPROC32_DPC_ID:404    return ::GetSegmentAndOffset<ProcSym>(sym);405  case S_THUNK32:406    return ::GetSegmentAndOffset<Thunk32Sym>(sym);407    break;408  case S_TRAMPOLINE:409    return ::GetSegmentAndOffset<TrampolineSym>(sym);410    break;411  case S_COFFGROUP:412    return ::GetSegmentAndOffset<CoffGroupSym>(sym);413    break;414  case S_BLOCK32:415    return ::GetSegmentAndOffset<BlockSym>(sym);416    break;417  case S_LABEL32:418    return ::GetSegmentAndOffset<LabelSym>(sym);419    break;420  case S_CALLSITEINFO:421    return ::GetSegmentAndOffset<CallSiteInfoSym>(sym);422    break;423  case S_HEAPALLOCSITE:424    return ::GetSegmentAndOffset<HeapAllocationSiteSym>(sym);425    break;426  case S_LDATA32:427  case S_GDATA32:428  case S_LMANDATA:429  case S_GMANDATA:430    return ::GetSegmentAndOffset<DataSym>(sym);431    break;432  case S_LTHREAD32:433  case S_GTHREAD32:434    return ::GetSegmentAndOffset<ThreadLocalDataSym>(sym);435    break;436  default:437    lldbassert(false && "Record does not have a segment/offset!");438  }439  return {0, 0};440}441 442template <typename RecordT>443SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) {444  RecordT record = createRecord<RecordT>(sym);445  return {record.Segment, record.CodeOffset, record.CodeSize};446}447 448template <>449SegmentOffsetLength450GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) {451  TrampolineSym record = createRecord<TrampolineSym>(sym);452  return {record.ThunkSection, record.ThunkOffset, record.Size};453}454 455template <>456SegmentOffsetLength GetSegmentOffsetAndLength<Thunk32Sym>(const CVSymbol &sym) {457  Thunk32Sym record = createRecord<Thunk32Sym>(sym);458  return SegmentOffsetLength{record.Segment, record.Offset, record.Length};459}460 461template <>462SegmentOffsetLength463GetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) {464  CoffGroupSym record = createRecord<CoffGroupSym>(sym);465  return SegmentOffsetLength{record.Segment, record.Offset, record.Size};466}467 468SegmentOffsetLength469lldb_private::npdb::GetSegmentOffsetAndLength(const CVSymbol &sym) {470  switch (sym.kind()) {471  case S_GPROC32:472  case S_LPROC32:473  case S_GPROC32_ID:474  case S_LPROC32_ID:475  case S_LPROC32_DPC:476  case S_LPROC32_DPC_ID:477    return ::GetSegmentOffsetAndLength<ProcSym>(sym);478  case S_THUNK32:479    return ::GetSegmentOffsetAndLength<Thunk32Sym>(sym);480    break;481  case S_TRAMPOLINE:482    return ::GetSegmentOffsetAndLength<TrampolineSym>(sym);483    break;484  case S_COFFGROUP:485    return ::GetSegmentOffsetAndLength<CoffGroupSym>(sym);486    break;487  case S_BLOCK32:488    return ::GetSegmentOffsetAndLength<BlockSym>(sym);489    break;490  default:491    lldbassert(false && "Record does not have a segment/offset/length triple!");492  }493  return {0, 0, 0};494}495 496bool lldb_private::npdb::IsForwardRefUdt(CVType cvt) {497  ClassRecord cr;498  UnionRecord ur;499  EnumRecord er;500  switch (cvt.kind()) {501  case LF_CLASS:502  case LF_STRUCTURE:503  case LF_INTERFACE:504    llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));505    return cr.isForwardRef();506  case LF_UNION:507    llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));508    return ur.isForwardRef();509  case LF_ENUM:510    llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));511    return er.isForwardRef();512  default:513    return false;514  }515}516 517bool lldb_private::npdb::IsTagRecord(llvm::codeview::CVType cvt) {518  switch (cvt.kind()) {519  case LF_CLASS:520  case LF_STRUCTURE:521  case LF_UNION:522  case LF_ENUM:523    return true;524  default:525    return false;526  }527}528 529bool lldb_private::npdb::IsClassStructUnion(llvm::codeview::CVType cvt) {530  switch (cvt.kind()) {531  case LF_CLASS:532  case LF_STRUCTURE:533  case LF_UNION:534    return true;535  default:536    return false;537  }538}539 540bool lldb_private::npdb::IsForwardRefUdt(const PdbTypeSymId &id,541                                         TpiStream &tpi) {542  if (id.is_ipi || id.index.isSimple())543    return false;544  return IsForwardRefUdt(tpi.getType(id.index));545}546 547bool lldb_private::npdb::IsTagRecord(const PdbTypeSymId &id, TpiStream &tpi) {548  if (id.is_ipi || id.index.isSimple())549    return false;550  return IsTagRecord(tpi.getType(id.index));551}552 553lldb::AccessType554lldb_private::npdb::TranslateMemberAccess(MemberAccess access) {555  switch (access) {556  case MemberAccess::Private:557    return lldb::eAccessPrivate;558  case MemberAccess::Protected:559    return lldb::eAccessProtected;560  case MemberAccess::Public:561    return lldb::eAccessPublic;562  case MemberAccess::None:563    return lldb::eAccessNone;564  }565  llvm_unreachable("unreachable");566}567 568TypeIndex lldb_private::npdb::GetFieldListIndex(CVType cvt) {569  switch (cvt.kind()) {570  case LF_CLASS:571  case LF_STRUCTURE:572  case LF_INTERFACE: {573    ClassRecord cr;574    cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));575    return cr.FieldList;576  }577  case LF_UNION: {578    UnionRecord ur;579    cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));580    return ur.FieldList;581  }582  case LF_ENUM: {583    EnumRecord er;584    cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));585    return er.FieldList;586  }587  default:588    llvm_unreachable("Unreachable!");589  }590}591 592TypeIndex lldb_private::npdb::LookThroughModifierRecord(CVType modifier) {593  lldbassert(modifier.kind() == LF_MODIFIER);594  ModifierRecord mr;595  llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(modifier, mr));596  return mr.ModifiedType;597}598 599llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {600  return MSVCUndecoratedNameParser::DropScope(name);601}602 603VariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) {604  VariableInfo result = {};605 606  if (sym.kind() == S_REGREL32) {607    RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);608    cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));609    result.type = reg.Type;610    result.name = reg.Name;611    return result;612  }613 614  if (sym.kind() == S_REGISTER) {615    RegisterSym reg(SymbolRecordKind::RegisterSym);616    cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));617    result.type = reg.Index;618    result.name = reg.Name;619    return result;620  }621 622  if (sym.kind() == S_LOCAL) {623    LocalSym local(SymbolRecordKind::LocalSym);624    cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));625    result.type = local.Type;626    result.name = local.Name;627    result.is_param =628        ((local.Flags & LocalSymFlags::IsParameter) != LocalSymFlags::None);629    return result;630  }631 632  if (sym.kind() == S_GDATA32 || sym.kind() == S_LDATA32) {633    DataSym data(SymbolRecordKind::DataSym);634    cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, data));635    result.type = data.Type;636    result.name = data.Name;637    return result;638  }639 640  if (sym.kind() == S_GTHREAD32 || sym.kind() == S_LTHREAD32) {641    ThreadLocalDataSym data(SymbolRecordKind::ThreadLocalDataSym);642    cantFail(SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, data));643    result.type = data.Type;644    result.name = data.Name;645    return result;646  }647 648  if (sym.kind() == S_CONSTANT) {649    ConstantSym constant(SymbolRecordKind::ConstantSym);650    cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(sym, constant));651    result.type = constant.Type;652    result.name = constant.Name;653    return result;654  }655 656  lldbassert(false && "Invalid variable record kind!");657  return {};658}659 660static llvm::FixedStreamArray<FrameData>::Iterator661GetCorrespondingFrameData(lldb::addr_t load_addr,662                          const DebugFrameDataSubsectionRef &fpo_data,663                          const Variable::RangeList &ranges) {664  lldbassert(!ranges.IsEmpty());665 666  // assume that all variable ranges correspond to one frame data667  using RangeListEntry = Variable::RangeList::Entry;668  const RangeListEntry &range = ranges.GetEntryRef(0);669 670  auto it = fpo_data.begin();671 672  // start by searching first frame data range containing variable range673  for (; it != fpo_data.end(); ++it) {674    RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);675 676    if (fd_range.Contains(range)) {677      break;678    }679  }680 681  // then first most nested entry that still contains variable range682  auto found = it;683  for (; it != fpo_data.end(); ++it) {684    RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);685 686    if (!fd_range.Contains(range)) {687      break;688    }689    found = it;690  }691 692  return found;693}694 695static bool GetFrameDataProgram(PdbIndex &index,696                                const Variable::RangeList &ranges,697                                llvm::StringRef &out_program) {698  const DebugFrameDataSubsectionRef &new_fpo_data =699      index.dbi().getNewFpoRecords();700 701  auto frame_data_it =702      GetCorrespondingFrameData(index.GetLoadAddress(), new_fpo_data, ranges);703  if (frame_data_it == new_fpo_data.end())704    return false;705 706  auto strings = index.pdb().getStringTable();707  if (!strings) {708    consumeError(strings.takeError());709    return false;710  }711  out_program = cantFail(strings->getStringForID(frame_data_it->FrameFunc));712  return true;713}714 715static RegisterId GetBaseFrameRegister(PdbIndex &index,716                                       PdbCompilandSymId frame_proc_id,717                                       bool is_parameter) {718  CVSymbol frame_proc_cvs = index.ReadSymbolRecord(frame_proc_id);719  if (frame_proc_cvs.kind() != S_FRAMEPROC)720    return RegisterId::NONE;721 722  FrameProcSym frame_proc(SymbolRecordKind::FrameProcSym);723  cantFail(SymbolDeserializer::deserializeAs<FrameProcSym>(frame_proc_cvs,724                                                           frame_proc));725 726  CPUType cpu_type = index.compilands()727                         .GetCompiland(frame_proc_id.modi)728                         ->m_compile_opts->Machine;729 730  return is_parameter ? frame_proc.getParamFramePtrReg(cpu_type)731                      : frame_proc.getLocalFramePtrReg(cpu_type);732}733 734VariableInfo lldb_private::npdb::GetVariableLocationInfo(735    PdbIndex &index, PdbCompilandSymId var_id, Block &func_block,736    lldb::ModuleSP module) {737 738  CVSymbol sym = index.ReadSymbolRecord(var_id);739 740  VariableInfo result = GetVariableNameInfo(sym);741 742  if (sym.kind() == S_REGREL32) {743    RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);744    cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));745    result.location = DWARFExpressionList(746        module, MakeRegRelLocationExpression(reg.Register, reg.Offset, module),747        nullptr);748    return result;749  }750 751  if (sym.kind() == S_REGISTER) {752    RegisterSym reg(SymbolRecordKind::RegisterSym);753    cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));754    result.location = DWARFExpressionList(755        module, MakeEnregisteredLocationExpression(reg.Register, module),756        nullptr);757    return result;758  }759 760  if (sym.kind() == S_LOCAL) {761    LocalSym local(SymbolRecordKind::LocalSym);762    if (llvm::Error error =763            SymbolDeserializer::deserializeAs<LocalSym>(sym, local)) {764      llvm::consumeError(std::move(error));765      return result;766    }767 768    PdbCompilandSymId loc_specifier_id(var_id.modi,769                                       var_id.offset + sym.RecordData.size());770    CVSymbol loc_specifier_cvs;771    // Only used for S_DEFRANGE_FRAMEPOINTER_REL.772    RegisterId base_reg = RegisterId::NONE;773    size_t type_size = GetSizeOfType(result.type, index.tpi());774    // A map from offset of a field in parent to size of the field.775    std::map<uint64_t, size_t> offset_to_size;776 777    // When overlaps happens, always prefer the one that doesn't split the value778    // into multiple locations and the location parsed first is perfered.779    RangeMap location_map;780 781    // Iterate through all location records after S_LOCAL. They describe the782    // value of this variable at different locations.783    bool finished = false;784    while (!finished) {785      loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);786      switch (loc_specifier_cvs.kind()) {787      case S_DEFRANGE_FRAMEPOINTER_REL: {788        DefRangeFramePointerRelSym loc(789            SymbolRecordKind::DefRangeFramePointerRelSym);790        if (llvm::Error error =791                SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(792                    loc_specifier_cvs, loc)) {793          llvm::consumeError(std::move(error));794          return result;795        }796        Variable::RangeList raw_ranges =797            MakeRangeList(index, loc.Range, loc.Gaps);798        if (base_reg == RegisterId::NONE) {799          PdbCompilandSymId func_scope_id =800              PdbSymUid(func_block.GetID()).asCompilandSym();801          CVSymbol func_block_cvs = index.ReadSymbolRecord(func_scope_id);802          lldbassert(func_block_cvs.kind() == S_GPROC32 ||803                     func_block_cvs.kind() == S_LPROC32);804          PdbCompilandSymId frame_proc_id(func_scope_id.modi,805                                          func_scope_id.offset +806                                              func_block_cvs.length());807          base_reg =808              GetBaseFrameRegister(index, frame_proc_id, result.is_param);809          if (base_reg == RegisterId::NONE)810            break;811        }812        DWARFExpression expr;813        if (base_reg == RegisterId::VFRAME) {814          llvm::StringRef program;815          if (GetFrameDataProgram(index, raw_ranges, program))816            expr = MakeVFrameRelLocationExpression(program, loc.Hdr.Offset,817                                                   module);818          else {819            // invalid variable820          }821        } else822          expr = MakeRegRelLocationExpression(base_reg, loc.Hdr.Offset, module);823        AddDwarfRange(location_map, expr, raw_ranges);824        break;825      }826      case S_DEFRANGE_REGISTER: {827        DefRangeRegisterSym loc(SymbolRecordKind::DefRangeRegisterSym);828        if (llvm::Error error =829                SymbolDeserializer::deserializeAs<DefRangeRegisterSym>(830                    loc_specifier_cvs, loc)) {831          llvm::consumeError(std::move(error));832          return result;833        }834        RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register;835        Variable::RangeList raw_ranges =836            MakeRangeList(index, loc.Range, loc.Gaps);837        DWARFExpression expr =838            MakeEnregisteredLocationExpression(reg_id, module);839        AddDwarfRange(location_map, expr, raw_ranges);840        break;841      }842      case S_DEFRANGE_REGISTER_REL: {843        DefRangeRegisterRelSym loc(SymbolRecordKind::DefRangeRegisterRelSym);844        if (llvm::Error error =845                SymbolDeserializer::deserializeAs<DefRangeRegisterRelSym>(846                    loc_specifier_cvs, loc)) {847          llvm::consumeError(std::move(error));848          return result;849        }850        Variable::RangeList raw_ranges =851            MakeRangeList(index, loc.Range, loc.Gaps);852        RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register;853        DWARFExpression expr;854        if (reg_id == RegisterId::VFRAME) {855          llvm::StringRef program;856          if (GetFrameDataProgram(index, raw_ranges, program))857            expr = MakeVFrameRelLocationExpression(858                program, loc.Hdr.BasePointerOffset, module);859          else {860            // invalid variable861          }862        } else {863          expr = MakeRegRelLocationExpression(reg_id, loc.Hdr.BasePointerOffset,864                                              module);865        }866        // FIXME: If it's UDT, we need to know the size of the value in byte.867        if (!loc.hasSpilledUDTMember())868          AddDwarfRange(location_map, expr, raw_ranges);869        break;870      }871      case S_DEFRANGE_SUBFIELD_REGISTER: {872        DefRangeSubfieldRegisterSym loc(873            SymbolRecordKind::DefRangeSubfieldRegisterSym);874        if (llvm::Error error =875                SymbolDeserializer::deserializeAs<DefRangeSubfieldRegisterSym>(876                    loc_specifier_cvs, loc)) {877          llvm::consumeError(std::move(error));878          return result;879        }880 881        Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);882        uint32_t reg_size =883            GetRegisterSize((RegisterId)(uint16_t)loc.Hdr.Register);884        if (reg_size == 0)885          break;886        offset_to_size[loc.Hdr.OffsetInParent] = reg_size;887        AddMemberLocationRanges(location_map, loc.Hdr.OffsetInParent,888                                {loc.Hdr.Register, 0, true}, ranges);889        break;890      }891      // FIXME: Handle other kinds. LLVM only generates the 4 types of records892      // above. MSVC generates other location types.893      case S_DEFRANGE:894      case S_DEFRANGE_SUBFIELD:895      case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:896        break;897      default:898        finished = true;899        break;900      }901      loc_specifier_id = PdbCompilandSymId(902          loc_specifier_id.modi,903          loc_specifier_id.offset + loc_specifier_cvs.RecordData.size());904    }905    for (const auto &entry : location_map) {906      DWARFExpression dwarf_expr =907          entry.data.is_dwarf ? entry.data.expr908                              : MakeEnregisteredLocationExpressionForComposite(909                                    entry.data.offset_to_location,910                                    offset_to_size, type_size, module);911 912      result.location.AddExpression(entry.GetRangeBase(), entry.GetRangeEnd(),913                                     dwarf_expr);914    }915    return result;916  }917  llvm_unreachable("Symbol is not a local variable!");918  return result;919}920 921lldb::BasicType922lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) {923  switch (kind) {924  case SimpleTypeKind::Boolean128:925  case SimpleTypeKind::Boolean16:926  case SimpleTypeKind::Boolean32:927  case SimpleTypeKind::Boolean64:928  case SimpleTypeKind::Boolean8:929    return lldb::eBasicTypeBool;930  case SimpleTypeKind::Byte:931  case SimpleTypeKind::UnsignedCharacter:932    return lldb::eBasicTypeUnsignedChar;933  case SimpleTypeKind::NarrowCharacter:934    return lldb::eBasicTypeChar;935  case SimpleTypeKind::SignedCharacter:936  case SimpleTypeKind::SByte:937    return lldb::eBasicTypeSignedChar;938  case SimpleTypeKind::Character16:939    return lldb::eBasicTypeChar16;940  case SimpleTypeKind::Character32:941    return lldb::eBasicTypeChar32;942  case SimpleTypeKind::Character8:943    return lldb::eBasicTypeChar8;944  case SimpleTypeKind::Complex80:945    return lldb::eBasicTypeLongDoubleComplex;946  case SimpleTypeKind::Complex64:947    return lldb::eBasicTypeDoubleComplex;948  case SimpleTypeKind::Complex32:949  case SimpleTypeKind::Complex32PartialPrecision:950    return lldb::eBasicTypeFloatComplex;951  case SimpleTypeKind::Float80:952    return lldb::eBasicTypeLongDouble;953  case SimpleTypeKind::Float128:954    return lldb::eBasicTypeFloat128;955  case SimpleTypeKind::Float64:956    return lldb::eBasicTypeDouble;957  case SimpleTypeKind::Float32:958  case SimpleTypeKind::Float32PartialPrecision:959    return lldb::eBasicTypeFloat;960  case SimpleTypeKind::Float16:961    return lldb::eBasicTypeHalf;962  case SimpleTypeKind::Int128:963  case SimpleTypeKind::Int128Oct:964    return lldb::eBasicTypeInt128;965  case SimpleTypeKind::Int64:966  case SimpleTypeKind::Int64Quad:967    return lldb::eBasicTypeLongLong;968  case SimpleTypeKind::Int32:969    return lldb::eBasicTypeInt;970  case SimpleTypeKind::Int16:971  case SimpleTypeKind::Int16Short:972    return lldb::eBasicTypeShort;973  case SimpleTypeKind::UInt128:974  case SimpleTypeKind::UInt128Oct:975    return lldb::eBasicTypeUnsignedInt128;976  case SimpleTypeKind::UInt64:977  case SimpleTypeKind::UInt64Quad:978    return lldb::eBasicTypeUnsignedLongLong;979  case SimpleTypeKind::HResult:980  case SimpleTypeKind::UInt32:981    return lldb::eBasicTypeUnsignedInt;982  case SimpleTypeKind::UInt16:983  case SimpleTypeKind::UInt16Short:984    return lldb::eBasicTypeUnsignedShort;985  case SimpleTypeKind::Int32Long:986    return lldb::eBasicTypeLong;987  case SimpleTypeKind::UInt32Long:988    return lldb::eBasicTypeUnsignedLong;989  case SimpleTypeKind::Void:990    return lldb::eBasicTypeVoid;991  case SimpleTypeKind::WideCharacter:992    return lldb::eBasicTypeWChar;993 994  // Not supported.995  case SimpleTypeKind::Float48:996  case SimpleTypeKind::Complex16:997  case SimpleTypeKind::Complex48:998  case SimpleTypeKind::Complex128:999  case SimpleTypeKind::NotTranslated:1000  case SimpleTypeKind::None:1001    return lldb::eBasicTypeInvalid;1002  }1003  return lldb::eBasicTypeInvalid;1004}1005 1006size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) {1007  switch (kind) {1008  case SimpleTypeKind::Boolean128:1009  case SimpleTypeKind::Complex128:1010  case SimpleTypeKind::Int128:1011  case SimpleTypeKind::Int128Oct:1012  case SimpleTypeKind::UInt128:1013  case SimpleTypeKind::UInt128Oct:1014  case SimpleTypeKind::Float128:1015    return 16;1016  case SimpleTypeKind::Complex80:1017  case SimpleTypeKind::Float80:1018    return 10;1019  case SimpleTypeKind::Boolean64:1020  case SimpleTypeKind::Complex64:1021  case SimpleTypeKind::UInt64:1022  case SimpleTypeKind::UInt64Quad:1023  case SimpleTypeKind::Float64:1024  case SimpleTypeKind::Int64:1025  case SimpleTypeKind::Int64Quad:1026    return 8;1027  case SimpleTypeKind::Complex48:1028  case SimpleTypeKind::Float48:1029    return 6;1030  case SimpleTypeKind::Boolean32:1031  case SimpleTypeKind::Character32:1032  case SimpleTypeKind::Complex32:1033  case SimpleTypeKind::Complex32PartialPrecision:1034  case SimpleTypeKind::Float32:1035  case SimpleTypeKind::Float32PartialPrecision:1036  case SimpleTypeKind::Int32:1037  case SimpleTypeKind::Int32Long:1038  case SimpleTypeKind::UInt32Long:1039  case SimpleTypeKind::HResult:1040  case SimpleTypeKind::UInt32:1041    return 4;1042  case SimpleTypeKind::Boolean16:1043  case SimpleTypeKind::Character16:1044  case SimpleTypeKind::Complex16:1045  case SimpleTypeKind::Float16:1046  case SimpleTypeKind::Int16:1047  case SimpleTypeKind::Int16Short:1048  case SimpleTypeKind::UInt16:1049  case SimpleTypeKind::UInt16Short:1050  case SimpleTypeKind::WideCharacter:1051    return 2;1052  case SimpleTypeKind::Boolean8:1053  case SimpleTypeKind::Byte:1054  case SimpleTypeKind::UnsignedCharacter:1055  case SimpleTypeKind::NarrowCharacter:1056  case SimpleTypeKind::SignedCharacter:1057  case SimpleTypeKind::SByte:1058  case SimpleTypeKind::Character8:1059    return 1;1060 1061  case SimpleTypeKind::Void:1062  case SimpleTypeKind::None:1063  case SimpleTypeKind::NotTranslated:1064    return 0;1065  }1066  return 0;1067}1068 1069PdbTypeSymId lldb_private::npdb::GetBestPossibleDecl(PdbTypeSymId id,1070                                                     TpiStream &tpi) {1071  if (id.index.isSimple())1072    return id;1073 1074  CVType cvt = tpi.getType(id.index);1075 1076  // Only tag records have a best and a worst record.1077  if (!IsTagRecord(cvt))1078    return id;1079 1080  // Tag records that are not forward decls are full decls, hence they are the1081  // best.1082  if (!IsForwardRefUdt(cvt))1083    return id;1084 1085  return llvm::cantFail(tpi.findFullDeclForForwardRef(id.index));1086}1087 1088template <typename RecordType> static size_t GetSizeOfTypeInternal(CVType cvt) {1089  RecordType record;1090  llvm::cantFail(TypeDeserializer::deserializeAs<RecordType>(cvt, record));1091  return record.getSize();1092}1093 1094size_t lldb_private::npdb::GetSizeOfType(PdbTypeSymId id,1095                                         llvm::pdb::TpiStream &tpi) {1096  if (id.index.isSimple()) {1097    switch (id.index.getSimpleMode()) {1098    case SimpleTypeMode::Direct:1099      return GetTypeSizeForSimpleKind(id.index.getSimpleKind());1100    case SimpleTypeMode::NearPointer32:1101    case SimpleTypeMode::FarPointer32:1102      return 4;1103    case SimpleTypeMode::NearPointer64:1104      return 8;1105    case SimpleTypeMode::NearPointer128:1106      return 16;1107    default:1108      break;1109    }1110    return 0;1111  }1112 1113  TypeIndex index = id.index;1114  if (IsForwardRefUdt(index, tpi))1115    index = llvm::cantFail(tpi.findFullDeclForForwardRef(index));1116 1117  CVType cvt = tpi.getType(index);1118  switch (cvt.kind()) {1119  case LF_MODIFIER:1120    return GetSizeOfType({LookThroughModifierRecord(cvt)}, tpi);1121  case LF_ENUM: {1122    EnumRecord record;1123    llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, record));1124    return GetSizeOfType({record.UnderlyingType}, tpi);1125  }1126  case LF_POINTER:1127    return GetSizeOfTypeInternal<PointerRecord>(cvt);1128  case LF_ARRAY:1129    return GetSizeOfTypeInternal<ArrayRecord>(cvt);1130  case LF_CLASS:1131  case LF_STRUCTURE:1132  case LF_INTERFACE:1133    return GetSizeOfTypeInternal<ClassRecord>(cvt);1134  case LF_UNION:1135    return GetSizeOfTypeInternal<UnionRecord>(cvt);1136  case LF_BITFIELD: {1137    BitFieldRecord record;1138    llvm::cantFail(TypeDeserializer::deserializeAs<BitFieldRecord>(cvt, record));1139    return GetSizeOfType({record.Type}, tpi);1140  }1141  default:1142    break;1143  }1144  return 0;1145}1146