/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "SymbolDatabase.h" #include "SymbolFileParser.h" #include #include #include #include #include #include #include #include #include #include #include #include "versioner.h" using namespace llvm; using namespace llvm::object; std::unordered_set getSymbols(const std::string& filename) { std::unordered_set result; auto binaryOrError = createBinary(filename); if (!binaryOrError) { errx(1, "failed to open library at %s: %s\n", filename.c_str(), llvm::toString(binaryOrError.takeError()).c_str()); } ELFObjectFileBase* elf = dyn_cast_or_null(binaryOrError.get().getBinary()); if (!elf) { errx(1, "failed to parse %s as ELF", filename.c_str()); } for (const ELFSymbolRef symbol : elf->getDynamicSymbolIterators()) { Expected symbolNameOrError = symbol.getName(); if (!symbolNameOrError) { errx(1, "failed to get symbol name for symbol in %s: %s", filename.c_str(), llvm::toString(symbolNameOrError.takeError()).c_str()); } result.insert(symbolNameOrError.get().str()); } return result; } static std::map parsePlatform(const CompilationType& type, const std::string& platform_dir) { static const std::pair wanted_files[] = { {"crtbegin.map.txt", false}, {"libc.map.txt", true}, }; std::map result; for (auto&& [filename, required] : wanted_files) { std::string path = platform_dir + "/" + filename; std::optional symbols = parseSymbolFile(path, type); if (!symbols) { if (required) { errx(1, "error: failed to load: %s", path.c_str()); } continue; } for (auto&& [symbol_name, symbol_type] : *symbols) { if (symbol_name.empty()) { continue; } if (result.count(symbol_name) != 0) { if (strict) { printf("duplicated symbol '%s' in '%s'\n", symbol_name.c_str(), path.c_str()); } } result[symbol_name] = symbol_type; } } return result; } std::optional parsePlatforms(const std::set& types, const std::string& platform_dir) { NdkSymbolDatabase result; for (const CompilationType& type : types) { std::map symbols = parsePlatform(type, platform_dir); for (const auto& it : symbols) { result[it.first][type] = it.second; } } return std::make_optional(std::move(result)); }