xref: /aosp_15_r20/art/disassembler/disassembler_arm64.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_DISASSEMBLER_DISASSEMBLER_ARM64_H_
18 #define ART_DISASSEMBLER_DISASSEMBLER_ARM64_H_
19 
20 #include "disassembler.h"
21 
22 // TODO(VIXL): Make VIXL compile cleanly with -Wshadow, -Wdeprecated-declarations.
23 #pragma GCC diagnostic push
24 #pragma GCC diagnostic ignored "-Wshadow"
25 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
26 #include "aarch64/decoder-aarch64.h"
27 #include "aarch64/disasm-aarch64.h"
28 #pragma GCC diagnostic pop
29 
30 namespace art {
31 namespace arm64 {
32 
33 class CustomDisassembler final : public vixl::aarch64::Disassembler {
34  public:
CustomDisassembler(DisassemblerOptions * options)35   explicit CustomDisassembler(DisassemblerOptions* options)
36       : vixl::aarch64::Disassembler(),
37         read_literals_(options->can_read_literals_),
38         base_address_(options->base_address_),
39         end_address_(options->end_address_),
40         options_(options) {
41     if (!options->absolute_addresses_) {
42       MapCodeAddress(0,
43                      reinterpret_cast<const vixl::aarch64::Instruction*>(options->base_address_));
44     }
45   }
46 
47   // Use register aliases in the disassembly.
48   void AppendRegisterNameToOutput(const vixl::aarch64::Instruction* instr,
49                                   const vixl::aarch64::CPURegister& reg) override;
50 
51   // Overriding to print the address with trailing zeroes e.g. 0x00004074 instead of 0x4074.
52   void AppendCodeRelativeAddressToOutput(const vixl::aarch64::Instruction* instr,
53                                          const void* addr) override;
54 
55   // Intercepts the instruction flow captured by the parent method,
56   // to specially instrument for particular instruction types.
57   void Visit(vixl::aarch64::Metadata* metadata, const vixl::aarch64::Instruction* instr) override;
58 
59  private:
60   // Improve the disassembly of literal load instructions.
61   void VisitLoadLiteralInstr(const vixl::aarch64::Instruction* instr);
62 
63   // Improve the disassembly of thread offset.
64   void VisitLoadStoreUnsignedOffsetInstr(const vixl::aarch64::Instruction* instr);
65 
66   // Improve the disassembly of branch to thunk jumping to pointer from thread entrypoint.
67   void VisitUnconditionalBranchInstr(const vixl::aarch64::Instruction* instr);
68 
69   void AppendThreadOfsetName(const vixl::aarch64::Instruction* instr);
70 
71   // Indicate if the disassembler should read data loaded from literal pools.
72   // This should only be enabled if reading the target of literal loads is safe.
73   // Here are possible outputs when the option is on or off:
74   // read_literals_ | disassembly
75   //           true | 0x72681558: 1c000acb  ldr s11, pc+344 (addr 0x726816b0)
76   //          false | 0x72681558: 1c000acb  ldr s11, pc+344 (addr 0x726816b0) (3.40282e+38)
77   const bool read_literals_;
78 
79   // Valid address range: [base_address_, end_address_)
80   const void* const base_address_;
81   const void* const end_address_;
82 
83   DisassemblerOptions* options_;
84 };
85 
86 class DisassemblerArm64 final : public Disassembler {
87  public:
DisassemblerArm64(DisassemblerOptions * options)88   explicit DisassemblerArm64(DisassemblerOptions* options) :
89       Disassembler(options), disasm(options) {
90     decoder.AppendVisitor(&disasm);
91   }
92 
93   size_t Dump(std::ostream& os, const uint8_t* begin) override;
94   void Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) override;
95 
96  private:
97   vixl::aarch64::Decoder decoder;
98   CustomDisassembler disasm;
99 
100   DISALLOW_COPY_AND_ASSIGN(DisassemblerArm64);
101 };
102 
103 }  // namespace arm64
104 }  // namespace art
105 
106 #endif  // ART_DISASSEMBLER_DISASSEMBLER_ARM64_H_
107