summaryrefslogtreecommitdiffstats
path: root/mozglue/linker/Elfxx.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /mozglue/linker/Elfxx.h
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mozglue/linker/Elfxx.h')
-rw-r--r--mozglue/linker/Elfxx.h246
1 files changed, 246 insertions, 0 deletions
diff --git a/mozglue/linker/Elfxx.h b/mozglue/linker/Elfxx.h
new file mode 100644
index 0000000000..4baf923b55
--- /dev/null
+++ b/mozglue/linker/Elfxx.h
@@ -0,0 +1,246 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef Elfxx_h
+#define Elfxx_h
+
+#include "Utils.h"
+
+/**
+ * Android system headers have two different elf.h file. The one under linux/
+ * is the most complete on older Android API versions without unified headers.
+ */
+#if defined(ANDROID) && __ANDROID_API__ < 21 && !defined(__ANDROID_API_L__)
+# include <linux/elf.h>
+#else
+# include <elf.h>
+#endif
+#include <endian.h>
+
+#if defined(__ARM_EABI__) && !defined(PT_ARM_EXIDX)
+# define PT_ARM_EXIDX 0x70000001
+#endif
+
+/**
+ * Generic ELF macros for the target system
+ */
+#ifdef __LP64__
+# define Elf_(type) Elf64_##type
+# define ELFCLASS ELFCLASS64
+# define ELF_R_TYPE ELF64_R_TYPE
+# define ELF_R_SYM ELF64_R_SYM
+# ifndef ELF_ST_BIND
+# define ELF_ST_BIND ELF64_ST_BIND
+# endif
+#else
+# define Elf_(type) Elf32_##type
+# define ELFCLASS ELFCLASS32
+# define ELF_R_TYPE ELF32_R_TYPE
+# define ELF_R_SYM ELF32_R_SYM
+# ifndef ELF_ST_BIND
+# define ELF_ST_BIND ELF32_ST_BIND
+# endif
+#endif
+
+#ifndef __BYTE_ORDER
+# error Cannot find endianness
+#endif
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# define ELFDATA ELFDATA2LSB
+#elif __BYTE_ORDER == __BIG_ENDIAN
+# define ELFDATA ELFDATA2MSB
+#endif
+
+#ifdef __linux__
+# define ELFOSABI ELFOSABI_LINUX
+# ifdef EI_ABIVERSION
+# define ELFABIVERSION 0
+# endif
+#else
+# error Unknown ELF OSABI
+#endif
+
+#if defined(__i386__)
+# define ELFMACHINE EM_386
+
+// Doing this way probably doesn't scale to other architectures
+# define R_ABS R_386_32
+# define R_GLOB_DAT R_386_GLOB_DAT
+# define R_JMP_SLOT R_386_JMP_SLOT
+# define R_RELATIVE R_386_RELATIVE
+# define RELOC(n) DT_REL##n
+# define UNSUPPORTED_RELOC(n) DT_RELA##n
+# define STR_RELOC(n) "DT_REL" #n
+# define Reloc Rel
+
+#elif defined(__x86_64__)
+# define ELFMACHINE EM_X86_64
+
+# define R_ABS R_X86_64_64
+# define R_GLOB_DAT R_X86_64_GLOB_DAT
+# define R_JMP_SLOT R_X86_64_JUMP_SLOT
+# define R_RELATIVE R_X86_64_RELATIVE
+# define RELOC(n) DT_RELA##n
+# define UNSUPPORTED_RELOC(n) DT_REL##n
+# define STR_RELOC(n) "DT_RELA" #n
+# define Reloc Rela
+
+#elif defined(__arm__)
+# define ELFMACHINE EM_ARM
+
+# ifndef R_ARM_ABS32
+# define R_ARM_ABS32 2
+# endif
+# ifndef R_ARM_GLOB_DAT
+# define R_ARM_GLOB_DAT 21
+# endif
+# ifndef R_ARM_JUMP_SLOT
+# define R_ARM_JUMP_SLOT 22
+# endif
+# ifndef R_ARM_RELATIVE
+# define R_ARM_RELATIVE 23
+# endif
+
+# define R_ABS R_ARM_ABS32
+# define R_GLOB_DAT R_ARM_GLOB_DAT
+# define R_JMP_SLOT R_ARM_JUMP_SLOT
+# define R_RELATIVE R_ARM_RELATIVE
+# define RELOC(n) DT_REL##n
+# define UNSUPPORTED_RELOC(n) DT_RELA##n
+# define STR_RELOC(n) "DT_REL" #n
+# define Reloc Rel
+
+#elif defined(__aarch64__)
+# define ELFMACHINE EM_AARCH64
+
+# define R_ABS R_AARCH64_ABS64
+# define R_GLOB_DAT R_AARCH64_GLOB_DAT
+# define R_JMP_SLOT R_AARCH64_JUMP_SLOT
+# define R_RELATIVE R_AARCH64_RELATIVE
+# define RELOC(n) DT_RELA##n
+# define UNSUPPORTED_RELOC(n) DT_REL##n
+# define STR_RELOC(n) "DT_RELA" #n
+# define Reloc Rela
+
+#else
+# error Unknown ELF machine type
+#endif
+
+/**
+ * Android system headers don't have all definitions
+ */
+#ifndef STN_UNDEF
+# define STN_UNDEF 0
+#endif
+#ifndef DT_INIT_ARRAY
+# define DT_INIT_ARRAY 25
+#endif
+#ifndef DT_FINI_ARRAY
+# define DT_FINI_ARRAY 26
+#endif
+#ifndef DT_INIT_ARRAYSZ
+# define DT_INIT_ARRAYSZ 27
+#endif
+#ifndef DT_FINI_ARRAYSZ
+# define DT_FINI_ARRAYSZ 28
+#endif
+#ifndef DT_RELACOUNT
+# define DT_RELACOUNT 0x6ffffff9
+#endif
+#ifndef DT_RELCOUNT
+# define DT_RELCOUNT 0x6ffffffa
+#endif
+#ifndef DT_VERSYM
+# define DT_VERSYM 0x6ffffff0
+#endif
+#ifndef DT_VERDEF
+# define DT_VERDEF 0x6ffffffc
+#endif
+#ifndef DT_VERDEFNUM
+# define DT_VERDEFNUM 0x6ffffffd
+#endif
+#ifndef DT_VERNEED
+# define DT_VERNEED 0x6ffffffe
+#endif
+#ifndef DT_VERNEEDNUM
+# define DT_VERNEEDNUM 0x6fffffff
+#endif
+#ifndef DT_FLAGS_1
+# define DT_FLAGS_1 0x6ffffffb
+#endif
+#ifndef DT_FLAGS
+# define DT_FLAGS 30
+#endif
+#ifndef DF_SYMBOLIC
+# define DF_SYMBOLIC 0x00000002
+#endif
+#ifndef DF_TEXTREL
+# define DF_TEXTREL 0x00000004
+#endif
+
+namespace Elf {
+
+/**
+ * Define a few basic Elf Types
+ */
+typedef Elf_(Phdr) Phdr;
+typedef Elf_(Dyn) Dyn;
+typedef Elf_(Sym) Sym;
+typedef Elf_(Addr) Addr;
+typedef Elf_(Word) Word;
+typedef Elf_(Half) Half;
+
+/**
+ * Helper class around the standard Elf header struct
+ */
+struct Ehdr : public Elf_(Ehdr) {
+ /**
+ * Equivalent to reinterpret_cast<const Ehdr *>(buf), but additionally
+ * checking that this is indeed an Elf header and that the Elf type
+ * corresponds to that of the system
+ */
+ static const Ehdr* validate(const void* buf);
+};
+
+/**
+ * Elf String table
+ */
+class Strtab : public UnsizedArray<const char> {
+ public:
+ /**
+ * Returns the string at the given index in the table
+ */
+ const char* GetStringAt(off_t index) const {
+ return &UnsizedArray<const char>::operator[](index);
+ }
+};
+
+/**
+ * Helper class around Elf relocation.
+ */
+struct Rel : public Elf_(Rel) {
+ /**
+ * Returns the addend for the relocation, which is the value stored
+ * at r_offset.
+ */
+ Addr GetAddend(void* base) const {
+ return *(reinterpret_cast<const Addr*>(reinterpret_cast<const char*>(base) +
+ r_offset));
+ }
+};
+
+/**
+ * Helper class around Elf relocation with addend.
+ */
+struct Rela : public Elf_(Rela) {
+ /**
+ * Returns the addend for the relocation.
+ */
+ Addr GetAddend(void* base) const { return r_addend; }
+};
+
+} /* namespace Elf */
+
+#endif /* Elfxx_h */