[lldb][NFC] Fix all formatting errors in .cpp file headers
Summary:
A *.cpp file header in LLDB (and in LLDB) should like this:
```
//===-- TestUtilities.cpp -------------------------------------------------===//
```
However in LLDB most of our source files have arbitrary changes to this format and
these changes are spreading through LLDB as folks usually just use the existing
source files as templates for their new files (most notably the unnecessary
editor language indicator `-*- C++ -*-` is spreading and in every review
someone is pointing out that this is wrong, resulting in people pointing out that this
is done in the same way in other files).
This patch removes most of these inconsistencies including the editor language indicators,
all the different missing/additional '-' characters, files that center the file name, missing
trailing `===//` (mostly caused by clang-format breaking the line).
Reviewers: aprantl, espindola, jfb, shafik, JDevlieghere
Reviewed By: JDevlieghere
Subscribers: dexonsmith, wuzish, emaste, sdardis, nemanjai, kbarton, MaskRay, atanasyan, arphaman, jfb, abidh, jsji, JDevlieghere, usaxena95, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D73258
2020-01-24 15:23:27 +08:00
|
|
|
//===-- ArchitectureArm.cpp -----------------------------------------------===//
|
2017-10-26 05:05:31 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2017-10-26 05:05:31 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "Plugins/Architecture/Arm/ArchitectureArm.h"
|
|
|
|
#include "Plugins/Process/Utility/ARMDefines.h"
|
|
|
|
#include "Plugins/Process/Utility/InstructionUtils.h"
|
|
|
|
#include "lldb/Core/PluginManager.h"
|
|
|
|
#include "lldb/Target/RegisterContext.h"
|
|
|
|
#include "lldb/Target/Thread.h"
|
2017-11-14 00:16:33 +08:00
|
|
|
#include "lldb/Utility/ArchSpec.h"
|
2017-10-26 05:05:31 +08:00
|
|
|
|
|
|
|
using namespace lldb_private;
|
|
|
|
using namespace lldb;
|
|
|
|
|
2020-02-15 01:46:02 +08:00
|
|
|
LLDB_PLUGIN_DEFINE(ArchitectureArm)
|
2020-02-08 06:58:18 +08:00
|
|
|
|
2017-10-26 05:05:31 +08:00
|
|
|
void ArchitectureArm::Initialize() {
|
|
|
|
PluginManager::RegisterPlugin(GetPluginNameStatic(),
|
|
|
|
"Arm-specific algorithms",
|
|
|
|
&ArchitectureArm::Create);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ArchitectureArm::Terminate() {
|
|
|
|
PluginManager::UnregisterPlugin(&ArchitectureArm::Create);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<Architecture> ArchitectureArm::Create(const ArchSpec &arch) {
|
|
|
|
if (arch.GetMachine() != llvm::Triple::arm)
|
|
|
|
return nullptr;
|
|
|
|
return std::unique_ptr<Architecture>(new ArchitectureArm());
|
|
|
|
}
|
|
|
|
|
2018-06-27 15:01:07 +08:00
|
|
|
void ArchitectureArm::OverrideStopInfo(Thread &thread) const {
|
2018-05-01 00:49:04 +08:00
|
|
|
// We need to check if we are stopped in Thumb mode in a IT instruction and
|
|
|
|
// detect if the condition doesn't pass. If this is the case it means we
|
|
|
|
// won't actually execute this instruction. If this happens we need to clear
|
|
|
|
// the stop reason to no thread plans think we are stopped for a reason and
|
|
|
|
// the plans should keep going.
|
2017-10-26 05:05:31 +08:00
|
|
|
//
|
|
|
|
// We do this because when single stepping many ARM processes, debuggers
|
2018-05-01 00:49:04 +08:00
|
|
|
// often use the BVR/BCR registers that says "stop when the PC is not equal
|
|
|
|
// to its current value". This method of stepping means we can end up
|
|
|
|
// stopping on instructions inside an if/then block that wouldn't get
|
|
|
|
// executed. By fixing this we can stop the debugger from seeming like you
|
|
|
|
// stepped through both the "if" _and_ the "else" clause when source level
|
|
|
|
// stepping because the debugger stops regardless due to the BVR/BCR
|
2017-10-26 05:05:31 +08:00
|
|
|
// triggering a stop.
|
|
|
|
//
|
2018-05-01 00:49:04 +08:00
|
|
|
// It also means we can set breakpoints on instructions inside an an if/then
|
|
|
|
// block and correctly skip them if we use the BKPT instruction. The ARM and
|
|
|
|
// Thumb BKPT instructions are unconditional even when executed in a Thumb IT
|
|
|
|
// block.
|
2017-10-26 05:05:31 +08:00
|
|
|
//
|
2018-05-01 00:49:04 +08:00
|
|
|
// If your debugger inserts software traps in ARM/Thumb code, it will need to
|
|
|
|
// use 16 and 32 bit instruction for 16 and 32 bit thumb instructions
|
|
|
|
// respectively. If your debugger inserts a 16 bit thumb trap on top of a 32
|
|
|
|
// bit thumb instruction for an opcode that is inside an if/then, it will
|
|
|
|
// change the it/then to conditionally execute your
|
2017-10-26 05:05:31 +08:00
|
|
|
// 16 bit trap and then cause your program to crash if it executes the
|
|
|
|
// trailing 16 bits (the second half of the 32 bit thumb instruction you
|
|
|
|
// partially overwrote).
|
|
|
|
|
|
|
|
RegisterContextSP reg_ctx_sp(thread.GetRegisterContext());
|
|
|
|
if (!reg_ctx_sp)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const uint32_t cpsr = reg_ctx_sp->GetFlags(0);
|
|
|
|
if (cpsr == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Read the J and T bits to get the ISETSTATE
|
|
|
|
const uint32_t J = Bit32(cpsr, 24);
|
|
|
|
const uint32_t T = Bit32(cpsr, 5);
|
|
|
|
const uint32_t ISETSTATE = J << 1 | T;
|
|
|
|
if (ISETSTATE == 0) {
|
|
|
|
// NOTE: I am pretty sure we want to enable the code below
|
2018-05-01 00:49:04 +08:00
|
|
|
// that detects when we stop on an instruction in ARM mode that is conditional
|
|
|
|
// and the condition doesn't pass. This can happen if you set a breakpoint on
|
|
|
|
// an instruction that is conditional. We currently will _always_ stop on the
|
|
|
|
// instruction which is bad. You can also run into this while single stepping
|
|
|
|
// and you could appear to run code in the "if" and in the "else" clause
|
|
|
|
// because it would stop at all of the conditional instructions in both. In
|
|
|
|
// such cases, we really don't want to stop at this location.
|
2017-10-26 05:05:31 +08:00
|
|
|
// I will check with the lldb-dev list first before I enable this.
|
|
|
|
#if 0
|
2018-05-29 17:10:46 +08:00
|
|
|
// ARM mode: check for condition on instruction
|
2017-10-26 05:05:31 +08:00
|
|
|
const addr_t pc = reg_ctx_sp->GetPC();
|
|
|
|
Status error;
|
2018-05-01 00:49:04 +08:00
|
|
|
// If we fail to read the opcode we will get UINT64_MAX as the result in
|
|
|
|
// "opcode" which we can use to detect if we read a valid opcode.
|
2017-10-26 05:05:31 +08:00
|
|
|
const uint64_t opcode = thread.GetProcess()->ReadUnsignedIntegerFromMemory(pc, 4, UINT64_MAX, error);
|
|
|
|
if (opcode <= UINT32_MAX)
|
|
|
|
{
|
|
|
|
const uint32_t condition = Bits32((uint32_t)opcode, 31, 28);
|
|
|
|
if (!ARMConditionPassed(condition, cpsr))
|
|
|
|
{
|
|
|
|
// We ARE stopped on an ARM instruction whose condition doesn't
|
2018-05-01 00:49:04 +08:00
|
|
|
// pass so this instruction won't get executed. Regardless of why
|
|
|
|
// it stopped, we need to clear the stop info
|
2017-10-26 05:05:31 +08:00
|
|
|
thread.SetStopInfo (StopInfoSP());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
} else if (ISETSTATE == 1) {
|
|
|
|
// Thumb mode
|
|
|
|
const uint32_t ITSTATE = Bits32(cpsr, 15, 10) << 2 | Bits32(cpsr, 26, 25);
|
|
|
|
if (ITSTATE != 0) {
|
|
|
|
const uint32_t condition = Bits32(ITSTATE, 7, 4);
|
|
|
|
if (!ARMConditionPassed(condition, cpsr)) {
|
|
|
|
// We ARE stopped in a Thumb IT instruction on an instruction whose
|
|
|
|
// condition doesn't pass so this instruction won't get executed.
|
|
|
|
// Regardless of why it stopped, we need to clear the stop info
|
|
|
|
thread.SetStopInfo(StopInfoSP());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-09-22 02:56:44 +08:00
|
|
|
|
|
|
|
addr_t ArchitectureArm::GetCallableLoadAddress(addr_t code_addr,
|
|
|
|
AddressClass addr_class) const {
|
|
|
|
bool is_alternate_isa = false;
|
|
|
|
|
|
|
|
switch (addr_class) {
|
|
|
|
case AddressClass::eData:
|
|
|
|
case AddressClass::eDebug:
|
|
|
|
return LLDB_INVALID_ADDRESS;
|
|
|
|
case AddressClass::eCodeAlternateISA:
|
|
|
|
is_alternate_isa = true;
|
|
|
|
break;
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((code_addr & 2u) || is_alternate_isa)
|
|
|
|
return code_addr | 1u;
|
|
|
|
return code_addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
addr_t ArchitectureArm::GetOpcodeLoadAddress(addr_t opcode_addr,
|
|
|
|
AddressClass addr_class) const {
|
|
|
|
switch (addr_class) {
|
|
|
|
case AddressClass::eData:
|
|
|
|
case AddressClass::eDebug:
|
|
|
|
return LLDB_INVALID_ADDRESS;
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
return opcode_addr & ~(1ull);
|
2018-11-12 07:17:06 +08:00
|
|
|
}
|