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
16 #include "verification/public_internal.h"
17 #include "verification/config/process/config_process.h"
18 #include "verification/util/parser/parser.h"
19
20 #include "verifier_messages.h"
21
22 #include "runtime/include/method.h"
23 #include "runtime/include/mem/panda_string.h"
24
25 #include "utils/logger.h"
26
27 #include <string>
28 #include <cstring>
29 #include <cstdint>
30
31 namespace ark::verifier::debug {
32
33 using ark::parser::Action;
34 using ark::parser::Parser;
35 using ark::verifier::config::Section;
36
37 namespace {
38
39 struct Context {
40 PandaString method;
41 std::vector<uint32_t> offsets;
42 };
43
44 } // namespace
45
BreakpointParser()46 const auto &BreakpointParser()
47 {
48 struct Breakpoint;
49 using ark::parser::Charset;
50 using P = Parser<Context, const char, const char *>::Next<Breakpoint>;
51 using P1 = P::P;
52 using P2 = P1::P;
53 using P3 = P2::P;
54 using P4 = P3::P;
55 using P5 = P4::P;
56
57 static const auto WS = P::OfCharset(" \t");
58 static const auto COMMA = P1::OfString(",");
59 static const auto DEC = P2::OfCharset("0123456789");
60 static const auto HEX = P3::OfCharset("0123456789abcdefABCDEF");
61
62 static const auto OFFSET_HANDLER = [](Action a, Context &c, auto from) {
63 if (a == Action::PARSED) {
64 c.offsets.push_back(std::strtol(from, nullptr, 0));
65 }
66 return true;
67 };
68
69 static const auto OFFSET = (P4::OfString("0x") >> HEX) | DEC |= OFFSET_HANDLER;
70
71 static const auto METHOD_NAME_HANDLER = [](Action a, Context &c, auto from, auto to) {
72 if (a == Action::PARSED) {
73 c.method = PandaString {from, to};
74 }
75 return true;
76 };
77
78 static const auto BREAKPOINT_HANDLER = [](Action a, Context &c) {
79 if (a == Action::START) {
80 c.method.clear();
81 c.offsets.clear();
82 }
83 return true;
84 };
85
86 static const auto METHOD_NAME = P5::OfCharset(!Charset {" \t,"}) |= METHOD_NAME_HANDLER;
87 static const auto BREAKPOINT = (~WS >> METHOD_NAME >> *(~WS >> COMMA >> ~WS >> OFFSET) >> ~WS >> P::End()) |
88 (~WS >> P::End()) |= BREAKPOINT_HANDLER; // NOLINT
89 return BREAKPOINT;
90 }
91
RegisterConfigHandlerBreakpointsVerifierAnalyzer(const struct Section & s,Config * & cfg)92 static bool RegisterConfigHandlerBreakpointsVerifierAnalyzer(const struct Section &s, Config *&cfg)
93 {
94 for (const auto &i : s.items) {
95 Context c;
96 const char *start = i.c_str();
97 const char *end = i.c_str() + i.length(); // NOLINT
98 if (!BreakpointParser()(c, start, end)) {
99 LOG_VERIFIER_DEBUG_BREAKPOINT_WRONG_CFG_LINE(i);
100 return false;
101 }
102 if (!c.method.empty()) {
103 if (c.offsets.empty()) {
104 c.offsets.push_back(0);
105 }
106 for (auto o : c.offsets) {
107 cfg->debugCfg.AddBreakpointConfig(c.method, o);
108 }
109 }
110 }
111 return true;
112 }
113
RegisterConfigHandlerBreakpoints(Config * dcfg)114 void RegisterConfigHandlerBreakpoints(Config *dcfg)
115 {
116 static const auto CONFIG_DEBUG_BREAKPOINTS = [](Config *cfg, const Section §ion) {
117 for (const auto &s : section.sections) {
118 if (s.name == "verifier" && !RegisterConfigHandlerBreakpointsVerifierAnalyzer(s, cfg)) {
119 return false;
120 }
121 if (s.name != "verifier") {
122 LOG_VERIFIER_DEBUG_BREAKPOINT_WRONG_SECTION(s.name);
123 return false;
124 }
125 }
126 return true;
127 };
128
129 config::RegisterConfigHandler(dcfg, "config.debug.breakpoints", CONFIG_DEBUG_BREAKPOINTS);
130 }
131
132 } // namespace ark::verifier::debug
133