brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.9 KiB · 8a026f8 Raw
130 lines · cpp
1//===-- BreakpointLocationsHandler..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 "DAP.h"10#include "RequestHandler.h"11#include <optional>12#include <vector>13 14namespace lldb_dap {15 16/// The `breakpointLocations` request returns all possible locations for source17/// breakpoints in a given range. Clients should only call this request if the18/// corresponding capability `supportsBreakpointLocationsRequest` is true.19llvm::Expected<protocol::BreakpointLocationsResponseBody>20BreakpointLocationsRequestHandler::Run(21    const protocol::BreakpointLocationsArguments &args) const {22  uint32_t start_line = args.line;23  uint32_t start_column = args.column.value_or(LLDB_INVALID_COLUMN_NUMBER);24  uint32_t end_line = args.endLine.value_or(start_line);25  uint32_t end_column =26      args.endColumn.value_or(std::numeric_limits<uint32_t>::max());27 28  // Find all relevant lines & columns.29  std::vector<std::pair<uint32_t, uint32_t>> locations;30  if (args.source.sourceReference) {31    locations = GetAssemblyBreakpointLocations(*args.source.sourceReference,32                                               start_line, end_line);33  } else {34    std::string path = args.source.path.value_or("");35    locations = GetSourceBreakpointLocations(36        std::move(path), start_line, start_column, end_line, end_column);37  }38 39  // The line entries are sorted by addresses, but we must return the list40  // ordered by line / column position.41  std::sort(locations.begin(), locations.end());42  locations.erase(llvm::unique(locations), locations.end());43 44  std::vector<protocol::BreakpointLocation> breakpoint_locations;45  for (auto &l : locations)46    breakpoint_locations.push_back(47        {l.first, l.second, std::nullopt, std::nullopt});48 49  return protocol::BreakpointLocationsResponseBody{50      /*breakpoints=*/std::move(breakpoint_locations)};51}52 53std::vector<std::pair<uint32_t, uint32_t>>54BreakpointLocationsRequestHandler::GetSourceBreakpointLocations(55    std::string path, uint32_t start_line, uint32_t start_column,56    uint32_t end_line, uint32_t end_column) const {57  std::vector<std::pair<uint32_t, uint32_t>> locations;58  lldb::SBFileSpec file_spec(path.c_str(), true);59  lldb::SBSymbolContextList compile_units =60      dap.target.FindCompileUnits(file_spec);61 62  for (uint32_t c_idx = 0, c_limit = compile_units.GetSize(); c_idx < c_limit;63       ++c_idx) {64    const lldb::SBCompileUnit &compile_unit =65        compile_units.GetContextAtIndex(c_idx).GetCompileUnit();66    if (!compile_unit.IsValid())67      continue;68    lldb::SBFileSpec primary_file_spec = compile_unit.GetFileSpec();69 70    // Go through the line table and find all matching lines / columns71    for (uint32_t l_idx = 0, l_limit = compile_unit.GetNumLineEntries();72         l_idx < l_limit; ++l_idx) {73      lldb::SBLineEntry line_entry = compile_unit.GetLineEntryAtIndex(l_idx);74 75      // Filter by line / column76      uint32_t line = line_entry.GetLine();77      if (line < start_line || line > end_line)78        continue;79      uint32_t column = line_entry.GetColumn();80      if (column == LLDB_INVALID_COLUMN_NUMBER)81        continue;82      if (line == start_line && column < start_column)83        continue;84      if (line == end_line && column > end_column)85        continue;86 87      // Make sure we are in the right file.88      // We might have a match on line & column range and still89      // be in the wrong file, e.g. for included files.90      // Given that the involved pointers point into LLDB's string pool,91      // we can directly compare the `const char*` pointers.92      if (line_entry.GetFileSpec().GetFilename() !=93              primary_file_spec.GetFilename() ||94          line_entry.GetFileSpec().GetDirectory() !=95              primary_file_spec.GetDirectory())96        continue;97 98      locations.emplace_back(line, column);99    }100  }101 102  return locations;103}104 105std::vector<std::pair<uint32_t, uint32_t>>106BreakpointLocationsRequestHandler::GetAssemblyBreakpointLocations(107    int64_t source_reference, uint32_t start_line, uint32_t end_line) const {108  std::vector<std::pair<uint32_t, uint32_t>> locations;109  lldb::SBAddress address(source_reference, dap.target);110  if (!address.IsValid())111    return locations;112 113  lldb::SBSymbol symbol = address.GetSymbol();114  if (!symbol.IsValid())115    return locations;116 117  // start_line is relative to the symbol's start address.118  lldb::SBInstructionList insts = symbol.GetInstructions(dap.target);119  if (insts.GetSize() > (start_line - 1))120    locations.reserve(insts.GetSize() - (start_line - 1));121  for (uint32_t i = start_line - 1; i < insts.GetSize() && i <= (end_line - 1);122       ++i) {123    locations.emplace_back(i, 1);124  }125 126  return locations;127}128 129} // namespace lldb_dap130