LLDB mainline
UnwindAssemblyInstEmulation.cpp
Go to the documentation of this file.
1//===-- UnwindAssemblyInstEmulation.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
10
11#include "lldb/Core/Address.h"
18#include "lldb/Target/Process.h"
19#include "lldb/Target/Target.h"
20#include "lldb/Target/Thread.h"
25#include "lldb/Utility/Log.h"
26#include "lldb/Utility/Status.h"
28#include "llvm/ADT/SmallSet.h"
29#include <deque>
30
31using namespace lldb;
32using namespace lldb_private;
33
35
36// UnwindAssemblyInstEmulation method definitions
37
39 AddressRange &range, Thread &thread, UnwindPlan &unwind_plan) {
40 std::vector<uint8_t> function_text(range.GetByteSize());
41 ProcessSP process_sp(thread.GetProcess());
42 if (process_sp) {
44 if (process_sp->GetTarget().ReadMemory(
45 range.GetBaseAddress(), function_text.data(), range.GetByteSize(),
46 error) != range.GetByteSize()) {
47 return false;
48 }
49 }
51 range, function_text.data(), function_text.size(), unwind_plan);
52}
53
54static void DumpUnwindRowsToLog(Log *log, AddressRange range,
55 const UnwindPlan &unwind_plan) {
56 if (!log || !log->GetVerbose())
57 return;
58 StreamString strm;
59 lldb::addr_t base_addr = range.GetBaseAddress().GetFileAddress();
60 strm.Printf("Resulting unwind rows for [0x%" PRIx64 " - 0x%" PRIx64 "):",
61 base_addr, base_addr + range.GetByteSize());
62 unwind_plan.Dump(strm, nullptr, base_addr);
63 log->PutString(strm.GetString());
64}
65
66static void DumpInstToLog(Log *log, Instruction &inst,
67 const InstructionList &inst_list) {
68 if (!log || !log->GetVerbose())
69 return;
70 const bool show_address = true;
71 const bool show_bytes = true;
72 const bool show_control_flow_kind = false;
73 StreamString strm;
75 FormatEntity::Parse("${frame.pc}: ", format);
76 inst.Dump(&strm, inst_list.GetMaxOpcocdeByteSize(), show_address, show_bytes,
77 show_control_flow_kind, nullptr, nullptr, nullptr, &format, 0);
78 log->PutString(strm.GetString());
79}
80
82 AddressRange &range, uint8_t *opcode_data, size_t opcode_size,
83 UnwindPlan &unwind_plan) {
84 if (opcode_data == nullptr || opcode_size == 0)
85 return false;
86
87 if (range.GetByteSize() == 0 || !range.GetBaseAddress().IsValid() ||
89 return false;
90
91 // The instruction emulation subclass setup the unwind plan for the first
92 // instruction.
93 m_inst_emulator_up->CreateFunctionEntryUnwind(unwind_plan);
94
95 // CreateFunctionEntryUnwind should have created the first row. If it doesn't,
96 // then we are done.
97 if (unwind_plan.GetRowCount() == 0)
98 return false;
99
100 const bool prefer_file_cache = true;
102 m_arch, nullptr, nullptr, nullptr, nullptr, range.GetBaseAddress(),
103 opcode_data, opcode_size, 99999, prefer_file_cache));
104
105 if (!disasm_sp)
106 return false;
107
108 Log *log = GetLog(LLDBLog::Unwind);
109
110 m_range_ptr = &range;
111 m_unwind_plan_ptr = &unwind_plan;
112
113 m_state.cfa_reg_info = *m_inst_emulator_up->GetRegisterInfo(
114 unwind_plan.GetRegisterKind(), unwind_plan.GetInitialCFARegister());
115 m_state.fp_is_cfa = false;
116 m_state.register_values.clear();
117
118 m_pushed_regs.clear();
119
120 RegisterValue cfa_reg_value;
121 cfa_reg_value.SetUInt(m_initial_cfa, m_state.cfa_reg_info.byte_size);
122 SetRegisterValue(m_state.cfa_reg_info, cfa_reg_value);
123
124 InstructionList inst_list = disasm_sp->GetInstructionList();
125
126 if (inst_list.GetSize() == 0) {
127 DumpUnwindRowsToLog(log, range, unwind_plan);
128 return unwind_plan.GetRowCount() > 0;
129 }
130
131 Instruction &first_inst = *inst_list.GetInstructionAtIndex(0);
132 const lldb::addr_t base_addr = first_inst.GetAddress().GetFileAddress();
133
134 // Map for storing the unwind state at a given offset. When we see a forward
135 // branch we add a new entry to this map with the actual unwind plan row and
136 // register context for the target address of the branch as the current data
137 // have to be valid for the target address of the branch too if we are in
138 // the same function.
139 std::map<lldb::addr_t, UnwindState> saved_unwind_states;
140
141 // Make a copy of the current instruction Row and save it in m_state so
142 // we can add updates as we process the instructions.
143 m_state.row = *unwind_plan.GetLastRow();
144
145 // Add the initial state to the save list with offset 0.
146 auto condition_block_start_state =
147 saved_unwind_states.emplace(0, m_state).first;
148
149 // The architecture dependent condition code of the last processed
150 // instruction.
153
154 std::deque<std::size_t> to_visit = {0};
155 llvm::SmallSet<std::size_t, 0> enqueued = {0};
156
157 // Instructions reachable through jumps are inserted on the front.
158 // The next instruction is inserted on the back.
159 // Pop from the back to ensure non-branching instructions are visited
160 // sequentially.
161 while (!to_visit.empty()) {
162 const std::size_t current_index = to_visit.back();
163 Instruction &inst = *inst_list.GetInstructionAtIndex(current_index);
164 to_visit.pop_back();
165 DumpInstToLog(log, inst, inst_list);
166
167 m_curr_row_modified = false;
168 m_branch_offset = 0;
169
170 lldb::addr_t current_offset =
171 inst.GetAddress().GetFileAddress() - base_addr;
172 auto it = saved_unwind_states.upper_bound(current_offset);
173 assert(it != saved_unwind_states.begin() &&
174 "Unwind row for the function entry missing");
175 --it; // Move it to the row corresponding to the current offset
176
177 // When state is forwarded through a branch, the offset of m_state.row is
178 // different from the offset available in saved_unwind_states. Use the
179 // forwarded state in this case, as the previous instruction may have been
180 // an unconditional jump.
181 // FIXME: this assignment can always be done unconditionally.
182 if (it->second.row.GetOffset() != m_state.row.GetOffset())
183 m_state = it->second;
184
185 m_inst_emulator_up->SetInstruction(inst.GetOpcode(), inst.GetAddress(),
186 nullptr);
187 const EmulateInstruction::InstructionCondition new_condition =
188 m_inst_emulator_up->GetInstructionCondition();
189
190 if (last_condition != new_condition) {
191 // If the last instruction was conditional with a different condition
192 // than the current condition then restore the state.
193 if (last_condition != EmulateInstruction::UnconditionalCondition) {
194 m_state = condition_block_start_state->second;
195 m_state.row.SetOffset(current_offset);
196 // The last instruction might already created a row for this offset
197 // and we want to overwrite it.
198 saved_unwind_states.insert_or_assign(current_offset, m_state);
199 }
200
201 // We are starting a new conditional block at the actual offset
202 condition_block_start_state = it;
203 }
204
205 last_condition = new_condition;
206
207 m_inst_emulator_up->EvaluateInstruction(
208 eEmulateInstructionOptionIgnoreConditions);
209
210 // If the current instruction is a branch forward then save the current
211 // CFI information for the offset where we are branching.
212 Address branch_address = inst.GetAddress();
213 branch_address.Slide(m_branch_offset);
214 if (m_branch_offset != 0 &&
215 range.ContainsFileAddress(branch_address.GetFileAddress())) {
216 if (auto [it, inserted] = saved_unwind_states.emplace(
217 current_offset + m_branch_offset, m_state);
218 inserted) {
219 it->second.row.SetOffset(current_offset + m_branch_offset);
220 if (std::size_t dest_instr_index =
221 inst_list.GetIndexOfInstructionAtAddress(branch_address);
222 dest_instr_index < inst_list.GetSize()) {
223 to_visit.push_front(dest_instr_index);
224 enqueued.insert(dest_instr_index);
225 }
226 }
227 }
228
229 // If inst is a barrier, do not propagate state to the next instruction.
230 if (inst.IsBarrier())
231 continue;
232
233 // Were there any changes to the CFI while evaluating this instruction?
235 // Save the modified row if we don't already have a CFI row in the
236 // current address
237 const lldb::addr_t next_inst_offset =
238 current_offset + inst.GetOpcode().GetByteSize();
239 if (saved_unwind_states.count(next_inst_offset) == 0) {
240 m_state.row.SetOffset(next_inst_offset);
241 saved_unwind_states.emplace(next_inst_offset, m_state);
242 }
243 }
244
245 const size_t next_idx = current_index + 1;
246 const bool never_enqueued = enqueued.insert(next_idx).second;
247 if (never_enqueued && next_idx < inst_list.GetSize())
248 to_visit.push_back(next_idx);
249 }
250
251 for (auto &[_, state] : saved_unwind_states)
252 unwind_plan.InsertRow(std::move(state.row),
253 /*replace_existing=*/true);
254
255 DumpUnwindRowsToLog(log, range, unwind_plan);
256 return unwind_plan.GetRowCount() > 0;
257}
258
260 AddressRange &func, Thread &thread, UnwindPlan &unwind_plan) {
261 return false;
262}
263
265 Thread &thread,
266 UnwindPlan &unwind_plan) {
267 return false;
268}
269
271 AddressRange &func, const ExecutionContext &exe_ctx,
272 Address &first_non_prologue_insn) {
273 return false;
274}
275
278 std::unique_ptr<EmulateInstruction> inst_emulator_up(
280 nullptr));
281 // Make sure that all prologue instructions are handled
282 if (inst_emulator_up)
283 return new UnwindAssemblyInstEmulation(arch, inst_emulator_up.release());
284 return nullptr;
285}
286
291
295
297 return "Instruction emulation based unwind information.";
298}
299
301 const RegisterInfo &reg_info) {
302 lldb::RegisterKind reg_kind;
303 uint32_t reg_num;
305 reg_num))
306 return (uint64_t)reg_kind << 24 | reg_num;
307 return 0ull;
308}
309
311 const RegisterInfo &reg_info, const RegisterValue &reg_value) {
312 m_state.register_values[MakeRegisterKindValuePair(reg_info)] = reg_value;
313}
314
316 RegisterValue &reg_value) {
317 const uint64_t reg_id = MakeRegisterKindValuePair(reg_info);
318 RegisterValueMap::const_iterator pos = m_state.register_values.find(reg_id);
319 if (pos != m_state.register_values.end()) {
320 reg_value = pos->second;
321 return true; // We had a real value that comes from an opcode that wrote
322 // to it...
323 }
324 // We are making up a value that is recognizable...
325 reg_value.SetUInt(reg_id, reg_info.byte_size);
326 return false;
327}
328
330 EmulateInstruction *instruction, void *baton,
331 const EmulateInstruction::Context &context, lldb::addr_t addr, void *dst,
332 size_t dst_len) {
333 Log *log = GetLog(LLDBLog::Unwind);
334
335 if (log && log->GetVerbose()) {
336 StreamString strm;
337 strm.Printf(
338 "UnwindAssemblyInstEmulation::ReadMemory (addr = 0x%16.16" PRIx64
339 ", dst = %p, dst_len = %" PRIu64 ", context = ",
340 addr, dst, (uint64_t)dst_len);
341 context.Dump(strm, instruction);
342 log->PutString(strm.GetString());
343 }
344 memset(dst, 0, dst_len);
345 return dst_len;
346}
347
349 EmulateInstruction *instruction, void *baton,
350 const EmulateInstruction::Context &context, lldb::addr_t addr,
351 const void *dst, size_t dst_len) {
352 if (baton && dst && dst_len)
353 return ((UnwindAssemblyInstEmulation *)baton)
354 ->WriteMemory(instruction, context, addr, dst, dst_len);
355 return 0;
356}
357
359 EmulateInstruction *instruction, const EmulateInstruction::Context &context,
360 lldb::addr_t addr, const void *dst, size_t dst_len) {
361 DataExtractor data(dst, dst_len,
362 instruction->GetArchitecture().GetByteOrder(),
363 instruction->GetArchitecture().GetAddressByteSize());
364
365 Log *log = GetLog(LLDBLog::Unwind);
366
367 if (log && log->GetVerbose()) {
368 StreamString strm;
369
370 strm.PutCString("UnwindAssemblyInstEmulation::WriteMemory (");
371 DumpDataExtractor(data, &strm, 0, eFormatBytes, 1, dst_len, UINT32_MAX,
372 addr, 0, 0);
373 strm.PutCString(", context = ");
374 context.Dump(strm, instruction);
375 log->PutString(strm.GetString());
376 }
377
378 switch (context.type) {
379 default:
399 break;
400
402 uint32_t reg_num = LLDB_INVALID_REGNUM;
403 uint32_t generic_regnum = LLDB_INVALID_REGNUM;
404 assert(context.GetInfoType() ==
406 "unhandled case, add code to handle this!");
407 const uint32_t unwind_reg_kind = m_unwind_plan_ptr->GetRegisterKind();
409 .kinds[unwind_reg_kind];
410 generic_regnum = context.info.RegisterToRegisterPlusOffset.data_reg
412
413 if (reg_num != LLDB_INVALID_REGNUM &&
414 generic_regnum != LLDB_REGNUM_GENERIC_SP) {
415 if (m_pushed_regs.try_emplace(reg_num, addr).second) {
416 const int32_t offset = addr - m_initial_cfa;
417 m_state.row.SetRegisterLocationToAtCFAPlusOffset(reg_num, offset,
418 /*can_replace=*/true);
419 m_curr_row_modified = true;
420 }
421 }
422 } break;
423 }
424
425 return dst_len;
426}
427
429 void *baton,
430 const RegisterInfo *reg_info,
431 RegisterValue &reg_value) {
432
433 if (baton && reg_info)
434 return ((UnwindAssemblyInstEmulation *)baton)
435 ->ReadRegister(instruction, reg_info, reg_value);
436 return false;
437}
439 const RegisterInfo *reg_info,
440 RegisterValue &reg_value) {
441 bool synthetic = GetRegisterValue(*reg_info, reg_value);
442
443 Log *log = GetLog(LLDBLog::Unwind);
444
445 if (log && log->GetVerbose()) {
446
447 StreamString strm;
448 strm.Printf("UnwindAssemblyInstEmulation::ReadRegister (name = \"%s\") => "
449 "synthetic_value = %i, value = ",
450 reg_info->name, synthetic);
451 DumpRegisterValue(reg_value, strm, *reg_info, false, false, eFormatDefault);
452 log->PutString(strm.GetString());
453 }
454 return true;
455}
456
458 EmulateInstruction *instruction, void *baton,
459 const EmulateInstruction::Context &context, const RegisterInfo *reg_info,
460 const RegisterValue &reg_value) {
461 if (baton && reg_info)
462 return ((UnwindAssemblyInstEmulation *)baton)
463 ->WriteRegister(instruction, context, reg_info, reg_value);
464 return false;
465}
467 EmulateInstruction *instruction, const EmulateInstruction::Context &context,
468 const RegisterInfo *reg_info, const RegisterValue &reg_value) {
469 Log *log = GetLog(LLDBLog::Unwind);
470
471 if (log && log->GetVerbose()) {
472
473 StreamString strm;
474 strm.Printf(
475 "UnwindAssemblyInstEmulation::WriteRegister (name = \"%s\", value = ",
476 reg_info->name);
477 DumpRegisterValue(reg_value, strm, *reg_info, false, false, eFormatDefault);
478 strm.PutCString(", context = ");
479 context.Dump(strm, instruction);
480 log->PutString(strm.GetString());
481 }
482
483 SetRegisterValue(*reg_info, reg_value);
484
485 switch (context.type) {
501 // {
502 // const uint32_t reg_num =
503 // reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
504 // if (reg_num != LLDB_INVALID_REGNUM)
505 // {
506 // const bool can_replace_only_if_unspecified = true;
507 //
508 // m_curr_row.SetRegisterLocationToUndefined (reg_num,
509 // can_replace_only_if_unspecified,
510 // can_replace_only_if_unspecified);
511 // m_curr_row_modified = true;
512 // }
513 // }
514 break;
515
517 // If we adjusted the current frame pointer by a constant then adjust the
518 // CFA offset
519 // with the same amount.
520 lldb::RegisterKind kind = m_unwind_plan_ptr->GetRegisterKind();
521 if (m_state.fp_is_cfa &&
522 reg_info->kinds[kind] == m_state.cfa_reg_info.kinds[kind] &&
523 context.GetInfoType() ==
525 context.info.RegisterPlusOffset.reg.kinds[kind] ==
526 m_state.cfa_reg_info.kinds[kind]) {
527 const int64_t offset = context.info.RegisterPlusOffset.signed_offset;
528 m_state.row.GetCFAValue().IncOffset(-1 * offset);
529 m_curr_row_modified = true;
530 }
531 } break;
532
536 context.info.ISAAndImmediate.unsigned_data32 != 0) {
538 } else if (context.GetInfoType() ==
542 } else if (context.GetInfoType() ==
544 context.info.unsigned_immediate != 0) {
546 } else if (context.GetInfoType() ==
548 context.info.signed_immediate != 0) {
550 }
551 } break;
552
554 const uint32_t reg_num =
555 reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
556 const uint32_t generic_regnum = reg_info->kinds[eRegisterKindGeneric];
557 if (reg_num != LLDB_INVALID_REGNUM &&
558 generic_regnum != LLDB_REGNUM_GENERIC_SP) {
559 switch (context.GetInfoType()) {
561 if (auto it = m_pushed_regs.find(reg_num);
562 it != m_pushed_regs.end() && context.info.address == it->second) {
563 m_state.row.SetRegisterLocationToSame(reg_num,
564 false /*must_replace*/);
565 m_curr_row_modified = true;
566
567 // FP has been restored to its original value, we are back
568 // to using SP to calculate the CFA.
569 if (m_state.fp_is_cfa) {
570 m_state.fp_is_cfa = false;
572 uint32_t sp_reg_num = LLDB_REGNUM_GENERIC_SP;
573 RegisterInfo sp_reg_info =
574 *m_inst_emulator_up->GetRegisterInfo(sp_reg_kind, sp_reg_num);
575 RegisterValue sp_reg_val;
576 if (GetRegisterValue(sp_reg_info, sp_reg_val)) {
577 m_state.cfa_reg_info = sp_reg_info;
578 const uint32_t cfa_reg_num =
579 sp_reg_info.kinds[m_unwind_plan_ptr->GetRegisterKind()];
580 assert(cfa_reg_num != LLDB_INVALID_REGNUM);
581 m_state.row.GetCFAValue().SetIsRegisterPlusOffset(
582 cfa_reg_num, m_initial_cfa - sp_reg_val.GetAsUInt64());
583 }
584 }
585 }
586 break;
588 assert(
589 (generic_regnum == LLDB_REGNUM_GENERIC_PC ||
590 generic_regnum == LLDB_REGNUM_GENERIC_FLAGS) &&
591 "eInfoTypeISA used for popping a register other the PC/FLAGS");
592 if (generic_regnum != LLDB_REGNUM_GENERIC_FLAGS) {
593 m_state.row.SetRegisterLocationToSame(reg_num,
594 false /*must_replace*/);
595 m_curr_row_modified = true;
596 }
597 break;
598 default:
599 assert(false && "unhandled case, add code to handle this!");
600 break;
601 }
602 }
603 } break;
604
606 if (!m_state.fp_is_cfa) {
607 m_state.fp_is_cfa = true;
608 m_state.cfa_reg_info = *reg_info;
609 const uint32_t cfa_reg_num =
610 reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
611 assert(cfa_reg_num != LLDB_INVALID_REGNUM);
612 m_state.row.GetCFAValue().SetIsRegisterPlusOffset(
613 cfa_reg_num, m_initial_cfa - reg_value.GetAsUInt64());
614 m_curr_row_modified = true;
615 }
616 break;
617
619 if (m_state.fp_is_cfa) {
620 m_state.fp_is_cfa = false;
621 m_state.cfa_reg_info = *reg_info;
622 const uint32_t cfa_reg_num =
623 reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
624 assert(cfa_reg_num != LLDB_INVALID_REGNUM);
625 m_state.row.GetCFAValue().SetIsRegisterPlusOffset(
626 cfa_reg_num, m_initial_cfa - reg_value.GetAsUInt64());
627 m_curr_row_modified = true;
628 }
629 break;
630
632 // If we have created a frame using the frame pointer, don't follow
633 // subsequent adjustments to the stack pointer.
634 if (!m_state.fp_is_cfa) {
635 m_state.row.GetCFAValue().SetIsRegisterPlusOffset(
636 m_state.row.GetCFAValue().GetRegisterNumber(),
637 m_initial_cfa - reg_value.GetAsUInt64());
638 m_curr_row_modified = true;
639 }
640 break;
641 }
642 return true;
643}
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_PLUGIN_DEFINE(PluginName)
static void DumpInstToLog(Log *log, Instruction &inst, const InstructionList &inst_list)
static void DumpUnwindRowsToLog(Log *log, AddressRange range, const UnwindPlan &unwind_plan)
bool GetRegisterValue(const lldb_private::RegisterInfo &reg_info, lldb_private::RegisterValue &reg_value)
static llvm::StringRef GetPluginNameStatic()
bool GetFastUnwindPlan(lldb_private::AddressRange &func, lldb_private::Thread &thread, lldb_private::UnwindPlan &unwind_plan) override
std::unique_ptr< lldb_private::EmulateInstruction > m_inst_emulator_up
lldb_private::UnwindPlan * m_unwind_plan_ptr
static size_t WriteMemory(lldb_private::EmulateInstruction *instruction, void *baton, const lldb_private::EmulateInstruction::Context &context, lldb::addr_t addr, const void *dst, size_t length)
static bool WriteRegister(lldb_private::EmulateInstruction *instruction, void *baton, const lldb_private::EmulateInstruction::Context &context, const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &reg_value)
static llvm::StringRef GetPluginDescriptionStatic()
bool AugmentUnwindPlanFromCallSite(lldb_private::AddressRange &func, lldb_private::Thread &thread, lldb_private::UnwindPlan &unwind_plan) override
static size_t ReadMemory(lldb_private::EmulateInstruction *instruction, void *baton, const lldb_private::EmulateInstruction::Context &context, lldb::addr_t addr, void *dst, size_t length)
lldb_private::AddressRange * m_range_ptr
static bool ReadRegister(lldb_private::EmulateInstruction *instruction, void *baton, const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &reg_value)
static uint64_t MakeRegisterKindValuePair(const lldb_private::RegisterInfo &reg_info)
static lldb_private::UnwindAssembly * CreateInstance(const lldb_private::ArchSpec &arch)
bool GetNonCallSiteUnwindPlanFromAssembly(lldb_private::AddressRange &func, lldb_private::Thread &thread, lldb_private::UnwindPlan &unwind_plan) override
void SetRegisterValue(const lldb_private::RegisterInfo &reg_info, const lldb_private::RegisterValue &reg_value)
UnwindAssemblyInstEmulation(const lldb_private::ArchSpec &arch, lldb_private::EmulateInstruction *inst_emulator)
bool FirstNonPrologueInsn(lldb_private::AddressRange &func, const lldb_private::ExecutionContext &exe_ctx, lldb_private::Address &first_non_prologue_insn) override
A section + offset based address range class.
Address & GetBaseAddress()
Get accessor for the base address of the range.
bool ContainsFileAddress(const Address &so_addr) const
Check if a section offset address is contained in this range.
lldb::addr_t GetByteSize() const
Get accessor for the byte size of this range.
A section + offset based address class.
Definition Address.h:62
bool Slide(int64_t offset)
Definition Address.h:452
lldb::addr_t GetFileAddress() const
Get the file address.
Definition Address.cpp:281
bool IsValid() const
Check if the object state is valid.
Definition Address.h:355
An architecture specification class.
Definition ArchSpec.h:32
uint32_t GetAddressByteSize() const
Returns the size in bytes of an address of the current architecture.
Definition ArchSpec.cpp:690
lldb::ByteOrder GetByteOrder() const
Returns the byte order for the architecture specification.
Definition ArchSpec.cpp:739
An data extractor class.
static lldb::DisassemblerSP DisassembleBytes(const ArchSpec &arch, const char *plugin_name, const char *flavor, const char *cpu, const char *features, const Address &start, const void *bytes, size_t length, uint32_t max_num_instructions, bool data_from_file)
"lldb/Core/EmulateInstruction.h" A class that allows emulation of CPU opcodes.
static bool GetBestRegisterKindAndNumber(const RegisterInfo *reg_info, lldb::RegisterKind &reg_kind, uint32_t &reg_num)
const ArchSpec & GetArchitecture() const
static const InstructionCondition UnconditionalCondition
static EmulateInstruction * FindPlugin(const ArchSpec &arch, InstructionType supported_inst_type, const char *plugin_name)
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
uint32_t GetIndexOfInstructionAtAddress(const Address &addr)
lldb::InstructionSP GetInstructionAtIndex(size_t idx) const
uint32_t GetMaxOpcocdeByteSize() const
const Address & GetAddress() const
const Opcode & GetOpcode() const
virtual bool IsBarrier()=0
virtual void Dump(Stream *s, uint32_t max_opcode_byte_size, bool show_address, bool show_bytes, bool show_control_flow_kind, const ExecutionContext *exe_ctx, const SymbolContext *sym_ctx, const SymbolContext *prev_sym_ctx, const FormatEntity::Entry *disassembly_addr_format, size_t max_address_text_size)
Dump the text representation of this Instruction to a Stream.
bool GetVerbose() const
Definition Log.cpp:300
void PutString(llvm::StringRef str)
Definition Log.cpp:147
uint32_t GetByteSize() const
Definition Opcode.h:231
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
bool SetUInt(uint64_t uint, uint32_t byte_size)
uint64_t GetAsUInt64(uint64_t fail_value=UINT64_MAX, bool *success_ptr=nullptr) const
An error handling class.
Definition Status.h:118
llvm::StringRef GetString() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition Stream.cpp:63
uint32_t GetInitialCFARegister() const
Definition UnwindPlan.h:470
void InsertRow(Row row, bool replace_existing=false)
lldb::RegisterKind GetRegisterKind() const
Definition UnwindPlan.h:460
const UnwindPlan::Row * GetLastRow() const
void Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const
#define LLDB_REGNUM_GENERIC_SP
#define LLDB_REGNUM_GENERIC_FLAGS
#define UINT32_MAX
#define LLDB_INVALID_REGNUM
#define LLDB_REGNUM_GENERIC_PC
Status Parse(const llvm::StringRef &format, Entry &entry)
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:327
lldb::offset_t DumpDataExtractor(const DataExtractor &DE, Stream *s, lldb::offset_t offset, lldb::Format item_format, size_t item_byte_size, size_t item_count, size_t num_per_line, uint64_t base_addr, uint32_t item_bit_size, uint32_t item_bit_offset, ExecutionContextScope *exe_scope=nullptr, bool show_memory_tags=false)
Dumps item_count objects into the stream s.
void DumpRegisterValue(const RegisterValue &reg_val, Stream &s, const RegisterInfo &reg_info, bool prefix_with_name, bool prefix_with_alt_name, lldb::Format format, uint32_t reg_name_right_align_at=0, ExecutionContextScope *exe_scope=nullptr, bool print_flags=false, lldb::TargetSP target_sp=nullptr)
std::shared_ptr< lldb_private::Process > ProcessSP
std::shared_ptr< lldb_private::Disassembler > DisassemblerSP
uint64_t addr_t
Definition lldb-types.h:80
RegisterKind
Register numbering types.
@ eRegisterKindGeneric
insn ptr reg, stack ptr reg, etc not specific to any particular target
void Dump(Stream &s, EmulateInstruction *instruction) const
union lldb_private::EmulateInstruction::Context::ContextInfo info
Every register is described in detail including its name, alternate name (optional),...
uint32_t byte_size
Size in bytes of the register.
uint32_t kinds[lldb::kNumRegisterKinds]
Holds all of the various register numbers for all register kinds.
const char * name
Name of this register, can't be NULL.
struct lldb_private::EmulateInstruction::Context::ContextInfo::ISAAndImmediateSigned ISAAndImmediateSigned
struct lldb_private::EmulateInstruction::Context::ContextInfo::RegisterPlusOffset RegisterPlusOffset
struct lldb_private::EmulateInstruction::Context::ContextInfo::RegisterToRegisterPlusOffset RegisterToRegisterPlusOffset
struct lldb_private::EmulateInstruction::Context::ContextInfo::ISAAndImmediate ISAAndImmediate