• 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 
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 &section) {
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