xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
15ffd83dbSDimitry Andric //===-- PDBLocationToDWARFExpression.cpp ----------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "PDBLocationToDWARFExpression.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "lldb/Core/Section.h"
120b57cec5SDimitry Andric #include "lldb/Core/dwarf.h"
130b57cec5SDimitry Andric #include "lldb/Expression/DWARFExpression.h"
140b57cec5SDimitry Andric #include "lldb/Symbol/Variable.h"
150b57cec5SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
16*5f757f3fSDimitry Andric #include "lldb/Utility/StreamBuffer.h"
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeView.h"
190b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/IPDBSession.h"
200b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric #include "Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h"
230b57cec5SDimitry Andric #include "Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h"
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric using namespace lldb;
260b57cec5SDimitry Andric using namespace lldb_private;
270b57cec5SDimitry Andric using namespace lldb_private::npdb;
2881ad6265SDimitry Andric using namespace lldb_private::dwarf;
290b57cec5SDimitry Andric using namespace llvm::pdb;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric static std::unique_ptr<IPDBFrameData>
GetCorrespondingFrameData(const IPDBSession & session,const Variable::RangeList & ranges)320b57cec5SDimitry Andric GetCorrespondingFrameData(const IPDBSession &session,
330b57cec5SDimitry Andric                           const Variable::RangeList &ranges) {
340b57cec5SDimitry Andric   auto enumFrameData = session.getFrameData();
350b57cec5SDimitry Andric   if (!enumFrameData)
360b57cec5SDimitry Andric     return nullptr;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric   std::unique_ptr<IPDBFrameData> found;
390b57cec5SDimitry Andric   while (auto fd = enumFrameData->getNext()) {
400b57cec5SDimitry Andric     Range<lldb::addr_t, lldb::addr_t> fdRange(fd->getVirtualAddress(),
410b57cec5SDimitry Andric                                               fd->getLengthBlock());
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric     for (size_t i = 0; i < ranges.GetSize(); i++) {
440b57cec5SDimitry Andric       auto range = ranges.GetEntryAtIndex(i);
450b57cec5SDimitry Andric       if (!range)
460b57cec5SDimitry Andric         continue;
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric       if (!range->DoesIntersect(fdRange))
490b57cec5SDimitry Andric         continue;
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric       found = std::move(fd);
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric       break;
540b57cec5SDimitry Andric     }
550b57cec5SDimitry Andric   }
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   return found;
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric 
EmitVFrameEvaluationDWARFExpression(llvm::StringRef program,llvm::Triple::ArchType arch_type,Stream & stream)600b57cec5SDimitry Andric static bool EmitVFrameEvaluationDWARFExpression(
610b57cec5SDimitry Andric     llvm::StringRef program, llvm::Triple::ArchType arch_type, Stream &stream) {
620b57cec5SDimitry Andric   // VFrame value always stored in $TO pseudo-register
630b57cec5SDimitry Andric   return TranslateFPOProgramToDWARFExpression(program, "$T0", arch_type,
640b57cec5SDimitry Andric                                               stream);
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric 
ConvertPDBLocationToDWARFExpression(ModuleSP module,const PDBSymbolData & symbol,const Variable::RangeList & ranges,bool & is_constant)670b57cec5SDimitry Andric DWARFExpression ConvertPDBLocationToDWARFExpression(
680b57cec5SDimitry Andric     ModuleSP module, const PDBSymbolData &symbol,
690b57cec5SDimitry Andric     const Variable::RangeList &ranges, bool &is_constant) {
700b57cec5SDimitry Andric   is_constant = true;
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   if (!module)
730b57cec5SDimitry Andric     return DWARFExpression();
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   const ArchSpec &architecture = module->GetArchitecture();
760b57cec5SDimitry Andric   llvm::Triple::ArchType arch_type = architecture.GetMachine();
770b57cec5SDimitry Andric   ByteOrder byte_order = architecture.GetByteOrder();
780b57cec5SDimitry Andric   uint32_t address_size = architecture.GetAddressByteSize();
790b57cec5SDimitry Andric   uint32_t byte_size = architecture.GetDataByteSize();
800b57cec5SDimitry Andric   if (byte_order == eByteOrderInvalid || address_size == 0)
810b57cec5SDimitry Andric     return DWARFExpression();
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   RegisterKind register_kind = eRegisterKindDWARF;
840b57cec5SDimitry Andric   StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);
850b57cec5SDimitry Andric   switch (symbol.getLocationType()) {
860b57cec5SDimitry Andric   case PDB_LocType::Static:
870b57cec5SDimitry Andric   case PDB_LocType::TLS: {
880b57cec5SDimitry Andric     stream.PutHex8(DW_OP_addr);
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric     SectionList *section_list = module->GetSectionList();
910b57cec5SDimitry Andric     if (!section_list)
920b57cec5SDimitry Andric       return DWARFExpression();
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric     uint32_t section_id = symbol.getAddressSection();
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric     auto section = section_list->FindSectionByID(section_id);
970b57cec5SDimitry Andric     if (!section)
980b57cec5SDimitry Andric       return DWARFExpression();
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric     uint32_t offset = symbol.getAddressOffset();
1010b57cec5SDimitry Andric     stream.PutMaxHex64(section->GetFileAddress() + offset, address_size,
1020b57cec5SDimitry Andric                        byte_order);
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric     is_constant = false;
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric     break;
1070b57cec5SDimitry Andric   }
1080b57cec5SDimitry Andric   case PDB_LocType::RegRel: {
1090b57cec5SDimitry Andric     uint32_t reg_num;
1100b57cec5SDimitry Andric     auto reg_id = symbol.getRegisterId();
1110b57cec5SDimitry Andric     if (reg_id == llvm::codeview::RegisterId::VFRAME) {
1120b57cec5SDimitry Andric       if (auto fd = GetCorrespondingFrameData(symbol.getSession(), ranges)) {
1130b57cec5SDimitry Andric         if (EmitVFrameEvaluationDWARFExpression(fd->getProgram(), arch_type,
1140b57cec5SDimitry Andric                                                 stream)) {
1150b57cec5SDimitry Andric           int32_t offset = symbol.getOffset();
1160b57cec5SDimitry Andric           stream.PutHex8(DW_OP_consts);
1170b57cec5SDimitry Andric           stream.PutSLEB128(offset);
1180b57cec5SDimitry Andric           stream.PutHex8(DW_OP_plus);
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric           register_kind = eRegisterKindLLDB;
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric           is_constant = false;
1230b57cec5SDimitry Andric           break;
1240b57cec5SDimitry Andric         }
1250b57cec5SDimitry Andric       }
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric       register_kind = eRegisterKindGeneric;
1280b57cec5SDimitry Andric       reg_num = LLDB_REGNUM_GENERIC_FP;
1290b57cec5SDimitry Andric     } else {
1300b57cec5SDimitry Andric       register_kind = eRegisterKindLLDB;
1310b57cec5SDimitry Andric       reg_num = GetLLDBRegisterNumber(arch_type, reg_id);
1320b57cec5SDimitry Andric       if (reg_num == LLDB_INVALID_REGNUM)
1330b57cec5SDimitry Andric         return DWARFExpression();
1340b57cec5SDimitry Andric     }
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric     if (reg_num > 31) {
1370b57cec5SDimitry Andric       stream.PutHex8(DW_OP_bregx);
1380b57cec5SDimitry Andric       stream.PutULEB128(reg_num);
1390b57cec5SDimitry Andric     } else
1400b57cec5SDimitry Andric       stream.PutHex8(DW_OP_breg0 + reg_num);
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric     int32_t offset = symbol.getOffset();
1430b57cec5SDimitry Andric     stream.PutSLEB128(offset);
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric     is_constant = false;
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric     break;
1480b57cec5SDimitry Andric   }
1490b57cec5SDimitry Andric   case PDB_LocType::Enregistered: {
1500b57cec5SDimitry Andric     register_kind = eRegisterKindLLDB;
1510b57cec5SDimitry Andric     uint32_t reg_num = GetLLDBRegisterNumber(arch_type, symbol.getRegisterId());
1520b57cec5SDimitry Andric     if (reg_num == LLDB_INVALID_REGNUM)
1530b57cec5SDimitry Andric       return DWARFExpression();
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric     if (reg_num > 31) {
1560b57cec5SDimitry Andric       stream.PutHex8(DW_OP_regx);
1570b57cec5SDimitry Andric       stream.PutULEB128(reg_num);
1580b57cec5SDimitry Andric     } else
1590b57cec5SDimitry Andric       stream.PutHex8(DW_OP_reg0 + reg_num);
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric     is_constant = false;
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric     break;
1640b57cec5SDimitry Andric   }
1650b57cec5SDimitry Andric   case PDB_LocType::Constant: {
1660b57cec5SDimitry Andric     Variant value = symbol.getValue();
1670b57cec5SDimitry Andric     stream.PutRawBytes(&value.Value, sizeof(value.Value),
1680b57cec5SDimitry Andric                        endian::InlHostByteOrder());
1690b57cec5SDimitry Andric     break;
1700b57cec5SDimitry Andric   }
1710b57cec5SDimitry Andric   default:
1720b57cec5SDimitry Andric     return DWARFExpression();
1730b57cec5SDimitry Andric   }
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   DataBufferSP buffer =
1760b57cec5SDimitry Andric       std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());
1770b57cec5SDimitry Andric   DataExtractor extractor(buffer, byte_order, address_size, byte_size);
178753f127fSDimitry Andric   DWARFExpression result(extractor);
1790b57cec5SDimitry Andric   result.SetRegisterKind(register_kind);
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   return result;
1820b57cec5SDimitry Andric }
183