Coverage Report

Created: 2023-09-21 18:56

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- EmulationStateARM.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 "EmulationStateARM.h"
10
11
#include "lldb/Interpreter/OptionValueArray.h"
12
#include "lldb/Interpreter/OptionValueDictionary.h"
13
#include "lldb/Target/RegisterContext.h"
14
#include "lldb/Target/StackFrame.h"
15
#include "lldb/Utility/RegisterValue.h"
16
#include "lldb/Utility/Scalar.h"
17
18
#include "Utility/ARM_DWARF_Registers.h"
19
20
using namespace lldb;
21
using namespace lldb_private;
22
23
320
EmulationStateARM::EmulationStateARM() : m_vfp_regs(), m_memory() {
24
320
  ClearPseudoRegisters();
25
320
}
26
27
320
EmulationStateARM::~EmulationStateARM() = default;
28
29
bool EmulationStateARM::StorePseudoRegisterValue(uint32_t reg_num,
30
16.0k
                                                 uint64_t value) {
31
16.0k
  if (reg_num <= dwarf_cpsr)
32
5.79k
    m_gpr[reg_num - dwarf_r0] = (uint32_t)value;
33
10.2k
  else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) {
34
10.1k
    uint32_t idx = reg_num - dwarf_s0;
35
10.1k
    m_vfp_regs.s_regs[idx] = (uint32_t)value;
36
10.1k
  } else 
if (136
(dwarf_d0 <= reg_num)136
&&
(reg_num <= dwarf_d31)136
) {
37
136
    uint32_t idx = reg_num - dwarf_d0;
38
136
    if (idx < 16) {
39
72
      m_vfp_regs.s_regs[idx * 2] = (uint32_t)value;
40
72
      m_vfp_regs.s_regs[idx * 2 + 1] = (uint32_t)(value >> 32);
41
72
    } else
42
64
      m_vfp_regs.d_regs[idx - 16] = value;
43
136
  } else
44
0
    return false;
45
46
16.0k
  return true;
47
16.0k
}
48
49
uint64_t EmulationStateARM::ReadPseudoRegisterValue(uint32_t reg_num,
50
699
                                                    bool &success) {
51
699
  uint64_t value = 0;
52
699
  success = true;
53
54
699
  if (reg_num <= dwarf_cpsr)
55
682
    value = m_gpr[reg_num - dwarf_r0];
56
17
  else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) {
57
9
    uint32_t idx = reg_num - dwarf_s0;
58
9
    value = m_vfp_regs.s_regs[idx];
59
9
  } else 
if (8
(dwarf_d0 <= reg_num)8
&&
(reg_num <= dwarf_d31)8
) {
60
8
    uint32_t idx = reg_num - dwarf_d0;
61
8
    if (idx < 16)
62
8
      value = (uint64_t)m_vfp_regs.s_regs[idx * 2] |
63
8
              ((uint64_t)m_vfp_regs.s_regs[idx * 2 + 1] << 32);
64
0
    else
65
0
      value = m_vfp_regs.d_regs[idx - 16];
66
8
  } else
67
0
    success = false;
68
69
699
  return value;
70
699
}
71
72
320
void EmulationStateARM::ClearPseudoRegisters() {
73
5.76k
  for (int i = 0; i < 17; 
++i5.44k
)
74
5.44k
    m_gpr[i] = 0;
75
76
10.5k
  for (int i = 0; i < 32; 
++i10.2k
)
77
10.2k
    m_vfp_regs.s_regs[i] = 0;
78
79
5.44k
  for (int i = 0; i < 16; 
++i5.12k
)
80
5.12k
    m_vfp_regs.d_regs[i] = 0;
81
320
}
82
83
0
void EmulationStateARM::ClearPseudoMemory() { m_memory.clear(); }
84
85
bool EmulationStateARM::StoreToPseudoAddress(lldb::addr_t p_address,
86
159
                                             uint32_t value) {
87
159
  m_memory[p_address] = value;
88
159
  return true;
89
159
}
90
91
uint32_t EmulationStateARM::ReadFromPseudoAddress(lldb::addr_t p_address,
92
81
                                                  bool &success) {
93
81
  std::map<lldb::addr_t, uint32_t>::iterator pos;
94
81
  uint32_t ret_val = 0;
95
96
81
  success = true;
97
81
  pos = m_memory.find(p_address);
98
81
  if (pos != m_memory.end())
99
81
    ret_val = pos->second;
100
0
  else
101
0
    success = false;
102
103
81
  return ret_val;
104
81
}
105
106
size_t EmulationStateARM::ReadPseudoMemory(
107
    EmulateInstruction *instruction, void *baton,
108
    const EmulateInstruction::Context &context, lldb::addr_t addr, void *dst,
109
73
    size_t length) {
110
73
  if (!baton)
111
0
    return 0;
112
113
73
  bool success = true;
114
73
  EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
115
73
  if (length <= 4) {
116
65
    uint32_t value = pseudo_state->ReadFromPseudoAddress(addr, success);
117
65
    if (!success)
118
0
      return 0;
119
120
65
    if (endian::InlHostByteOrder() == lldb::eByteOrderBig)
121
0
      value = llvm::byteswap<uint32_t>(value);
122
65
    *((uint32_t *)dst) = value;
123
65
  } else 
if (8
length == 88
) {
124
8
    uint32_t value1 = pseudo_state->ReadFromPseudoAddress(addr, success);
125
8
    if (!success)
126
0
      return 0;
127
128
8
    uint32_t value2 = pseudo_state->ReadFromPseudoAddress(addr + 4, success);
129
8
    if (!success)
130
0
      return 0;
131
132
8
    if (endian::InlHostByteOrder() == lldb::eByteOrderBig) {
133
0
      value1 = llvm::byteswap<uint32_t>(value1);
134
0
      value2 = llvm::byteswap<uint32_t>(value2);
135
0
    }
136
8
    ((uint32_t *)dst)[0] = value1;
137
8
    ((uint32_t *)dst)[1] = value2;
138
8
  } else
139
0
    success = false;
140
141
73
  if (success)
142
73
    return length;
143
144
0
  return 0;
145
73
}
146
147
size_t EmulationStateARM::WritePseudoMemory(
148
    EmulateInstruction *instruction, void *baton,
149
    const EmulateInstruction::Context &context, lldb::addr_t addr,
150
50
    const void *dst, size_t length) {
151
50
  if (!baton)
152
0
    return 0;
153
154
50
  EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
155
156
50
  if (length <= 4) {
157
42
    uint32_t value;
158
42
    memcpy (&value, dst, sizeof (uint32_t));
159
42
    if (endian::InlHostByteOrder() == lldb::eByteOrderBig)
160
0
      value = llvm::byteswap<uint32_t>(value);
161
162
42
    pseudo_state->StoreToPseudoAddress(addr, value);
163
42
    return length;
164
42
  } else 
if (8
length == 88
) {
165
8
    uint32_t value1;
166
8
    uint32_t value2;
167
8
    memcpy (&value1, dst, sizeof (uint32_t));
168
8
    memcpy(&value2, static_cast<const uint8_t *>(dst) + sizeof(uint32_t),
169
8
           sizeof(uint32_t));
170
8
    if (endian::InlHostByteOrder() == lldb::eByteOrderBig) {
171
0
      value1 = llvm::byteswap<uint32_t>(value1);
172
0
      value2 = llvm::byteswap<uint32_t>(value2);
173
0
    }
174
175
8
    pseudo_state->StoreToPseudoAddress(addr, value1);
176
8
    pseudo_state->StoreToPseudoAddress(addr + 4, value2);
177
8
    return length;
178
8
  }
179
180
0
  return 0;
181
50
}
182
183
bool EmulationStateARM::ReadPseudoRegister(
184
    EmulateInstruction *instruction, void *baton,
185
    const lldb_private::RegisterInfo *reg_info,
186
699
    lldb_private::RegisterValue &reg_value) {
187
699
  if (!baton || !reg_info)
188
0
    return false;
189
190
699
  bool success = true;
191
699
  EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
192
699
  const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF];
193
699
  assert(dwarf_reg_num != LLDB_INVALID_REGNUM);
194
699
  uint64_t reg_uval =
195
699
      pseudo_state->ReadPseudoRegisterValue(dwarf_reg_num, success);
196
197
699
  if (success)
198
699
    success = reg_value.SetUInt(reg_uval, reg_info->byte_size);
199
699
  return success;
200
699
}
201
202
bool EmulationStateARM::WritePseudoRegister(
203
    EmulateInstruction *instruction, void *baton,
204
    const EmulateInstruction::Context &context,
205
    const lldb_private::RegisterInfo *reg_info,
206
370
    const lldb_private::RegisterValue &reg_value) {
207
370
  if (!baton || !reg_info)
208
0
    return false;
209
210
370
  EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
211
370
  const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF];
212
370
  assert(dwarf_reg_num != LLDB_INVALID_REGNUM);
213
370
  return pseudo_state->StorePseudoRegisterValue(dwarf_reg_num,
214
370
                                                reg_value.GetAsUInt64());
215
370
}
216
217
bool EmulationStateARM::CompareState(EmulationStateARM &other_state,
218
160
                                     Stream &out_stream) {
219
160
  bool match = true;
220
221
2.88k
  for (int i = 0; match && i < 17; 
++i2.72k
) {
222
2.72k
    if (m_gpr[i] != other_state.m_gpr[i]) {
223
0
      match = false;
224
0
      out_stream.Printf("r%d: 0x%x != 0x%x\n", i, m_gpr[i],
225
0
                        other_state.m_gpr[i]);
226
0
    }
227
2.72k
  }
228
229
5.28k
  for (int i = 0; match && i < 32; 
++i5.12k
) {
230
5.12k
    if (m_vfp_regs.s_regs[i] != other_state.m_vfp_regs.s_regs[i]) {
231
0
      match = false;
232
0
      out_stream.Printf("s%d: 0x%x != 0x%x\n", i, m_vfp_regs.s_regs[i],
233
0
                        other_state.m_vfp_regs.s_regs[i]);
234
0
    }
235
5.12k
  }
236
237
2.72k
  for (int i = 0; match && i < 16; 
++i2.56k
) {
238
2.56k
    if (m_vfp_regs.d_regs[i] != other_state.m_vfp_regs.d_regs[i]) {
239
0
      match = false;
240
0
      out_stream.Printf("d%d: 0x%" PRIx64 " != 0x%" PRIx64 "\n", i + 16,
241
0
                        m_vfp_regs.d_regs[i], other_state.m_vfp_regs.d_regs[i]);
242
0
    }
243
2.56k
  }
244
245
  // other_state is the expected state. If it has memory, check it.
246
160
  if (!other_state.m_memory.empty() && 
m_memory != other_state.m_memory3
) {
247
0
    match = false;
248
0
    out_stream.Printf("memory does not match\n");
249
0
    out_stream.Printf("got memory:\n");
250
0
    for (auto p : m_memory)
251
0
      out_stream.Printf("0x%08" PRIx64 ": 0x%08x\n", p.first, p.second);
252
0
    out_stream.Printf("expected memory:\n");
253
0
    for (auto p : other_state.m_memory)
254
0
      out_stream.Printf("0x%08" PRIx64 ": 0x%08x\n", p.first, p.second);
255
0
  }
256
257
160
  return match;
258
160
}
259
260
bool EmulationStateARM::LoadRegistersStateFromDictionary(
261
960
    OptionValueDictionary *reg_dict, char kind, int first_reg, int num) {
262
960
  StreamString sstr;
263
16.3k
  for (int i = 0; i < num; 
++i15.3k
) {
264
15.6k
    sstr.Clear();
265
15.6k
    sstr.Printf("%c%d", kind, i);
266
15.6k
    OptionValueSP value_sp = reg_dict->GetValueForKey(sstr.GetString());
267
15.6k
    if (value_sp.get() == nullptr)
268
320
      return false;
269
15.3k
    uint64_t reg_value = value_sp->GetValueAs<uint64_t>().value_or(0);
270
15.3k
    StorePseudoRegisterValue(first_reg + i, reg_value);
271
15.3k
  }
272
273
640
  return true;
274
960
}
275
276
bool EmulationStateARM::LoadStateFromDictionary(
277
320
    OptionValueDictionary *test_data) {
278
320
  static constexpr llvm::StringLiteral memory_key("memory");
279
320
  static constexpr llvm::StringLiteral registers_key("registers");
280
281
320
  if (!test_data)
282
0
    return false;
283
284
320
  OptionValueSP value_sp = test_data->GetValueForKey(memory_key);
285
286
  // Load memory, if present.
287
288
320
  if (value_sp.get() != nullptr) {
289
44
    static constexpr llvm::StringLiteral address_key("address");
290
44
    static constexpr llvm::StringLiteral data_key("data");
291
44
    uint64_t start_address = 0;
292
293
44
    OptionValueDictionary *mem_dict = value_sp->GetAsDictionary();
294
44
    value_sp = mem_dict->GetValueForKey(address_key);
295
44
    if (value_sp.get() == nullptr)
296
0
      return false;
297
44
    else
298
44
      start_address = value_sp->GetValueAs<uint64_t>().value_or(0);
299
300
44
    value_sp = mem_dict->GetValueForKey(data_key);
301
44
    OptionValueArray *mem_array = value_sp->GetAsArray();
302
44
    if (!mem_array)
303
0
      return false;
304
305
44
    uint32_t num_elts = mem_array->GetSize();
306
44
    uint32_t address = (uint32_t)start_address;
307
308
145
    for (uint32_t i = 0; i < num_elts; 
++i101
) {
309
101
      value_sp = mem_array->GetValueAtIndex(i);
310
101
      if (value_sp.get() == nullptr)
311
0
        return false;
312
101
      uint64_t value = value_sp->GetValueAs<uint64_t>().value_or(0);
313
101
      StoreToPseudoAddress(address, value);
314
101
      address = address + 4;
315
101
    }
316
44
  }
317
318
320
  value_sp = test_data->GetValueForKey(registers_key);
319
320
  if (value_sp.get() == nullptr)
320
0
    return false;
321
322
  // Load General Registers
323
324
320
  OptionValueDictionary *reg_dict = value_sp->GetAsDictionary();
325
320
  if (!LoadRegistersStateFromDictionary(reg_dict, 'r', dwarf_r0, 16))
326
0
    return false;
327
328
320
  static constexpr llvm::StringLiteral cpsr_name("cpsr");
329
320
  value_sp = reg_dict->GetValueForKey(cpsr_name);
330
320
  if (value_sp.get() == nullptr)
331
0
    return false;
332
320
  StorePseudoRegisterValue(dwarf_cpsr,
333
320
                           value_sp->GetValueAs<uint64_t>().value_or(0));
334
335
  // Load s/d Registers
336
  // To prevent you giving both types in a state and overwriting
337
  // one or the other, we'll expect to get either all S registers,
338
  // or all D registers. Not a mix of the two.
339
320
  bool found_s_registers =
340
320
      LoadRegistersStateFromDictionary(reg_dict, 's', dwarf_s0, 32);
341
320
  bool found_d_registers =
342
320
      LoadRegistersStateFromDictionary(reg_dict, 'd', dwarf_d0, 32);
343
344
320
  return found_s_registers != found_d_registers;
345
320
}