blob: 0b7756df54109362d1cb15e1727bda3289d7fdb7 [file] [log] [blame] [view] [edit]
# ELF Loading & Dynamic Linking Template Library (`elfldltl`)
This library provides a toolkit of C++ template APIs for implementing ELF
dynamic linking and loading functionality. It uses C++ namespace `elfldltl`.
The library API supports either 32-bit or 64-bit ELF with either little-endian
or big-endian byte order, via template parameters. Thus it is suitable for
cross-tools without assumptions about host machine or operating system details,
as well as for ELF target build environments of various sorts.
## Format layouts and constants
The library provides the ELF format layouts and constants in a modern C++ API
using canonical style. It does not intend to be an exhaustive API for all of
the ELF format. It provides the full range of data structures and constants
used in dynamic linking and loading, and some others that are of use in related
tools. It does not provide full details needed for compilers, linkers,
debuggers, etc. In some instances it defines all constants of a particular
type, while in others it defines only the subset actually used or supported by
the toolkit. It provides details from the formal ELF specification and for de
facto standard GNU and LLVM extensions on the same footing. The constants and
data structures largely mimic the spellings used in the ELF specification,
which come from the traditional `<elf.h>` C API. However, these definitions
use C++ scoping and canonical identifier styles that do not overlap with it.
The generic ELF format constants are defined in
[`<lib/elfldltl/constants.h>`](include/lib/elfldltl/constants.h). These are
mostly `enum class` types that apply to all format variants and machines.
Types selecting format variant and machine also include convenient `kNative`
aliases for the native platform being compiled for.
ELF data layouts are defined in
[`<lib/elfldltl/layout.h>`](include/lib/elfldltl/layout.h). These are provided
as C++ struct types within the `elfldltl::Elf` template class, which is
parameterized by class (32-bit vs 64-bit) and data format (byte order) with
default template arguments matching the native platform being compiled for.
### Field accessors
ELF format data types are defined using a simple set of generic wrapper
template types for defining fields, defined in
[`<lib/elfldltl/field.h>`](include/lib/elfldltl/field.h). This API can also be
used directly for other data structures in ELF sections or in memory for which
doing access across bit widths and/or byte orders may be useful.
The wrapper types used for fields have the same exact ABI layout as a specified
underlying integer type. Their API behavior as C++ objects is roughly like a
normal field of a given integer or `enum` type, in that they are implicitly
convertible to and from that type and can be compared to it for equality. In
contexts where the C++ type is flexible, these implicit conversions may not be
sufficient and these objects do not fully emulate an integer or `enum` type.
So they also provide direct accessor methods via `field.get()` or `field()`
(i.e. calling the field as a function of no arguments).
## Note parser
[`<lib/elfldltl/note.h>`](include/lib/elfldltl/note.h) provides a parser for
the ELF note format found in `PT_NOTE` segments or `SHT_NOTE` sections. It
provides a convenient container-view / iterator API across a note segment in
memory. The "elements" of the virtual container provide easy access to the
note name (vendor) and description (payload) bytes using `string_view` and
`span` style types, and a field accessor for the 32-bit type field. The note
format is the same across 32-bit and 64-bit ELF files, so the note parser's
template classes are actually parameterized only by the byte order. But the
canonical access to the API is via the `elfldltl::Elf` template class for the
specific format variant, which has the `Note` and `NoteSegment` types.
## Introspection
[`<lib/elfldltl/self.h>`](include/lib/elfldltl/self.h) provides accessors for a
program or shared library to refer to its own ELF data structures at runtime
using link-time references. Both 32-bit and 64-bit formats are supported
independent of the native pointer size, as is dynamic selection between the two
in case the 32-bit format is used to size-optimize 64-bit binaries. These APIs
are useful for implementing static PIE self-relocation and similar cases.
## Relocation
[`<lib/elfldltl/relocation.h>`](include/lib/elfldltl/relocation.h) provides
decoders for the relocation metadata formats. This provides straightforward
iterable C++ container views for the various kinds of relocation records.
[`<lib/elfldltl/machine.h>`](include/lib/elfldltl/machine.h) provides a uniform
API for the machine-specific format constants needed for dynamic relocation and
TLS layout via a template class parameterized by machine. Each specialization
provides a consistent API for the constants whose values (and presence) vary by
machine. Only the constants related to machines and relocation types supported
by the toolkit are provided.
## Symbol table
[`<lib/elfldltl/symbol.h>`](include/lib/elfldltl/symbol.h) provides access to
the dynamic symbol table of an ELF file. It provides C++ container views for
the symbol table and the hash tables. It handles symbol name string hashing
and hash table lookup.
## Dynamic Section
[`<lib/elfldltl/dynamic.h>`](include/lib/elfldltl/dynamic.h) provides a
framework for examining the `PT_DYNAMIC` metadata in a single pass using a
mix-and-match variety of observer objects looking for different kinds of
entries. The toolkit provides observer object types for some common tasks.
Custom observer objects can be implemented easily.
## "Remotable" pointers
['<lib/elfldltl/abi-ptr.h>`](include/lib/elfldltl/abi-ptr.h) and
['<lib/elfldltl/abi-span.h>`](include/lib/elfldltl/abi-span.h) provide an
abstraction for pointer types and `std::span`-style types. The purpose of
these is to define data structure layouts that can be populated from outside
the address space where they will be used. This is used to implement the
"passive ABI" concept that enables out-of-process dynamic linking to be
indistinguishable from in-process dynamic linking for application code. See
[`//sdk/lib/ld`](/sdk/lib/ld) for a more thorough explanation.
A subset of the class APIs representing information of use in this kind of ABI
are defined using `elfldltl::AbiPtr` and related template types. These classes
take an extra "traits" template parameter that's passed along to the
`elfldltl::AbiPtr` template to facilitate duplicating the data structure from
one address space and pointer encoding to another. There is a default that
boils down to using normal pointer and integer types under the hood, so this
can generally be ignored by users of these classes. When these classes are
instantiated using different traits as part of the "remoting" process, those
class objects can't really be used with all the methods supported by the
default instantiations--they're really just for the mechanics of remoting.
**TODO(fxbug.dev/121817):** Remoting is not implemented yet.