xref: /aosp_15_r20/system/extras/simpleperf/build_id.h (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker  *
4*288bf522SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker  *
8*288bf522SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker  *
10*288bf522SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker  * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker  */
16*288bf522SAndroid Build Coastguard Worker 
17*288bf522SAndroid Build Coastguard Worker #ifndef SIMPLE_PERF_BUILD_ID_H_
18*288bf522SAndroid Build Coastguard Worker #define SIMPLE_PERF_BUILD_ID_H_
19*288bf522SAndroid Build Coastguard Worker 
20*288bf522SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
21*288bf522SAndroid Build Coastguard Worker #include <string.h>
22*288bf522SAndroid Build Coastguard Worker #include <algorithm>
23*288bf522SAndroid Build Coastguard Worker #include <string>
24*288bf522SAndroid Build Coastguard Worker #include <string_view>
25*288bf522SAndroid Build Coastguard Worker 
26*288bf522SAndroid Build Coastguard Worker namespace simpleperf {
27*288bf522SAndroid Build Coastguard Worker 
28*288bf522SAndroid Build Coastguard Worker constexpr size_t BUILD_ID_SIZE = 20;
29*288bf522SAndroid Build Coastguard Worker 
30*288bf522SAndroid Build Coastguard Worker // Shared libraries can have a section called .note.gnu.build-id, containing
31*288bf522SAndroid Build Coastguard Worker // a ~20 bytes unique id. Build id is used to compare if two shared libraries
32*288bf522SAndroid Build Coastguard Worker // are actually the same. BuildId class is the representation of build id in
33*288bf522SAndroid Build Coastguard Worker // memory.
34*288bf522SAndroid Build Coastguard Worker class BuildId {
35*288bf522SAndroid Build Coastguard Worker  public:
Size()36*288bf522SAndroid Build Coastguard Worker   static size_t Size() { return BUILD_ID_SIZE; }
37*288bf522SAndroid Build Coastguard Worker 
BuildId()38*288bf522SAndroid Build Coastguard Worker   BuildId() { memset(data_, '\0', BUILD_ID_SIZE); }
39*288bf522SAndroid Build Coastguard Worker 
40*288bf522SAndroid Build Coastguard Worker   // Copy build id from a byte array, like {0x76, 0x00, 0x32,...}.
BuildId(const void * data,size_t len)41*288bf522SAndroid Build Coastguard Worker   BuildId(const void* data, size_t len) : BuildId() {
42*288bf522SAndroid Build Coastguard Worker     memcpy(data_, data, std::min(len, BUILD_ID_SIZE));
43*288bf522SAndroid Build Coastguard Worker   }
44*288bf522SAndroid Build Coastguard Worker 
45*288bf522SAndroid Build Coastguard Worker   // Read build id from a hex string, like "7600329e31058e12b145d153ef27cd40e1a5f7b9".
BuildId(const std::string & s)46*288bf522SAndroid Build Coastguard Worker   explicit BuildId(const std::string& s) : BuildId() {
47*288bf522SAndroid Build Coastguard Worker     for (size_t i = 0; i < s.size() && i < BUILD_ID_SIZE * 2; i += 2) {
48*288bf522SAndroid Build Coastguard Worker       unsigned char ch = 0;
49*288bf522SAndroid Build Coastguard Worker       for (size_t j = i; j < i + 2; ++j) {
50*288bf522SAndroid Build Coastguard Worker         ch <<= 4;
51*288bf522SAndroid Build Coastguard Worker         if (s[j] >= '0' && s[j] <= '9') {
52*288bf522SAndroid Build Coastguard Worker           ch |= s[j] - '0';
53*288bf522SAndroid Build Coastguard Worker         } else if (s[j] >= 'a' && s[j] <= 'f') {
54*288bf522SAndroid Build Coastguard Worker           ch |= s[j] - 'a' + 10;
55*288bf522SAndroid Build Coastguard Worker         } else if (s[j] >= 'A' && s[j] <= 'F') {
56*288bf522SAndroid Build Coastguard Worker           ch |= s[j] - 'A' + 10;
57*288bf522SAndroid Build Coastguard Worker         }
58*288bf522SAndroid Build Coastguard Worker       }
59*288bf522SAndroid Build Coastguard Worker       data_[i / 2] = ch;
60*288bf522SAndroid Build Coastguard Worker     }
61*288bf522SAndroid Build Coastguard Worker   }
62*288bf522SAndroid Build Coastguard Worker 
Data()63*288bf522SAndroid Build Coastguard Worker   const unsigned char* Data() const { return data_; }
64*288bf522SAndroid Build Coastguard Worker 
ToString()65*288bf522SAndroid Build Coastguard Worker   std::string ToString() const {
66*288bf522SAndroid Build Coastguard Worker     std::string s = "0x";
67*288bf522SAndroid Build Coastguard Worker     for (size_t i = 0; i < BUILD_ID_SIZE; ++i) {
68*288bf522SAndroid Build Coastguard Worker       s += android::base::StringPrintf("%02x", data_[i]);
69*288bf522SAndroid Build Coastguard Worker     }
70*288bf522SAndroid Build Coastguard Worker     return s;
71*288bf522SAndroid Build Coastguard Worker   }
72*288bf522SAndroid Build Coastguard Worker 
73*288bf522SAndroid Build Coastguard Worker   bool operator==(const BuildId& build_id) const {
74*288bf522SAndroid Build Coastguard Worker     return memcmp(data_, build_id.data_, BUILD_ID_SIZE) == 0;
75*288bf522SAndroid Build Coastguard Worker   }
76*288bf522SAndroid Build Coastguard Worker 
77*288bf522SAndroid Build Coastguard Worker   bool operator!=(const BuildId& build_id) const { return !(*this == build_id); }
78*288bf522SAndroid Build Coastguard Worker 
IsEmpty()79*288bf522SAndroid Build Coastguard Worker   bool IsEmpty() const {
80*288bf522SAndroid Build Coastguard Worker     static BuildId empty_build_id;
81*288bf522SAndroid Build Coastguard Worker     return *this == empty_build_id;
82*288bf522SAndroid Build Coastguard Worker   }
83*288bf522SAndroid Build Coastguard Worker 
84*288bf522SAndroid Build Coastguard Worker  private:
85*288bf522SAndroid Build Coastguard Worker   unsigned char data_[BUILD_ID_SIZE];
86*288bf522SAndroid Build Coastguard Worker };
87*288bf522SAndroid Build Coastguard Worker 
88*288bf522SAndroid Build Coastguard Worker inline std::ostream& operator<<(std::ostream& os, const BuildId& build_id) {
89*288bf522SAndroid Build Coastguard Worker   os << build_id.ToString();
90*288bf522SAndroid Build Coastguard Worker   return os;
91*288bf522SAndroid Build Coastguard Worker }
92*288bf522SAndroid Build Coastguard Worker 
93*288bf522SAndroid Build Coastguard Worker }  // namespace simpleperf
94*288bf522SAndroid Build Coastguard Worker 
95*288bf522SAndroid Build Coastguard Worker namespace std {
96*288bf522SAndroid Build Coastguard Worker 
97*288bf522SAndroid Build Coastguard Worker template <>
98*288bf522SAndroid Build Coastguard Worker struct hash<simpleperf::BuildId> {
99*288bf522SAndroid Build Coastguard Worker   size_t operator()(const simpleperf::BuildId& build_id) const noexcept {
100*288bf522SAndroid Build Coastguard Worker     return std::hash<std::string_view>()(
101*288bf522SAndroid Build Coastguard Worker         std::string_view(reinterpret_cast<const char*>(build_id.Data()), build_id.Size()));
102*288bf522SAndroid Build Coastguard Worker   }
103*288bf522SAndroid Build Coastguard Worker };
104*288bf522SAndroid Build Coastguard Worker 
105*288bf522SAndroid Build Coastguard Worker }  // namespace std
106*288bf522SAndroid Build Coastguard Worker 
107*288bf522SAndroid Build Coastguard Worker #endif  // SIMPLE_PERF_BUILD_ID_H_
108