• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }