7.3. Linker Plugin API Usage and Reference

7.3.1. Linker Wrapper

documentation/images/LinkerWrapper.png

Plugins interacts with the linker using LinkerWrapper.

class LinkerWrapper

LinkerWrapper provides a bridge between the linker plugin and the linker. The plugins uses a LinkerWrapper object to interact and communicate with the linker.

Note

Even though, all LinkerWrapper APIs are available to all plugin interface types at all link stages, some APIs are only meaningful for certain plugin interface types and link stages.

Public Types

enum State

Stages of the link process. What actions a plugin can perform depends on the link state. For example:

  • Plugins can change the output section of an input section only in BeforeLayout link state.

  • Plugins can move chunks from one output section to another only in CreatingSections link state.

  • Plugins can only compute the output image layout checkum using LinkerWrapper::getImageLayoutChecksum only in AfterLayout linker state.

  • Plugins can reassign virtual addresses using LinkerWrapper::reassignVirtualAddresses() only in CreatingSegments link state.

Plugin authors should ensure that the action being performed by the plugin is meaningful in the link state in which it is executed. Executing invalid actions for a link state can result in undefined behavior.

Values:

enumerator Unknown
enumerator Initializing
enumerator BeforeLayout
enumerator CreatingSections
enumerator AfterLayout
enumerator CreatingSegments
enum LinkMode

Link modes.

Values:

enumerator UnknownLinkMode
enumerator StaticExecutable
enumerator DynamicExecutable
enumerator SharedLibrary
enumerator PIE
enumerator PartialLink

Public Functions

explicit LinkerWrapper(eld::Plugin*, eld::Module&)

Construct LinkerWrapper object.

void RequestGarbageCollection()

Tell the linker that garbage collection should run. This method must be called early, at least no later than when symbols are created, for example from Init(). This call will set the initial state of each symbol before garbage collection and force the GC pass. This is not really needed, but avoiding this will require a bit of refactoring.

eld::Expected<std::vector<Use>> getUses(Chunk &C)

Returns a vector of Uses of symbols defined in chunk C.

Note

This function’s result is valid for the link states BeforeLayout and beyond.

Parameters

CChunk containing the symbol definition.

Returns

vector of Uses that are referred from the Chunk C.

std::string getLinkerVersion() const

Returns eld version.

eld::Expected<std::vector<Use>> getUses(Section &S)

Returns a vector of Uses that are referred from the Section S.

Note

This function’s result is valid for the link states BeforeLayout and beyond.

Parameters

SSection

Returns

vector of uses that are referred from the Section S.

eld::Expected<Symbol> getSymbol(const std::string &Sym) const

Returns the linker symbol Sym.

Note

This function’s result is valid for the link states BeforeLayout and beyond.

Parameters

SymSymbol name

Returns

if successfully found, then Symbol object which represents the specified symbol; Otherwise an empty Symbol object.

eld::Expected<Symbol> addSymbol(InputFile InputFile, const std::string &Name, plugin::Symbol::Binding Binding, Section InputSection, plugin::Symbol::Kind Kind, plugin::Symbol::Visibility Visibility = plugin::Symbol::Default, unsigned Type = 0, uint64_t Size = 0)

Create a symbol but do not provide symbol resolution information (chunk or value). Used to define bitcode symbols. Note that InputSection is optional. IMPORTANT: The symbol is resolved right away and the returned symbol will reference the resolved symbol. This means that the returned symbol may not be the bitcode symbol.

eld::Expected<void> setOutputSection(Section &S, const std::string &OutputSection, const std::string &Annotation = "")

Override the output section to OutputSection for Section S.

Note

This function must only be used in BeforeLayout link state.

Parameters
  • SSection for which the output section needs to be overriden.

  • OutputSection – Name of the output section.

  • Annotation – Annotations are used for diagnostic purposes.

eld::Expected<void> setPreserveSymbol(Symbol Symbol)

Mark the symbol as preserved for garbage collection.

void setSectionName(plugin::Section, const std::string&)

Rename a section.

void setRuleMatchingInput(plugin::Section, plugin::InputFile)

For a given section, set its input used for rule matching. Matching input file must be set for post-LTO sections.

eld::Expected<void> addReferencedSymbol(plugin::Section ReferencingSection, plugin::Symbol ReferencedSymbol)

Add a reference from ReferencingSection to ReferencedSymbol.

eld::Expected<OutputSection> getOutputSection(Section &S) const

Return the corresponding output section for the section S.

Note

This function’s result is valid for link states BeforeLayout and beyond.

Note

This function’s result is invalid for SectionIteratorPlugin run even though the link state is Beforelayout.

Parameters

S – Input section

Returns

corresponding output section for the section S.

eld::Expected<OutputSection> getOutputSection(const std::string &OutputSection)

Finds an output section with the name OutputSection.

Note

This function’s result is valid for link states BeforeLayout and beyond.

Note

This function’s result is invalid for SectionIteratorPlugin run even though the link state is Beforelayout.

Parameters

OutputSection – Output section name

Returns

If successfully found, an output section representing the specified output section; Otherwise an empty plugin::OutputSection object.

eld::Expected<std::unique_ptr<const uint8_t[]>> getOutputSectionContents(OutputSection &O) const
Returns

contents of this output section

eld::Expected<void> finishAssignOutputSections()

Finish assigning output sections.

This function should be called by the plugin after all the section rule-matching modifications has been done by the plugin.

Note

If the plugin has not changed any section rule-matching, then there is no need to call this function.

Note

This function must only be used in BeforeLayout link state.

eld::Expected<void> reassignVirtualAddresses()

This function may be called to reassign section addresses to reflect newly added output sections that have not yet been assigned an address.

Note

This function may only be used in CreatingSegments state.

void setLinkerFatalError()

Set the linker to fatally error. This function will cause link process to terminate as soon as it can. It must be used if a plugin has encountered an unrecoverable error.

inline eld::Plugin *getPlugin() const

Returns the underlying linker plugin associated with the linker wrapper.

bool matchPattern(const std::string &Pattern, const std::string &Name) const

Returns true if the string Name matches the pattern specified by Pattern; Otherwise returns false.

Pattern matching here follows unix glob style pattern matching.

Parameters
  • Pattern – glob pattern

  • name – string to be matched against the pattern

Returns

true if Name matches the pattern specified by Pattern; Otherwise returns false.

~LinkerWrapper()

Destroy the Linker Wrapper.

State getState() const

Returns the current link state.

bool isPostLTOPhase() const

Return true if the linker is processing post LTO objects.

eld::Expected<void> addSymbolToChunk(Chunk &C, const std::string &Symbol, uint64_t Val)

Adds a local symbol Symbol to the chunk C.

Parameters
  • CChunk in which the symbol should be added.

  • symbol – Name of the symbol

  • Val – Value of the symbol

eld::Expected<Chunk> createPaddingChunk(uint32_t Alignment, size_t PaddingSize)

Creates a Padding Chunk in the section, ‘.bss.paddingchunk.${PluginName}’, having contents as 0x0.

Parameters
  • Alignment – Required alignment for the padding chunk

  • PaddingSize – Required size for the padding chunk

Returns

The created padding chunk

eld::Expected<Chunk> createCodeChunk(const std::string &Name, uint32_t Alignment, const char *Buf, size_t Sz)

Creates a code chunk in the section, ‘.text.codechunk.${Name}.${PluginName}’, having contents specified by the buffer Buf of size Sz. The created Code chunk will have all the usual properties of the code section such as PROGBITS section type, and allocation and execution permissions.

Parameters
  • Name – It is used to determined the section name of the chunk.

  • Alignment – Alignment to be used for the chunk

  • Buf – Buffer containing the data that the the chunk will store.

  • Sz – Size of the buffer Buf

Returns

The created code chunk

eld::Expected<Chunk> createDataChunk(const std::string &Name, uint32_t Alignment, const char *Buf, size_t Sz)

Creates a data chunk in the section, ‘.data.codechunk.${Name}.${PluginName}’, having contents specified by the buffer Buf of size Sz. Data chunk will have all the usual properties of the data section such as PROGBITS section type, and allocation and write permissions.

Parameters
  • Name – It is used to determine the section name of the chunk

  • Alignment – Alignment to be used for the chunk

  • Buf – Buffer containing the data that the chunk will store.

  • Sz – Size of the buffer Buf

Returns

The created data chunk.

eld::Expected<Chunk> createDataChunkWithCustomName(const std::string &Name, uint32_t Alignment, const char *Buf, size_t Sz)

Creates a data chunk in the section, ‘Name’, having contents specified by the buffer Buf of size Sz. Data chunk will have all the usual properties of the data section such as PROGBITS section type, and allocation and write permissions.

Parameters
  • Name – It is used to determine the section name of the chunk

  • Alignment – Alignment to be used for the chunk

  • Buf – Buffer containing the data that the chunk will store.

  • Sz – Size of the buffer Buf

Returns

The created data chunk.

eld::Expected<Chunk> createBSSChunk(const std::string &Name, uint32_t Alignment, size_t Sz)

Create a Data Chunk in .bss section.

eld::Expected<void> replaceSymbolContent(plugin::Symbol S, const uint8_t *Buf, size_t Sz)

Replace symbol S content with the buffer Buf of size Sz.

Note

This function can be used in any link state upto and including AfterLayout.

Parameters
  • SSymbol whose content has to be replaced.

  • Buf – Buffer containing the new content.

  • Sz – Buffer size

Returns

void if the symbol’s content is successfully replaced; Otherwise returns a DiagnosticEntry object (as std::unique_ptr<DiagnosticEntry>) describing the error.

eld::Expected<void> addChunk(const LinkerScriptRule &Rule, const Chunk &C, const std::string &A = "")

Adds the chunk C to the LinkerScriptRule rule.

Note

This function must only be used in CreatingSections link state.

Parameters
  • Rule – Linker script rule to which the chunk C must be added.

  • CChunk that is to be added.

  • A – Annotation to be used for diagnostics purpose.

eld::Expected<void> removeChunk(const LinkerScriptRule &Rule, const Chunk &C, const std::string &A = "")

Removes the chunk C from the output section of the rule.

Note

This function must only be used in CreatingSections link state.

Parameters
  • Rule – Linker script rule from which chunk has to be removed

  • CChunk that is to be removed.

  • A – Annotation to be used for diagnostics purpose.

eld::Expected<void> updateChunks(const LinkerScriptRule &Rule, const std::vector<Chunk> &V, const std::string &A = "")

Reset the chunks of the output section of the rule to the sequence of chunks specified by V. More precisely, this function removes all the existing chunks from the output sections, and adds the sequence of chunks , in order, as specified by V.

Note

This function must only be used in CreatingSections link state.

Parameters
  • Rule – Linker script rule whose output section’s chunks have to be updated.

  • V – Sequence of chunks that are to be added to the output section of the rule.

  • A – Annotation to be used for diagnostics purposes.

std::string getRepositoryVersion() const

Returns a string containing Linker and LLVM repository version informations.

void recordPluginData(uint32_t Key, void *Data, const std::string &Annotation)

Record Plugin Data from a plugin.

std::vector<PluginData> getPluginData(const std::string &PluginName)

Return the recorded plugin data.

llvm::Timer *CreateTimer(const std::string &Name, const std::string &Description, bool IsEnabled)

Profiling Plugin support.

eld::Expected<void> registerReloc(uint32_t RelocType, const std::string &Name = "")

Register a relocation for the plugin to call back.

RelocationHandler getRelocationHandler() const

Returns the relocation handler.

bool isMultiThreaded() const

Returns true if the linker is using multiple threads.

size_t getPluginThreadCount() const

Returns number of threads used by the linker.

LinkerScript getLinkerScript()

Return the associated LinkerScript.

std::string getFileContents(std::string FileName)

Get FileName file contents

If FileName doesn’t exist, then returns an empty string.

eld::Expected<std::string> findConfigFile(const std::string &FileName) const
Returns

path to file if it is found. If not found, then an Error DiagnosticEntry is returned.

eld::Expected<INIFile> readINIFile(std::string FileName)

Read a config file in ini format.

Parameters

FileName – ini file to read

Returns

eld::Expected<INIFile> object containing either the successfully read INI file, or a diagnostic object describing the failure..

eld::Expected<void> writeINIFile(INIFile &INI, const std::string &OutputPath) const

Write an ini file.

Parameters
  • iniINIFile

  • OutputPath – path of the file to write

Returns

std::unique_ptr<DiagnosticEntry> object that describes the error; if no error occurs, then returns void.

eld::Expected<TarWriter> getTarWriter(const std::string &Name) const

Creates and returns eld::Expected<TarWriter> to support creating a tar archive with the name passed and add files to it.

Parameters

std::string – &Name for tar file name.

Returns

eld::Expected<TarWriter>

bool isTimingEnabled() const
Returns

true if Timing is enabled for this plugin; Otherwise returns false.

std::vector<plugin::InputFile> getInputFiles() const

Note

This function do not returns the input linker scripts.

Returns

the input object files visited by the Linker.

LinkMode getLinkMode() const

Returns the link mode.

bool is32Bits() const

Return true if 32 bit target.

char *getUninitBuffer(size_t S) const

Allocate an uninitialized buffer that will live throughout the link process.

Parameters

S – Size of the uninitialized buffer

Returns

base address of the created uninitialized buffer.

eld::Expected<void> resetSymbol(plugin::Symbol S, Chunk C)

Reset an undefined symbol to another chunk. Reset here means, change the source chunk of the symbol. This functions marks that symbol S is defined in the chunk C.

Note

This function can be used in any link state including and upto Afterlayout.

Note

This function only works for symbols that do not have a value. The function returns false, if the symbol requested to be reset is a defined symbol with an initial value.

Parameters
  • SSymbol whose source chunk is to be changed.

  • C – New source chunk for the symbol.

Returns

true if resetting is successful; Otherwise false.

eld::Expected<Use> createAndAddUse(Chunk C, off_t Offset, uint32_t RelocationType, plugin::Symbol S, int64_t Addend)

Create and return a Use for a Chunk, and add it to the Chunk.

eld::Expected<void> getTargetDataForUse(Use &U, uint64_t &Data) const

Return the value of the relocation target.

eld::Expected<void> setTargetDataForUse(Use &U, uint64_t Data)

Set the value of the relocation target.

eld::Expected<uint32_t> getImageLayoutChecksum() const

Returns the 32-bit checksum of the image layout if this function is used when the linker state is AfterLayout; Otherwise returns 0.

Note

This function’s result is only valid when the link state is AfterLayout.

std::string getOutputFileName() const

Returns the output file name of the current link process.

eld::Expected<LinkerScriptRule> createLinkerScriptRule(OutputSection S, const std::string &Annotation)

Create a Linker script rule.

Note

Annotation must not be empty. If annotation is empty, then this function returns an empty LinkerScriptRule object.

Parameters
  • S – Corresponding output section of the linker script rule.

  • Annotation – It is used to create the rule name. It’s also helpful for debugging purposes.

eld::Expected<void> insertAfterRule(plugin::OutputSection O, LinkerScriptRule Rule, LinkerScriptRule RuleToAdd)

Add a linker script rule after an existing rule. A rule describes an input section description.

Note

This function must only be used when the link state is CreatingSections. Behavior of using this function in other linker states is undefined.

Parameters
  • O – Output section of the rule.

  • Rule – Rule after which RuleToAdd have to be inserted.

  • RuleToAdd – Rule that is to be added.

Returns

true if rule is successfully inserted; Otherwise false.

eld::Expected<void> insertBeforeRule(plugin::OutputSection O, LinkerScriptRule Rule, LinkerScriptRule RuleToAdd)

Add a linker script rule before an existing rule.

Note

This function should only be used when the linker state is CreatingSections. Behavior of using this function in other linker states is undefined.

Parameters
  • O – Output section of the rule.

  • Rule – Rule before which RuleToAdd have to be inserted.

  • RuleToAdd – Rule that is to be added.

Returns

true if rule is successfully inserted; Otherwise false.

DEPRECATED void removeSymbolTableEntry (plugin::Symbol S)

Exclude the symbol S from the symbol table.

This function only removes the symbol from the symbol table. It does not remove the symbol content from the output image.

Note

This function can be used in any link state including and upto AfterLayout.

Parameters

SSymbol to remove

eld::Expected<std::vector<plugin::Symbol>> getAllSymbols() const

Returns all symbols.

Note

Currently, the function returns an empty vector for SectionIteratorPlugin and SectionMatcherPlugin.

Note

The function returns all non-section symbol names for OutputSectionIteratorPlugin when linker state is including and upto CreatingSections. The function returns all symbols names, including section symbol names, when the linker state is AfterLayout.

DiagnosticEntry::DiagIDType getFatalDiagID(const std::string &formatStr)

Returns an ID for a fatal error diagnostic with the specified format string.

DiagnosticEntry::DiagIDType getErrorDiagID(const std::string &formatStr)

Returns an ID for an error diagnostic with the specified format string.

DiagnosticEntry::DiagIDType getWarningDiagID(const std::string &formatStr)

Returns an ID for a warning diagnostic with the specified format string.

DiagnosticEntry::DiagIDType getNoteDiagID(const std::string &formatStr) const

Returns an ID for a note diagnostic with the specified format string.

DiagnosticEntry::DiagIDType getVerboseDiagID(const std::string &formatStr)

Returns an ID for a verbose diagnostic with the specified format string.

bool reportDiagEntry(std::unique_ptr<DiagnosticEntry> de)

Issue a diagnostic using DiagnosticEntry.

Returns

true if diagnostic is successfully emitted; Otherwise returns false.

template<class ...Args>
inline bool reportDiag(DiagnosticEntry::DiagIDType id, Args&&... args) const

Report a diagnostic.

DiagnosticBuilder getDiagnosticBuilder(DiagnosticEntry::DiagIDType id) const

Create and return a DiagnosticBuilder for the diagnostic ID ‘id’.

For all cases, reporting diagnostics using ‘LinkerWrapper::report’ should be preferred. DiagnosticBuilder can be beneficial in some cases. One such case is to reduce code-duplication when emitting same family of diagnostics.

DiagnosticBuilder should be used carefully as incorrect usage can cause deadlock in a program. In particular, no two DiagnosticBuilder objects should be in scope at the same time in the same thread.

bool isChunkMovableFromOutputSection(const Chunk &C) const

Allow plugins to determine if a chunk can be moved out of an output section and placed in a different output section.

Note

This function needs to be used by plugins before moving any Chunk as a safety net

Parameters

CChunk

Returns

true if Chunk can be moved

std::string_view getCurrentLinkStateAsStr() const

Returns the string representation of the current link state.

bool isVerbose() const

Returns true if user has requested verbose diagnostics.

eld::Expected<std::vector<Segment>> getSegmentTable() const
Returns

the segment table

eld::Expected<void> applyRelocations(uint8_t *Buf)

Applies relocations to an unrelocated buffer Buf.

eld::Expected<void> doRelocation()

Apply all relocations or return an error.

eld::Expected<DynamicLibrary> loadLibrary(const std::string &LibraryName)

Return a handle to the library LibraryName or an error. LibraryName will be searched using the linker search path including -L directories. First the file called LibraryName will be searched. If it is not found, libLibraryName.so or libraryName.dll on windows will be searched. If neither are found an error is returned.

eld::Expected<void*> getFunction(void *LibraryHandle, const std::string &FunctionName) const
Returns

a handle to the function FunctionName or an error.

std::vector<UnbalancedChunkMove> getUnbalancedChunkRemoves() const

Returns a vector of (Chunk, LinkerScriptRule) pairs for chunks that were removed by the plugin but have not been inserted back to the output image.

std::vector<UnbalancedChunkMove> getUnbalancedChunkAdds() const

Returns a vector of (Chunk, LinkerScriptRule) pairs for chunks that are inserted to a rule but are not removed from their original rule. This typically happens when a plugin inserts a chunk from rule A to rule B but forgets to remove it from rule A.

eld::Expected<void> addChunkToOutput(Chunk C)

Add chunk C to the output. The output section where C lives will be deterimned according to the linker script.

eld::Expected<void> resetOffset(OutputSection O)

Clear the offset for this section to be reassigned later by the linker.

eld::Expected<std::pair<OutputSection, LinkerScriptRule>> getOutputSectionAndRule(Section S)

Return the OutputSection and LinkerScriptRule for a given Input section according to the linker script.

std::optional<std::string> getEnv(const std::string &envVar) const

Returns the value of the environment variable envVar.

eld::Expected<void> linkSections(OutputSection A, OutputSection B) const

Link Section A to B using the sh_link field in the output ELF.

eld::Expected<void> registerCommandLineOption(const std::string &opt, bool hasValue, const CommandLineOptionHandlerType &optionHandler)

Registers the command-line option opt.

optionHandler callback function is invoked for each registered option present in the link command-line.

opt must always start with --. If hasValue is true, then options of the form --<OptionName>=<value> are matched; Otherwise options of the form --<OptionName> are matched.

Note

opt must not match any in-built linker command-line option.

eld::Expected<void> enableVisitSymbol()

Enables VisitSymbol hook. VisitSymbol hook is disabled by default.

eld::Expected<void> setRuleMatchingSectionNameMap(InputFile IF, std::unordered_map<uint64_t, std::string> sectionMap)

Sets rule-matching section name map for the input file IF. Rule matching section name map contains the mapping of section index to the rule-matching section name.

If a section has rule-matching section name, then this name is used, instead of the actual section name, for linker script rule-matching. For example, if for an input file IF, the rule-matching section name map is as shown below, and section with index 3 is ‘.text.foo’, then for linker script rule-matching, then linker will use the name ‘.code.foo’ instead of ‘.text.foo’.

{ 3 -> .code.foo … … }

Note

Rule-matching section map can be set only once per input-file. Setting a rule-matching section name map for an input file is an error if the file already has one.

const std::optional<std::unordered_map<uint64_t, std::string>> &getRuleMatchingSectionNameMap(const InputFile &IF)

Returns the rule-matching section name map for the input file IF.

void showRuleMatchingSectionNameInDiagnostics()

Instruct linker to show rule-matching section name in diagnostics and map-files.

eld::Expected<void> setAuxiliarySymbolNameMap(InputFile IF, const AuxiliarySymbolNameMap &symbolNameMap)

Sets the auxiliary symbol name map for the input file IF. Auxiliary symbol name map contains the mapping of symbol index to the auxiliary symbol name.

Auxiliary symbol names are printed along with the original symbol names in the diagnostics and map-files. The auxiliary symbol names are helpful for providing more meaningful diagnostics.

Auxiliary symbol names do not affect the link behavior.

Note

Auxiliary symbol name map can be set only once per input-file. Setting an auxiliary symbol name map for an input file is an error if the file already has one.

eld::Expected<uint64_t> getOutputSymbolIndex(plugin::Symbol S)

Returns the index of the symbol S in the output image symbol table.

eld::Expected<bool> doesRuleMatchWithSection(const LinkerScriptRule &R, const Section &S, bool doNotUseRMName = false)

Returns true if the rule R matches the section S.

If doNotUseRMName is true, then the section actual name is used for rule-matching instead of the rule-matching name. By default, rule-matching name is preferred over the section name.

This function is thread-safe.

struct UnbalancedChunkMove

Represents an unbalanced chunk move. For unbalanced chunk remove: chunk: The removed chunk rule: Rule from which it was removed.

For unbalanced chunk add: chunk: The added chunk rule: Rule to which it was added.

7.3.2. Plugin Abstract Data Types

7.3.2.1. Chunk

struct Chunk

A section is formed of a set of chunks. Chunk is a handler for one such section chunk. A Chunk object can be used to inspect the properties, symbols and content of a chunk.

Chunk is a wrapper for an internal fragment class. If two Chunk objects both refer to the same underlying fragment, then they represent the same chunk.

Subclassed by eld::plugin::MergeStringChunk

Public Functions

std::string getName() const

Returns the name of the section that contains the chunk. If the object is an empty handler, then returns an empty string.

plugin::InputFile getInputFile() const

Returns the input file handler of the file from which the chunk has originated. If the object is an empty handler, then returns an empty input file handler.

uint32_t getSize() const

Returns the size of the chunk.

uint32_t getAlignment() const

Returns the alignment of the chunk.

plugin::Section getSection() const

Returns the section from which the chunk has originated.

inline eld::Fragment *getFragment() const

Returns the pointer to the underlying fragment object of the Chunk.

const char *getRawData() const

Returns the raw data that the Chunk contains.

std::vector<plugin::Symbol> getSymbols() const

Returns the list of symbols that are defined in this chunk.

inline bool operator<(const Chunk &RHS) const

Pointer comparison between the underlyling fragment pointers of LHS and RHS.

inline bool operator>(const Chunk &RHS) const

Pointer comparison between the underlyling fragment pointers of LHS and RHS.

inline bool operator==(const Chunk &RHS) const

Returns true if both the LHS and RHS represents the same chunk.

inline operator bool() const

Returns true if the underlying fragment pointer is non-null.

bool hasContent() const

Returns true if the underlying fragment pointer is non-null.

bool isProgBits() const

Returns true if the chunk is stored in the image. In ELF, such chunks are from sections of the PROGBITS type.

bool isNoBits() const

Returns true if the chunk is not stored in the image. In ELF, such chunks are from sections of the NOBITS type.

bool isCode() const

Returns true if the chunk contains code. More concretely, return true if the section from which the chunk originates has SHF_EXECINSTR flag set.

bool isAlloc() const

Returns true if the chunk is allocated in memory. In ELF, such chunks are from sections that have the ALLOC attribute.

bool isWritable() const

Returns true if the chunk is writable. In ELF, such chunks are from sections that have the WRITE attribute.

bool isMergeableString() const

Does this chunk contain mergeable strings ?

size_t getAddress() const

Retrieve the address of the Chunk.

std::vector<plugin::Section> getDependentSections() const

Returns a sequence of all the sections that are dependent on the section from which the chunk has originated.

struct Compare

Returns true if the chunks A and B originates from different input sections; Otherwise returns false.

7.3.2.2. LinkerScriptRule

struct LinkerScriptRule

LinkerScriptRule represents an output section command in a linker script. For example:

section {
  .text : {
    *(.text)
    LONG(1)
    _etext = .;
  }
}
In this example, *(.text), LONG(1), and _etext=1, all are output section commands. They are all represented as LinkerScriptRule objects. Here .text is the corresponding output section of the rule.

A LinkerScriptRule object can be used to inspect, and modify linker rules. Rules determine the output image layout and it’s contents.

LinkerScriptRule is a wrapper for an internal RuleContainer class. If two LinkerScriptRule objects have the same underlying RuleContainer object, then both the objects represent the same rule.

Public Functions

bool canMoveSections() const

Returns true if the sections matched by the linker script rule can be moved to another output section; Otherwise returns false.

bool isLinkerInsertedRule() const

Returns true if this rule is inserted by the linker; Otherwise returns false.

bool isKeep() const

Returns true if the rule corresponds to KEEP sections.

bool hasExpressions() const

Returns true if the rule has any expression; Otherwise returns false.

Expressions are symbol assignments.

bool doesExpressionModifyDot() const

Returns true if the expression modifies the location counter (‘.’); Otherwise returns false.

std::string asString() const

Return the rule as a string for diagnostics.

DEPRECATED void addChunk (plugin::Chunk C)

Add chunk C to this rule. All properties specified by the rule will be applied to the chunk C.

Note

A chunk can be a part of only one rule. Therefore, on using this function, the chunk C is removed from any other rule that it was part of.

Note

This function should only be used when the linker state is BeforeLayout. Behavior of using this function in other linker states is undefined.

DEPRECATED void removeChunk (plugin::Chunk C)

Remove chunk C from this rule. No property specified by the rule will be applied to the chunk C.

Note

This function should only be used when the linker state is BeforeLayout. Behavior of using this function in other linker states is undefined.

DEPRECATED void updateChunks (std::vector< plugin::Chunk > C)

Remove all the existing chunks and sections from the rule, and add all the chunks in sequence C to the rule.

Note

This function should only be used when the linker state is BeforeLayout. Behavior of using this function in other linker states is undefined.

DEPRECATED State addChunk (plugin::Chunk C, bool Verify)

If verify is true, then perform verification while adding the chunk; Otherwise simply add the chunk and returns the State::Ok.

Verification makes sure a chunk is not being added multiple times to the rule. Verification step checks for duplication, and if the rule contains the chunk that is to be added, then the function returns State::DuplicateChunk and does not add the chunk to the rule.

Note

This function should only be used when the linker state is BeforeLayout. Behavior of using this function in other linker states is undefined.

Parameters
  • C – chunk to be added

  • Verify – Specifies if verification should be performed or not.

Returns

State::Ok if the verification succeeds; Otherwise return a state that describes the verification failure.

DEPRECATED State removeChunk (plugin::Chunk C, bool Verify)

If verify is true, then perform verification while removing the chunk; Otherwise simply remove the chunk and returns the State::Ok.

Verfication makes sure the rule indeed contains the chunk that is to be removed.

Note

This function should only be used when the linker state is BeforeLayout. Behavior of using this function in other linker states is undefined.

Parameters
  • C – chunk to be removed

  • Verify – Specifies if verification should be performed or not.

Returns

State::Ok if the verification succeeds; Otherwise return a state that describes the verification failure.

DEPRECATED State updateChunks (std::vector< plugin::Chunk > C, bool Verify)

If verify is true, then perform verification while updating chunks; Otherwise simply update chunks and returns the State::Ok.

Verification make sure that initially the rule contained no chunks, and no duplicate chunks are being added.

Note

This function should only be used when the linker state is BeforeLayout. Behavior of using this function in other linker states is undefined.

Parameters
  • C – chunk to be removed

  • Verify – Specifies if verification should be performed or not.

Returns

State::Ok if the verification succeeds; Otherwise return a state that describes the verification failure.

std::vector<plugin::Chunk> getChunks() const

Return chunks associated with this linker script rule.

std::vector<plugin::Section> getSections()

Return sections associated with the linker script rule.

std::vector<plugin::Section> getMatchedSections() const

Return all sections matched by this rule including garbage collected sections.

std::vector<plugin::Chunk> getChunks(plugin::Section S)

Get all the Chunks in the rule that correspond to Section S.

inline eld::RuleContainer *getRuleContainer() const

Return the corresponding RuleContainer of the linker script rule.

inline operator bool() const

Returns true if the object has a corresponding non-null RuleContainer object; Otherwise returns false.

inline bool operator()(const LinkerScriptRule &A, const LinkerScriptRule &B) const

Returns true if A and B have different underlying RuleContainer objects.

inline bool operator<(const LinkerScriptRule &RHS) const

Pointer comparision between the underlying RuleContainer handle of LHS and RHS.

inline bool operator>(const LinkerScriptRule &RHS) const

Pointer comparision between the underlying RuleContainer handle of LHS and RHS.

inline bool operator==(const LinkerScriptRule &RHS) const

Returns true if LHS and RHS have the same RuleContainer objects.

7.3.2.3. OutputSection

struct OutputSection

OutputSection is a handler for an output section. An OutputSection object can be used to inspect an output section, and get it’s associated linker script rules.

It is a wrapper for an internal OutputSectionEntry class. If two OutputSection objects points to the same underlying OutputSectionEntry object, then they both represent the same output section.

Public Functions

std::string getName() const

Returns the name of the output section.

If the object is an empty handler, then returns an empty string.

uint64_t getAlignment() const

Returns the alignment of the output section.

uint64_t getFlags() const

Returns the section attribute flags. Each bit of flag defines some attribute. If a flag bit is set, then the attribute which corresponds to that bit is on for the section. Otherwise, the attribute is off and does not apply. Examples of section attributes: SHF_WRITE, SHF_ALLOC, SHF_EXECINSTR, and SHF_MASKPROC etc.

uint64_t getType() const

Returns the section semantics type. Section type specifies the section semantics e.g. SHT_PROGBITS, SHT_NOBITS, SHT_NOTE, etc.

uint64_t getIndex() const

Returns the Index of the output section. If the object is an empty handler, then returns 0.

uint64_t getSize() const

Returns the number of bytes that the section occupies in the file.

std::vector<plugin::LinkerScriptRule> getLinkerScriptRules()

Returns all linker script rules for the output section.

inline const eld::OutputSectionEntry *getOutputSection() const

Returns a pointer to the underlying OuputSectionEntry object. This can be used as a unique identifier for the output section.

eld::Expected<std::optional<Segment>> getLoadSegment(const LinkerWrapper &LW) const
Returns

The load segment for this output section, if one exists. This API should only be called in CreatingSections or AfterLayout linker states.

eld::Expected<std::vector<Segment>> getSegments(const LinkerWrapper &LW) const
Returns

All segments this OutputSection belongs to. This API should only be called in CreatingSections or AfterLayout linker states.

inline eld::OutputSectionEntry *getOutputSection()

Returns a pointer to the underlying OutputSectionEntry object. This can be used as a unique identifier for the output section.

eld::Expected<uint64_t> getVirtualAddress(const LinkerWrapper&) const

Returns the virtual address of the output section.

eld::Expected<uint64_t> getPhysicalAddress(const LinkerWrapper&) const

Returns the physical address of the output section.

inline operator bool() const

Returns true if the object represents a non-null output section.

inline bool operator()(const OutputSection &A, const OutputSection &B) const

Returns true if A and B represents different output sections.

inline bool operator<(const OutputSection &RHS) const

Pointer comparison between the underlying OutputSectionEntry handles of LHS and RHS.

inline bool operator>(const OutputSection &RHS) const

Pointer comparison between the underlying OutputSectionEntry handles of LHS and RHS.

inline bool operator==(const OutputSection &RHS) const

Returns true if both the LHS and RHS objects represents the same output sections.

eld::Expected<uint64_t> getOffset() const

Return the offset of this OutputSection, or an error if it has not been assigned one.

eld::Expected<void> setOffset(uint64_t Offset, const LinkerWrapper &LW)

Set the output offset of this section, or error.

bool isNoBits() const

Returns true if this section is of type SHT_NOBITS (the section occupies no file space).

bool isDiscard() const

Returns true if the section is being discarded.

bool isCode() const

Returns true if the section contains code with SHF_EXECINSTR flag set.

bool isAlloc() const

does this section have the SHF_ALLOC flag

std::vector<Stub> getStubs() const

Returns a list of all stubs created for this output section.

Expected<void> setPluginOverride(Plugin *P, const LinkerWrapper &LW)

Plugin P assumes repsonsibility for this section. Some layout warnings/errors will be ignored for such sections (e.g. “loadable section

`foo` not in any load segment”). This API may only be used in

CreatingSegments state.

7.3.2.4. Section

struct Section

Section is a handler for an ELF input section. A Section object can be used to inspect section properties, chunks and symbols. It can also be used to discard a section.

Section is a wrapper for an internal Section class. If two objects have the same underlying Section object, then they both represents the same section.

Public Functions

std::string getName() const

Returns the name of the section. If the object is an empty handler, then returns an empty string.

inline SectionType getType() const

Returns the type of the input section. If the object is an empty handler, then returns SectionType::Default.

plugin::InputFile getInputFile() const

Returns the InputFile of the input section. If the object is an empty handler, then returns an empty InputFile object.

uint32_t getIndex() const

Returns index of the section in the input file. If the object is an empty handler, then returns 0xFFFFFFFF.

uint32_t getSize() const

Returns the size of the section.

bool isDiscarded() const

Returns true if the section is being discarded.

bool isGarbageCollected() const

Returns true if the section is garbage collected.

uint32_t getAlignment() const

Returns the alignment of the section if the object.

bool matchPattern(const std::string &Pattern) const

Returns true if the section name matches the pattern Pattern.

Note

Here, pattern matching follows unix glob style pattern matching.

Parameters

Pattern – glob pattern

Returns

true if the section name matches the pattern Pattern; Otherwise false.

std::vector<plugin::Symbol> getSymbols() const

Returns a sequence of symbols contained by this section.

std::vector<plugin::Chunk> getChunks() const

Returns a sequence of chunks contained by this section.

void markAsDiscarded()

Discard the section from the output object file.

Warning

This is a dangerous function, if not used carefully, it can discard important information, that can result in invalid output object file. TODO: What exactly discarding a section means?

bool isProgBits() const

Returns true if the section is stored in the image. In ELF, such sections are of the PROGBITS type.

bool isNoBits() const

Returns true if the section is not stored in the image. In ELF, such sections are of the NOBITS type.

bool isCode() const

Returns true if the section contains code. More precisely, it returns true if the section has SHF_EXECINSTR flag set.

bool isAlloc() const

Returns true if the section is allocated in memory. In ELF, such sections have the ALLOC attribute.

bool isWritable() const

Returns true if the section is writable. In ELF, such sections have the WRITE attribute.

inline eld::Section *getSection() const

Return a pointer to the underlying section handle.

This can be used as a unique identifier for the section.

plugin::OutputSection getOutputSection() const

Returns the output section for this section.

LinkerScriptRule getLinkerScriptRule() const

Return the linker script rule that is matched for this section.

std::vector<plugin::Section> getDependentSections() const

Returns a sequence of sections that are dependent on this section.

inline operator bool() const

Returns true if the object represents a non-null section.

inline bool operator()(const Section &A, const Section &B) const

Returns true if A and B represents different sections.

inline bool operator<(const Section &RHS) const

Pointer comparision between the underlying section handlers.

inline bool operator>(const Section &RHS) const

Pointer comparision between the underlying section handlers.

inline bool operator==(const Section &RHS) const

Return true if both the lhs and rhs represents the same section.

7.3.2.5. Use

struct Use

Use represents references from a chunk. In ELD terminology, source address and source chunk of the Use are the places where relocation has to be performed. And target address and target chunk are the places which contain the relocation symbol definition. Use can be used to inspect symbol references.

Use is a wrapper class for an internal relocation class. If two Use objects have the same underlying relocation objects, then the two Use objects represents the same Use.

Public Types

enum Status

Symbol status.

Values:

enumerator Ok
enumerator SymbolDoesNotExist
enumerator Error

Public Functions

std::string getName() const

If the Use represents a valid relocation, then return the symbol name described by this Use; Otherwise return an empty string. The symbol name is returned as how it is recorded in the input ELF file.

DEPRECATED Chunk getChunk () const

If the Use represents a valid relocation, then returns the chunk that defines the symbol represented by this Use; Otherwise returns an empty Chunk object. DEPRECATED in favor of Use::getTargetChunk

Chunk getSourceChunk() const

If the Use represents a valid relocation, then returns the chunk that contain the symbol reference represented by this Use; Otherwise returns an empty Chunk object.

plugin::Symbol getSymbol() const

If the Use represents a valid relocation, then returns the corresponding symbol info of the relocation; Otherwise returns a null Symbol object.

inline eld::Relocation *getRelocation() const

Returns a pointer to the underlying relocation object.

Use::Status resetSymbol(plugin::Symbol S)

Reset the symbol info to a different symbol info object.

Parameters

SSymbol that should replace the already existing symbol.

Returns

Status of the replacement.

uint32_t getType() const

If the Use has a non-null relocation handle, then returns the relocation type; Otherwise returns UINT32_MAX.

off_t getOffsetInChunk() const

If the Use represents a valid relocation, then returns the source chunk offset in it’s corresponding section; Otherwise returns -1.

size_t getSourceAddress() const

If the Use represents a valid relocation; then return the address of the Use &#8212; target address of relocation; Otherwise returns UINT64_MAX.

plugin::Chunk getTargetChunk() const

If the Use represents a valid relocation; then returns the chunk that defines the symbol represented by this Use; Otherwise returns an empty Chunk object.

off_t getTargetChunkOffset() const

If the Use has a non-null relocation handle; then returns the chunk that defines the symbol represented by this Use;

inline operator bool() const

Returns true if the Use has a non-null relocation handle.

inline bool operator()(const Use &A, const Use &B) const

Returns true if the Use A and B represent different Uses.

inline bool operator<(const Use &RHS) const

Pointer comparison between relocation handles of LHS and RHS.

inline bool operator>(const Use &RHS) const

Pointer comparison between relocation handles of LHS and RHS.

inline bool operator==(const Use &RHS) const

Returns true if the Use LHS and RHS represents the same use.

7.3.2.6. Symbol

struct Symbol

Symbol is a handler for a linker symbol. Symbol can be used to inspect a symbol.

Symbol is a wrapper for the internal ResolveInfo class. If two Symbol objects have the same underlying ResolveInfo object, then they both represent the same symbol.

Public Functions

Chunk getChunk() const

Returns the chunk that defines the symbol.

If the object is an empty handler, then returns an empty Chunk object.

std::string getName() const

Returns the symbol name.

If the object is an empty handler, then returns an empty string.

bool isLocal() const

Returns true if the symbol is local.

bool isWeak() const

Returns true if the symbol is weak.

bool isGlobal() const

Returns true if the symbol is global.

bool isUndef() const

Returns true if the symbol is undefined.

bool isCommon() const

Returns true if the symbol is common.

bool isSection() const

Returns true if the symbol is section.

bool isFunction() const

Returns true if the symbol is function.

bool isObject() const

Returns true if the symbol is object.

bool isFile() const

Returns true if the symbol is File.

bool isNoType() const

Returns true if the symbol is NoType.

bool isGarbageCollected() const

Returns true if the symbol got garbage collected.

std::string getResolvedPath() const

Returns the resolved path of a Symbol.

uint32_t getSize() const

Returns the symbol size.

A symbol size is the number of bytes contained in the object represented by the symbol.

size_t getValue() const

Returns the symbol value.

Please note that:

size_t getAddress() const

Get the Symbol Address. Most times the symbol value will be equal to the address of the symbol. If there is a need to access the address of the symbol before a symbol gets finalized, getAddress can be utilized.

off_t getOffsetInChunk() const

Returns the symbol’s offset in chunk.

inline eld::ResolveInfo *getSymbol() const

Return a pointer to the underlying ResolveInfo object. This can be used as a unique identifier for the symbol.

inline operator bool() const

Conversion Operator.

inline bool operator()(const Symbol &A, const Symbol &B) const

Returns true if A and B represents different symbols.

inline bool operator<(const Symbol &RHS) const

Pointer comparison between the underlying ResolveInfo handles of LHS and RHS.

inline bool operator>(const Symbol &RHS) const

Pointer comparison between the underlying ResolveInfo handles of LHS and RHS.

inline bool operator==(const Symbol &RHS) const

Returns true if LHS and RHS represents the same symbol.

7.3.2.7. INIFile

struct INIFile

INIFile represents an ini configuration file. It provides APIs to easily inspect and modify the INI configuration.

Public Functions

explicit INIFile(const std::string FileName)

Initialize an INIFile.

void addSection(const std::string &section)

Add an empty section to this file if does not currently exist.

void insert(const std::string &section, const std::string &K, const std::string &V)

Insert a key-value pair into a given section If the section does not exist, it is automatically created.

Parameters
  • section – Name of the section in which key-value pair has to be inserted

  • K – Key

  • V – Value

bool containsSection(const std::string &sectionName) const
Returns

true if a section with name sectionName is found in this file; Otherwise false.

bool containsItem(const std::string &sectionName, const std::string &key) const
Returns

true if the section sectionName contains the key named key; Otherwise false.

std::vector<std::string> getSections() const
Returns

vector of all section names in this file

std::vector<std::pair<std::string, std::string>> getSection(const std::string Section) const
Parameters

Section – Name of the section of the file, minus any brackets

Returns

A vector of all key/value pairs in a given section of this file If the provided section does not exist or is empty, an empty vector is returned

std::string getValue(const std::string Section, const std::string Item)

Get the value of an item in a given section of this file

Parameters
  • Section – Name of the section, without brackets

  • Item – Name of an item within the section

Returns

Value associated with Item in Section, if it exists If provided Section or Item does not exist, an empty string is returned

inline ErrorCode getErrorCode()
Returns

INIFile::ErrorCode depending on the last error

inline void setLastError(ErrorCode e)

Set last error.

std::string getLastErrorAsString()

Return last error as string.

operator bool() const

return true if file is non-empty.

inline eld::INIReader *getReader() const

Return the underlying INI Reader pointer for the file.

Public Static Functions

static eld::Expected<INIFile> Create(const std::string &filename)

Creates a INIFile object for filename. INIFile object can be used to easily perform suitable read and write operations to the INI file.

Returns

eld::Expected<INIFile> contains INIFile if initialisation of INIFile object was successful; Otherwise it contains a diagnostic object describing the error.

7.3.2.8. InputFile

struct InputFile

InputFile represents an input file. Input file can be an object file, a linker script, or anything else that the the linker can work with. An InputFile object can be used to inspect input file properties, and contents.

Subclassed by eld::plugin::BitcodeFile

Public Functions

std::string getFileName() const

Returns the file name of the input file if the object has an input file; Otherwise returns an empty string.

bool hasInputFile() const

Returns true if the object has an input file; Otherwise returns false.

bool isArchive() const

Returns true if the input is an archive member; Otherwise returns false.

bool isBitcode() const

Returns true if the input is LLVM bitcode; Otherwise returns false.

std::string getMemberName() const

If the input file is an archive member, return the member name; Otherwise return an empty string.

std::vector<plugin::Symbol> getSymbols() const

Returns a sequence of all the symbols that are defined in this file.

std::vector<plugin::Section> getSections() const

Returns a sequence of all the sections in the input file.

std::optional<plugin::Section> getSection(uint64_t i) const

Get section at index i.

inline operator bool() const

Returns true if the object has an input file.

const char *getMemoryBuffer() const

Returns a pointer to the data of the input file.

size_t getSize() const

Returns the input file size.

bool isInternal() const

Returns true if the input file is an internal input file.

bool isArchiveMember() const

Returns ture if the input file is an archive member.

std::optional<plugin::InputFile> getArchiveFile() const

Returns the archive file that contains the input if the input is an archive member; Otherwise returns std::nullopt.

inline bool operator()(const InputFile &A, const InputFile &B) const

Returns true if A and B represents different input files.

inline bool operator<(const InputFile &RHS) const

Pointer comparison between the underlying input file handles of LHS and RHS.

inline bool operator>(const InputFile &RHS) const

Pointer comparison between the underlying input file handles of LHS and RHS.

inline bool operator==(const InputFile &RHS) const

Returns true if both LHS and RHS represents the same input file.

inline eld::InputFile *getInputFile() const

Returns the underlying input file handler. This can be used as a unique identifier for the input file.

uint32_t getOrdinal() const

Return the input ordinal which is the order in which the linker visited this input file

std::string decoratedPath() const

TODO.

7.3.2.9. PluginData

struct PluginData

PluginData provide a way for storing data and communicating between plugins.

Public Functions

inline operator bool() const

Conversion Operator.

inline bool operator()(const PluginData &A, const PluginData &B) const

Operators

7.3.2.10. AutoTimer

struct AutoTimer

Plugin Profiling support.

Public Functions

void start()

Start Timer.

void end()

End Timer.

inline operator bool() const

Conversion Operator.

inline bool operator()(const AutoTimer &A, const AutoTimer &B) const

Operators

7.3.2.11. Timer

struct Timer

Public Functions

void start()

Start Timer.

void end()

End Timer.

inline operator bool() const

Conversion Operator.

inline bool operator()(const Timer &A, const Timer &B) const

Operators

7.3.2.12. RelocationHandler

struct RelocationHandler

RelocationHandler handles relocations. It can be to inspect and compare relocations.

Public Functions

uint32_t getRelocationType(std::string Name) const

Get Relocation Type for a relocation.

std::string getRelocationName(uint32_t Type) const

Get the Relocation name from its type.

inline operator bool() const

Conversion Operator.

inline bool operator()(const RelocationHandler &A, const RelocationHandler &B) const

Operators

7.3.3. LinkerPluginConfig

class LinkerPluginConfig

LinkerPluginConfig allows to inspect and modify relocations. Each LinkerPluginConfig object has a corresponding plugin::Plugin object. LinkerPluginConfig provides callback hooks that are called for each registered relocation type. Relocation types must be registered via LinkerWrapper::RegisterReloc.

Public Functions

virtual void Init() = 0

The Init callback hook is called before any relocation callback hook call. It is used for initialization purposes. Typically, plugins register relocation types in the init callback function.

virtual void RelocCallBack(plugin::Use U) = 0

RelocCallBack is the callback hook function that the linker calls for each registered relocation.

This function must be thread-safe as the linker may handle relocations parallelly and thus may make calls to this function parallelly as well.

Note

There can be at most one registered relocation handler for each relocation type per plugin.

inline plugin::Plugin *getPlugin() const

Return the corresponding plugin.

Protected Attributes

plugin::Plugin *Plugin

Pointer to the corresponding plugin object.

Warning

Please do not modify the plugin object directly.

7.3.4. Utility Data Structures

7.3.4.1. JSON Objects

struct SmallJSONObject

Represents a JSON Object consisting of key value pairs. This class is append only. Items will appear in the order in which they were inserted

Public Functions

SmallJSONObject(SmallJSONObject &&Other)

Move constructor.

SmallJSONObject(const uint32_t InitialSize = 0)

Create a JSONObject and reserve InitialSize bytes for its string representation

void finish()

Insert the closing brace (‘}’) and complete the string representation of this object. Every SmallJSONObject must be finish()’ed in order to produce valid JSON.

bool isFinished() const

Has this Object been finish()’ed?

bool empty() const

Is this object empty.

struct SmallJSONArray

An append-only class represeting a heterogenous array of JSON values. Items are stored in insertion order.

Public Functions

SmallJSONArray(SmallJSONArray &&Other)

Move constructor.

SmallJSONArray(const uint32_t InitialSize = 0)

Create a SmallJSONArray and reserve InitialSize bytes for its string representation

void push_back(SmallJSONValue &&V)

Add a value to the string representing this JSON Array.

void finish()

Insert the closing bracket (‘]’) and complete the string representation of this Array. Every SmallJSONArray must be finish()’ed in order to produce valid JSON.

bool isFinished() const

Has this Array been finish()’ed?

bool empty() const

Is this object empty?

struct SmallJSONValue

A Class representing a value representible in JSON. Includes Objects, Arrays, boolean, floating point, integral, string, and null types

Public Functions

SmallJSONValue(SmallJSONObject &&Obj)

Create a SmallJSONValue from a SmallJSONObject.

SmallJSONValue(SmallJSONArray &&Arr)

Create a SmallJSONValue from SmallJSONArray.

SmallJSONValue(bool b)

Create a SmallJSONValue representing true or false.

SmallJSONValue(const std::string S)

Create a SmallJSONValue representing a JSON string.

SmallJSONValue(std::nullptr_t null)

Create a SmallJSONValue representing a JSON null.

template<typename T, typename = std::enable_if_t<std::is_integral<T>::value>, typename = std::enable_if_t<!std::is_same<T, bool>::value>>
inline SmallJSONValue(T I)

Create a SmallJSONValue representing an integer type. Must be non-narrowing convertible to int64_t

template<typename T, typename = std::enable_if_t<std::is_floating_point<T>::value>, double* = nullptr>
inline SmallJSONValue(T D)

Create a SmallJSONValue representing a floating point type. Must be non-narrowing convertible to double

const std::string &str()

Get this JSONValue as a string in JSON format The string will be as compact as possible without any formatting or indentation

const uint8_t *getData() const

Get an unsigned integer pointer to raw data of the JSON object.

eld::Expected<plugin::MemoryBuffer> getMemoryBuffer(const std::string &BufferName)

Get a memory buffer for containing data.

7.3.4.2. TarWriter

class TarWriter

A utility class for creating tar archives.

Public Functions

eld::Expected<void> addBufferToTar(plugin::MemoryBuffer &buffer) const

Adds MemoryBuffer contents to tar. After tar is updated, the buffer is destroyed. NOTE: This function is not thread safe.

7.3.4.3. ThreadPool

class ThreadPool

A ThreadPool for asynchronous parallel execution on a defined number of threads.

The pool keeps a vector of threads alive, waiting on a condition variable for some work to become available.

Public Functions

template<typename Function, typename ...Args>
inline std::shared_future<void> run(Function &&F, Args&&... ArgList)

Run a function F in a thread pool.

template<typename Function>
inline std::shared_future<void> run(Function &&F)

Run a function F in a thread pool.

void wait()

Blocking wait for all the threads to complete and the queue to be empty.

7.3.5. Plugin Diagnostic Framework

Plugin diagnostic framework provides a uniform and consistent solution for reporting diagnostics from plugins. It is recommended to avoid custom solutions for printing diagnostics from a plugin.

First, let’s go over some of the key benefits of using the Plugin Diagnostic Framework. After that, we’ll see how to effectively use the framework.

The framework allows for creating and reporting diagnositcs on the fly. Diagnostics can be reported with different severities such as Note, Warning, Error and more. Each severity has a unique color, and diagnostics are prefixed with “PluginName:DiagnosticSeverity”.

The linker keeps track of diagnostics emitted from the diagnostic framework. This is required to maintain extensive logs for diagnostic purposes. The framework also adjusts diagnostic behavior based on linker command-line options that affect diagnostics. For example, if the --fatal-warnings option is enabled, then warnings will be converted to fatal errors. If the -Werror option is used, warnings are promoted to regular errors instead of fatals.

The framework is thread-safe. Thus, diagnostics can be reported safely from multiple threads simultaneously. This is crucial in situations where thread-safety is neessary. In such cases, C++ std::cout and std::cerr output streams cannot be used, as they are not thread-safe.

That’s enough about the theories. Now, let’s take a look at how to use the Plugin Diagnostic Framework.

The linker assigns a unique ID to each diagnostic template. A diagnostic template has a diagnostic severity and a diagnostic format string. Diagnostic template unique IDs are necessary for creating and reporting diagnostics. The code below demonstrates how to obtain a diagnostic ID for a diagnostic template.

// There are similar functions for other diagnostic severities.
// Linker is a LinkerWrapper object.
DiagnosticEntry::DiagIDType errorID = Linker->getErrorDiagID("Error diagnostic with two args: %0 and %1");
DiagnosticEntry::DiagIDType warnID = Linker->getWarningDiagID("Warning diagnostic with one arg: %0");

%0, %1 and so on in diagnostic format string are replaced by diagnostic arguments. Diagnostic arguments must be provided when reporting a diagnostic.

The below code demonstrates how to report a diagnostic using a diagnostic ID.

// arguments can be of any type. 'LinkerWrapper::reportDiag' is a
// variadic template function.
Linker->reportDiag(errorID, arg1, arg2);
Linker->reportDiag(warnID, arg1);

7.3.5.1. DiagnosticEntry

DiagnosticEntry packs complete diagnostic information, and can be used to pass diagnostics from one location to another. Many plugin framework APIs use DiagnosticEntry to return errors to the caller, where they can be properly handled.

// diag represents a complete diagnostic.
// diagID encodes diagnostic severity and diagnostic format string.
DiagnosticEntry diag(diagID, {arg1, arg2, ...});

7.3.5.2. eld::Expected<ReturnType>

Many plugin framework APIs return values of type eld::Expected<ReturnType>. At any given time, eld::Expected<ReturnType> holds either an expected value of type ReturnType or an unexpected value of type std::unique_ptr<eld::plugin::DiagnosticEntry>. Returning the error to the caller allows plugin authors to decide how to best handle a particular error for their use case. A typical usage pattern for this is.

eld::Expected<eld::plugin::INIFile> readFile = Linker->readINIFile(configPath);
if (!readFile) {
  if (readFile.error()->diagID() == eld::plugin::Diagnostic::errr_file_does_not_exit) {
    // handle this particular error
    // ...
  } else {
    // Or, simply report the error and return.
    Linker->reportDiagEntry(std::move(readFile.error()));
    return;
  }
}

eld::plugin::INIFile file = std::move(readFile.value());

7.3.5.3. Overriding Diagnostic Severity

Diagnostic severity can be overriden by using DiagnosticEntry subclasses. DiagnosticEntry has subclasses for each diagnostic severity level. Let’s explore how to use them to override diagnostic severity.

eld::Expected<eld::plugin::INIFile> readFile = Linker->readINIFile(configPath);
eld::plugin::INIFile file;
if (readFile)
  file = std::move(readFile.value());
else {
  // Let's report the error as a Note, and move on by using a default INI file.
  eld::plugin::NoteDiagnositcEntry noteDiag(readFile.error()->diagID(), readFile.error()->args());
  Linker->reportDiagEntry(noteDiag);
  file = DefaultINIFile();
}

7.3.5.4. Diagnostic Framework types API reference

class DiagnosticBuilder

A light-weight helper class to produce diagnostics.

This is created by LinkerWrapper::getDiagnosticBuilder, and it allows to add arguments to the diagnostic in a cout style as described below:

Linker->getDiagnosticBuilder(id) << arg1 << arg2

DiagnosticBuilder object should always be used as a temporary object. This ensures that the diagnostics are emitted when intended. This is because diagnostics are emitted when the DiagnosicBuilder object is destructed, and temporary objects are destructed when their parent expression is fully evaluated. On the other hand, if DiagnosticBuilder object is stored in a variable, then the diagnostic won’t be emitted until the variable goes out of scope. For example:

    {
      auto builder = Linker->getDiagnosticBuilder(id);
      builder << arg1 << arg2;  // diagnostic would not be emitted at this
      // ...                    // point.
      // ...
//  } // diagnostic is emitted at this point.

Public Functions

DiagnosticBuilder(const DiagnosticBuilder&) = delete

DiagnosticBuilder should not be copied. If it is copied, then multiple DiagnosticBuilder object would represent the same diagnostic. This would lead to multiple DiagnosticBuilder object trying to emit the same diagnostic.

const DiagnosticBuilder &operator<<(const std::string &pStr) const

Add string argument to the diagnostic.

const DiagnosticBuilder &operator<<(const char *pStr) const

Add C-style string argument to the diagnostic.

const DiagnosticBuilder &operator<<(int pValue) const

Add integer argument to the diagnostic.

const DiagnosticBuilder &operator<<(unsigned int pValue) const

Add unsigned int argument to the diagnostic.

const DiagnosticBuilder &operator<<(long pValue) const

Add long int argument to the diagnostic.

const DiagnosticBuilder &operator<<(unsigned long pValue) const

Add unsigned long argument to the diagnostic.

const DiagnosticBuilder &operator<<(unsigned long long pValue) const

Add unsigned long long argument to the diagnostic.

const DiagnosticBuilder &operator<<(bool pValue) const

Add bool argument to the diagnostic.

class DiagnosticEntry

DiagnosticEntry represents a diagnostic. It allows to conveniently pass diagnostics from one function to another.

Each diagnostic ID has an associated severity. ‘Severity’ specified in DiagnosticEntry overrides the default severity associated with a diagnostic ID. If no ‘Severity’ is specified, then the default severity associated with a diagnostic ID is used.

Subclassed by eld::plugin::ErrorDiagnosticEntry, eld::plugin::FatalDiagnosticEntry, eld::plugin::NoteDiagnosticEntry, eld::plugin::VerboseDiagnosticEntry, eld::plugin::WarningDiagnosticEntry

Public Functions

inline explicit operator bool() const

Returns true if the object contains an error.

inline DiagIDType diagID() const

Returns diagnostic ID.

inline std::vector<std::string> &args()

Returns diagnostic arguments.

bool isWarning() const

Returns true if the diagnostic entry represents a warning.

bool isVerbose() const

Returns true if the diagnostic entry represents a verbose message.

bool isNote() const

Returns true if the diagnostic entry represents a note.

bool isError() const

Returns true if the diagnostic entry represents an error.

bool isFatal() const

Returns true if the diagnostic entry represents a fatal error or fatal warning

class FatalDiagnosticEntry : public eld::plugin::DiagnosticEntry

FatalDiagnosticEntry subclass allows to easily create fatal diagnostic entry.

class ErrorDiagnosticEntry : public eld::plugin::DiagnosticEntry

ErrorDiagnosticEntry subclass allows to easily create error diagnostic entry.

class WarningDiagnosticEntry : public eld::plugin::DiagnosticEntry

WarningDiagnosticEntry subclass allows to easily create warning diagnostic entry.

class NoteDiagnosticEntry : public eld::plugin::DiagnosticEntry

NoteDiagnosticEntry subclass allows to easily create note diagnostic entry.

class VerboseDiagnosticEntry : public eld::plugin::DiagnosticEntry

VerboseDiagnosticEntry subclass allows to easily create verbose diagnostic entry.