Coverage Report

Created: 2022-01-18 06:27

/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
314
EmulationStateARM::EmulationStateARM() : m_vfp_regs(), m_memory() {
24
314
  ClearPseudoRegisters();
25
314
}
26
27
314
EmulationStateARM::~EmulationStateARM() = default;
28
29
0
bool EmulationStateARM::LoadPseudoRegistersFromFrame(StackFrame &frame) {
30
0
  RegisterContext *reg_ctx = frame.GetRegisterContext().get();
31
0
  bool success = true;
32
0
  uint32_t reg_num;
33
34
0
  for (int i = dwarf_r0; i < dwarf_r0 + 17; ++i) {
35
0
    reg_num =
36
0
        reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindDWARF, i);
37
0
    const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
38
0
    RegisterValue reg_value;
39
0
    if (reg_ctx->ReadRegister(reg_info, reg_value)) {
40
0
      m_gpr[i - dwarf_r0] = reg_value.GetAsUInt32();
41
0
    } else
42
0
      success = false;
43
0
  }
44
45
0
  for (int i = dwarf_d0; i < dwarf_d0 + 32; ++i) {
46
0
    reg_num =
47
0
        reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindDWARF, i);
48
0
    RegisterValue reg_value;
49
0
    const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
50
51
0
    if (reg_ctx->ReadRegister(reg_info, reg_value)) {
52
0
      uint64_t value = reg_value.GetAsUInt64();
53
0
      uint32_t idx = i - dwarf_d0;
54
0
      if (i < 16) {
55
0
        m_vfp_regs.s_regs[idx * 2] = (uint32_t)value;
56
0
        m_vfp_regs.s_regs[idx * 2 + 1] = (uint32_t)(value >> 32);
57
0
      } else
58
0
        m_vfp_regs.d_regs[idx - 16] = value;
59
0
    } else
60
0
      success = false;
61
0
  }
62
63
0
  return success;
64
0
}
65
66
bool EmulationStateARM::StorePseudoRegisterValue(uint32_t reg_num,
67
15.7k
                                                 uint64_t value) {
68
15.7k
  if (reg_num <= dwarf_cpsr)
69
5.68k
    m_gpr[reg_num - dwarf_r0] = (uint32_t)value;
70
10.0k
  else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) {
71
10.0k
    uint32_t idx = reg_num - dwarf_s0;
72
10.0k
    m_vfp_regs.s_regs[idx] = (uint32_t)value;
73
10.0k
  } else 
if (4
(dwarf_d0 <= reg_num)4
&&
(reg_num <= dwarf_d31)4
) {
74
4
    uint32_t idx = reg_num - dwarf_d0;
75
4
    if (idx < 16) {
76
4
      m_vfp_regs.s_regs[idx * 2] = (uint32_t)value;
77
4
      m_vfp_regs.s_regs[idx * 2 + 1] = (uint32_t)(value >> 32);
78
4
    } else
79
0
      m_vfp_regs.d_regs[idx - 16] = value;
80
4
  } else
81
0
    return false;
82
83
15.7k
  return true;
84
15.7k
}
85
86
uint64_t EmulationStateARM::ReadPseudoRegisterValue(uint32_t reg_num,
87
679
                                                    bool &success) {
88
679
  uint64_t value = 0;
89
679
  success = true;
90
91
679
  if (reg_num <= dwarf_cpsr)
92
670
    value = m_gpr[reg_num - dwarf_r0];
93
9
  else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) {
94
5
    uint32_t idx = reg_num - dwarf_s0;
95
5
    value = m_vfp_regs.d_regs[idx];
96
5
  } else 
if (4
(dwarf_d0 <= reg_num)4
&&
(reg_num <= dwarf_d31)4
) {
97
4
    uint32_t idx = reg_num - dwarf_d0;
98
4
    if (idx < 16)
99
4
      value = (uint64_t)m_vfp_regs.s_regs[idx * 2] |
100
4
              ((uint64_t)m_vfp_regs.s_regs[idx * 2 + 1] >> 32);
101
0
    else
102
0
      value = m_vfp_regs.d_regs[idx - 16];
103
4
  } else
104
0
    success = false;
105
106
679
  return value;
107
679
}
108
109
314
void EmulationStateARM::ClearPseudoRegisters() {
110
5.65k
  for (int i = 0; i < 17; 
++i5.33k
)
111
5.33k
    m_gpr[i] = 0;
112
113
10.3k
  for (int i = 0; i < 32; 
++i10.0k
)
114
10.0k
    m_vfp_regs.s_regs[i] = 0;
115
116
5.33k
  for (int i = 0; i < 16; 
++i5.02k
)
117
5.02k
    m_vfp_regs.d_regs[i] = 0;
118
314
}
119
120
0
void EmulationStateARM::ClearPseudoMemory() { m_memory.clear(); }
121
122
bool EmulationStateARM::StoreToPseudoAddress(lldb::addr_t p_address,
123
119
                                             uint32_t value) {
124
119
  m_memory[p_address] = value;
125
119
  return true;
126
119
}
127
128
uint32_t EmulationStateARM::ReadFromPseudoAddress(lldb::addr_t p_address,
129
73
                                                  bool &success) {
130
73
  std::map<lldb::addr_t, uint32_t>::iterator pos;
131
73
  uint32_t ret_val = 0;
132
133
73
  success = true;
134
73
  pos = m_memory.find(p_address);
135
73
  if (pos != m_memory.end())
136
73
    ret_val = pos->second;
137
0
  else
138
0
    success = false;
139
140
73
  return ret_val;
141
73
}
142
143
size_t EmulationStateARM::ReadPseudoMemory(
144
    EmulateInstruction *instruction, void *baton,
145
    const EmulateInstruction::Context &context, lldb::addr_t addr, void *dst,
146
69
    size_t length) {
147
69
  if (!baton)
148
0
    return 0;
149
150
69
  bool success = true;
151
69
  EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
152
69
  if (length <= 4) {
153
65
    uint32_t value = pseudo_state->ReadFromPseudoAddress(addr, success);
154
65
    if (!success)
155
0
      return 0;
156
157
65
    if (endian::InlHostByteOrder() == lldb::eByteOrderBig)
158
0
      value = llvm::ByteSwap_32(value);
159
65
    *((uint32_t *)dst) = value;
160
65
  } else 
if (4
length == 84
) {
161
4
    uint32_t value1 = pseudo_state->ReadFromPseudoAddress(addr, success);
162
4
    if (!success)
163
0
      return 0;
164
165
4
    uint32_t value2 = pseudo_state->ReadFromPseudoAddress(addr + 4, success);
166
4
    if (!success)
167
0
      return 0;
168
169
4
    if (endian::InlHostByteOrder() == lldb::eByteOrderBig) {
170
0
      value1 = llvm::ByteSwap_32(value1);
171
0
      value2 = llvm::ByteSwap_32(value2);
172
0
    }
173
4
    ((uint32_t *)dst)[0] = value1;
174
4
    ((uint32_t *)dst)[1] = value2;
175
4
  } else
176
0
    success = false;
177
178
69
  if (success)
179
69
    return length;
180
181
0
  return 0;
182
69
}
183
184
size_t EmulationStateARM::WritePseudoMemory(
185
    EmulateInstruction *instruction, void *baton,
186
    const EmulateInstruction::Context &context, lldb::addr_t addr,
187
42
    const void *dst, size_t length) {
188
42
  if (!baton)
189
0
    return 0;
190
191
42
  EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
192
193
42
  if (length <= 4) {
194
38
    uint32_t value;
195
38
    memcpy (&value, dst, sizeof (uint32_t));
196
38
    if (endian::InlHostByteOrder() == lldb::eByteOrderBig)
197
0
      value = llvm::ByteSwap_32(value);
198
199
38
    pseudo_state->StoreToPseudoAddress(addr, value);
200
38
    return length;
201
38
  } else 
if (4
length == 84
) {
202
4
    uint32_t value1;
203
4
    uint32_t value2;
204
4
    memcpy (&value1, dst, sizeof (uint32_t));
205
4
    memcpy(&value2, static_cast<const uint8_t *>(dst) + sizeof(uint32_t),
206
4
           sizeof(uint32_t));
207
4
    if (endian::InlHostByteOrder() == lldb::eByteOrderBig) {
208
0
      value1 = llvm::ByteSwap_32(value1);
209
0
      value2 = llvm::ByteSwap_32(value2);
210
0
    }
211
212
4
    pseudo_state->StoreToPseudoAddress(addr, value1);
213
4
    pseudo_state->StoreToPseudoAddress(addr + 4, value2);
214
4
    return length;
215
4
  }
216
217
0
  return 0;
218
42
}
219
220
bool EmulationStateARM::ReadPseudoRegister(
221
    EmulateInstruction *instruction, void *baton,
222
    const lldb_private::RegisterInfo *reg_info,
223
679
    lldb_private::RegisterValue &reg_value) {
224
679
  if (!baton || !reg_info)
225
0
    return false;
226
227
679
  bool success = true;
228
679
  EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
229
679
  const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF];
230
679
  assert(dwarf_reg_num != LLDB_INVALID_REGNUM);
231
0
  uint64_t reg_uval =
232
679
      pseudo_state->ReadPseudoRegisterValue(dwarf_reg_num, success);
233
234
679
  if (success)
235
679
    success = reg_value.SetUInt(reg_uval, reg_info->byte_size);
236
679
  return success;
237
679
}
238
239
bool EmulationStateARM::WritePseudoRegister(
240
    EmulateInstruction *instruction, void *baton,
241
    const EmulateInstruction::Context &context,
242
    const lldb_private::RegisterInfo *reg_info,
243
360
    const lldb_private::RegisterValue &reg_value) {
244
360
  if (!baton || !reg_info)
245
0
    return false;
246
247
360
  EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
248
360
  const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF];
249
360
  assert(dwarf_reg_num != LLDB_INVALID_REGNUM);
250
0
  return pseudo_state->StorePseudoRegisterValue(dwarf_reg_num,
251
360
                                                reg_value.GetAsUInt64());
252
360
}
253
254
157
bool EmulationStateARM::CompareState(EmulationStateARM &other_state) {
255
157
  bool match = true;
256
257
2.82k
  for (int i = 0; match && i < 17; 
++i2.66k
) {
258
2.66k
    if (m_gpr[i] != other_state.m_gpr[i])
259
0
      match = false;
260
2.66k
  }
261
262
5.18k
  for (int i = 0; match && i < 32; 
++i5.02k
) {
263
5.02k
    if (m_vfp_regs.s_regs[i] != other_state.m_vfp_regs.s_regs[i])
264
0
      match = false;
265
5.02k
  }
266
267
2.66k
  for (int i = 0; match && i < 16; 
++i2.51k
) {
268
2.51k
    if (m_vfp_regs.d_regs[i] != other_state.m_vfp_regs.d_regs[i])
269
0
      match = false;
270
2.51k
  }
271
272
157
  return match;
273
157
}
274
275
bool EmulationStateARM::LoadStateFromDictionary(
276
314
    OptionValueDictionary *test_data) {
277
314
  static ConstString memory_key("memory");
278
314
  static ConstString registers_key("registers");
279
280
314
  if (!test_data)
281
0
    return false;
282
283
314
  OptionValueSP value_sp = test_data->GetValueForKey(memory_key);
284
285
  // Load memory, if present.
286
287
314
  if (value_sp.get() != nullptr) {
288
40
    static ConstString address_key("address");
289
40
    static ConstString data_key("data");
290
40
    uint64_t start_address = 0;
291
292
40
    OptionValueDictionary *mem_dict = value_sp->GetAsDictionary();
293
40
    value_sp = mem_dict->GetValueForKey(address_key);
294
40
    if (value_sp.get() == nullptr)
295
0
      return false;
296
40
    else
297
40
      start_address = value_sp->GetUInt64Value();
298
299
40
    value_sp = mem_dict->GetValueForKey(data_key);
300
40
    OptionValueArray *mem_array = value_sp->GetAsArray();
301
40
    if (!mem_array)
302
0
      return false;
303
304
40
    uint32_t num_elts = mem_array->GetSize();
305
40
    uint32_t address = (uint32_t)start_address;
306
307
113
    for (uint32_t i = 0; i < num_elts; 
++i73
) {
308
73
      value_sp = mem_array->GetValueAtIndex(i);
309
73
      if (value_sp.get() == nullptr)
310
0
        return false;
311
73
      uint64_t value = value_sp->GetUInt64Value();
312
73
      StoreToPseudoAddress(address, value);
313
73
      address = address + 4;
314
73
    }
315
40
  }
316
317
314
  value_sp = test_data->GetValueForKey(registers_key);
318
314
  if (value_sp.get() == nullptr)
319
0
    return false;
320
321
  // Load General Registers
322
323
314
  OptionValueDictionary *reg_dict = value_sp->GetAsDictionary();
324
325
314
  StreamString sstr;
326
5.33k
  for (int i = 0; i < 16; 
++i5.02k
) {
327
5.02k
    sstr.Clear();
328
5.02k
    sstr.Printf("r%d", i);
329
5.02k
    ConstString reg_name(sstr.GetString());
330
5.02k
    value_sp = reg_dict->GetValueForKey(reg_name);
331
5.02k
    if (value_sp.get() == nullptr)
332
0
      return false;
333
5.02k
    uint64_t reg_value = value_sp->GetUInt64Value();
334
5.02k
    StorePseudoRegisterValue(dwarf_r0 + i, reg_value);
335
5.02k
  }
336
337
314
  static ConstString cpsr_name("cpsr");
338
314
  value_sp = reg_dict->GetValueForKey(cpsr_name);
339
314
  if (value_sp.get() == nullptr)
340
0
    return false;
341
314
  StorePseudoRegisterValue(dwarf_cpsr, value_sp->GetUInt64Value());
342
343
  // Load s/d Registers
344
10.3k
  for (int i = 0; i < 32; 
++i10.0k
) {
345
10.0k
    sstr.Clear();
346
10.0k
    sstr.Printf("s%d", i);
347
10.0k
    ConstString reg_name(sstr.GetString());
348
10.0k
    value_sp = reg_dict->GetValueForKey(reg_name);
349
10.0k
    if (value_sp.get() == nullptr)
350
0
      return false;
351
10.0k
    uint64_t reg_value = value_sp->GetUInt64Value();
352
10.0k
    StorePseudoRegisterValue(dwarf_s0 + i, reg_value);
353
10.0k
  }
354
355
314
  return true;
356
314
}