1/*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
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 "ftrace_field_parser.h"
16#include "logging.h"
17#include "printk_formats_parser.h"
18#include "securec.h"
19
20#include <cinttypes>
21#include <cstring>
22#include <fcntl.h>
23#include <memory>
24#include <unistd.h>
25
26FTRACE_NS_BEGIN
27namespace {
28constexpr uint32_t DATALOC_OFFSET_MASK = 0xffff;
29constexpr uint32_t DATALOC_LENGTH_MASK = 0xffff;
30constexpr uint32_t DATALOC_LENGTH_SHIFT = 16;
31
32std::string ReadString(const uint8_t start[], const uint8_t end[], int size)
33{
34    std::string str;
35
36    if (end - start < static_cast<ptrdiff_t>(size)) {
37        return str;
38    }
39
40    const uint8_t* cursor = start;
41    const uint8_t* sectionEnd = start + size;
42    while (*cursor && cursor < sectionEnd) {
43        cursor++;
44    }
45
46    str.assign(start, cursor);
47    return str;
48}
49} // namespace
50
51bool FtraceFieldParser::ReadData(const uint8_t start[], const uint8_t end[], void* out, size_t size)
52{
53    ptrdiff_t memSize = end - start;
54    if (memSize < static_cast<ptrdiff_t>(size)) {
55        return false;
56    }
57
58    CHECK_TRUE(memcpy_s(out, size, start, size) == EOK, false, "copy %zu byte to memory FAILED!", size);
59    return true;
60}
61
62std::string FtraceFieldParser::ParseStrField(const FieldFormat& format, uint8_t data[], size_t size)
63{
64    std::string retval;
65    if ((format.offset + format.size) > size) {
66        return retval;
67    }
68
69    uint8_t* start = data + format.offset;
70    uint8_t* end = data + size;
71    size_t strSize = 0;
72    uint64_t strPtr = 0;
73    uint32_t dataLoc = 0;
74    uint32_t dataOffset = 0;
75    uint32_t dataLength = 0;
76
77    switch (format.filedType) {
78        case FIELD_TYPE_FIXEDCSTRING:
79            retval = ReadString(start, end, format.size);
80            break;
81        case FIELD_TYPE_CSTRING:
82            strSize = format.size;
83            if (strSize == 0) {
84                strSize = end - start;
85                retval = ReadString(start, end, strSize);
86            } else {
87                retval = ReadString(start, end, strSize);
88            }
89            break;
90        case FIELD_TYPE_STRINGPTR:
91            strSize = std::min(static_cast<size_t>(format.size), sizeof(strPtr));
92            CHECK_TRUE(memcpy_s(&strPtr, sizeof(strPtr), start, strSize) == EOK, "", "parse STRINGPTR FAILED!");
93            retval = PrintkFormatsParser::GetInstance().GetSymbol(strPtr);
94            break;
95        case FIELD_TYPE_DATALOC:
96            dataLoc = 0;
97            ReadData(start, end, &dataLoc, sizeof(dataLoc));
98            dataOffset = dataLoc & DATALOC_OFFSET_MASK;
99            dataLength = (dataLoc >> DATALOC_LENGTH_SHIFT) & DATALOC_LENGTH_MASK;
100            if (dataOffset > 0 && data + dataOffset + dataLength <= end) {
101                retval = ReadString(data + dataOffset, end, dataLength);
102            }
103            break;
104        default:
105            break;
106    }
107    return retval;
108}
109FTRACE_NS_END
110