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