[Lldb-commits] [PATCH] D139955: [LLDB] Change formatting to use llvm::formatv
ayermolo updated this revision to Diff 486719. ayermolo added a comment. removed + Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D139955/new/ https://reviews.llvm.org/D139955 Files: lldb/include/lldb/Core/Module.h lldb/include/lldb/Utility/Status.h lldb/source/Core/Module.cpp lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp lldb/source/Symbol/CompileUnit.cpp lldb/source/Symbol/DWARFCallFrameInfo.cpp lldb/source/Target/SectionLoadList.cpp lldb/test/Shell/SymbolFile/DWARF/DW_AT_range-DW_FORM_sec_offset.s lldb/test/Shell/SymbolFile/DWARF/x86/debug_ranges-missing-section.s Index: lldb/test/Shell/SymbolFile/DWARF/x86/debug_ranges-missing-section.s === --- lldb/test/Shell/SymbolFile/DWARF/x86/debug_ranges-missing-section.s +++ lldb/test/Shell/SymbolFile/DWARF/x86/debug_ranges-missing-section.s @@ -2,7 +2,7 @@ # RUN: %lldb %t -o "image lookup -v -s lookup_ranges" -o exit 2>%t.error | FileCheck %s # RUN: cat %t.error | FileCheck %s --check-prefix ERROR -# ERROR: DIE has DW_AT_ranges(DW_FORM_sec_offset 0x47) attribute, but range extraction failed (No debug_ranges section), +# ERROR: DIE has DW_AT_ranges(DW_FORM_sec_offset 0x0047) attribute, but range extraction failed (No debug_ranges section), # CHECK: Function: id = {0x001c}, name = "ranges", range = [0x-0x0004) # CHECK:Blocks: id = {0x001c}, range = [0x-0x0004) Index: lldb/test/Shell/SymbolFile/DWARF/DW_AT_range-DW_FORM_sec_offset.s === --- lldb/test/Shell/SymbolFile/DWARF/DW_AT_range-DW_FORM_sec_offset.s +++ lldb/test/Shell/SymbolFile/DWARF/DW_AT_range-DW_FORM_sec_offset.s @@ -22,7 +22,7 @@ # RUN: cat %t.error | FileCheck --check-prefix=ERROR %s # RNGLISTX-LABEL: image lookup -v -s lookup_rnglists -# ERROR: error: {{.*}} {0x003f}: DIE has DW_AT_ranges(DW_FORM_rnglistx 0x0) attribute, but range extraction failed (DW_FORM_rnglistx cannot be used without DW_AT_rnglists_base for CU at 0x), please file a bug and attach the file at the start of this error message +# ERROR: error: {{.*}} [0x003f]: DIE has DW_AT_ranges(DW_FORM_rnglistx 0x) attribute, but range extraction failed (DW_FORM_rnglistx cannot be used without DW_AT_rnglists_base for CU at 0x), please file a bug and attach the file at the start of this error message # RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj \ # RUN: --defsym RNGLISTX=0 --defsym RNGLISTBASE=0 %s > %t-rnglistbase @@ -31,7 +31,7 @@ # RUN: cat %t.error | FileCheck --check-prefix=ERRORBASE %s # RNGLISTBASE-LABEL: image lookup -v -s lookup_rnglists -# ERRORBASE: error: {{.*}}-rnglistbase {0x0043}: DIE has DW_AT_ranges(DW_FORM_rnglistx 0x0) attribute, but range extraction failed (invalid range list table index 0; OffsetEntryCount is 0, DW_AT_rnglists_base is 24), please file a bug and attach the file at the start of this error message +# ERRORBASE: error: {{.*}}-rnglistbase [0x0043]: DIE has DW_AT_ranges(DW_FORM_rnglistx 0x) attribute, but range extraction failed (invalid range list table index 0; OffsetEntryCount is 0, DW_AT_rnglists_base is 24), please file a bug and attach the file at the start of this error message .text rnglists: Index: lldb/source/Target/SectionLoadList.cpp === --- lldb/source/Target/SectionLoadList.cpp +++ lldb/source/Target/SectionLoadList.cpp @@ -106,8 +106,8 @@ ModuleSP curr_module_sp(ats_pos->second->GetModule()); if (curr_module_sp) { module_sp->ReportWarning( -"address 0x%16.16" PRIx64 -" maps to more than one section: %s.%s and %s.%s", +"address {0:x16} maps to more than one section: {1}.{2} and " +"{3}.{4}", load_addr, module_sp->GetFileSpec().GetFilename().GetCString(), section->GetName().GetCString(),
[Lldb-commits] [PATCH] D140999: [NFC][TargetParser] Deprecate llvm/Support/AArch64TargetParser.h
MaskRay accepted this revision. MaskRay added a comment. I don't think it is necessary to deprecate the old header then delete it after 16.0.0 is branched. llvm/Support/AArch64TargetParser.h has very few open-source out-of-tree uses. Perhaps only ldc `driver/targetmachine.cpp` uses the header. So it is not worth extra expedience. Changing the include to `#include "llvm/TargetParser/AArch64TargetParser.h"` is totally fine, though. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D140999/new/ https://reviews.llvm.org/D140999 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D140358: [lldb-vscode] Add support for disassembly view
clayborg added inline comments. Comment at: lldb/tools/lldb-vscode/lldb-vscode.cpp:2177 + const auto bytes_offset = -instruction_offset * bytes_per_instruction; + auto start_addr = base_addr - bytes_offset; + const auto disassemble_bytes = instruction_count * bytes_per_instruction; eloparco wrote: > clayborg wrote: > > This will work if the min and max opcode byte size are the same, like for > > arm64, the min and max are 4. This won't work for x86 or arm32 in thumb > > mode. So when backing up, we need to do an address lookup on the address we > > think we want to go to, and then adjust the starting address accordingly. > > Something like: > > > > ``` > > SBAddress start_sbaddr = (base_addr - bytes_offset, g_vsc.target); > > ``` > > now we have a section offset address that can tell us more about what it > > is. We can find the SBFunction or SBSymbol for this address and use those > > to find the right instructions. This will allow us to correctly disassemble > > code bytes. > > > > We can also look at the section that the memory comes from and see what the > > section contains. If the section is data, then emit something like: > > ``` > > 0x1000 .byte 0x23 > > 0x1001 .byte 0x34 > > ... > > ``` > > To find the section type we can do: > > ``` > > SBSection section = start_sbaddr.GetSection(); > > if (section.IsValid() && section.GetSectionType() == > > lldb::eSectionTypeCode) { > > // Disassemble from a valid boundary > > } else { > > // Emit a byte or long at a time with ".byte 0xXX" or other ASM directive > > for binary data > > } > > ``` > > We need to ensure we start disassembling on the correct instruction > > boundary as well as our math for "start_addr" might be in between actual > > opcode boundaries. If we are in a lldb::eSectionTypeCode, then we know we > > have instructions, and if we are not, then we can emit ".byte" or other > > binary data directives. So if we do have lldb::eSectionTypeCode as our > > section type, then we should have a function or symbol, and we can get > > instructions from those objects easily: > > > > ``` > > if (section.IsValid() && section.GetSectionType() == > > lldb::eSectionTypeCode) { > > lldb::SBInstructionList instructions; > > lldb::SBFunction function = start_sbaddr.GetFunction(); > > if (function.IsValid()) { > > instructions = function.GetInstructions(g_vsc.target); > > } else { > > symbol = start_sbaddr.GetSymbol(); > > if (symbol.IsValid()) > > instructions = symbol.GetInstructions(g_vsc.target); > > } > > const size_t num_instrs = instructions.GetSize(); > > if (num_instrs > 0) { > > // we found instructions from a function or symbol and we need to > > // find the matching instruction that we want to start from by iterating > > // over the instructions and finding the right address > > size_t matching_idx = num_instrs; // Invalid index > > for (size_t i=0; i > lldb::SBInstruction inst = instructions.GetInstructionAtIndex(i); > > if (inst.GetAddress().GetLoadAddress(g_vsc.target) >= start_addr) { > > matching_idx = i; > > break; > > } > > } > > if (matching_idx < num_instrs) { > > // Now we can print the instructions from [matching_idx, num_instrs) > > // then we need to repeat the search for the next function or symbol. > > // note there may be bytes between functions or symbols which we can > > disassemble > > // by calling _get_instructions_from_memory(...) but we must find the > > next > > // symbol or function boundary and get back on track > > } > > > > ``` > Sorry, I should have provided a proper explanation. > > I use the maximum instruction size as the "worst case". Basically, I need to > read a portion of memory but I do not know the start address and the size. > For the start address, if I want to read N instructions before `base_addr` I > need to read at least starting from `base_addr - N * max_instruction_size`: > if all instructions are of size `max_instruction_size` I will read exactly N > instructions; otherwise I will read more than N instructions and prune the > additional ones afterwards. Same for applies for the size. > > Since `start_addr` is based on a "worst case", it may be an address in the > middle of an instruction. In that case, that first instruction will be > misinterpreted, but I think that is negligible. > > The logic is similar to what is implemented in other VS Code extensions, like > https://github.com/vadimcn/vscode-lldb/blob/master/adapter/src/debug_session.rs#L1134. > > Does it make sense? The issue is, you might end up backing up by N bytes, and you might not end up on an opcode boundary. Lets say you have x86 disassembly like: ``` 0x12e37 <+183>: 48 8b 4d f8 movq -0x8(%rbp), %rcx 0x12e3b <+187>: 48 39 c8 cmpq %rcx, %rax 0x12e3e <+190>: 0f 85 09 00 00 00jne0x12e4d
[Lldb-commits] [PATCH] D141042: [lldb] Allow configuring on Windows with python interpreter within a junction
clayborg accepted this revision. clayborg added a comment. lgtm Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D141042/new/ https://reviews.llvm.org/D141042 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D141087: Revert an unintentional API ABI break
This revision was automatically updated to reflect the committed changes. Closed by commit rG69f2b5fcf1be: Revert an unintentional API ABI break (authored by aprantl). Herald added a project: LLDB. Herald added a subscriber: lldb-commits. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D141087/new/ https://reviews.llvm.org/D141087 Files: lldb/include/lldb/lldb-enumerations.h Index: lldb/include/lldb/lldb-enumerations.h === --- lldb/include/lldb/lldb-enumerations.h +++ lldb/include/lldb/lldb-enumerations.h @@ -437,7 +437,10 @@ /// specification for ease of use and consistency. /// The enum -> string code is in Language.cpp, don't change this /// table without updating that code as well. -enum LanguageType : uint16_t { +/// +/// This datatype is used in SBExpressionOptions::SetLanguage() which +/// makes this type API. Do not change its underlying storage type! +enum LanguageType { eLanguageTypeUnknown = 0x,///< Unknown or invalid language value. eLanguageTypeC89 = 0x0001,///< ISO C:1989. eLanguageTypeC = 0x0002, ///< Non-standardized C, such as K Index: lldb/include/lldb/lldb-enumerations.h === --- lldb/include/lldb/lldb-enumerations.h +++ lldb/include/lldb/lldb-enumerations.h @@ -437,7 +437,10 @@ /// specification for ease of use and consistency. /// The enum -> string code is in Language.cpp, don't change this /// table without updating that code as well. -enum LanguageType : uint16_t { +/// +/// This datatype is used in SBExpressionOptions::SetLanguage() which +/// makes this type API. Do not change its underlying storage type! +enum LanguageType { eLanguageTypeUnknown = 0x,///< Unknown or invalid language value. eLanguageTypeC89 = 0x0001,///< ISO C:1989. eLanguageTypeC = 0x0002, ///< Non-standardized C, such as K ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] 69f2b5f - Revert an unintentional API ABI break
Author: Adrian Prantl Date: 2023-01-05T13:43:12-08:00 New Revision: 69f2b5fcf1be2226181cce21066f072279ba5d14 URL: https://github.com/llvm/llvm-project/commit/69f2b5fcf1be2226181cce21066f072279ba5d14 DIFF: https://github.com/llvm/llvm-project/commit/69f2b5fcf1be2226181cce21066f072279ba5d14.diff LOG: Revert an unintentional API ABI break lldb::LanguageType is used as a parameter in SBExpressionOptions::SetLanguage(), which actually makes this type API too. Commit 6eaedbb52f2a616e644e5acc7279c8b07c4cfe82 added a `: uint16_t` to it, which broke binary compatibility for the SBAPI. This patch reverts to the original enum. I tried moving the entire enum into include/API, but that created a cyclic module dependency between API and Utility. To keep things simple, this just reverts to the original code and adds a warning. rdar://103415402 Differential Revision: https://reviews.llvm.org/D141087 Added: Modified: lldb/include/lldb/lldb-enumerations.h Removed: diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index f4748d0030f56..f92e63cc45f42 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -437,7 +437,10 @@ FLAGS_ENUM(WatchpointEventType){ /// specification for ease of use and consistency. /// The enum -> string code is in Language.cpp, don't change this /// table without updating that code as well. -enum LanguageType : uint16_t { +/// +/// This datatype is used in SBExpressionOptions::SetLanguage() which +/// makes this type API. Do not change its underlying storage type! +enum LanguageType { eLanguageTypeUnknown = 0x,///< Unknown or invalid language value. eLanguageTypeC89 = 0x0001,///< ISO C:1989. eLanguageTypeC = 0x0002, ///< Non-standardized C, such as K ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D140066: Add a final fallback technique to the old Darwin dynamic loader plugin to find the dyld_all_image_infos structure
JDevlieghere accepted this revision. JDevlieghere added a comment. This revision is now accepted and ready to land. LGTM Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D140066/new/ https://reviews.llvm.org/D140066 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D141042: [lldb] Allow configuring on Windows with python interpreter within a junction
JDevlieghere accepted this revision. JDevlieghere added a comment. This revision is now accepted and ready to land. Looks reasonable to me. @lawrence_danna do you happen to remember why you wrote: exe = os.path.join(os.path.realpath(os.path.dirname(exe)), os.readlink(exe)) instead of exe = os.path.realpath(exe) which seems like it should be equivalent? Aand you're doing a `realpath` call anyway... Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D141042/new/ https://reviews.llvm.org/D141042 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D140358: [lldb-vscode] Add support for disassembly view
eloparco updated this revision to Diff 486554. eloparco added a comment. Add integration tests for disassemble request Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D140358/new/ https://reviews.llvm.org/D140358 Files: lldb/include/lldb/API/SBTarget.h lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py lldb/source/API/SBTarget.cpp lldb/test/API/tools/lldb-vscode/disassemble/Makefile lldb/test/API/tools/lldb-vscode/disassemble/TestVSCode_disassemble.py lldb/test/API/tools/lldb-vscode/disassemble/main.cpp lldb/tools/lldb-vscode/CMakeLists.txt lldb/tools/lldb-vscode/DisassembledInstruction.cpp lldb/tools/lldb-vscode/DisassembledInstruction.h lldb/tools/lldb-vscode/JSONUtils.cpp lldb/tools/lldb-vscode/JSONUtils.h lldb/tools/lldb-vscode/LLDBUtils.cpp lldb/tools/lldb-vscode/LLDBUtils.h lldb/tools/lldb-vscode/VSCode.h lldb/tools/lldb-vscode/VSCodeForward.h lldb/tools/lldb-vscode/lldb-vscode.cpp Index: lldb/tools/lldb-vscode/lldb-vscode.cpp === --- lldb/tools/lldb-vscode/lldb-vscode.cpp +++ lldb/tools/lldb-vscode/lldb-vscode.cpp @@ -1451,8 +1451,7 @@ // which may affect the outcome of tests. bool source_init_file = GetBoolean(arguments, "sourceInitFile", true); - g_vsc.debugger = - lldb::SBDebugger::Create(source_init_file, log_cb, nullptr); + g_vsc.debugger = lldb::SBDebugger::Create(source_init_file, log_cb, nullptr); g_vsc.progress_event_thread = std::thread(ProgressEventThreadFunction); // Start our event thread so we can receive events from the debugger, target, @@ -1542,6 +1541,8 @@ // The debug adapter supports 'logMessage' in breakpoint. body.try_emplace("supportsLogPoints", true); + body.try_emplace("supportsDisassembleRequest", true); + response.try_emplace("body", std::move(body)); g_vsc.SendJSON(llvm::json::Value(std::move(response))); } @@ -2117,6 +2118,163 @@ g_vsc.SendJSON(llvm::json::Value(std::move(response))); } +std::vector +_get_instructions_from_memory(lldb::addr_t start, uint64_t count) { + lldb::SBProcess process = g_vsc.target.GetProcess(); + + lldb::SBError error; + std::vector buffer(count, 0); + const size_t bytes_read __attribute__((unused)) = process.ReadMemory( + start, static_cast(buffer.data()), count, error); + assert(bytes_read == count && error.Success() && + "unable to read byte range from memory"); + + // If base_addr starts in the middle of an instruction, + // that first instruction will not be parsed correctly (negligible) + std::vector sb_instructions; + const auto base_addr = lldb::SBAddress(start, g_vsc.target); + lldb::SBInstructionList instructions = + g_vsc.target.GetInstructions(base_addr, buffer.data(), count); + + for (size_t i = 0; i < instructions.GetSize(); i++) { +auto instr = instructions.GetInstructionAtIndex(i); +sb_instructions.emplace_back(instr); + } + return sb_instructions; +} + +auto _handle_disassemble_positive_offset(lldb::addr_t base_addr, + int64_t instruction_offset, + uint64_t instruction_count) { + llvm::json::Array response_instructions; + + auto start_addr = + lldb::SBAddress(base_addr + instruction_offset, g_vsc.target); + lldb::SBInstructionList instructions = g_vsc.target.ReadInstructions( + start_addr, instruction_offset + instruction_count); + + std::vector dis_instructions; + const auto num_instrs_to_skip = static_cast(instruction_offset); + for (size_t i = num_instrs_to_skip; i < instructions.GetSize(); ++i) { +lldb::SBInstruction instr = instructions.GetInstructionAtIndex(i); + +auto disass_instr = +CreateDisassembledInstruction(DisassembledInstruction(instr)); +response_instructions.emplace_back(std::move(disass_instr)); + } + + return response_instructions; +} + +auto _handle_disassemble_negative_offset( +lldb::addr_t base_addr, int64_t instruction_offset, +uint64_t instruction_count, +std::optional memory_reference) { + llvm::json::Array response_instructions; + + const auto bytes_per_instruction = g_vsc.target.GetMaximumOpcodeByteSize(); + const auto bytes_offset = -instruction_offset * bytes_per_instruction; + auto start_addr = base_addr - bytes_offset; + const auto disassemble_bytes = instruction_count * bytes_per_instruction; + + auto sb_instructions = + _get_instructions_from_memory(start_addr, disassemble_bytes); + + // Find position of requested instruction + // in retrieved disassembled instructions + auto index = sb_instructions.size() + 1; + for (size_t i = 0; i < sb_instructions.size(); i++) { +if (sb_instructions[i].GetAddress().GetLoadAddress(g_vsc.target) == +base_addr) { + index = i; + break; +} + } + if (index == sb_instructions.size() + 1) { +g_vsc.SendOutput(OutputType::Console, +
[Lldb-commits] [PATCH] D140358: [lldb-vscode] Add support for disassembly view
eloparco updated this revision to Diff 486553. eloparco added a comment. Add integration tests for disassemble request Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D140358/new/ https://reviews.llvm.org/D140358 Files: lldb/include/lldb/API/SBTarget.h lldb/source/API/SBTarget.cpp lldb/tools/lldb-vscode/CMakeLists.txt lldb/tools/lldb-vscode/DisassembledInstruction.cpp lldb/tools/lldb-vscode/DisassembledInstruction.h lldb/tools/lldb-vscode/JSONUtils.cpp lldb/tools/lldb-vscode/JSONUtils.h lldb/tools/lldb-vscode/LLDBUtils.cpp lldb/tools/lldb-vscode/LLDBUtils.h lldb/tools/lldb-vscode/VSCode.h lldb/tools/lldb-vscode/VSCodeForward.h lldb/tools/lldb-vscode/lldb-vscode.cpp Index: lldb/tools/lldb-vscode/lldb-vscode.cpp === --- lldb/tools/lldb-vscode/lldb-vscode.cpp +++ lldb/tools/lldb-vscode/lldb-vscode.cpp @@ -1451,8 +1451,7 @@ // which may affect the outcome of tests. bool source_init_file = GetBoolean(arguments, "sourceInitFile", true); - g_vsc.debugger = - lldb::SBDebugger::Create(source_init_file, log_cb, nullptr); + g_vsc.debugger = lldb::SBDebugger::Create(source_init_file, log_cb, nullptr); g_vsc.progress_event_thread = std::thread(ProgressEventThreadFunction); // Start our event thread so we can receive events from the debugger, target, @@ -1542,6 +1541,8 @@ // The debug adapter supports 'logMessage' in breakpoint. body.try_emplace("supportsLogPoints", true); + body.try_emplace("supportsDisassembleRequest", true); + response.try_emplace("body", std::move(body)); g_vsc.SendJSON(llvm::json::Value(std::move(response))); } @@ -2117,6 +2118,163 @@ g_vsc.SendJSON(llvm::json::Value(std::move(response))); } +std::vector +_get_instructions_from_memory(lldb::addr_t start, uint64_t count) { + lldb::SBProcess process = g_vsc.target.GetProcess(); + + lldb::SBError error; + std::vector buffer(count, 0); + const size_t bytes_read __attribute__((unused)) = process.ReadMemory( + start, static_cast(buffer.data()), count, error); + assert(bytes_read == count && error.Success() && + "unable to read byte range from memory"); + + // If base_addr starts in the middle of an instruction, + // that first instruction will not be parsed correctly (negligible) + std::vector sb_instructions; + const auto base_addr = lldb::SBAddress(start, g_vsc.target); + lldb::SBInstructionList instructions = + g_vsc.target.GetInstructions(base_addr, buffer.data(), count); + + for (size_t i = 0; i < instructions.GetSize(); i++) { +auto instr = instructions.GetInstructionAtIndex(i); +sb_instructions.emplace_back(instr); + } + return sb_instructions; +} + +auto _handle_disassemble_positive_offset(lldb::addr_t base_addr, + int64_t instruction_offset, + uint64_t instruction_count) { + llvm::json::Array response_instructions; + + auto start_addr = + lldb::SBAddress(base_addr + instruction_offset, g_vsc.target); + lldb::SBInstructionList instructions = g_vsc.target.ReadInstructions( + start_addr, instruction_offset + instruction_count); + + std::vector dis_instructions; + const auto num_instrs_to_skip = static_cast(instruction_offset); + for (size_t i = num_instrs_to_skip; i < instructions.GetSize(); ++i) { +lldb::SBInstruction instr = instructions.GetInstructionAtIndex(i); + +auto disass_instr = +CreateDisassembledInstruction(DisassembledInstruction(instr)); +response_instructions.emplace_back(std::move(disass_instr)); + } + + return response_instructions; +} + +auto _handle_disassemble_negative_offset( +lldb::addr_t base_addr, int64_t instruction_offset, +uint64_t instruction_count, +std::optional memory_reference) { + llvm::json::Array response_instructions; + + const auto bytes_per_instruction = g_vsc.target.GetMaximumOpcodeByteSize(); + const auto bytes_offset = -instruction_offset * bytes_per_instruction; + auto start_addr = base_addr - bytes_offset; + const auto disassemble_bytes = instruction_count * bytes_per_instruction; + + auto sb_instructions = + _get_instructions_from_memory(start_addr, disassemble_bytes); + + // Find position of requested instruction + // in retrieved disassembled instructions + auto index = sb_instructions.size() + 1; + for (size_t i = 0; i < sb_instructions.size(); i++) { +if (sb_instructions[i].GetAddress().GetLoadAddress(g_vsc.target) == +base_addr) { + index = i; + break; +} + } + if (index == sb_instructions.size() + 1) { +g_vsc.SendOutput(OutputType::Console, + "current line not found in disassembled instructions"); +return response_instructions; + } + + // Copy instructions into queue to easily manipulate them + std::deque disass_instructions; + for (auto : sb_instructions) +
[Lldb-commits] [PATCH] D140358: [lldb-vscode] Add support for disassembly view
eloparco updated this revision to Diff 486514. eloparco added a comment. Remove printf usage Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D140358/new/ https://reviews.llvm.org/D140358 Files: lldb/include/lldb/API/SBTarget.h lldb/source/API/SBTarget.cpp lldb/tools/lldb-vscode/CMakeLists.txt lldb/tools/lldb-vscode/DisassembledInstruction.cpp lldb/tools/lldb-vscode/DisassembledInstruction.h lldb/tools/lldb-vscode/JSONUtils.cpp lldb/tools/lldb-vscode/JSONUtils.h lldb/tools/lldb-vscode/LLDBUtils.cpp lldb/tools/lldb-vscode/LLDBUtils.h lldb/tools/lldb-vscode/VSCode.h lldb/tools/lldb-vscode/VSCodeForward.h lldb/tools/lldb-vscode/lldb-vscode.cpp Index: lldb/tools/lldb-vscode/lldb-vscode.cpp === --- lldb/tools/lldb-vscode/lldb-vscode.cpp +++ lldb/tools/lldb-vscode/lldb-vscode.cpp @@ -1451,8 +1451,7 @@ // which may affect the outcome of tests. bool source_init_file = GetBoolean(arguments, "sourceInitFile", true); - g_vsc.debugger = - lldb::SBDebugger::Create(source_init_file, log_cb, nullptr); + g_vsc.debugger = lldb::SBDebugger::Create(source_init_file, log_cb, nullptr); g_vsc.progress_event_thread = std::thread(ProgressEventThreadFunction); // Start our event thread so we can receive events from the debugger, target, @@ -1542,6 +1541,8 @@ // The debug adapter supports 'logMessage' in breakpoint. body.try_emplace("supportsLogPoints", true); + body.try_emplace("supportsDisassembleRequest", true); + response.try_emplace("body", std::move(body)); g_vsc.SendJSON(llvm::json::Value(std::move(response))); } @@ -2117,6 +2118,163 @@ g_vsc.SendJSON(llvm::json::Value(std::move(response))); } +std::vector +_get_instructions_from_memory(lldb::addr_t start, uint64_t count) { + lldb::SBProcess process = g_vsc.target.GetProcess(); + + lldb::SBError error; + std::vector buffer(count, 0); + const size_t bytes_read __attribute__((unused)) = process.ReadMemory( + start, static_cast(buffer.data()), count, error); + assert(bytes_read == count && error.Success() && + "unable to read byte range from memory"); + + // If base_addr starts in the middle of an instruction, + // that first instruction will not be parsed correctly (negligible) + std::vector sb_instructions; + const auto base_addr = lldb::SBAddress(start, g_vsc.target); + lldb::SBInstructionList instructions = + g_vsc.target.GetInstructions(base_addr, buffer.data(), count); + + for (size_t i = 0; i < instructions.GetSize(); i++) { +auto instr = instructions.GetInstructionAtIndex(i); +sb_instructions.emplace_back(instr); + } + return sb_instructions; +} + +auto _handle_disassemble_positive_offset(lldb::addr_t base_addr, + int64_t instruction_offset, + uint64_t instruction_count) { + llvm::json::Array response_instructions; + + auto start_addr = + lldb::SBAddress(base_addr + instruction_offset, g_vsc.target); + lldb::SBInstructionList instructions = g_vsc.target.ReadInstructions( + start_addr, instruction_offset + instruction_count); + + std::vector dis_instructions; + const auto num_instrs_to_skip = static_cast(instruction_offset); + for (size_t i = num_instrs_to_skip; i < instructions.GetSize(); ++i) { +lldb::SBInstruction instr = instructions.GetInstructionAtIndex(i); + +auto disass_instr = +CreateDisassembledInstruction(DisassembledInstruction(instr)); +response_instructions.emplace_back(std::move(disass_instr)); + } + + return response_instructions; +} + +auto _handle_disassemble_negative_offset( +lldb::addr_t base_addr, int64_t instruction_offset, +uint64_t instruction_count, +std::optional memory_reference) { + llvm::json::Array response_instructions; + + const auto bytes_per_instruction = g_vsc.target.GetMaximumOpcodeByteSize(); + const auto bytes_offset = -instruction_offset * bytes_per_instruction; + auto start_addr = base_addr - bytes_offset; + const auto disassemble_bytes = instruction_count * bytes_per_instruction; + + auto sb_instructions = + _get_instructions_from_memory(start_addr, disassemble_bytes); + + // Find position of requested instruction + // in retrieved disassembled instructions + auto index = sb_instructions.size() + 1; + for (size_t i = 0; i < sb_instructions.size(); i++) { +if (sb_instructions[i].GetAddress().GetLoadAddress(g_vsc.target) == +base_addr) { + index = i; + break; +} + } + if (index == sb_instructions.size() + 1) { +g_vsc.SendOutput(OutputType::Console, + "current line not found in disassembled instructions"); +return response_instructions; + } + + // Copy instructions into queue to easily manipulate them + std::deque disass_instructions; + for (auto : sb_instructions) +
[Lldb-commits] [PATCH] D141042: [lldb] Allow configuring on Windows with python interpreter within a junction
zero9178 created this revision. zero9178 added reviewers: JDevlieghere, lawrence_danna, clayborg, labath, jingham. Herald added a project: All. zero9178 requested review of this revision. Herald added a project: LLDB. Herald added a subscriber: lldb-commits. The current implementation nicely takes into account when the python interpreter is symlinked (or transitively within a symlinked directory). Sadly, `os.path.islink` returns `false` on Windows if instead of Windows symlinks, junctions are used. This has caused me issues after I started using `scoop` as my package manager on Windows, which creates junctions instead of symlinks. The fix proposed in this patch is to check whether `realpath` returns a different path to `exe`, and if it does, to simply try again with that path. The code could also be simplified since `sys.executable` is guaranteed to be absolute, and `os.readlink`, which can return a relative path, is no longer used. Tested on Windows 11 with Python 3.11 as interpereter and Ubuntu 18.04 with Python 3.6 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D141042 Files: lldb/bindings/python/get-python-config.py Index: lldb/bindings/python/get-python-config.py === --- lldb/bindings/python/get-python-config.py +++ lldb/bindings/python/get-python-config.py @@ -51,8 +51,10 @@ break except ValueError: tried.append(exe) -if os.path.islink(exe): -exe = os.path.join(os.path.realpath(os.path.dirname(exe)), os.readlink(exe)) +# Retry if the executable is symlinked or similar. +# This is roughly equal to os.path.islink, except it also works for junctions on Windows. +if os.path.realpath(exe) != exe: +exe = os.path.realpath(exe) continue else: print("Could not find a relative path to sys.executable under sys.prefix", file=sys.stderr) Index: lldb/bindings/python/get-python-config.py === --- lldb/bindings/python/get-python-config.py +++ lldb/bindings/python/get-python-config.py @@ -51,8 +51,10 @@ break except ValueError: tried.append(exe) -if os.path.islink(exe): -exe = os.path.join(os.path.realpath(os.path.dirname(exe)), os.readlink(exe)) +# Retry if the executable is symlinked or similar. +# This is roughly equal to os.path.islink, except it also works for junctions on Windows. +if os.path.realpath(exe) != exe: +exe = os.path.realpath(exe) continue else: print("Could not find a relative path to sys.executable under sys.prefix", file=sys.stderr) ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D140358: [lldb-vscode] Add support for disassembly view
eloparco added inline comments. Comment at: lldb/tools/lldb-vscode/lldb-vscode.cpp:2194 + if (index == sb_instructions.size() + 1) { +fprintf(stderr, "current line not found in disassembled instructions\n"); +return response_instructions; clayborg wrote: > Remove any and all printf, or fprintf statements. You can't print anything to > stderr or stdout as this is where the DAP packets are get emitted to. We do > make it so this won't affect lldb-vscode by doing some magic with the > STDOUT/STDERR file handles, but this output will be sent to /dev/null most > likely. You can print something to a console (using "g_vsc.SendOutput(...)" > is one way). I suppose I have to replace `llvm::errs()` too, right? Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D140358/new/ https://reviews.llvm.org/D140358 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D140358: [lldb-vscode] Add support for disassembly view
eloparco added inline comments. Comment at: lldb/tools/lldb-vscode/lldb-vscode.cpp:2177 + const auto bytes_offset = -instruction_offset * bytes_per_instruction; + auto start_addr = base_addr - bytes_offset; + const auto disassemble_bytes = instruction_count * bytes_per_instruction; clayborg wrote: > This will work if the min and max opcode byte size are the same, like for > arm64, the min and max are 4. This won't work for x86 or arm32 in thumb mode. > So when backing up, we need to do an address lookup on the address we think > we want to go to, and then adjust the starting address accordingly. Something > like: > > ``` > SBAddress start_sbaddr = (base_addr - bytes_offset, g_vsc.target); > ``` > now we have a section offset address that can tell us more about what it is. > We can find the SBFunction or SBSymbol for this address and use those to find > the right instructions. This will allow us to correctly disassemble code > bytes. > > We can also look at the section that the memory comes from and see what the > section contains. If the section is data, then emit something like: > ``` > 0x1000 .byte 0x23 > 0x1001 .byte 0x34 > ... > ``` > To find the section type we can do: > ``` > SBSection section = start_sbaddr.GetSection(); > if (section.IsValid() && section.GetSectionType() == lldb::eSectionTypeCode) { > // Disassemble from a valid boundary > } else { > // Emit a byte or long at a time with ".byte 0xXX" or other ASM directive > for binary data > } > ``` > We need to ensure we start disassembling on the correct instruction boundary > as well as our math for "start_addr" might be in between actual opcode > boundaries. If we are in a lldb::eSectionTypeCode, then we know we have > instructions, and if we are not, then we can emit ".byte" or other binary > data directives. So if we do have lldb::eSectionTypeCode as our section type, > then we should have a function or symbol, and we can get instructions from > those objects easily: > > ``` > if (section.IsValid() && section.GetSectionType() == lldb::eSectionTypeCode) { > lldb::SBInstructionList instructions; > lldb::SBFunction function = start_sbaddr.GetFunction(); > if (function.IsValid()) { > instructions = function.GetInstructions(g_vsc.target); > } else { > symbol = start_sbaddr.GetSymbol(); > if (symbol.IsValid()) > instructions = symbol.GetInstructions(g_vsc.target); > } > const size_t num_instrs = instructions.GetSize(); > if (num_instrs > 0) { > // we found instructions from a function or symbol and we need to > // find the matching instruction that we want to start from by iterating > // over the instructions and finding the right address > size_t matching_idx = num_instrs; // Invalid index > for (size_t i=0; i lldb::SBInstruction inst = instructions.GetInstructionAtIndex(i); > if (inst.GetAddress().GetLoadAddress(g_vsc.target) >= start_addr) { > matching_idx = i; > break; > } > } > if (matching_idx < num_instrs) { > // Now we can print the instructions from [matching_idx, num_instrs) > // then we need to repeat the search for the next function or symbol. > // note there may be bytes between functions or symbols which we can > disassemble > // by calling _get_instructions_from_memory(...) but we must find the next > // symbol or function boundary and get back on track > } > > ``` Sorry, I should have provided a proper explanation. I use the maximum instruction size as the "worst case". Basically, I need to read a portion of memory but I do not know the start address and the size. For the start address, if I want to read N instructions before `base_addr` I need to read at least starting from `base_addr - N * max_instruction_size`: if all instructions are of size `max_instruction_size` I will read exactly N instructions; otherwise I will read more than N instructions and prune the additional ones afterwards. Same for applies for the size. Since `start_addr` is based on a "worst case", it may be an address in the middle of an instruction. In that case, that first instruction will be misinterpreted, but I think that is negligible. The logic is similar to what is implemented in other VS Code extensions, like https://github.com/vadimcn/vscode-lldb/blob/master/adapter/src/debug_session.rs#L1134. Does it make sense? Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D140358/new/ https://reviews.llvm.org/D140358 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D140999: [NFC][TargetParser] Deprecate llvm/Support/AArch64TargetParser.h
pratlucas accepted this revision. pratlucas added a comment. This revision is now accepted and ready to land. LGTM. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D140999/new/ https://reviews.llvm.org/D140999 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits