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