182 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			182 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- PDBLocationToDWARFExpression.cpp ----------------------------------===//
 | |
| //
 | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | |
| // See https://llvm.org/LICENSE.txt for license information.
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "PDBLocationToDWARFExpression.h"
 | |
| 
 | |
| #include "lldb/Core/Section.h"
 | |
| #include "lldb/Core/StreamBuffer.h"
 | |
| #include "lldb/Core/dwarf.h"
 | |
| #include "lldb/Expression/DWARFExpression.h"
 | |
| #include "lldb/Symbol/Variable.h"
 | |
| #include "lldb/Utility/DataBufferHeap.h"
 | |
| 
 | |
| #include "llvm/DebugInfo/CodeView/CodeView.h"
 | |
| #include "llvm/DebugInfo/PDB/IPDBSession.h"
 | |
| #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
 | |
| 
 | |
| #include "Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h"
 | |
| #include "Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h"
 | |
| 
 | |
| using namespace lldb;
 | |
| using namespace lldb_private;
 | |
| using namespace lldb_private::npdb;
 | |
| using namespace llvm::pdb;
 | |
| 
 | |
| static std::unique_ptr<IPDBFrameData>
 | |
| GetCorrespondingFrameData(const IPDBSession &session,
 | |
|                           const Variable::RangeList &ranges) {
 | |
|   auto enumFrameData = session.getFrameData();
 | |
|   if (!enumFrameData)
 | |
|     return nullptr;
 | |
| 
 | |
|   std::unique_ptr<IPDBFrameData> found;
 | |
|   while (auto fd = enumFrameData->getNext()) {
 | |
|     Range<lldb::addr_t, lldb::addr_t> fdRange(fd->getVirtualAddress(),
 | |
|                                               fd->getLengthBlock());
 | |
| 
 | |
|     for (size_t i = 0; i < ranges.GetSize(); i++) {
 | |
|       auto range = ranges.GetEntryAtIndex(i);
 | |
|       if (!range)
 | |
|         continue;
 | |
| 
 | |
|       if (!range->DoesIntersect(fdRange))
 | |
|         continue;
 | |
| 
 | |
|       found = std::move(fd);
 | |
| 
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return found;
 | |
| }
 | |
| 
 | |
| static bool EmitVFrameEvaluationDWARFExpression(
 | |
|     llvm::StringRef program, llvm::Triple::ArchType arch_type, Stream &stream) {
 | |
|   // VFrame value always stored in $TO pseudo-register
 | |
|   return TranslateFPOProgramToDWARFExpression(program, "$T0", arch_type,
 | |
|                                               stream);
 | |
| }
 | |
| 
 | |
| DWARFExpression ConvertPDBLocationToDWARFExpression(
 | |
|     ModuleSP module, const PDBSymbolData &symbol,
 | |
|     const Variable::RangeList &ranges, bool &is_constant) {
 | |
|   is_constant = true;
 | |
| 
 | |
|   if (!module)
 | |
|     return DWARFExpression();
 | |
| 
 | |
|   const ArchSpec &architecture = module->GetArchitecture();
 | |
|   llvm::Triple::ArchType arch_type = architecture.GetMachine();
 | |
|   ByteOrder byte_order = architecture.GetByteOrder();
 | |
|   uint32_t address_size = architecture.GetAddressByteSize();
 | |
|   uint32_t byte_size = architecture.GetDataByteSize();
 | |
|   if (byte_order == eByteOrderInvalid || address_size == 0)
 | |
|     return DWARFExpression();
 | |
| 
 | |
|   RegisterKind register_kind = eRegisterKindDWARF;
 | |
|   StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);
 | |
|   switch (symbol.getLocationType()) {
 | |
|   case PDB_LocType::Static:
 | |
|   case PDB_LocType::TLS: {
 | |
|     stream.PutHex8(DW_OP_addr);
 | |
| 
 | |
|     SectionList *section_list = module->GetSectionList();
 | |
|     if (!section_list)
 | |
|       return DWARFExpression();
 | |
| 
 | |
|     uint32_t section_id = symbol.getAddressSection();
 | |
| 
 | |
|     auto section = section_list->FindSectionByID(section_id);
 | |
|     if (!section)
 | |
|       return DWARFExpression();
 | |
| 
 | |
|     uint32_t offset = symbol.getAddressOffset();
 | |
|     stream.PutMaxHex64(section->GetFileAddress() + offset, address_size,
 | |
|                        byte_order);
 | |
| 
 | |
|     is_constant = false;
 | |
| 
 | |
|     break;
 | |
|   }
 | |
|   case PDB_LocType::RegRel: {
 | |
|     uint32_t reg_num;
 | |
|     auto reg_id = symbol.getRegisterId();
 | |
|     if (reg_id == llvm::codeview::RegisterId::VFRAME) {
 | |
|       if (auto fd = GetCorrespondingFrameData(symbol.getSession(), ranges)) {
 | |
|         if (EmitVFrameEvaluationDWARFExpression(fd->getProgram(), arch_type,
 | |
|                                                 stream)) {
 | |
|           int32_t offset = symbol.getOffset();
 | |
|           stream.PutHex8(DW_OP_consts);
 | |
|           stream.PutSLEB128(offset);
 | |
|           stream.PutHex8(DW_OP_plus);
 | |
| 
 | |
|           register_kind = eRegisterKindLLDB;
 | |
| 
 | |
|           is_constant = false;
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       register_kind = eRegisterKindGeneric;
 | |
|       reg_num = LLDB_REGNUM_GENERIC_FP;
 | |
|     } else {
 | |
|       register_kind = eRegisterKindLLDB;
 | |
|       reg_num = GetLLDBRegisterNumber(arch_type, reg_id);
 | |
|       if (reg_num == LLDB_INVALID_REGNUM)
 | |
|         return DWARFExpression();
 | |
|     }
 | |
| 
 | |
|     if (reg_num > 31) {
 | |
|       stream.PutHex8(DW_OP_bregx);
 | |
|       stream.PutULEB128(reg_num);
 | |
|     } else
 | |
|       stream.PutHex8(DW_OP_breg0 + reg_num);
 | |
| 
 | |
|     int32_t offset = symbol.getOffset();
 | |
|     stream.PutSLEB128(offset);
 | |
| 
 | |
|     is_constant = false;
 | |
| 
 | |
|     break;
 | |
|   }
 | |
|   case PDB_LocType::Enregistered: {
 | |
|     register_kind = eRegisterKindLLDB;
 | |
|     uint32_t reg_num = GetLLDBRegisterNumber(arch_type, symbol.getRegisterId());
 | |
|     if (reg_num == LLDB_INVALID_REGNUM)
 | |
|       return DWARFExpression();
 | |
| 
 | |
|     if (reg_num > 31) {
 | |
|       stream.PutHex8(DW_OP_regx);
 | |
|       stream.PutULEB128(reg_num);
 | |
|     } else
 | |
|       stream.PutHex8(DW_OP_reg0 + reg_num);
 | |
| 
 | |
|     is_constant = false;
 | |
| 
 | |
|     break;
 | |
|   }
 | |
|   case PDB_LocType::Constant: {
 | |
|     Variant value = symbol.getValue();
 | |
|     stream.PutRawBytes(&value.Value, sizeof(value.Value),
 | |
|                        endian::InlHostByteOrder());
 | |
|     break;
 | |
|   }
 | |
|   default:
 | |
|     return DWARFExpression();
 | |
|   }
 | |
| 
 | |
|   DataBufferSP buffer =
 | |
|       std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());
 | |
|   DataExtractor extractor(buffer, byte_order, address_size, byte_size);
 | |
|   DWARFExpression result(module, extractor, nullptr);
 | |
|   result.SetRegisterKind(register_kind);
 | |
| 
 | |
|   return result;
 | |
| }
 |