From 8f7180b11e024406e50ed53e27c95af461e6ec4d Mon Sep 17 00:00:00 2001 From: Greg Clayton Date: Mon, 26 Sep 2011 07:11:27 +0000 Subject: Added more functionality to the public API to allow for better symbolication. Also improved the SBInstruction API to allow access to the instruction opcode name, mnemonics, comment and instruction data. Added the ability to edit SBLineEntry objects (change the file, line and column), and also allow SBSymbolContext objects to be modified (set module, comp unit, function, block, line entry or symbol). The SymbolContext and SBSymbolContext can now generate inlined call stack infomration for symbolication much easier using the SymbolContext::GetParentInlinedFrameInfo(...) and SBSymbolContext::GetParentInlinedFrameInfo(...) methods. llvm-svn: 140518 --- .../Plugins/Disassembler/llvm/DisassemblerLLVM.cpp | 172 +++++++++++++++++++-- 1 file changed, 158 insertions(+), 14 deletions(-) (limited to 'lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp') diff --git a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp index a8c423f44e6..610271deb98 100644 --- a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp +++ b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp @@ -99,13 +99,15 @@ PadString(Stream *s, const std::string &str, size_t width) s->Printf("%s ", str.c_str()); } static void -AddSymbolicInfo(const ExecutionContext *exe_ctx, ExecutionContextScope *exe_scope, - StreamString &comment, uint64_t operand_value, const Address &inst_addr) +AddSymbolicInfo (ExecutionContextScope *exe_scope, + StreamString &comment, + uint64_t operand_value, + const Address &inst_addr) { Address so_addr; Target *target = NULL; - if (exe_ctx) - target = exe_ctx->GetTargetPtr(); + if (exe_scope) + target = exe_scope->CalculateTarget(); if (target && !target->GetSectionLoadList().IsEmpty()) { if (target->GetSectionLoadList().ResolveLoadAddress(operand_value, so_addr)) @@ -225,12 +227,16 @@ InstructionLLVM::Dump if (numTokens != -1 && !raw) { addr_t base_addr = LLDB_INVALID_ADDRESS; - + uint32_t addr_nibble_size = 8; Target *target = NULL; if (exe_ctx) target = exe_ctx->GetTargetPtr(); - if (target && !target->GetSectionLoadList().IsEmpty()) - base_addr = GetAddress().GetLoadAddress (target); + if (target) + { + if (!target->GetSectionLoadList().IsEmpty()) + base_addr = GetAddress().GetLoadAddress (target); + addr_nibble_size = target->GetArchitecture().GetAddressByteSize() * 2; + } if (base_addr == LLDB_INVALID_ADDRESS) base_addr = GetAddress().GetFileAddress (); @@ -314,16 +320,16 @@ InstructionLLVM::Dump { if (EDInstIsBranch(m_inst)) { - operands.Printf("0x%llx ", operand_value); + operands.Printf("0x%*.*llx ", addr_nibble_size, addr_nibble_size, operand_value); show_token = false; } else { // Put the address value into the comment - comment.Printf("0x%llx ", operand_value); + comment.Printf("0x%*.*llx ", addr_nibble_size, addr_nibble_size, operand_value); } - AddSymbolicInfo(exe_ctx, exe_scope, comment, operand_value, GetAddress()); + AddSymbolicInfo(exe_scope, comment, operand_value, GetAddress()); } // EDEvaluateOperand } // EDOperandIsMemory } // EDGetOperand @@ -351,8 +357,8 @@ InstructionLLVM::Dump if (EDGetInstString(&inst_str, m_inst) == 0 && (pos = strstr(inst_str, "#")) != NULL) { uint64_t operand_value = PC + atoi(++pos); // Put the address value into the operands. - operands.Printf("0x%llx ", operand_value); - AddSymbolicInfo(exe_ctx, exe_scope, comment, operand_value, GetAddress()); + operands.Printf("0x%8.8llx ", operand_value); + AddSymbolicInfo(exe_scope, comment, operand_value, GetAddress()); } } // Yet more workaround for "bl #..." and "blx #...". @@ -369,12 +375,12 @@ InstructionLLVM::Dump } uint64_t operand_value = PC + atoi(++pos); // Put the address value into the comment. - comment.Printf("0x%llx ", operand_value); + comment.Printf("0x%8.8llx ", operand_value); // And the original token string into the operands. llvm::StringRef Str(pos - 1); RStrip(Str, '\n'); operands.PutCString(Str.str().c_str()); - AddSymbolicInfo(exe_ctx, exe_scope, comment, operand_value, GetAddress()); + AddSymbolicInfo(exe_scope, comment, operand_value, GetAddress()); } } // END of workaround. @@ -423,6 +429,144 @@ InstructionLLVM::Dump } } +void +InstructionLLVM::CalculateOpcodeName (ExecutionContextScope *exe_scope) +{ + const int num_tokens = EDNumTokens(m_inst); + if (num_tokens > 0) + { + const char *token_cstr = NULL; + int currentOpIndex = -1; + StreamString comment; + uint32_t addr_nibble_size = 8; + addr_t base_addr = LLDB_INVALID_ADDRESS; + Target *target = NULL; + if (exe_scope) + target = exe_scope->CalculateTarget(); + if (target && !target->GetSectionLoadList().IsEmpty()) + base_addr = GetAddress().GetLoadAddress (target); + if (base_addr == LLDB_INVALID_ADDRESS) + base_addr = GetAddress().GetFileAddress (); + addr_nibble_size = target->GetArchitecture().GetAddressByteSize() * 2; + + lldb::addr_t PC = base_addr + EDInstByteSize(m_inst); + + // When executing an ARM instruction, PC reads as the address of the + // current instruction plus 8. And for Thumb, it is plus 4. + if (m_arch_type == llvm::Triple::arm) + PC = base_addr + 8; + else if (m_arch_type == llvm::Triple::thumb) + PC = base_addr + 4; + + RegisterReaderArg rra(PC, m_disassembler); + + for (int token_idx = 0; token_idx < num_tokens; ++token_idx) + { + EDTokenRef token; + if (EDGetToken(&token, m_inst, token_idx)) + break; + + if (EDTokenIsOpcode(token) == 1) + { + if (EDGetTokenString(&token_cstr, token) == 0) // 0 on success + { + if (token_cstr) + m_opcode_name.assign(token_cstr); + } + } + else + { + int operandIndex = EDOperandIndexForToken(token); + + if (operandIndex >= 0) + { + if (operandIndex != currentOpIndex) + { + currentOpIndex = operandIndex; + EDOperandRef operand; + + if (!EDGetOperand(&operand, m_inst, currentOpIndex)) + { + if (EDOperandIsMemory(operand)) + { + uint64_t operand_value; + + if (!EDEvaluateOperand(&operand_value, operand, IPRegisterReader, &rra)) + { + comment.Printf("0x%*.*llx ", addr_nibble_size, addr_nibble_size, operand_value); + AddSymbolicInfo (exe_scope, comment, operand_value, GetAddress()); + } + } + } + } + } + if (m_mnemocics.empty() && EDTokenIsWhitespace (token) == 1) + continue; + if (EDGetTokenString (&token_cstr, token)) + break; + m_mnemocics.append (token_cstr); + } + } + // FIXME!!! + // Workaround for llvm::tB's operands not properly parsed by ARMAsmParser. + if (m_arch_type == llvm::Triple::thumb && m_opcode_name.compare("b") == 0) + { + const char *inst_str; + const char *pos = NULL; + comment.Clear(); + if (EDGetInstString(&inst_str, m_inst) == 0 && (pos = strstr(inst_str, "#")) != NULL) + { + uint64_t operand_value = PC + atoi(++pos); + // Put the address value into the operands. + comment.Printf("0x%*.*llx ", addr_nibble_size, addr_nibble_size, operand_value); + AddSymbolicInfo (exe_scope, comment, operand_value, GetAddress()); + } + } + // Yet more workaround for "bl #..." and "blx #...". + if ((m_arch_type == llvm::Triple::arm || m_arch_type == llvm::Triple::thumb) && + (m_opcode_name.compare("bl") == 0 || m_opcode_name.compare("blx") == 0)) + { + const char *inst_str; + const char *pos = NULL; + comment.Clear(); + if (EDGetInstString(&inst_str, m_inst) == 0 && (pos = strstr(inst_str, "#")) != NULL) + { + if (m_arch_type == llvm::Triple::thumb && m_opcode_name.compare("blx") == 0) + { + // A8.6.23 BLX (immediate) + // Target Address = Align(PC,4) + offset value + PC = AlignPC(PC); + } + uint64_t operand_value = PC + atoi(++pos); + // Put the address value into the comment. + comment.Printf("0x%*.*llx ", addr_nibble_size, addr_nibble_size, operand_value); + // And the original token string into the operands. +// llvm::StringRef Str(pos - 1); +// RStrip(Str, '\n'); +// operands.PutCString(Str.str().c_str()); + AddSymbolicInfo (exe_scope, comment, operand_value, GetAddress()); + } + } + // END of workaround. + + m_comment.swap (comment.GetString()); + } +} + +void +InstructionLLVM::CalculateMnemonics(ExecutionContextScope *exe_scope) +{ + // Do all of the work in CalculateOpcodeName() + CalculateOpcodeName (exe_scope); +} + +void +InstructionLLVM::CalculateComment(ExecutionContextScope *exe_scope) +{ + // Do all of the work in CalculateOpcodeName() + CalculateOpcodeName (exe_scope); +} + bool InstructionLLVM::DoesBranch() const { -- cgit v1.2.3