1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "read_symbol_map.h"
18
19 #include <errno.h>
20 #include <stdlib.h>
21
22 #include <algorithm>
23 #include <optional>
24 #include <string>
25 #include <string_view>
26 #include <vector>
27
28 #include "dso.h"
29
30 namespace simpleperf {
31 namespace {
32
ConsumeWord(std::string_view & content_ref)33 std::optional<std::string_view> ConsumeWord(std::string_view& content_ref) {
34 size_t begin = content_ref.find_first_not_of(" \t");
35 if (begin == content_ref.npos) {
36 return {};
37 }
38
39 size_t end = content_ref.find_first_of(" \t", begin + 1);
40 if (end == content_ref.npos) {
41 end = content_ref.size();
42 }
43
44 auto res = content_ref.substr(begin, end - begin);
45 content_ref.remove_prefix(end);
46 return res;
47 }
48
ConsumeUInt(std::string_view & content_ref)49 std::optional<uint64_t> ConsumeUInt(std::string_view& content_ref) {
50 auto word = ConsumeWord(content_ref);
51 if (!word) {
52 return {};
53 }
54
55 errno = 0;
56 const char* start = word.value().data();
57 char* stop;
58 auto res = strtoull(start, &stop, 0);
59 if (errno != 0 || stop - start != word.value().size()) {
60 return {};
61 }
62
63 return res;
64 }
65
ReadSymbol(std::string_view content,std::vector<Symbol> * symbols)66 void ReadSymbol(std::string_view content, std::vector<Symbol>* symbols) {
67 auto addr = ConsumeUInt(content);
68 if (!addr) {
69 return;
70 }
71
72 auto size = ConsumeUInt(content);
73 if (!size) {
74 return;
75 }
76
77 auto name = ConsumeWord(content);
78 if (!name) {
79 return;
80 }
81
82 if (ConsumeWord(content)) {
83 return;
84 }
85
86 symbols->emplace_back(name.value(), addr.value(), size.value());
87 }
88
89 } // namespace
90
ReadSymbolMapFromString(const std::string & content)91 std::vector<Symbol> ReadSymbolMapFromString(const std::string& content) {
92 std::vector<Symbol> symbols;
93
94 for (size_t begin = 0;;) {
95 size_t end = content.find_first_of("\n\r", begin);
96
97 if (end == content.npos) {
98 ReadSymbol({content.c_str() + begin, content.size() - begin}, &symbols);
99 std::sort(symbols.begin(), symbols.end(), Symbol::CompareValueByAddr);
100 return symbols;
101 }
102
103 ReadSymbol({content.c_str() + begin, end - begin}, &symbols);
104 begin = end + 1;
105 }
106 }
107
108 } // namespace simpleperf
109