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 const bool force_live_memory = true;
45 if (process_sp->GetTarget().ReadMemory(
46 range.GetBaseAddress(), function_text.data(), range.GetByteSize(),
47 error, force_live_memory) != range.GetByteSize()) {
48 return false;
49 }
50 }
52 range, function_text.data(), function_text.size(), unwind_plan);
53}
54
55static void DumpUnwindRowsToLog(Log *log, AddressRange range,
56 const UnwindPlan &unwind_plan) {
57 if (!log || !log->GetVerbose())
58 return;
59 StreamString strm;
60 lldb::addr_t base_addr = range.GetBaseAddress().GetFileAddress();
61 strm.Printf("Resulting unwind rows for [0x%" PRIx64 " - 0x%" PRIx64 "):",
62 base_addr, base_addr + range.GetByteSize());
63 unwind_plan.Dump(strm, nullptr, base_addr);
64 log->PutString(strm.GetString());
65}
66
67static void DumpInstToLog(Log *log, Instruction &inst,
68 const InstructionList &inst_list) {
69 if (!log || !log->GetVerbose())
70 return;
71 const bool show_address = true;
72 const bool show_bytes = true;
73 const bool show_control_flow_kind = false;
74 StreamString strm;
76 FormatEntity::Parse("${frame.pc}: ", format);
77 inst.Dump(&strm, inst_list.GetMaxOpcocdeByteSize(), show_address, show_bytes,
78 show_control_flow_kind, nullptr, nullptr, nullptr, &format, 0);
79 log->PutString(strm.GetString());
80}
81
83 AddressRange &range, uint8_t *opcode_data, size_t opcode_size,
84 UnwindPlan &unwind_plan) {
85 if (opcode_data == nullptr || opcode_size == 0)
86 return false;
87
88 if (range.GetByteSize() == 0 || !range.GetBaseAddress().IsValid() ||
90 return false;
91
92 // The instruction emulation subclass setup the unwind plan for the first
93 // instruction.
94 m_inst_emulator_up->CreateFunctionEntryUnwind(unwind_plan);
95
96 // CreateFunctionEntryUnwind should have created the first row. If it doesn't,
97 // then we are done.
98 if (unwind_plan.GetRowCount() == 0)
99 return false;
100
101 const bool prefer_file_cache = true;
103 m_arch, nullptr, nullptr, nullptr, nullptr, range.GetBaseAddress(),
104 opcode_data, opcode_size, 99999, prefer_file_cache));
105
106 if (!disasm_sp)
107 return false;
108
109 Log *log = GetLog(LLDBLog::Unwind);
110
111 m_range_ptr = &range;
112 m_unwind_plan_ptr = &unwind_plan;
113
114 m_state.cfa_reg_info = *m_inst_emulator_up->GetRegisterInfo(
115 unwind_plan.GetRegisterKind(), unwind_plan.GetInitialCFARegister());
116 m_state.fp_is_cfa = false;
117 m_state.register_values.clear();
118
119 m_pushed_regs.clear();
120
121 RegisterValue cfa_reg_value;
122 cfa_reg_value.SetUInt(m_initial_cfa, m_state.cfa_reg_info.byte_size);
123 SetRegisterValue(m_state.cfa_reg_info, cfa_reg_value);
124
125 InstructionList inst_list = disasm_sp->GetInstructionList();
126
127 if (inst_list.GetSize() == 0) {
128 DumpUnwindRowsToLog(log, range, unwind_plan);
129 return unwind_plan.GetRowCount() > 0;
130 }
131
132 Instruction &first_inst = *inst_list.GetInstructionAtIndex(0);
133 const lldb::addr_t base_addr = first_inst.GetAddress().GetFileAddress();
134
135 // Map for storing the unwind state at a given offset. When we see a forward
136 // branch we add a new entry to this map with the actual unwind plan row and
137 // register context for the target address of the branch as the current data
138 // have to be valid for the target address of the branch too if we are in
139 // the same function.
140 std::map<lldb::addr_t, UnwindState> saved_unwind_states;
141
142 // Make a copy of the current instruction Row and save it in m_state so
143 // we can add updates as we process the instructions.
144 m_state.row = *unwind_plan.GetLastRow();
145
146 // Add the initial state to the save list with offset 0.
147 auto condition_block_start_state =
148 saved_unwind_states.emplace(0, m_state).first;
149
150 // The architecture dependent condition code of the last processed
151 // instruction.
154
155 std::deque<std::size_t> to_visit = {0};
156 llvm::SmallSet<std::size_t, 0> enqueued = {0};
157
158 // Instructions reachable through jumps are inserted on the front.
159 // The next instruction is inserted on the back.
160 // Pop from the back to ensure non-branching instructions are visited
161 // sequentially.
162 while (!to_visit.empty()) {
163 const std::size_t current_index = to_visit.back();
164 Instruction &inst = *inst_list.GetInstructionAtIndex(current_index);
165 to_visit.pop_back();
166 DumpInstToLog(log, inst, inst_list);
167
168 m_curr_row_modified = false;
169 m_branch_offset = 0;
170
171 lldb::addr_t current_offset =
172 inst.GetAddress().GetFileAddress() - base_addr;
173 auto it = saved_unwind_states.upper_bound(current_offset);
174 assert(it != saved_unwind_states.begin() &&
175 "Unwind row for the function entry missing");
176 --it; // Move it to the row corresponding to the current offset
177
178 // When state is forwarded through a branch, the offset of m_state.row is
179 // different from the offset available in saved_unwind_states. Use the
180 // forwarded state in this case, as the previous instruction may have been
181 // an unconditional jump.
182 // FIXME: this assignment can always be done unconditionally.
183 if (it->second.row.GetOffset() != m_state.row.GetOffset())
184 m_state = it->second;
185
186 m_inst_emulator_up->SetInstruction(inst.GetOpcode(), inst.GetAddress(),
187 nullptr);
188 const EmulateInstruction::InstructionCondition new_condition =
189 m_inst_emulator_up->GetInstructionCondition();
190
191 if (last_condition != new_condition) {
192 // If the last instruction was conditional with a different condition
193 // than the current condition then restore the state.
194 if (last_condition != EmulateInstruction::UnconditionalCondition) {
195 m_state = condition_block_start_state->second;
196 m_state.row.SetOffset(current_offset);
197 // The last instruction might already created a row for this offset
198 // and we want to overwrite it.
199 saved_unwind_states.insert_or_assign(current_offset, m_state);
200 }
201
202 // We are starting a new conditional block at the actual offset
203 condition_block_start_state = it;
204 }
205
206 last_condition = new_condition;
207
208 m_inst_emulator_up->EvaluateInstruction(
209 eEmulateInstructionOptionIgnoreConditions);
210
211 // If the current instruction is a branch forward then save the current
212 // CFI information for the offset where we are branching.
213 Address branch_address = inst.GetAddress();
214 branch_address.Slide(m_branch_offset);
215 if (m_branch_offset != 0 &&
216 range.ContainsFileAddress(branch_address.GetFileAddress())) {
217 if (auto [it, inserted] = saved_unwind_states.emplace(
218 current_offset + m_branch_offset, m_state);
219 inserted) {
220 it->second.row.SetOffset(current_offset + m_branch_offset);
221 if (std::size_t dest_instr_index =
222 inst_list.GetIndexOfInstructionAtAddress(branch_address);
223 dest_instr_index < inst_list.GetSize()) {
224 to_visit.push_front(dest_instr_index);
225 enqueued.insert(dest_instr_index);
226 }
227 }
228 }
229
230 // If inst is a barrier, do not propagate state to the next instruction.
231 if (inst.IsBarrier())
232 continue;
233
234 // Were there any changes to the CFI while evaluating this instruction?
236 // Save the modified row if we don't already have a CFI row in the
237 // current address
238 const lldb::addr_t next_inst_offset =
239 current_offset + inst.GetOpcode().GetByteSize();
240 if (saved_unwind_states.count(next_inst_offset) == 0) {
241 m_state.row.SetOffset(next_inst_offset);
242 saved_unwind_states.emplace(next_inst_offset, m_state);
243 }
244 }
245
246 const size_t next_idx = current_index + 1;
247 const bool never_enqueued = enqueued.insert(next_idx).second;
248 if (never_enqueued && next_idx < inst_list.GetSize())
249 to_visit.push_back(next_idx);
250 }
251
252 for (auto &[_, state] : saved_unwind_states)
253 unwind_plan.InsertRow(std::move(state.row),
254 /*replace_existing=*/true);
255
256 DumpUnwindRowsToLog(log, range, unwind_plan);
257 return unwind_plan.GetRowCount() > 0;
258}
259
261 AddressRange &func, Thread &thread, UnwindPlan &unwind_plan) {
262 return false;
263}
264
266 Thread &thread,
267 UnwindPlan &unwind_plan) {
268 return false;
269}
270
272 AddressRange &func, const ExecutionContext &exe_ctx,
273 Address &first_non_prologue_insn) {
274 return false;
275}
276
279 std::unique_ptr<EmulateInstruction> inst_emulator_up(
281 nullptr));
282 // Make sure that all prologue instructions are handled
283 if (inst_emulator_up)
284 return new UnwindAssemblyInstEmulation(arch, inst_emulator_up.release());
285 return nullptr;
286}
287
292
296
298 return "Instruction emulation based unwind information.";
299}
300
302 const RegisterInfo &reg_info) {
303 lldb::RegisterKind reg_kind;
304 uint32_t reg_num;
306 reg_num))
307 return (uint64_t)reg_kind << 24 | reg_num;
308 return 0ull;
309}
310
312 const RegisterInfo &reg_info, const RegisterValue &reg_value) {
313 m_state.register_values[MakeRegisterKindValuePair(reg_info)] = reg_value;
314}
315
317 RegisterValue &reg_value) {
318 const uint64_t reg_id = MakeRegisterKindValuePair(reg_info);
319 RegisterValueMap::const_iterator pos = m_state.register_values.find(reg_id);
320 if (pos != m_state.register_values.end()) {
321 reg_value = pos->second;
322 return true; // We had a real value that comes from an opcode that wrote
323 // to it...
324 }
325 // We are making up a value that is recognizable...
326 reg_value.SetUInt(reg_id, reg_info.byte_size);
327 return false;
328}
329
331 EmulateInstruction *instruction, void *baton,
332 const EmulateInstruction::Context &context, lldb::addr_t addr, void *dst,
333 size_t dst_len) {
334 Log *log = GetLog(LLDBLog::Unwind);
335
336 if (log && log->GetVerbose()) {
337 StreamString strm;
338 strm.Printf(
339 "UnwindAssemblyInstEmulation::ReadMemory (addr = 0x%16.16" PRIx64
340 ", dst = %p, dst_len = %" PRIu64 ", context = ",
341 addr, dst, (uint64_t)dst_len);
342 context.Dump(strm, instruction);
343 log->PutString(strm.GetString());
344 }
345 memset(dst, 0, dst_len);
346 return dst_len;
347}
348
350 EmulateInstruction *instruction, void *baton,
351 const EmulateInstruction::Context &context, lldb::addr_t addr,
352 const void *dst, size_t dst_len) {
353 if (baton && dst && dst_len)
354 return ((UnwindAssemblyInstEmulation *)baton)
355 ->WriteMemory(instruction, context, addr, dst, dst_len);
356 return 0;
357}
358
360 EmulateInstruction *instruction, const EmulateInstruction::Context &context,
361 lldb::addr_t addr, const void *dst, size_t dst_len) {
362 DataExtractor data(dst, dst_len,
363 instruction->GetArchitecture().GetByteOrder(),
364 instruction->GetArchitecture().GetAddressByteSize());
365
366 Log *log = GetLog(LLDBLog::Unwind);
367
368 if (log && log->GetVerbose()) {
369 StreamString strm;
370
371 strm.PutCString("UnwindAssemblyInstEmulation::WriteMemory (");
372 DumpDataExtractor(data, &strm, 0, eFormatBytes, 1, dst_len, UINT32_MAX,
373 addr, 0, 0);
374 strm.PutCString(", context = ");
375 context.Dump(strm, instruction);
376 log->PutString(strm.GetString());
377 }
378
379 switch (context.type) {
380 default:
400 break;
401
403 uint32_t reg_num = LLDB_INVALID_REGNUM;
404 uint32_t generic_regnum = LLDB_INVALID_REGNUM;
405 assert(context.GetInfoType() ==
407 "unhandled case, add code to handle this!");
408 const uint32_t unwind_reg_kind = m_unwind_plan_ptr->GetRegisterKind();
410 .kinds[unwind_reg_kind];
411 generic_regnum = context.info.RegisterToRegisterPlusOffset.data_reg
413
414 if (reg_num != LLDB_INVALID_REGNUM &&
415 generic_regnum != LLDB_REGNUM_GENERIC_SP) {
416 if (m_pushed_regs.try_emplace(reg_num, addr).second) {
417 const int32_t offset = addr - m_initial_cfa;
418 m_state.row.SetRegisterLocationToAtCFAPlusOffset(reg_num, offset,
419 /*can_replace=*/true);
420 m_curr_row_modified = true;
421 }
422 }
423 } break;
424 }
425
426 return dst_len;
427}
428
430 void *baton,
431 const RegisterInfo *reg_info,
432 RegisterValue &reg_value) {
433
434 if (baton && reg_info)
435 return ((UnwindAssemblyInstEmulation *)baton)
436 ->ReadRegister(instruction, reg_info, reg_value);
437 return false;
438}
440 const RegisterInfo *reg_info,
441 RegisterValue &reg_value) {
442 bool synthetic = GetRegisterValue(*reg_info, reg_value);
443
444 Log *log = GetLog(LLDBLog::Unwind);
445
446 if (log && log->GetVerbose()) {
447
448 StreamString strm;
449 strm.Printf("UnwindAssemblyInstEmulation::ReadRegister (name = \"%s\") => "
450 "synthetic_value = %i, value = ",
451 reg_info->name, synthetic);
452 DumpRegisterValue(reg_value, strm, *reg_info, false, false, eFormatDefault);
453 log->PutString(strm.GetString());
454 }
455 return true;
456}
457
459 EmulateInstruction *instruction, void *baton,
460 const EmulateInstruction::Context &context, const RegisterInfo *reg_info,
461 const RegisterValue &reg_value) {
462 if (baton && reg_info)
463 return ((UnwindAssemblyInstEmulation *)baton)
464 ->WriteRegister(instruction, context, reg_info, reg_value);
465 return false;
466}
468 EmulateInstruction *instruction, const EmulateInstruction::Context &context,
469 const RegisterInfo *reg_info, const RegisterValue &reg_value) {
470 Log *log = GetLog(LLDBLog::Unwind);
471
472 if (log && log->GetVerbose()) {
473
474 StreamString strm;
475 strm.Printf(
476 "UnwindAssemblyInstEmulation::WriteRegister (name = \"%s\", value = ",
477 reg_info->name);
478 DumpRegisterValue(reg_value, strm, *reg_info, false, false, eFormatDefault);
479 strm.PutCString(", context = ");
480 context.Dump(strm, instruction);
481 log->PutString(strm.GetString());
482 }
483
484 SetRegisterValue(*reg_info, reg_value);
485
486 switch (context.type) {
502 // {
503 // const uint32_t reg_num =
504 // reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
505 // if (reg_num != LLDB_INVALID_REGNUM)
506 // {
507 // const bool can_replace_only_if_unspecified = true;
508 //
509 // m_curr_row.SetRegisterLocationToUndefined (reg_num,
510 // can_replace_only_if_unspecified,
511 // can_replace_only_if_unspecified);
512 // m_curr_row_modified = true;
513 // }
514 // }
515 break;
516
518 // If we adjusted the current frame pointer by a constant then adjust the
519 // CFA offset
520 // with the same amount.
521 lldb::RegisterKind kind = m_unwind_plan_ptr->GetRegisterKind();
522 if (m_state.fp_is_cfa &&
523 reg_info->kinds[kind] == m_state.cfa_reg_info.kinds[kind] &&
524 context.GetInfoType() ==
526 context.info.RegisterPlusOffset.reg.kinds[kind] ==
527 m_state.cfa_reg_info.kinds[kind]) {
528 const int64_t offset = context.info.RegisterPlusOffset.signed_offset;
529 m_state.row.GetCFAValue().IncOffset(-1 * offset);
530 m_curr_row_modified = true;
531 }
532 } break;
533
537 context.info.ISAAndImmediate.unsigned_data32 != 0) {
539 } else if (context.GetInfoType() ==
543 } else if (context.GetInfoType() ==
545 context.info.unsigned_immediate != 0) {
547 } else if (context.GetInfoType() ==
549 context.info.signed_immediate != 0) {
551 }
552 } break;
553
555 const uint32_t reg_num =
556 reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
557 const uint32_t generic_regnum = reg_info->kinds[eRegisterKindGeneric];
558 if (reg_num != LLDB_INVALID_REGNUM &&
559 generic_regnum != LLDB_REGNUM_GENERIC_SP) {
560 switch (context.GetInfoType()) {
562 if (auto it = m_pushed_regs.find(reg_num);
563 it != m_pushed_regs.end() && context.info.address == it->second) {
564 m_state.row.SetRegisterLocationToSame(reg_num,
565 false /*must_replace*/);
566 m_curr_row_modified = true;
567
568 // FP has been restored to its original value, we are back
569 // to using SP to calculate the CFA.
570 if (m_state.fp_is_cfa) {
571 m_state.fp_is_cfa = false;
573 uint32_t sp_reg_num = LLDB_REGNUM_GENERIC_SP;
574 RegisterInfo sp_reg_info =
575 *m_inst_emulator_up->GetRegisterInfo(sp_reg_kind, sp_reg_num);
576 RegisterValue sp_reg_val;
577 if (GetRegisterValue(sp_reg_info, sp_reg_val)) {
578 m_state.cfa_reg_info = sp_reg_info;
579 const uint32_t cfa_reg_num =
580 sp_reg_info.kinds[m_unwind_plan_ptr->GetRegisterKind()];
581 assert(cfa_reg_num != LLDB_INVALID_REGNUM);
582 m_state.row.GetCFAValue().SetIsRegisterPlusOffset(
583 cfa_reg_num, m_initial_cfa - sp_reg_val.GetAsUInt64());
584 }
585 }
586 }
587 break;
589 assert(
590 (generic_regnum == LLDB_REGNUM_GENERIC_PC ||
591 generic_regnum == LLDB_REGNUM_GENERIC_FLAGS) &&
592 "eInfoTypeISA used for popping a register other the PC/FLAGS");
593 if (generic_regnum != LLDB_REGNUM_GENERIC_FLAGS) {
594 m_state.row.SetRegisterLocationToSame(reg_num,
595 false /*must_replace*/);
596 m_curr_row_modified = true;
597 }
598 break;
599 default:
600 assert(false && "unhandled case, add code to handle this!");
601 break;
602 }
603 }
604 } break;
605
607 if (!m_state.fp_is_cfa) {
608 m_state.fp_is_cfa = true;
609 m_state.cfa_reg_info = *reg_info;
610 const uint32_t cfa_reg_num =
611 reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
612 assert(cfa_reg_num != LLDB_INVALID_REGNUM);
613 m_state.row.GetCFAValue().SetIsRegisterPlusOffset(
614 cfa_reg_num, m_initial_cfa - reg_value.GetAsUInt64());
615 m_curr_row_modified = true;
616 }
617 break;
618
620 if (m_state.fp_is_cfa) {
621 m_state.fp_is_cfa = false;
622 m_state.cfa_reg_info = *reg_info;
623 const uint32_t cfa_reg_num =
624 reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
625 assert(cfa_reg_num != LLDB_INVALID_REGNUM);
626 m_state.row.GetCFAValue().SetIsRegisterPlusOffset(
627 cfa_reg_num, m_initial_cfa - reg_value.GetAsUInt64());
628 m_curr_row_modified = true;
629 }
630 break;
631
633 // If we have created a frame using the frame pointer, don't follow
634 // subsequent adjustments to the stack pointer.
635 if (!m_state.fp_is_cfa) {
636 m_state.row.GetCFAValue().SetIsRegisterPlusOffset(
637 m_state.row.GetCFAValue().GetRegisterNumber(),
638 m_initial_cfa - reg_value.GetAsUInt64());
639 m_curr_row_modified = true;
640 }
641 break;
642 }
643 return true;
644}
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:31
uint32_t GetAddressByteSize() const
Returns the size in bytes of an address of the current architecture.
Definition ArchSpec.cpp:685
lldb::ByteOrder GetByteOrder() const
Returns the byte order for the architecture specification.
Definition ArchSpec.cpp:732
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:326
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:65
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:332
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