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