Mercurial > hg > CbC > CbC_llvm
view llvm/lib/DebugInfo/GSYM/ObjectFileTransformer.cpp @ 173:0572611fdcc8 llvm10 llvm12
reorgnization done
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 25 May 2020 11:55:54 +0900 |
parents | |
children | 1f2b6ac9f198 |
line wrap: on
line source
//===- ObjectFileTransformer.cpp --------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include <unordered_set> #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/MachOUniversal.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/raw_ostream.h" #include "llvm/DebugInfo/GSYM/ObjectFileTransformer.h" #include "llvm/DebugInfo/GSYM/GsymCreator.h" using namespace llvm; using namespace gsym; constexpr uint32_t NT_GNU_BUILD_ID_TAG = 0x03; static std::vector<uint8_t> getUUID(const object::ObjectFile &Obj) { // Extract the UUID from the object file std::vector<uint8_t> UUID; if (auto *MachO = dyn_cast<object::MachOObjectFile>(&Obj)) { const ArrayRef<uint8_t> MachUUID = MachO->getUuid(); if (!MachUUID.empty()) UUID.assign(MachUUID.data(), MachUUID.data() + MachUUID.size()); } else if (isa<object::ELFObjectFileBase>(&Obj)) { const StringRef GNUBuildID(".note.gnu.build-id"); for (const object::SectionRef &Sect : Obj.sections()) { Expected<StringRef> SectNameOrErr = Sect.getName(); if (!SectNameOrErr) { consumeError(SectNameOrErr.takeError()); continue; } StringRef SectName(*SectNameOrErr); if (SectName != GNUBuildID) continue; StringRef BuildIDData; Expected<StringRef> E = Sect.getContents(); if (E) BuildIDData = *E; else { consumeError(E.takeError()); continue; } DataExtractor Decoder(BuildIDData, Obj.makeTriple().isLittleEndian(), 8); uint64_t Offset = 0; const uint32_t NameSize = Decoder.getU32(&Offset); const uint32_t PayloadSize = Decoder.getU32(&Offset); const uint32_t PayloadType = Decoder.getU32(&Offset); StringRef Name(Decoder.getFixedLengthString(&Offset, NameSize)); if (Name == "GNU" && PayloadType == NT_GNU_BUILD_ID_TAG) { Offset = alignTo(Offset, 4); StringRef UUIDBytes(Decoder.getBytes(&Offset, PayloadSize)); if (!UUIDBytes.empty()) { auto Ptr = reinterpret_cast<const uint8_t *>(UUIDBytes.data()); UUID.assign(Ptr, Ptr + UUIDBytes.size()); } } } } return UUID; } llvm::Error ObjectFileTransformer::convert(const object::ObjectFile &Obj, raw_ostream &Log, GsymCreator &Gsym) { using namespace llvm::object; const bool IsMachO = isa<MachOObjectFile>(&Obj); const bool IsELF = isa<ELFObjectFileBase>(&Obj); // Read build ID. Gsym.setUUID(getUUID(Obj)); // Parse the symbol table. size_t NumBefore = Gsym.getNumFunctionInfos(); for (const object::SymbolRef &Sym : Obj.symbols()) { Expected<SymbolRef::Type> SymType = Sym.getType(); if (!SymType) { consumeError(SymType.takeError()); continue; } Expected<uint64_t> AddrOrErr = Sym.getValue(); if (!AddrOrErr) // TODO: Test this error. return AddrOrErr.takeError(); if (SymType.get() != SymbolRef::Type::ST_Function || !Gsym.IsValidTextAddress(*AddrOrErr) || Gsym.hasFunctionInfoForAddress(*AddrOrErr)) continue; // Function size for MachO files will be 0 constexpr bool NoCopy = false; const uint64_t size = IsELF ? ELFSymbolRef(Sym).getSize() : 0; Expected<StringRef> Name = Sym.getName(); if (!Name) { logAllUnhandledErrors(Name.takeError(), Log, "ObjectFileTransformer: "); continue; } // Remove the leading '_' character in any symbol names if there is one // for mach-o files. if (IsMachO) Name->consume_front("_"); Gsym.addFunctionInfo( FunctionInfo(*AddrOrErr, size, Gsym.insertString(*Name, NoCopy))); } size_t FunctionsAddedCount = Gsym.getNumFunctionInfos() - NumBefore; Log << "Loaded " << FunctionsAddedCount << " functions from symbol table.\n"; return Error::success(); }