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 // Interpret the rest of the line as the symbol name, after stripping leading
78 // and trailing spaces.
79 size_t symbol_begin = content.find_first_not_of(" \t");
80 if (symbol_begin == content.npos) {
81 return;
82 }
83 size_t symbol_end = content.find_last_not_of(" \t") + 1;
84
85 auto name = content.substr(symbol_begin, symbol_end - symbol_begin);
86
87 symbols->emplace_back(name, addr.value(), size.value());
88 }
89
90 } // namespace
91
ReadSymbolMapFromString(const std::string & content)92 std::vector<Symbol> ReadSymbolMapFromString(const std::string& content) {
93 std::vector<Symbol> symbols;
94
95 for (size_t begin = 0;;) {
96 size_t end = content.find_first_of("\n\r", begin);
97
98 if (end == content.npos) {
99 ReadSymbol({content.c_str() + begin, content.size() - begin}, &symbols);
100 std::sort(symbols.begin(), symbols.end(), Symbol::CompareValueByAddr);
101 return symbols;
102 }
103
104 ReadSymbol({content.c_str() + begin, end - begin}, &symbols);
105 begin = end + 1;
106 }
107 }
108
109 } // namespace simpleperf
110