PK hwFZeש{* * PassAnalysisSupport.hnu �[��� //===- llvm/PassAnalysisSupport.h - Analysis Pass Support code --*- 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
//
//===----------------------------------------------------------------------===//
//
// This file defines stuff that is used to define and "use" Analysis Passes.
// This file is automatically #included by Pass.h, so:
//
// NO .CPP FILES SHOULD INCLUDE THIS FILE DIRECTLY
//
// Instead, #include Pass.h
//
//===----------------------------------------------------------------------===//
#if !defined(LLVM_PASS_H) || defined(LLVM_PASSANALYSISSUPPORT_H)
#error "Do not include <PassAnalysisSupport.h>; include <Pass.h> instead"
#endif
#ifndef LLVM_PASSANALYSISSUPPORT_H
#define LLVM_PASSANALYSISSUPPORT_H
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include <cassert>
#include <tuple>
#include <utility>
#include <vector>
namespace llvm {
class Function;
class Pass;
class PMDataManager;
class StringRef;
//===----------------------------------------------------------------------===//
/// Represent the analysis usage information of a pass. This tracks analyses
/// that the pass REQUIRES (must be available when the pass runs), REQUIRES
/// TRANSITIVE (must be available throughout the lifetime of the pass), and
/// analyses that the pass PRESERVES (the pass does not invalidate the results
/// of these analyses). This information is provided by a pass to the Pass
/// infrastructure through the getAnalysisUsage virtual function.
///
class AnalysisUsage {
public:
using VectorType = SmallVectorImpl<AnalysisID>;
private:
/// Sets of analyses required and preserved by a pass
// TODO: It's not clear that SmallVector is an appropriate data structure for
// this usecase. The sizes were picked to minimize wasted space, but are
// otherwise fairly meaningless.
SmallVector<AnalysisID, 8> Required;
SmallVector<AnalysisID, 2> RequiredTransitive;
SmallVector<AnalysisID, 2> Preserved;
SmallVector<AnalysisID, 0> Used;
bool PreservesAll = false;
void pushUnique(VectorType &Set, AnalysisID ID) {
if (!llvm::is_contained(Set, ID))
Set.push_back(ID);
}
public:
AnalysisUsage() = default;
///@{
/// Add the specified ID to the required set of the usage info for a pass.
AnalysisUsage &addRequiredID(const void *ID);
AnalysisUsage &addRequiredID(char &ID);
template<class PassClass>
AnalysisUsage &addRequired() {
return addRequiredID(PassClass::ID);
}
AnalysisUsage &addRequiredTransitiveID(char &ID);
template<class PassClass>
AnalysisUsage &addRequiredTransitive() {
return addRequiredTransitiveID(PassClass::ID);
}
///@}
///@{
/// Add the specified ID to the set of analyses preserved by this pass.
AnalysisUsage &addPreservedID(const void *ID) {
pushUnique(Preserved, ID);
return *this;
}
AnalysisUsage &addPreservedID(char &ID) {
pushUnique(Preserved, &ID);
return *this;
}
/// Add the specified Pass class to the set of analyses preserved by this pass.
template<class PassClass>
AnalysisUsage &addPreserved() {
pushUnique(Preserved, &PassClass::ID);
return *this;
}
///@}
///@{
/// Add the specified ID to the set of analyses used by this pass if they are
/// available..
AnalysisUsage &addUsedIfAvailableID(const void *ID) {
pushUnique(Used, ID);
return *this;
}
AnalysisUsage &addUsedIfAvailableID(char &ID) {
pushUnique(Used, &ID);
return *this;
}
/// Add the specified Pass class to the set of analyses used by this pass.
template<class PassClass>
AnalysisUsage &addUsedIfAvailable() {
pushUnique(Used, &PassClass::ID);
return *this;
}
///@}
/// Add the Pass with the specified argument string to the set of analyses
/// preserved by this pass. If no such Pass exists, do nothing. This can be
/// useful when a pass is trivially preserved, but may not be linked in. Be
/// careful about spelling!
AnalysisUsage &addPreserved(StringRef Arg);
/// Set by analyses that do not transform their input at all
void setPreservesAll() { PreservesAll = true; }
/// Determine whether a pass said it does not transform its input at all
bool getPreservesAll() const { return PreservesAll; }
/// This function should be called by the pass, iff they do not:
///
/// 1. Add or remove basic blocks from the function
/// 2. Modify terminator instructions in any way.
///
/// This function annotates the AnalysisUsage info object to say that analyses
/// that only depend on the CFG are preserved by this pass.
void setPreservesCFG();
const VectorType &getRequiredSet() const { return Required; }
const VectorType &getRequiredTransitiveSet() const {
return RequiredTransitive;
}
const VectorType &getPreservedSet() const { return Preserved; }
const VectorType &getUsedSet() const { return Used; }
};
//===----------------------------------------------------------------------===//
/// AnalysisResolver - Simple interface used by Pass objects to pull all
/// analysis information out of pass manager that is responsible to manage
/// the pass.
///
class AnalysisResolver {
public:
AnalysisResolver() = delete;
explicit AnalysisResolver(PMDataManager &P) : PM(P) {}
PMDataManager &getPMDataManager() { return PM; }
/// Find pass that is implementing PI.
Pass *findImplPass(AnalysisID PI) {
Pass *ResultPass = nullptr;
for (const auto &AnalysisImpl : AnalysisImpls) {
if (AnalysisImpl.first == PI) {
ResultPass = AnalysisImpl.second;
break;
}
}
return ResultPass;
}
/// Find pass that is implementing PI. Initialize pass for Function F.
std::tuple<Pass *, bool> findImplPass(Pass *P, AnalysisID PI, Function &F);
void addAnalysisImplsPair(AnalysisID PI, Pass *P) {
if (findImplPass(PI) == P)
return;
std::pair<AnalysisID, Pass*> pir = std::make_pair(PI,P);
AnalysisImpls.push_back(pir);
}
/// Clear cache that is used to connect a pass to the analysis (PassInfo).
void clearAnalysisImpls() {
AnalysisImpls.clear();
}
/// Return analysis result or null if it doesn't exist.
Pass *getAnalysisIfAvailable(AnalysisID ID) const;
private:
/// This keeps track of which passes implements the interfaces that are
/// required by the current pass (to implement getAnalysis()).
std::vector<std::pair<AnalysisID, Pass *>> AnalysisImpls;
/// PassManager that is used to resolve analysis info
PMDataManager &PM;
};
/// getAnalysisIfAvailable<AnalysisType>() - Subclasses use this function to
/// get analysis information that might be around, for example to update it.
/// This is different than getAnalysis in that it can fail (if the analysis
/// results haven't been computed), so should only be used if you can handle
/// the case when the analysis is not available. This method is often used by
/// transformation APIs to update analysis results for a pass automatically as
/// the transform is performed.
template<typename AnalysisType>
AnalysisType *Pass::getAnalysisIfAvailable() const {
assert(Resolver && "Pass not resident in a PassManager object!");
const void *PI = &AnalysisType::ID;
Pass *ResultPass = Resolver->getAnalysisIfAvailable(PI);
if (!ResultPass) return nullptr;
// Because the AnalysisType may not be a subclass of pass (for
// AnalysisGroups), we use getAdjustedAnalysisPointer here to potentially
// adjust the return pointer (because the class may multiply inherit, once
// from pass, once from AnalysisType).
return (AnalysisType*)ResultPass->getAdjustedAnalysisPointer(PI);
}
/// getAnalysis<AnalysisType>() - This function is used by subclasses to get
/// to the analysis information that they claim to use by overriding the
/// getAnalysisUsage function.
template<typename AnalysisType>
AnalysisType &Pass::getAnalysis() const {
assert(Resolver && "Pass has not been inserted into a PassManager object!");
return getAnalysisID<AnalysisType>(&AnalysisType::ID);
}
template<typename AnalysisType>
AnalysisType &Pass::getAnalysisID(AnalysisID PI) const {
assert(PI && "getAnalysis for unregistered pass!");
assert(Resolver&&"Pass has not been inserted into a PassManager object!");
// PI *must* appear in AnalysisImpls. Because the number of passes used
// should be a small number, we just do a linear search over a (dense)
// vector.
Pass *ResultPass = Resolver->findImplPass(PI);
assert(ResultPass &&
"getAnalysis*() called on an analysis that was not "
"'required' by pass!");
// Because the AnalysisType may not be a subclass of pass (for
// AnalysisGroups), we use getAdjustedAnalysisPointer here to potentially
// adjust the return pointer (because the class may multiply inherit, once
// from pass, once from AnalysisType).
return *(AnalysisType*)ResultPass->getAdjustedAnalysisPointer(PI);
}
/// getAnalysis<AnalysisType>() - This function is used by subclasses to get
/// to the analysis information that they claim to use by overriding the
/// getAnalysisUsage function. If as part of the dependencies, an IR
/// transformation is triggered (e.g. because the analysis requires
/// BreakCriticalEdges), and Changed is non null, *Changed is updated.
template <typename AnalysisType>
AnalysisType &Pass::getAnalysis(Function &F, bool *Changed) {
assert(Resolver &&"Pass has not been inserted into a PassManager object!");
return getAnalysisID<AnalysisType>(&AnalysisType::ID, F, Changed);
}
template <typename AnalysisType>
AnalysisType &Pass::getAnalysisID(AnalysisID PI, Function &F, bool *Changed) {
assert(PI && "getAnalysis for unregistered pass!");
assert(Resolver && "Pass has not been inserted into a PassManager object!");
// PI *must* appear in AnalysisImpls. Because the number of passes used
// should be a small number, we just do a linear search over a (dense)
// vector.
Pass *ResultPass;
bool LocalChanged;
std::tie(ResultPass, LocalChanged) = Resolver->findImplPass(this, PI, F);
assert(ResultPass && "Unable to find requested analysis info");
if (Changed)
*Changed |= LocalChanged;
else
assert(!LocalChanged &&
"A pass trigged a code update but the update status is lost");
// Because the AnalysisType may not be a subclass of pass (for
// AnalysisGroups), we use getAdjustedAnalysisPointer here to potentially
// adjust the return pointer (because the class may multiply inherit, once
// from pass, once from AnalysisType).
return *(AnalysisType*)ResultPass->getAdjustedAnalysisPointer(PI);
}
} // end namespace llvm
#endif // LLVM_PASSANALYSISSUPPORT_H
PK hwFZ��R�� � Debuginfod/HTTPServer.hnu �[��� //===-- llvm/Debuginfod/HTTPServer.h - HTTP server library ------*- 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains the declarations of the HTTPServer and HTTPServerRequest
/// classes, the HTTPResponse, and StreamingHTTPResponse structs, and the
/// streamFile function.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFOD_HTTPSERVER_H
#define LLVM_DEBUGINFOD_HTTPSERVER_H
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#ifdef LLVM_ENABLE_HTTPLIB
// forward declarations
namespace httplib {
class Request;
class Response;
class Server;
} // namespace httplib
#endif
namespace llvm {
struct HTTPResponse;
struct StreamingHTTPResponse;
class HTTPServer;
class HTTPServerError : public ErrorInfo<HTTPServerError, ECError> {
public:
static char ID;
HTTPServerError(const Twine &Msg);
void log(raw_ostream &OS) const override;
private:
std::string Msg;
};
class HTTPServerRequest {
friend HTTPServer;
#ifdef LLVM_ENABLE_HTTPLIB
private:
HTTPServerRequest(const httplib::Request &HTTPLibRequest,
httplib::Response &HTTPLibResponse);
httplib::Response &HTTPLibResponse;
#endif
public:
std::string UrlPath;
/// The elements correspond to match groups in the url path matching regex.
SmallVector<std::string, 1> UrlPathMatches;
// TODO bring in HTTP headers
void setResponse(StreamingHTTPResponse Response);
void setResponse(HTTPResponse Response);
};
struct HTTPResponse {
unsigned Code;
const char *ContentType;
StringRef Body;
};
typedef std::function<void(HTTPServerRequest &)> HTTPRequestHandler;
/// An HTTPContentProvider is called by the HTTPServer to obtain chunks of the
/// streaming response body. The returned chunk should be located at Offset
/// bytes and have Length bytes.
typedef std::function<StringRef(size_t /*Offset*/, size_t /*Length*/)>
HTTPContentProvider;
/// Wraps the content provider with HTTP Status code and headers.
struct StreamingHTTPResponse {
unsigned Code;
const char *ContentType;
size_t ContentLength;
HTTPContentProvider Provider;
/// Called after the response transfer is complete with the success value of
/// the transfer.
std::function<void(bool)> CompletionHandler = [](bool Success) {};
};
/// Sets the response to stream the file at FilePath, if available, and
/// otherwise an HTTP 404 error response.
bool streamFile(HTTPServerRequest &Request, StringRef FilePath);
/// An HTTP server which can listen on a single TCP/IP port for HTTP
/// requests and delgate them to the appropriate registered handler.
class HTTPServer {
#ifdef LLVM_ENABLE_HTTPLIB
std::unique_ptr<httplib::Server> Server;
unsigned Port = 0;
#endif
public:
HTTPServer();
~HTTPServer();
/// Returns true only if LLVM has been compiled with a working HTTPServer.
static bool isAvailable();
/// Registers a URL pattern routing rule. When the server is listening, each
/// request is dispatched to the first registered handler whose UrlPathPattern
/// matches the UrlPath.
Error get(StringRef UrlPathPattern, HTTPRequestHandler Handler);
/// Attempts to assign the requested port and interface, returning an Error
/// upon failure.
Error bind(unsigned Port, const char *HostInterface = "0.0.0.0");
/// Attempts to assign any available port and interface, returning either the
/// port number or an Error upon failure.
Expected<unsigned> bind(const char *HostInterface = "0.0.0.0");
/// Attempts to listen for requests on the bound port. Returns an Error if
/// called before binding a port.
Error listen();
/// If the server is listening, stop and unbind the socket.
void stop();
};
} // end namespace llvm
#endif // LLVM_DEBUGINFOD_HTTPSERVER_H
PK hwFZu��PN N Debuginfod/DIFetcher.hnu �[��� //===- llvm/DebugInfod/DIFetcher.h - Debug info fetcher----------*- 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file declares a DIFetcher implementation for obtaining debug info from
/// debuginfod.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFOD_DIFETCHER_H
#define LLVM_DEBUGINFOD_DIFETCHER_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/DebugInfo/Symbolize/DIFetcher.h"
namespace llvm {
class DebuginfodDIFetcher : public symbolize::DIFetcher {
public:
virtual ~DebuginfodDIFetcher() = default;
/// Fetches the given Build ID using debuginfod and returns a local path to
/// the resulting debug binary.
Optional<std::string> fetchBuildID(ArrayRef<uint8_t> BuildID) const override;
};
} // namespace llvm
#endif // LLVM_DEBUGINFOD_DIFETCHER_H
PK hwFZHV*�
�
Debuginfod/HTTPClient.hnu �[��� //===-- llvm/Support/HTTPClient.h - HTTP client library ---------*- 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains the declarations of the HTTPClient library for issuing
/// HTTP requests and handling the responses.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFOD_HTTPCLIENT_H
#define LLVM_DEBUGINFOD_HTTPCLIENT_H
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"
#include <chrono>
namespace llvm {
enum class HTTPMethod { GET };
/// A stateless description of an outbound HTTP request.
struct HTTPRequest {
SmallString<128> Url;
SmallVector<std::string, 0> Headers;
HTTPMethod Method = HTTPMethod::GET;
bool FollowRedirects = true;
HTTPRequest(StringRef Url);
};
bool operator==(const HTTPRequest &A, const HTTPRequest &B);
/// A handler for state updates occurring while an HTTPRequest is performed.
/// Can trigger the client to abort the request by returning an Error from any
/// of its methods.
class HTTPResponseHandler {
public:
/// Processes an additional chunk of bytes of the HTTP response body.
virtual Error handleBodyChunk(StringRef BodyChunk) = 0;
protected:
~HTTPResponseHandler();
};
/// A reusable client that can perform HTTPRequests through a network socket.
class HTTPClient {
#ifdef LLVM_ENABLE_CURL
void *Curl = nullptr;
#endif
public:
HTTPClient();
~HTTPClient();
static bool IsInitialized;
/// Returns true only if LLVM has been compiled with a working HTTPClient.
static bool isAvailable();
/// Must be called at the beginning of a program, while it is a single thread.
static void initialize();
/// Must be called at the end of a program, while it is a single thread.
static void cleanup();
/// Sets the timeout for the entire request, in milliseconds. A zero or
/// negative value means the request never times out.
void setTimeout(std::chrono::milliseconds Timeout);
/// Performs the Request, passing response data to the Handler. Returns all
/// errors which occur during the request. Aborts if an error is returned by a
/// Handler method.
Error perform(const HTTPRequest &Request, HTTPResponseHandler &Handler);
/// Returns the last received response code or zero if none.
unsigned responseCode();
};
} // end namespace llvm
#endif // LLVM_DEBUGINFOD_HTTPCLIENT_H
PK hwFZ1gx Debuginfod/Debuginfod.hnu �[��� //===-- llvm/Debuginfod/Debuginfod.h - Debuginfod client --------*- 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains several declarations for the debuginfod client and
/// server. The client functions are getDefaultDebuginfodUrls,
/// getCachedOrDownloadArtifact, and several convenience functions for specific
/// artifact types: getCachedOrDownloadSource, getCachedOrDownloadExecutable,
/// and getCachedOrDownloadDebuginfo. For the server, this file declares the
/// DebuginfodLogEntry and DebuginfodServer structs, as well as the
/// DebuginfodLog, DebuginfodCollection classes.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFOD_DEBUGINFOD_H
#define LLVM_DEBUGINFOD_DEBUGINFOD_H
#include "HTTPServer.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/BuildID.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/RWMutex.h"
#include "llvm/Support/Timer.h"
#include <chrono>
#include <condition_variable>
#include <optional>
#include <queue>
namespace llvm {
/// Returns false if a debuginfod lookup can be determined to have no chance of
/// succeeding.
bool canUseDebuginfod();
/// Finds default array of Debuginfod server URLs by checking DEBUGINFOD_URLS
/// environment variable.
SmallVector<StringRef> getDefaultDebuginfodUrls();
/// Finds a default local file caching directory for the debuginfod client,
/// first checking DEBUGINFOD_CACHE_PATH.
Expected<std::string> getDefaultDebuginfodCacheDirectory();
/// Finds a default timeout for debuginfod HTTP requests. Checks
/// DEBUGINFOD_TIMEOUT environment variable, default is 90 seconds (90000 ms).
std::chrono::milliseconds getDefaultDebuginfodTimeout();
/// Fetches a specified source file by searching the default local cache
/// directory and server URLs.
Expected<std::string> getCachedOrDownloadSource(object::BuildIDRef ID,
StringRef SourceFilePath);
/// Fetches an executable by searching the default local cache directory and
/// server URLs.
Expected<std::string> getCachedOrDownloadExecutable(object::BuildIDRef ID);
/// Fetches a debug binary by searching the default local cache directory and
/// server URLs.
Expected<std::string> getCachedOrDownloadDebuginfo(object::BuildIDRef ID);
/// Fetches any debuginfod artifact using the default local cache directory and
/// server URLs.
Expected<std::string> getCachedOrDownloadArtifact(StringRef UniqueKey,
StringRef UrlPath);
/// Fetches any debuginfod artifact using the specified local cache directory,
/// server URLs, and request timeout (in milliseconds). If the artifact is
/// found, uses the UniqueKey for the local cache file.
Expected<std::string> getCachedOrDownloadArtifact(
StringRef UniqueKey, StringRef UrlPath, StringRef CacheDirectoryPath,
ArrayRef<StringRef> DebuginfodUrls, std::chrono::milliseconds Timeout);
class ThreadPool;
struct DebuginfodLogEntry {
std::string Message;
DebuginfodLogEntry() = default;
DebuginfodLogEntry(const Twine &Message);
};
class DebuginfodLog {
std::mutex QueueMutex;
std::condition_variable QueueCondition;
std::queue<DebuginfodLogEntry> LogEntryQueue;
public:
// Adds a log entry to end of the queue.
void push(DebuginfodLogEntry Entry);
// Adds a log entry to end of the queue.
void push(const Twine &Message);
// Blocks until there are log entries in the queue, then pops and returns the
// first one.
DebuginfodLogEntry pop();
};
/// Tracks a collection of debuginfod artifacts on the local filesystem.
class DebuginfodCollection {
SmallVector<std::string, 1> Paths;
sys::RWMutex BinariesMutex;
StringMap<std::string> Binaries;
sys::RWMutex DebugBinariesMutex;
StringMap<std::string> DebugBinaries;
Error findBinaries(StringRef Path);
Expected<std::optional<std::string>> getDebugBinaryPath(object::BuildIDRef);
Expected<std::optional<std::string>> getBinaryPath(object::BuildIDRef);
// If the collection has not been updated since MinInterval, call update() and
// return true. Otherwise return false. If update returns an error, return the
// error.
Expected<bool> updateIfStale();
DebuginfodLog &Log;
ThreadPool &Pool;
Timer UpdateTimer;
sys::Mutex UpdateMutex;
// Minimum update interval, in seconds, for on-demand updates triggered when a
// build-id is not found.
double MinInterval;
public:
DebuginfodCollection(ArrayRef<StringRef> Paths, DebuginfodLog &Log,
ThreadPool &Pool, double MinInterval);
Error update();
Error updateForever(std::chrono::milliseconds Interval);
Expected<std::string> findDebugBinaryPath(object::BuildIDRef);
Expected<std::string> findBinaryPath(object::BuildIDRef);
};
struct DebuginfodServer {
HTTPServer Server;
DebuginfodLog &Log;
DebuginfodCollection &Collection;
DebuginfodServer(DebuginfodLog &Log, DebuginfodCollection &Collection);
};
} // end namespace llvm
#endif
PK hwFZ���ˮ � Debuginfod/BuildIDFetcher.hnu �[��� //===- llvm/DebugInfod/BuildIDFetcher.h - Build ID fetcher ------*- 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file declares a Build ID fetcher implementation for obtaining debug
/// info from debuginfod.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFOD_DIFETCHER_H
#define LLVM_DEBUGINFOD_DIFETCHER_H
#include "llvm/Object/BuildID.h"
#include <optional>
namespace llvm {
class DebuginfodFetcher : public object::BuildIDFetcher {
public:
DebuginfodFetcher(std::vector<std::string> DebugFileDirectories)
: BuildIDFetcher(std::move(DebugFileDirectories)) {}
virtual ~DebuginfodFetcher() = default;
/// Fetches the given Build ID using debuginfod and returns a local path to
/// the resulting file.
std::optional<std::string> fetch(object::BuildIDRef BuildID) const override;
};
} // namespace llvm
#endif // LLVM_DEBUGINFOD_DIFETCHER_H
PK hwFZdO��� � Object/RelocationResolver.hnu �[��� //===- RelocVisitor.h - Visitor for object file relocations -----*- 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
//
//===----------------------------------------------------------------------===//
//
// This file provides a wrapper around all the different types of relocations
// in different file formats, such that a client can handle them in a unified
// manner by only implementing a minimal number of functions.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_RELOCATIONRESOLVER_H
#define LLVM_OBJECT_RELOCATIONRESOLVER_H
#include <cstdint>
#include <utility>
namespace llvm {
namespace object {
class ObjectFile;
class RelocationRef;
using SupportsRelocation = bool (*)(uint64_t);
using RelocationResolver = uint64_t (*)(uint64_t Type, uint64_t Offset,
uint64_t S, uint64_t LocData,
int64_t Addend);
std::pair<SupportsRelocation, RelocationResolver>
getRelocationResolver(const ObjectFile &Obj);
uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R,
uint64_t S, uint64_t LocData);
} // end namespace object
} // end namespace llvm
#endif // LLVM_OBJECT_RELOCATIONRESOLVER_H
PK hwFZ�_F(�9 �9 Object/StackMapParser.hnu �[��� //===- StackMapParser.h - StackMap Parsing Support --------------*- 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_STACKMAPPARSER_H
#define LLVM_OBJECT_STACKMAPPARSER_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Object/ELF.h"
#include "llvm/Support/Endian.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <vector>
namespace llvm {
/// A parser for the latest stackmap format. At the moment, latest=V3.
template <support::endianness Endianness>
class StackMapParser {
public:
template <typename AccessorT>
class AccessorIterator {
public:
AccessorIterator(AccessorT A) : A(A) {}
AccessorIterator& operator++() { A = A.next(); return *this; }
AccessorIterator operator++(int) {
auto tmp = *this;
++*this;
return tmp;
}
bool operator==(const AccessorIterator &Other) const {
return A.P == Other.A.P;
}
bool operator!=(const AccessorIterator &Other) const {
return !(*this == Other);
}
AccessorT& operator*() { return A; }
AccessorT* operator->() { return &A; }
private:
AccessorT A;
};
/// Accessor for function records.
class FunctionAccessor {
friend class StackMapParser;
public:
/// Get the function address.
uint64_t getFunctionAddress() const {
return read<uint64_t>(P);
}
/// Get the function's stack size.
uint64_t getStackSize() const {
return read<uint64_t>(P + sizeof(uint64_t));
}
/// Get the number of callsite records.
uint64_t getRecordCount() const {
return read<uint64_t>(P + (2 * sizeof(uint64_t)));
}
private:
FunctionAccessor(const uint8_t *P) : P(P) {}
const static int FunctionAccessorSize = 3 * sizeof(uint64_t);
FunctionAccessor next() const {
return FunctionAccessor(P + FunctionAccessorSize);
}
const uint8_t *P;
};
/// Accessor for constants.
class ConstantAccessor {
friend class StackMapParser;
public:
/// Return the value of this constant.
uint64_t getValue() const { return read<uint64_t>(P); }
private:
ConstantAccessor(const uint8_t *P) : P(P) {}
const static int ConstantAccessorSize = sizeof(uint64_t);
ConstantAccessor next() const {
return ConstantAccessor(P + ConstantAccessorSize);
}
const uint8_t *P;
};
enum class LocationKind : uint8_t {
Register = 1, Direct = 2, Indirect = 3, Constant = 4, ConstantIndex = 5
};
/// Accessor for location records.
class LocationAccessor {
friend class StackMapParser;
friend class RecordAccessor;
public:
/// Get the Kind for this location.
LocationKind getKind() const {
return LocationKind(P[KindOffset]);
}
/// Get the Size for this location.
unsigned getSizeInBytes() const {
return read<uint16_t>(P + SizeOffset);
}
/// Get the Dwarf register number for this location.
uint16_t getDwarfRegNum() const {
return read<uint16_t>(P + DwarfRegNumOffset);
}
/// Get the small-constant for this location. (Kind must be Constant).
uint32_t getSmallConstant() const {
assert(getKind() == LocationKind::Constant && "Not a small constant.");
return read<uint32_t>(P + SmallConstantOffset);
}
/// Get the constant-index for this location. (Kind must be ConstantIndex).
uint32_t getConstantIndex() const {
assert(getKind() == LocationKind::ConstantIndex &&
"Not a constant-index.");
return read<uint32_t>(P + SmallConstantOffset);
}
/// Get the offset for this location. (Kind must be Direct or Indirect).
int32_t getOffset() const {
assert((getKind() == LocationKind::Direct ||
getKind() == LocationKind::Indirect) &&
"Not direct or indirect.");
return read<int32_t>(P + SmallConstantOffset);
}
private:
LocationAccessor(const uint8_t *P) : P(P) {}
LocationAccessor next() const {
return LocationAccessor(P + LocationAccessorSize);
}
static const int KindOffset = 0;
static const int SizeOffset = KindOffset + sizeof(uint16_t);
static const int DwarfRegNumOffset = SizeOffset + sizeof(uint16_t);
static const int SmallConstantOffset = DwarfRegNumOffset + sizeof(uint32_t);
static const int LocationAccessorSize = sizeof(uint64_t) + sizeof(uint32_t);
const uint8_t *P;
};
/// Accessor for stackmap live-out fields.
class LiveOutAccessor {
friend class StackMapParser;
friend class RecordAccessor;
public:
/// Get the Dwarf register number for this live-out.
uint16_t getDwarfRegNum() const {
return read<uint16_t>(P + DwarfRegNumOffset);
}
/// Get the size in bytes of live [sub]register.
unsigned getSizeInBytes() const {
return read<uint8_t>(P + SizeOffset);
}
private:
LiveOutAccessor(const uint8_t *P) : P(P) {}
LiveOutAccessor next() const {
return LiveOutAccessor(P + LiveOutAccessorSize);
}
static const int DwarfRegNumOffset = 0;
static const int SizeOffset =
DwarfRegNumOffset + sizeof(uint16_t) + sizeof(uint8_t);
static const int LiveOutAccessorSize = sizeof(uint32_t);
const uint8_t *P;
};
/// Accessor for stackmap records.
class RecordAccessor {
friend class StackMapParser;
public:
using location_iterator = AccessorIterator<LocationAccessor>;
using liveout_iterator = AccessorIterator<LiveOutAccessor>;
/// Get the patchpoint/stackmap ID for this record.
uint64_t getID() const {
return read<uint64_t>(P + PatchpointIDOffset);
}
/// Get the instruction offset (from the start of the containing function)
/// for this record.
uint32_t getInstructionOffset() const {
return read<uint32_t>(P + InstructionOffsetOffset);
}
/// Get the number of locations contained in this record.
uint16_t getNumLocations() const {
return read<uint16_t>(P + NumLocationsOffset);
}
/// Get the location with the given index.
LocationAccessor getLocation(unsigned LocationIndex) const {
unsigned LocationOffset =
LocationListOffset + LocationIndex * LocationSize;
return LocationAccessor(P + LocationOffset);
}
/// Begin iterator for locations.
location_iterator location_begin() const {
return location_iterator(getLocation(0));
}
/// End iterator for locations.
location_iterator location_end() const {
return location_iterator(getLocation(getNumLocations()));
}
/// Iterator range for locations.
iterator_range<location_iterator> locations() const {
return make_range(location_begin(), location_end());
}
/// Get the number of liveouts contained in this record.
uint16_t getNumLiveOuts() const {
return read<uint16_t>(P + getNumLiveOutsOffset());
}
/// Get the live-out with the given index.
LiveOutAccessor getLiveOut(unsigned LiveOutIndex) const {
unsigned LiveOutOffset =
getNumLiveOutsOffset() + sizeof(uint16_t) + LiveOutIndex * LiveOutSize;
return LiveOutAccessor(P + LiveOutOffset);
}
/// Begin iterator for live-outs.
liveout_iterator liveouts_begin() const {
return liveout_iterator(getLiveOut(0));
}
/// End iterator for live-outs.
liveout_iterator liveouts_end() const {
return liveout_iterator(getLiveOut(getNumLiveOuts()));
}
/// Iterator range for live-outs.
iterator_range<liveout_iterator> liveouts() const {
return make_range(liveouts_begin(), liveouts_end());
}
private:
RecordAccessor(const uint8_t *P) : P(P) {}
unsigned getNumLiveOutsOffset() const {
unsigned LocOffset =
((LocationListOffset + LocationSize * getNumLocations()) + 7) & ~0x7;
return LocOffset + sizeof(uint16_t);
}
unsigned getSizeInBytes() const {
unsigned RecordSize =
getNumLiveOutsOffset() + sizeof(uint16_t) + getNumLiveOuts() * LiveOutSize;
return (RecordSize + 7) & ~0x7;
}
RecordAccessor next() const {
return RecordAccessor(P + getSizeInBytes());
}
static const unsigned PatchpointIDOffset = 0;
static const unsigned InstructionOffsetOffset =
PatchpointIDOffset + sizeof(uint64_t);
static const unsigned NumLocationsOffset =
InstructionOffsetOffset + sizeof(uint32_t) + sizeof(uint16_t);
static const unsigned LocationListOffset =
NumLocationsOffset + sizeof(uint16_t);
static const unsigned LocationSize = sizeof(uint64_t) + sizeof(uint32_t);
static const unsigned LiveOutSize = sizeof(uint32_t);
const uint8_t *P;
};
/// Construct a parser for a version-3 stackmap. StackMap data will be read
/// from the given array.
StackMapParser(ArrayRef<uint8_t> StackMapSection)
: StackMapSection(StackMapSection) {
ConstantsListOffset = FunctionListOffset + getNumFunctions() * FunctionSize;
assert(StackMapSection[0] == 3 &&
"StackMapParser can only parse version 3 stackmaps");
unsigned CurrentRecordOffset =
ConstantsListOffset + getNumConstants() * ConstantSize;
for (unsigned I = 0, E = getNumRecords(); I != E; ++I) {
StackMapRecordOffsets.push_back(CurrentRecordOffset);
CurrentRecordOffset +=
RecordAccessor(&StackMapSection[CurrentRecordOffset]).getSizeInBytes();
}
}
/// Validates the header of the specified stack map section.
static Error validateHeader(ArrayRef<uint8_t> StackMapSection) {
// See the comment for StackMaps::emitStackmapHeader().
if (StackMapSection.size() < 16)
return object::createError(
"the stack map section size (" + Twine(StackMapSection.size()) +
") is less than the minimum possible size of its header (16)");
unsigned Version = StackMapSection[0];
if (Version != 3)
return object::createError(
"the version (" + Twine(Version) +
") of the stack map section is unsupported, the "
"supported version is 3");
return Error::success();
}
using function_iterator = AccessorIterator<FunctionAccessor>;
using constant_iterator = AccessorIterator<ConstantAccessor>;
using record_iterator = AccessorIterator<RecordAccessor>;
/// Get the version number of this stackmap. (Always returns 3).
unsigned getVersion() const { return 3; }
/// Get the number of functions in the stack map.
uint32_t getNumFunctions() const {
return read<uint32_t>(&StackMapSection[NumFunctionsOffset]);
}
/// Get the number of large constants in the stack map.
uint32_t getNumConstants() const {
return read<uint32_t>(&StackMapSection[NumConstantsOffset]);
}
/// Get the number of stackmap records in the stackmap.
uint32_t getNumRecords() const {
return read<uint32_t>(&StackMapSection[NumRecordsOffset]);
}
/// Return an FunctionAccessor for the given function index.
FunctionAccessor getFunction(unsigned FunctionIndex) const {
return FunctionAccessor(StackMapSection.data() +
getFunctionOffset(FunctionIndex));
}
/// Begin iterator for functions.
function_iterator functions_begin() const {
return function_iterator(getFunction(0));
}
/// End iterator for functions.
function_iterator functions_end() const {
return function_iterator(
FunctionAccessor(StackMapSection.data() +
getFunctionOffset(getNumFunctions())));
}
/// Iterator range for functions.
iterator_range<function_iterator> functions() const {
return make_range(functions_begin(), functions_end());
}
/// Return the large constant at the given index.
ConstantAccessor getConstant(unsigned ConstantIndex) const {
return ConstantAccessor(StackMapSection.data() +
getConstantOffset(ConstantIndex));
}
/// Begin iterator for constants.
constant_iterator constants_begin() const {
return constant_iterator(getConstant(0));
}
/// End iterator for constants.
constant_iterator constants_end() const {
return constant_iterator(
ConstantAccessor(StackMapSection.data() +
getConstantOffset(getNumConstants())));
}
/// Iterator range for constants.
iterator_range<constant_iterator> constants() const {
return make_range(constants_begin(), constants_end());
}
/// Return a RecordAccessor for the given record index.
RecordAccessor getRecord(unsigned RecordIndex) const {
std::size_t RecordOffset = StackMapRecordOffsets[RecordIndex];
return RecordAccessor(StackMapSection.data() + RecordOffset);
}
/// Begin iterator for records.
record_iterator records_begin() const {
if (getNumRecords() == 0)
return record_iterator(RecordAccessor(nullptr));
return record_iterator(getRecord(0));
}
/// End iterator for records.
record_iterator records_end() const {
// Records need to be handled specially, since we cache the start addresses
// for them: We can't just compute the 1-past-the-end address, we have to
// look at the last record and use the 'next' method.
if (getNumRecords() == 0)
return record_iterator(RecordAccessor(nullptr));
return record_iterator(getRecord(getNumRecords() - 1).next());
}
/// Iterator range for records.
iterator_range<record_iterator> records() const {
return make_range(records_begin(), records_end());
}
private:
template <typename T>
static T read(const uint8_t *P) {
return support::endian::read<T, Endianness, 1>(P);
}
static const unsigned HeaderOffset = 0;
static const unsigned NumFunctionsOffset = HeaderOffset + sizeof(uint32_t);
static const unsigned NumConstantsOffset = NumFunctionsOffset + sizeof(uint32_t);
static const unsigned NumRecordsOffset = NumConstantsOffset + sizeof(uint32_t);
static const unsigned FunctionListOffset = NumRecordsOffset + sizeof(uint32_t);
static const unsigned FunctionSize = 3 * sizeof(uint64_t);
static const unsigned ConstantSize = sizeof(uint64_t);
std::size_t getFunctionOffset(unsigned FunctionIndex) const {
return FunctionListOffset + FunctionIndex * FunctionSize;
}
std::size_t getConstantOffset(unsigned ConstantIndex) const {
return ConstantsListOffset + ConstantIndex * ConstantSize;
}
ArrayRef<uint8_t> StackMapSection;
unsigned ConstantsListOffset;
std::vector<unsigned> StackMapRecordOffsets;
};
} // end namespace llvm
#endif // LLVM_OBJECT_STACKMAPPARSER_H
PK hwFZ��Y�� � Object/ModuleSymbolTable.hnu �[��� //===- ModuleSymbolTable.h - symbol table for in-memory IR ------*- 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
//
//===----------------------------------------------------------------------===//
//
// This class represents a symbol table built from in-memory IR. It provides
// access to GlobalValues and should only be used if such access is required
// (e.g. in the LTO implementation).
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_MODULESYMBOLTABLE_H
#define LLVM_OBJECT_MODULESYMBOLTABLE_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/IR/Mangler.h"
#include "llvm/Object/SymbolicFile.h"
#include "llvm/Support/Allocator.h"
#include <cstdint>
#include <string>
#include <utility>
#include <vector>
namespace llvm {
class GlobalValue;
class Module;
class ModuleSymbolTable {
public:
using AsmSymbol = std::pair<std::string, uint32_t>;
using Symbol = PointerUnion<GlobalValue *, AsmSymbol *>;
private:
Module *FirstMod = nullptr;
SpecificBumpPtrAllocator<AsmSymbol> AsmSymbols;
std::vector<Symbol> SymTab;
Mangler Mang;
public:
ArrayRef<Symbol> symbols() const { return SymTab; }
void addModule(Module *M);
void printSymbolName(raw_ostream &OS, Symbol S) const;
uint32_t getSymbolFlags(Symbol S) const;
/// Parse inline ASM and collect the symbols that are defined or referenced in
/// the current module.
///
/// For each found symbol, call \p AsmSymbol with the name of the symbol found
/// and the associated flags.
static void CollectAsmSymbols(
const Module &M,
function_ref<void(StringRef, object::BasicSymbolRef::Flags)> AsmSymbol);
/// Parse inline ASM and collect the symvers directives that are defined in
/// the current module.
///
/// For each found symbol, call \p AsmSymver with the name of the symbol and
/// its alias.
static void
CollectAsmSymvers(const Module &M,
function_ref<void(StringRef, StringRef)> AsmSymver);
};
} // end namespace llvm
#endif // LLVM_OBJECT_MODULESYMBOLTABLE_H
PK hwFZ߿��$ $ Object/Minidump.hnu �[��� //===- Minidump.h - Minidump object file implementation ---------*- 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_MINIDUMP_H
#define LLVM_OBJECT_MINIDUMP_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/iterator.h"
#include "llvm/BinaryFormat/Minidump.h"
#include "llvm/Object/Binary.h"
#include "llvm/Support/Error.h"
namespace llvm {
namespace object {
/// A class providing access to the contents of a minidump file.
class MinidumpFile : public Binary {
public:
/// Construct a new MinidumpFile object from the given memory buffer. Returns
/// an error if this file cannot be identified as a minidump file, or if its
/// contents are badly corrupted (i.e. we cannot read the stream directory).
static Expected<std::unique_ptr<MinidumpFile>> create(MemoryBufferRef Source);
static bool classof(const Binary *B) { return B->isMinidump(); }
/// Returns the contents of the minidump header.
const minidump::Header &header() const { return Header; }
/// Returns the list of streams (stream directory entries) in this file.
ArrayRef<minidump::Directory> streams() const { return Streams; }
/// Returns the raw contents of the stream given by the directory entry.
ArrayRef<uint8_t> getRawStream(const minidump::Directory &Stream) const {
return getData().slice(Stream.Location.RVA, Stream.Location.DataSize);
}
/// Returns the raw contents of the stream of the given type, or std::nullopt
/// if the file does not contain a stream of this type.
std::optional<ArrayRef<uint8_t>>
getRawStream(minidump::StreamType Type) const;
/// Returns the raw contents of an object given by the LocationDescriptor. An
/// error is returned if the descriptor points outside of the minidump file.
Expected<ArrayRef<uint8_t>>
getRawData(minidump::LocationDescriptor Desc) const {
return getDataSlice(getData(), Desc.RVA, Desc.DataSize);
}
/// Returns the minidump string at the given offset. An error is returned if
/// we fail to parse the string, or the string is invalid UTF16.
Expected<std::string> getString(size_t Offset) const;
/// Returns the contents of the SystemInfo stream, cast to the appropriate
/// type. An error is returned if the file does not contain this stream, or
/// the stream is smaller than the size of the SystemInfo structure. The
/// internal consistency of the stream is not checked in any way.
Expected<const minidump::SystemInfo &> getSystemInfo() const {
return getStream<minidump::SystemInfo>(minidump::StreamType::SystemInfo);
}
/// Returns the module list embedded in the ModuleList stream. An error is
/// returned if the file does not contain this stream, or if the stream is
/// not large enough to contain the number of modules declared in the stream
/// header. The consistency of the Module entries themselves is not checked in
/// any way.
Expected<ArrayRef<minidump::Module>> getModuleList() const {
return getListStream<minidump::Module>(minidump::StreamType::ModuleList);
}
/// Returns the thread list embedded in the ThreadList stream. An error is
/// returned if the file does not contain this stream, or if the stream is
/// not large enough to contain the number of threads declared in the stream
/// header. The consistency of the Thread entries themselves is not checked in
/// any way.
Expected<ArrayRef<minidump::Thread>> getThreadList() const {
return getListStream<minidump::Thread>(minidump::StreamType::ThreadList);
}
/// Returns the contents of the Exception stream. An error is returned if the
/// file does not contain this stream, or the stream is smaller than the size
/// of the ExceptionStream structure. The internal consistency of the stream
/// is not checked in any way.
Expected<const minidump::ExceptionStream &> getExceptionStream() const {
return getStream<minidump::ExceptionStream>(
minidump::StreamType::Exception);
}
/// Returns the list of descriptors embedded in the MemoryList stream. The
/// descriptors provide the content of interesting regions of memory at the
/// time the minidump was taken. An error is returned if the file does not
/// contain this stream, or if the stream is not large enough to contain the
/// number of memory descriptors declared in the stream header. The
/// consistency of the MemoryDescriptor entries themselves is not checked in
/// any way.
Expected<ArrayRef<minidump::MemoryDescriptor>> getMemoryList() const {
return getListStream<minidump::MemoryDescriptor>(
minidump::StreamType::MemoryList);
}
class MemoryInfoIterator
: public iterator_facade_base<MemoryInfoIterator,
std::forward_iterator_tag,
minidump::MemoryInfo> {
public:
MemoryInfoIterator(ArrayRef<uint8_t> Storage, size_t Stride)
: Storage(Storage), Stride(Stride) {
assert(Storage.size() % Stride == 0);
}
bool operator==(const MemoryInfoIterator &R) const {
return Storage.size() == R.Storage.size();
}
const minidump::MemoryInfo &operator*() const {
assert(Storage.size() >= sizeof(minidump::MemoryInfo));
return *reinterpret_cast<const minidump::MemoryInfo *>(Storage.data());
}
MemoryInfoIterator &operator++() {
Storage = Storage.drop_front(Stride);
return *this;
}
private:
ArrayRef<uint8_t> Storage;
size_t Stride;
};
/// Returns the list of descriptors embedded in the MemoryInfoList stream. The
/// descriptors provide properties (e.g. permissions) of interesting regions
/// of memory at the time the minidump was taken. An error is returned if the
/// file does not contain this stream, or if the stream is not large enough to
/// contain the number of memory descriptors declared in the stream header.
/// The consistency of the MemoryInfoList entries themselves is not checked
/// in any way.
Expected<iterator_range<MemoryInfoIterator>> getMemoryInfoList() const;
private:
static Error createError(StringRef Str) {
return make_error<GenericBinaryError>(Str, object_error::parse_failed);
}
static Error createEOFError() {
return make_error<GenericBinaryError>("Unexpected EOF",
object_error::unexpected_eof);
}
/// Return a slice of the given data array, with bounds checking.
static Expected<ArrayRef<uint8_t>> getDataSlice(ArrayRef<uint8_t> Data,
size_t Offset, size_t Size);
/// Return the slice of the given data array as an array of objects of the
/// given type. The function checks that the input array is large enough to
/// contain the correct number of objects of the given type.
template <typename T>
static Expected<ArrayRef<T>> getDataSliceAs(ArrayRef<uint8_t> Data,
size_t Offset, size_t Count);
MinidumpFile(MemoryBufferRef Source, const minidump::Header &Header,
ArrayRef<minidump::Directory> Streams,
DenseMap<minidump::StreamType, std::size_t> StreamMap)
: Binary(ID_Minidump, Source), Header(Header), Streams(Streams),
StreamMap(std::move(StreamMap)) {}
ArrayRef<uint8_t> getData() const {
return arrayRefFromStringRef(Data.getBuffer());
}
/// Return the stream of the given type, cast to the appropriate type. Checks
/// that the stream is large enough to hold an object of this type.
template <typename T>
Expected<const T &> getStream(minidump::StreamType Stream) const;
/// Return the contents of a stream which contains a list of fixed-size items,
/// prefixed by the list size.
template <typename T>
Expected<ArrayRef<T>> getListStream(minidump::StreamType Stream) const;
const minidump::Header &Header;
ArrayRef<minidump::Directory> Streams;
DenseMap<minidump::StreamType, std::size_t> StreamMap;
};
template <typename T>
Expected<const T &> MinidumpFile::getStream(minidump::StreamType Type) const {
if (std::optional<ArrayRef<uint8_t>> Stream = getRawStream(Type)) {
if (Stream->size() >= sizeof(T))
return *reinterpret_cast<const T *>(Stream->data());
return createEOFError();
}
return createError("No such stream");
}
template <typename T>
Expected<ArrayRef<T>> MinidumpFile::getDataSliceAs(ArrayRef<uint8_t> Data,
size_t Offset,
size_t Count) {
// Check for overflow.
if (Count > std::numeric_limits<size_t>::max() / sizeof(T))
return createEOFError();
Expected<ArrayRef<uint8_t>> Slice =
getDataSlice(Data, Offset, sizeof(T) * Count);
if (!Slice)
return Slice.takeError();
return ArrayRef<T>(reinterpret_cast<const T *>(Slice->data()), Count);
}
} // end namespace object
} // end namespace llvm
#endif // LLVM_OBJECT_MINIDUMP_H
PK hwFZEu� Object/TapiFile.hnu �[��� //===- TapiFile.h - Text-based Dynamic Library Stub -------------*- 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
//
//===----------------------------------------------------------------------===//
//
// This file declares the TapiFile interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_TAPIFILE_H
#define LLVM_OBJECT_TAPIFILE_H
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/SymbolicFile.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBufferRef.h"
#include "llvm/TextAPI/Architecture.h"
namespace llvm {
class raw_ostream;
namespace MachO {
class InterfaceFile;
}
namespace object {
class TapiFile : public SymbolicFile {
public:
TapiFile(MemoryBufferRef Source, const MachO::InterfaceFile &Interface,
MachO::Architecture Arch);
~TapiFile() override;
void moveSymbolNext(DataRefImpl &DRI) const override;
Error printSymbolName(raw_ostream &OS, DataRefImpl DRI) const override;
Expected<uint32_t> getSymbolFlags(DataRefImpl DRI) const override;
basic_symbol_iterator symbol_begin() const override;
basic_symbol_iterator symbol_end() const override;
Expected<SymbolRef::Type> getSymbolType(DataRefImpl DRI) const;
static bool classof(const Binary *v) { return v->isTapiFile(); }
bool is64Bit() const override { return MachO::is64Bit(Arch); }
private:
struct Symbol {
StringRef Prefix;
StringRef Name;
uint32_t Flags;
SymbolRef::Type Type;
constexpr Symbol(StringRef Prefix, StringRef Name, uint32_t Flags,
SymbolRef::Type Type)
: Prefix(Prefix), Name(Name), Flags(Flags), Type(Type) {}
};
std::vector<Symbol> Symbols;
MachO::Architecture Arch;
};
} // end namespace object.
} // end namespace llvm.
#endif // LLVM_OBJECT_TAPIFILE_H
PK hwFZ��,X� X� Object/ELFTypes.hnu �[��� //===- ELFTypes.h - Endian specific types for ELF ---------------*- 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_ELFTYPES_H
#define LLVM_OBJECT_ELFTYPES_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Object/Error.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
#include <cstdint>
#include <cstring>
#include <type_traits>
namespace llvm {
namespace object {
using support::endianness;
template <class ELFT> struct Elf_Ehdr_Impl;
template <class ELFT> struct Elf_Shdr_Impl;
template <class ELFT> struct Elf_Sym_Impl;
template <class ELFT> struct Elf_Dyn_Impl;
template <class ELFT> struct Elf_Phdr_Impl;
template <class ELFT, bool isRela> struct Elf_Rel_Impl;
template <class ELFT> struct Elf_Verdef_Impl;
template <class ELFT> struct Elf_Verdaux_Impl;
template <class ELFT> struct Elf_Verneed_Impl;
template <class ELFT> struct Elf_Vernaux_Impl;
template <class ELFT> struct Elf_Versym_Impl;
template <class ELFT> struct Elf_Hash_Impl;
template <class ELFT> struct Elf_GnuHash_Impl;
template <class ELFT> struct Elf_Chdr_Impl;
template <class ELFT> struct Elf_Nhdr_Impl;
template <class ELFT> class Elf_Note_Impl;
template <class ELFT> class Elf_Note_Iterator_Impl;
template <class ELFT> struct Elf_CGProfile_Impl;
template <endianness E, bool Is64> struct ELFType {
private:
template <typename Ty>
using packed = support::detail::packed_endian_specific_integral<Ty, E, 1>;
public:
static const endianness TargetEndianness = E;
static const bool Is64Bits = Is64;
using uint = std::conditional_t<Is64, uint64_t, uint32_t>;
using Ehdr = Elf_Ehdr_Impl<ELFType<E, Is64>>;
using Shdr = Elf_Shdr_Impl<ELFType<E, Is64>>;
using Sym = Elf_Sym_Impl<ELFType<E, Is64>>;
using Dyn = Elf_Dyn_Impl<ELFType<E, Is64>>;
using Phdr = Elf_Phdr_Impl<ELFType<E, Is64>>;
using Rel = Elf_Rel_Impl<ELFType<E, Is64>, false>;
using Rela = Elf_Rel_Impl<ELFType<E, Is64>, true>;
using Relr = packed<uint>;
using Verdef = Elf_Verdef_Impl<ELFType<E, Is64>>;
using Verdaux = Elf_Verdaux_Impl<ELFType<E, Is64>>;
using Verneed = Elf_Verneed_Impl<ELFType<E, Is64>>;
using Vernaux = Elf_Vernaux_Impl<ELFType<E, Is64>>;
using Versym = Elf_Versym_Impl<ELFType<E, Is64>>;
using Hash = Elf_Hash_Impl<ELFType<E, Is64>>;
using GnuHash = Elf_GnuHash_Impl<ELFType<E, Is64>>;
using Chdr = Elf_Chdr_Impl<ELFType<E, Is64>>;
using Nhdr = Elf_Nhdr_Impl<ELFType<E, Is64>>;
using Note = Elf_Note_Impl<ELFType<E, Is64>>;
using NoteIterator = Elf_Note_Iterator_Impl<ELFType<E, Is64>>;
using CGProfile = Elf_CGProfile_Impl<ELFType<E, Is64>>;
using DynRange = ArrayRef<Dyn>;
using ShdrRange = ArrayRef<Shdr>;
using SymRange = ArrayRef<Sym>;
using RelRange = ArrayRef<Rel>;
using RelaRange = ArrayRef<Rela>;
using RelrRange = ArrayRef<Relr>;
using PhdrRange = ArrayRef<Phdr>;
using Half = packed<uint16_t>;
using Word = packed<uint32_t>;
using Sword = packed<int32_t>;
using Xword = packed<uint64_t>;
using Sxword = packed<int64_t>;
using Addr = packed<uint>;
using Off = packed<uint>;
};
using ELF32LE = ELFType<support::little, false>;
using ELF32BE = ELFType<support::big, false>;
using ELF64LE = ELFType<support::little, true>;
using ELF64BE = ELFType<support::big, true>;
// Use an alignment of 2 for the typedefs since that is the worst case for
// ELF files in archives.
// I really don't like doing this, but the alternative is copypasta.
#define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \
using Elf_Addr = typename ELFT::Addr; \
using Elf_Off = typename ELFT::Off; \
using Elf_Half = typename ELFT::Half; \
using Elf_Word = typename ELFT::Word; \
using Elf_Sword = typename ELFT::Sword; \
using Elf_Xword = typename ELFT::Xword; \
using Elf_Sxword = typename ELFT::Sxword; \
using uintX_t = typename ELFT::uint; \
using Elf_Ehdr = typename ELFT::Ehdr; \
using Elf_Shdr = typename ELFT::Shdr; \
using Elf_Sym = typename ELFT::Sym; \
using Elf_Dyn = typename ELFT::Dyn; \
using Elf_Phdr = typename ELFT::Phdr; \
using Elf_Rel = typename ELFT::Rel; \
using Elf_Rela = typename ELFT::Rela; \
using Elf_Relr = typename ELFT::Relr; \
using Elf_Verdef = typename ELFT::Verdef; \
using Elf_Verdaux = typename ELFT::Verdaux; \
using Elf_Verneed = typename ELFT::Verneed; \
using Elf_Vernaux = typename ELFT::Vernaux; \
using Elf_Versym = typename ELFT::Versym; \
using Elf_Hash = typename ELFT::Hash; \
using Elf_GnuHash = typename ELFT::GnuHash; \
using Elf_Chdr = typename ELFT::Chdr; \
using Elf_Nhdr = typename ELFT::Nhdr; \
using Elf_Note = typename ELFT::Note; \
using Elf_Note_Iterator = typename ELFT::NoteIterator; \
using Elf_CGProfile = typename ELFT::CGProfile; \
using Elf_Dyn_Range = typename ELFT::DynRange; \
using Elf_Shdr_Range = typename ELFT::ShdrRange; \
using Elf_Sym_Range = typename ELFT::SymRange; \
using Elf_Rel_Range = typename ELFT::RelRange; \
using Elf_Rela_Range = typename ELFT::RelaRange; \
using Elf_Relr_Range = typename ELFT::RelrRange; \
using Elf_Phdr_Range = typename ELFT::PhdrRange;
#define LLVM_ELF_COMMA ,
#define LLVM_ELF_IMPORT_TYPES(E, W) \
LLVM_ELF_IMPORT_TYPES_ELFT(ELFType<E LLVM_ELF_COMMA W>)
// Section header.
template <class ELFT> struct Elf_Shdr_Base;
template <endianness TargetEndianness>
struct Elf_Shdr_Base<ELFType<TargetEndianness, false>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
Elf_Word sh_name; // Section name (index into string table)
Elf_Word sh_type; // Section type (SHT_*)
Elf_Word sh_flags; // Section flags (SHF_*)
Elf_Addr sh_addr; // Address where section is to be loaded
Elf_Off sh_offset; // File offset of section data, in bytes
Elf_Word sh_size; // Size of section, in bytes
Elf_Word sh_link; // Section type-specific header table index link
Elf_Word sh_info; // Section type-specific extra information
Elf_Word sh_addralign; // Section address alignment
Elf_Word sh_entsize; // Size of records contained within the section
};
template <endianness TargetEndianness>
struct Elf_Shdr_Base<ELFType<TargetEndianness, true>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
Elf_Word sh_name; // Section name (index into string table)
Elf_Word sh_type; // Section type (SHT_*)
Elf_Xword sh_flags; // Section flags (SHF_*)
Elf_Addr sh_addr; // Address where section is to be loaded
Elf_Off sh_offset; // File offset of section data, in bytes
Elf_Xword sh_size; // Size of section, in bytes
Elf_Word sh_link; // Section type-specific header table index link
Elf_Word sh_info; // Section type-specific extra information
Elf_Xword sh_addralign; // Section address alignment
Elf_Xword sh_entsize; // Size of records contained within the section
};
template <class ELFT>
struct Elf_Shdr_Impl : Elf_Shdr_Base<ELFT> {
using Elf_Shdr_Base<ELFT>::sh_entsize;
using Elf_Shdr_Base<ELFT>::sh_size;
/// Get the number of entities this section contains if it has any.
unsigned getEntityCount() const {
if (sh_entsize == 0)
return 0;
return sh_size / sh_entsize;
}
};
template <class ELFT> struct Elf_Sym_Base;
template <endianness TargetEndianness>
struct Elf_Sym_Base<ELFType<TargetEndianness, false>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
Elf_Word st_name; // Symbol name (index into string table)
Elf_Addr st_value; // Value or address associated with the symbol
Elf_Word st_size; // Size of the symbol
unsigned char st_info; // Symbol's type and binding attributes
unsigned char st_other; // Must be zero; reserved
Elf_Half st_shndx; // Which section (header table index) it's defined in
};
template <endianness TargetEndianness>
struct Elf_Sym_Base<ELFType<TargetEndianness, true>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
Elf_Word st_name; // Symbol name (index into string table)
unsigned char st_info; // Symbol's type and binding attributes
unsigned char st_other; // Must be zero; reserved
Elf_Half st_shndx; // Which section (header table index) it's defined in
Elf_Addr st_value; // Value or address associated with the symbol
Elf_Xword st_size; // Size of the symbol
};
template <class ELFT>
struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> {
using Elf_Sym_Base<ELFT>::st_info;
using Elf_Sym_Base<ELFT>::st_shndx;
using Elf_Sym_Base<ELFT>::st_other;
using Elf_Sym_Base<ELFT>::st_value;
// These accessors and mutators correspond to the ELF32_ST_BIND,
// ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification:
unsigned char getBinding() const { return st_info >> 4; }
unsigned char getType() const { return st_info & 0x0f; }
uint64_t getValue() const { return st_value; }
void setBinding(unsigned char b) { setBindingAndType(b, getType()); }
void setType(unsigned char t) { setBindingAndType(getBinding(), t); }
void setBindingAndType(unsigned char b, unsigned char t) {
st_info = (b << 4) + (t & 0x0f);
}
/// Access to the STV_xxx flag stored in the first two bits of st_other.
/// STV_DEFAULT: 0
/// STV_INTERNAL: 1
/// STV_HIDDEN: 2
/// STV_PROTECTED: 3
unsigned char getVisibility() const { return st_other & 0x3; }
void setVisibility(unsigned char v) {
assert(v < 4 && "Invalid value for visibility");
st_other = (st_other & ~0x3) | v;
}
bool isAbsolute() const { return st_shndx == ELF::SHN_ABS; }
bool isCommon() const {
return getType() == ELF::STT_COMMON || st_shndx == ELF::SHN_COMMON;
}
bool isDefined() const { return !isUndefined(); }
bool isProcessorSpecific() const {
return st_shndx >= ELF::SHN_LOPROC && st_shndx <= ELF::SHN_HIPROC;
}
bool isOSSpecific() const {
return st_shndx >= ELF::SHN_LOOS && st_shndx <= ELF::SHN_HIOS;
}
bool isReserved() const {
// ELF::SHN_HIRESERVE is 0xffff so st_shndx <= ELF::SHN_HIRESERVE is always
// true and some compilers warn about it.
return st_shndx >= ELF::SHN_LORESERVE;
}
bool isUndefined() const { return st_shndx == ELF::SHN_UNDEF; }
bool isExternal() const {
return getBinding() != ELF::STB_LOCAL;
}
Expected<StringRef> getName(StringRef StrTab) const;
};
template <class ELFT>
Expected<StringRef> Elf_Sym_Impl<ELFT>::getName(StringRef StrTab) const {
uint32_t Offset = this->st_name;
if (Offset >= StrTab.size())
return createStringError(object_error::parse_failed,
"st_name (0x%" PRIx32
") is past the end of the string table"
" of size 0x%zx",
Offset, StrTab.size());
return StringRef(StrTab.data() + Offset);
}
/// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section
/// (.gnu.version). This structure is identical for ELF32 and ELF64.
template <class ELFT>
struct Elf_Versym_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
Elf_Half vs_index; // Version index with flags (e.g. VERSYM_HIDDEN)
};
/// Elf_Verdef: This is the structure of entries in the SHT_GNU_verdef section
/// (.gnu.version_d). This structure is identical for ELF32 and ELF64.
template <class ELFT>
struct Elf_Verdef_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
Elf_Half vd_version; // Version of this structure (e.g. VER_DEF_CURRENT)
Elf_Half vd_flags; // Bitwise flags (VER_DEF_*)
Elf_Half vd_ndx; // Version index, used in .gnu.version entries
Elf_Half vd_cnt; // Number of Verdaux entries
Elf_Word vd_hash; // Hash of name
Elf_Word vd_aux; // Offset to the first Verdaux entry (in bytes)
Elf_Word vd_next; // Offset to the next Verdef entry (in bytes)
/// Get the first Verdaux entry for this Verdef.
const Elf_Verdaux *getAux() const {
return reinterpret_cast<const Elf_Verdaux *>((const char *)this + vd_aux);
}
};
/// Elf_Verdaux: This is the structure of auxiliary data in the SHT_GNU_verdef
/// section (.gnu.version_d). This structure is identical for ELF32 and ELF64.
template <class ELFT>
struct Elf_Verdaux_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
Elf_Word vda_name; // Version name (offset in string table)
Elf_Word vda_next; // Offset to next Verdaux entry (in bytes)
};
/// Elf_Verneed: This is the structure of entries in the SHT_GNU_verneed
/// section (.gnu.version_r). This structure is identical for ELF32 and ELF64.
template <class ELFT>
struct Elf_Verneed_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
Elf_Half vn_version; // Version of this structure (e.g. VER_NEED_CURRENT)
Elf_Half vn_cnt; // Number of associated Vernaux entries
Elf_Word vn_file; // Library name (string table offset)
Elf_Word vn_aux; // Offset to first Vernaux entry (in bytes)
Elf_Word vn_next; // Offset to next Verneed entry (in bytes)
};
/// Elf_Vernaux: This is the structure of auxiliary data in SHT_GNU_verneed
/// section (.gnu.version_r). This structure is identical for ELF32 and ELF64.
template <class ELFT>
struct Elf_Vernaux_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
Elf_Word vna_hash; // Hash of dependency name
Elf_Half vna_flags; // Bitwise Flags (VER_FLAG_*)
Elf_Half vna_other; // Version index, used in .gnu.version entries
Elf_Word vna_name; // Dependency name
Elf_Word vna_next; // Offset to next Vernaux entry (in bytes)
};
/// Elf_Dyn_Base: This structure matches the form of entries in the dynamic
/// table section (.dynamic) look like.
template <class ELFT> struct Elf_Dyn_Base;
template <endianness TargetEndianness>
struct Elf_Dyn_Base<ELFType<TargetEndianness, false>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
Elf_Sword d_tag;
union {
Elf_Word d_val;
Elf_Addr d_ptr;
} d_un;
};
template <endianness TargetEndianness>
struct Elf_Dyn_Base<ELFType<TargetEndianness, true>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
Elf_Sxword d_tag;
union {
Elf_Xword d_val;
Elf_Addr d_ptr;
} d_un;
};
/// Elf_Dyn_Impl: This inherits from Elf_Dyn_Base, adding getters.
template <class ELFT>
struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> {
using Elf_Dyn_Base<ELFT>::d_tag;
using Elf_Dyn_Base<ELFT>::d_un;
using intX_t = std::conditional_t<ELFT::Is64Bits, int64_t, int32_t>;
using uintX_t = std::conditional_t<ELFT::Is64Bits, uint64_t, uint32_t>;
intX_t getTag() const { return d_tag; }
uintX_t getVal() const { return d_un.d_val; }
uintX_t getPtr() const { return d_un.d_ptr; }
};
template <endianness TargetEndianness>
struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, false> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
static const bool IsRela = false;
Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
Elf_Word r_info; // Symbol table index and type of relocation to apply
uint32_t getRInfo(bool isMips64EL) const {
assert(!isMips64EL);
return r_info;
}
void setRInfo(uint32_t R, bool IsMips64EL) {
assert(!IsMips64EL);
r_info = R;
}
// These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE,
// and ELF32_R_INFO macros defined in the ELF specification:
uint32_t getSymbol(bool isMips64EL) const {
return this->getRInfo(isMips64EL) >> 8;
}
unsigned char getType(bool isMips64EL) const {
return (unsigned char)(this->getRInfo(isMips64EL) & 0x0ff);
}
void setSymbol(uint32_t s, bool IsMips64EL) {
setSymbolAndType(s, getType(IsMips64EL), IsMips64EL);
}
void setType(unsigned char t, bool IsMips64EL) {
setSymbolAndType(getSymbol(IsMips64EL), t, IsMips64EL);
}
void setSymbolAndType(uint32_t s, unsigned char t, bool IsMips64EL) {
this->setRInfo((s << 8) + t, IsMips64EL);
}
};
template <endianness TargetEndianness>
struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, true>
: public Elf_Rel_Impl<ELFType<TargetEndianness, false>, false> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
static const bool IsRela = true;
Elf_Sword r_addend; // Compute value for relocatable field by adding this
};
template <endianness TargetEndianness>
struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, false> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
static const bool IsRela = false;
Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
Elf_Xword r_info; // Symbol table index and type of relocation to apply
uint64_t getRInfo(bool isMips64EL) const {
uint64_t t = r_info;
if (!isMips64EL)
return t;
// Mips64 little endian has a "special" encoding of r_info. Instead of one
// 64 bit little endian number, it is a little endian 32 bit number followed
// by a 32 bit big endian number.
return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) |
((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff);
}
void setRInfo(uint64_t R, bool IsMips64EL) {
if (IsMips64EL)
r_info = (R >> 32) | ((R & 0xff000000) << 8) | ((R & 0x00ff0000) << 24) |
((R & 0x0000ff00) << 40) | ((R & 0x000000ff) << 56);
else
r_info = R;
}
// These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE,
// and ELF64_R_INFO macros defined in the ELF specification:
uint32_t getSymbol(bool isMips64EL) const {
return (uint32_t)(this->getRInfo(isMips64EL) >> 32);
}
uint32_t getType(bool isMips64EL) const {
return (uint32_t)(this->getRInfo(isMips64EL) & 0xffffffffL);
}
void setSymbol(uint32_t s, bool IsMips64EL) {
setSymbolAndType(s, getType(IsMips64EL), IsMips64EL);
}
void setType(uint32_t t, bool IsMips64EL) {
setSymbolAndType(getSymbol(IsMips64EL), t, IsMips64EL);
}
void setSymbolAndType(uint32_t s, uint32_t t, bool IsMips64EL) {
this->setRInfo(((uint64_t)s << 32) + (t & 0xffffffffL), IsMips64EL);
}
};
template <endianness TargetEndianness>
struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, true>
: public Elf_Rel_Impl<ELFType<TargetEndianness, true>, false> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
static const bool IsRela = true;
Elf_Sxword r_addend; // Compute value for relocatable field by adding this.
};
template <class ELFT>
struct Elf_Ehdr_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes
Elf_Half e_type; // Type of file (see ET_*)
Elf_Half e_machine; // Required architecture for this file (see EM_*)
Elf_Word e_version; // Must be equal to 1
Elf_Addr e_entry; // Address to jump to in order to start program
Elf_Off e_phoff; // Program header table's file offset, in bytes
Elf_Off e_shoff; // Section header table's file offset, in bytes
Elf_Word e_flags; // Processor-specific flags
Elf_Half e_ehsize; // Size of ELF header, in bytes
Elf_Half e_phentsize; // Size of an entry in the program header table
Elf_Half e_phnum; // Number of entries in the program header table
Elf_Half e_shentsize; // Size of an entry in the section header table
Elf_Half e_shnum; // Number of entries in the section header table
Elf_Half e_shstrndx; // Section header table index of section name
// string table
bool checkMagic() const {
return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0;
}
unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; }
unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; }
};
template <endianness TargetEndianness>
struct Elf_Phdr_Impl<ELFType<TargetEndianness, false>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
Elf_Word p_type; // Type of segment
Elf_Off p_offset; // FileOffset where segment is located, in bytes
Elf_Addr p_vaddr; // Virtual Address of beginning of segment
Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific)
Elf_Word p_filesz; // Num. of bytes in file image of segment (may be zero)
Elf_Word p_memsz; // Num. of bytes in mem image of segment (may be zero)
Elf_Word p_flags; // Segment flags
Elf_Word p_align; // Segment alignment constraint
};
template <endianness TargetEndianness>
struct Elf_Phdr_Impl<ELFType<TargetEndianness, true>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
Elf_Word p_type; // Type of segment
Elf_Word p_flags; // Segment flags
Elf_Off p_offset; // FileOffset where segment is located, in bytes
Elf_Addr p_vaddr; // Virtual Address of beginning of segment
Elf_Addr p_paddr; // Physical address of beginning of segment (OS-specific)
Elf_Xword p_filesz; // Num. of bytes in file image of segment (may be zero)
Elf_Xword p_memsz; // Num. of bytes in mem image of segment (may be zero)
Elf_Xword p_align; // Segment alignment constraint
};
// ELFT needed for endianness.
template <class ELFT>
struct Elf_Hash_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
Elf_Word nbucket;
Elf_Word nchain;
ArrayRef<Elf_Word> buckets() const {
return ArrayRef<Elf_Word>(&nbucket + 2, &nbucket + 2 + nbucket);
}
ArrayRef<Elf_Word> chains() const {
return ArrayRef<Elf_Word>(&nbucket + 2 + nbucket,
&nbucket + 2 + nbucket + nchain);
}
};
// .gnu.hash section
template <class ELFT>
struct Elf_GnuHash_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
Elf_Word nbuckets;
Elf_Word symndx;
Elf_Word maskwords;
Elf_Word shift2;
ArrayRef<Elf_Off> filter() const {
return ArrayRef<Elf_Off>(reinterpret_cast<const Elf_Off *>(&shift2 + 1),
maskwords);
}
ArrayRef<Elf_Word> buckets() const {
return ArrayRef<Elf_Word>(
reinterpret_cast<const Elf_Word *>(filter().end()), nbuckets);
}
ArrayRef<Elf_Word> values(unsigned DynamicSymCount) const {
assert(DynamicSymCount >= symndx);
return ArrayRef<Elf_Word>(buckets().end(), DynamicSymCount - symndx);
}
};
// Compressed section headers.
// http://www.sco.com/developers/gabi/latest/ch4.sheader.html#compression_header
template <endianness TargetEndianness>
struct Elf_Chdr_Impl<ELFType<TargetEndianness, false>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
Elf_Word ch_type;
Elf_Word ch_size;
Elf_Word ch_addralign;
};
template <endianness TargetEndianness>
struct Elf_Chdr_Impl<ELFType<TargetEndianness, true>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
Elf_Word ch_type;
Elf_Word ch_reserved;
Elf_Xword ch_size;
Elf_Xword ch_addralign;
};
/// Note header
template <class ELFT>
struct Elf_Nhdr_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
Elf_Word n_namesz;
Elf_Word n_descsz;
Elf_Word n_type;
/// Get the size of the note, including name, descriptor, and padding. Both
/// the start and the end of the descriptor are aligned by the section
/// alignment. In practice many 64-bit systems deviate from the generic ABI by
/// using sh_addralign=4.
size_t getSize(size_t Align) const {
return alignToPowerOf2(sizeof(*this) + n_namesz, Align) +
alignToPowerOf2(n_descsz, Align);
}
};
/// An ELF note.
///
/// Wraps a note header, providing methods for accessing the name and
/// descriptor safely.
template <class ELFT>
class Elf_Note_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
const Elf_Nhdr_Impl<ELFT> &Nhdr;
template <class NoteIteratorELFT> friend class Elf_Note_Iterator_Impl;
public:
Elf_Note_Impl(const Elf_Nhdr_Impl<ELFT> &Nhdr) : Nhdr(Nhdr) {}
/// Get the note's name, excluding the terminating null byte.
StringRef getName() const {
if (!Nhdr.n_namesz)
return StringRef();
return StringRef(reinterpret_cast<const char *>(&Nhdr) + sizeof(Nhdr),
Nhdr.n_namesz - 1);
}
/// Get the note's descriptor.
ArrayRef<uint8_t> getDesc(size_t Align) const {
if (!Nhdr.n_descsz)
return ArrayRef<uint8_t>();
return ArrayRef<uint8_t>(
reinterpret_cast<const uint8_t *>(&Nhdr) +
alignToPowerOf2(sizeof(Nhdr) + Nhdr.n_namesz, Align),
Nhdr.n_descsz);
}
/// Get the note's descriptor as StringRef
StringRef getDescAsStringRef(size_t Align) const {
ArrayRef<uint8_t> Desc = getDesc(Align);
return StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size());
}
/// Get the note's type.
Elf_Word getType() const { return Nhdr.n_type; }
};
template <class ELFT> class Elf_Note_Iterator_Impl {
public:
using iterator_category = std::forward_iterator_tag;
using value_type = Elf_Note_Impl<ELFT>;
using difference_type = std::ptrdiff_t;
using pointer = value_type *;
using reference = value_type &;
private:
// Nhdr being a nullptr marks the end of iteration.
const Elf_Nhdr_Impl<ELFT> *Nhdr = nullptr;
size_t RemainingSize = 0u;
size_t Align = 0;
Error *Err = nullptr;
template <class ELFFileELFT> friend class ELFFile;
// Stop iteration and indicate an overflow.
void stopWithOverflowError() {
Nhdr = nullptr;
*Err = make_error<StringError>("ELF note overflows container",
object_error::parse_failed);
}
// Advance Nhdr by NoteSize bytes, starting from NhdrPos.
//
// Assumes NoteSize <= RemainingSize. Ensures Nhdr->getSize() <= RemainingSize
// upon returning. Handles stopping iteration when reaching the end of the
// container, either cleanly or with an overflow error.
void advanceNhdr(const uint8_t *NhdrPos, size_t NoteSize) {
RemainingSize -= NoteSize;
if (RemainingSize == 0u) {
// Ensure that if the iterator walks to the end, the error is checked
// afterwards.
*Err = Error::success();
Nhdr = nullptr;
} else if (sizeof(*Nhdr) > RemainingSize)
stopWithOverflowError();
else {
Nhdr = reinterpret_cast<const Elf_Nhdr_Impl<ELFT> *>(NhdrPos + NoteSize);
if (Nhdr->getSize(Align) > RemainingSize)
stopWithOverflowError();
else
*Err = Error::success();
}
}
Elf_Note_Iterator_Impl() = default;
explicit Elf_Note_Iterator_Impl(Error &Err) : Err(&Err) {}
Elf_Note_Iterator_Impl(const uint8_t *Start, size_t Size, size_t Align,
Error &Err)
: RemainingSize(Size), Align(Align), Err(&Err) {
consumeError(std::move(Err));
assert(Start && "ELF note iterator starting at NULL");
advanceNhdr(Start, 0u);
}
public:
Elf_Note_Iterator_Impl &operator++() {
assert(Nhdr && "incremented ELF note end iterator");
const uint8_t *NhdrPos = reinterpret_cast<const uint8_t *>(Nhdr);
size_t NoteSize = Nhdr->getSize(Align);
advanceNhdr(NhdrPos, NoteSize);
return *this;
}
bool operator==(Elf_Note_Iterator_Impl Other) const {
if (!Nhdr && Other.Err)
(void)(bool)(*Other.Err);
if (!Other.Nhdr && Err)
(void)(bool)(*Err);
return Nhdr == Other.Nhdr;
}
bool operator!=(Elf_Note_Iterator_Impl Other) const {
return !(*this == Other);
}
Elf_Note_Impl<ELFT> operator*() const {
assert(Nhdr && "dereferenced ELF note end iterator");
return Elf_Note_Impl<ELFT>(*Nhdr);
}
};
template <class ELFT> struct Elf_CGProfile_Impl {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
Elf_Xword cgp_weight;
};
// MIPS .reginfo section
template <class ELFT>
struct Elf_Mips_RegInfo;
template <support::endianness TargetEndianness>
struct Elf_Mips_RegInfo<ELFType<TargetEndianness, false>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, false)
Elf_Word ri_gprmask; // bit-mask of used general registers
Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers
Elf_Addr ri_gp_value; // gp register value
};
template <support::endianness TargetEndianness>
struct Elf_Mips_RegInfo<ELFType<TargetEndianness, true>> {
LLVM_ELF_IMPORT_TYPES(TargetEndianness, true)
Elf_Word ri_gprmask; // bit-mask of used general registers
Elf_Word ri_pad; // unused padding field
Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers
Elf_Addr ri_gp_value; // gp register value
};
// .MIPS.options section
template <class ELFT> struct Elf_Mips_Options {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
uint8_t kind; // Determines interpretation of variable part of descriptor
uint8_t size; // Byte size of descriptor, including this header
Elf_Half section; // Section header index of section affected,
// or 0 for global options
Elf_Word info; // Kind-specific information
Elf_Mips_RegInfo<ELFT> &getRegInfo() {
assert(kind == ELF::ODK_REGINFO);
return *reinterpret_cast<Elf_Mips_RegInfo<ELFT> *>(
(uint8_t *)this + sizeof(Elf_Mips_Options));
}
const Elf_Mips_RegInfo<ELFT> &getRegInfo() const {
return const_cast<Elf_Mips_Options *>(this)->getRegInfo();
}
};
// .MIPS.abiflags section content
template <class ELFT> struct Elf_Mips_ABIFlags {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
Elf_Half version; // Version of the structure
uint8_t isa_level; // ISA level: 1-5, 32, and 64
uint8_t isa_rev; // ISA revision (0 for MIPS I - MIPS V)
uint8_t gpr_size; // General purpose registers size
uint8_t cpr1_size; // Co-processor 1 registers size
uint8_t cpr2_size; // Co-processor 2 registers size
uint8_t fp_abi; // Floating-point ABI flag
Elf_Word isa_ext; // Processor-specific extension
Elf_Word ases; // ASEs flags
Elf_Word flags1; // General flags
Elf_Word flags2; // General flags
};
// Struct representing the BBAddrMap for one function.
struct BBAddrMap {
uint64_t Addr; // Function address
// Struct representing the BBAddrMap information for one basic block.
struct BBEntry {
struct Metadata {
bool HasReturn : 1; // If this block ends with a return (or tail
// call).
bool HasTailCall : 1; // If this block ends with a tail call.
bool IsEHPad : 1; // If this is an exception handling block.
bool CanFallThrough : 1; // If this block can fall through to its next.
bool HasIndirectBranch : 1; // If this block ends with an indirect branch
// (branch via a register).
bool operator==(const Metadata &Other) const {
return HasReturn == Other.HasReturn &&
HasTailCall == Other.HasTailCall && IsEHPad == Other.IsEHPad &&
CanFallThrough == Other.CanFallThrough &&
HasIndirectBranch == Other.HasIndirectBranch;
}
// Encodes this struct as a uint32_t value.
uint32_t encode() const {
return static_cast<uint32_t>(HasReturn) |
(static_cast<uint32_t>(HasTailCall) << 1) |
(static_cast<uint32_t>(IsEHPad) << 2) |
(static_cast<uint32_t>(CanFallThrough) << 3) |
(static_cast<uint32_t>(HasIndirectBranch) << 4);
}
// Decodes and returns a Metadata struct from a uint32_t value.
static Expected<Metadata> decode(uint32_t V) {
Metadata MD{/*HasReturn=*/static_cast<bool>(V & 1),
/*HasTailCall=*/static_cast<bool>(V & (1 << 1)),
/*IsEHPad=*/static_cast<bool>(V & (1 << 2)),
/*CanFallThrough=*/static_cast<bool>(V & (1 << 3)),
/*HasIndirectBranch=*/static_cast<bool>(V & (1 << 4))};
if (MD.encode() != V)
return createStringError(
std::error_code(), "invalid encoding for BBEntry::Metadata: 0x%x",
V);
return MD;
}
};
uint32_t ID; // Unique ID of this basic block.
uint32_t Offset; // Offset of basic block relative to function start.
uint32_t Size; // Size of the basic block.
Metadata MD; // Metdata for this basic block.
BBEntry(uint32_t ID, uint32_t Offset, uint32_t Size, Metadata MD)
: ID(ID), Offset(Offset), Size(Size), MD(MD){};
bool operator==(const BBEntry &Other) const {
return ID == Other.ID && Offset == Other.Offset && Size == Other.Size &&
MD == Other.MD;
}
bool hasReturn() const { return MD.HasReturn; }
bool hasTailCall() const { return MD.HasTailCall; }
bool isEHPad() const { return MD.IsEHPad; }
bool canFallThrough() const { return MD.CanFallThrough; }
};
std::vector<BBEntry> BBEntries; // Basic block entries for this function.
// Equality operator for unit testing.
bool operator==(const BBAddrMap &Other) const {
return Addr == Other.Addr && std::equal(BBEntries.begin(), BBEntries.end(),
Other.BBEntries.begin());
}
};
} // end namespace object.
} // end namespace llvm.
#endif // LLVM_OBJECT_ELFTYPES_H
PK hwFZVlJ,3 3 Object/Archive.hnu �[��� //===- Archive.h - ar archive file format -----------------------*- 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
//
//===----------------------------------------------------------------------===//
//
// This file declares the ar archive file format class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_ARCHIVE_H
#define LLVM_OBJECT_ARCHIVE_H
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/fallible_iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Object/Binary.h"
#include "llvm/Support/Chrono.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cassert>
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
namespace llvm {
namespace object {
const char ArchiveMagic[] = "!<arch>\n";
const char ThinArchiveMagic[] = "!<thin>\n";
const char BigArchiveMagic[] = "<bigaf>\n";
class Archive;
class AbstractArchiveMemberHeader {
protected:
AbstractArchiveMemberHeader(const Archive *Parent) : Parent(Parent){};
public:
friend class Archive;
virtual std::unique_ptr<AbstractArchiveMemberHeader> clone() const = 0;
virtual ~AbstractArchiveMemberHeader() = default;
/// Get the name without looking up long names.
virtual Expected<StringRef> getRawName() const = 0;
virtual StringRef getRawAccessMode() const = 0;
virtual StringRef getRawLastModified() const = 0;
virtual StringRef getRawUID() const = 0;
virtual StringRef getRawGID() const = 0;
/// Get the name looking up long names.
virtual Expected<StringRef> getName(uint64_t Size) const = 0;
virtual Expected<uint64_t> getSize() const = 0;
virtual uint64_t getOffset() const = 0;
/// Get next file member location.
virtual Expected<const char *> getNextChildLoc() const = 0;
virtual Expected<bool> isThin() const = 0;
Expected<sys::fs::perms> getAccessMode() const;
Expected<sys::TimePoint<std::chrono::seconds>> getLastModified() const;
Expected<unsigned> getUID() const;
Expected<unsigned> getGID() const;
/// Returns the size in bytes of the format-defined member header of the
/// concrete archive type.
virtual uint64_t getSizeOf() const = 0;
const Archive *Parent;
};
template <typename T>
class CommonArchiveMemberHeader : public AbstractArchiveMemberHeader {
public:
CommonArchiveMemberHeader(const Archive *Parent, const T *RawHeaderPtr)
: AbstractArchiveMemberHeader(Parent), ArMemHdr(RawHeaderPtr){};
StringRef getRawAccessMode() const override;
StringRef getRawLastModified() const override;
StringRef getRawUID() const override;
StringRef getRawGID() const override;
uint64_t getOffset() const override;
uint64_t getSizeOf() const override { return sizeof(T); }
T const *ArMemHdr;
};
struct UnixArMemHdrType {
char Name[16];
char LastModified[12];
char UID[6];
char GID[6];
char AccessMode[8];
char Size[10]; ///< Size of data, not including header or padding.
char Terminator[2];
};
class ArchiveMemberHeader : public CommonArchiveMemberHeader<UnixArMemHdrType> {
public:
ArchiveMemberHeader(const Archive *Parent, const char *RawHeaderPtr,
uint64_t Size, Error *Err);
std::unique_ptr<AbstractArchiveMemberHeader> clone() const override {
return std::make_unique<ArchiveMemberHeader>(*this);
}
Expected<StringRef> getRawName() const override;
Expected<StringRef> getName(uint64_t Size) const override;
Expected<uint64_t> getSize() const override;
Expected<const char *> getNextChildLoc() const override;
Expected<bool> isThin() const override;
};
// File Member Header
struct BigArMemHdrType {
char Size[20]; // File member size in decimal
char NextOffset[20]; // Next member offset in decimal
char PrevOffset[20]; // Previous member offset in decimal
char LastModified[12];
char UID[12];
char GID[12];
char AccessMode[12];
char NameLen[4]; // File member name length in decimal
union {
char Name[2]; // Start of member name
char Terminator[2];
};
};
// Define file member header of AIX big archive.
class BigArchiveMemberHeader
: public CommonArchiveMemberHeader<BigArMemHdrType> {
public:
BigArchiveMemberHeader(Archive const *Parent, const char *RawHeaderPtr,
uint64_t Size, Error *Err);
std::unique_ptr<AbstractArchiveMemberHeader> clone() const override {
return std::make_unique<BigArchiveMemberHeader>(*this);
}
Expected<StringRef> getRawName() const override;
Expected<uint64_t> getRawNameSize() const;
Expected<StringRef> getName(uint64_t Size) const override;
Expected<uint64_t> getSize() const override;
Expected<const char *> getNextChildLoc() const override;
Expected<uint64_t> getNextOffset() const;
Expected<bool> isThin() const override { return false; }
};
class Archive : public Binary {
virtual void anchor();
public:
class Child {
friend Archive;
friend AbstractArchiveMemberHeader;
const Archive *Parent;
std::unique_ptr<AbstractArchiveMemberHeader> Header;
/// Includes header but not padding byte.
StringRef Data;
/// Offset from Data to the start of the file.
uint16_t StartOfFile;
Expected<bool> isThinMember() const;
public:
Child(const Archive *Parent, const char *Start, Error *Err);
Child(const Archive *Parent, StringRef Data, uint16_t StartOfFile);
Child(const Child &C)
: Parent(C.Parent), Data(C.Data), StartOfFile(C.StartOfFile) {
if (C.Header)
Header = C.Header->clone();
}
Child(Child &&C) {
Parent = std::move(C.Parent);
Header = std::move(C.Header);
Data = C.Data;
StartOfFile = C.StartOfFile;
}
Child &operator=(Child &&C) noexcept {
if (&C == this)
return *this;
Parent = std::move(C.Parent);
Header = std::move(C.Header);
Data = C.Data;
StartOfFile = C.StartOfFile;
return *this;
}
Child &operator=(const Child &C) {
if (&C == this)
return *this;
Parent = C.Parent;
if (C.Header)
Header = C.Header->clone();
Data = C.Data;
StartOfFile = C.StartOfFile;
return *this;
}
bool operator==(const Child &other) const {
assert(!Parent || !other.Parent || Parent == other.Parent);
return Data.begin() == other.Data.begin();
}
const Archive *getParent() const { return Parent; }
Expected<Child> getNext() const;
Expected<StringRef> getName() const;
Expected<std::string> getFullName() const;
Expected<StringRef> getRawName() const { return Header->getRawName(); }
Expected<sys::TimePoint<std::chrono::seconds>> getLastModified() const {
return Header->getLastModified();
}
StringRef getRawLastModified() const {
return Header->getRawLastModified();
}
Expected<unsigned> getUID() const { return Header->getUID(); }
Expected<unsigned> getGID() const { return Header->getGID(); }
Expected<sys::fs::perms> getAccessMode() const {
return Header->getAccessMode();
}
/// \return the size of the archive member without the header or padding.
Expected<uint64_t> getSize() const;
/// \return the size in the archive header for this member.
Expected<uint64_t> getRawSize() const;
Expected<StringRef> getBuffer() const;
uint64_t getChildOffset() const;
uint64_t getDataOffset() const { return getChildOffset() + StartOfFile; }
Expected<MemoryBufferRef> getMemoryBufferRef() const;
Expected<std::unique_ptr<Binary>>
getAsBinary(LLVMContext *Context = nullptr) const;
};
class ChildFallibleIterator {
Child C;
public:
ChildFallibleIterator() : C(Child(nullptr, nullptr, nullptr)) {}
ChildFallibleIterator(const Child &C) : C(C) {}
const Child *operator->() const { return &C; }
const Child &operator*() const { return C; }
bool operator==(const ChildFallibleIterator &other) const {
// Ignore errors here: If an error occurred during increment then getNext
// will have been set to child_end(), and the following comparison should
// do the right thing.
return C == other.C;
}
bool operator!=(const ChildFallibleIterator &other) const {
return !(*this == other);
}
Error inc() {
auto NextChild = C.getNext();
if (!NextChild)
return NextChild.takeError();
C = std::move(*NextChild);
return Error::success();
}
};
using child_iterator = fallible_iterator<ChildFallibleIterator>;
class Symbol {
const Archive *Parent;
uint32_t SymbolIndex;
uint32_t StringIndex; // Extra index to the string.
public:
Symbol(const Archive *p, uint32_t symi, uint32_t stri)
: Parent(p), SymbolIndex(symi), StringIndex(stri) {}
bool operator==(const Symbol &other) const {
return (Parent == other.Parent) && (SymbolIndex == other.SymbolIndex);
}
StringRef getName() const;
Expected<Child> getMember() const;
Symbol getNext() const;
bool isECSymbol() const;
};
class symbol_iterator {
Symbol symbol;
public:
symbol_iterator(const Symbol &s) : symbol(s) {}
const Symbol *operator->() const { return &symbol; }
const Symbol &operator*() const { return symbol; }
bool operator==(const symbol_iterator &other) const {
return symbol == other.symbol;
}
bool operator!=(const symbol_iterator &other) const {
return !(*this == other);
}
symbol_iterator &operator++() { // Preincrement
symbol = symbol.getNext();
return *this;
}
};
Archive(MemoryBufferRef Source, Error &Err);
static Expected<std::unique_ptr<Archive>> create(MemoryBufferRef Source);
/// Size field is 10 decimal digits long
static const uint64_t MaxMemberSize = 9999999999;
enum Kind { K_GNU, K_GNU64, K_BSD, K_DARWIN, K_DARWIN64, K_COFF, K_AIXBIG };
Kind kind() const { return (Kind)Format; }
bool isThin() const { return IsThin; }
static object::Archive::Kind getDefaultKindForHost();
child_iterator child_begin(Error &Err, bool SkipInternal = true) const;
child_iterator child_end() const;
iterator_range<child_iterator> children(Error &Err,
bool SkipInternal = true) const {
return make_range(child_begin(Err, SkipInternal), child_end());
}
symbol_iterator symbol_begin() const;
symbol_iterator symbol_end() const;
iterator_range<symbol_iterator> symbols() const {
return make_range(symbol_begin(), symbol_end());
}
Expected<iterator_range<symbol_iterator>> ec_symbols() const;
static bool classof(Binary const *v) { return v->isArchive(); }
// check if a symbol is in the archive
Expected<std::optional<Child>> findSym(StringRef name) const;
virtual bool isEmpty() const;
bool hasSymbolTable() const;
StringRef getSymbolTable() const { return SymbolTable; }
StringRef getStringTable() const { return StringTable; }
uint32_t getNumberOfSymbols() const;
uint32_t getNumberOfECSymbols() const;
virtual uint64_t getFirstChildOffset() const { return getArchiveMagicLen(); }
std::vector<std::unique_ptr<MemoryBuffer>> takeThinBuffers() {
return std::move(ThinBuffers);
}
std::unique_ptr<AbstractArchiveMemberHeader>
createArchiveMemberHeader(const char *RawHeaderPtr, uint64_t Size,
Error *Err) const;
protected:
uint64_t getArchiveMagicLen() const;
void setFirstRegular(const Child &C);
StringRef SymbolTable;
StringRef ECSymbolTable;
StringRef StringTable;
private:
StringRef FirstRegularData;
uint16_t FirstRegularStartOfFile = -1;
unsigned Format : 3;
unsigned IsThin : 1;
mutable std::vector<std::unique_ptr<MemoryBuffer>> ThinBuffers;
};
class BigArchive : public Archive {
public:
/// Fixed-Length Header.
struct FixLenHdr {
char Magic[sizeof(BigArchiveMagic) - 1]; ///< Big archive magic string.
char MemOffset[20]; ///< Offset to member table.
char GlobSymOffset[20]; ///< Offset to global symbol table.
char
GlobSym64Offset[20]; ///< Offset global symbol table for 64-bit objects.
char FirstChildOffset[20]; ///< Offset to first archive member.
char LastChildOffset[20]; ///< Offset to last archive member.
char FreeOffset[20]; ///< Offset to first mem on free list.
};
const FixLenHdr *ArFixLenHdr;
uint64_t FirstChildOffset = 0;
uint64_t LastChildOffset = 0;
std::string MergedGlobalSymtabBuf;
public:
BigArchive(MemoryBufferRef Source, Error &Err);
uint64_t getFirstChildOffset() const override { return FirstChildOffset; }
uint64_t getLastChildOffset() const { return LastChildOffset; }
bool isEmpty() const override { return getFirstChildOffset() == 0; }
};
} // end namespace object
} // end namespace llvm
#endif // LLVM_OBJECT_ARCHIVE_H
PK hwFZ;DŽ��$ �$ Object/WindowsResource.hnu �[��� //===-- WindowsResource.h ---------------------------------------*- 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
//
//===---------------------------------------------------------------------===//
//
// This file declares the .res file class. .res files are intermediate
// products of the typical resource-compilation process on Windows. This
// process is as follows:
//
// .rc file(s) ---(rc.exe)---> .res file(s) ---(cvtres.exe)---> COFF file
//
// .rc files are human-readable scripts that list all resources a program uses.
//
// They are compiled into .res files, which are a list of the resources in
// binary form.
//
// Finally the data stored in the .res is compiled into a COFF file, where it
// is organized in a directory tree structure for optimized access by the
// program during runtime.
//
// Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648007(v=vs.85).aspx
//
//===---------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_WINDOWSRESOURCE_H
#define LLVM_OBJECT_WINDOWSRESOURCE_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/Error.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <map>
namespace llvm {
class raw_ostream;
class ScopedPrinter;
namespace object {
class WindowsResource;
class ResourceSectionRef;
struct coff_resource_dir_table;
const size_t WIN_RES_MAGIC_SIZE = 16;
const size_t WIN_RES_NULL_ENTRY_SIZE = 16;
const uint32_t WIN_RES_HEADER_ALIGNMENT = 4;
const uint32_t WIN_RES_DATA_ALIGNMENT = 4;
const uint16_t WIN_RES_PURE_MOVEABLE = 0x0030;
struct WinResHeaderPrefix {
support::ulittle32_t DataSize;
support::ulittle32_t HeaderSize;
};
// Type and Name may each either be an integer ID or a string. This struct is
// only used in the case where they are both IDs.
struct WinResIDs {
uint16_t TypeFlag;
support::ulittle16_t TypeID;
uint16_t NameFlag;
support::ulittle16_t NameID;
void setType(uint16_t ID) {
TypeFlag = 0xffff;
TypeID = ID;
}
void setName(uint16_t ID) {
NameFlag = 0xffff;
NameID = ID;
}
};
struct WinResHeaderSuffix {
support::ulittle32_t DataVersion;
support::ulittle16_t MemoryFlags;
support::ulittle16_t Language;
support::ulittle32_t Version;
support::ulittle32_t Characteristics;
};
class EmptyResError : public GenericBinaryError {
public:
EmptyResError(Twine Msg, object_error ECOverride)
: GenericBinaryError(Msg, ECOverride) {}
};
class ResourceEntryRef {
public:
Error moveNext(bool &End);
bool checkTypeString() const { return IsStringType; }
ArrayRef<UTF16> getTypeString() const { return Type; }
uint16_t getTypeID() const { return TypeID; }
bool checkNameString() const { return IsStringName; }
ArrayRef<UTF16> getNameString() const { return Name; }
uint16_t getNameID() const { return NameID; }
uint16_t getDataVersion() const { return Suffix->DataVersion; }
uint16_t getLanguage() const { return Suffix->Language; }
uint16_t getMemoryFlags() const { return Suffix->MemoryFlags; }
uint16_t getMajorVersion() const { return Suffix->Version >> 16; }
uint16_t getMinorVersion() const { return Suffix->Version; }
uint32_t getCharacteristics() const { return Suffix->Characteristics; }
ArrayRef<uint8_t> getData() const { return Data; }
private:
friend class WindowsResource;
ResourceEntryRef(BinaryStreamRef Ref, const WindowsResource *Owner);
Error loadNext();
static Expected<ResourceEntryRef> create(BinaryStreamRef Ref,
const WindowsResource *Owner);
BinaryStreamReader Reader;
const WindowsResource *Owner;
bool IsStringType;
ArrayRef<UTF16> Type;
uint16_t TypeID;
bool IsStringName;
ArrayRef<UTF16> Name;
uint16_t NameID;
const WinResHeaderSuffix *Suffix = nullptr;
ArrayRef<uint8_t> Data;
};
class WindowsResource : public Binary {
public:
Expected<ResourceEntryRef> getHeadEntry();
static bool classof(const Binary *V) { return V->isWinRes(); }
static Expected<std::unique_ptr<WindowsResource>>
createWindowsResource(MemoryBufferRef Source);
private:
friend class ResourceEntryRef;
WindowsResource(MemoryBufferRef Source);
BinaryByteStream BBS;
};
class WindowsResourceParser {
public:
class TreeNode;
WindowsResourceParser(bool MinGW = false);
Error parse(WindowsResource *WR, std::vector<std::string> &Duplicates);
Error parse(ResourceSectionRef &RSR, StringRef Filename,
std::vector<std::string> &Duplicates);
void cleanUpManifests(std::vector<std::string> &Duplicates);
void printTree(raw_ostream &OS) const;
const TreeNode &getTree() const { return Root; }
ArrayRef<std::vector<uint8_t>> getData() const { return Data; }
ArrayRef<std::vector<UTF16>> getStringTable() const { return StringTable; }
class TreeNode {
public:
template <typename T>
using Children = std::map<T, std::unique_ptr<TreeNode>>;
void print(ScopedPrinter &Writer, StringRef Name) const;
uint32_t getTreeSize() const;
uint32_t getStringIndex() const { return StringIndex; }
uint32_t getDataIndex() const { return DataIndex; }
uint16_t getMajorVersion() const { return MajorVersion; }
uint16_t getMinorVersion() const { return MinorVersion; }
uint32_t getCharacteristics() const { return Characteristics; }
bool checkIsDataNode() const { return IsDataNode; }
const Children<uint32_t> &getIDChildren() const { return IDChildren; }
const Children<std::string> &getStringChildren() const {
return StringChildren;
}
private:
friend class WindowsResourceParser;
// Index is the StringTable vector index for this node's name.
static std::unique_ptr<TreeNode> createStringNode(uint32_t Index);
static std::unique_ptr<TreeNode> createIDNode();
// DataIndex is the Data vector index that the data node points at.
static std::unique_ptr<TreeNode> createDataNode(uint16_t MajorVersion,
uint16_t MinorVersion,
uint32_t Characteristics,
uint32_t Origin,
uint32_t DataIndex);
explicit TreeNode(uint32_t StringIndex);
TreeNode(uint16_t MajorVersion, uint16_t MinorVersion,
uint32_t Characteristics, uint32_t Origin, uint32_t DataIndex);
bool addEntry(const ResourceEntryRef &Entry, uint32_t Origin,
std::vector<std::vector<uint8_t>> &Data,
std::vector<std::vector<UTF16>> &StringTable,
TreeNode *&Result);
TreeNode &addTypeNode(const ResourceEntryRef &Entry,
std::vector<std::vector<UTF16>> &StringTable);
TreeNode &addNameNode(const ResourceEntryRef &Entry,
std::vector<std::vector<UTF16>> &StringTable);
bool addLanguageNode(const ResourceEntryRef &Entry, uint32_t Origin,
std::vector<std::vector<uint8_t>> &Data,
TreeNode *&Result);
bool addDataChild(uint32_t ID, uint16_t MajorVersion, uint16_t MinorVersion,
uint32_t Characteristics, uint32_t Origin,
uint32_t DataIndex, TreeNode *&Result);
TreeNode &addIDChild(uint32_t ID);
TreeNode &addNameChild(ArrayRef<UTF16> NameRef,
std::vector<std::vector<UTF16>> &StringTable);
void shiftDataIndexDown(uint32_t Index);
bool IsDataNode = false;
uint32_t StringIndex;
uint32_t DataIndex;
Children<uint32_t> IDChildren;
Children<std::string> StringChildren;
uint16_t MajorVersion = 0;
uint16_t MinorVersion = 0;
uint32_t Characteristics = 0;
// The .res file that defined this TreeNode, for diagnostics.
// Index into InputFilenames.
uint32_t Origin;
};
struct StringOrID {
bool IsString;
ArrayRef<UTF16> String;
uint32_t ID = ~0u;
StringOrID(uint32_t ID) : IsString(false), ID(ID) {}
StringOrID(ArrayRef<UTF16> String) : IsString(true), String(String) {}
};
private:
Error addChildren(TreeNode &Node, ResourceSectionRef &RSR,
const coff_resource_dir_table &Table, uint32_t Origin,
std::vector<StringOrID> &Context,
std::vector<std::string> &Duplicates);
bool shouldIgnoreDuplicate(const ResourceEntryRef &Entry) const;
bool shouldIgnoreDuplicate(const std::vector<StringOrID> &Context) const;
TreeNode Root;
std::vector<std::vector<uint8_t>> Data;
std::vector<std::vector<UTF16>> StringTable;
std::vector<std::string> InputFilenames;
bool MinGW;
};
Expected<std::unique_ptr<MemoryBuffer>>
writeWindowsResourceCOFF(llvm::COFF::MachineTypes MachineType,
const WindowsResourceParser &Parser,
uint32_t TimeDateStamp);
void printResourceTypeName(uint16_t TypeID, raw_ostream &OS);
} // namespace object
} // namespace llvm
#endif
PK hwFZ�D�n� � Object/OffloadBinary.hnu �[��� //===--- Offloading.h - Utilities for handling offloading code -*- 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
//
//===----------------------------------------------------------------------===//
//
// This file contains the binary format used for budingling device metadata with
// an associated device image. The data can then be stored inside a host object
// file to create a fat binary and read by the linker. This is intended to be a
// thin wrapper around the image itself. If this format becomes sufficiently
// complex it should be moved to a standard binary format like msgpack or ELF.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_OFFLOADBINARY_H
#define LLVM_OBJECT_OFFLOADBINARY_H
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/Binary.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"
#include <memory>
namespace llvm {
namespace object {
/// The producer of the associated offloading image.
enum OffloadKind : uint16_t {
OFK_None = 0,
OFK_OpenMP,
OFK_Cuda,
OFK_HIP,
OFK_LAST,
};
/// The type of contents the offloading image contains.
enum ImageKind : uint16_t {
IMG_None = 0,
IMG_Object,
IMG_Bitcode,
IMG_Cubin,
IMG_Fatbinary,
IMG_PTX,
IMG_LAST,
};
/// A simple binary serialization of an offloading file. We use this format to
/// embed the offloading image into the host executable so it can be extracted
/// and used by the linker.
///
/// Many of these could be stored in the same section by the time the linker
/// sees it so we mark this information with a header. The version is used to
/// detect ABI stability and the size is used to find other offloading entries
/// that may exist in the same section. All offsets are given as absolute byte
/// offsets from the beginning of the file.
class OffloadBinary : public Binary {
public:
using string_iterator = MapVector<StringRef, StringRef>::const_iterator;
using string_iterator_range = iterator_range<string_iterator>;
/// The current version of the binary used for backwards compatibility.
static const uint32_t Version = 1;
/// The offloading metadata that will be serialized to a memory buffer.
struct OffloadingImage {
ImageKind TheImageKind;
OffloadKind TheOffloadKind;
uint32_t Flags;
MapVector<StringRef, StringRef> StringData;
std::unique_ptr<MemoryBuffer> Image;
};
/// Attempt to parse the offloading binary stored in \p Data.
static Expected<std::unique_ptr<OffloadBinary>> create(MemoryBufferRef);
/// Serialize the contents of \p File to a binary buffer to be read later.
static std::unique_ptr<MemoryBuffer> write(const OffloadingImage &);
static uint64_t getAlignment() { return 8; }
ImageKind getImageKind() const { return TheEntry->TheImageKind; }
OffloadKind getOffloadKind() const { return TheEntry->TheOffloadKind; }
uint32_t getVersion() const { return TheHeader->Version; }
uint32_t getFlags() const { return TheEntry->Flags; }
uint64_t getSize() const { return TheHeader->Size; }
StringRef getTriple() const { return getString("triple"); }
StringRef getArch() const { return getString("arch"); }
StringRef getImage() const {
return StringRef(&Buffer[TheEntry->ImageOffset], TheEntry->ImageSize);
}
// Iterator over all the key and value pairs in the binary.
string_iterator_range strings() const {
return string_iterator_range(StringData.begin(), StringData.end());
}
StringRef getString(StringRef Key) const { return StringData.lookup(Key); }
static bool classof(const Binary *V) { return V->isOffloadFile(); }
struct Header {
uint8_t Magic[4] = {0x10, 0xFF, 0x10, 0xAD}; // 0x10FF10AD magic bytes.
uint32_t Version = OffloadBinary::Version; // Version identifier.
uint64_t Size; // Size in bytes of this entire binary.
uint64_t EntryOffset; // Offset of the metadata entry in bytes.
uint64_t EntrySize; // Size of the metadata entry in bytes.
};
struct Entry {
ImageKind TheImageKind; // The kind of the image stored.
OffloadKind TheOffloadKind; // The producer of this image.
uint32_t Flags; // Additional flags associated with the image.
uint64_t StringOffset; // Offset in bytes to the string map.
uint64_t NumStrings; // Number of entries in the string map.
uint64_t ImageOffset; // Offset in bytes of the actual binary image.
uint64_t ImageSize; // Size in bytes of the binary image.
};
struct StringEntry {
uint64_t KeyOffset;
uint64_t ValueOffset;
};
private:
OffloadBinary(MemoryBufferRef Source, const Header *TheHeader,
const Entry *TheEntry)
: Binary(Binary::ID_Offload, Source), Buffer(Source.getBufferStart()),
TheHeader(TheHeader), TheEntry(TheEntry) {
const StringEntry *StringMapBegin =
reinterpret_cast<const StringEntry *>(&Buffer[TheEntry->StringOffset]);
for (uint64_t I = 0, E = TheEntry->NumStrings; I != E; ++I) {
StringRef Key = &Buffer[StringMapBegin[I].KeyOffset];
StringData[Key] = &Buffer[StringMapBegin[I].ValueOffset];
}
}
OffloadBinary(const OffloadBinary &Other) = delete;
/// Map from keys to offsets in the binary.
MapVector<StringRef, StringRef> StringData;
/// Raw pointer to the MemoryBufferRef for convenience.
const char *Buffer;
/// Location of the header within the binary.
const Header *TheHeader;
/// Location of the metadata entries within the binary.
const Entry *TheEntry;
};
/// A class to contain the binary information for a single OffloadBinary that
/// owns its memory.
class OffloadFile : public OwningBinary<OffloadBinary> {
public:
using TargetID = std::pair<StringRef, StringRef>;
OffloadFile(std::unique_ptr<OffloadBinary> Binary,
std::unique_ptr<MemoryBuffer> Buffer)
: OwningBinary<OffloadBinary>(std::move(Binary), std::move(Buffer)) {}
/// We use the Triple and Architecture pair to group linker inputs together.
/// This conversion function lets us use these inputs in a hash-map.
operator TargetID() const {
return std::make_pair(getBinary()->getTriple(), getBinary()->getArch());
}
};
/// Extracts embedded device offloading code from a memory \p Buffer to a list
/// of \p Binaries.
Error extractOffloadBinaries(MemoryBufferRef Buffer,
SmallVectorImpl<OffloadFile> &Binaries);
/// Convert a string \p Name to an image kind.
ImageKind getImageKind(StringRef Name);
/// Convert an image kind to its string representation.
StringRef getImageKindName(ImageKind Name);
/// Convert a string \p Name to an offload kind.
OffloadKind getOffloadKind(StringRef Name);
/// Convert an offload kind to its string representation.
StringRef getOffloadKindName(OffloadKind Name);
} // namespace object
} // namespace llvm
#endif
PK hwFZ:���% % Object/COFFModuleDefinition.hnu �[��� //===--- COFFModuleDefinition.h ---------------------------------*- 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
//
//===----------------------------------------------------------------------===//
//
// Windows-specific.
// A parser for the module-definition file (.def file).
// Parsed results are directly written to Config global variable.
//
// The format of module-definition files are described in this document:
// https://msdn.microsoft.com/en-us/library/28d6s79h.aspx
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_COFFMODULEDEFINITION_H
#define LLVM_OBJECT_COFFMODULEDEFINITION_H
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/Object/COFFImportFile.h"
namespace llvm {
namespace object {
struct COFFModuleDefinition {
std::vector<COFFShortExport> Exports;
std::string OutputFile;
std::string ImportName;
uint64_t ImageBase = 0;
uint64_t StackReserve = 0;
uint64_t StackCommit = 0;
uint64_t HeapReserve = 0;
uint64_t HeapCommit = 0;
uint32_t MajorImageVersion = 0;
uint32_t MinorImageVersion = 0;
uint32_t MajorOSVersion = 0;
uint32_t MinorOSVersion = 0;
};
Expected<COFFModuleDefinition>
parseCOFFModuleDefinition(MemoryBufferRef MB, COFF::MachineTypes Machine,
bool MingwDef = false, bool AddUnderscores = true);
} // End namespace object.
} // End namespace llvm.
#endif
PK hwFZ�@��> > Object/FaultMapParser.hnu �[��� //===-- FaultMapParser.h - Parser for the "FaultMaps" section --*- 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_FAULTMAPPARSER_H
#define LLVM_OBJECT_FAULTMAPPARSER_H
#include "llvm/Support/Endian.h"
#include <cassert>
#include <cstdint>
namespace llvm {
class raw_ostream;
/// A parser for the __llvm_faultmaps section generated by the FaultMaps class
/// declared in llvm/CodeGen/FaultMaps.h. This parser is version locked with
/// with the __llvm_faultmaps section generated by the version of LLVM that
/// includes it. No guarantees are made with respect to forward or backward
/// compatibility.
class FaultMapParser {
using FaultMapVersionType = uint8_t;
using Reserved0Type = uint8_t;
using Reserved1Type = uint16_t;
using NumFunctionsType = uint32_t;
static const size_t FaultMapVersionOffset = 0;
static const size_t Reserved0Offset =
FaultMapVersionOffset + sizeof(FaultMapVersionType);
static const size_t Reserved1Offset = Reserved0Offset + sizeof(Reserved0Type);
static const size_t NumFunctionsOffset =
Reserved1Offset + sizeof(Reserved1Type);
static const size_t FunctionInfosOffset =
NumFunctionsOffset + sizeof(NumFunctionsType);
const uint8_t *P;
const uint8_t *E;
template <typename T> static T read(const uint8_t *P, const uint8_t *E) {
assert(P + sizeof(T) <= E && "out of bounds read!");
return support::endian::read<T, support::little, 1>(P);
}
public:
enum FaultKind {
FaultingLoad = 1,
FaultingLoadStore,
FaultingStore,
FaultKindMax
};
class FunctionFaultInfoAccessor {
using FaultKindType = uint32_t;
using FaultingPCOffsetType = uint32_t;
using HandlerPCOffsetType = uint32_t;
static const size_t FaultKindOffset = 0;
static const size_t FaultingPCOffsetOffset =
FaultKindOffset + sizeof(FaultKindType);
static const size_t HandlerPCOffsetOffset =
FaultingPCOffsetOffset + sizeof(FaultingPCOffsetType);
const uint8_t *P;
const uint8_t *E;
public:
static const size_t Size =
HandlerPCOffsetOffset + sizeof(HandlerPCOffsetType);
explicit FunctionFaultInfoAccessor(const uint8_t *P, const uint8_t *E)
: P(P), E(E) {}
FaultKindType getFaultKind() const {
return read<FaultKindType>(P + FaultKindOffset, E);
}
FaultingPCOffsetType getFaultingPCOffset() const {
return read<FaultingPCOffsetType>(P + FaultingPCOffsetOffset, E);
}
HandlerPCOffsetType getHandlerPCOffset() const {
return read<HandlerPCOffsetType>(P + HandlerPCOffsetOffset, E);
}
};
class FunctionInfoAccessor {
using FunctionAddrType = uint64_t;
using NumFaultingPCsType = uint32_t;
using ReservedType = uint32_t;
static const size_t FunctionAddrOffset = 0;
static const size_t NumFaultingPCsOffset =
FunctionAddrOffset + sizeof(FunctionAddrType);
static const size_t ReservedOffset =
NumFaultingPCsOffset + sizeof(NumFaultingPCsType);
static const size_t FunctionFaultInfosOffset =
ReservedOffset + sizeof(ReservedType);
static const size_t FunctionInfoHeaderSize = FunctionFaultInfosOffset;
const uint8_t *P = nullptr;
const uint8_t *E = nullptr;
public:
FunctionInfoAccessor() = default;
explicit FunctionInfoAccessor(const uint8_t *P, const uint8_t *E)
: P(P), E(E) {}
FunctionAddrType getFunctionAddr() const {
return read<FunctionAddrType>(P + FunctionAddrOffset, E);
}
NumFaultingPCsType getNumFaultingPCs() const {
return read<NumFaultingPCsType>(P + NumFaultingPCsOffset, E);
}
FunctionFaultInfoAccessor getFunctionFaultInfoAt(uint32_t Index) const {
assert(Index < getNumFaultingPCs() && "index out of bounds!");
const uint8_t *Begin = P + FunctionFaultInfosOffset +
FunctionFaultInfoAccessor::Size * Index;
return FunctionFaultInfoAccessor(Begin, E);
}
FunctionInfoAccessor getNextFunctionInfo() const {
size_t MySize = FunctionInfoHeaderSize +
getNumFaultingPCs() * FunctionFaultInfoAccessor::Size;
const uint8_t *Begin = P + MySize;
assert(Begin < E && "out of bounds!");
return FunctionInfoAccessor(Begin, E);
}
};
explicit FaultMapParser(const uint8_t *Begin, const uint8_t *End)
: P(Begin), E(End) {}
FaultMapVersionType getFaultMapVersion() const {
auto Version = read<FaultMapVersionType>(P + FaultMapVersionOffset, E);
assert(Version == 1 && "only version 1 supported!");
return Version;
}
NumFunctionsType getNumFunctions() const {
return read<NumFunctionsType>(P + NumFunctionsOffset, E);
}
FunctionInfoAccessor getFirstFunctionInfo() const {
const uint8_t *Begin = P + FunctionInfosOffset;
return FunctionInfoAccessor(Begin, E);
}
};
raw_ostream &operator<<(raw_ostream &OS,
const FaultMapParser::FunctionFaultInfoAccessor &);
raw_ostream &operator<<(raw_ostream &OS,
const FaultMapParser::FunctionInfoAccessor &);
raw_ostream &operator<<(raw_ostream &OS, const FaultMapParser &);
} // namespace llvm
#endif
PK hwFZ< �ӊ � Object/SymbolicFile.hnu �[��� //===- SymbolicFile.h - Interface that only provides symbols ----*- 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
//
//===----------------------------------------------------------------------===//
//
// This file declares the SymbolicFile interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_SYMBOLICFILE_H
#define LLVM_OBJECT_SYMBOLICFILE_H
#include "llvm/ADT/iterator_range.h"
#include "llvm/BinaryFormat/Magic.h"
#include "llvm/Object/Binary.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBufferRef.h"
#include <cinttypes>
#include <cstdint>
#include <cstring>
#include <iterator>
#include <memory>
namespace llvm {
class LLVMContext;
class raw_ostream;
namespace object {
union DataRefImpl {
// This entire union should probably be a
// char[max(8, sizeof(uintptr_t))] and require the impl to cast.
struct {
uint32_t a, b;
} d;
uintptr_t p;
DataRefImpl() { std::memset(this, 0, sizeof(DataRefImpl)); }
};
template <typename OStream>
OStream& operator<<(OStream &OS, const DataRefImpl &D) {
OS << "(" << format("0x%08" PRIxPTR, D.p) << " (" << format("0x%08x", D.d.a)
<< ", " << format("0x%08x", D.d.b) << "))";
return OS;
}
inline bool operator==(const DataRefImpl &a, const DataRefImpl &b) {
// Check bitwise identical. This is the only legal way to compare a union w/o
// knowing which member is in use.
return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0;
}
inline bool operator!=(const DataRefImpl &a, const DataRefImpl &b) {
return !operator==(a, b);
}
inline bool operator<(const DataRefImpl &a, const DataRefImpl &b) {
// Check bitwise identical. This is the only legal way to compare a union w/o
// knowing which member is in use.
return std::memcmp(&a, &b, sizeof(DataRefImpl)) < 0;
}
template <class content_type> class content_iterator {
content_type Current;
public:
using iterator_category = std::forward_iterator_tag;
using value_type = content_type;
using difference_type = std::ptrdiff_t;
using pointer = value_type *;
using reference = value_type &;
content_iterator(content_type symb) : Current(std::move(symb)) {}
const content_type *operator->() const { return &Current; }
const content_type &operator*() const { return Current; }
bool operator==(const content_iterator &other) const {
return Current == other.Current;
}
bool operator!=(const content_iterator &other) const {
return !(*this == other);
}
content_iterator &operator++() { // preincrement
Current.moveNext();
return *this;
}
};
class SymbolicFile;
/// This is a value type class that represents a single symbol in the list of
/// symbols in the object file.
class BasicSymbolRef {
DataRefImpl SymbolPimpl;
const SymbolicFile *OwningObject = nullptr;
public:
enum Flags : unsigned {
SF_None = 0,
SF_Undefined = 1U << 0, // Symbol is defined in another object file
SF_Global = 1U << 1, // Global symbol
SF_Weak = 1U << 2, // Weak symbol
SF_Absolute = 1U << 3, // Absolute symbol
SF_Common = 1U << 4, // Symbol has common linkage
SF_Indirect = 1U << 5, // Symbol is an alias to another symbol
SF_Exported = 1U << 6, // Symbol is visible to other DSOs
SF_FormatSpecific = 1U << 7, // Specific to the object file format
// (e.g. section symbols)
SF_Thumb = 1U << 8, // Thumb symbol in a 32-bit ARM binary
SF_Hidden = 1U << 9, // Symbol has hidden visibility
SF_Const = 1U << 10, // Symbol value is constant
SF_Executable = 1U << 11, // Symbol points to an executable section
// (IR only)
};
BasicSymbolRef() = default;
BasicSymbolRef(DataRefImpl SymbolP, const SymbolicFile *Owner);
bool operator==(const BasicSymbolRef &Other) const;
bool operator<(const BasicSymbolRef &Other) const;
void moveNext();
Error printName(raw_ostream &OS) const;
/// Get symbol flags (bitwise OR of SymbolRef::Flags)
Expected<uint32_t> getFlags() const;
DataRefImpl getRawDataRefImpl() const;
const SymbolicFile *getObject() const;
};
using basic_symbol_iterator = content_iterator<BasicSymbolRef>;
class SymbolicFile : public Binary {
public:
SymbolicFile(unsigned int Type, MemoryBufferRef Source);
~SymbolicFile() override;
// virtual interface.
virtual void moveSymbolNext(DataRefImpl &Symb) const = 0;
virtual Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const = 0;
virtual Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const = 0;
virtual basic_symbol_iterator symbol_begin() const = 0;
virtual basic_symbol_iterator symbol_end() const = 0;
virtual bool is64Bit() const = 0;
// convenience wrappers.
using basic_symbol_iterator_range = iterator_range<basic_symbol_iterator>;
basic_symbol_iterator_range symbols() const {
return basic_symbol_iterator_range(symbol_begin(), symbol_end());
}
// construction aux.
static Expected<std::unique_ptr<SymbolicFile>>
createSymbolicFile(MemoryBufferRef Object, llvm::file_magic Type,
LLVMContext *Context, bool InitContent = true);
static Expected<std::unique_ptr<SymbolicFile>>
createSymbolicFile(MemoryBufferRef Object) {
return createSymbolicFile(Object, llvm::file_magic::unknown, nullptr);
}
static bool classof(const Binary *v) {
return v->isSymbolic();
}
static bool isSymbolicFile(file_magic Type, const LLVMContext *Context);
};
inline BasicSymbolRef::BasicSymbolRef(DataRefImpl SymbolP,
const SymbolicFile *Owner)
: SymbolPimpl(SymbolP), OwningObject(Owner) {}
inline bool BasicSymbolRef::operator==(const BasicSymbolRef &Other) const {
return SymbolPimpl == Other.SymbolPimpl;
}
inline bool BasicSymbolRef::operator<(const BasicSymbolRef &Other) const {
return SymbolPimpl < Other.SymbolPimpl;
}
inline void BasicSymbolRef::moveNext() {
return OwningObject->moveSymbolNext(SymbolPimpl);
}
inline Error BasicSymbolRef::printName(raw_ostream &OS) const {
return OwningObject->printSymbolName(OS, SymbolPimpl);
}
inline Expected<uint32_t> BasicSymbolRef::getFlags() const {
return OwningObject->getSymbolFlags(SymbolPimpl);
}
inline DataRefImpl BasicSymbolRef::getRawDataRefImpl() const {
return SymbolPimpl;
}
inline const SymbolicFile *BasicSymbolRef::getObject() const {
return OwningObject;
}
} // end namespace object
} // end namespace llvm
#endif // LLVM_OBJECT_SYMBOLICFILE_H
PK hwFZJ�� � Object/Error.hnu �[��� //===- Error.h - system_error extensions for Object -------------*- 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
//
//===----------------------------------------------------------------------===//
//
// This declares a new error_category for the Object library.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_ERROR_H
#define LLVM_OBJECT_ERROR_H
#include "llvm/Support/Error.h"
#include <system_error>
namespace llvm {
class Twine;
namespace object {
const std::error_category &object_category();
enum class object_error {
// Error code 0 is absent. Use std::error_code() instead.
arch_not_found = 1,
invalid_file_type,
parse_failed,
unexpected_eof,
string_table_non_null_end,
invalid_section_index,
bitcode_section_not_found,
invalid_symbol_index,
section_stripped,
};
inline std::error_code make_error_code(object_error e) {
return std::error_code(static_cast<int>(e), object_category());
}
/// Base class for all errors indicating malformed binary files.
///
/// Having a subclass for all malformed binary files allows archive-walking
/// code to skip malformed files without having to understand every possible
/// way that a binary file might be malformed.
///
/// Currently inherits from ECError for easy interoperability with
/// std::error_code, but this will be removed in the future.
class BinaryError : public ErrorInfo<BinaryError, ECError> {
void anchor() override;
public:
static char ID;
BinaryError() {
// Default to parse_failed, can be overridden with setErrorCode.
setErrorCode(make_error_code(object_error::parse_failed));
}
};
/// Generic binary error.
///
/// For errors that don't require their own specific sub-error (most errors)
/// this class can be used to describe the error via a string message.
class GenericBinaryError : public ErrorInfo<GenericBinaryError, BinaryError> {
public:
static char ID;
GenericBinaryError(const Twine &Msg);
GenericBinaryError(const Twine &Msg, object_error ECOverride);
const std::string &getMessage() const { return Msg; }
void log(raw_ostream &OS) const override;
private:
std::string Msg;
};
/// isNotObjectErrorInvalidFileType() is used when looping through the children
/// of an archive after calling getAsBinary() on the child and it returns an
/// llvm::Error. In the cases we want to loop through the children and ignore the
/// non-objects in the archive this is used to test the error to see if an
/// error() function needs to called on the llvm::Error.
Error isNotObjectErrorInvalidFileType(llvm::Error Err);
inline Error createError(const Twine &Err) {
return make_error<StringError>(Err, object_error::parse_failed);
}
} // end namespace object.
} // end namespace llvm.
namespace std {
template <>
struct is_error_code_enum<llvm::object::object_error> : std::true_type {};
}
#endif
PK hwFZ��I� � Object/BuildID.hnu �[��� //===- llvm/Object/BuildID.h - Build ID -------------------------*- 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file declares a library for handling Build IDs and using them to find
/// debug info.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_OBJECT_BUILDID_H
#define LLVM_DEBUGINFO_OBJECT_BUILDID_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
namespace llvm {
namespace object {
/// A build ID in binary form.
typedef SmallVector<uint8_t, 10> BuildID;
/// A reference to a BuildID in binary form.
typedef ArrayRef<uint8_t> BuildIDRef;
class ObjectFile;
/// Parses a build ID from a hex string.
BuildID parseBuildID(StringRef Str);
/// Returns the build ID, if any, contained in the given object file.
BuildIDRef getBuildID(const ObjectFile *Obj);
/// BuildIDFetcher searches local cache directories for debug info.
class BuildIDFetcher {
public:
BuildIDFetcher(std::vector<std::string> DebugFileDirectories)
: DebugFileDirectories(std::move(DebugFileDirectories)) {}
virtual ~BuildIDFetcher() = default;
/// Returns the path to the debug file with the given build ID.
virtual std::optional<std::string> fetch(BuildIDRef BuildID) const;
private:
const std::vector<std::string> DebugFileDirectories;
};
} // namespace object
} // namespace llvm
#endif // LLVM_DEBUGINFO_OBJECT_BUILDID_H
PK hwFZ��Y�� � Object/Binary.hnu �[��� //===- Binary.h - A generic binary file -------------------------*- 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
//
//===----------------------------------------------------------------------===//
//
// This file declares the Binary class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_BINARY_H
#define LLVM_OBJECT_BINARY_H
#include "llvm-c/Types.h"
#include "llvm/Object/Error.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/TargetParser/Triple.h"
#include <memory>
#include <utility>
namespace llvm {
class LLVMContext;
class StringRef;
namespace object {
class Binary {
private:
unsigned int TypeID;
protected:
MemoryBufferRef Data;
Binary(unsigned int Type, MemoryBufferRef Source);
enum {
ID_Archive,
ID_MachOUniversalBinary,
ID_COFFImportFile,
ID_IR, // LLVM IR
ID_TapiUniversal, // Text-based Dynamic Library Stub file.
ID_TapiFile, // Text-based Dynamic Library Stub file.
ID_Minidump,
ID_WinRes, // Windows resource (.res) file.
ID_Offload, // Offloading binary file.
// Object and children.
ID_StartObjects,
ID_COFF,
ID_XCOFF32, // AIX XCOFF 32-bit
ID_XCOFF64, // AIX XCOFF 64-bit
ID_ELF32L, // ELF 32-bit, little endian
ID_ELF32B, // ELF 32-bit, big endian
ID_ELF64L, // ELF 64-bit, little endian
ID_ELF64B, // ELF 64-bit, big endian
ID_MachO32L, // MachO 32-bit, little endian
ID_MachO32B, // MachO 32-bit, big endian
ID_MachO64L, // MachO 64-bit, little endian
ID_MachO64B, // MachO 64-bit, big endian
ID_GOFF,
ID_Wasm,
ID_EndObjects
};
static inline unsigned int getELFType(bool isLE, bool is64Bits) {
if (isLE)
return is64Bits ? ID_ELF64L : ID_ELF32L;
else
return is64Bits ? ID_ELF64B : ID_ELF32B;
}
static unsigned int getMachOType(bool isLE, bool is64Bits) {
if (isLE)
return is64Bits ? ID_MachO64L : ID_MachO32L;
else
return is64Bits ? ID_MachO64B : ID_MachO32B;
}
public:
Binary() = delete;
Binary(const Binary &other) = delete;
virtual ~Binary();
virtual Error initContent() { return Error::success(); };
StringRef getData() const;
StringRef getFileName() const;
MemoryBufferRef getMemoryBufferRef() const;
// Cast methods.
unsigned int getType() const { return TypeID; }
// Convenience methods
bool isObject() const {
return TypeID > ID_StartObjects && TypeID < ID_EndObjects;
}
bool isSymbolic() const {
return isIR() || isObject() || isCOFFImportFile() || isTapiFile();
}
bool isArchive() const { return TypeID == ID_Archive; }
bool isMachOUniversalBinary() const {
return TypeID == ID_MachOUniversalBinary;
}
bool isTapiUniversal() const { return TypeID == ID_TapiUniversal; }
bool isELF() const {
return TypeID >= ID_ELF32L && TypeID <= ID_ELF64B;
}
bool isMachO() const {
return TypeID >= ID_MachO32L && TypeID <= ID_MachO64B;
}
bool isCOFF() const {
return TypeID == ID_COFF;
}
bool isXCOFF() const { return TypeID == ID_XCOFF32 || TypeID == ID_XCOFF64; }
bool isWasm() const { return TypeID == ID_Wasm; }
bool isOffloadFile() const { return TypeID == ID_Offload; }
bool isCOFFImportFile() const {
return TypeID == ID_COFFImportFile;
}
bool isIR() const {
return TypeID == ID_IR;
}
bool isGOFF() const { return TypeID == ID_GOFF; }
bool isMinidump() const { return TypeID == ID_Minidump; }
bool isTapiFile() const { return TypeID == ID_TapiFile; }
bool isLittleEndian() const {
return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B ||
TypeID == ID_MachO32B || TypeID == ID_MachO64B ||
TypeID == ID_XCOFF32 || TypeID == ID_XCOFF64);
}
bool isWinRes() const { return TypeID == ID_WinRes; }
Triple::ObjectFormatType getTripleObjectFormat() const {
if (isCOFF())
return Triple::COFF;
if (isMachO())
return Triple::MachO;
if (isELF())
return Triple::ELF;
if (isGOFF())
return Triple::GOFF;
return Triple::UnknownObjectFormat;
}
static Error checkOffset(MemoryBufferRef M, uintptr_t Addr,
const uint64_t Size) {
if (Addr + Size < Addr || Addr + Size < Size ||
Addr + Size > reinterpret_cast<uintptr_t>(M.getBufferEnd()) ||
Addr < reinterpret_cast<uintptr_t>(M.getBufferStart())) {
return errorCodeToError(object_error::unexpected_eof);
}
return Error::success();
}
};
// Create wrappers for C Binding types (see CBindingWrapping.h).
DEFINE_ISA_CONVERSION_FUNCTIONS(Binary, LLVMBinaryRef)
/// Create a Binary from Source, autodetecting the file type.
///
/// @param Source The data to create the Binary from.
Expected<std::unique_ptr<Binary>> createBinary(MemoryBufferRef Source,
LLVMContext *Context = nullptr,
bool InitContent = true);
template <typename T> class OwningBinary {
std::unique_ptr<T> Bin;
std::unique_ptr<MemoryBuffer> Buf;
public:
OwningBinary();
OwningBinary(std::unique_ptr<T> Bin, std::unique_ptr<MemoryBuffer> Buf);
OwningBinary(OwningBinary<T>&& Other);
OwningBinary<T> &operator=(OwningBinary<T> &&Other);
std::pair<std::unique_ptr<T>, std::unique_ptr<MemoryBuffer>> takeBinary();
T* getBinary();
const T* getBinary() const;
};
template <typename T>
OwningBinary<T>::OwningBinary(std::unique_ptr<T> Bin,
std::unique_ptr<MemoryBuffer> Buf)
: Bin(std::move(Bin)), Buf(std::move(Buf)) {}
template <typename T> OwningBinary<T>::OwningBinary() = default;
template <typename T>
OwningBinary<T>::OwningBinary(OwningBinary &&Other)
: Bin(std::move(Other.Bin)), Buf(std::move(Other.Buf)) {}
template <typename T>
OwningBinary<T> &OwningBinary<T>::operator=(OwningBinary &&Other) {
Bin = std::move(Other.Bin);
Buf = std::move(Other.Buf);
return *this;
}
template <typename T>
std::pair<std::unique_ptr<T>, std::unique_ptr<MemoryBuffer>>
OwningBinary<T>::takeBinary() {
return std::make_pair(std::move(Bin), std::move(Buf));
}
template <typename T> T* OwningBinary<T>::getBinary() {
return Bin.get();
}
template <typename T> const T* OwningBinary<T>::getBinary() const {
return Bin.get();
}
Expected<OwningBinary<Binary>> createBinary(StringRef Path,
LLVMContext *Context = nullptr,
bool InitContent = true);
} // end namespace object
} // end namespace llvm
#endif // LLVM_OBJECT_BINARY_H
PK hwFZ%�%� � Object/DXContainer.hnu �[��� //===- DXContainer.h - DXContainer file implementation ----------*- 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
//
//===----------------------------------------------------------------------===//
//
// This file declares the DXContainerFile class, which implements the ObjectFile
// interface for DXContainer files.
//
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_DXCONTAINER_H
#define LLVM_OBJECT_DXCONTAINER_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/DXContainer.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBufferRef.h"
#include "llvm/TargetParser/Triple.h"
#include <variant>
namespace llvm {
namespace object {
namespace DirectX {
class PSVRuntimeInfo {
// This class provides a view into the underlying resource array. The Resource
// data is little-endian encoded and may not be properly aligned to read
// directly from. The dereference operator creates a copy of the data and byte
// swaps it as appropriate.
struct ResourceArray {
StringRef Data;
uint32_t Stride; // size of each element in the list.
ResourceArray() = default;
ResourceArray(StringRef D, size_t S) : Data(D), Stride(S) {}
using value_type = dxbc::PSV::v2::ResourceBindInfo;
static constexpr uint32_t MaxStride() {
return static_cast<uint32_t>(sizeof(value_type));
}
struct iterator {
StringRef Data;
uint32_t Stride; // size of each element in the list.
const char *Current;
iterator(const ResourceArray &A, const char *C)
: Data(A.Data), Stride(A.Stride), Current(C) {}
iterator(const iterator &) = default;
value_type operator*() {
// Explicitly zero the structure so that unused fields are zeroed. It is
// up to the user to know if the fields are used by verifying the PSV
// version.
value_type Val = {{0, 0, 0, 0}, 0, 0};
if (Current >= Data.end())
return Val;
memcpy(static_cast<void *>(&Val), Current,
std::min(Stride, MaxStride()));
if (sys::IsBigEndianHost)
Val.swapBytes();
return Val;
}
iterator operator++() {
if (Current < Data.end())
Current += Stride;
return *this;
}
iterator operator++(int) {
iterator Tmp = *this;
++*this;
return Tmp;
}
iterator operator--() {
if (Current > Data.begin())
Current -= Stride;
return *this;
}
iterator operator--(int) {
iterator Tmp = *this;
--*this;
return Tmp;
}
bool operator==(const iterator I) { return I.Current == Current; }
bool operator!=(const iterator I) { return !(*this == I); }
};
iterator begin() const { return iterator(*this, Data.begin()); }
iterator end() const { return iterator(*this, Data.end()); }
size_t size() const { return Data.size() / Stride; }
};
StringRef Data;
uint32_t Size;
using InfoStruct =
std::variant<std::monostate, dxbc::PSV::v0::RuntimeInfo,
dxbc::PSV::v1::RuntimeInfo, dxbc::PSV::v2::RuntimeInfo>;
InfoStruct BasicInfo;
ResourceArray Resources;
public:
PSVRuntimeInfo(StringRef D) : Data(D), Size(0) {}
// Parsing depends on the shader kind
Error parse(uint16_t ShaderKind);
uint32_t getSize() const { return Size; }
uint32_t getResourceCount() const { return Resources.size(); }
ResourceArray getResources() const { return Resources; }
uint32_t getVersion() const {
return Size >= sizeof(dxbc::PSV::v2::RuntimeInfo)
? 2
: (Size >= sizeof(dxbc::PSV::v1::RuntimeInfo) ? 1 : 0);
}
uint32_t getResourceStride() const { return Resources.Stride; }
const InfoStruct &getInfo() const { return BasicInfo; }
};
} // namespace DirectX
class DXContainer {
public:
using DXILData = std::pair<dxbc::ProgramHeader, const char *>;
private:
DXContainer(MemoryBufferRef O);
MemoryBufferRef Data;
dxbc::Header Header;
SmallVector<uint32_t, 4> PartOffsets;
std::optional<DXILData> DXIL;
std::optional<uint64_t> ShaderFlags;
std::optional<dxbc::ShaderHash> Hash;
std::optional<DirectX::PSVRuntimeInfo> PSVInfo;
Error parseHeader();
Error parsePartOffsets();
Error parseDXILHeader(StringRef Part);
Error parseShaderFlags(StringRef Part);
Error parseHash(StringRef Part);
Error parsePSVInfo(StringRef Part);
friend class PartIterator;
public:
// The PartIterator is a wrapper around the iterator for the PartOffsets
// member of the DXContainer. It contains a refernce to the container, and the
// current iterator value, as well as storage for a parsed part header.
class PartIterator {
const DXContainer &Container;
SmallVectorImpl<uint32_t>::const_iterator OffsetIt;
struct PartData {
dxbc::PartHeader Part;
uint32_t Offset;
StringRef Data;
} IteratorState;
friend class DXContainer;
PartIterator(const DXContainer &C,
SmallVectorImpl<uint32_t>::const_iterator It)
: Container(C), OffsetIt(It) {
if (OffsetIt == Container.PartOffsets.end())
updateIteratorImpl(Container.PartOffsets.back());
else
updateIterator();
}
// Updates the iterator's state data. This results in copying the part
// header into the iterator and handling any required byte swapping. This is
// called when incrementing or decrementing the iterator.
void updateIterator() {
if (OffsetIt != Container.PartOffsets.end())
updateIteratorImpl(*OffsetIt);
}
// Implementation for updating the iterator state based on a specified
// offest.
void updateIteratorImpl(const uint32_t Offset);
public:
PartIterator &operator++() {
if (OffsetIt == Container.PartOffsets.end())
return *this;
++OffsetIt;
updateIterator();
return *this;
}
PartIterator operator++(int) {
PartIterator Tmp = *this;
++(*this);
return Tmp;
}
bool operator==(const PartIterator &RHS) const {
return OffsetIt == RHS.OffsetIt;
}
bool operator!=(const PartIterator &RHS) const {
return OffsetIt != RHS.OffsetIt;
}
const PartData &operator*() { return IteratorState; }
const PartData *operator->() { return &IteratorState; }
};
PartIterator begin() const {
return PartIterator(*this, PartOffsets.begin());
}
PartIterator end() const { return PartIterator(*this, PartOffsets.end()); }
StringRef getData() const { return Data.getBuffer(); }
static Expected<DXContainer> create(MemoryBufferRef Object);
const dxbc::Header &getHeader() const { return Header; }
const std::optional<DXILData> &getDXIL() const { return DXIL; }
std::optional<uint64_t> getShaderFlags() const { return ShaderFlags; }
std::optional<dxbc::ShaderHash> getShaderHash() const { return Hash; }
const std::optional<DirectX::PSVRuntimeInfo> &getPSVInfo() const {
return PSVInfo;
};
};
} // namespace object
} // namespace llvm
#endif // LLVM_OBJECT_DXCONTAINER_H
PK hwFZ���A A Object/ArchiveWriter.hnu �[��� //===- ArchiveWriter.h - ar archive file format writer ----------*- 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
//
//===----------------------------------------------------------------------===//
//
// Declares the writeArchive function for writing an archive file.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_ARCHIVEWRITER_H
#define LLVM_OBJECT_ARCHIVEWRITER_H
#include "llvm/Object/Archive.h"
namespace llvm {
struct NewArchiveMember {
std::unique_ptr<MemoryBuffer> Buf;
StringRef MemberName;
sys::TimePoint<std::chrono::seconds> ModTime;
unsigned UID = 0, GID = 0, Perms = 0644;
NewArchiveMember() = default;
NewArchiveMember(MemoryBufferRef BufRef);
// Detect the archive format from the object or bitcode file. This helps
// assume the archive format when creating or editing archives in the case
// one isn't explicitly set.
object::Archive::Kind detectKindFromObject() const;
static Expected<NewArchiveMember>
getOldMember(const object::Archive::Child &OldMember, bool Deterministic);
static Expected<NewArchiveMember> getFile(StringRef FileName,
bool Deterministic);
};
Expected<std::string> computeArchiveRelativePath(StringRef From, StringRef To);
Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers,
bool WriteSymtab, object::Archive::Kind Kind,
bool Deterministic, bool Thin,
std::unique_ptr<MemoryBuffer> OldArchiveBuf = nullptr,
bool IsEC = false);
// writeArchiveToBuffer is similar to writeArchive but returns the Archive in a
// buffer instead of writing it out to a file.
Expected<std::unique_ptr<MemoryBuffer>>
writeArchiveToBuffer(ArrayRef<NewArchiveMember> NewMembers, bool WriteSymtab,
object::Archive::Kind Kind, bool Deterministic, bool Thin);
}
#endif
PK hwFZ�}ľ � Object/IRObjectFile.hnu �[��� //===- IRObjectFile.h - LLVM IR object file implementation ------*- 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
//
//===----------------------------------------------------------------------===//
//
// This file declares the IRObjectFile template class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_IROBJECTFILE_H
#define LLVM_OBJECT_IROBJECTFILE_H
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Object/IRSymtab.h"
#include "llvm/Object/ModuleSymbolTable.h"
#include "llvm/Object/SymbolicFile.h"
namespace llvm {
class Module;
namespace object {
class ObjectFile;
class IRObjectFile : public SymbolicFile {
std::vector<std::unique_ptr<Module>> Mods;
ModuleSymbolTable SymTab;
IRObjectFile(MemoryBufferRef Object,
std::vector<std::unique_ptr<Module>> Mods);
public:
~IRObjectFile() override;
void moveSymbolNext(DataRefImpl &Symb) const override;
Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override;
Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
basic_symbol_iterator symbol_begin() const override;
basic_symbol_iterator symbol_end() const override;
bool is64Bit() const override {
return Triple(getTargetTriple()).isArch64Bit();
}
StringRef getTargetTriple() const;
static bool classof(const Binary *v) {
return v->isIR();
}
using module_iterator =
pointee_iterator<std::vector<std::unique_ptr<Module>>::const_iterator,
const Module>;
module_iterator module_begin() const { return module_iterator(Mods.begin()); }
module_iterator module_end() const { return module_iterator(Mods.end()); }
iterator_range<module_iterator> modules() const {
return make_range(module_begin(), module_end());
}
/// Finds and returns bitcode embedded in the given object file, or an
/// error code if not found.
static Expected<MemoryBufferRef> findBitcodeInObject(const ObjectFile &Obj);
/// Finds and returns bitcode in the given memory buffer (which may
/// be either a bitcode file or a native object file with embedded bitcode),
/// or an error code if not found.
static Expected<MemoryBufferRef>
findBitcodeInMemBuffer(MemoryBufferRef Object);
static Expected<std::unique_ptr<IRObjectFile>> create(MemoryBufferRef Object,
LLVMContext &Context);
};
/// The contents of a bitcode file and its irsymtab. Any underlying data
/// for the irsymtab are owned by Symtab and Strtab.
struct IRSymtabFile {
std::vector<BitcodeModule> Mods;
SmallVector<char, 0> Symtab, Strtab;
irsymtab::Reader TheReader;
};
/// Reads a bitcode file, creating its irsymtab if necessary.
Expected<IRSymtabFile> readIRSymtab(MemoryBufferRef MBRef);
}
} // namespace llvm
#endif
PK hwFZZ��2�T �T Object/ObjectFile.hnu �[��� //===- ObjectFile.h - File format independent object file -------*- 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
//
//===----------------------------------------------------------------------===//
//
// This file declares a file format independent ObjectFile class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_OBJECTFILE_H
#define LLVM_OBJECT_OBJECTFILE_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/BinaryFormat/Magic.h"
#include "llvm/BinaryFormat/Swift.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/Error.h"
#include "llvm/Object/SymbolicFile.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBufferRef.h"
#include "llvm/TargetParser/Triple.h"
#include <cassert>
#include <cstdint>
#include <memory>
namespace llvm {
class SubtargetFeatures;
namespace object {
class COFFObjectFile;
class MachOObjectFile;
class ObjectFile;
class SectionRef;
class SymbolRef;
class symbol_iterator;
class WasmObjectFile;
using section_iterator = content_iterator<SectionRef>;
typedef std::function<bool(const SectionRef &)> SectionFilterPredicate;
/// This is a value type class that represents a single relocation in the list
/// of relocations in the object file.
class RelocationRef {
DataRefImpl RelocationPimpl;
const ObjectFile *OwningObject = nullptr;
public:
RelocationRef() = default;
RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner);
bool operator==(const RelocationRef &Other) const;
void moveNext();
uint64_t getOffset() const;
symbol_iterator getSymbol() const;
uint64_t getType() const;
/// Get a string that represents the type of this relocation.
///
/// This is for display purposes only.
void getTypeName(SmallVectorImpl<char> &Result) const;
DataRefImpl getRawDataRefImpl() const;
const ObjectFile *getObject() const;
};
using relocation_iterator = content_iterator<RelocationRef>;
/// This is a value type class that represents a single section in the list of
/// sections in the object file.
class SectionRef {
friend class SymbolRef;
DataRefImpl SectionPimpl;
const ObjectFile *OwningObject = nullptr;
public:
SectionRef() = default;
SectionRef(DataRefImpl SectionP, const ObjectFile *Owner);
bool operator==(const SectionRef &Other) const;
bool operator!=(const SectionRef &Other) const;
bool operator<(const SectionRef &Other) const;
void moveNext();
Expected<StringRef> getName() const;
uint64_t getAddress() const;
uint64_t getIndex() const;
uint64_t getSize() const;
Expected<StringRef> getContents() const;
/// Get the alignment of this section.
Align getAlignment() const;
bool isCompressed() const;
/// Whether this section contains instructions.
bool isText() const;
/// Whether this section contains data, not instructions.
bool isData() const;
/// Whether this section contains BSS uninitialized data.
bool isBSS() const;
bool isVirtual() const;
bool isBitcode() const;
bool isStripped() const;
/// Whether this section will be placed in the text segment, according to the
/// Berkeley size format. This is true if the section is allocatable, and
/// contains either code or readonly data.
bool isBerkeleyText() const;
/// Whether this section will be placed in the data segment, according to the
/// Berkeley size format. This is true if the section is allocatable and
/// contains data (e.g. PROGBITS), but is not text.
bool isBerkeleyData() const;
/// Whether this section is a debug section.
bool isDebugSection() const;
bool containsSymbol(SymbolRef S) const;
relocation_iterator relocation_begin() const;
relocation_iterator relocation_end() const;
iterator_range<relocation_iterator> relocations() const {
return make_range(relocation_begin(), relocation_end());
}
/// Returns the related section if this section contains relocations. The
/// returned section may or may not have applied its relocations.
Expected<section_iterator> getRelocatedSection() const;
DataRefImpl getRawDataRefImpl() const;
const ObjectFile *getObject() const;
};
struct SectionedAddress {
const static uint64_t UndefSection = UINT64_MAX;
uint64_t Address = 0;
uint64_t SectionIndex = UndefSection;
};
inline bool operator<(const SectionedAddress &LHS,
const SectionedAddress &RHS) {
return std::tie(LHS.SectionIndex, LHS.Address) <
std::tie(RHS.SectionIndex, RHS.Address);
}
inline bool operator==(const SectionedAddress &LHS,
const SectionedAddress &RHS) {
return std::tie(LHS.SectionIndex, LHS.Address) ==
std::tie(RHS.SectionIndex, RHS.Address);
}
raw_ostream &operator<<(raw_ostream &OS, const SectionedAddress &Addr);
/// This is a value type class that represents a single symbol in the list of
/// symbols in the object file.
class SymbolRef : public BasicSymbolRef {
friend class SectionRef;
public:
enum Type {
ST_Unknown, // Type not specified
ST_Other,
ST_Data,
ST_Debug,
ST_File,
ST_Function,
};
SymbolRef() = default;
SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner);
SymbolRef(const BasicSymbolRef &B) : BasicSymbolRef(B) {
assert(isa<ObjectFile>(BasicSymbolRef::getObject()));
}
Expected<StringRef> getName() const;
/// Returns the symbol virtual address (i.e. address at which it will be
/// mapped).
Expected<uint64_t> getAddress() const;
/// Return the value of the symbol depending on the object this can be an
/// offset or a virtual address.
Expected<uint64_t> getValue() const;
/// Get the alignment of this symbol as the actual value (not log 2).
uint32_t getAlignment() const;
uint64_t getCommonSize() const;
Expected<SymbolRef::Type> getType() const;
/// Get section this symbol is defined in reference to. Result is
/// end_sections() if it is undefined or is an absolute symbol.
Expected<section_iterator> getSection() const;
const ObjectFile *getObject() const;
};
class symbol_iterator : public basic_symbol_iterator {
public:
symbol_iterator(SymbolRef Sym) : basic_symbol_iterator(Sym) {}
symbol_iterator(const basic_symbol_iterator &B)
: basic_symbol_iterator(SymbolRef(B->getRawDataRefImpl(),
cast<ObjectFile>(B->getObject()))) {}
const SymbolRef *operator->() const {
const BasicSymbolRef &P = basic_symbol_iterator::operator *();
return static_cast<const SymbolRef*>(&P);
}
const SymbolRef &operator*() const {
const BasicSymbolRef &P = basic_symbol_iterator::operator *();
return static_cast<const SymbolRef&>(P);
}
};
/// This class is the base class for all object file types. Concrete instances
/// of this object are created by createObjectFile, which figures out which type
/// to create.
class ObjectFile : public SymbolicFile {
virtual void anchor();
protected:
ObjectFile(unsigned int Type, MemoryBufferRef Source);
const uint8_t *base() const {
return reinterpret_cast<const uint8_t *>(Data.getBufferStart());
}
// These functions are for SymbolRef to call internally. The main goal of
// this is to allow SymbolRef::SymbolPimpl to point directly to the symbol
// entry in the memory mapped object file. SymbolPimpl cannot contain any
// virtual functions because then it could not point into the memory mapped
// file.
//
// Implementations assume that the DataRefImpl is valid and has not been
// modified externally. It's UB otherwise.
friend class SymbolRef;
virtual Expected<StringRef> getSymbolName(DataRefImpl Symb) const = 0;
Error printSymbolName(raw_ostream &OS,
DataRefImpl Symb) const override;
virtual Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const = 0;
virtual uint64_t getSymbolValueImpl(DataRefImpl Symb) const = 0;
virtual uint32_t getSymbolAlignment(DataRefImpl Symb) const;
virtual uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const = 0;
virtual Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const = 0;
virtual Expected<section_iterator>
getSymbolSection(DataRefImpl Symb) const = 0;
// Same as above for SectionRef.
friend class SectionRef;
virtual void moveSectionNext(DataRefImpl &Sec) const = 0;
virtual Expected<StringRef> getSectionName(DataRefImpl Sec) const = 0;
virtual uint64_t getSectionAddress(DataRefImpl Sec) const = 0;
virtual uint64_t getSectionIndex(DataRefImpl Sec) const = 0;
virtual uint64_t getSectionSize(DataRefImpl Sec) const = 0;
virtual Expected<ArrayRef<uint8_t>>
getSectionContents(DataRefImpl Sec) const = 0;
virtual uint64_t getSectionAlignment(DataRefImpl Sec) const = 0;
virtual bool isSectionCompressed(DataRefImpl Sec) const = 0;
virtual bool isSectionText(DataRefImpl Sec) const = 0;
virtual bool isSectionData(DataRefImpl Sec) const = 0;
virtual bool isSectionBSS(DataRefImpl Sec) const = 0;
// A section is 'virtual' if its contents aren't present in the object image.
virtual bool isSectionVirtual(DataRefImpl Sec) const = 0;
virtual bool isSectionBitcode(DataRefImpl Sec) const;
virtual bool isSectionStripped(DataRefImpl Sec) const;
virtual bool isBerkeleyText(DataRefImpl Sec) const;
virtual bool isBerkeleyData(DataRefImpl Sec) const;
virtual bool isDebugSection(DataRefImpl Sec) const;
virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0;
virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0;
virtual Expected<section_iterator> getRelocatedSection(DataRefImpl Sec) const;
// Same as above for RelocationRef.
friend class RelocationRef;
virtual void moveRelocationNext(DataRefImpl &Rel) const = 0;
virtual uint64_t getRelocationOffset(DataRefImpl Rel) const = 0;
virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0;
virtual uint64_t getRelocationType(DataRefImpl Rel) const = 0;
virtual void getRelocationTypeName(DataRefImpl Rel,
SmallVectorImpl<char> &Result) const = 0;
virtual llvm::binaryformat::Swift5ReflectionSectionKind
mapReflectionSectionNameToEnumValue(StringRef SectionName) const {
return llvm::binaryformat::Swift5ReflectionSectionKind::unknown;
};
Expected<uint64_t> getSymbolValue(DataRefImpl Symb) const;
public:
ObjectFile() = delete;
ObjectFile(const ObjectFile &other) = delete;
uint64_t getCommonSymbolSize(DataRefImpl Symb) const {
Expected<uint32_t> SymbolFlagsOrErr = getSymbolFlags(Symb);
if (!SymbolFlagsOrErr)
// TODO: Actually report errors helpfully.
report_fatal_error(SymbolFlagsOrErr.takeError());
assert(*SymbolFlagsOrErr & SymbolRef::SF_Common);
return getCommonSymbolSizeImpl(Symb);
}
virtual std::vector<SectionRef> dynamic_relocation_sections() const {
return std::vector<SectionRef>();
}
using symbol_iterator_range = iterator_range<symbol_iterator>;
symbol_iterator_range symbols() const {
return symbol_iterator_range(symbol_begin(), symbol_end());
}
virtual section_iterator section_begin() const = 0;
virtual section_iterator section_end() const = 0;
using section_iterator_range = iterator_range<section_iterator>;
section_iterator_range sections() const {
return section_iterator_range(section_begin(), section_end());
}
virtual bool hasDebugInfo() const;
/// The number of bytes used to represent an address in this object
/// file format.
virtual uint8_t getBytesInAddress() const = 0;
virtual StringRef getFileFormatName() const = 0;
virtual Triple::ArchType getArch() const = 0;
virtual Expected<SubtargetFeatures> getFeatures() const = 0;
virtual std::optional<StringRef> tryGetCPUName() const {
return std::nullopt;
};
virtual void setARMSubArch(Triple &TheTriple) const { }
virtual Expected<uint64_t> getStartAddress() const {
return errorCodeToError(object_error::parse_failed);
};
/// Create a triple from the data in this object file.
Triple makeTriple() const;
/// Maps a debug section name to a standard DWARF section name.
virtual StringRef mapDebugSectionName(StringRef Name) const { return Name; }
/// True if this is a relocatable object (.o/.obj).
virtual bool isRelocatableObject() const = 0;
/// True if the reflection section can be stripped by the linker.
bool isReflectionSectionStrippable(
llvm::binaryformat::Swift5ReflectionSectionKind ReflectionSectionKind)
const;
/// @returns Pointer to ObjectFile subclass to handle this type of object.
/// @param ObjectPath The path to the object file. ObjectPath.isObject must
/// return true.
/// Create ObjectFile from path.
static Expected<OwningBinary<ObjectFile>>
createObjectFile(StringRef ObjectPath);
static Expected<std::unique_ptr<ObjectFile>>
createObjectFile(MemoryBufferRef Object, llvm::file_magic Type,
bool InitContent = true);
static Expected<std::unique_ptr<ObjectFile>>
createObjectFile(MemoryBufferRef Object) {
return createObjectFile(Object, llvm::file_magic::unknown);
}
static bool classof(const Binary *v) {
return v->isObject();
}
static Expected<std::unique_ptr<COFFObjectFile>>
createCOFFObjectFile(MemoryBufferRef Object);
static Expected<std::unique_ptr<ObjectFile>>
createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType);
static Expected<std::unique_ptr<ObjectFile>>
createELFObjectFile(MemoryBufferRef Object, bool InitContent = true);
static Expected<std::unique_ptr<MachOObjectFile>>
createMachOObjectFile(MemoryBufferRef Object,
uint32_t UniversalCputype = 0,
uint32_t UniversalIndex = 0);
static Expected<std::unique_ptr<ObjectFile>>
createGOFFObjectFile(MemoryBufferRef Object);
static Expected<std::unique_ptr<WasmObjectFile>>
createWasmObjectFile(MemoryBufferRef Object);
};
/// A filtered iterator for SectionRefs that skips sections based on some given
/// predicate.
class SectionFilterIterator {
public:
SectionFilterIterator(SectionFilterPredicate Pred,
const section_iterator &Begin,
const section_iterator &End)
: Predicate(std::move(Pred)), Iterator(Begin), End(End) {
scanPredicate();
}
const SectionRef &operator*() const { return *Iterator; }
SectionFilterIterator &operator++() {
++Iterator;
scanPredicate();
return *this;
}
bool operator!=(const SectionFilterIterator &Other) const {
return Iterator != Other.Iterator;
}
private:
void scanPredicate() {
while (Iterator != End && !Predicate(*Iterator)) {
++Iterator;
}
}
SectionFilterPredicate Predicate;
section_iterator Iterator;
section_iterator End;
};
/// Creates an iterator range of SectionFilterIterators for a given Object and
/// predicate.
class SectionFilter {
public:
SectionFilter(SectionFilterPredicate Pred, const ObjectFile &Obj)
: Predicate(std::move(Pred)), Object(Obj) {}
SectionFilterIterator begin() {
return SectionFilterIterator(Predicate, Object.section_begin(),
Object.section_end());
}
SectionFilterIterator end() {
return SectionFilterIterator(Predicate, Object.section_end(),
Object.section_end());
}
private:
SectionFilterPredicate Predicate;
const ObjectFile &Object;
};
// Inline function definitions.
inline SymbolRef::SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner)
: BasicSymbolRef(SymbolP, Owner) {}
inline Expected<StringRef> SymbolRef::getName() const {
return getObject()->getSymbolName(getRawDataRefImpl());
}
inline Expected<uint64_t> SymbolRef::getAddress() const {
return getObject()->getSymbolAddress(getRawDataRefImpl());
}
inline Expected<uint64_t> SymbolRef::getValue() const {
return getObject()->getSymbolValue(getRawDataRefImpl());
}
inline uint32_t SymbolRef::getAlignment() const {
return getObject()->getSymbolAlignment(getRawDataRefImpl());
}
inline uint64_t SymbolRef::getCommonSize() const {
return getObject()->getCommonSymbolSize(getRawDataRefImpl());
}
inline Expected<section_iterator> SymbolRef::getSection() const {
return getObject()->getSymbolSection(getRawDataRefImpl());
}
inline Expected<SymbolRef::Type> SymbolRef::getType() const {
return getObject()->getSymbolType(getRawDataRefImpl());
}
inline const ObjectFile *SymbolRef::getObject() const {
const SymbolicFile *O = BasicSymbolRef::getObject();
return cast<ObjectFile>(O);
}
/// SectionRef
inline SectionRef::SectionRef(DataRefImpl SectionP,
const ObjectFile *Owner)
: SectionPimpl(SectionP)
, OwningObject(Owner) {}
inline bool SectionRef::operator==(const SectionRef &Other) const {
return OwningObject == Other.OwningObject &&
SectionPimpl == Other.SectionPimpl;
}
inline bool SectionRef::operator!=(const SectionRef &Other) const {
return !(*this == Other);
}
inline bool SectionRef::operator<(const SectionRef &Other) const {
assert(OwningObject == Other.OwningObject);
return SectionPimpl < Other.SectionPimpl;
}
inline void SectionRef::moveNext() {
return OwningObject->moveSectionNext(SectionPimpl);
}
inline Expected<StringRef> SectionRef::getName() const {
return OwningObject->getSectionName(SectionPimpl);
}
inline uint64_t SectionRef::getAddress() const {
return OwningObject->getSectionAddress(SectionPimpl);
}
inline uint64_t SectionRef::getIndex() const {
return OwningObject->getSectionIndex(SectionPimpl);
}
inline uint64_t SectionRef::getSize() const {
return OwningObject->getSectionSize(SectionPimpl);
}
inline Expected<StringRef> SectionRef::getContents() const {
Expected<ArrayRef<uint8_t>> Res =
OwningObject->getSectionContents(SectionPimpl);
if (!Res)
return Res.takeError();
return StringRef(reinterpret_cast<const char *>(Res->data()), Res->size());
}
inline Align SectionRef::getAlignment() const {
return MaybeAlign(OwningObject->getSectionAlignment(SectionPimpl))
.valueOrOne();
}
inline bool SectionRef::isCompressed() const {
return OwningObject->isSectionCompressed(SectionPimpl);
}
inline bool SectionRef::isText() const {
return OwningObject->isSectionText(SectionPimpl);
}
inline bool SectionRef::isData() const {
return OwningObject->isSectionData(SectionPimpl);
}
inline bool SectionRef::isBSS() const {
return OwningObject->isSectionBSS(SectionPimpl);
}
inline bool SectionRef::isVirtual() const {
return OwningObject->isSectionVirtual(SectionPimpl);
}
inline bool SectionRef::isBitcode() const {
return OwningObject->isSectionBitcode(SectionPimpl);
}
inline bool SectionRef::isStripped() const {
return OwningObject->isSectionStripped(SectionPimpl);
}
inline bool SectionRef::isBerkeleyText() const {
return OwningObject->isBerkeleyText(SectionPimpl);
}
inline bool SectionRef::isBerkeleyData() const {
return OwningObject->isBerkeleyData(SectionPimpl);
}
inline bool SectionRef::isDebugSection() const {
return OwningObject->isDebugSection(SectionPimpl);
}
inline relocation_iterator SectionRef::relocation_begin() const {
return OwningObject->section_rel_begin(SectionPimpl);
}
inline relocation_iterator SectionRef::relocation_end() const {
return OwningObject->section_rel_end(SectionPimpl);
}
inline Expected<section_iterator> SectionRef::getRelocatedSection() const {
return OwningObject->getRelocatedSection(SectionPimpl);
}
inline DataRefImpl SectionRef::getRawDataRefImpl() const {
return SectionPimpl;
}
inline const ObjectFile *SectionRef::getObject() const {
return OwningObject;
}
/// RelocationRef
inline RelocationRef::RelocationRef(DataRefImpl RelocationP,
const ObjectFile *Owner)
: RelocationPimpl(RelocationP)
, OwningObject(Owner) {}
inline bool RelocationRef::operator==(const RelocationRef &Other) const {
return RelocationPimpl == Other.RelocationPimpl;
}
inline void RelocationRef::moveNext() {
return OwningObject->moveRelocationNext(RelocationPimpl);
}
inline uint64_t RelocationRef::getOffset() const {
return OwningObject->getRelocationOffset(RelocationPimpl);
}
inline symbol_iterator RelocationRef::getSymbol() const {
return OwningObject->getRelocationSymbol(RelocationPimpl);
}
inline uint64_t RelocationRef::getType() const {
return OwningObject->getRelocationType(RelocationPimpl);
}
inline void RelocationRef::getTypeName(SmallVectorImpl<char> &Result) const {
return OwningObject->getRelocationTypeName(RelocationPimpl, Result);
}
inline DataRefImpl RelocationRef::getRawDataRefImpl() const {
return RelocationPimpl;
}
inline const ObjectFile *RelocationRef::getObject() const {
return OwningObject;
}
} // end namespace object
template <> struct DenseMapInfo<object::SectionRef> {
static bool isEqual(const object::SectionRef &A,
const object::SectionRef &B) {
return A == B;
}
static object::SectionRef getEmptyKey() {
return object::SectionRef({}, nullptr);
}
static object::SectionRef getTombstoneKey() {
object::DataRefImpl TS;
TS.p = (uintptr_t)-1;
return object::SectionRef(TS, nullptr);
}
static unsigned getHashValue(const object::SectionRef &Sec) {
object::DataRefImpl Raw = Sec.getRawDataRefImpl();
return hash_combine(Raw.p, Raw.d.a, Raw.d.b);
}
};
} // end namespace llvm
#endif // LLVM_OBJECT_OBJECTFILE_H
PK hwFZv�5u>. >. Object/IRSymtab.hnu �[��� //===- IRSymtab.h - data definitions for IR symbol tables -------*- 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
//
//===----------------------------------------------------------------------===//
//
// This file contains data definitions and a reader and builder for a symbol
// table for LLVM IR. Its purpose is to allow linkers and other consumers of
// bitcode files to efficiently read the symbol table for symbol resolution
// purposes without needing to construct a module in memory.
//
// As with most object files the symbol table has two parts: the symbol table
// itself and a string table which is referenced by the symbol table.
//
// A symbol table corresponds to a single bitcode file, which may consist of
// multiple modules, so symbol tables may likewise contain symbols for multiple
// modules.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_IRSYMTAB_H
#define LLVM_OBJECT_IRSYMTAB_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/Comdat.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/Object/SymbolicFile.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <cassert>
#include <cstdint>
#include <vector>
namespace llvm {
struct BitcodeFileContents;
class StringTableBuilder;
namespace irsymtab {
namespace storage {
// The data structures in this namespace define the low-level serialization
// format. Clients that just want to read a symbol table should use the
// irsymtab::Reader class.
using Word = support::ulittle32_t;
/// A reference to a string in the string table.
struct Str {
Word Offset, Size;
StringRef get(StringRef Strtab) const {
return {Strtab.data() + Offset, Size};
}
};
/// A reference to a range of objects in the symbol table.
template <typename T> struct Range {
Word Offset, Size;
ArrayRef<T> get(StringRef Symtab) const {
return {reinterpret_cast<const T *>(Symtab.data() + Offset), Size};
}
};
/// Describes the range of a particular module's symbols within the symbol
/// table.
struct Module {
Word Begin, End;
/// The index of the first Uncommon for this Module.
Word UncBegin;
};
/// This is equivalent to an IR comdat.
struct Comdat {
Str Name;
// llvm::Comdat::SelectionKind
Word SelectionKind;
};
/// Contains the information needed by linkers for symbol resolution, as well as
/// by the LTO implementation itself.
struct Symbol {
/// The mangled symbol name.
Str Name;
/// The unmangled symbol name, or the empty string if this is not an IR
/// symbol.
Str IRName;
/// The index into Header::Comdats, or -1 if not a comdat member.
Word ComdatIndex;
Word Flags;
enum FlagBits {
FB_visibility, // 2 bits
FB_has_uncommon = FB_visibility + 2,
FB_undefined,
FB_weak,
FB_common,
FB_indirect,
FB_used,
FB_tls,
FB_may_omit,
FB_global,
FB_format_specific,
FB_unnamed_addr,
FB_executable,
};
};
/// This data structure contains rarely used symbol fields and is optionally
/// referenced by a Symbol.
struct Uncommon {
Word CommonSize, CommonAlign;
/// COFF-specific: the name of the symbol that a weak external resolves to
/// if not defined.
Str COFFWeakExternFallbackName;
/// Specified section name, if any.
Str SectionName;
};
struct Header {
/// Version number of the symtab format. This number should be incremented
/// when the format changes, but it does not need to be incremented if a
/// change to LLVM would cause it to create a different symbol table.
Word Version;
enum { kCurrentVersion = 3 };
/// The producer's version string (LLVM_VERSION_STRING " " LLVM_REVISION).
/// Consumers should rebuild the symbol table from IR if the producer's
/// version does not match the consumer's version due to potential differences
/// in symbol table format, symbol enumeration order and so on.
Str Producer;
Range<Module> Modules;
Range<Comdat> Comdats;
Range<Symbol> Symbols;
Range<Uncommon> Uncommons;
Str TargetTriple, SourceFileName;
/// COFF-specific: linker directives.
Str COFFLinkerOpts;
/// Dependent Library Specifiers
Range<Str> DependentLibraries;
};
} // end namespace storage
/// Fills in Symtab and StrtabBuilder with a valid symbol and string table for
/// Mods.
Error build(ArrayRef<Module *> Mods, SmallVector<char, 0> &Symtab,
StringTableBuilder &StrtabBuilder, BumpPtrAllocator &Alloc);
/// This represents a symbol that has been read from a storage::Symbol and
/// possibly a storage::Uncommon.
struct Symbol {
// Copied from storage::Symbol.
StringRef Name, IRName;
int ComdatIndex;
uint32_t Flags;
// Copied from storage::Uncommon.
uint32_t CommonSize, CommonAlign;
StringRef COFFWeakExternFallbackName;
StringRef SectionName;
/// Returns the mangled symbol name.
StringRef getName() const { return Name; }
/// Returns the unmangled symbol name, or the empty string if this is not an
/// IR symbol.
StringRef getIRName() const { return IRName; }
/// Returns the index into the comdat table (see Reader::getComdatTable()), or
/// -1 if not a comdat member.
int getComdatIndex() const { return ComdatIndex; }
using S = storage::Symbol;
GlobalValue::VisibilityTypes getVisibility() const {
return GlobalValue::VisibilityTypes((Flags >> S::FB_visibility) & 3);
}
bool isUndefined() const { return (Flags >> S::FB_undefined) & 1; }
bool isWeak() const { return (Flags >> S::FB_weak) & 1; }
bool isCommon() const { return (Flags >> S::FB_common) & 1; }
bool isIndirect() const { return (Flags >> S::FB_indirect) & 1; }
bool isUsed() const { return (Flags >> S::FB_used) & 1; }
bool isTLS() const { return (Flags >> S::FB_tls) & 1; }
bool canBeOmittedFromSymbolTable() const {
return (Flags >> S::FB_may_omit) & 1;
}
bool isGlobal() const { return (Flags >> S::FB_global) & 1; }
bool isFormatSpecific() const { return (Flags >> S::FB_format_specific) & 1; }
bool isUnnamedAddr() const { return (Flags >> S::FB_unnamed_addr) & 1; }
bool isExecutable() const { return (Flags >> S::FB_executable) & 1; }
uint64_t getCommonSize() const {
assert(isCommon());
return CommonSize;
}
uint32_t getCommonAlignment() const {
assert(isCommon());
return CommonAlign;
}
/// COFF-specific: for weak externals, returns the name of the symbol that is
/// used as a fallback if the weak external remains undefined.
StringRef getCOFFWeakExternalFallback() const {
assert(isWeak() && isIndirect());
return COFFWeakExternFallbackName;
}
StringRef getSectionName() const { return SectionName; }
};
/// This class can be used to read a Symtab and Strtab produced by
/// irsymtab::build.
class Reader {
StringRef Symtab, Strtab;
ArrayRef<storage::Module> Modules;
ArrayRef<storage::Comdat> Comdats;
ArrayRef<storage::Symbol> Symbols;
ArrayRef<storage::Uncommon> Uncommons;
ArrayRef<storage::Str> DependentLibraries;
StringRef str(storage::Str S) const { return S.get(Strtab); }
template <typename T> ArrayRef<T> range(storage::Range<T> R) const {
return R.get(Symtab);
}
const storage::Header &header() const {
return *reinterpret_cast<const storage::Header *>(Symtab.data());
}
public:
class SymbolRef;
Reader() = default;
Reader(StringRef Symtab, StringRef Strtab) : Symtab(Symtab), Strtab(Strtab) {
Modules = range(header().Modules);
Comdats = range(header().Comdats);
Symbols = range(header().Symbols);
Uncommons = range(header().Uncommons);
DependentLibraries = range(header().DependentLibraries);
}
using symbol_range = iterator_range<object::content_iterator<SymbolRef>>;
/// Returns the symbol table for the entire bitcode file.
/// The symbols enumerated by this method are ephemeral, but they can be
/// copied into an irsymtab::Symbol object.
symbol_range symbols() const;
size_t getNumModules() const { return Modules.size(); }
/// Returns a slice of the symbol table for the I'th module in the file.
/// The symbols enumerated by this method are ephemeral, but they can be
/// copied into an irsymtab::Symbol object.
symbol_range module_symbols(unsigned I) const;
StringRef getTargetTriple() const { return str(header().TargetTriple); }
/// Returns the source file path specified at compile time.
StringRef getSourceFileName() const { return str(header().SourceFileName); }
/// Returns a table with all the comdats used by this file.
std::vector<std::pair<StringRef, llvm::Comdat::SelectionKind>>
getComdatTable() const {
std::vector<std::pair<StringRef, llvm::Comdat::SelectionKind>> ComdatTable;
ComdatTable.reserve(Comdats.size());
for (auto C : Comdats)
ComdatTable.push_back({str(C.Name), llvm::Comdat::SelectionKind(
uint32_t(C.SelectionKind))});
return ComdatTable;
}
/// COFF-specific: returns linker options specified in the input file.
StringRef getCOFFLinkerOpts() const { return str(header().COFFLinkerOpts); }
/// Returns dependent library specifiers
std::vector<StringRef> getDependentLibraries() const {
std::vector<StringRef> Specifiers;
Specifiers.reserve(DependentLibraries.size());
for (auto S : DependentLibraries) {
Specifiers.push_back(str(S));
}
return Specifiers;
}
};
/// Ephemeral symbols produced by Reader::symbols() and
/// Reader::module_symbols().
class Reader::SymbolRef : public Symbol {
const storage::Symbol *SymI, *SymE;
const storage::Uncommon *UncI;
const Reader *R;
void read() {
if (SymI == SymE)
return;
Name = R->str(SymI->Name);
IRName = R->str(SymI->IRName);
ComdatIndex = SymI->ComdatIndex;
Flags = SymI->Flags;
if (Flags & (1 << storage::Symbol::FB_has_uncommon)) {
CommonSize = UncI->CommonSize;
CommonAlign = UncI->CommonAlign;
COFFWeakExternFallbackName = R->str(UncI->COFFWeakExternFallbackName);
SectionName = R->str(UncI->SectionName);
} else
// Reset this field so it can be queried unconditionally for all symbols.
SectionName = "";
}
public:
SymbolRef(const storage::Symbol *SymI, const storage::Symbol *SymE,
const storage::Uncommon *UncI, const Reader *R)
: SymI(SymI), SymE(SymE), UncI(UncI), R(R) {
read();
}
void moveNext() {
++SymI;
if (Flags & (1 << storage::Symbol::FB_has_uncommon))
++UncI;
read();
}
bool operator==(const SymbolRef &Other) const { return SymI == Other.SymI; }
};
inline Reader::symbol_range Reader::symbols() const {
return {SymbolRef(Symbols.begin(), Symbols.end(), Uncommons.begin(), this),
SymbolRef(Symbols.end(), Symbols.end(), nullptr, this)};
}
inline Reader::symbol_range Reader::module_symbols(unsigned I) const {
const storage::Module &M = Modules[I];
const storage::Symbol *MBegin = Symbols.begin() + M.Begin,
*MEnd = Symbols.begin() + M.End;
return {SymbolRef(MBegin, MEnd, Uncommons.begin() + M.UncBegin, this),
SymbolRef(MEnd, MEnd, nullptr, this)};
}
/// The contents of the irsymtab in a bitcode file. Any underlying data for the
/// irsymtab are owned by Symtab and Strtab.
struct FileContents {
SmallVector<char, 0> Symtab, Strtab;
Reader TheReader;
};
/// Reads the contents of a bitcode file, creating its irsymtab if necessary.
Expected<FileContents> readBitcode(const BitcodeFileContents &BFC);
} // end namespace irsymtab
} // end namespace llvm
#endif // LLVM_OBJECT_IRSYMTAB_H
PK hwFZ?����5 �5
Object/Wasm.hnu �[��� //===- Wasm.h - Wasm object file implementation -----------------*- 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
//
//===----------------------------------------------------------------------===//
//
// This file declares the WasmObjectFile class, which implements the ObjectFile
// interface for Wasm files.
//
// See: https://github.com/WebAssembly/design/blob/main/BinaryEncoding.md
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_WASM_H
#define LLVM_OBJECT_WASM_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Wasm.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/MC/MCSymbolWasm.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cstddef>
#include <cstdint>
#include <vector>
namespace llvm {
namespace object {
class WasmSymbol {
public:
WasmSymbol(const wasm::WasmSymbolInfo &Info,
const wasm::WasmGlobalType *GlobalType,
const wasm::WasmTableType *TableType,
const wasm::WasmSignature *Signature)
: Info(Info), GlobalType(GlobalType), TableType(TableType),
Signature(Signature) {}
const wasm::WasmSymbolInfo &Info;
const wasm::WasmGlobalType *GlobalType;
const wasm::WasmTableType *TableType;
const wasm::WasmSignature *Signature;
bool isTypeFunction() const {
return Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION;
}
bool isTypeTable() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_TABLE; }
bool isTypeData() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_DATA; }
bool isTypeGlobal() const {
return Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL;
}
bool isTypeSection() const {
return Info.Kind == wasm::WASM_SYMBOL_TYPE_SECTION;
}
bool isTypeTag() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_TAG; }
bool isDefined() const { return !isUndefined(); }
bool isUndefined() const {
return (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) != 0;
}
bool isBindingWeak() const {
return getBinding() == wasm::WASM_SYMBOL_BINDING_WEAK;
}
bool isBindingGlobal() const {
return getBinding() == wasm::WASM_SYMBOL_BINDING_GLOBAL;
}
bool isBindingLocal() const {
return getBinding() == wasm::WASM_SYMBOL_BINDING_LOCAL;
}
unsigned getBinding() const {
return Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK;
}
bool isHidden() const {
return getVisibility() == wasm::WASM_SYMBOL_VISIBILITY_HIDDEN;
}
unsigned getVisibility() const {
return Info.Flags & wasm::WASM_SYMBOL_VISIBILITY_MASK;
}
void print(raw_ostream &Out) const;
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void dump() const;
#endif
};
struct WasmSection {
WasmSection() = default;
uint32_t Type = 0;
uint32_t Offset = 0; // Offset within the file
StringRef Name; // Section name (User-defined sections only)
uint32_t Comdat = UINT32_MAX; // From the "comdat info" section
ArrayRef<uint8_t> Content;
std::vector<wasm::WasmRelocation> Relocations;
// Length of the LEB encoding of the section header's size field
std::optional<uint8_t> HeaderSecSizeEncodingLen;
};
struct WasmSegment {
uint32_t SectionOffset;
wasm::WasmDataSegment Data;
};
class WasmObjectFile : public ObjectFile {
public:
WasmObjectFile(MemoryBufferRef Object, Error &Err);
const wasm::WasmObjectHeader &getHeader() const;
const WasmSymbol &getWasmSymbol(const DataRefImpl &Symb) const;
const WasmSymbol &getWasmSymbol(const SymbolRef &Symbol) const;
const WasmSection &getWasmSection(const SectionRef &Section) const;
const wasm::WasmRelocation &getWasmRelocation(const RelocationRef &Ref) const;
static bool classof(const Binary *v) { return v->isWasm(); }
const wasm::WasmDylinkInfo &dylinkInfo() const { return DylinkInfo; }
const wasm::WasmProducerInfo &getProducerInfo() const { return ProducerInfo; }
ArrayRef<wasm::WasmFeatureEntry> getTargetFeatures() const {
return TargetFeatures;
}
ArrayRef<wasm::WasmSignature> types() const { return Signatures; }
ArrayRef<wasm::WasmImport> imports() const { return Imports; }
ArrayRef<wasm::WasmTable> tables() const { return Tables; }
ArrayRef<wasm::WasmLimits> memories() const { return Memories; }
ArrayRef<wasm::WasmGlobal> globals() const { return Globals; }
ArrayRef<wasm::WasmTag> tags() const { return Tags; }
ArrayRef<wasm::WasmExport> exports() const { return Exports; }
ArrayRef<WasmSymbol> syms() const { return Symbols; }
const wasm::WasmLinkingData &linkingData() const { return LinkingData; }
uint32_t getNumberOfSymbols() const { return Symbols.size(); }
ArrayRef<wasm::WasmElemSegment> elements() const { return ElemSegments; }
ArrayRef<WasmSegment> dataSegments() const { return DataSegments; }
ArrayRef<wasm::WasmFunction> functions() const { return Functions; }
ArrayRef<wasm::WasmDebugName> debugNames() const { return DebugNames; }
uint32_t startFunction() const { return StartFunction; }
uint32_t getNumImportedGlobals() const { return NumImportedGlobals; }
uint32_t getNumImportedTables() const { return NumImportedTables; }
uint32_t getNumImportedFunctions() const { return NumImportedFunctions; }
uint32_t getNumImportedTags() const { return NumImportedTags; }
uint32_t getNumSections() const { return Sections.size(); }
void moveSymbolNext(DataRefImpl &Symb) const override;
Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
basic_symbol_iterator symbol_begin() const override;
basic_symbol_iterator symbol_end() const override;
Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
bool is64Bit() const override { return false; }
Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
uint64_t getWasmSymbolValue(const WasmSymbol &Sym) const;
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
uint32_t getSymbolSectionId(SymbolRef Sym) const;
// Overrides from SectionRef.
void moveSectionNext(DataRefImpl &Sec) const override;
Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
uint64_t getSectionAddress(DataRefImpl Sec) const override;
uint64_t getSectionIndex(DataRefImpl Sec) const override;
uint64_t getSectionSize(DataRefImpl Sec) const override;
Expected<ArrayRef<uint8_t>>
getSectionContents(DataRefImpl Sec) const override;
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
bool isSectionCompressed(DataRefImpl Sec) const override;
bool isSectionText(DataRefImpl Sec) const override;
bool isSectionData(DataRefImpl Sec) const override;
bool isSectionBSS(DataRefImpl Sec) const override;
bool isSectionVirtual(DataRefImpl Sec) const override;
relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
relocation_iterator section_rel_end(DataRefImpl Sec) const override;
// Overrides from RelocationRef.
void moveRelocationNext(DataRefImpl &Rel) const override;
uint64_t getRelocationOffset(DataRefImpl Rel) const override;
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
uint64_t getRelocationType(DataRefImpl Rel) const override;
void getRelocationTypeName(DataRefImpl Rel,
SmallVectorImpl<char> &Result) const override;
section_iterator section_begin() const override;
section_iterator section_end() const override;
uint8_t getBytesInAddress() const override;
StringRef getFileFormatName() const override;
Triple::ArchType getArch() const override;
Expected<SubtargetFeatures> getFeatures() const override;
bool isRelocatableObject() const override;
bool isSharedObject() const;
struct ReadContext {
const uint8_t *Start;
const uint8_t *Ptr;
const uint8_t *End;
};
private:
bool isValidFunctionIndex(uint32_t Index) const;
bool isDefinedFunctionIndex(uint32_t Index) const;
bool isValidGlobalIndex(uint32_t Index) const;
bool isValidTableNumber(uint32_t Index) const;
bool isDefinedGlobalIndex(uint32_t Index) const;
bool isDefinedTableNumber(uint32_t Index) const;
bool isValidTagIndex(uint32_t Index) const;
bool isDefinedTagIndex(uint32_t Index) const;
bool isValidFunctionSymbol(uint32_t Index) const;
bool isValidTableSymbol(uint32_t Index) const;
bool isValidGlobalSymbol(uint32_t Index) const;
bool isValidTagSymbol(uint32_t Index) const;
bool isValidDataSymbol(uint32_t Index) const;
bool isValidSectionSymbol(uint32_t Index) const;
wasm::WasmFunction &getDefinedFunction(uint32_t Index);
const wasm::WasmFunction &getDefinedFunction(uint32_t Index) const;
wasm::WasmGlobal &getDefinedGlobal(uint32_t Index);
wasm::WasmTag &getDefinedTag(uint32_t Index);
const WasmSection &getWasmSection(DataRefImpl Ref) const;
const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const;
uint32_t getSymbolSectionIdImpl(const WasmSymbol &Symb) const;
Error parseSection(WasmSection &Sec);
Error parseCustomSection(WasmSection &Sec, ReadContext &Ctx);
// Standard section types
Error parseTypeSection(ReadContext &Ctx);
Error parseImportSection(ReadContext &Ctx);
Error parseFunctionSection(ReadContext &Ctx);
Error parseTableSection(ReadContext &Ctx);
Error parseMemorySection(ReadContext &Ctx);
Error parseTagSection(ReadContext &Ctx);
Error parseGlobalSection(ReadContext &Ctx);
Error parseExportSection(ReadContext &Ctx);
Error parseStartSection(ReadContext &Ctx);
Error parseElemSection(ReadContext &Ctx);
Error parseCodeSection(ReadContext &Ctx);
Error parseDataSection(ReadContext &Ctx);
Error parseDataCountSection(ReadContext &Ctx);
// Custom section types
Error parseDylinkSection(ReadContext &Ctx);
Error parseDylink0Section(ReadContext &Ctx);
Error parseNameSection(ReadContext &Ctx);
Error parseLinkingSection(ReadContext &Ctx);
Error parseLinkingSectionSymtab(ReadContext &Ctx);
Error parseLinkingSectionComdat(ReadContext &Ctx);
Error parseProducersSection(ReadContext &Ctx);
Error parseTargetFeaturesSection(ReadContext &Ctx);
Error parseRelocSection(StringRef Name, ReadContext &Ctx);
wasm::WasmObjectHeader Header;
std::vector<WasmSection> Sections;
wasm::WasmDylinkInfo DylinkInfo;
wasm::WasmProducerInfo ProducerInfo;
std::vector<wasm::WasmFeatureEntry> TargetFeatures;
std::vector<wasm::WasmSignature> Signatures;
std::vector<wasm::WasmTable> Tables;
std::vector<wasm::WasmLimits> Memories;
std::vector<wasm::WasmGlobal> Globals;
std::vector<wasm::WasmTag> Tags;
std::vector<wasm::WasmImport> Imports;
std::vector<wasm::WasmExport> Exports;
std::vector<wasm::WasmElemSegment> ElemSegments;
std::vector<WasmSegment> DataSegments;
std::optional<size_t> DataCount;
std::vector<wasm::WasmFunction> Functions;
std::vector<WasmSymbol> Symbols;
std::vector<wasm::WasmDebugName> DebugNames;
uint32_t StartFunction = -1;
bool HasLinkingSection = false;
bool HasDylinkSection = false;
bool HasMemory64 = false;
wasm::WasmLinkingData LinkingData;
uint32_t NumImportedGlobals = 0;
uint32_t NumImportedTables = 0;
uint32_t NumImportedFunctions = 0;
uint32_t NumImportedTags = 0;
uint32_t CodeSection = 0;
uint32_t DataSection = 0;
uint32_t TagSection = 0;
uint32_t GlobalSection = 0;
uint32_t TableSection = 0;
};
class WasmSectionOrderChecker {
public:
// We define orders for all core wasm sections and known custom sections.
enum : int {
// Sentinel, must be zero
WASM_SEC_ORDER_NONE = 0,
// Core sections
WASM_SEC_ORDER_TYPE,
WASM_SEC_ORDER_IMPORT,
WASM_SEC_ORDER_FUNCTION,
WASM_SEC_ORDER_TABLE,
WASM_SEC_ORDER_MEMORY,
WASM_SEC_ORDER_TAG,
WASM_SEC_ORDER_GLOBAL,
WASM_SEC_ORDER_EXPORT,
WASM_SEC_ORDER_START,
WASM_SEC_ORDER_ELEM,
WASM_SEC_ORDER_DATACOUNT,
WASM_SEC_ORDER_CODE,
WASM_SEC_ORDER_DATA,
// Custom sections
// "dylink" should be the very first section in the module
WASM_SEC_ORDER_DYLINK,
// "linking" section requires DATA section in order to validate data symbols
WASM_SEC_ORDER_LINKING,
// Must come after "linking" section in order to validate reloc indexes.
WASM_SEC_ORDER_RELOC,
// "name" section must appear after DATA. Comes after "linking" to allow
// symbol table to set default function name.
WASM_SEC_ORDER_NAME,
// "producers" section must appear after "name" section.
WASM_SEC_ORDER_PRODUCERS,
// "target_features" section must appear after producers section
WASM_SEC_ORDER_TARGET_FEATURES,
// Must be last
WASM_NUM_SEC_ORDERS
};
// Sections that may or may not be present, but cannot be predecessors
static int DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS];
bool isValidSectionOrder(unsigned ID, StringRef CustomSectionName = "");
private:
bool Seen[WASM_NUM_SEC_ORDERS] = {}; // Sections that have been seen already
// Returns -1 for unknown sections.
int getSectionOrder(unsigned ID, StringRef CustomSectionName = "");
};
} // end namespace object
inline raw_ostream &operator<<(raw_ostream &OS, const object::WasmSymbol &Sym) {
Sym.print(OS);
return OS;
}
} // end namespace llvm
#endif // LLVM_OBJECT_WASM_H
PK hwFZy\�w� � Object/Decompressor.hnu �[��� //===-- Decompressor.h ------------------------------------------*- 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
//
//===----------------------------------------------------------------------===/
#ifndef LLVM_OBJECT_DECOMPRESSOR_H
#define LLVM_OBJECT_DECOMPRESSOR_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/Error.h"
namespace llvm {
namespace object {
/// Decompressor helps to handle decompression of compressed sections.
class Decompressor {
public:
/// Create decompressor object.
/// @param Name Section name.
/// @param Data Section content.
/// @param IsLE Flag determines if Data is in little endian form.
/// @param Is64Bit Flag determines if object is 64 bit.
static Expected<Decompressor> create(StringRef Name, StringRef Data,
bool IsLE, bool Is64Bit);
/// Resize the buffer and uncompress section data into it.
/// @param Out Destination buffer.
template <class T> Error resizeAndDecompress(T &Out) {
Out.resize(DecompressedSize);
return decompress({(uint8_t *)Out.data(), (size_t)DecompressedSize});
}
/// Uncompress section data to raw buffer provided.
Error decompress(MutableArrayRef<uint8_t> Output);
/// Return memory buffer size required for decompression.
uint64_t getDecompressedSize() { return DecompressedSize; }
private:
Decompressor(StringRef Data);
Error consumeCompressedHeader(bool Is64Bit, bool IsLittleEndian);
StringRef SectionData;
uint64_t DecompressedSize;
DebugCompressionType CompressionType = DebugCompressionType::None;
};
} // end namespace object
} // end namespace llvm
#endif // LLVM_OBJECT_DECOMPRESSOR_H
PK hwFZ̦��
Object/MachOUniversalWriter.hnu �[��� //===- MachOUniversalWriter.h - MachO universal binary writer----*- 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
//
//===----------------------------------------------------------------------===//
//
// Declares the Slice class and writeUniversalBinary function for writing a
// MachO universal binary file.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_MACHOUNIVERSALWRITER_H
#define LLVM_OBJECT_MACHOUNIVERSALWRITER_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/MachO.h"
#include "llvm/Support/Error.h"
#include <cstdint>
#include <string>
namespace llvm {
class LLVMContext;
namespace object {
class Archive;
class Binary;
class IRObjectFile;
class MachOObjectFile;
class Slice {
const Binary *B;
uint32_t CPUType;
uint32_t CPUSubType;
std::string ArchName;
// P2Alignment field stores slice alignment values from universal
// binaries. This is also needed to order the slices so the total
// file size can be calculated before creating the output buffer.
uint32_t P2Alignment;
Slice(const IRObjectFile &IRO, uint32_t CPUType, uint32_t CPUSubType,
std::string ArchName, uint32_t Align);
public:
explicit Slice(const MachOObjectFile &O);
Slice(const MachOObjectFile &O, uint32_t Align);
/// This constructor takes pre-specified \param CPUType , \param CPUSubType ,
/// \param ArchName , \param Align instead of inferring them from the archive
/// members.
Slice(const Archive &A, uint32_t CPUType, uint32_t CPUSubType,
std::string ArchName, uint32_t Align);
static Expected<Slice> create(const Archive &A,
LLVMContext *LLVMCtx = nullptr);
static Expected<Slice> create(const IRObjectFile &IRO, uint32_t Align);
void setP2Alignment(uint32_t Align) { P2Alignment = Align; }
const Binary *getBinary() const { return B; }
uint32_t getCPUType() const { return CPUType; }
uint32_t getCPUSubType() const { return CPUSubType; }
uint32_t getP2Alignment() const { return P2Alignment; }
uint64_t getCPUID() const {
return static_cast<uint64_t>(CPUType) << 32 | CPUSubType;
}
std::string getArchString() const {
if (!ArchName.empty())
return ArchName;
return ("unknown(" + Twine(CPUType) + "," +
Twine(CPUSubType & ~MachO::CPU_SUBTYPE_MASK) + ")")
.str();
}
friend bool operator<(const Slice &Lhs, const Slice &Rhs) {
if (Lhs.CPUType == Rhs.CPUType)
return Lhs.CPUSubType < Rhs.CPUSubType;
// force arm64-family to follow after all other slices for
// compatibility with cctools lipo
if (Lhs.CPUType == MachO::CPU_TYPE_ARM64)
return false;
if (Rhs.CPUType == MachO::CPU_TYPE_ARM64)
return true;
// Sort by alignment to minimize file size
return Lhs.P2Alignment < Rhs.P2Alignment;
}
};
Error writeUniversalBinary(ArrayRef<Slice> Slices, StringRef OutputFileName);
Error writeUniversalBinaryToStream(ArrayRef<Slice> Slices, raw_ostream &Out);
} // end namespace object
} // end namespace llvm
#endif // LLVM_OBJECT_MACHOUNIVERSALWRITER_H
PK hwFZ�U�� Object/GOFFObjectFile.hnu �[��� //===- GOFFObjectFile.h - GOFF object file implementation -------*- 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
//
//===----------------------------------------------------------------------===//
//
// This file declares the GOFFObjectFile class.
// Record classes and derivatives are also declared and implemented.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_GOFFOBJECTFILE_H
#define LLVM_OBJECT_GOFFOBJECTFILE_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IndexedMap.h"
#include "llvm/BinaryFormat/GOFF.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/ConvertEBCDIC.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/SubtargetFeature.h"
#include "llvm/TargetParser/Triple.h"
namespace llvm {
namespace object {
class GOFFObjectFile : public ObjectFile {
IndexedMap<const uint8_t *> EsdPtrs; // Indexed by EsdId.
mutable DenseMap<uint32_t, std::pair<size_t, std::unique_ptr<char[]>>>
EsdNamesCache;
typedef DataRefImpl SectionEntryImpl;
// (EDID, 0) code, r/o data section
// (EDID,PRID) r/w data section
SmallVector<SectionEntryImpl, 256> SectionList;
mutable DenseMap<uint32_t, std::string> SectionDataCache;
public:
Expected<StringRef> getSymbolName(SymbolRef Symbol) const;
GOFFObjectFile(MemoryBufferRef Object, Error &Err);
static inline bool classof(const Binary *V) { return V->isGOFF(); }
section_iterator section_begin() const override;
section_iterator section_end() const override;
uint8_t getBytesInAddress() const override { return 8; }
StringRef getFileFormatName() const override { return "GOFF-SystemZ"; }
Triple::ArchType getArch() const override { return Triple::systemz; }
Expected<SubtargetFeatures> getFeatures() const override { return SubtargetFeatures(); }
bool isRelocatableObject() const override { return true; }
void moveSymbolNext(DataRefImpl &Symb) const override;
basic_symbol_iterator symbol_begin() const override;
basic_symbol_iterator symbol_end() const override;
bool is64Bit() const override {
return true;
}
private:
// SymbolRef.
Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
const uint8_t *getSymbolEsdRecord(DataRefImpl Symb) const;
bool isSymbolUnresolved(DataRefImpl Symb) const;
bool isSymbolIndirect(DataRefImpl Symb) const;
// SectionRef.
void moveSectionNext(DataRefImpl &Sec) const override {}
virtual Expected<StringRef> getSectionName(DataRefImpl Sec) const override {
return StringRef();
}
uint64_t getSectionAddress(DataRefImpl Sec) const override { return 0; }
uint64_t getSectionSize(DataRefImpl Sec) const override { return 0; }
virtual Expected<ArrayRef<uint8_t>>
getSectionContents(DataRefImpl Sec) const override {
return ArrayRef<uint8_t>();
}
uint64_t getSectionIndex(DataRefImpl Sec) const override { return 0; }
uint64_t getSectionAlignment(DataRefImpl Sec) const override { return 0; }
bool isSectionCompressed(DataRefImpl Sec) const override { return false; }
bool isSectionText(DataRefImpl Sec) const override { return false; }
bool isSectionData(DataRefImpl Sec) const override { return false; }
bool isSectionBSS(DataRefImpl Sec) const override { return false; }
bool isSectionVirtual(DataRefImpl Sec) const override { return false; }
relocation_iterator section_rel_begin(DataRefImpl Sec) const override {
return relocation_iterator(RelocationRef(Sec, this));
}
relocation_iterator section_rel_end(DataRefImpl Sec) const override {
return relocation_iterator(RelocationRef(Sec, this));
}
const uint8_t *getSectionEdEsdRecord(DataRefImpl &Sec) const;
const uint8_t *getSectionPrEsdRecord(DataRefImpl &Sec) const;
const uint8_t *getSectionEdEsdRecord(uint32_t SectionIndex) const;
const uint8_t *getSectionPrEsdRecord(uint32_t SectionIndex) const;
// RelocationRef.
void moveRelocationNext(DataRefImpl &Rel) const override {}
uint64_t getRelocationOffset(DataRefImpl Rel) const override { return 0; }
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override {
DataRefImpl Temp;
return basic_symbol_iterator(SymbolRef(Temp, this));
}
uint64_t getRelocationType(DataRefImpl Rel) const override { return 0; }
void getRelocationTypeName(DataRefImpl Rel,
SmallVectorImpl<char> &Result) const override {}
};
} // namespace object
} // namespace llvm
#endif
PK hwFZ(�
� � Object/CVDebugRecord.hnu �[��� //===- CVDebugRecord.h ------------------------------------------*- 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJECT_CVDEBUGRECORD_H
#define LLVM_OBJECT_CVDEBUGRECORD_H
#include "llvm/Support/Endian.h"
namespace llvm {
namespace OMF {
struct Signature {
enum ID : uint32_t {
PDB70 = 0x53445352, // RSDS
PDB20 = 0x3031424e, // NB10
CV50 = 0x3131424e, // NB11
CV41 = 0x3930424e, // NB09
};
support::ulittle32_t CVSignature;
support::ulittle32_t Offset;
};
}
namespace codeview {
struct PDB70DebugInfo {
support::ulittle32_t CVSignature;
uint8_t Signature[16];
support::ulittle32_t Age;
// char PDBFileName[];
};
struct PDB20DebugInfo {
support::ulittle32_t CVSignature;
support::ulittle32_t Offset;
support::ulittle32_t Signature;
support::ulittle32_t Age;
// char PDBFileName[];
};
union DebugInfo {
struct OMF::Signature Signature;
struct PDB20DebugInfo PDB20;
struct PDB70DebugInfo PDB70;
};
}
}
#endif
PK hwFZ�g/ҷ"