Skip to content

Commit fec1308

Browse files
authored
Merge pull request #9598 from swiftlang/cherrypick-f109517
[lldb] Support overriding the disassembly CPU & features (llvm#115382)
2 parents b76740b + ed2c6cc commit fec1308

34 files changed

+493
-152
lines changed

lldb/include/lldb/Core/Disassembler.h

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -409,35 +409,37 @@ class Disassembler : public std::enable_shared_from_this<Disassembler>,
409409
// flavor string gets set wrong. Instead, if you get a flavor string you
410410
// don't understand, use the default. Folks who care to check can use the
411411
// FlavorValidForArchSpec method on the disassembler they got back.
412-
static lldb::DisassemblerSP
413-
FindPlugin(const ArchSpec &arch, const char *flavor, const char *plugin_name);
412+
static lldb::DisassemblerSP FindPlugin(const ArchSpec &arch,
413+
const char *flavor, const char *cpu,
414+
const char *features,
415+
const char *plugin_name);
414416

415417
// This version will use the value in the Target settings if flavor is NULL;
416-
static lldb::DisassemblerSP FindPluginForTarget(const Target &target,
417-
const ArchSpec &arch,
418-
const char *flavor,
419-
const char *plugin_name);
418+
static lldb::DisassemblerSP
419+
FindPluginForTarget(const Target &target, const ArchSpec &arch,
420+
const char *flavor, const char *cpu, const char *features,
421+
const char *plugin_name);
420422

421423
struct Limit {
422424
enum { Bytes, Instructions } kind;
423425
lldb::addr_t value;
424426
};
425427

426-
static lldb::DisassemblerSP DisassembleRange(const ArchSpec &arch,
427-
const char *plugin_name,
428-
const char *flavor,
429-
Target &target,
430-
const AddressRange &disasm_range,
431-
bool force_live_memory = false);
428+
static lldb::DisassemblerSP
429+
DisassembleRange(const ArchSpec &arch, const char *plugin_name,
430+
const char *flavor, const char *cpu, const char *features,
431+
Target &target, const AddressRange &disasm_range,
432+
bool force_live_memory = false);
432433

433434
static lldb::DisassemblerSP
434435
DisassembleBytes(const ArchSpec &arch, const char *plugin_name,
435-
const char *flavor, const Address &start, const void *bytes,
436-
size_t length, uint32_t max_num_instructions,
437-
bool data_from_file);
436+
const char *flavor, const char *cpu, const char *features,
437+
const Address &start, const void *bytes, size_t length,
438+
uint32_t max_num_instructions, bool data_from_file);
438439

439440
static bool Disassemble(Debugger &debugger, const ArchSpec &arch,
440441
const char *plugin_name, const char *flavor,
442+
const char *cpu, const char *features,
441443
const ExecutionContext &exe_ctx, const Address &start,
442444
Limit limit, bool mixed_source_and_assembly,
443445
uint32_t num_mixed_context_lines, uint32_t options,

lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,8 @@ static constexpr CommandObject::ArgumentTableEntry g_argument_table[] = {
334334
{ lldb::eArgTypeRemotePath, "remote-path", lldb::CompletionType::eRemoteDiskFileCompletion, {}, { nullptr, false }, "A path on the system managed by the current platform." },
335335
{ lldb::eArgTypeRemoteFilename, "remote-filename", lldb::CompletionType::eRemoteDiskFileCompletion, {}, { nullptr, false }, "A file on the system managed by the current platform." },
336336
{ lldb::eArgTypeModule, "module", lldb::CompletionType::eModuleCompletion, {}, { nullptr, false }, "The name of a module loaded into the current target." },
337+
{ lldb::eArgTypeCPUName, "cpu-name", lldb::CompletionType::eNoCompletion, {}, { nullptr, false }, "The name of a CPU." },
338+
{ lldb::eArgTypeCPUFeatures, "cpu-features", lldb::CompletionType::eNoCompletion, {}, { nullptr, false }, "The CPU feature string." },
337339
// clang-format on
338340
};
339341

lldb/include/lldb/Target/Target.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,10 @@ class TargetProperties : public Properties {
130130

131131
const char *GetDisassemblyFlavor() const;
132132

133+
const char *GetDisassemblyCPU() const;
134+
135+
const char *GetDisassemblyFeatures() const;
136+
133137
InlineStrategy GetInlineStrategy() const;
134138

135139
llvm::StringRef GetArg0() const;

lldb/include/lldb/lldb-enumerations.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,8 @@ enum CommandArgumentType {
667667
eArgTypeRemotePath,
668668
eArgTypeRemoteFilename,
669669
eArgTypeModule,
670+
eArgTypeCPUName,
671+
eArgTypeCPUFeatures,
670672
eArgTypeLastArg // Always keep this entry as the last entry in this
671673
// enumeration!!
672674
};

lldb/include/lldb/lldb-private-interfaces.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ typedef lldb::ABISP (*ABICreateInstance)(lldb::ProcessSP process_sp,
2929
const ArchSpec &arch);
3030
typedef std::unique_ptr<Architecture> (*ArchitectureCreateInstance)(
3131
const ArchSpec &arch);
32-
typedef lldb::DisassemblerSP (*DisassemblerCreateInstance)(const ArchSpec &arch,
33-
const char *flavor);
32+
typedef lldb::DisassemblerSP (*DisassemblerCreateInstance)(
33+
const ArchSpec &arch, const char *flavor, const char *cpu,
34+
const char *features);
3435
typedef DynamicLoader *(*DynamicLoaderCreateInstance)(Process *process,
3536
bool force);
3637
typedef lldb::JITLoaderSP (*JITLoaderCreateInstance)(Process *process,

lldb/source/API/SBFunction.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,9 @@ SBInstructionList SBFunction::GetInstructions(SBTarget target,
125125
lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
126126
const bool force_live_memory = true;
127127
sb_instructions.SetDisassembler(Disassembler::DisassembleRange(
128-
module_sp->GetArchitecture(), nullptr, flavor, *target_sp,
129-
m_opaque_ptr->GetAddressRange(), force_live_memory));
128+
module_sp->GetArchitecture(), nullptr, flavor,
129+
target_sp->GetDisassemblyCPU(), target_sp->GetDisassemblyFeatures(),
130+
*target_sp, m_opaque_ptr->GetAddressRange(), force_live_memory));
130131
}
131132
}
132133
return sb_instructions;

lldb/source/API/SBSymbol.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,9 @@ SBInstructionList SBSymbol::GetInstructions(SBTarget target,
126126
AddressRange symbol_range(symbol_addr, m_opaque_ptr->GetByteSize());
127127
const bool force_live_memory = true;
128128
sb_instructions.SetDisassembler(Disassembler::DisassembleRange(
129-
module_sp->GetArchitecture(), nullptr, flavor_string, *target_sp,
130-
symbol_range, force_live_memory));
129+
module_sp->GetArchitecture(), nullptr, flavor_string,
130+
target_sp->GetDisassemblyCPU(), target_sp->GetDisassemblyFeatures(),
131+
*target_sp, symbol_range, force_live_memory));
131132
}
132133
}
133134
}

lldb/source/API/SBTarget.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2072,7 +2072,8 @@ lldb::SBInstructionList SBTarget::ReadInstructions(lldb::SBAddress base_addr,
20722072
error, force_live_memory, &load_addr);
20732073
const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
20742074
sb_instructions.SetDisassembler(Disassembler::DisassembleBytes(
2075-
target_sp->GetArchitecture(), nullptr, flavor_string, *addr_ptr,
2075+
target_sp->GetArchitecture(), nullptr, target_sp->GetDisassemblyCPU(),
2076+
target_sp->GetDisassemblyFeatures(), flavor_string, *addr_ptr,
20762077
data.GetBytes(), bytes_read, count, data_from_file));
20772078
}
20782079
}
@@ -2097,8 +2098,9 @@ lldb::SBInstructionList SBTarget::ReadInstructions(lldb::SBAddress start_addr,
20972098
AddressRange range(start_load_addr, size);
20982099
const bool force_live_memory = true;
20992100
sb_instructions.SetDisassembler(Disassembler::DisassembleRange(
2100-
target_sp->GetArchitecture(), nullptr, flavor_string, *target_sp,
2101-
range, force_live_memory));
2101+
target_sp->GetArchitecture(), nullptr, flavor_string,
2102+
target_sp->GetDisassemblyCPU(), target_sp->GetDisassemblyFeatures(),
2103+
*target_sp, range, force_live_memory));
21022104
}
21032105
}
21042106
return sb_instructions;
@@ -2130,8 +2132,9 @@ SBTarget::GetInstructionsWithFlavor(lldb::SBAddress base_addr,
21302132
const bool data_from_file = true;
21312133

21322134
sb_instructions.SetDisassembler(Disassembler::DisassembleBytes(
2133-
target_sp->GetArchitecture(), nullptr, flavor_string, addr, buf, size,
2134-
UINT32_MAX, data_from_file));
2135+
target_sp->GetArchitecture(), nullptr, flavor_string,
2136+
target_sp->GetDisassemblyCPU(), target_sp->GetDisassemblyFeatures(),
2137+
addr, buf, size, UINT32_MAX, data_from_file));
21352138
}
21362139

21372140
return sb_instructions;

lldb/source/Commands/CommandObjectDisassemble.cpp

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,14 @@ Status CommandObjectDisassemble::CommandOptions::SetOptionValue(
120120
break;
121121
}
122122

123+
case 'X':
124+
cpu_string = std::string(option_arg);
125+
break;
126+
127+
case 'Y':
128+
features_string = std::string(option_arg);
129+
break;
130+
123131
case 'r':
124132
raw = true;
125133
break;
@@ -176,20 +184,27 @@ void CommandObjectDisassemble::CommandOptions::OptionParsingStarting(
176184
Target *target =
177185
execution_context ? execution_context->GetTargetPtr() : nullptr;
178186

179-
// This is a hack till we get the ability to specify features based on
180-
// architecture. For now GetDisassemblyFlavor is really only valid for x86
181-
// (and for the llvm assembler plugin, but I'm papering over that since that
182-
// is the only disassembler plugin we have...
183187
if (target) {
188+
// This is a hack till we get the ability to specify features based on
189+
// architecture. For now GetDisassemblyFlavor is really only valid for x86
190+
// (and for the llvm assembler plugin, but I'm papering over that since that
191+
// is the only disassembler plugin we have...
184192
if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86 ||
185193
target->GetArchitecture().GetTriple().getArch() ==
186194
llvm::Triple::x86_64) {
187195
flavor_string.assign(target->GetDisassemblyFlavor());
188-
} else
196+
} else {
189197
flavor_string.assign("default");
190-
191-
} else
198+
}
199+
if (const char *cpu = target->GetDisassemblyCPU())
200+
cpu_string.assign(cpu);
201+
if (const char *features = target->GetDisassemblyFeatures())
202+
features_string.assign(features);
203+
} else {
192204
flavor_string.assign("default");
205+
cpu_string.assign("default");
206+
features_string.assign("default");
207+
}
193208

194209
arch.Clear();
195210
some_location_specified = false;
@@ -453,9 +468,11 @@ void CommandObjectDisassemble::DoExecute(Args &command,
453468

454469
const char *plugin_name = m_options.GetPluginName();
455470
const char *flavor_string = m_options.GetFlavorString();
471+
const char *cpu_string = m_options.GetCPUString();
472+
const char *features_string = m_options.GetFeaturesString();
456473

457-
DisassemblerSP disassembler =
458-
Disassembler::FindPlugin(m_options.arch, flavor_string, plugin_name);
474+
DisassemblerSP disassembler = Disassembler::FindPlugin(
475+
m_options.arch, flavor_string, cpu_string, features_string, plugin_name);
459476

460477
if (!disassembler) {
461478
if (plugin_name) {
@@ -524,7 +541,8 @@ void CommandObjectDisassemble::DoExecute(Args &command,
524541
}
525542
if (Disassembler::Disassemble(
526543
GetDebugger(), m_options.arch, plugin_name, flavor_string,
527-
m_exe_ctx, cur_range.GetBaseAddress(), limit, m_options.show_mixed,
544+
cpu_string, features_string, m_exe_ctx, cur_range.GetBaseAddress(),
545+
limit, m_options.show_mixed,
528546
m_options.show_mixed ? m_options.num_lines_context : 0, options,
529547
result.GetOutputStream())) {
530548
result.SetStatus(eReturnStatusSuccessFinishResult);

lldb/source/Commands/CommandObjectDisassemble.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,18 @@ class CommandObjectDisassemble : public CommandObjectParsed {
4242
return flavor_string.c_str();
4343
}
4444

45+
const char *GetCPUString() {
46+
if (cpu_string.empty() || cpu_string == "default")
47+
return nullptr;
48+
return cpu_string.c_str();
49+
}
50+
51+
const char *GetFeaturesString() {
52+
if (features_string.empty() || features_string == "default")
53+
return nullptr;
54+
return features_string.c_str();
55+
}
56+
4557
Status OptionParsingFinished(ExecutionContext *execution_context) override;
4658

4759
bool show_mixed; // Show mixed source/assembly
@@ -58,6 +70,8 @@ class CommandObjectDisassemble : public CommandObjectParsed {
5870
bool frame_line = false;
5971
std::string plugin_name;
6072
std::string flavor_string;
73+
std::string cpu_string;
74+
std::string features_string;
6175
ArchSpec arch;
6276
bool some_location_specified = false; // If no location was specified, we'll
6377
// select "at_pc". This should be set

lldb/source/Commands/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,10 @@ let Command = "disassemble" in {
330330
Arg<"DisassemblyFlavor">, Desc<"Name of the disassembly flavor you want to "
331331
"use. Currently the only valid options are default, and for Intel "
332332
"architectures, att and intel.">;
333+
def disassemble_options_cpu : Option<"cpu", "X">, Arg<"CPUName">,
334+
Desc<"Override the CPU for disassembling.">;
335+
def disassemble_options_features : Option<"features", "Y">, Arg<"CPUFeatures">,
336+
Desc<"Specify additional CPU features for disassembling.">;
333337
def disassemble_options_arch : Option<"arch", "A">, Arg<"Architecture">,
334338
Desc<"Specify the architecture to use from cross disassembly.">;
335339
def disassemble_options_start_address : Option<"start-address", "s">,

lldb/source/Core/Disassembler.cpp

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ using namespace lldb;
5656
using namespace lldb_private;
5757

5858
DisassemblerSP Disassembler::FindPlugin(const ArchSpec &arch,
59-
const char *flavor,
59+
const char *flavor, const char *cpu,
60+
const char *features,
6061
const char *plugin_name) {
6162
LLDB_SCOPED_TIMERF("Disassembler::FindPlugin (arch = %s, plugin_name = %s)",
6263
arch.GetArchitectureName(), plugin_name);
@@ -67,34 +68,38 @@ DisassemblerSP Disassembler::FindPlugin(const ArchSpec &arch,
6768
create_callback =
6869
PluginManager::GetDisassemblerCreateCallbackForPluginName(plugin_name);
6970
if (create_callback) {
70-
if (auto disasm_sp = create_callback(arch, flavor))
71+
if (auto disasm_sp = create_callback(arch, flavor, cpu, features))
7172
return disasm_sp;
7273
}
7374
} else {
7475
for (uint32_t idx = 0;
7576
(create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(
7677
idx)) != nullptr;
7778
++idx) {
78-
if (auto disasm_sp = create_callback(arch, flavor))
79+
if (auto disasm_sp = create_callback(arch, flavor, cpu, features))
7980
return disasm_sp;
8081
}
8182
}
8283
return DisassemblerSP();
8384
}
8485

85-
DisassemblerSP Disassembler::FindPluginForTarget(const Target &target,
86-
const ArchSpec &arch,
87-
const char *flavor,
88-
const char *plugin_name) {
89-
if (flavor == nullptr) {
86+
DisassemblerSP Disassembler::FindPluginForTarget(
87+
const Target &target, const ArchSpec &arch, const char *flavor,
88+
const char *cpu, const char *features, const char *plugin_name) {
89+
if (!flavor) {
9090
// FIXME - we don't have the mechanism in place to do per-architecture
9191
// settings. But since we know that for now we only support flavors on x86
9292
// & x86_64,
9393
if (arch.GetTriple().getArch() == llvm::Triple::x86 ||
9494
arch.GetTriple().getArch() == llvm::Triple::x86_64)
9595
flavor = target.GetDisassemblyFlavor();
9696
}
97-
return FindPlugin(arch, flavor, plugin_name);
97+
if (!cpu)
98+
cpu = target.GetDisassemblyCPU();
99+
if (!features)
100+
features = target.GetDisassemblyFeatures();
101+
102+
return FindPlugin(arch, flavor, cpu, features, plugin_name);
98103
}
99104

100105
static Address ResolveAddress(Target &target, const Address &addr) {
@@ -117,15 +122,16 @@ static Address ResolveAddress(Target &target, const Address &addr) {
117122

118123
lldb::DisassemblerSP Disassembler::DisassembleRange(
119124
const ArchSpec &arch, const char *plugin_name, const char *flavor,
120-
Target &target, const AddressRange &range, bool force_live_memory) {
125+
const char *cpu, const char *features, Target &target,
126+
const AddressRange &range, bool force_live_memory) {
121127
if (range.GetByteSize() <= 0)
122128
return {};
123129

124130
if (!range.GetBaseAddress().IsValid())
125131
return {};
126132

127-
lldb::DisassemblerSP disasm_sp =
128-
Disassembler::FindPluginForTarget(target, arch, flavor, plugin_name);
133+
lldb::DisassemblerSP disasm_sp = Disassembler::FindPluginForTarget(
134+
target, arch, flavor, cpu, features, plugin_name);
129135

130136
if (!disasm_sp)
131137
return {};
@@ -141,14 +147,15 @@ lldb::DisassemblerSP Disassembler::DisassembleRange(
141147

142148
lldb::DisassemblerSP
143149
Disassembler::DisassembleBytes(const ArchSpec &arch, const char *plugin_name,
144-
const char *flavor, const Address &start,
150+
const char *flavor, const char *cpu,
151+
const char *features, const Address &start,
145152
const void *src, size_t src_len,
146153
uint32_t num_instructions, bool data_from_file) {
147154
if (!src)
148155
return {};
149156

150157
lldb::DisassemblerSP disasm_sp =
151-
Disassembler::FindPlugin(arch, flavor, plugin_name);
158+
Disassembler::FindPlugin(arch, flavor, cpu, features, plugin_name);
152159

153160
if (!disasm_sp)
154161
return {};
@@ -163,6 +170,7 @@ Disassembler::DisassembleBytes(const ArchSpec &arch, const char *plugin_name,
163170

164171
bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
165172
const char *plugin_name, const char *flavor,
173+
const char *cpu, const char *features,
166174
const ExecutionContext &exe_ctx,
167175
const Address &address, Limit limit,
168176
bool mixed_source_and_assembly,
@@ -172,7 +180,7 @@ bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
172180
return false;
173181

174182
lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget(
175-
exe_ctx.GetTargetRef(), arch, flavor, plugin_name));
183+
exe_ctx.GetTargetRef(), arch, flavor, cpu, features, plugin_name));
176184
if (!disasm_sp)
177185
return false;
178186

@@ -558,8 +566,8 @@ bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
558566
if (limit.value == 0)
559567
limit.value = DEFAULT_DISASM_BYTE_SIZE;
560568

561-
return Disassemble(debugger, arch, nullptr, nullptr, frame,
562-
range.GetBaseAddress(), limit, false, 0, 0, strm);
569+
return Disassemble(debugger, arch, nullptr, nullptr, nullptr, nullptr,
570+
frame, range.GetBaseAddress(), limit, false, 0, 0, strm);
563571
}
564572

565573
Instruction::Instruction(const Address &address, AddressClass addr_class)

0 commit comments

Comments
 (0)