• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2024 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  */
SampleReader(const char * filename)46 inline SampleReader::SampleReader(const char *filename)
47 {
48     {
49         std::ifstream binFile(filename, std::ios::binary | std::ios::ate);
50         if (!binFile) {
51             LOG(FATAL, PROFILER) << "Unable to open file \"" << filename << "\"";
52             UNREACHABLE();
53         }
54         std::streamsize bufferSize = binFile.tellg();
55         binFile.seekg(0, std::ios::beg);
56 
57         buffer_.resize(bufferSize);
58 
59         if (!binFile.read(buffer_.data(), bufferSize)) {
60             LOG(FATAL, PROFILER) << "Unable to read sampler trace file";
61             UNREACHABLE();
62         }
63         binFile.close();
64     }
65 
66     size_t bufferCounter = 0;
67     while (bufferCounter < buffer_.size()) {
68         if (ReadUintptrTBitMisaligned(&buffer_[bufferCounter]) == StreamWriter::MODULE_INDICATOR_VALUE) {
69             // This entry is panda file
70             size_t pfNameSize = ReadUintptrTBitMisaligned(&buffer_[bufferCounter + PANDA_FILE_NAME_SIZE_OFFSET]);
71             size_t nextModulePtrOffset = PANDA_FILE_NAME_OFFSET + pfNameSize * sizeof(char);
72 
73             if (bufferCounter + nextModulePtrOffset > buffer_.size()) {
74                 LOG(ERROR, PROFILER) << "ark sampling profiler drop last module, because of invalid trace file";
75                 return;
76             }
77 
78             moduleRowPtrs_.push_back(&buffer_[bufferCounter]);
79             bufferCounter += nextModulePtrOffset;
80             continue;
81         }
82 
83         // buffer_counter now is entry of a sample, stack size lies after thread_id
84         size_t stackSize = ReadUintptrTBitMisaligned(&buffer_[bufferCounter + SAMPLE_STACK_SIZE_OFFSET]);
85         if (stackSize > SampleInfo::StackInfo::MAX_STACK_DEPTH) {
86             LOG(FATAL, PROFILER) << "ark sampling profiler trace file is invalid, stack_size > MAX_STACK_DEPTH";
87             UNREACHABLE();
88         }
89 
90         size_t nextSamplePtrOffset = SAMPLE_STACK_OFFSET + stackSize * sizeof(SampleInfo::ManagedStackFrameId);
91         if (bufferCounter + nextSamplePtrOffset > buffer_.size()) {
92             LOG(ERROR, PROFILER) << "ark sampling profiler drop last samples, because of invalid trace file";
93             return;
94         }
95 
96         sampleRowPtrs_.push_back(&buffer_[bufferCounter]);
97         bufferCounter += nextSamplePtrOffset;
98     }
99 
100     if (bufferCounter != buffer_.size()) {
101         LOG(ERROR, PROFILER) << "ark sampling profiler trace file is invalid";
102     }
103 }
104 
105 // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
GetNextSample(SampleInfo * sampleOut)106 inline bool SampleReader::GetNextSample(SampleInfo *sampleOut)
107 {
108     if (sampleRowPtrs_.size() <= sampleRowCounter_) {
109         return false;
110     }
111     const char *currentSamplePtr = sampleRowPtrs_[sampleRowCounter_];
112     sampleOut->threadInfo.threadId = ReadUint32TBitMisaligned(&currentSamplePtr[SAMPLE_THREAD_ID_OFFSET]);
113     sampleOut->threadInfo.threadStatus =
114         static_cast<SampleInfo::ThreadStatus>(ReadUint32TBitMisaligned(&currentSamplePtr[SAMPLE_THREAD_STATUS_OFFSET]));
115     sampleOut->stackInfo.managedStackSize = ReadUintptrTBitMisaligned(&currentSamplePtr[SAMPLE_STACK_SIZE_OFFSET]);
116 
117     ASSERT(sampleOut->stackInfo.managedStackSize <= SampleInfo::StackInfo::MAX_STACK_DEPTH);
118     auto copySize = sampleOut->stackInfo.managedStackSize * sizeof(SampleInfo::ManagedStackFrameId);
119     [[maybe_unused]] int r =
120         memcpy_s(sampleOut->stackInfo.managedStack.data(), copySize, currentSamplePtr + SAMPLE_STACK_OFFSET, copySize);
121     ASSERT(r == 0);
122     ++sampleRowCounter_;
123     return true;
124 }
125 
GetNextModule(FileInfo * moduleOut)126 inline bool SampleReader::GetNextModule(FileInfo *moduleOut)
127 {
128     if (moduleRowPtrs_.size() <= moduleRowCounter_) {
129         return false;
130     }
131 
132     moduleOut->pathname.clear();
133 
134     const char *currentModulePtr = moduleRowPtrs_[moduleRowCounter_];
135     moduleOut->ptr = ReadUintptrTBitMisaligned(&currentModulePtr[PANDA_FILE_POINTER_OFFSET]);
136     moduleOut->checksum = ReadUint32TBitMisaligned(&currentModulePtr[PANDA_FILE_CHECKSUM_OFFSET]);
137     size_t strSize = ReadUintptrTBitMisaligned(&currentModulePtr[PANDA_FILE_NAME_SIZE_OFFSET]);
138     const char *strPtr = &currentModulePtr[PANDA_FILE_NAME_OFFSET];
139     moduleOut->pathname = std::string(strPtr, strSize);
140 
141     ++moduleRowCounter_;
142     return true;
143 }
144 // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
145 
146 }  // namespace ark::tooling::sampler
147 
148 #endif  // PANDA_RUNTIME_TOOLING_SAMPLER_SAMPLE_READER_INL_H
149