mirror of
https://github.com/JakeHillion/drgn.git
synced 2024-12-23 17:53:07 +00:00
1d4854a5bc
After the libdwfl conversion, we apply ELF relocations with libdwfl
instead of our homegrown implementation. However, libdwfl is much slower
at it than the previous implementation. We can work around this by
(again) applying ELF relocations ourselves for architectures that we
care about (x86-64, to start). For other architectures, we can fall back
to libdwfl.
This new implementation of ELF relocation reworks the parallelization to
be per-file rather than per-relocation. The latter was done originally
because before commit 6f16ab09d6
("libdrgn: only apply ELF relocations
to relocatable files"), we applied relocations to vmlinux, which is much
larger than most kernel modules. Now that we don't do that, it seems to
be slightly faster to parallelize by file.
72 lines
2.0 KiB
C
72 lines
2.0 KiB
C
// Copyright 2019 - Omar Sandoval
|
|
// SPDX-License-Identifier: GPL-3.0+
|
|
|
|
/**
|
|
* @file
|
|
*
|
|
* ELF relocator.
|
|
*
|
|
* See @ref ElfRelocator.
|
|
*/
|
|
|
|
#ifndef DRGN_ELF_RELOCATOR_H
|
|
#define DRGN_ELF_RELOCATOR_H
|
|
|
|
#include <libelf.h>
|
|
|
|
#include "vector.h"
|
|
|
|
/**
|
|
* @ingroup Internals.
|
|
*
|
|
* @defgroup ElfRelocator ELF relocator
|
|
*
|
|
* Fast ELF relocations.
|
|
*
|
|
* Before the debugging information in a relocatable ELF file (e.g., Linux
|
|
* kernel module) can be used, it must have ELF relocations applied. This is
|
|
* usually done by libdwfl. However, libdwfl is relatively slow at it. @ref
|
|
* drgn_elf_relocator is a much faster, parallelized implementation of ELF
|
|
* relocation. It is only implemented for x86-64; for other architectures, we
|
|
* can fall back to libdwfl.
|
|
*/
|
|
|
|
DEFINE_VECTOR_TYPE(elf_vector, Elf *)
|
|
|
|
/**
|
|
* ELF relocation interface.
|
|
*
|
|
* This interface is used to apply ELF relocations to debug sections in ELF
|
|
* files.
|
|
*
|
|
* A relocator is initialized with @ref drgn_elf_relocator_init(). Files to be
|
|
* relocated are added with @ref drgn_elf_relocator_add_elf(). Once all files
|
|
* have been added, relocations are applied with @ref
|
|
* drgn_elf_relocator_apply(). Finally, the relocator must be cleaned up with
|
|
* @ref drgn_elf_relocator_deinit().
|
|
*/
|
|
struct drgn_elf_relocator {
|
|
struct elf_vector elfs;
|
|
};
|
|
|
|
/** Initialize a @ref drgn_elf_relocator. */
|
|
void drgn_elf_relocator_init(struct drgn_elf_relocator *relocator);
|
|
|
|
/** Deinitialize a @ref drgn_elf_relocator. */
|
|
void drgn_elf_relocator_deinit(struct drgn_elf_relocator *relocator);
|
|
|
|
/**
|
|
* Add an ELF file to be relocated by a @ref drgn_elf_relocator.
|
|
*
|
|
* If the ELF file is not relocatable or has an unsupported architecture, this
|
|
* does nothing.
|
|
*/
|
|
struct drgn_error *
|
|
drgn_elf_relocator_add_elf(struct drgn_elf_relocator *relocator, Elf *elf);
|
|
|
|
/** Apply ELF relocations to all files added to a @ref drgn_elf_relocator. */
|
|
struct drgn_error *
|
|
drgn_elf_relocator_apply(struct drgn_elf_relocator *relocator);
|
|
|
|
#endif /* DRGN_ELF_RELOCATOR_H */
|