1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "decorative_dump_info.h"
16 #include "dfx_buffer_writer.h"
17 #include "dfx_define.h"
18 #include "dfx_log.h"
19 #include "dfx_util.h"
20 #include "process_dump_config.h"
21 #include "string_printf.h"
22 #include "dump_utils.h"
23 namespace OHOS {
24 namespace HiviewDFX {
25 namespace {
26 #if defined(__arm__)
27 const char* const NAME_PREFIX = "r";
28 #else
29 const char* const NAME_PREFIX = "x";
30 #endif
31 const char* const LR_REG_NAME = "lr";
32 const char* const PC_REG_NAME = "pc";
33 }
34 REGISTER_DUMP_INFO_CLASS(MemoryNearRegister);
35
Print(DfxProcess & process,const ProcessDumpRequest & request,Unwinder & unwinder)36 void MemoryNearRegister::Print(DfxProcess& process, const ProcessDumpRequest& request, Unwinder& unwinder)
37 {
38 DecorativeDumpInfo::Print(process, request, unwinder);
39 pid_t tid = process.GetKeyThread()->GetThreadInfo().nsTid;
40 bool extendPcLrPrinting = process.GetCrashLogConfig().extendPcLrPrinting ||
41 ProcessDumpConfig::GetInstance().GetConfig().extendPcLrPrinting;
42 CollectRegistersBlock(tid, process.GetFaultThreadRegisters(), unwinder.GetMaps(), extendPcLrPrinting);
43 DfxBufferWriter::GetInstance().WriteMsg("Memory near registers:\n");
44 for (const auto& block : registerBlocks_) {
45 uintptr_t targetAddr = block.startAddr;
46 DfxBufferWriter::GetInstance().WriteMsg(block.name + ":\n");
47 for (size_t i = 0; i < block.content.size(); i++) {
48 DfxBufferWriter::GetInstance().WriteFormatMsg(" " PRINT_FORMAT " " PRINT_FORMAT "\n",
49 targetAddr,
50 block.content.at(i));
51 targetAddr += STEP;
52 }
53 }
54 }
55
GetMemoryValues(std::set<uintptr_t> & memoryValues)56 void MemoryNearRegister::GetMemoryValues(std::set<uintptr_t>& memoryValues)
57 {
58 for (const auto& block : registerBlocks_) {
59 for (const auto& value : block.content) {
60 memoryValues.emplace(StripPac(value, 0));
61 }
62 }
63 }
64
CollectRegistersBlock(pid_t tid,std::shared_ptr<DfxRegs> regs,std::shared_ptr<DfxMaps> maps,bool extendPcLrPrinting)65 void MemoryNearRegister::CollectRegistersBlock(pid_t tid, std::shared_ptr<DfxRegs> regs,
66 std::shared_ptr<DfxMaps> maps, bool extendPcLrPrinting)
67 {
68 if (regs == nullptr || maps == nullptr) {
69 DFXLOGE("%{public}s : regs or maps is null.", __func__);
70 return;
71 }
72 auto regsData = regs->GetRegsData();
73 int index = 0;
74 for (auto data : regsData) {
75 #if defined(ENABLE_HWASAN)
76 constexpr uintptr_t tbiMask = 0xff00000000000000; // the upper eight bits are TBI
77 data &= ~tbiMask;
78 #endif
79 index++;
80 std::shared_ptr<DfxMap> map;
81 if (!maps->FindMapByAddr(data, map) || (map->prots & PROT_READ) == 0) {
82 continue;
83 }
84 std::string name = regs->GetSpecialRegsNameByIndex(index - 1);
85 if (name.empty()) {
86 name = NAME_PREFIX + std::to_string(index - 1);
87 }
88 constexpr size_t size = sizeof(uintptr_t);
89 uintptr_t count = 32;
90 uintptr_t forwardSize = 2;
91 if (extendPcLrPrinting && (name == LR_REG_NAME || name == PC_REG_NAME)) {
92 forwardSize = 31; // 31 : forward count of print value
93 count = 64; // // 64 : total count of print value
94 }
95 auto mapName = map->name;
96 if (!mapName.empty()) {
97 name.append("(" + mapName + ")");
98 }
99 data = data & ~(size - 1);
100 data -= (forwardSize * size);
101 MemoryBlockInfo blockInfo = {
102 .startAddr = data,
103 .nameAddr = 0,
104 .size = count,
105 .name = name,
106 };
107 CreateMemoryBlock(tid, blockInfo);
108 registerBlocks_.push_back(blockInfo);
109 }
110 }
111
CreateMemoryBlock(pid_t tid,MemoryBlockInfo & blockInfo) const112 void MemoryNearRegister::CreateMemoryBlock(pid_t tid, MemoryBlockInfo& blockInfo) const
113 {
114 uintptr_t targetAddr = blockInfo.startAddr;
115 for (uint64_t i = 0; i < static_cast<uint64_t>(blockInfo.size); i++) {
116 uintptr_t value = 0;
117 if (DumpUtils::ReadTargetMemory(tid, targetAddr, value)) {
118 blockInfo.content.push_back(value);
119 } else {
120 blockInfo.content.push_back(-1);
121 }
122 targetAddr += STEP;
123 }
124 }
125 }
126 }