Coverage Report

Created: 2022-01-18 06:27

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/Architecture/Mips/ArchitectureMips.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- ArchitectureMips.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-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "Plugins/Architecture/Mips/ArchitectureMips.h"
10
#include "lldb/Core/Address.h"
11
#include "lldb/Core/Disassembler.h"
12
#include "lldb/Core/Module.h"
13
#include "lldb/Core/PluginManager.h"
14
#include "lldb/Symbol/Function.h"
15
#include "lldb/Symbol/SymbolContext.h"
16
#include "lldb/Target/SectionLoadList.h"
17
#include "lldb/Target/Target.h"
18
#include "lldb/Utility/ArchSpec.h"
19
#include "lldb/Utility/Log.h"
20
21
using namespace lldb_private;
22
using namespace lldb;
23
24
LLDB_PLUGIN_DEFINE(ArchitectureMips)
25
26
3.44k
void ArchitectureMips::Initialize() {
27
3.44k
  PluginManager::RegisterPlugin(GetPluginNameStatic(),
28
3.44k
                                "Mips-specific algorithms",
29
3.44k
                                &ArchitectureMips::Create);
30
3.44k
}
31
32
3.43k
void ArchitectureMips::Terminate() {
33
3.43k
  PluginManager::UnregisterPlugin(&ArchitectureMips::Create);
34
3.43k
}
35
36
12.2k
std::unique_ptr<Architecture> ArchitectureMips::Create(const ArchSpec &arch) {
37
12.2k
  return arch.IsMIPS() ?
38
12.2k
      
std::unique_ptr<Architecture>(new ArchitectureMips(arch))0
: nullptr;
39
12.2k
}
40
41
addr_t ArchitectureMips::GetCallableLoadAddress(addr_t code_addr,
42
0
                                                AddressClass addr_class) const {
43
0
  bool is_alternate_isa = false;
44
45
0
  switch (addr_class) {
46
0
  case AddressClass::eData:
47
0
  case AddressClass::eDebug:
48
0
    return LLDB_INVALID_ADDRESS;
49
0
  case AddressClass::eCodeAlternateISA:
50
0
    is_alternate_isa = true;
51
0
    break;
52
0
  default: break;
53
0
  }
54
55
0
  if ((code_addr & 2ull) || is_alternate_isa)
56
0
    return code_addr | 1u;
57
0
  return code_addr;
58
0
}
59
60
addr_t ArchitectureMips::GetOpcodeLoadAddress(addr_t opcode_addr,
61
0
                                              AddressClass addr_class) const {
62
0
  switch (addr_class) {
63
0
  case AddressClass::eData:
64
0
  case AddressClass::eDebug:
65
0
    return LLDB_INVALID_ADDRESS;
66
0
  default: break;
67
0
  }
68
0
  return opcode_addr & ~(1ull);
69
0
}
70
71
lldb::addr_t ArchitectureMips::GetBreakableLoadAddress(lldb::addr_t addr,
72
0
                                                       Target &target) const {
73
74
0
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
75
76
0
  Address resolved_addr;
77
78
0
  SectionLoadList &section_load_list = target.GetSectionLoadList();
79
0
  if (section_load_list.IsEmpty())
80
    // No sections are loaded, so we must assume we are not running yet and
81
    // need to operate only on file address.
82
0
    target.ResolveFileAddress(addr, resolved_addr);
83
0
  else
84
0
    target.ResolveLoadAddress(addr, resolved_addr);
85
86
0
  addr_t current_offset = 0;
87
88
  // Get the function boundaries to make sure we don't scan back before the
89
  // beginning of the current function.
90
0
  ModuleSP temp_addr_module_sp(resolved_addr.GetModule());
91
0
  if (temp_addr_module_sp) {
92
0
    SymbolContext sc;
93
0
    SymbolContextItem resolve_scope =
94
0
        eSymbolContextFunction | eSymbolContextSymbol;
95
0
    temp_addr_module_sp->ResolveSymbolContextForAddress(resolved_addr,
96
0
      resolve_scope, sc);
97
0
    Address sym_addr;
98
0
    if (sc.function)
99
0
      sym_addr = sc.function->GetAddressRange().GetBaseAddress();
100
0
    else if (sc.symbol)
101
0
      sym_addr = sc.symbol->GetAddress();
102
103
0
    addr_t function_start = sym_addr.GetLoadAddress(&target);
104
0
    if (function_start == LLDB_INVALID_ADDRESS)
105
0
      function_start = sym_addr.GetFileAddress();
106
107
0
    if (function_start)
108
0
      current_offset = addr - function_start;
109
0
  }
110
111
  // If breakpoint address is start of function then we dont have to do
112
  // anything.
113
0
  if (current_offset == 0)
114
0
    return addr;
115
116
0
  auto insn = GetInstructionAtAddress(target, current_offset, addr);
117
118
0
  if (nullptr == insn || !insn->HasDelaySlot())
119
0
    return addr;
120
121
  // Adjust the breakable address
122
0
  uint64_t breakable_addr = addr - insn->GetOpcode().GetByteSize();
123
0
  LLDB_LOGF(log,
124
0
            "Target::%s Breakpoint at 0x%8.8" PRIx64
125
0
            " is adjusted to 0x%8.8" PRIx64 " due to delay slot\n",
126
0
            __FUNCTION__, addr, breakable_addr);
127
128
0
  return breakable_addr;
129
0
}
130
131
Instruction *ArchitectureMips::GetInstructionAtAddress(
132
0
    Target &target, const Address &resolved_addr, addr_t symbol_offset) const {
133
134
0
  auto loop_count = symbol_offset / 2;
135
136
0
  uint32_t arch_flags = m_arch.GetFlags();
137
0
  bool IsMips16 = arch_flags & ArchSpec::eMIPSAse_mips16;
138
0
  bool IsMicromips = arch_flags & ArchSpec::eMIPSAse_micromips;
139
140
0
  if (loop_count > 3) {
141
    // Scan previous 6 bytes
142
0
    if (IsMips16 | IsMicromips)
143
0
      loop_count = 3;
144
    // For mips-only, instructions are always 4 bytes, so scan previous 4
145
    // bytes only.
146
0
    else
147
0
      loop_count = 2;
148
0
  }
149
150
  // Create Disassembler Instance
151
0
  lldb::DisassemblerSP disasm_sp(
152
0
    Disassembler::FindPlugin(m_arch, nullptr, nullptr));
153
154
0
  InstructionList instruction_list;
155
0
  InstructionSP prev_insn;
156
0
  uint32_t inst_to_choose = 0;
157
158
0
  Address addr = resolved_addr;
159
160
0
  for (uint32_t i = 1; i <= loop_count; i++) {
161
    // Adjust the address to read from.
162
0
    addr.Slide(-2);
163
0
    uint32_t insn_size = 0;
164
165
0
    disasm_sp->ParseInstructions(target, addr,
166
0
                                 {Disassembler::Limit::Bytes, i * 2}, nullptr);
167
168
0
    uint32_t num_insns = disasm_sp->GetInstructionList().GetSize();
169
0
    if (num_insns) {
170
0
      prev_insn = disasm_sp->GetInstructionList().GetInstructionAtIndex(0);
171
0
      insn_size = prev_insn->GetOpcode().GetByteSize();
172
0
      if (i == 1 && insn_size == 2) {
173
        // This looks like a valid 2-byte instruction (but it could be a part
174
        // of upper 4 byte instruction).
175
0
        instruction_list.Append(prev_insn);
176
0
        inst_to_choose = 1;
177
0
      }
178
0
      else if (i == 2) {
179
        // Here we may get one 4-byte instruction or two 2-byte instructions.
180
0
        if (num_insns == 2) {
181
          // Looks like there are two 2-byte instructions above our
182
          // breakpoint target address. Now the upper 2-byte instruction is
183
          // either a valid 2-byte instruction or could be a part of it's
184
          // upper 4-byte instruction. In both cases we don't care because in
185
          // this case lower 2-byte instruction is definitely a valid
186
          // instruction and whatever i=1 iteration has found out is true.
187
0
          inst_to_choose = 1;
188
0
          break;
189
0
        }
190
0
        else if (insn_size == 4) {
191
          // This instruction claims its a valid 4-byte instruction. But it
192
          // could be a part of it's upper 4-byte instruction. Lets try
193
          // scanning upper 2 bytes to verify this.
194
0
          instruction_list.Append(prev_insn);
195
0
          inst_to_choose = 2;
196
0
        }
197
0
      }
198
0
      else if (i == 3) {
199
0
        if (insn_size == 4)
200
          // FIXME: We reached here that means instruction at [target - 4] has
201
          // already claimed to be a 4-byte instruction, and now instruction
202
          // at [target - 6] is also claiming that it's a 4-byte instruction.
203
          // This can not be true. In this case we can not decide the valid
204
          // previous instruction so we let lldb set the breakpoint at the
205
          // address given by user.
206
0
          inst_to_choose = 0;
207
0
        else
208
          // This is straight-forward
209
0
          inst_to_choose = 2;
210
0
        break;
211
0
      }
212
0
    }
213
0
    else {
214
      // Decode failed, bytes do not form a valid instruction. So whatever
215
      // previous iteration has found out is true.
216
0
      if (i > 1) {
217
0
        inst_to_choose = i - 1;
218
0
        break;
219
0
      }
220
0
    }
221
0
  }
222
223
  // Check if we are able to find any valid instruction.
224
0
  if (inst_to_choose) {
225
0
    if (inst_to_choose > instruction_list.GetSize())
226
0
      inst_to_choose--;
227
0
    return instruction_list.GetInstructionAtIndex(inst_to_choose - 1).get();
228
0
  }
229
230
0
  return nullptr;
231
0
}