1/*
2 * Copyright (c) 2021-2022 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 HIPERF_PERF_FILE_FORMAT_H
16#define HIPERF_PERF_FILE_FORMAT_H
17
18#include <string>
19
20#include "perf_event_record.h"
21
22namespace OHOS {
23namespace Developtools {
24namespace HiPerf {
25enum class FEATURE {
26    RESERVED = 0, /* always cleared */
27    FIRST_FEATURE = 1,
28    TRACING_DATA = 1,
29    BUILD_ID, // build_id_event
30
31    HOSTNAME,  // A perf_header_string with the hostname where the data was collected (uname -n)
32    OSRELEASE, // A perf_header_string with the os release where the data was collected (uname -r)
33    VERSION,   // A perf_header_string with the perf user tool version where the data was collected.
34               // This is the same as the version of the source tree the perf tool was built from.
35    ARCH,      // A perf_header_string with the CPU architecture (uname -m)
36    NRCPUS,    // A structure defining the number of CPUs.
37    CPUDESC,   // A perf_header_string with description of the CPU. On x86 this is the model name
38               // in /proc/cpuinfo
39    CPUID,     // A perf_header_string with the exact CPU type. On x86 this is
40               // vendor,family,model,stepping. For example: GenuineIntel,6,69,1
41    TOTAL_MEM, // An uint64_t with the total memory in kilobytes.
42    CMDLINE,   // A perf_header_string_list with the perf arg-vector used to collect the data.
43    EVENT_DESC,    // Another description of the perf_event_attrs
44    CPU_TOPOLOGY,  //
45    NUMA_TOPOLOGY, // A list of NUMA node descriptions
46    BRANCH_STACK,  // Not implemented in perf.
47    PMU_MAPPINGS,  // A list of PMU structures, defining the different PMUs supported by perf.
48    GROUP_DESC,    // Description of counter groups ({...} in perf syntax)
49    AUXTRACE,      // Define additional auxtrace areas in the perf.data. auxtrace is used to store
50                   // undecoded hardware tracing information, such as Intel Processor Trace data.
51    STAT,
52    CACHE,
53    SAMPLE_TIME,
54    MEM_TOPOLOGY,
55    LAST_FEATURE,
56
57    HIPERF_FIRST_FEATURE = 192,
58    HIPERF_FILES_SYMBOL = HIPERF_FIRST_FEATURE,
59    HIPERF_WORKLOAD_CMD,
60    HIPERF_RECORD_TIME,
61    HIPERF_CPU_OFF,
62    HIPERF_HM_DEVHOST,
63    // HIPERF_LAST_FEATURE = HIPERF_HM_DEVHOST,
64    HIPERF_FILES_UNISTACK_TABLE,
65    HIPERF_LAST_FEATURE = HIPERF_FILES_UNISTACK_TABLE,
66    FEATURE_MAX_BITS = 256,
67};
68
69const static std::vector<FEATURE> FeatureStrings = {
70    FEATURE::HOSTNAME,
71    FEATURE::OSRELEASE,
72    FEATURE::VERSION,
73    FEATURE::ARCH,
74    FEATURE::CPUDESC,
75    FEATURE::CPUID,
76    FEATURE::CMDLINE,
77
78    FEATURE::HIPERF_WORKLOAD_CMD,
79    FEATURE::HIPERF_RECORD_TIME,
80    FEATURE::HIPERF_HM_DEVHOST,
81};
82
83struct perf_file_section {
84    uint64_t offset;
85    uint64_t size;
86};
87
88struct perf_file_attr {
89    perf_event_attr attr;
90    perf_file_section ids;
91};
92
93struct perf_header_string {
94    uint32_t len;
95    char string[0]; /* zero terminated */
96};
97
98constexpr char PERF_MAGIC[] = "PERFILE2";
99constexpr int BITS_IN_BYTE = 8;
100constexpr int NUM_FEATURES_FILE_HEADER = 256;
101
102struct perf_file_header {
103    char magic[8] = {'P', 'E', 'R', 'F', 'I', 'L', 'E', '2'};
104    uint64_t size = sizeof(perf_file_header);
105    uint64_t attrSize = sizeof(perf_file_attr);
106    perf_file_section attrs;
107    perf_file_section data;
108    perf_file_section eventTypes;
109    uint8_t features[NUM_FEATURES_FILE_HEADER / BITS_IN_BYTE] = {0};
110};
111
112class PerfFileSection {
113public:
114    struct perf_file_section header;
115    const FEATURE featureId_;
116
117    virtual bool GetBinary(char *buf, size_t size) = 0;
118    virtual size_t GetSize() = 0;
119    virtual ~PerfFileSection() {}
120    explicit PerfFileSection(const FEATURE featureId) : featureId_(featureId)
121    {
122        header.size = 0;
123        header.offset = 0;
124    }
125    static std::string GetFeatureName(FEATURE featureId);
126
127protected:
128    const char *rBuffer_ = nullptr;
129    char *wBuffer_ = nullptr;
130    size_t maxSize_ = 0;
131    size_t offset_ = 0;
132
133    // for read
134    void Init(const char *buffer, size_t maxSize);
135    // for write
136    void Init(char *buffer, size_t maxSize);
137    bool Write(uint32_t u32);
138    bool Write(uint64_t u64);
139    bool Write(const std::string &str);
140
141    bool Write(const char *buf, size_t size);
142    bool Write(const char *buf, size_t size, size_t max);
143
144    bool Read(uint32_t &value);
145    bool Read(uint64_t &value);
146    bool Read(std::string &value);
147    bool Read(char *buf, size_t size);
148    void Skip(size_t size);
149
150    uint32_t SizeOf(std::string &string);
151};
152
153class PerfFileSectionString : public PerfFileSection {
154    std::string stdString_;
155
156public:
157    // convert buff to PerfFileSectionString, used to read file
158    // if the data in buf is incorrect, ......
159    PerfFileSectionString(FEATURE id, const char *buf, size_t size);
160    PerfFileSectionString(FEATURE id, const std::string &charString);
161
162    bool GetBinary(char *buf, size_t size);
163    size_t GetSize();
164    const std::string ToString() const;
165};
166
167// ref struct
168struct SymbolStruct {
169    uint64_t vaddr_ = 0;
170    uint32_t len_ = 0;
171    std::string symbolName_ = EMPTY_STRING;
172    SymbolStruct() {}
173    SymbolStruct(uint64_t vaddr, uint32_t len, const std::string &symbolName)
174        : vaddr_(vaddr), len_(len), symbolName_(symbolName)
175    {
176    }
177};
178
179struct SymbolFileStruct {
180    std::string filePath_ = EMPTY_STRING;
181    uint32_t symbolType_;
182    uint64_t textExecVaddr_;
183    uint64_t textExecVaddrFileOffset_;
184    std::string buildId_;
185    std::vector<SymbolStruct> symbolStructs_;
186};
187
188class PerfFileSectionSymbolsFiles : public PerfFileSection {
189public:
190    std::vector<SymbolFileStruct> symbolFileStructs_;
191
192    size_t GetSize();
193    PerfFileSectionSymbolsFiles(FEATURE id, const std::vector<SymbolFileStruct> &symbolFileStructs)
194        : PerfFileSection(id), symbolFileStructs_(symbolFileStructs)
195    {
196    }
197    // if the data in buf is incorrect, ......
198    PerfFileSectionSymbolsFiles(FEATURE id, const char *buf, size_t size);
199
200    bool GetBinary(char *buf, size_t size);
201    void ReadSymbolFileStructs();
202private:
203};
204
205// NRCPUS: A structure defining the number of CPUs.
206class PerfFileSectionNrCpus : public PerfFileSection {
207    uint32_t nrCpusAvailable_ = 0; /* CPUs not yet onlined */
208    uint32_t nrCpusOnline_ = 0;
209
210public:
211    PerfFileSectionNrCpus(FEATURE id, const char *buf, size_t size);
212    PerfFileSectionNrCpus(FEATURE id, uint32_t nrCpusAvailable, uint32_t nrCpusOnline);
213
214    bool GetBinary(char *buf, size_t size);
215    size_t GetSize();
216    void GetValue(uint32_t &nrCpusAvailable, uint32_t &nrCpusOnline) const;
217};
218
219class PerfFileSectionU64 : public PerfFileSection {
220    uint64_t value_;
221
222public:
223    PerfFileSectionU64(FEATURE id, const char *buf, size_t size);
224    PerfFileSectionU64(FEATURE id, uint64_t v);
225
226    bool GetBinary(char *buf, size_t size);
227    size_t GetSize();
228    void GetValue(uint64_t &v) const;
229};
230
231class PerfFileSectionUniStackTable : public PerfFileSection {
232public:
233    std::vector<UniStackTableInfo> uniStackTableInfos_;
234    PerfFileSectionUniStackTable(FEATURE id,
235        const ProcessStackMap *table)
236        : PerfFileSection(id), processStackTable_(table) {}
237    PerfFileSectionUniStackTable(FEATURE id, const char *buf, size_t size);
238private:
239    const ProcessStackMap *processStackTable_;
240    size_t GetSize();
241    bool GetBinary(char *buf, size_t size);
242};
243
244struct AttrWithId;
245class PerfFileSectionEventDesc : public PerfFileSection {
246public:
247    std::vector<AttrWithId> eventDesces_;
248
249    PerfFileSectionEventDesc(FEATURE id, const char *buf, size_t size);
250    PerfFileSectionEventDesc(FEATURE id, const std::vector<AttrWithId> &eventDesces);
251
252    bool GetBinary(char *buf, size_t size);
253    size_t GetSize();
254    void GetValue(std::vector<AttrWithId> &eventDesces) const;
255};
256} // namespace HiPerf
257} // namespace Developtools
258} // namespace OHOS
259#endif // HIPERF_PERF_FILE_FORMAT_H
260