summaryrefslogtreecommitdiffstats
path: root/tester/covoar/AddressToLineMapper.cc
blob: 838b156c12f3bb41adc3846134e2e0867c4dde68 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/*! @file AddressToLineMapper.cc
 *  @brief AddressToLineMapper Implementation
 *
 *  This file contains the implementation of the functionality
 *  of the AddressToLineMapper class.
 */

#include "AddressToLineMapper.h"

namespace Coverage {

  uint64_t SourceLine::location() const
  {
    return address;
  }

  bool SourceLine::is_an_end_sequence() const
  {
    return is_end_sequence;
  }

  const std::string SourceLine::path() const
  {
    if (!path_) {
      return "unknown";
    } else {
      return *path_;
    }
  }

  int SourceLine::line() const
  {
    return line_num;
  }

  void AddressLineRange::addSourceLine(const rld::dwarf::address& address)
  {
    auto insertResult = sourcePaths.insert(
      std::make_shared<std::string>(address.path()));

    sourceLines.emplace_back(
      SourceLine (
        address.location(),
        *insertResult.first,
        address.line(),
        address.is_an_end_sequence()
      )
    );
  }

  const SourceLine& AddressLineRange::getSourceLine(uint32_t address) const
  {
    if (address < lowAddress || address > highAddress) {
      throw SourceNotFoundError(std::to_string(address));
    }

    const SourceLine* last_line = nullptr;
    for (const auto &line : sourceLines) {
      if (address <= line.location())
      {
        if (address == line.location())
          last_line = &line;
        break;
      }
      last_line = &line;
    }

    if (last_line == nullptr) {
      throw SourceNotFoundError(std::to_string(address));
    }

    return *last_line;
  }

  void AddressToLineMapper::getSource(
    uint32_t address,
    std::string& sourceFile,
    int& sourceLine
  ) const {
    const SourceLine default_sourceline = SourceLine();
    const SourceLine* match = &default_sourceline;

    for (const auto &range : addressLineRanges) {
      try {
        const SourceLine& potential_match = range.getSourceLine(address);

        if (match->is_an_end_sequence() || !potential_match.is_an_end_sequence()) {
          match = &potential_match;
        }
      } catch (const AddressLineRange::SourceNotFoundError&) {}
    }

    sourceFile = match->path();
    sourceLine = match->line();
  }

  AddressLineRange& AddressToLineMapper::makeRange(
    uint32_t low,
    uint32_t high
  )
  {
    addressLineRanges.emplace_back(
      AddressLineRange(low, high)
    );

    return addressLineRanges.back();
  }

}