• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-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 #ifndef PANDA_RUNTIME_TOOLING_SAMPLER_SAMPLE_READER_INL_H
16 #define PANDA_RUNTIME_TOOLING_SAMPLER_SAMPLE_READER_INL_H
17 
18 #include <iostream>
19 #include <securec.h>
20 #include <string>
21 
22 #include "libpandabase/utils/logger.h"
23 
24 #include "runtime/tooling/sampler/sample_info.h"
25 #include "runtime/tooling/sampler/sample_reader.h"
26 #include "runtime/tooling/sampler/sample_writer.h"
27 
28 namespace ark::tooling::sampler {
29 
30 // -------------------------------------------------
31 // ------------- Format reader ---------------------
32 // -------------------------------------------------
33 
34 /*
35  * Example for 64 bit architecture
36  *
37  *              Thread id   Thread status    Stack Size      Managed stack frame id
38  * Sample row |___________|______________|________________|_____________------___________|
39  *              32 bits      32 bits          64 bits       (128 * <stack size>) bits
40  *
41  *
42  *              0xFF..FF    pointer   checksum   name size     module path (ASCII str)
43  * Module row |__________|__________|__________|___________|_____________------___________|
44  *              64 bits    64 bits    32 bits    64 bits       (8 * <name size>) bits
45  */
46 
47 // CC-OFFNXT(G.FUD.06) Splitting this function will degrade readability. Keyword "inline" needs to satisfy ODR rule.
SampleReader(const char * filename)48 inline SampleReader::SampleReader(const char *filename)
49 {
50     {
51         std::ifstream binFile(filename, std::ios::binary | std::ios::ate);
52         if (!binFile) {
53             LOG(FATAL, PROFILER) << "Unable to open file \"" << filename << "\"";
54             UNREACHABLE();
55         }
56         std::streamsize bufferSize = binFile.tellg();
57         binFile.seekg(0, std::ios::beg);
58 
59         buffer_.resize(bufferSize);
60 
61         if (!binFile.read(buffer_.data(), bufferSize)) {
62             LOG(FATAL, PROFILER) << "Unable to read sampler trace file";
63             UNREACHABLE();
64         }
65         binFile.close();
66     }
67 
68     size_t bufferCounter = 0;
69     while (bufferCounter < buffer_.size()) {
70         if (ReadUintptrTBitMisaligned(&buffer_[bufferCounter]) == FileStreamWriter::MODULE_INDICATOR_VALUE) {
71             // This entry is panda file
72             size_t pfNameSize = ReadUintptrTBitMisaligned(&buffer_[bufferCounter + PANDA_FILE_NAME_SIZE_OFFSET]);
73             size_t nextModulePtrOffset = PANDA_FILE_NAME_OFFSET + pfNameSize * sizeof(char);
74 
75             if (bufferCounter + nextModulePtrOffset > buffer_.size()) {
76                 LOG(ERROR, PROFILER) << "ark sampling profiler drop last module, because of invalid trace file";
77                 return;
78             }
79 
80             moduleRowPtrs_.push_back(&buffer_[bufferCounter]);
81             bufferCounter += nextModulePtrOffset;
82             continue;
83         }
84 
85         // buffer_counter now is entry of a sample, stack size lies after thread_id
86         size_t stackSize = ReadUintptrTBitMisaligned(&buffer_[bufferCounter + SAMPLE_STACK_SIZE_OFFSET]);
87         if (stackSize > SampleInfo::StackInfo::MAX_STACK_DEPTH) {
88             LOG(FATAL, PROFILER) << "ark sampling profiler trace file is invalid, stack_size > MAX_STACK_DEPTH";
89             UNREACHABLE();
90         }
91 
92         size_t nextSamplePtrOffset = SAMPLE_STACK_OFFSET + stackSize * sizeof(SampleInfo::ManagedStackFrameId);
93         if (bufferCounter + nextSamplePtrOffset > buffer_.size()) {
94             LOG(ERROR, PROFILER) << "ark sampling profiler drop last samples, because of invalid trace file";
95             return;
96         }
97 
98         sampleRowPtrs_.push_back(&buffer_[bufferCounter]);
99         bufferCounter += nextSamplePtrOffset;
100     }
101 
102     if (bufferCounter != buffer_.size()) {
103         LOG(ERROR, PROFILER) << "ark sampling profiler trace file is invalid";
104     }
105 }
106 
107 // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
108 // CC-OFFNXT(G.FUD.06) Splitting this function will degrade readability. Keyword "inline" needs to satisfy ODR rule.
GetNextSample(SampleInfo * sampleOut)109 inline bool SampleReader::GetNextSample(SampleInfo *sampleOut)
110 {
111     if (sampleRowPtrs_.size() <= sampleRowCounter_) {
112         return false;
113     }
114     const char *currentSamplePtr = sampleRowPtrs_[sampleRowCounter_];
115     sampleOut->threadInfo.threadId = ReadUint32TBitMisaligned(&currentSamplePtr[SAMPLE_THREAD_ID_OFFSET]);
116     sampleOut->threadInfo.threadStatus =
117         static_cast<SampleInfo::ThreadStatus>(ReadUint32TBitMisaligned(&currentSamplePtr[SAMPLE_THREAD_STATUS_OFFSET]));
118     sampleOut->stackInfo.managedStackSize = ReadUintptrTBitMisaligned(&currentSamplePtr[SAMPLE_STACK_SIZE_OFFSET]);
119 
120     ASSERT(sampleOut->stackInfo.managedStackSize <= SampleInfo::StackInfo::MAX_STACK_DEPTH);
121     auto copySize = sampleOut->stackInfo.managedStackSize * sizeof(SampleInfo::ManagedStackFrameId);
122     [[maybe_unused]] int r =
123         memcpy_s(sampleOut->stackInfo.managedStack.data(), copySize, currentSamplePtr + SAMPLE_STACK_OFFSET, copySize);
124     ASSERT(r == 0);
125     ++sampleRowCounter_;
126     return true;
127 }
128 
129 // CC-OFFNXT(G.FUD.06) Splitting this function will degrade readability. Keyword "inline" needs to satisfy ODR rule.
GetNextModule(FileInfo * moduleOut)130 inline bool SampleReader::GetNextModule(FileInfo *moduleOut)
131 {
132     if (moduleRowPtrs_.size() <= moduleRowCounter_) {
133         return false;
134     }
135 
136     moduleOut->pathname.clear();
137 
138     const char *currentModulePtr = moduleRowPtrs_[moduleRowCounter_];
139     moduleOut->ptr = ReadUintptrTBitMisaligned(&currentModulePtr[PANDA_FILE_POINTER_OFFSET]);
140     moduleOut->checksum = ReadUint32TBitMisaligned(&currentModulePtr[PANDA_FILE_CHECKSUM_OFFSET]);
141     size_t strSize = ReadUintptrTBitMisaligned(&currentModulePtr[PANDA_FILE_NAME_SIZE_OFFSET]);
142     const char *strPtr = &currentModulePtr[PANDA_FILE_NAME_OFFSET];
143     moduleOut->pathname = std::string(strPtr, strSize);
144 
145     ++moduleRowCounter_;
146     return true;
147 }
148 // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
149 
150 }  // namespace ark::tooling::sampler
151 
152 #endif  // PANDA_RUNTIME_TOOLING_SAMPLER_SAMPLE_READER_INL_H
153