From c9ccf0f657b90c804e252a3febc2d8b76827c5e5 Mon Sep 17 00:00:00 2001 From: Maschell Date: Wed, 4 Jan 2023 02:05:57 +0100 Subject: [PATCH] Update to latest ELFIO and undo any changes directly to ELFIO --- .github/workflows/ci.yml | 2 +- .github/workflows/pr.yml | 2 +- README.md | 2 +- source/elfio/elf_types.hpp | 1811 +++++++++++------ source/elfio/elfio.hpp | 1109 +++++----- source/elfio/elfio_array.hpp | 88 + source/elfio/elfio_dump.hpp | 1721 ++++++++++------ source/elfio/elfio_dynamic.hpp | 160 +- source/elfio/elfio_header.hpp | 149 +- source/elfio/elfio_modinfo.hpp | 124 ++ source/elfio/elfio_note.hpp | 127 +- source/elfio/elfio_relocation.hpp | 392 ++-- source/elfio/elfio_section.hpp | 493 ++--- source/elfio/elfio_segment.hpp | 287 +-- source/elfio/elfio_strings.hpp | 56 +- source/elfio/elfio_symbols.hpp | 525 +++-- source/elfio/elfio_utils.hpp | 323 +-- source/elfio/elfio_version.hpp | 1 + source/elfio/elfio_versym.hpp | 179 ++ source/plugin/PluginInformationFactory.cpp | 47 +- .../plugin/PluginMetaInformationFactory.cpp | 26 +- source/utils/membuf.hpp | 23 + source/utils/wiiu_zlib.hpp | 119 ++ 23 files changed, 4970 insertions(+), 2796 deletions(-) create mode 100644 source/elfio/elfio_array.hpp create mode 100644 source/elfio/elfio_modinfo.hpp create mode 100644 source/elfio/elfio_version.hpp create mode 100644 source/elfio/elfio_versym.hpp create mode 100644 source/utils/membuf.hpp create mode 100644 source/utils/wiiu_zlib.hpp diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6a8c83f..fe2cf49 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v3 - name: clang-format run: | - docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source + docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source --exclude ./source/elfio build-binary: runs-on: ubuntu-22.04 needs: clang-format diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 0476eb8..8a90481 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -9,7 +9,7 @@ jobs: - uses: actions/checkout@v3 - name: clang-format run: | - docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source + docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source --exclude ./source/elfio check-build-with-logging: runs-on: ubuntu-22.04 needs: clang-format diff --git a/README.md b/README.md index 849527b..00b9991 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ docker run -it --rm -v ${PWD}:/project wiiupluginloaderbackend-builder make clea ## Format the code via docker -`docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source -i` +`docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./source --exclude ./source/elfio -i` # Credits - Maschell diff --git a/source/elfio/elf_types.hpp b/source/elfio/elf_types.hpp index 9a20040..c4f6b47 100644 --- a/source/elfio/elf_types.hpp +++ b/source/elfio/elf_types.hpp @@ -1,6 +1,5 @@ -// clang-format off /* -Copyright (C) 2001-2015 by Serge Lamikhov-Center +Copyright (C) 2001-present by Serge Lamikhov-Center Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -24,703 +23,1123 @@ THE SOFTWARE. #ifndef ELFTYPES_H #define ELFTYPES_H -#ifndef ELFIO_NO_OWN_TYPES - #if !defined(ELFIO_NO_CSTDINT) && !defined(ELFIO_NO_INTTYPES) - #include - #else - typedef unsigned char uint8_t; - typedef signed char int8_t; - typedef unsigned short uint16_t; - typedef signed short int16_t; - #ifdef _MSC_VER - typedef unsigned __int32 uint32_t; - typedef signed __int32 int32_t; - typedef unsigned __int64 uint64_t; - typedef signed __int64 int64_t; - #else - typedef unsigned int uint32_t; - typedef signed int int32_t; - typedef unsigned long long uint64_t; - typedef signed long long int64_t; - #endif // _MSC_VER - #endif // ELFIO_NO_CSTDINT -#endif // ELFIO_NO_OWN_TYPES - +#ifdef __cplusplus namespace ELFIO { +#endif -// Attention! Platform depended definitions. -typedef uint16_t Elf_Half; -typedef uint32_t Elf_Word; -typedef int32_t Elf_Sword; -typedef uint64_t Elf_Xword; -typedef int64_t Elf_Sxword; +using Elf_Half = uint16_t; +using Elf_Word = uint32_t; +using Elf_Sword = int32_t; +using Elf_Xword = uint64_t; +using Elf_Sxword = int64_t; -typedef uint32_t Elf32_Addr; -typedef uint32_t Elf32_Off; -typedef uint64_t Elf64_Addr; -typedef uint64_t Elf64_Off; +using Elf32_Addr = uint32_t; +using Elf32_Off = uint32_t; +using Elf64_Addr = uint64_t; +using Elf64_Off = uint64_t; -#define Elf32_Half Elf_Half -#define Elf64_Half Elf_Half -#define Elf32_Word Elf_Word -#define Elf64_Word Elf_Word -#define Elf32_Sword Elf_Sword -#define Elf64_Sword Elf_Sword +using Elf32_Half = Elf_Half; +using Elf64_Half = Elf_Half; +using Elf32_Word = Elf_Word; +using Elf64_Word = Elf_Word; +using Elf32_Sword = Elf_Sword; +using Elf64_Sword = Elf_Sword; /////////////////////// // ELF Header Constants // File type -#define ET_NONE 0 -#define ET_REL 1 -#define ET_EXEC 2 -#define ET_DYN 3 -#define ET_CORE 4 -#define ET_LOOS 0xFE00 -#define ET_HIOS 0xFEFF -#define ET_LOPROC 0xFF00 -#define ET_HIPROC 0xFFFF +constexpr Elf_Half ET_NONE = 0; +constexpr Elf_Half ET_REL = 1; +constexpr Elf_Half ET_EXEC = 2; +constexpr Elf_Half ET_DYN = 3; +constexpr Elf_Half ET_CORE = 4; +constexpr Elf_Half ET_LOOS = 0xFE00; +constexpr Elf_Half ET_HIOS = 0xFEFF; +constexpr Elf_Half ET_LOPROC = 0xFF00; +constexpr Elf_Half ET_HIPROC = 0xFFFF; +// clang-format off +// Machine number +constexpr Elf_Half EM_NONE = 0 ; // No machine +constexpr Elf_Half EM_M32 = 1 ; // AT&T WE 32100 +constexpr Elf_Half EM_SPARC = 2 ; // SUN SPARC +constexpr Elf_Half EM_386 = 3 ; // Intel 80386 +constexpr Elf_Half EM_68K = 4 ; // Motorola m68k family +constexpr Elf_Half EM_88K = 5 ; // Motorola m88k family +constexpr Elf_Half EM_486 = 6 ; // Intel 80486// Reserved for future use +constexpr Elf_Half EM_860 = 7 ; // Intel 80860 +constexpr Elf_Half EM_MIPS = 8 ; // MIPS R3000 (officially, big-endian only) +constexpr Elf_Half EM_S370 = 9 ; // IBM System/370 +constexpr Elf_Half EM_MIPS_RS3_LE = 10; // MIPS R3000 little-endian (Deprecated) +constexpr Elf_Half EM_res011 = 11; // Reserved +constexpr Elf_Half EM_res012 = 12; // Reserved +constexpr Elf_Half EM_res013 = 13; // Reserved +constexpr Elf_Half EM_res014 = 14; // Reserved +constexpr Elf_Half EM_PARISC = 15; // HPPA +constexpr Elf_Half EM_res016 = 16; // Reserved +constexpr Elf_Half EM_VPP550 = 17; // Fujitsu VPP500 +constexpr Elf_Half EM_SPARC32PLUS = 18; // Sun's "v8plus" +constexpr Elf_Half EM_960 = 19; // Intel 80960 +constexpr Elf_Half EM_PPC = 20; // PowerPC +constexpr Elf_Half EM_PPC64 = 21; // 64-bit PowerPC +constexpr Elf_Half EM_S390 = 22; // IBM S/390 +constexpr Elf_Half EM_SPU = 23; // Sony/Toshiba/IBM SPU +constexpr Elf_Half EM_res024 = 24; // Reserved +constexpr Elf_Half EM_res025 = 25; // Reserved +constexpr Elf_Half EM_res026 = 26; // Reserved +constexpr Elf_Half EM_res027 = 27; // Reserved +constexpr Elf_Half EM_res028 = 28; // Reserved +constexpr Elf_Half EM_res029 = 29; // Reserved +constexpr Elf_Half EM_res030 = 30; // Reserved +constexpr Elf_Half EM_res031 = 31; // Reserved +constexpr Elf_Half EM_res032 = 32; // Reserved +constexpr Elf_Half EM_res033 = 33; // Reserved +constexpr Elf_Half EM_res034 = 34; // Reserved +constexpr Elf_Half EM_res035 = 35; // Reserved +constexpr Elf_Half EM_V800 = 36; // NEC V800 series +constexpr Elf_Half EM_FR20 = 37; // Fujitsu FR20 +constexpr Elf_Half EM_RH32 = 38; // TRW RH32 +constexpr Elf_Half EM_MCORE = 39; // Motorola M*Core // May also be taken by Fujitsu MMA +constexpr Elf_Half EM_RCE = 39; // Old name for MCore +constexpr Elf_Half EM_ARM = 40; // ARM +constexpr Elf_Half EM_OLD_ALPHA = 41; // Digital Alpha +constexpr Elf_Half EM_SH = 42; // Renesas (formerly Hitachi) / SuperH SH +constexpr Elf_Half EM_SPARCV9 = 43; // SPARC v9 64-bit +constexpr Elf_Half EM_TRICORE = 44; // Siemens Tricore embedded processor +constexpr Elf_Half EM_ARC = 45; // ARC Cores +constexpr Elf_Half EM_H8_300 = 46; // Renesas (formerly Hitachi) H8/300 +constexpr Elf_Half EM_H8_300H = 47; // Renesas (formerly Hitachi) H8/300H +constexpr Elf_Half EM_H8S = 48; // Renesas (formerly Hitachi) H8S +constexpr Elf_Half EM_H8_500 = 49; // Renesas (formerly Hitachi) H8/500 +constexpr Elf_Half EM_IA_64 = 50; // Intel IA-64 Processor +constexpr Elf_Half EM_MIPS_X = 51; // Stanford MIPS-X +constexpr Elf_Half EM_COLDFIRE = 52; // Motorola Coldfire +constexpr Elf_Half EM_68HC12 = 53; // Motorola M68HC12 +constexpr Elf_Half EM_MMA = 54; // Fujitsu Multimedia Accelerator +constexpr Elf_Half EM_PCP = 55; // Siemens PCP +constexpr Elf_Half EM_NCPU = 56; // Sony nCPU embedded RISC processor +constexpr Elf_Half EM_NDR1 = 57; // Denso NDR1 microprocesspr +constexpr Elf_Half EM_STARCORE = 58; // Motorola Star*Core processor +constexpr Elf_Half EM_ME16 = 59; // Toyota ME16 processor +constexpr Elf_Half EM_ST100 = 60; // STMicroelectronics ST100 processor +constexpr Elf_Half EM_TINYJ = 61; // Advanced Logic Corp. TinyJ embedded processor +constexpr Elf_Half EM_X86_64 = 62; // Advanced Micro Devices X86-64 processor +constexpr Elf_Half EM_PDSP = 63; // Sony DSP Processor +constexpr Elf_Half EM_PDP10 = 64; // Digital Equipment Corp. PDP-10 +constexpr Elf_Half EM_PDP11 = 65; // Digital Equipment Corp. PDP-11 +constexpr Elf_Half EM_FX66 = 66; // Siemens FX66 microcontroller +constexpr Elf_Half EM_ST9PLUS = 67; // STMicroelectronics ST9+ 8/16 bit microcontroller +constexpr Elf_Half EM_ST7 = 68 ; // STMicroelectronics ST7 8-bit microcontroller +constexpr Elf_Half EM_68HC16 = 69 ; // Motorola MC68HC16 Microcontroller +constexpr Elf_Half EM_68HC11 = 70 ; // Motorola MC68HC11 Microcontroller +constexpr Elf_Half EM_68HC08 = 71 ; // Motorola MC68HC08 Microcontroller +constexpr Elf_Half EM_68HC05 = 72 ; // Motorola MC68HC05 Microcontroller +constexpr Elf_Half EM_SVX = 73 ; // Silicon Graphics SVx +constexpr Elf_Half EM_ST19 = 74 ; // STMicroelectronics ST19 8-bit cpu +constexpr Elf_Half EM_VAX = 75 ; // Digital VAX +constexpr Elf_Half EM_CRIS = 76 ; // Axis Communications 32-bit embedded processor +constexpr Elf_Half EM_JAVELIN = 77 ; // Infineon Technologies 32-bit embedded cpu +constexpr Elf_Half EM_FIREPATH = 78 ; // Element 14 64-bit DSP processor +constexpr Elf_Half EM_ZSP = 79 ; // LSI Logic's 16-bit DSP processor +constexpr Elf_Half EM_MMIX = 80 ; // Donald Knuth's educational 64-bit processor +constexpr Elf_Half EM_HUANY = 81 ; // Harvard's machine-independent format +constexpr Elf_Half EM_PRISM = 82 ; // SiTera Prism +constexpr Elf_Half EM_AVR = 83 ; // Atmel AVR 8-bit microcontroller +constexpr Elf_Half EM_FR30 = 84 ; // Fujitsu FR30 +constexpr Elf_Half EM_D10V = 85 ; // Mitsubishi D10V +constexpr Elf_Half EM_D30V = 86 ; // Mitsubishi D30V +constexpr Elf_Half EM_V850 = 87 ; // NEC v850 +constexpr Elf_Half EM_M32R = 88 ; // Renesas M32R (formerly Mitsubishi M32R) +constexpr Elf_Half EM_MN10300 = 89 ; // Matsushita MN10300 +constexpr Elf_Half EM_MN10200 = 90 ; // Matsushita MN10200 +constexpr Elf_Half EM_PJ = 91 ; // picoJava +constexpr Elf_Half EM_OPENRISC = 92 ; // OpenRISC 32-bit embedded processor +constexpr Elf_Half EM_ARC_A5 = 93 ; // ARC Cores Tangent-A5 +constexpr Elf_Half EM_XTENSA = 94 ; // Tensilica Xtensa Architecture +constexpr Elf_Half EM_VIDEOCORE = 95 ; // Alphamosaic VideoCore processor +constexpr Elf_Half EM_TMM_GPP = 96 ; // Thompson Multimedia General Purpose Processor +constexpr Elf_Half EM_NS32K = 97 ; // National Semiconductor 32000 series +constexpr Elf_Half EM_TPC = 98 ; // Tenor Network TPC processor +constexpr Elf_Half EM_SNP1K = 99 ; // Trebia SNP 1000 processor +constexpr Elf_Half EM_ST200 = 100; // STMicroelectronics ST200 microcontroller +constexpr Elf_Half EM_IP2K = 101; // Ubicom IP2022 micro controller +constexpr Elf_Half EM_MAX = 102; // MAX Processor +constexpr Elf_Half EM_CR = 103; // National Semiconductor CompactRISC +constexpr Elf_Half EM_F2MC16 = 104; // Fujitsu F2MC16 +constexpr Elf_Half EM_MSP430 = 105; // TI msp430 micro controller +constexpr Elf_Half EM_BLACKFIN = 106; // ADI Blackfin +constexpr Elf_Half EM_SE_C33 = 107; // S1C33 Family of Seiko Epson processors +constexpr Elf_Half EM_SEP = 108; // Sharp embedded microprocessor +constexpr Elf_Half EM_ARCA = 109; // Arca RISC Microprocessor +constexpr Elf_Half EM_UNICORE = 110; // Microprocessor series from PKU-Unity Ltd. +constexpr Elf_Half EM_EXCESS = 111; // eXcess: 16/32/64-bit configurable embedded CPU +constexpr Elf_Half EM_DXP = 112; // Icera Semiconductor Inc. Deep Execution Processor +constexpr Elf_Half EM_ALTERA_NIOS2 = 113; // Altera Nios II soft-core processor +constexpr Elf_Half EM_CRX = 114; // National Semiconductor CRX +constexpr Elf_Half EM_XGATE = 115; // Motorola XGATE embedded processor +constexpr Elf_Half EM_C166 = 116; // Infineon C16x/XC16x processor +constexpr Elf_Half EM_M16C = 117; // Renesas M16C series microprocessors +constexpr Elf_Half EM_DSPIC30F = 118; // Microchip Technology dsPIC30F DSignal Controller +constexpr Elf_Half EM_CE = 119; // Freescale Communication Engine RISC core +constexpr Elf_Half EM_M32C = 120; // Renesas M32C series microprocessors +constexpr Elf_Half EM_res121 = 121; // Reserved +constexpr Elf_Half EM_res122 = 122; // Reserved +constexpr Elf_Half EM_res123 = 123; // Reserved +constexpr Elf_Half EM_res124 = 124; // Reserved +constexpr Elf_Half EM_res125 = 125; // Reserved +constexpr Elf_Half EM_res126 = 126; // Reserved +constexpr Elf_Half EM_res127 = 127; // Reserved +constexpr Elf_Half EM_res128 = 128; // Reserved +constexpr Elf_Half EM_res129 = 129; // Reserved +constexpr Elf_Half EM_res130 = 130; // Reserved +constexpr Elf_Half EM_TSK3000 = 131; // Altium TSK3000 core +constexpr Elf_Half EM_RS08 = 132; // Freescale RS08 embedded processor +constexpr Elf_Half EM_res133 = 133; // Reserved +constexpr Elf_Half EM_ECOG2 = 134; // Cyan Technology eCOG2 microprocessor +constexpr Elf_Half EM_SCORE = 135; // Sunplus Score +constexpr Elf_Half EM_SCORE7 = 135; // Sunplus S+core7 RISC processor +constexpr Elf_Half EM_DSP24 = 136; // New Japan Radio (NJR) 24-bit DSP Processor +constexpr Elf_Half EM_VIDEOCORE3 = 137; // Broadcom VideoCore III processor +constexpr Elf_Half EM_LATTICEMICO32 = 138; // RISC processor for Lattice FPGA architecture +constexpr Elf_Half EM_SE_C17 = 139; // Seiko Epson C17 family +constexpr Elf_Half EM_TI_C6000 = 140; // Texas Instruments TMS320C6000 DSP family +constexpr Elf_Half EM_TI_C2000 = 141; // Texas Instruments TMS320C2000 DSP family +constexpr Elf_Half EM_TI_C5500 = 142; // Texas Instruments TMS320C55x DSP family +constexpr Elf_Half EM_res143 = 143; // Reserved +constexpr Elf_Half EM_res144 = 144; // Reserved +constexpr Elf_Half EM_res145 = 145; // Reserved +constexpr Elf_Half EM_res146 = 146; // Reserved +constexpr Elf_Half EM_res147 = 147; // Reserved +constexpr Elf_Half EM_res148 = 148; // Reserved +constexpr Elf_Half EM_res149 = 149; // Reserved +constexpr Elf_Half EM_res150 = 150; // Reserved +constexpr Elf_Half EM_res151 = 151; // Reserved +constexpr Elf_Half EM_res152 = 152; // Reserved +constexpr Elf_Half EM_res153 = 153; // Reserved +constexpr Elf_Half EM_res154 = 154; // Reserved +constexpr Elf_Half EM_res155 = 155; // Reserved +constexpr Elf_Half EM_res156 = 156; // Reserved +constexpr Elf_Half EM_res157 = 157; // Reserved +constexpr Elf_Half EM_res158 = 158; // Reserved +constexpr Elf_Half EM_res159 = 159; // Reserved +constexpr Elf_Half EM_MMDSP_PLUS = 160; // STMicroelectronics 64bit VLIW Data Signal Processor +constexpr Elf_Half EM_CYPRESS_M8C = 161; // Cypress M8C microprocessor +constexpr Elf_Half EM_R32C = 162; // Renesas R32C series microprocessors +constexpr Elf_Half EM_TRIMEDIA = 163; // NXP Semiconductors TriMedia architecture family +constexpr Elf_Half EM_QDSP6 = 164; // QUALCOMM DSP6 Processor +constexpr Elf_Half EM_8051 = 165; // Intel 8051 and variants +constexpr Elf_Half EM_STXP7X = 166; // STMicroelectronics STxP7x family +constexpr Elf_Half EM_NDS32 = 167; // Andes Technology embedded RISC processor family +constexpr Elf_Half EM_ECOG1 = 168; // Cyan Technology eCOG1X family +constexpr Elf_Half EM_ECOG1X = 168; // Cyan Technology eCOG1X family +constexpr Elf_Half EM_MAXQ30 = 169; // Dallas Semiconductor MAXQ30 Core Micro-controllers +constexpr Elf_Half EM_XIMO16 = 170; // New Japan Radio (NJR) 16-bit DSP Processor +constexpr Elf_Half EM_MANIK = 171; // M2000 Reconfigurable RISC Microprocessor +constexpr Elf_Half EM_CRAYNV2 = 172; // Cray Inc. NV2 vector architecture +constexpr Elf_Half EM_RX = 173; // Renesas RX family +constexpr Elf_Half EM_METAG = 174; // Imagination Technologies META processor architecture +constexpr Elf_Half EM_MCST_ELBRUS = 175; // MCST Elbrus general purpose hardware architecture +constexpr Elf_Half EM_ECOG16 = 176; // Cyan Technology eCOG16 family +constexpr Elf_Half EM_CR16 = 177; // National Semiconductor CompactRISC 16-bit processor +constexpr Elf_Half EM_ETPU = 178; // Freescale Extended Time Processing Unit +constexpr Elf_Half EM_SLE9X = 179; // Infineon Technologies SLE9X core +constexpr Elf_Half EM_L1OM = 180; // Intel L1OM +constexpr Elf_Half EM_INTEL181 = 181; // Reserved by Intel +constexpr Elf_Half EM_INTEL182 = 182; // Reserved by Intel +constexpr Elf_Half EM_AARCH64 = 183; // ARM AArch64 +constexpr Elf_Half EM_res184 = 184; // Reserved by ARM +constexpr Elf_Half EM_AVR32 = 185; // Atmel Corporation 32-bit microprocessor family +constexpr Elf_Half EM_STM8 = 186; // STMicroeletronics STM8 8-bit microcontroller +constexpr Elf_Half EM_TILE64 = 187; // Tilera TILE64 multicore architecture family +constexpr Elf_Half EM_TILEPRO = 188; // Tilera TILEPro multicore architecture family +constexpr Elf_Half EM_MICROBLAZE = 189; // Xilinx MicroBlaze 32-bit RISC soft processor core +constexpr Elf_Half EM_CUDA = 190; // NVIDIA CUDA architecture +constexpr Elf_Half EM_TILEGX = 191; // Tilera TILE-Gx multicore architecture family +constexpr Elf_Half EM_CLOUDSHIELD = 192; // CloudShield architecture family +constexpr Elf_Half EM_COREA_1ST = 193; // KIPO-KAIST Core-A 1st generation processor family +constexpr Elf_Half EM_COREA_2ND = 194; // KIPO-KAIST Core-A 2nd generation processor family +constexpr Elf_Half EM_ARC_COMPACT2 = 195; // Synopsys ARCompact V2 +constexpr Elf_Half EM_OPEN8 = 196; // Open8 8-bit RISC soft processor core +constexpr Elf_Half EM_RL78 = 197; // Renesas RL78 family +constexpr Elf_Half EM_VIDEOCORE5 = 198; // Broadcom VideoCore V processor +constexpr Elf_Half EM_78KOR = 199; // Renesas 78KOR family +constexpr Elf_Half EM_56800EX = 200; // Freescale 56800EX Digital Signal Controller (DSC) +constexpr Elf_Half EM_BA1 = 201; // Beyond BA1 CPU architecture +constexpr Elf_Half EM_BA2 = 202; // Beyond BA2 CPU architecture +constexpr Elf_Half EM_XCORE = 203; // XMOS xCORE processor family +constexpr Elf_Half EM_MCHP_PIC = 204; // Microchip 8-bit PIC(r) family +constexpr Elf_Half EM_INTEL205 = 205; // Reserved by Intel +constexpr Elf_Half EM_INTEL206 = 206; // Reserved by Intel +constexpr Elf_Half EM_INTEL207 = 207; // Reserved by Intel +constexpr Elf_Half EM_INTEL208 = 208; // Reserved by Intel +constexpr Elf_Half EM_INTEL209 = 209; // Reserved by Intel +constexpr Elf_Half EM_KM32 = 210; // KM211 KM32 32-bit processor +constexpr Elf_Half EM_KMX32 = 211; // KM211 KMX32 32-bit processor +constexpr Elf_Half EM_KMX16 = 212; // KM211 KMX16 16-bit processor +constexpr Elf_Half EM_KMX8 = 213; // KM211 KMX8 8-bit processor +constexpr Elf_Half EM_KVARC = 214; // KM211 KVARC processor +constexpr Elf_Half EM_CDP = 215; // Paneve CDP architecture family +constexpr Elf_Half EM_COGE = 216; // Cognitive Smart Memory Processor +constexpr Elf_Half EM_COOL = 217; // iCelero CoolEngine +constexpr Elf_Half EM_NORC = 218; // Nanoradio Optimized RISC +constexpr Elf_Half EM_CSR_KALIMBA = 219; // CSR Kalimba architecture family +constexpr Elf_Half EM_Z80 = 220; // Zilog Z80 +constexpr Elf_Half EM_VISIUM = 221; // Controls and Data Services VISIUMcore processor +constexpr Elf_Half EM_FT32 = 222; // FTDI Chip FT32 high performance 32-bit RISC architecture +constexpr Elf_Half EM_MOXIE = 223; // Moxie processor family +constexpr Elf_Half EM_AMDGPU = 224; // AMD GPU architecture +constexpr Elf_Half EM_RISCV = 243; // RISC-V +constexpr Elf_Half EM_LANAI = 244; // Lanai processor +constexpr Elf_Half EM_CEVA = 245; // CEVA Processor Architecture Family +constexpr Elf_Half EM_CEVA_X2 = 246; // CEVA X2 Processor Family +constexpr Elf_Half EM_BPF = 247; // Linux BPF – in-kernel virtual machine +constexpr Elf_Half EM_GRAPHCORE_IPU = 248; // Graphcore Intelligent Processing Unit +constexpr Elf_Half EM_IMG1 = 249; // Imagination Technologies +constexpr Elf_Half EM_NFP = 250; // Netronome Flow Processor (P) +constexpr Elf_Half EM_CSKY = 252; // C-SKY processor family +constexpr Elf_Half EM_ARC_COMPACT3_64 = 253; // Synopsys ARCv2.3 64-bit +constexpr Elf_Half EM_MCS6502 = 254; // MOS Technology MCS 6502 processor +constexpr Elf_Half EM_ARC_COMPACT3 = 255; // Synopsys ARCv2.3 32-bit +constexpr Elf_Half EM_KVX = 256; // Kalray VLIW core of the MPPA processor family +constexpr Elf_Half EM_65816 = 257; // WDC 65816/65C816 +constexpr Elf_Half EM_LOONGARCH = 258; // Loongson Loongarch +constexpr Elf_Half EM_KF32 = 259; // ChipON KungFu32 -#define EM_NONE 0 // No machine -#define EM_M32 1 // AT&T WE 32100 -#define EM_SPARC 2 // SUN SPARC -#define EM_386 3 // Intel 80386 -#define EM_68K 4 // Motorola m68k family -#define EM_88K 5 // Motorola m88k family -#define EM_486 6 // Intel 80486// Reserved for future use -#define EM_860 7 // Intel 80860 -#define EM_MIPS 8 // MIPS R3000 (officially, big-endian only) -#define EM_S370 9 // IBM System/370 -#define EM_MIPS_RS3_LE 10 // MIPS R3000 little-endian (Oct 4 1999 Draft) Deprecated -#define EM_res011 11 // Reserved -#define EM_res012 12 // Reserved -#define EM_res013 13 // Reserved -#define EM_res014 14 // Reserved -#define EM_PARISC 15 // HPPA -#define EM_res016 16 // Reserved -#define EM_VPP550 17 // Fujitsu VPP500 -#define EM_SPARC32PLUS 18 // Sun's "v8plus" -#define EM_960 19 // Intel 80960 -#define EM_PPC 20 // PowerPC -#define EM_PPC64 21 // 64-bit PowerPC -#define EM_S390 22 // IBM S/390 -#define EM_SPU 23 // Sony/Toshiba/IBM SPU -#define EM_res024 24 // Reserved -#define EM_res025 25 // Reserved -#define EM_res026 26 // Reserved -#define EM_res027 27 // Reserved -#define EM_res028 28 // Reserved -#define EM_res029 29 // Reserved -#define EM_res030 30 // Reserved -#define EM_res031 31 // Reserved -#define EM_res032 32 // Reserved -#define EM_res033 33 // Reserved -#define EM_res034 34 // Reserved -#define EM_res035 35 // Reserved -#define EM_V800 36 // NEC V800 series -#define EM_FR20 37 // Fujitsu FR20 -#define EM_RH32 38 // TRW RH32 -#define EM_MCORE 39 // Motorola M*Core // May also be taken by Fujitsu MMA -#define EM_RCE 39 // Old name for MCore -#define EM_ARM 40 // ARM -#define EM_OLD_ALPHA 41 // Digital Alpha -#define EM_SH 42 // Renesas (formerly Hitachi) / SuperH SH -#define EM_SPARCV9 43 // SPARC v9 64-bit -#define EM_TRICORE 44 // Siemens Tricore embedded processor -#define EM_ARC 45 // ARC Cores -#define EM_H8_300 46 // Renesas (formerly Hitachi) H8/300 -#define EM_H8_300H 47 // Renesas (formerly Hitachi) H8/300H -#define EM_H8S 48 // Renesas (formerly Hitachi) H8S -#define EM_H8_500 49 // Renesas (formerly Hitachi) H8/500 -#define EM_IA_64 50 // Intel IA-64 Processor -#define EM_MIPS_X 51 // Stanford MIPS-X -#define EM_COLDFIRE 52 // Motorola Coldfire -#define EM_68HC12 53 // Motorola M68HC12 -#define EM_MMA 54 // Fujitsu Multimedia Accelerator -#define EM_PCP 55 // Siemens PCP -#define EM_NCPU 56 // Sony nCPU embedded RISC processor -#define EM_NDR1 57 // Denso NDR1 microprocesspr -#define EM_STARCORE 58 // Motorola Star*Core processor -#define EM_ME16 59 // Toyota ME16 processor -#define EM_ST100 60 // STMicroelectronics ST100 processor -#define EM_TINYJ 61 // Advanced Logic Corp. TinyJ embedded processor -#define EM_X86_64 62 // Advanced Micro Devices X86-64 processor -#define EM_PDSP 63 // Sony DSP Processor -#define EM_PDP10 64 // Digital Equipment Corp. PDP-10 -#define EM_PDP11 65 // Digital Equipment Corp. PDP-11 -#define EM_FX66 66 // Siemens FX66 microcontroller -#define EM_ST9PLUS 67 // STMicroelectronics ST9+ 8/16 bit microcontroller -#define EM_ST7 68 // STMicroelectronics ST7 8-bit microcontroller -#define EM_68HC16 69 // Motorola MC68HC16 Microcontroller -#define EM_68HC11 70 // Motorola MC68HC11 Microcontroller -#define EM_68HC08 71 // Motorola MC68HC08 Microcontroller -#define EM_68HC05 72 // Motorola MC68HC05 Microcontroller -#define EM_SVX 73 // Silicon Graphics SVx -#define EM_ST19 74 // STMicroelectronics ST19 8-bit cpu -#define EM_VAX 75 // Digital VAX -#define EM_CRIS 76 // Axis Communications 32-bit embedded processor -#define EM_JAVELIN 77 // Infineon Technologies 32-bit embedded cpu -#define EM_FIREPATH 78 // Element 14 64-bit DSP processor -#define EM_ZSP 79 // LSI Logic's 16-bit DSP processor -#define EM_MMIX 80 // Donald Knuth's educational 64-bit processor -#define EM_HUANY 81 // Harvard's machine-independent format -#define EM_PRISM 82 // SiTera Prism -#define EM_AVR 83 // Atmel AVR 8-bit microcontroller -#define EM_FR30 84 // Fujitsu FR30 -#define EM_D10V 85 // Mitsubishi D10V -#define EM_D30V 86 // Mitsubishi D30V -#define EM_V850 87 // NEC v850 -#define EM_M32R 88 // Renesas M32R (formerly Mitsubishi M32R) -#define EM_MN10300 89 // Matsushita MN10300 -#define EM_MN10200 90 // Matsushita MN10200 -#define EM_PJ 91 // picoJava -#define EM_OPENRISC 92 // OpenRISC 32-bit embedded processor -#define EM_ARC_A5 93 // ARC Cores Tangent-A5 -#define EM_XTENSA 94 // Tensilica Xtensa Architecture -#define EM_VIDEOCORE 95 // Alphamosaic VideoCore processor -#define EM_TMM_GPP 96 // Thompson Multimedia General Purpose Processor -#define EM_NS32K 97 // National Semiconductor 32000 series -#define EM_TPC 98 // Tenor Network TPC processor -#define EM_SNP1K 99 // Trebia SNP 1000 processor -#define EM_ST200 100 // STMicroelectronics ST200 microcontroller -#define EM_IP2K 101 // Ubicom IP2022 micro controller -#define EM_MAX 102 // MAX Processor -#define EM_CR 103 // National Semiconductor CompactRISC -#define EM_F2MC16 104 // Fujitsu F2MC16 -#define EM_MSP430 105 // TI msp430 micro controller -#define EM_BLACKFIN 106 // ADI Blackfin -#define EM_SE_C33 107 // S1C33 Family of Seiko Epson processors -#define EM_SEP 108 // Sharp embedded microprocessor -#define EM_ARCA 109 // Arca RISC Microprocessor -#define EM_UNICORE 110 // Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University -#define EM_EXCESS 111 // eXcess: 16/32/64-bit configurable embedded CPU -#define EM_DXP 112 // Icera Semiconductor Inc. Deep Execution Processor -#define EM_ALTERA_NIOS2 113 // Altera Nios II soft-core processor -#define EM_CRX 114 // National Semiconductor CRX -#define EM_XGATE 115 // Motorola XGATE embedded processor -#define EM_C166 116 // Infineon C16x/XC16x processor -#define EM_M16C 117 // Renesas M16C series microprocessors -#define EM_DSPIC30F 118 // Microchip Technology dsPIC30F Digital Signal Controller -#define EM_CE 119 // Freescale Communication Engine RISC core -#define EM_M32C 120 // Renesas M32C series microprocessors -#define EM_res121 121 // Reserved -#define EM_res122 122 // Reserved -#define EM_res123 123 // Reserved -#define EM_res124 124 // Reserved -#define EM_res125 125 // Reserved -#define EM_res126 126 // Reserved -#define EM_res127 127 // Reserved -#define EM_res128 128 // Reserved -#define EM_res129 129 // Reserved -#define EM_res130 130 // Reserved -#define EM_TSK3000 131 // Altium TSK3000 core -#define EM_RS08 132 // Freescale RS08 embedded processor -#define EM_res133 133 // Reserved -#define EM_ECOG2 134 // Cyan Technology eCOG2 microprocessor -#define EM_SCORE 135 // Sunplus Score -#define EM_SCORE7 135 // Sunplus S+core7 RISC processor -#define EM_DSP24 136 // New Japan Radio (NJR) 24-bit DSP Processor -#define EM_VIDEOCORE3 137 // Broadcom VideoCore III processor -#define EM_LATTICEMICO32 138 // RISC processor for Lattice FPGA architecture -#define EM_SE_C17 139 // Seiko Epson C17 family -#define EM_TI_C6000 140 // Texas Instruments TMS320C6000 DSP family -#define EM_TI_C2000 141 // Texas Instruments TMS320C2000 DSP family -#define EM_TI_C5500 142 // Texas Instruments TMS320C55x DSP family -#define EM_res143 143 // Reserved -#define EM_res144 144 // Reserved -#define EM_res145 145 // Reserved -#define EM_res146 146 // Reserved -#define EM_res147 147 // Reserved -#define EM_res148 148 // Reserved -#define EM_res149 149 // Reserved -#define EM_res150 150 // Reserved -#define EM_res151 151 // Reserved -#define EM_res152 152 // Reserved -#define EM_res153 153 // Reserved -#define EM_res154 154 // Reserved -#define EM_res155 155 // Reserved -#define EM_res156 156 // Reserved -#define EM_res157 157 // Reserved -#define EM_res158 158 // Reserved -#define EM_res159 159 // Reserved -#define EM_MMDSP_PLUS 160 // STMicroelectronics 64bit VLIW Data Signal Processor -#define EM_CYPRESS_M8C 161 // Cypress M8C microprocessor -#define EM_R32C 162 // Renesas R32C series microprocessors -#define EM_TRIMEDIA 163 // NXP Semiconductors TriMedia architecture family -#define EM_QDSP6 164 // QUALCOMM DSP6 Processor -#define EM_8051 165 // Intel 8051 and variants -#define EM_STXP7X 166 // STMicroelectronics STxP7x family -#define EM_NDS32 167 // Andes Technology compact code size embedded RISC processor family -#define EM_ECOG1 168 // Cyan Technology eCOG1X family -#define EM_ECOG1X 168 // Cyan Technology eCOG1X family -#define EM_MAXQ30 169 // Dallas Semiconductor MAXQ30 Core Micro-controllers -#define EM_XIMO16 170 // New Japan Radio (NJR) 16-bit DSP Processor -#define EM_MANIK 171 // M2000 Reconfigurable RISC Microprocessor -#define EM_CRAYNV2 172 // Cray Inc. NV2 vector architecture -#define EM_RX 173 // Renesas RX family -#define EM_METAG 174 // Imagination Technologies META processor architecture -#define EM_MCST_ELBRUS 175 // MCST Elbrus general purpose hardware architecture -#define EM_ECOG16 176 // Cyan Technology eCOG16 family -#define EM_CR16 177 // National Semiconductor CompactRISC 16-bit processor -#define EM_ETPU 178 // Freescale Extended Time Processing Unit -#define EM_SLE9X 179 // Infineon Technologies SLE9X core -#define EM_L1OM 180 // Intel L1OM -#define EM_INTEL181 181 // Reserved by Intel -#define EM_INTEL182 182 // Reserved by Intel -#define EM_res183 183 // Reserved by ARM -#define EM_res184 184 // Reserved by ARM -#define EM_AVR32 185 // Atmel Corporation 32-bit microprocessor family -#define EM_STM8 186 // STMicroeletronics STM8 8-bit microcontroller -#define EM_TILE64 187 // Tilera TILE64 multicore architecture family -#define EM_TILEPRO 188 // Tilera TILEPro multicore architecture family -#define EM_MICROBLAZE 189 // Xilinx MicroBlaze 32-bit RISC soft processor core -#define EM_CUDA 190 // NVIDIA CUDA architecture -#define EM_TILEGX 191 // Tilera TILE-Gx multicore architecture family -#define EM_CLOUDSHIELD 192 // CloudShield architecture family -#define EM_COREA_1ST 193 // KIPO-KAIST Core-A 1st generation processor family -#define EM_COREA_2ND 194 // KIPO-KAIST Core-A 2nd generation processor family -#define EM_ARC_COMPACT2 195 // Synopsys ARCompact V2 -#define EM_OPEN8 196 // Open8 8-bit RISC soft processor core -#define EM_RL78 197 // Renesas RL78 family -#define EM_VIDEOCORE5 198 // Broadcom VideoCore V processor -#define EM_78KOR 199 // Renesas 78KOR family -#define EM_56800EX 200 // Freescale 56800EX Digital Signal Controller (DSC) -#define EM_BA1 201 // Beyond BA1 CPU architecture -#define EM_BA2 202 // Beyond BA2 CPU architecture -#define EM_XCORE 203 // XMOS xCORE processor family -#define EM_MCHP_PIC 204 // Microchip 8-bit PIC(r) family -#define EM_INTEL205 205 // Reserved by Intel -#define EM_INTEL206 206 // Reserved by Intel -#define EM_INTEL207 207 // Reserved by Intel -#define EM_INTEL208 208 // Reserved by Intel -#define EM_INTEL209 209 // Reserved by Intel -#define EM_KM32 210 // KM211 KM32 32-bit processor -#define EM_KMX32 211 // KM211 KMX32 32-bit processor -#define EM_KMX16 212 // KM211 KMX16 16-bit processor -#define EM_KMX8 213 // KM211 KMX8 8-bit processor -#define EM_KVARC 214 // KM211 KVARC processor -#define EM_CDP 215 // Paneve CDP architecture family -#define EM_COGE 216 // Cognitive Smart Memory Processor -#define EM_COOL 217 // iCelero CoolEngine -#define EM_NORC 218 // Nanoradio Optimized RISC -#define EM_CSR_KALIMBA 219 // CSR Kalimba architecture family -#define EM_Z80 220 // Zilog Z80 -#define EM_VISIUM 221 // Controls and Data Services VISIUMcore processor -#define EM_FT32 222 // FTDI Chip FT32 high performance 32-bit RISC architecture -#define EM_MOXIE 223 // Moxie processor family -#define EM_AMDGPU 224 // AMD GPU architecture -#define EM_RISCV 243 // RISC-V -#define EM_LANAI 244 // Lanai processor -#define EM_CEVA 245 // CEVA Processor Architecture Family -#define EM_CEVA_X2 246 // CEVA X2 Processor Family -#define EM_BPF 247 // Linux BPF – in-kernel virtual machine +constexpr Elf_Half EM_MT = 0x2530; // Morpho Techologies MT processor +constexpr Elf_Half EM_ALPHA = 0x9026; // Alpha +constexpr Elf_Half EM_WEBASSEMBLY = 0x4157; // Web Assembly +constexpr Elf_Half EM_DLX = 0x5aa5; // OpenDLX +constexpr Elf_Half EM_XSTORMY16 = 0xad45; // Sanyo XStormy16 CPU core +constexpr Elf_Half EM_IQ2000 = 0xFEBA; // Vitesse IQ2000 +constexpr Elf_Half EM_M32C_OLD = 0xFEB; +constexpr Elf_Half EM_NIOS32 = 0xFEBB; // Altera Nios +constexpr Elf_Half EM_CYGNUS_MEP = 0xF00D; // Toshiba MeP Media Engine +constexpr Elf_Half EM_ADAPTEVA_EPIPHANY = 0x1223; // Adapteva EPIPHANY +constexpr Elf_Half EM_CYGNUS_FRV = 0x5441; // Fujitsu FR-V +constexpr Elf_Half EM_S12Z = 0x4DEF; // Freescale S12Z +// clang-format on // File version -#define EV_NONE 0 -#define EV_CURRENT 1 +constexpr unsigned char EV_NONE = 0; +constexpr unsigned char EV_CURRENT = 1; // Identification index -#define EI_MAG0 0 -#define EI_MAG1 1 -#define EI_MAG2 2 -#define EI_MAG3 3 -#define EI_CLASS 4 -#define EI_DATA 5 -#define EI_VERSION 6 -#define EI_OSABI 7 -#define EI_ABIVERSION 8 -#define EI_PAD 9 -#define EI_NIDENT 16 +constexpr unsigned char EI_MAG0 = 0; +constexpr unsigned char EI_MAG1 = 1; +constexpr unsigned char EI_MAG2 = 2; +constexpr unsigned char EI_MAG3 = 3; +constexpr unsigned char EI_CLASS = 4; +constexpr unsigned char EI_DATA = 5; +constexpr unsigned char EI_VERSION = 6; +constexpr unsigned char EI_OSABI = 7; +constexpr unsigned char EI_ABIVERSION = 8; +constexpr unsigned char EI_PAD = 9; +constexpr unsigned char EI_NIDENT = 16; // Magic number -#define ELFMAG0 0x7F -#define ELFMAG1 'E' -#define ELFMAG2 'L' -#define ELFMAG3 'F' +constexpr unsigned char ELFMAG0 = 0x7F; +constexpr unsigned char ELFMAG1 = 'E'; +constexpr unsigned char ELFMAG2 = 'L'; +constexpr unsigned char ELFMAG3 = 'F'; // File class -#define ELFCLASSNONE 0 -#define ELFCLASS32 1 -#define ELFCLASS64 2 +constexpr unsigned char ELFCLASSNONE = 0; +constexpr unsigned char ELFCLASS32 = 1; +constexpr unsigned char ELFCLASS64 = 2; // Encoding -#define ELFDATANONE 0 -#define ELFDATA2LSB 1 -#define ELFDATA2MSB 2 +constexpr unsigned char ELFDATANONE = 0; +constexpr unsigned char ELFDATA2LSB = 1; +constexpr unsigned char ELFDATA2MSB = 2; +// clang-format off // OS extensions -#define ELFOSABI_NONE 0 // No extensions or unspecified -#define ELFOSABI_HPUX 1 // Hewlett-Packard HP-UX -#define ELFOSABI_NETBSD 2 // NetBSD -#define ELFOSABI_LINUX 3 // Linux -#define ELFOSABI_SOLARIS 6 // Sun Solaris -#define ELFOSABI_AIX 7 // AIX -#define ELFOSABI_IRIX 8 // IRIX -#define ELFOSABI_FREEBSD 9 // FreeBSD -#define ELFOSABI_TRU64 10 // Compaq TRU64 UNIX -#define ELFOSABI_MODESTO 11 // Novell Modesto -#define ELFOSABI_OPENBSD 12 // Open BSD -#define ELFOSABI_OPENVMS 13 // Open VMS -#define ELFOSABI_NSK 14 // Hewlett-Packard Non-Stop Kernel -#define ELFOSABI_AROS 15 // Amiga Research OS -#define ELFOSABI_FENIXOS 16 // The FenixOS highly scalable multi-core OS -// 64-255 Architecture-specific value range -#define ELFOSABI_AMDGPU_HSA 64 // AMDGPU OS for HSA compatible compute - // kernels. -#define ELFOSABI_AMDGPU_PAL 65 // AMDGPU OS for AMD PAL compatible graphics - // shaders and compute kernels. -#define ELFOSABI_AMDGPU_MESA3D 66 // AMDGPU OS for Mesa3D compatible graphics - // shaders and compute kernels. +constexpr unsigned char ELFOSABI_NONE = 0; // No extensions or unspecified +constexpr unsigned char ELFOSABI_HPUX = 1; // Hewlett-Packard HP-UX +constexpr unsigned char ELFOSABI_NETBSD = 2; // NetBSD +constexpr unsigned char ELFOSABI_LINUX = 3; // Linux +constexpr unsigned char ELFOSABI_HURD = 4; // GNU Hurd +constexpr unsigned char ELFOSABI_SOLARIS = 6; // Sun Solaris +constexpr unsigned char ELFOSABI_AIX = 7; // AIX +constexpr unsigned char ELFOSABI_IRIX = 8; // IRIX +constexpr unsigned char ELFOSABI_FREEBSD = 9; // FreeBSD +constexpr unsigned char ELFOSABI_TRU64 = 10; // Compaq TRU64 UNIX +constexpr unsigned char ELFOSABI_MODESTO = 11; // Novell Modesto +constexpr unsigned char ELFOSABI_OPENBSD = 12; // Open BSD +constexpr unsigned char ELFOSABI_OPENVMS = 13; // Open VMS +constexpr unsigned char ELFOSABI_NSK = 14; // Hewlett-Packard Non-Stop Kernel +constexpr unsigned char ELFOSABI_AROS = 15; // Amiga Research OS +constexpr unsigned char ELFOSABI_FENIXOS = 16; // The FenixOS highly scalable multi-core OS +constexpr unsigned char ELFOSABI_NUXI = 17; // Nuxi CloudABI +constexpr unsigned char ELFOSABI_OPENVOS = 18; // Stratus Technologies OpenVOS +constexpr unsigned char ELFOSABI_ARM = 97; // ARM +constexpr unsigned char ELFOSABI_STANDALONE = 255; // Standalone (embedded) application +// 64-255 Architecture-specific value range +// AMDGPU OS for HSA compatible compute kernels +constexpr unsigned char ELFOSABI_AMDGPU_HSA = 64; +// AMDGPU OS for AMD PAL compatible graphics +// shaders and compute kernels +constexpr unsigned char ELFOSABI_AMDGPU_PAL = 65; +// AMDGPU OS for Mesa3D compatible graphics +// shaders and compute kernels +constexpr unsigned char ELFOSABI_AMDGPU_MESA3D = 66; +// clang-format on + +constexpr unsigned char ELFABIVERSION_AMDGPU_HSA_V2 = 0; +constexpr unsigned char ELFABIVERSION_AMDGPU_HSA_V3 = 1; +constexpr unsigned char ELFABIVERSION_AMDGPU_HSA_V4 = 2; // AMDGPU specific e_flags -#define EF_AMDGPU_MACH 0x0ff // AMDGPU processor selection mask. -#define EF_AMDGPU_XNACK 0x100 // Indicates if the XNACK target feature is - // enabled for all code contained in the ELF. +constexpr Elf_Word EF_AMDGPU_MACH = 0x0ff; // AMDGPU processor selection mask. +// Indicates if the XNACK target feature is +// enabled for all code contained in the ELF. +constexpr Elf_Word EF_AMDGPU_XNACK = 0x100; + +constexpr Elf_Word EF_AMDGPU_FEATURE_XNACK_V2 = 0x01; +constexpr Elf_Word EF_AMDGPU_FEATURE_TRAP_HANDLER_V2 = 0x02; +constexpr Elf_Word EF_AMDGPU_FEATURE_XNACK_V3 = 0x100; +constexpr Elf_Word EF_AMDGPU_FEATURE_SRAMECC_V3 = 0x200; +constexpr Elf_Word EF_AMDGPU_FEATURE_XNACK_V4 = 0x300; +constexpr Elf_Word EF_AMDGPU_FEATURE_XNACK_UNSUPPORTED_V4 = 0x000; +constexpr Elf_Word EF_AMDGPU_FEATURE_XNACK_ANY_V4 = 0x100; +constexpr Elf_Word EF_AMDGPU_FEATURE_XNACK_OFF_V4 = 0x200; +constexpr Elf_Word EF_AMDGPU_FEATURE_XNACK_ON_V4 = 0x300; +constexpr Elf_Word EF_AMDGPU_FEATURE_SRAMECC_V4 = 0xc00; +constexpr Elf_Word EF_AMDGPU_FEATURE_SRAMECC_UNSUPPORTED_V4 = 0x000; +constexpr Elf_Word EF_AMDGPU_FEATURE_SRAMECC_ANY_V4 = 0x400; +constexpr Elf_Word EF_AMDGPU_FEATURE_SRAMECC_OFF_V4 = 0x800; +constexpr Elf_Word EF_AMDGPU_FEATURE_SRAMECC_ON_V4 = 0xc00; + // AMDGPU processors -#define EF_AMDGPU_MACH_NONE 0x000 // Unspecified processor. -#define EF_AMDGPU_MACH_R600_R600 0x001 -#define EF_AMDGPU_MACH_R600_R630 0x002 -#define EF_AMDGPU_MACH_R600_RS880 0x003 -#define EF_AMDGPU_MACH_R600_RV670 0x004 -#define EF_AMDGPU_MACH_R600_RV710 0x005 -#define EF_AMDGPU_MACH_R600_RV730 0x006 -#define EF_AMDGPU_MACH_R600_RV770 0x007 -#define EF_AMDGPU_MACH_R600_CEDAR 0x008 -#define EF_AMDGPU_MACH_R600_CYPRESS 0x009 -#define EF_AMDGPU_MACH_R600_JUNIPER 0x00a -#define EF_AMDGPU_MACH_R600_REDWOOD 0x00b -#define EF_AMDGPU_MACH_R600_SUMO 0x00c -#define EF_AMDGPU_MACH_R600_BARTS 0x00d -#define EF_AMDGPU_MACH_R600_CAICOS 0x00e -#define EF_AMDGPU_MACH_R600_CAYMAN 0x00f -#define EF_AMDGPU_MACH_R600_TURKS 0x010 -#define EF_AMDGPU_MACH_R600_RESERVED_FIRST 0x011 -#define EF_AMDGPU_MACH_R600_RESERVED_LAST 0x01f -#define EF_AMDGPU_MACH_R600_FIRST EF_AMDGPU_MACH_R600_R600 -#define EF_AMDGPU_MACH_R600_LAST EF_AMDGPU_MACH_R600_TURKS -#define EF_AMDGPU_MACH_AMDGCN_GFX600 0x020 -#define EF_AMDGPU_MACH_AMDGCN_GFX601 0x021 -#define EF_AMDGPU_MACH_AMDGCN_GFX700 0x022 -#define EF_AMDGPU_MACH_AMDGCN_GFX701 0x023 -#define EF_AMDGPU_MACH_AMDGCN_GFX702 0x024 -#define EF_AMDGPU_MACH_AMDGCN_GFX703 0x025 -#define EF_AMDGPU_MACH_AMDGCN_GFX704 0x026 -#define EF_AMDGPU_MACH_AMDGCN_GFX801 0x028 -#define EF_AMDGPU_MACH_AMDGCN_GFX802 0x029 -#define EF_AMDGPU_MACH_AMDGCN_GFX803 0x02a -#define EF_AMDGPU_MACH_AMDGCN_GFX810 0x02b -#define EF_AMDGPU_MACH_AMDGCN_GFX900 0x02c -#define EF_AMDGPU_MACH_AMDGCN_GFX902 0x02d -#define EF_AMDGPU_MACH_AMDGCN_GFX904 0x02e -#define EF_AMDGPU_MACH_AMDGCN_GFX906 0x02f -#define EF_AMDGPU_MACH_AMDGCN_RESERVED0 0x027 -#define EF_AMDGPU_MACH_AMDGCN_RESERVED1 0x030 -#define EF_AMDGPU_MACH_AMDGCN_FIRST EF_AMDGPU_MACH_AMDGCN_GFX600 -#define EF_AMDGPU_MACH_AMDGCN_LAST EF_AMDGPU_MACH_AMDGCN_GFX906 +constexpr Elf_Word EF_AMDGPU_MACH_NONE = 0x000; // Unspecified processor. +constexpr Elf_Word EF_AMDGPU_MACH_R600_R600 = 0x001; +constexpr Elf_Word EF_AMDGPU_MACH_R600_R630 = 0x002; +constexpr Elf_Word EF_AMDGPU_MACH_R600_RS880 = 0x003; +constexpr Elf_Word EF_AMDGPU_MACH_R600_RV670 = 0x004; +constexpr Elf_Word EF_AMDGPU_MACH_R600_RV710 = 0x005; +constexpr Elf_Word EF_AMDGPU_MACH_R600_RV730 = 0x006; +constexpr Elf_Word EF_AMDGPU_MACH_R600_RV770 = 0x007; +constexpr Elf_Word EF_AMDGPU_MACH_R600_CEDAR = 0x008; +constexpr Elf_Word EF_AMDGPU_MACH_R600_CYPRESS = 0x009; +constexpr Elf_Word EF_AMDGPU_MACH_R600_JUNIPER = 0x00a; +constexpr Elf_Word EF_AMDGPU_MACH_R600_REDWOOD = 0x00b; +constexpr Elf_Word EF_AMDGPU_MACH_R600_SUMO = 0x00c; +constexpr Elf_Word EF_AMDGPU_MACH_R600_BARTS = 0x00d; +constexpr Elf_Word EF_AMDGPU_MACH_R600_CAICOS = 0x00e; +constexpr Elf_Word EF_AMDGPU_MACH_R600_CAYMAN = 0x00f; +constexpr Elf_Word EF_AMDGPU_MACH_R600_TURKS = 0x010; +constexpr Elf_Word EF_AMDGPU_MACH_R600_RESERVED_FIRST = 0x011; +constexpr Elf_Word EF_AMDGPU_MACH_R600_RESERVED_LAST = 0x01f; +constexpr Elf_Word EF_AMDGPU_MACH_R600_FIRST = EF_AMDGPU_MACH_R600_R600; +constexpr Elf_Word EF_AMDGPU_MACH_R600_LAST = EF_AMDGPU_MACH_R600_TURKS; + +// AMDGCN-based processors. +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX600 = 0x020; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX601 = 0x021; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX700 = 0x022; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX701 = 0x023; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX702 = 0x024; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX703 = 0x025; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX704 = 0x026; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_RESERVED_0X27 = 0x027; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX801 = 0x028; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX802 = 0x029; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX803 = 0x02a; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX810 = 0x02b; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX900 = 0x02c; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX902 = 0x02d; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX904 = 0x02e; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX906 = 0x02f; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX908 = 0x030; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX909 = 0x031; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX90C = 0x032; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX1010 = 0x033; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX1011 = 0x034; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX1012 = 0x035; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX1030 = 0x036; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX1031 = 0x037; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX1032 = 0x038; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX1033 = 0x039; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX602 = 0x03a; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX705 = 0x03b; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX805 = 0x03c; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_RESERVED_0X3D = 0x03d; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX1034 = 0x03e; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX90A = 0x03f; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_RESERVED_0X40 = 0x040; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_RESERVED_0X41 = 0x041; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_GFX1013 = 0x042; +// First/last AMDGCN-based processors. +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_FIRST = EF_AMDGPU_MACH_AMDGCN_GFX600; +constexpr Elf_Word EF_AMDGPU_MACH_AMDGCN_LAST = EF_AMDGPU_MACH_AMDGCN_GFX1013; ///////////////////// // Sections constants // Section indexes -#define SHN_UNDEF 0 -#define SHN_LORESERVE 0xFF00 -#define SHN_LOPROC 0xFF00 -#define SHN_HIPROC 0xFF1F -#define SHN_LOOS 0xFF20 -#define SHN_HIOS 0xFF3F -#define SHN_ABS 0xFFF1 -#define SHN_COMMON 0xFFF2 -#define SHN_XINDEX 0xFFFF -#define SHN_HIRESERVE 0xFFFF +constexpr Elf_Word SHN_UNDEF = 0; +constexpr Elf_Word SHN_LORESERVE = 0xFF00; +constexpr Elf_Word SHN_LOPROC = 0xFF00; +constexpr Elf_Word SHN_HIPROC = 0xFF1F; +constexpr Elf_Word SHN_LOOS = 0xFF20; +constexpr Elf_Word SHN_HIOS = 0xFF3F; +constexpr Elf_Word SHN_ABS = 0xFFF1; +constexpr Elf_Word SHN_COMMON = 0xFFF2; +constexpr Elf_Word SHN_XINDEX = 0xFFFF; +constexpr Elf_Word SHN_HIRESERVE = 0xFFFF; // Section types -#define SHT_NULL 0 -#define SHT_PROGBITS 1 -#define SHT_SYMTAB 2 -#define SHT_STRTAB 3 -#define SHT_RELA 4 -#define SHT_HASH 5 -#define SHT_DYNAMIC 6 -#define SHT_NOTE 7 -#define SHT_NOBITS 8 -#define SHT_REL 9 -#define SHT_SHLIB 10 -#define SHT_DYNSYM 11 -#define SHT_INIT_ARRAY 14 -#define SHT_FINI_ARRAY 15 -#define SHT_PREINIT_ARRAY 16 -#define SHT_GROUP 17 -#define SHT_SYMTAB_SHNDX 18 -#define SHT_LOOS 0x60000000 -#define SHT_HIOS 0x6fffffff -#define SHT_LOPROC 0x70000000 -#define SHT_HIPROC 0x7FFFFFFF -#define SHT_LOUSER 0x80000000 -#define SHT_HIUSER 0xFFFFFFFF +constexpr Elf_Word SHT_NULL = 0; +constexpr Elf_Word SHT_PROGBITS = 1; +constexpr Elf_Word SHT_SYMTAB = 2; +constexpr Elf_Word SHT_STRTAB = 3; +constexpr Elf_Word SHT_RELA = 4; +constexpr Elf_Word SHT_HASH = 5; +constexpr Elf_Word SHT_DYNAMIC = 6; +constexpr Elf_Word SHT_NOTE = 7; +constexpr Elf_Word SHT_NOBITS = 8; +constexpr Elf_Word SHT_REL = 9; +constexpr Elf_Word SHT_SHLIB = 10; +constexpr Elf_Word SHT_DYNSYM = 11; +constexpr Elf_Word SHT_INIT_ARRAY = 14; +constexpr Elf_Word SHT_FINI_ARRAY = 15; +constexpr Elf_Word SHT_PREINIT_ARRAY = 16; +constexpr Elf_Word SHT_GROUP = 17; +constexpr Elf_Word SHT_SYMTAB_SHNDX = 18; +constexpr Elf_Word SHT_GNU_ATTRIBUTES = 0x6ffffff5; +constexpr Elf_Word SHT_GNU_HASH = 0x6ffffff6; +constexpr Elf_Word SHT_GNU_LIBLIST = 0x6ffffff7; +constexpr Elf_Word SHT_CHECKSUM = 0x6ffffff8; +constexpr Elf_Word SHT_LOSUNW = 0x6ffffffa; +constexpr Elf_Word SHT_SUNW_move = 0x6ffffffa; +constexpr Elf_Word SHT_SUNW_COMDAT = 0x6ffffffb; +constexpr Elf_Word SHT_SUNW_syminfo = 0x6ffffffc; +constexpr Elf_Word SHT_GNU_verdef = 0x6ffffffd; +constexpr Elf_Word SHT_GNU_verneed = 0x6ffffffe; +constexpr Elf_Word SHT_GNU_versym = 0x6fffffff; +constexpr Elf_Word SHT_LOOS = 0x60000000; +constexpr Elf_Word SHT_HIOS = 0x6fffffff; +constexpr Elf_Word SHT_LOPROC = 0x70000000; +constexpr Elf_Word SHT_ARM_EXIDX = 0x70000001; +constexpr Elf_Word SHT_ARM_PREEMPTMAP = 0x70000002; +constexpr Elf_Word SHT_ARM_ATTRIBUTES = 0x70000003; +constexpr Elf_Word SHT_ARM_DEBUGOVERLAY = 0x70000004; +constexpr Elf_Word SHT_ARM_OVERLAYSECTION = 0x70000005; +constexpr Elf_Word SHT_HIPROC = 0x7FFFFFFF; +constexpr Elf_Word SHT_LOUSER = 0x80000000; +// Used by Nintendo Wii U +constexpr Elf_Word SHT_RPL_EXPORTS = 0x80000001; +constexpr Elf_Word SHT_RPL_IMPORTS = 0x80000002; +constexpr Elf_Word SHT_RPL_CRCS = 0x80000003; +constexpr Elf_Word SHT_RPL_FILEINFO = 0x80000004; +constexpr Elf_Word SHT_HIUSER = 0xFFFFFFFF; // Section attribute flags -#define SHF_WRITE 0x1 -#define SHF_ALLOC 0x2 -#define SHF_EXECINSTR 0x4 -#define SHF_MERGE 0x10 -#define SHF_STRINGS 0x20 -#define SHF_INFO_LINK 0x40 -#define SHF_LINK_ORDER 0x80 -#define SHF_OS_NONCONFORMING 0x100 -#define SHF_GROUP 0x200 -#define SHF_TLS 0x400 -#define SHF_MASKOS 0x0ff00000 -#define SHF_MASKPROC 0xF0000000 +constexpr Elf_Xword SHF_WRITE = 0x1; +constexpr Elf_Xword SHF_ALLOC = 0x2; +constexpr Elf_Xword SHF_EXECINSTR = 0x4; +constexpr Elf_Xword SHF_MERGE = 0x10; +constexpr Elf_Xword SHF_STRINGS = 0x20; +constexpr Elf_Xword SHF_INFO_LINK = 0x40; +constexpr Elf_Xword SHF_LINK_ORDER = 0x80; +constexpr Elf_Xword SHF_OS_NONCONFORMING = 0x100; +constexpr Elf_Xword SHF_GROUP = 0x200; +constexpr Elf_Xword SHF_TLS = 0x400; +constexpr Elf_Xword SHF_COMPRESSED = 0x800; +constexpr Elf_Xword SHF_GNU_RETAIN = 0x200000; +constexpr Elf_Xword SHF_GNU_MBIND = 0x01000000; +// flag used in Nintendo RPX/RPL to indicate section data is compressed +constexpr Elf_Xword SHF_RPX_DEFLATE = 0x08000000; +constexpr Elf_Xword SHF_MASKOS = 0x0FF00000; +constexpr Elf_Xword SHF_MIPS_GPREL = 0x10000000; +constexpr Elf_Xword SHF_ORDERED = 0x40000000; +constexpr Elf_Xword SHF_EXCLUDE = 0x80000000; +constexpr Elf_Xword SHF_MASKPROC = 0xF0000000; // Section group flags -#define GRP_COMDAT 0x1 -#define GRP_MASKOS 0x0ff00000 -#define GRP_MASKPROC 0xf0000000 +constexpr Elf_Word GRP_COMDAT = 0x1; +constexpr Elf_Word GRP_MASKOS = 0x0ff00000; +constexpr Elf_Word GRP_MASKPROC = 0xf0000000; // Symbol binding -#define STB_LOCAL 0 -#define STB_GLOBAL 1 -#define STB_WEAK 2 -#define STB_LOOS 10 -#define STB_HIOS 12 -#define STB_MULTIDEF 13 -#define STB_LOPROC 13 -#define STB_HIPROC 15 +constexpr unsigned char STB_LOCAL = 0; +constexpr unsigned char STB_GLOBAL = 1; +constexpr unsigned char STB_WEAK = 2; +constexpr unsigned char STB_LOOS = 10; +constexpr unsigned char STB_HIOS = 12; +constexpr unsigned char STB_MULTIDEF = 13; +constexpr unsigned char STB_LOPROC = 13; +constexpr unsigned char STB_HIPROC = 15; -// Note types -#define NT_AMDGPU_METADATA 1 -#define NT_AMD_AMDGPU_HSA_METADATA 10 -#define NT_AMD_AMDGPU_ISA 11 -#define NT_AMD_AMDGPU_PAL_METADATA 12 +// Values of note segment descriptor types for core files +constexpr Elf_Word NT_PRSTATUS = 1; // Contains copy of prstatus struct +constexpr Elf_Word NT_FPREGSET = 2; // Contains copy of fpregset struct +constexpr Elf_Word NT_PRPSINFO = 3; // Contains copy of prpsinfo struct +constexpr Elf_Word NT_TASKSTRUCT = 4; // Contains copy of task struct +constexpr Elf_Word NT_AUXV = 6; // Contains copy of Elfxx_auxv_t +constexpr Elf_Word NT_SIGINFO = 0x53494749; // Fields of siginfo_t. +constexpr Elf_Word NT_FILE = 0x46494c45; // Description of mapped files. + +// Note segments for core files on dir-style procfs systems. +constexpr Elf_Word NT_PSTATUS = 10; // Has a struct pstatus +constexpr Elf_Word NT_FPREGS = 12; // Has a struct fpregset +constexpr Elf_Word NT_PSINFO = 13; // Has a struct psinfo +constexpr Elf_Word NT_LWPSTATUS = 16; // Has a struct lwpstatus_t +constexpr Elf_Word NT_LWPSINFO = 17; // Has a struct lwpsinfo_t +constexpr Elf_Word NT_WIN32PSTATUS = 18; // Has a struct win32_pstatus + +// clang-format off + +// Note name must be "LINUX" +constexpr Elf_Word NT_PRXFPREG = 0x46e62b7f; // Contains a user_xfpregs_struct +constexpr Elf_Word NT_PPC_VMX = 0x100; // PowerPC Altivec/VMX registers +constexpr Elf_Word NT_PPC_VSX = 0x102; // PowerPC VSX registers +constexpr Elf_Word NT_PPC_TAR = 0x103; // PowerPC Target Address Register +constexpr Elf_Word NT_PPC_PPR = 0x104; // PowerPC Program Priority Register +constexpr Elf_Word NT_PPC_DSCR = 0x105; // PowerPC Data Stream Control Register +constexpr Elf_Word NT_PPC_EBB = 0x106; // PowerPC Event Based Branch Registers +constexpr Elf_Word NT_PPC_PMU = 0x107; // PowerPC Performance Monitor Registers +constexpr Elf_Word NT_PPC_TM_CGPR = 0x108; // PowerPC TM checkpointed GPR Registers +constexpr Elf_Word NT_PPC_TM_CFPR = 0x109; // PowerPC TM checkpointed FPR Registers +constexpr Elf_Word NT_PPC_TM_CVMX = 0x10a; // PowerPC TM checkpointed VMX Registers +constexpr Elf_Word NT_PPC_TM_CVSX = 0x10b; // PowerPC TM checkpointed VSX Registers +constexpr Elf_Word NT_PPC_TM_SPR = 0x10c; // PowerPC TM Special Purpose Registers +constexpr Elf_Word NT_PPC_TM_CTAR = 0x10d; // PowerPC TM checkpointed TAR +constexpr Elf_Word NT_PPC_TM_CPPR = 0x10e; // PowerPC TM checkpointed PPR +constexpr Elf_Word NT_PPC_TM_CDSCR = 0x10f; // PowerPC TM checkpointed Data SCR +constexpr Elf_Word NT_386_TLS = 0x200; // x86 TLS information +constexpr Elf_Word NT_386_IOPERM = 0x201; // x86 io permissions +constexpr Elf_Word NT_X86_XSTATE = 0x202; // x86 XSAVE extended state +constexpr Elf_Word NT_X86_CET = 0x203; // x86 CET state. +constexpr Elf_Word NT_S390_HIGH_GPRS = 0x300; // S/390 upper halves of GPRs +constexpr Elf_Word NT_S390_TIMER = 0x301; // S390 timer +constexpr Elf_Word NT_S390_TODCMP = 0x302; // S390 TOD clock comparator +constexpr Elf_Word NT_S390_TODPREG = 0x303; // S390 TOD programmable register +constexpr Elf_Word NT_S390_CTRS = 0x304; // S390 control registers +constexpr Elf_Word NT_S390_PREFIX = 0x305; // S390 prefix register +constexpr Elf_Word NT_S390_LAST_BREAK = 0x306; // S390 breaking event address +constexpr Elf_Word NT_S390_SYSTEM_CALL = 0x307; // S390 system call restart data +constexpr Elf_Word NT_S390_TDB = 0x308; // S390 transaction diagnostic block +constexpr Elf_Word NT_S390_VXRS_LOW = 0x309; // S390 vector registers 0-15 upper half +constexpr Elf_Word NT_S390_VXRS_HIGH = 0x30a; // S390 vector registers 16-31 +constexpr Elf_Word NT_S390_GS_CB = 0x30b; // s390 guarded storage registers +constexpr Elf_Word NT_S390_GS_BC = 0x30c; // s390 guarded storage broadcast control block +constexpr Elf_Word NT_ARM_VFP = 0x400; // ARM VFP registers +constexpr Elf_Word NT_ARM_TLS = 0x401; // AArch TLS registers +constexpr Elf_Word NT_ARM_HW_BREAK = 0x402; // AArch hardware breakpoint registers +constexpr Elf_Word NT_ARM_HW_WATCH = 0x403; // AArch hardware watchpoint registers +constexpr Elf_Word NT_ARM_SVE = 0x405; // AArch SVE registers. +constexpr Elf_Word NT_ARM_PAC_MASK = 0x406; // AArch pointer authentication code masks +constexpr Elf_Word NT_ARM_PACA_KEYS = 0x407; // ARM pointer authentication address keys +constexpr Elf_Word NT_ARM_PACG_KEYS = 0x408; // ARM pointer authentication generic keys +constexpr Elf_Word NT_ARM_TAGGED_ADDR_CTRL = 0x409; // AArch64 tagged address control (prctl()) +constexpr Elf_Word NT_ARM_PAC_ENABLED_KEYS = 0x40a; // AArch64 pointer authentication enabled keys (prctl()) +constexpr Elf_Word NT_ARC_V2 = 0x600; // ARC HS accumulator/extra registers. +constexpr Elf_Word NT_LARCH_CPUCFG = 0xa00; // LoongArch CPU config registers +constexpr Elf_Word NT_LARCH_CSR = 0xa01; // LoongArch Control State Registers +constexpr Elf_Word NT_LARCH_LSX = 0xa02; // LoongArch SIMD eXtension registers +constexpr Elf_Word NT_LARCH_LASX = 0xa03; // LoongArch Advanced SIMD eXtension registers +constexpr Elf_Word NT_RISCV_CSR = 0x900; // RISC-V Control and Status Registers + +// Note name must be "CORE" +constexpr Elf_Word NT_LARCH_LBT = 0xa04; // LoongArch Binary Translation registers + +/* The range 0xff000000 to 0xffffffff is set aside for notes that don't + originate from any particular operating system. */ +constexpr Elf_Word NT_GDB_TDESC = 0xff000000; // Contains copy of GDB's target description XML. +constexpr Elf_Word NT_MEMTAG = 0xff000001; // Contains a copy of the memory tags. +/* ARM-specific NT_MEMTAG types. */ +constexpr Elf_Word NT_MEMTAG_TYPE_AARCH_MTE = 0x400; // MTE memory tags for AArch64. + +constexpr Elf_Word NT_STAPSDT = 3; // Note segment for SystemTap probes. + +// Note name is "FreeBSD" +constexpr Elf_Word NT_FREEBSD_THRMISC = 7; // Thread miscellaneous info. +constexpr Elf_Word NT_FREEBSD_PROCSTAT_PROC = 8; // Procstat proc data. +constexpr Elf_Word NT_FREEBSD_PROCSTAT_FILES = 9; // Procstat files data. +constexpr Elf_Word NT_FREEBSD_PROCSTAT_VMMAP = 10; // Procstat vmmap data. +constexpr Elf_Word NT_FREEBSD_PROCSTAT_GROUPS = 11; // Procstat groups data. +constexpr Elf_Word NT_FREEBSD_PROCSTAT_UMASK = 12; // Procstat umask data. +constexpr Elf_Word NT_FREEBSD_PROCSTAT_RLIMIT = 13; // Procstat rlimit data. +constexpr Elf_Word NT_FREEBSD_PROCSTAT_OSREL = 14; // Procstat osreldate data. +constexpr Elf_Word NT_FREEBSD_PROCSTAT_PSSTRINGS = 15; // Procstat ps_strings data. +constexpr Elf_Word NT_FREEBSD_PROCSTAT_AUXV = 16; // Procstat auxv data. +constexpr Elf_Word NT_FREEBSD_PTLWPINFO = 17; // Thread ptrace miscellaneous info. + +// Note name must start with "NetBSD-CORE" +constexpr Elf_Word NT_NETBSDCORE_PROCINFO = 1; // Has a struct procinfo +constexpr Elf_Word NT_NETBSDCORE_AUXV = 2; // Has auxv data +constexpr Elf_Word NT_NETBSDCORE_LWPSTATUS = 24; // Has LWPSTATUS data +constexpr Elf_Word NT_NETBSDCORE_FIRSTMACH = 32; // start of machdep note types + +// Note name is "OpenBSD" +constexpr Elf_Word NT_OPENBSD_PROCINFO = 10; +constexpr Elf_Word NT_OPENBSD_AUXV = 11; +constexpr Elf_Word NT_OPENBSD_REGS = 20; +constexpr Elf_Word NT_OPENBSD_FPREGS = 21; +constexpr Elf_Word NT_OPENBSD_XFPREGS = 22; +constexpr Elf_Word NT_OPENBSD_WCOOKIE = 23; + +// Note name must start with "SPU" +constexpr Elf_Word NT_SPU = 1; + +// Values of note segment descriptor types for object files +constexpr Elf_Word NT_VERSION = 1; // Contains a version string. +constexpr Elf_Word NT_ARCH = 2; // Contains an architecture string. +constexpr Elf_Word NT_GO_BUILDID = 4; // Contains GO buildid data. + +// Values for notes in non-core files using name "GNU" +constexpr Elf_Word NT_GNU_ABI_TAG = 1; +constexpr Elf_Word NT_GNU_HWCAP = 2; // Used by ld.so and kernel vDSO. +constexpr Elf_Word NT_GNU_BUILD_ID = 3; // Generated by ld --build-id. +constexpr Elf_Word NT_GNU_GOLD_VERSION = 4; // Generated by gold. +constexpr Elf_Word NT_GNU_PROPERTY_TYPE_0 = 5; // Generated by gcc. +// clang-format on + +constexpr Elf_Word NT_GNU_BUILD_ATTRIBUTE_OPEN = 0x100; +constexpr Elf_Word NT_GNU_BUILD_ATTRIBUTE_FUNC = 0x101; // Symbol types -#define STT_NOTYPE 0 -#define STT_OBJECT 1 -#define STT_FUNC 2 -#define STT_SECTION 3 -#define STT_FILE 4 -#define STT_COMMON 5 -#define STT_TLS 6 -#define STT_LOOS 10 -#define STT_AMDGPU_HSA_KERNEL 10 -#define STT_HIOS 12 -#define STT_LOPROC 13 -#define STT_HIPROC 15 +constexpr Elf_Word STT_NOTYPE = 0; +constexpr Elf_Word STT_OBJECT = 1; +constexpr Elf_Word STT_FUNC = 2; +constexpr Elf_Word STT_SECTION = 3; +constexpr Elf_Word STT_FILE = 4; +constexpr Elf_Word STT_COMMON = 5; +constexpr Elf_Word STT_TLS = 6; +constexpr Elf_Word STT_LOOS = 10; +constexpr Elf_Word STT_AMDGPU_HSA_KERNEL = 10; +constexpr Elf_Word STT_HIOS = 12; +constexpr Elf_Word STT_LOPROC = 13; +constexpr Elf_Word STT_HIPROC = 15; // Symbol visibility -#define STV_DEFAULT 0 -#define STV_INTERNAL 1 -#define STV_HIDDEN 2 -#define STV_PROTECTED 3 +constexpr unsigned char STV_DEFAULT = 0; +constexpr unsigned char STV_INTERNAL = 1; +constexpr unsigned char STV_HIDDEN = 2; +constexpr unsigned char STV_PROTECTED = 3; // Undefined name -#define STN_UNDEF 0 +constexpr Elf_Word STN_UNDEF = 0; // Relocation types -#define R_386_NONE 0 -#define R_X86_64_NONE 0 -#define R_AMDGPU_NONE 0 -#define R_386_32 1 -#define R_X86_64_64 1 -#define R_AMDGPU_ABS32_LO 1 -#define R_386_PC32 2 -#define R_X86_64_PC32 2 -#define R_AMDGPU_ABS32_HI 2 -#define R_386_GOT32 3 -#define R_X86_64_GOT32 3 -#define R_AMDGPU_ABS64 3 -#define R_386_PLT32 4 -#define R_X86_64_PLT32 4 -#define R_AMDGPU_REL32 4 -#define R_386_COPY 5 -#define R_X86_64_COPY 5 -#define R_AMDGPU_REL64 5 -#define R_386_GLOB_DAT 6 -#define R_X86_64_GLOB_DAT 6 -#define R_AMDGPU_ABS32 6 -#define R_386_JMP_SLOT 7 -#define R_X86_64_JUMP_SLOT 7 -#define R_AMDGPU_GOTPCREL 7 -#define R_386_RELATIVE 8 -#define R_X86_64_RELATIVE 8 -#define R_AMDGPU_GOTPCREL32_LO 8 -#define R_386_GOTOFF 9 -#define R_X86_64_GOTPCREL 9 -#define R_AMDGPU_GOTPCREL32_HI 9 -#define R_386_GOTPC 10 -#define R_X86_64_32 10 -#define R_AMDGPU_REL32_LO 10 -#define R_386_32PLT 11 -#define R_X86_64_32S 11 -#define R_AMDGPU_REL32_HI 11 -#define R_X86_64_16 12 -#define R_X86_64_PC16 13 -#define R_AMDGPU_RELATIVE64 13 -#define R_386_TLS_TPOFF 14 -#define R_X86_64_8 14 -#define R_386_TLS_IE 15 -#define R_X86_64_PC8 15 -#define R_386_TLS_GOTIE 16 -#define R_X86_64_DTPMOD64 16 -#define R_386_TLS_LE 17 -#define R_X86_64_DTPOFF64 17 -#define R_386_TLS_GD 18 -#define R_X86_64_TPOFF64 18 -#define R_386_TLS_LDM 19 -#define R_X86_64_TLSGD 19 -#define R_386_16 20 -#define R_X86_64_TLSLD 20 -#define R_386_PC16 21 -#define R_X86_64_DTPOFF32 21 -#define R_386_8 22 -#define R_X86_64_GOTTPOFF 22 -#define R_386_PC8 23 -#define R_X86_64_TPOFF32 23 -#define R_386_TLS_GD_32 24 -#define R_X86_64_PC64 24 -#define R_386_TLS_GD_PUSH 25 -#define R_X86_64_GOTOFF64 25 -#define R_386_TLS_GD_CALL 26 -#define R_X86_64_GOTPC32 26 -#define R_386_TLS_GD_POP 27 -#define R_X86_64_GOT64 27 -#define R_386_TLS_LDM_32 28 -#define R_X86_64_GOTPCREL64 28 -#define R_386_TLS_LDM_PUSH 29 -#define R_X86_64_GOTPC64 29 -#define R_386_TLS_LDM_CALL 30 -#define R_X86_64_GOTPLT64 30 -#define R_386_TLS_LDM_POP 31 -#define R_X86_64_PLTOFF64 31 -#define R_386_TLS_LDO_32 32 -#define R_386_TLS_IE_32 33 -#define R_386_TLS_LE_32 34 -#define R_X86_64_GOTPC32_TLSDESC 34 -#define R_386_TLS_DTPMOD32 35 -#define R_X86_64_TLSDESC_CALL 35 -#define R_386_TLS_DTPOFF32 36 -#define R_X86_64_TLSDESC 36 -#define R_386_TLS_TPOFF32 37 -#define R_X86_64_IRELATIVE 37 -#define R_386_SIZE32 38 -#define R_386_TLS_GOTDESC 39 -#define R_386_TLS_DESC_CALL 40 -#define R_386_TLS_DESC 41 -#define R_386_IRELATIVE 42 -#define R_386_GOT32X 43 -#define R_X86_64_GNU_VTINHERIT 250 -#define R_X86_64_GNU_VTENTRY 251 +// X86 +constexpr unsigned R_386_NONE = 0; +constexpr unsigned R_X86_64_NONE = 0; +constexpr unsigned R_AMDGPU_NONE = 0; +constexpr unsigned R_386_32 = 1; +constexpr unsigned R_X86_64_64 = 1; +constexpr unsigned R_AMDGPU_ABS32_LO = 1; +constexpr unsigned R_386_PC32 = 2; +constexpr unsigned R_X86_64_PC32 = 2; +constexpr unsigned R_AMDGPU_ABS32_HI = 2; +constexpr unsigned R_386_GOT32 = 3; +constexpr unsigned R_X86_64_GOT32 = 3; +constexpr unsigned R_AMDGPU_ABS64 = 3; +constexpr unsigned R_386_PLT32 = 4; +constexpr unsigned R_X86_64_PLT32 = 4; +constexpr unsigned R_AMDGPU_REL32 = 4; +constexpr unsigned R_386_COPY = 5; +constexpr unsigned R_X86_64_COPY = 5; +constexpr unsigned R_AMDGPU_REL64 = 5; +constexpr unsigned R_386_GLOB_DAT = 6; +constexpr unsigned R_X86_64_GLOB_DAT = 6; +constexpr unsigned R_AMDGPU_ABS32 = 6; +constexpr unsigned R_386_JMP_SLOT = 7; +constexpr unsigned R_X86_64_JUMP_SLOT = 7; +constexpr unsigned R_AMDGPU_GOTPCREL = 7; +constexpr unsigned R_386_RELATIVE = 8; +constexpr unsigned R_X86_64_RELATIVE = 8; +constexpr unsigned R_AMDGPU_GOTPCREL32_LO = 8; +constexpr unsigned R_386_GOTOFF = 9; +constexpr unsigned R_X86_64_GOTPCREL = 9; +constexpr unsigned R_AMDGPU_GOTPCREL32_HI = 9; +constexpr unsigned R_386_GOTPC = 10; +constexpr unsigned R_X86_64_32 = 10; +constexpr unsigned R_AMDGPU_REL32_LO = 10; +constexpr unsigned R_386_32PLT = 11; +constexpr unsigned R_X86_64_32S = 11; +constexpr unsigned R_AMDGPU_REL32_HI = 11; +constexpr unsigned R_X86_64_16 = 12; +constexpr unsigned R_X86_64_PC16 = 13; +constexpr unsigned R_AMDGPU_RELATIVE64 = 13; +constexpr unsigned R_386_TLS_TPOFF = 14; +constexpr unsigned R_X86_64_8 = 14; +constexpr unsigned R_386_TLS_IE = 15; +constexpr unsigned R_X86_64_PC8 = 15; +constexpr unsigned R_386_TLS_GOTIE = 16; +constexpr unsigned R_X86_64_DTPMOD64 = 16; +constexpr unsigned R_386_TLS_LE = 17; +constexpr unsigned R_X86_64_DTPOFF64 = 17; +constexpr unsigned R_386_TLS_GD = 18; +constexpr unsigned R_X86_64_TPOFF64 = 18; +constexpr unsigned R_386_TLS_LDM = 19; +constexpr unsigned R_X86_64_TLSGD = 19; +constexpr unsigned R_386_16 = 20; +constexpr unsigned R_X86_64_TLSLD = 20; +constexpr unsigned R_386_PC16 = 21; +constexpr unsigned R_X86_64_DTPOFF32 = 21; +constexpr unsigned R_386_8 = 22; +constexpr unsigned R_X86_64_GOTTPOFF = 22; +constexpr unsigned R_386_PC8 = 23; +constexpr unsigned R_X86_64_TPOFF32 = 23; +constexpr unsigned R_386_TLS_GD_32 = 24; +constexpr unsigned R_X86_64_PC64 = 24; +constexpr unsigned R_386_TLS_GD_PUSH = 25; +constexpr unsigned R_X86_64_GOTOFF64 = 25; +constexpr unsigned R_386_TLS_GD_CALL = 26; +constexpr unsigned R_X86_64_GOTPC32 = 26; +constexpr unsigned R_386_TLS_GD_POP = 27; +constexpr unsigned R_X86_64_GOT64 = 27; +constexpr unsigned R_386_TLS_LDM_32 = 28; +constexpr unsigned R_X86_64_GOTPCREL64 = 28; +constexpr unsigned R_386_TLS_LDM_PUSH = 29; +constexpr unsigned R_X86_64_GOTPC64 = 29; +constexpr unsigned R_386_TLS_LDM_CALL = 30; +constexpr unsigned R_X86_64_GOTPLT64 = 30; +constexpr unsigned R_386_TLS_LDM_POP = 31; +constexpr unsigned R_X86_64_PLTOFF64 = 31; +constexpr unsigned R_386_TLS_LDO_32 = 32; +constexpr unsigned R_386_TLS_IE_32 = 33; +constexpr unsigned R_386_TLS_LE_32 = 34; +constexpr unsigned R_X86_64_GOTPC32_TLSDESC = 34; +constexpr unsigned R_386_TLS_DTPMOD32 = 35; +constexpr unsigned R_X86_64_TLSDESC_CALL = 35; +constexpr unsigned R_386_TLS_DTPOFF32 = 36; +constexpr unsigned R_X86_64_TLSDESC = 36; +constexpr unsigned R_386_TLS_TPOFF32 = 37; +constexpr unsigned R_X86_64_IRELATIVE = 37; +constexpr unsigned R_386_SIZE32 = 38; +constexpr unsigned R_386_TLS_GOTDESC = 39; +constexpr unsigned R_386_TLS_DESC_CALL = 40; +constexpr unsigned R_386_TLS_DESC = 41; +constexpr unsigned R_386_IRELATIVE = 42; +constexpr unsigned R_386_GOT32X = 43; +constexpr unsigned R_X86_64_GNU_VTINHERIT = 250; +constexpr unsigned R_X86_64_GNU_VTENTRY = 251; +// AArch64 +constexpr unsigned R_AARCH64_NONE = 0; +constexpr unsigned R_AARCH64_P32_ABS32 = 1; +constexpr unsigned R_AARCH64_P32_COPY = 180; +constexpr unsigned R_AARCH64_P32_GLOB_DAT = 181; +constexpr unsigned R_AARCH64_P32_JUMP_SLOT = 182; +constexpr unsigned R_AARCH64_P32_RELATIVE = 183; +constexpr unsigned R_AARCH64_P32_TLS_DTPMOD = 184; +constexpr unsigned R_AARCH64_P32_TLS_DTPREL = 185; +constexpr unsigned R_AARCH64_P32_TLS_TPREL = 186; +constexpr unsigned R_AARCH64_P32_TLSDESC = 187; +constexpr unsigned R_AARCH64_P32_IRELATIVE = 188; +constexpr unsigned R_AARCH64_ABS64 = 257; +constexpr unsigned R_AARCH64_ABS32 = 258; +constexpr unsigned R_AARCH64_ABS16 = 259; +constexpr unsigned R_AARCH64_PREL64 = 260; +constexpr unsigned R_AARCH64_PREL32 = 261; +constexpr unsigned R_AARCH64_PREL16 = 262; +constexpr unsigned R_AARCH64_MOVW_UABS_G0 = 263; +constexpr unsigned R_AARCH64_MOVW_UABS_G0_NC = 264; +constexpr unsigned R_AARCH64_MOVW_UABS_G1 = 265; +constexpr unsigned R_AARCH64_MOVW_UABS_G1_NC = 266; +constexpr unsigned R_AARCH64_MOVW_UABS_G2 = 267; +constexpr unsigned R_AARCH64_MOVW_UABS_G2_NC = 268; +constexpr unsigned R_AARCH64_MOVW_UABS_G3 = 269; +constexpr unsigned R_AARCH64_MOVW_SABS_G0 = 270; +constexpr unsigned R_AARCH64_MOVW_SABS_G1 = 271; +constexpr unsigned R_AARCH64_MOVW_SABS_G2 = 272; +constexpr unsigned R_AARCH64_LD_PREL_LO19 = 273; +constexpr unsigned R_AARCH64_ADR_PREL_LO21 = 274; +constexpr unsigned R_AARCH64_ADR_PREL_PG_HI21 = 275; +constexpr unsigned R_AARCH64_ADR_PREL_PG_HI21_NC = 276; +constexpr unsigned R_AARCH64_ADD_ABS_LO12_NC = 277; +constexpr unsigned R_AARCH64_LDST8_ABS_LO12_NC = 278; +constexpr unsigned R_AARCH64_TSTBR14 = 279; +constexpr unsigned R_AARCH64_CONDBR19 = 280; +constexpr unsigned R_AARCH64_JUMP26 = 282; +constexpr unsigned R_AARCH64_CALL26 = 283; +constexpr unsigned R_AARCH64_LDST16_ABS_LO12_NC = 284; +constexpr unsigned R_AARCH64_LDST32_ABS_LO12_NC = 285; +constexpr unsigned R_AARCH64_LDST64_ABS_LO12_NC = 286; +constexpr unsigned R_AARCH64_MOVW_PREL_G0 = 287; +constexpr unsigned R_AARCH64_MOVW_PREL_G0_NC = 288; +constexpr unsigned R_AARCH64_MOVW_PREL_G1 = 289; +constexpr unsigned R_AARCH64_MOVW_PREL_G1_NC = 290; +constexpr unsigned R_AARCH64_MOVW_PREL_G2 = 291; +constexpr unsigned R_AARCH64_MOVW_PREL_G2_NC = 292; +constexpr unsigned R_AARCH64_MOVW_PREL_G3 = 293; +constexpr unsigned R_AARCH64_LDST128_ABS_LO12_NC = 299; +constexpr unsigned R_AARCH64_MOVW_GOTOFF_G0 = 300; +constexpr unsigned R_AARCH64_MOVW_GOTOFF_G0_NC = 301; +constexpr unsigned R_AARCH64_MOVW_GOTOFF_G1 = 302; +constexpr unsigned R_AARCH64_MOVW_GOTOFF_G1_NC = 303; +constexpr unsigned R_AARCH64_MOVW_GOTOFF_G2 = 304; +constexpr unsigned R_AARCH64_MOVW_GOTOFF_G2_NC = 305; +constexpr unsigned R_AARCH64_MOVW_GOTOFF_G3 = 306; +constexpr unsigned R_AARCH64_GOTREL64 = 307; +constexpr unsigned R_AARCH64_GOTREL32 = 308; +constexpr unsigned R_AARCH64_GOT_LD_PREL19 = 309; +constexpr unsigned R_AARCH64_LD64_GOTOFF_LO15 = 310; +constexpr unsigned R_AARCH64_ADR_GOT_PAGE = 311; +constexpr unsigned R_AARCH64_LD64_GOT_LO12_NC = 312; +constexpr unsigned R_AARCH64_LD64_GOTPAGE_LO15 = 313; +constexpr unsigned R_AARCH64_TLSGD_ADR_PREL21 = 512; +constexpr unsigned R_AARCH64_TLSGD_ADR_PAGE21 = 513; +constexpr unsigned R_AARCH64_TLSGD_ADD_LO12_NC = 514; +constexpr unsigned R_AARCH64_TLSGD_MOVW_G1 = 515; +constexpr unsigned R_AARCH64_TLSGD_MOVW_G0_NC = 516; +constexpr unsigned R_AARCH64_TLSLD_ADR_PREL21 = 517; +constexpr unsigned R_AARCH64_TLSLD_ADR_PAGE21 = 518; +constexpr unsigned R_AARCH64_TLSLD_ADD_LO12_NC = 519; +constexpr unsigned R_AARCH64_TLSLD_MOVW_G1 = 520; +constexpr unsigned R_AARCH64_TLSLD_MOVW_G0_NC = 521; +constexpr unsigned R_AARCH64_TLSLD_LD_PREL19 = 522; +constexpr unsigned R_AARCH64_TLSLD_MOVW_DTPREL_G2 = 523; +constexpr unsigned R_AARCH64_TLSLD_MOVW_DTPREL_G1 = 524; +constexpr unsigned R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC = 525; +constexpr unsigned R_AARCH64_TLSLD_MOVW_DTPREL_G0 = 526; +constexpr unsigned R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC = 527; +constexpr unsigned R_AARCH64_TLSLD_ADD_DTPREL_HI12 = 528; +constexpr unsigned R_AARCH64_TLSLD_ADD_DTPREL_LO12 = 529; +constexpr unsigned R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC = 530; +constexpr unsigned R_AARCH64_TLSLD_LDST8_DTPREL_LO12 = 531; +constexpr unsigned R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC = 532; +constexpr unsigned R_AARCH64_TLSLD_LDST16_DTPREL_LO12 = 533; +constexpr unsigned R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC = 534; +constexpr unsigned R_AARCH64_TLSLD_LDST32_DTPREL_LO12 = 535; +constexpr unsigned R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC = 536; +constexpr unsigned R_AARCH64_TLSLD_LDST64_DTPREL_LO12 = 537; +constexpr unsigned R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC = 538; +constexpr unsigned R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 = 539; +constexpr unsigned R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC = 540; +constexpr unsigned R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 = 541; +constexpr unsigned R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC = 542; +constexpr unsigned R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 = 543; +constexpr unsigned R_AARCH64_TLSLE_MOVW_TPREL_G2 = 544; +constexpr unsigned R_AARCH64_TLSLE_MOVW_TPREL_G1 = 545; +constexpr unsigned R_AARCH64_TLSLE_MOVW_TPREL_G1_NC = 546; +constexpr unsigned R_AARCH64_TLSLE_MOVW_TPREL_G0 = 547; +constexpr unsigned R_AARCH64_TLSLE_MOVW_TPREL_G0_NC = 548; +constexpr unsigned R_AARCH64_TLSLE_ADD_TPREL_HI12 = 549; +constexpr unsigned R_AARCH64_TLSLE_ADD_TPREL_LO12 = 550; +constexpr unsigned R_AARCH64_TLSLE_ADD_TPREL_LO12_NC = 551; +constexpr unsigned R_AARCH64_TLSLE_LDST8_TPREL_LO12 = 552; +constexpr unsigned R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC = 553; +constexpr unsigned R_AARCH64_TLSLE_LDST16_TPREL_LO12 = 554; +constexpr unsigned R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC = 555; +constexpr unsigned R_AARCH64_TLSLE_LDST32_TPREL_LO12 = 556; +constexpr unsigned R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC = 557; +constexpr unsigned R_AARCH64_TLSLE_LDST64_TPREL_LO12 = 558; +constexpr unsigned R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC = 559; +constexpr unsigned R_AARCH64_TLSDESC_LD_PREL19 = 560; +constexpr unsigned R_AARCH64_TLSDESC_ADR_PREL21 = 561; +constexpr unsigned R_AARCH64_TLSDESC_ADR_PAGE21 = 562; +constexpr unsigned R_AARCH64_TLSDESC_LD64_LO12 = 563; +constexpr unsigned R_AARCH64_TLSDESC_ADD_LO12 = 564; +constexpr unsigned R_AARCH64_TLSDESC_OFF_G1 = 565; +constexpr unsigned R_AARCH64_TLSDESC_OFF_G0_NC = 566; +constexpr unsigned R_AARCH64_TLSDESC_LDR = 567; +constexpr unsigned R_AARCH64_TLSDESC_ADD = 568; +constexpr unsigned R_AARCH64_TLSDESC_CALL = 569; +constexpr unsigned R_AARCH64_TLSLE_LDST128_TPREL_LO12 = 570; +constexpr unsigned R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC = 571; +constexpr unsigned R_AARCH64_TLSLD_LDST128_DTPREL_LO12 = 572; +constexpr unsigned R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC = 573; +constexpr unsigned R_AARCH64_COPY = 1024; +constexpr unsigned R_AARCH64_GLOB_DAT = 1025; +constexpr unsigned R_AARCH64_JUMP_SLOT = 1026; +constexpr unsigned R_AARCH64_RELATIVE = 1027; +constexpr unsigned R_AARCH64_TLS_DTPMOD = 1028; +constexpr unsigned R_AARCH64_TLS_DTPMOD64 = 1028; +constexpr unsigned R_AARCH64_TLS_DTPREL = 1029; +constexpr unsigned R_AARCH64_TLS_DTPREL64 = 1029; +constexpr unsigned R_AARCH64_TLS_TPREL = 1030; +constexpr unsigned R_AARCH64_TLS_TPREL64 = 1030; +constexpr unsigned R_AARCH64_TLSDESC = 1031; // Segment types -#define PT_NULL 0 -#define PT_LOAD 1 -#define PT_DYNAMIC 2 -#define PT_INTERP 3 -#define PT_NOTE 4 -#define PT_SHLIB 5 -#define PT_PHDR 6 -#define PT_TLS 7 -#define PT_LOOS 0x60000000 -#define PT_HIOS 0x6fffffff -#define PT_LOPROC 0x70000000 -#define PT_HIPROC 0x7FFFFFFF +constexpr Elf_Word PT_NULL = 0; +constexpr Elf_Word PT_LOAD = 1; +constexpr Elf_Word PT_DYNAMIC = 2; +constexpr Elf_Word PT_INTERP = 3; +constexpr Elf_Word PT_NOTE = 4; +constexpr Elf_Word PT_SHLIB = 5; +constexpr Elf_Word PT_PHDR = 6; +constexpr Elf_Word PT_TLS = 7; +constexpr Elf_Word PT_LOOS = 0X60000000; +constexpr Elf_Word PT_GNU_EH_FRAME = 0X6474E550; // Frame unwind information +constexpr Elf_Word PT_GNU_STACK = 0X6474E551; // Stack flags +constexpr Elf_Word PT_GNU_RELRO = 0X6474E552; // Read only after relocs +constexpr Elf_Word PT_GNU_PROPERTY = 0X6474E553; // GNU property +constexpr Elf_Word PT_GNU_MBIND_LO = 0X6474E555; // Mbind segments start +constexpr Elf_Word PT_GNU_MBIND_HI = 0X6474F554; // Mbind segments finish +constexpr Elf_Word PT_PAX_FLAGS = 0X65041580; +constexpr Elf_Word PT_OPENBSD_RANDOMIZE = 0X65A3DBE6; +constexpr Elf_Word PT_OPENBSD_WXNEEDED = 0X65A3DBE7; +constexpr Elf_Word PT_OPENBSD_BOOTDATA = 0X65A41BE6; +constexpr Elf_Word PT_SUNWBSS = 0X6FFFFFFA; +constexpr Elf_Word PT_SUNWSTACK = 0X6FFFFFFB; +constexpr Elf_Word PT_HIOS = 0X6FFFFFFF; +constexpr Elf_Word PT_LOPROC = 0X70000000; +constexpr Elf_Word PT_HIPROC = 0X7FFFFFFF; // Segment flags -#define PF_X 1 // Execute -#define PF_W 2 // Write -#define PF_R 4 // Read -#define PF_MASKOS 0x0ff00000 // Unspecified -#define PF_MASKPROC 0xf0000000 // Unspecified +constexpr Elf_Word PF_X = 1; // Execute +constexpr Elf_Word PF_W = 2; // Write +constexpr Elf_Word PF_R = 4; // Read +constexpr Elf_Word PF_MASKOS = 0x0ff00000; // Unspecified +constexpr Elf_Word PF_MASKPROC = 0xf0000000; // Unspecified // Dynamic Array Tags -#define DT_NULL 0 -#define DT_NEEDED 1 -#define DT_PLTRELSZ 2 -#define DT_PLTGOT 3 -#define DT_HASH 4 -#define DT_STRTAB 5 -#define DT_SYMTAB 6 -#define DT_RELA 7 -#define DT_RELASZ 8 -#define DT_RELAENT 9 -#define DT_STRSZ 10 -#define DT_SYMENT 11 -#define DT_INIT 12 -#define DT_FINI 13 -#define DT_SONAME 14 -#define DT_RPATH 15 -#define DT_SYMBOLIC 16 -#define DT_REL 17 -#define DT_RELSZ 18 -#define DT_RELENT 19 -#define DT_PLTREL 20 -#define DT_DEBUG 21 -#define DT_TEXTREL 22 -#define DT_JMPREL 23 -#define DT_BIND_NOW 24 -#define DT_INIT_ARRAY 25 -#define DT_FINI_ARRAY 26 -#define DT_INIT_ARRAYSZ 27 -#define DT_FINI_ARRAYSZ 28 -#define DT_RUNPATH 29 -#define DT_FLAGS 30 -#define DT_ENCODING 32 -#define DT_PREINIT_ARRAY 32 -#define DT_PREINIT_ARRAYSZ 33 -#define DT_MAXPOSTAGS 34 -#define DT_LOOS 0x6000000D -#define DT_HIOS 0x6ffff000 -#define DT_LOPROC 0x70000000 -#define DT_HIPROC 0x7FFFFFFF +constexpr Elf_Word DT_NULL = 0; +constexpr Elf_Word DT_NEEDED = 1; +constexpr Elf_Word DT_PLTRELSZ = 2; +constexpr Elf_Word DT_PLTGOT = 3; +constexpr Elf_Word DT_HASH = 4; +constexpr Elf_Word DT_STRTAB = 5; +constexpr Elf_Word DT_SYMTAB = 6; +constexpr Elf_Word DT_RELA = 7; +constexpr Elf_Word DT_RELASZ = 8; +constexpr Elf_Word DT_RELAENT = 9; +constexpr Elf_Word DT_STRSZ = 10; +constexpr Elf_Word DT_SYMENT = 11; +constexpr Elf_Word DT_INIT = 12; +constexpr Elf_Word DT_FINI = 13; +constexpr Elf_Word DT_SONAME = 14; +constexpr Elf_Word DT_RPATH = 15; +constexpr Elf_Word DT_SYMBOLIC = 16; +constexpr Elf_Word DT_REL = 17; +constexpr Elf_Word DT_RELSZ = 18; +constexpr Elf_Word DT_RELENT = 19; +constexpr Elf_Word DT_PLTREL = 20; +constexpr Elf_Word DT_DEBUG = 21; +constexpr Elf_Word DT_TEXTREL = 22; +constexpr Elf_Word DT_JMPREL = 23; +constexpr Elf_Word DT_BIND_NOW = 24; +constexpr Elf_Word DT_INIT_ARRAY = 25; +constexpr Elf_Word DT_FINI_ARRAY = 26; +constexpr Elf_Word DT_INIT_ARRAYSZ = 27; +constexpr Elf_Word DT_FINI_ARRAYSZ = 28; +constexpr Elf_Word DT_RUNPATH = 29; +constexpr Elf_Word DT_FLAGS = 30; +constexpr Elf_Word DT_ENCODING = 32; +constexpr Elf_Word DT_PREINIT_ARRAY = 32; +constexpr Elf_Word DT_PREINIT_ARRAYSZ = 33; +constexpr Elf_Word DT_MAXPOSTAGS = 34; +constexpr Elf_Word DT_LOOS = 0x6000000D; +constexpr Elf_Word DT_HIOS = 0x6ffff000; +constexpr Elf_Word DT_GNU_HASH = 0x6ffffef5; +constexpr Elf_Word DT_TLSDESC_PLT = 0x6ffffef6; +constexpr Elf_Word DT_TLSDESC_GOT = 0x6ffffef7; +constexpr Elf_Word DT_GNU_CONFLICT = 0x6ffffef8; +constexpr Elf_Word DT_GNU_LIBLIST = 0x6ffffef9; +constexpr Elf_Word DT_CONFIG = 0x6ffffefa; +constexpr Elf_Word DT_DEPAUDIT = 0x6ffffefb; +constexpr Elf_Word DT_AUDIT = 0x6ffffefc; +constexpr Elf_Word DT_PLTPAD = 0x6ffffefd; +constexpr Elf_Word DT_MOVETAB = 0x6ffffefe; +constexpr Elf_Word DT_SYMINFO = 0x6ffffeff; +constexpr Elf_Word DT_ADDRRNGHI = 0x6ffffeff; +constexpr Elf_Word DT_VERSYM = 0x6ffffff0; +constexpr Elf_Word DT_RELACOUNT = 0x6ffffff9; +constexpr Elf_Word DT_RELCOUNT = 0x6ffffffa; +constexpr Elf_Word DT_FLAGS_1 = 0x6ffffffb; +constexpr Elf_Word DT_VERDEF = 0x6ffffffc; +constexpr Elf_Word DT_VERDEFNUM = 0x6ffffffd; +constexpr Elf_Word DT_VERNEED = 0x6ffffffe; +constexpr Elf_Word DT_VERNEEDNUM = 0x6fffffff; +constexpr Elf_Word DT_LOPROC = 0x70000000; +constexpr Elf_Word DT_HIPROC = 0x7FFFFFFF; // DT_FLAGS values -#define DF_ORIGIN 0x1 -#define DF_SYMBOLIC 0x2 -#define DF_TEXTREL 0x4 -#define DF_BIND_NOW 0x8 -#define DF_STATIC_TLS 0x10 +constexpr Elf_Word DF_ORIGIN = 0x1; +constexpr Elf_Word DF_SYMBOLIC = 0x2; +constexpr Elf_Word DF_TEXTREL = 0x4; +constexpr Elf_Word DF_BIND_NOW = 0x8; +constexpr Elf_Word DF_STATIC_TLS = 0x10; +// Legal values for d_tag (dynamic entry type). +constexpr Elf_Word AT_NULL = 0; // End of vector +constexpr Elf_Word AT_IGNORE = 1; // Entry should be ignored +constexpr Elf_Word AT_EXECFD = 2; // File descriptor of program +constexpr Elf_Word AT_PHDR = 3; // Program headers for program +constexpr Elf_Word AT_PHENT = 4; // Size of program header entry +constexpr Elf_Word AT_PHNUM = 5; // Number of program headers +constexpr Elf_Word AT_PAGESZ = 6; // System page size +constexpr Elf_Word AT_BASE = 7; // Base address of interpreter +constexpr Elf_Word AT_FLAGS = 8; // Flags +constexpr Elf_Word AT_ENTRY = 9; // Entry point of program +constexpr Elf_Word AT_NOTELF = 10; // Program is not ELF +constexpr Elf_Word AT_UID = 11; // Real uid +constexpr Elf_Word AT_EUID = 12; // Effective uid +constexpr Elf_Word AT_GID = 13; // Real gid +constexpr Elf_Word AT_EGID = 14; // Effective gid +constexpr Elf_Word AT_CLKTCK = 17; // Frequency of times() +constexpr Elf_Word AT_PLATFORM = 15; // String identifying platform. +constexpr Elf_Word AT_HWCAP = 16; // Hints about processor capabilities. +constexpr Elf_Word AT_FPUCW = 18; // Used FPU control word. +constexpr Elf_Word AT_DCACHEBSIZE = 19; // Data cache block size. +constexpr Elf_Word AT_ICACHEBSIZE = 20; // Instruction cache block size. +constexpr Elf_Word AT_UCACHEBSIZE = 21; // Unified cache block size. +constexpr Elf_Word AT_IGNOREPPC = 22; // Entry should be ignored. +constexpr Elf_Word AT_SECURE = 23; // Boolean, was exec setuid-like? +constexpr Elf_Word AT_BASE_PLATFORM = 24; // String identifying real platforms. +constexpr Elf_Word AT_RANDOM = 25; // Address of 16 random bytes. +constexpr Elf_Word AT_HWCAP2 = 26; // More hints about processor capabilities. +constexpr Elf_Word AT_EXECFN = 31; // Filename of executable. +constexpr Elf_Word AT_SYSINFO = 32; // EP to the system call in the vDSO. +constexpr Elf_Word AT_SYSINFO_EHDR = 33; // Start of the ELF header of the vDSO. +constexpr Elf_Word AT_L1I_CACHESHAPE = 34; +constexpr Elf_Word AT_L1D_CACHESHAPE = 35; +constexpr Elf_Word AT_L2_CACHESHAPE = 36; +constexpr Elf_Word AT_L3_CACHESHAPE = 37; +constexpr Elf_Word AT_L1I_CACHESIZE = 40; +constexpr Elf_Word AT_L1I_CACHEGEOMETRY = 41; +constexpr Elf_Word AT_L1D_CACHESIZE = 42; +constexpr Elf_Word AT_L1D_CACHEGEOMETRY = 43; +constexpr Elf_Word AT_L2_CACHESIZE = 44; +constexpr Elf_Word AT_L2_CACHEGEOMETRY = 45; +constexpr Elf_Word AT_L3_CACHESIZE = 46; // ELF file header -struct Elf32_Ehdr { +struct Elf32_Ehdr +{ unsigned char e_ident[EI_NIDENT]; - Elf_Half e_type; - Elf_Half e_machine; - Elf_Word e_version; - Elf32_Addr e_entry; - Elf32_Off e_phoff; - Elf32_Off e_shoff; - Elf_Word e_flags; - Elf_Half e_ehsize; - Elf_Half e_phentsize; - Elf_Half e_phnum; - Elf_Half e_shentsize; - Elf_Half e_shnum; - Elf_Half e_shstrndx; + Elf_Half e_type; + Elf_Half e_machine; + Elf_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf_Word e_flags; + Elf_Half e_ehsize; + Elf_Half e_phentsize; + Elf_Half e_phnum; + Elf_Half e_shentsize; + Elf_Half e_shnum; + Elf_Half e_shstrndx; }; -struct Elf64_Ehdr { +struct Elf64_Ehdr +{ unsigned char e_ident[EI_NIDENT]; - Elf_Half e_type; - Elf_Half e_machine; - Elf_Word e_version; - Elf64_Addr e_entry; - Elf64_Off e_phoff; - Elf64_Off e_shoff; - Elf_Word e_flags; - Elf_Half e_ehsize; - Elf_Half e_phentsize; - Elf_Half e_phnum; - Elf_Half e_shentsize; - Elf_Half e_shnum; - Elf_Half e_shstrndx; + Elf_Half e_type; + Elf_Half e_machine; + Elf_Word e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + Elf_Word e_flags; + Elf_Half e_ehsize; + Elf_Half e_phentsize; + Elf_Half e_phnum; + Elf_Half e_shentsize; + Elf_Half e_shnum; + Elf_Half e_shstrndx; }; - // Section header -struct Elf32_Shdr { +struct Elf32_Shdr +{ Elf_Word sh_name; Elf_Word sh_type; Elf_Word sh_flags; @@ -733,7 +1152,8 @@ struct Elf32_Shdr { Elf_Word sh_entsize; }; -struct Elf64_Shdr { +struct Elf64_Shdr +{ Elf_Word sh_name; Elf_Word sh_type; Elf_Xword sh_flags; @@ -746,9 +1166,9 @@ struct Elf64_Shdr { Elf_Xword sh_entsize; }; - // Segment header -struct Elf32_Phdr { +struct Elf32_Phdr +{ Elf_Word p_type; Elf32_Off p_offset; Elf32_Addr p_vaddr; @@ -759,7 +1179,8 @@ struct Elf32_Phdr { Elf_Word p_align; }; -struct Elf64_Phdr { +struct Elf64_Phdr +{ Elf_Word p_type; Elf_Word p_flags; Elf64_Off p_offset; @@ -770,9 +1191,9 @@ struct Elf64_Phdr { Elf_Xword p_align; }; - // Symbol table entry -struct Elf32_Sym { +struct Elf32_Sym +{ Elf_Word st_name; Elf32_Addr st_value; Elf_Word st_size; @@ -781,7 +1202,8 @@ struct Elf32_Sym { Elf_Half st_shndx; }; -struct Elf64_Sym { +struct Elf64_Sym +{ Elf_Word st_name; unsigned char st_info; unsigned char st_other; @@ -790,48 +1212,51 @@ struct Elf64_Sym { Elf_Xword st_size; }; +#define ELF_ST_BIND( i ) ( ( i ) >> 4 ) +#define ELF_ST_TYPE( i ) ( (i)&0xf ) +#define ELF_ST_INFO( b, t ) ( ( ( b ) << 4 ) + ( (t)&0xf ) ) -#define ELF_ST_BIND(i) ((i)>>4) -#define ELF_ST_TYPE(i) ((i)&0xf) -#define ELF_ST_INFO(b,t) (((b)<<4)+((t)&0xf)) - -#define ELF_ST_VISIBILITY(o) ((o)&0x3) - +#define ELF_ST_VISIBILITY( o ) ( (o)&0x3 ) // Relocation entries -struct Elf32_Rel { +struct Elf32_Rel +{ Elf32_Addr r_offset; Elf_Word r_info; }; -struct Elf32_Rela { +struct Elf32_Rela +{ Elf32_Addr r_offset; Elf_Word r_info; Elf_Sword r_addend; }; -struct Elf64_Rel { +struct Elf64_Rel +{ Elf64_Addr r_offset; Elf_Xword r_info; }; -struct Elf64_Rela { +struct Elf64_Rela +{ Elf64_Addr r_offset; Elf_Xword r_info; Elf_Sxword r_addend; }; +#define ELF32_R_SYM( i ) ( ( i ) >> 8 ) +#define ELF32_R_TYPE( i ) ( (unsigned char)( i ) ) +#define ELF32_R_INFO( s, t ) ( ( ( s ) << 8 ) + (unsigned char)( t ) ) -#define ELF32_R_SYM(i) ((i)>>8) -#define ELF32_R_TYPE(i) ((unsigned char)(i)) -#define ELF32_R_INFO(s,t) (((s)<<8 )+(unsigned char)(t)) - -#define ELF64_R_SYM(i) ((i)>>32) -#define ELF64_R_TYPE(i) ((i)&0xffffffffL) -#define ELF64_R_INFO(s,t) ((((int64_t)(s))<<32)+((t)&0xffffffffL)) +#define ELF64_R_SYM( i ) ( ( i ) >> 32 ) +#define ELF64_R_TYPE( i ) ( (i)&0xffffffffL ) +#define ELF64_R_INFO( s, t ) \ + ( ( ( (int64_t)( s ) ) << 32 ) + ( (t)&0xffffffffL ) ) // Dynamic structure -struct Elf32_Dyn { +struct Elf32_Dyn +{ Elf_Sword d_tag; union { Elf_Word d_val; @@ -839,7 +1264,8 @@ struct Elf32_Dyn { } d_un; }; -struct Elf64_Dyn { +struct Elf64_Dyn +{ Elf_Sxword d_tag; union { Elf_Xword d_val; @@ -847,6 +1273,75 @@ struct Elf64_Dyn { } d_un; }; +struct Elfxx_Verneed +{ + Elf_Half vn_version; + Elf_Half vn_cnt; + Elf_Word vn_file; + Elf_Word vn_aux; + Elf_Word vn_next; +}; + +struct Elfxx_Vernaux +{ + Elf_Word vna_hash; + Elf_Half vna_flags; + Elf_Half vna_other; + Elf_Word vna_name; + Elf_Word vna_next; +}; + +// ELF auxiliary vectors, they are usually run-time information +// being passed to program when the kernel is loading it. +// This is now required, +// because in order to initialize the stack cookie +// to protect against buffer overflows, +// most of libc ask us to have a valid pointer for the AT_RANDOM entry. +// glibc for example crashes if you don't. +// https://sourceware.org/git/?p=glibc.git;a=blob;f=csu/libc-start.c;h=543560f36c33b07a1fbe1b7e4578374fe8007b1f;hb=HEAD#l308 +// This is also useful to be able to reconstruct at run-time +// the ELF headers, if ELF headers were erased after loading. +// Although this library is targeted to be parsing files only, +// I assume auxiliary vectors could be also used to get +// more information about the ELF binary at run-time in future. +// The main purpose is also for ELF injectors. +struct Elf32_auxv +{ + uint32_t a_type; // Entry type + + union { + uint32_t a_val; // Integer value, usually a pointer + } a_un; +}; + +struct Elf64_auxv +{ + uint64_t a_type; // Entry type + + union { + uint64_t a_val; // Integer value, usually a pointer + } a_un; +}; + +struct Elf32_Chdr +{ + Elf32_Word ch_type; // The compression algorithm used + Elf32_Word ch_size; //The size, in bytes, of the uncompressed section data + Elf32_Word + ch_addralign; // The address alignment of the uncompressed section data +}; + +struct Elf64_Chdr +{ + Elf64_Word ch_type; //The compression algorithm used + Elf64_Word ch_reserved; // Reserved + Elf_Xword ch_size; //The size, in bytes, of the uncompressed section data + Elf_Xword + ch_addralign; //The address alignment of the uncompressed section data +}; + +#ifdef __cplusplus } // namespace ELFIO +#endif #endif // ELFTYPES_H diff --git a/source/elfio/elfio.hpp b/source/elfio/elfio.hpp index 1d691b1..343b41b 100644 --- a/source/elfio/elfio.hpp +++ b/source/elfio/elfio.hpp @@ -1,6 +1,5 @@ -// clang-format off /* -Copyright (C) 2001-2015 by Serge Lamikhov-Center +Copyright (C) 2001-present by Serge Lamikhov-Center Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -24,186 +23,218 @@ THE SOFTWARE. #ifndef ELFIO_HPP #define ELFIO_HPP -#ifdef _MSC_VER -#pragma warning ( push ) -#pragma warning(disable:4996) -#pragma warning(disable:4355) -#pragma warning(disable:4244) -#endif - #include #include #include +#include #include +#include #include #include -#include -#include +#include #include +#include #include #include #include #include #include -#define ELFIO_HEADER_ACCESS_GET( TYPE, FNAME ) \ -TYPE \ -get_##FNAME() const \ -{ \ - return header? header->get_##FNAME() : 0; \ -} - -#define ELFIO_HEADER_ACCESS_GET_SET( TYPE, FNAME ) \ -TYPE \ -get_##FNAME() const \ -{ \ - return header? header->get_##FNAME() : 0; \ -} \ -void \ -set_##FNAME( TYPE val ) \ -{ \ - if (header) { \ - header->set_##FNAME( val ); \ - } \ -} \ - -struct membuf : std::streambuf { - membuf(char* begin, char* end) { - this->setg(begin, begin, end); +#define ELFIO_HEADER_ACCESS_GET( TYPE, FNAME ) \ + TYPE get_##FNAME() const \ + { \ + return header ? ( header->get_##FNAME() ) : 0; \ } - pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which = std::ios_base::in) override { - if (dir == std::ios_base::cur) - gbump(off); - else if (dir == std::ios_base::end) - setg(eback(), egptr() + off, egptr()); - else if (dir == std::ios_base::beg) - setg(eback(), eback() + off, egptr()); - return gptr() - eback(); +#define ELFIO_HEADER_ACCESS_GET_SET( TYPE, FNAME ) \ + TYPE get_##FNAME() const \ + { \ + return header ? ( header->get_##FNAME() ) : 0; \ + } \ + void set_##FNAME( TYPE val ) \ + { \ + if ( header ) { \ + header->set_##FNAME( val ); \ + } \ } - pos_type seekpos(pos_type sp, std::ios_base::openmode which) override { - return seekoff(sp - pos_type(off_type(0)), std::ios_base::beg, which); - } -}; - namespace ELFIO { //------------------------------------------------------------------------------ -class elfio { -public: -//------------------------------------------------------------------------------ - elfio() : sections( this ), segments( this ) { - header = 0; - current_file_pos = 0; +class elfio +{ + public: + //------------------------------------------------------------------------------ + elfio() noexcept : sections( this ), segments( this ) + { create( ELFCLASS32, ELFDATA2LSB ); } -//------------------------------------------------------------------------------ - ~elfio() { - clean(); + explicit elfio( compression_interface* compression ) noexcept + : sections( this ), segments( this ), + compression( std::shared_ptr( compression ) ) + { + elfio(); } -//------------------------------------------------------------------------------ - void create( unsigned char file_class, unsigned char encoding ) { - clean(); + elfio( elfio&& other ) noexcept + : sections( this ), segments( this ), + current_file_pos( other.current_file_pos ) + { + header = std::move( other.header ); + sections_ = std::move( other.sections_ ); + segments_ = std::move( other.segments_ ); + convertor = std::move( other.convertor ); + addr_translator = std::move( other.addr_translator ); + compression = std::move( other.compression ); + + other.header = nullptr; + other.sections_.clear(); + other.segments_.clear(); + other.compression = nullptr; + } + + elfio& operator=( elfio&& other ) noexcept + { + if ( this != &other ) { + header = std::move( other.header ); + sections_ = std::move( other.sections_ ); + segments_ = std::move( other.segments_ ); + convertor = std::move( other.convertor ); + addr_translator = std::move( other.addr_translator ); + current_file_pos = other.current_file_pos; + compression = std::move( other.compression ); + + other.current_file_pos = 0; + other.header = nullptr; + other.compression = nullptr; + other.sections_.clear(); + other.segments_.clear(); + } + return *this; + } + + //------------------------------------------------------------------------------ + // clang-format off + elfio( const elfio& ) = delete; + elfio& operator=( const elfio& ) = delete; + ~elfio() = default; + // clang-format on + + //------------------------------------------------------------------------------ + void create( unsigned char file_class, unsigned char encoding ) + { + sections_.clear(); + segments_.clear(); convertor.setup( encoding ); header = create_header( file_class, encoding ); create_mandatory_sections(); } - -//------------------------------------------------------------------------------ - bool load(char * buffer, size_t length) { - membuf sbuf(buffer, buffer + length); - std::istream in(&sbuf); - return load(in); + void set_address_translation( std::vector& addr_trans ) + { + addr_translator.set_address_translation( addr_trans ); } -//------------------------------------------------------------------------------ - bool load( const std::string& file_name ) { - std::ifstream stream; - stream.open( file_name.c_str(), std::ios::in | std::ios::binary ); - if ( !stream ) { + //------------------------------------------------------------------------------ + bool load( const std::string& file_name, bool is_lazy = false ) + { + pstream = std::make_unique(); + pstream->open( file_name.c_str(), std::ios::in | std::ios::binary ); + if ( pstream == nullptr || !*pstream ) { return false; } - auto res = load(stream); - stream.close(); - return res; + bool ret = load( *pstream, is_lazy ); + + if ( !is_lazy ) { + pstream.release(); + } + + return ret; } -//------------------------------------------------------------------------------ - bool load( std::istream &stream ) { - clean(); + //------------------------------------------------------------------------------ + bool load( std::istream& stream, bool is_lazy = false ) + { + sections_.clear(); + segments_.clear(); - unsigned char e_ident[EI_NIDENT]; + std::array e_ident = { 0 }; // Read ELF file signature - stream.read( reinterpret_cast( &e_ident ), sizeof( e_ident ) ); + stream.seekg( addr_translator[0] ); + stream.read( e_ident.data(), sizeof( e_ident ) ); // Is it ELF file? if ( stream.gcount() != sizeof( e_ident ) || - e_ident[EI_MAG0] != ELFMAG0 || - e_ident[EI_MAG1] != ELFMAG1 || - e_ident[EI_MAG2] != ELFMAG2 || - e_ident[EI_MAG3] != ELFMAG3 ) { + e_ident[EI_MAG0] != ELFMAG0 || e_ident[EI_MAG1] != ELFMAG1 || + e_ident[EI_MAG2] != ELFMAG2 || e_ident[EI_MAG3] != ELFMAG3 ) { return false; } if ( ( e_ident[EI_CLASS] != ELFCLASS64 ) && - ( e_ident[EI_CLASS] != ELFCLASS32 )) { + ( e_ident[EI_CLASS] != ELFCLASS32 ) ) { + return false; + } + + if ( ( e_ident[EI_DATA] != ELFDATA2LSB ) && + ( e_ident[EI_DATA] != ELFDATA2MSB ) ) { return false; } convertor.setup( e_ident[EI_DATA] ); header = create_header( e_ident[EI_CLASS], e_ident[EI_DATA] ); - if ( 0 == header ) { + if ( nullptr == header ) { return false; } if ( !header->load( stream ) ) { return false; } - load_sections( stream ); - bool is_still_good = load_segments( stream ); + load_sections( stream, is_lazy ); + bool is_still_good = load_segments( stream, is_lazy ); return is_still_good; } -//------------------------------------------------------------------------------ - bool save( const std::string& file_name ) { + //------------------------------------------------------------------------------ + bool save( const std::string& file_name ) + { std::ofstream stream; stream.open( file_name.c_str(), std::ios::out | std::ios::binary ); if ( !stream ) { return false; } - return save(stream); + return save( stream ); } -//------------------------------------------------------------------------------ - bool save( std::ostream &stream ) { - if ( !stream || !header) { + //------------------------------------------------------------------------------ + bool save( std::ostream& stream ) + { + if ( !stream || header == nullptr ) { return false; } - bool is_still_good = true; // Define layout specific header fields // The position of the segment table is fixed after the header. // The position of the section table is variable and needs to be fixed // before saving. header->set_segments_num( segments.size() ); - header->set_segments_offset( segments.size() ? header->get_header_size() : 0 ); + header->set_segments_offset( + segments.size() > 0 ? header->get_header_size() : 0 ); header->set_sections_num( sections.size() ); header->set_sections_offset( 0 ); // Layout the first section right after the segment table - current_file_pos = header->get_header_size() + - header->get_segment_entry_size() * header->get_segments_num(); + current_file_pos = + header->get_header_size() + + header->get_segment_entry_size() * + static_cast( header->get_segments_num() ); calc_segment_alignment(); - is_still_good = layout_segments_and_their_sections(); + bool is_still_good = layout_segments_and_their_sections(); is_still_good = is_still_good && layout_sections_without_segments(); is_still_good = is_still_good && layout_section_table(); @@ -214,56 +245,59 @@ public: return is_still_good; } -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ // ELF header access functions - ELFIO_HEADER_ACCESS_GET( unsigned char, class ); - ELFIO_HEADER_ACCESS_GET( unsigned char, elf_version ); - ELFIO_HEADER_ACCESS_GET( unsigned char, encoding ); - ELFIO_HEADER_ACCESS_GET( Elf_Word, version ); - ELFIO_HEADER_ACCESS_GET( Elf_Half, header_size ); - ELFIO_HEADER_ACCESS_GET( Elf_Half, section_entry_size ); - ELFIO_HEADER_ACCESS_GET( Elf_Half, segment_entry_size ); + ELFIO_HEADER_ACCESS_GET( unsigned char, class ); + ELFIO_HEADER_ACCESS_GET( unsigned char, elf_version ); + ELFIO_HEADER_ACCESS_GET( unsigned char, encoding ); + ELFIO_HEADER_ACCESS_GET( Elf_Word, version ); + ELFIO_HEADER_ACCESS_GET( Elf_Half, header_size ); + ELFIO_HEADER_ACCESS_GET( Elf_Half, section_entry_size ); + ELFIO_HEADER_ACCESS_GET( Elf_Half, segment_entry_size ); - ELFIO_HEADER_ACCESS_GET_SET( unsigned char, os_abi ); - ELFIO_HEADER_ACCESS_GET_SET( unsigned char, abi_version ); - ELFIO_HEADER_ACCESS_GET_SET( Elf_Half, type ); - ELFIO_HEADER_ACCESS_GET_SET( Elf_Half, machine ); - ELFIO_HEADER_ACCESS_GET_SET( Elf_Word, flags ); - ELFIO_HEADER_ACCESS_GET_SET( Elf64_Addr, entry ); - ELFIO_HEADER_ACCESS_GET_SET( Elf64_Off, sections_offset ); - ELFIO_HEADER_ACCESS_GET_SET( Elf64_Off, segments_offset ); - ELFIO_HEADER_ACCESS_GET_SET( Elf_Half, section_name_str_index ); + ELFIO_HEADER_ACCESS_GET_SET( unsigned char, os_abi ); + ELFIO_HEADER_ACCESS_GET_SET( unsigned char, abi_version ); + ELFIO_HEADER_ACCESS_GET_SET( Elf_Half, type ); + ELFIO_HEADER_ACCESS_GET_SET( Elf_Half, machine ); + ELFIO_HEADER_ACCESS_GET_SET( Elf_Word, flags ); + ELFIO_HEADER_ACCESS_GET_SET( Elf64_Addr, entry ); + ELFIO_HEADER_ACCESS_GET_SET( Elf64_Off, sections_offset ); + ELFIO_HEADER_ACCESS_GET_SET( Elf64_Off, segments_offset ); + ELFIO_HEADER_ACCESS_GET_SET( Elf_Half, section_name_str_index ); -//------------------------------------------------------------------------------ - const endianess_convertor& get_convertor() const { - return convertor; - } + //------------------------------------------------------------------------------ + const endianess_convertor& get_convertor() const { return convertor; } -//------------------------------------------------------------------------------ - Elf_Xword get_default_entry_size( Elf_Word section_type ) const { - switch( section_type ) { + //------------------------------------------------------------------------------ + Elf_Xword get_default_entry_size( Elf_Word section_type ) const + { + switch ( section_type ) { case SHT_RELA: if ( header->get_class() == ELFCLASS64 ) { return sizeof( Elf64_Rela ); - } else { + } + else { return sizeof( Elf32_Rela ); } case SHT_REL: if ( header->get_class() == ELFCLASS64 ) { return sizeof( Elf64_Rel ); - } else { + } + else { return sizeof( Elf32_Rel ); } case SHT_SYMTAB: if ( header->get_class() == ELFCLASS64 ) { return sizeof( Elf64_Sym ); - } else { + } + else { return sizeof( Elf32_Sym ); } case SHT_DYNAMIC: if ( header->get_class() == ELFCLASS64 ) { return sizeof( Elf64_Dyn ); - } else { + } + else { return sizeof( Elf32_Dyn ); } default: @@ -271,123 +305,174 @@ public: } } -//------------------------------------------------------------------------------ -private: - bool is_offset_in_section( Elf64_Off offset, const section* sec ) const { - return offset >= sec->get_offset() && offset < sec->get_offset()+sec->get_size(); - } - -//------------------------------------------------------------------------------ -public: - + //------------------------------------------------------------------------------ //! returns an empty string if no problems are detected, - //! or a string containing an error message if problems are found - std::string validate() const { + //! or a string containing an error message if problems are found, + //! with one error per line. + std::string validate() const + { + // clang-format off - // check for overlapping sections in the file + std::string errors; + // Check for overlapping sections in the file + // This is explicitly forbidden by ELF specification for ( int i = 0; i < sections.size(); ++i) { for ( int j = i+1; j < sections.size(); ++j ) { const section* a = sections[i]; const section* b = sections[j]; - if ( !(a->get_type() & SHT_NOBITS) - && !(b->get_type() & SHT_NOBITS) - && (a->get_size() > 0) - && (b->get_size() > 0) - && (a->get_offset() > 0) - && (b->get_offset() > 0)) { - if ( is_offset_in_section( a->get_offset(), b ) - || is_offset_in_section( a->get_offset()+a->get_size()-1, b ) - || is_offset_in_section( b->get_offset(), a ) - || is_offset_in_section( b->get_offset()+b->get_size()-1, a )) { - return "Sections " + a->get_name() + " and " + b->get_name() + " overlap in file"; - } + if ( ( ( a->get_type() & SHT_NOBITS) == 0 ) + && ( ( b->get_type() & SHT_NOBITS) == 0 ) + && ( a->get_size() > 0 ) + && ( b->get_size() > 0 ) + && ( a->get_offset() > 0 ) + && ( b->get_offset() > 0 ) + && ( is_offset_in_section( a->get_offset(), b ) + || is_offset_in_section( a->get_offset()+a->get_size()-1, b ) + || is_offset_in_section( b->get_offset(), a ) + || is_offset_in_section( b->get_offset()+b->get_size()-1, a ) ) ) { + errors += "Sections " + a->get_name() + " and " + b->get_name() + " overlap in file\n"; + } + } + } + // clang-format on + + // Check for conflicting section / program header tables, where + // the same offset has different vaddresses in section table and + // program header table. + // This doesn't seem to be explicitly forbidden by ELF specification, + // but: + // - it doesn't make any sense + // - ELFIO relies on this being consistent when writing ELF files, + // since offsets are re-calculated from vaddress + for ( int h = 0; h < segments.size(); ++h ) { + const segment* seg = segments[h]; + const section* sec = + find_prog_section_for_offset( seg->get_offset() ); + if ( seg->get_type() == PT_LOAD && seg->get_file_size() > 0 && + sec != nullptr ) { + Elf64_Addr sec_addr = + get_virtual_addr( seg->get_offset(), sec ); + if ( sec_addr != seg->get_virtual_address() ) { + errors += "Virtual address of segment " + + std::to_string( h ) + " (" + + to_hex_string( seg->get_virtual_address() ) + + ")" + " conflicts with address of section " + + sec->get_name() + " (" + + to_hex_string( sec_addr ) + ")" + " at offset " + + to_hex_string( seg->get_offset() ) + "\n"; } } } // more checks to be added here... - return ""; + return errors; } -//------------------------------------------------------------------------------ -private: -//------------------------------------------------------------------------------ - void clean() { - delete header; - header = 0; - - std::vector::const_iterator it; - for ( it = sections_.begin(); it != sections_.end(); ++it ) { - delete *it; - } - sections_.clear(); - - std::vector::const_iterator it1; - for ( it1 = segments_.begin(); it1 != segments_.end(); ++it1 ) { - delete *it1; - } - segments_.clear(); + private: + //------------------------------------------------------------------------------ + static bool is_offset_in_section( Elf64_Off offset, const section* sec ) + { + return ( offset >= sec->get_offset() ) && + ( offset < ( sec->get_offset() + sec->get_size() ) ); } -//------------------------------------------------------------------------------ - elf_header* create_header( unsigned char file_class, unsigned char encoding ) { - elf_header* new_header = 0; + //------------------------------------------------------------------------------ + static Elf64_Addr get_virtual_addr( Elf64_Off offset, const section* sec ) + { + return sec->get_address() + offset - sec->get_offset(); + } + + //------------------------------------------------------------------------------ + const section* find_prog_section_for_offset( Elf64_Off offset ) const + { + for ( const auto& sec : sections ) { + if ( sec->get_type() == SHT_PROGBITS && + is_offset_in_section( offset, sec.get() ) ) { + return sec.get(); + } + } + return nullptr; + } + + //------------------------------------------------------------------------------ + std::unique_ptr create_header( unsigned char file_class, + unsigned char encoding ) + { + std::unique_ptr new_header; if ( file_class == ELFCLASS64 ) { - new_header = new elf_header_impl< Elf64_Ehdr >( &convertor, - encoding ); - } else if ( file_class == ELFCLASS32 ) { - new_header = new elf_header_impl< Elf32_Ehdr >( &convertor, - encoding ); - } else { - return 0; + new_header = std::unique_ptr( + new ( std::nothrow ) elf_header_impl( + &convertor, encoding, &addr_translator ) ); + } + else if ( file_class == ELFCLASS32 ) { + new_header = std::unique_ptr( + new ( std::nothrow ) elf_header_impl( + &convertor, encoding, &addr_translator ) ); + } + else { + return nullptr; } return new_header; } -//------------------------------------------------------------------------------ - section* create_section() { - section* new_section; + //------------------------------------------------------------------------------ + section* create_section() + { unsigned char file_class = get_class(); if ( file_class == ELFCLASS64 ) { - new_section = new section_impl( &convertor ); - } else if ( file_class == ELFCLASS32 ) { - new_section = new section_impl( &convertor ); - } else { - return 0; + sections_.emplace_back( + new ( std::nothrow ) section_impl( + &convertor, &addr_translator, compression ) ); + } + else if ( file_class == ELFCLASS32 ) { + sections_.emplace_back( + new ( std::nothrow ) section_impl( + &convertor, &addr_translator, compression ) ); + } + else { + sections_.pop_back(); + return nullptr; } - new_section->set_index( (Elf_Half)sections_.size() ); - sections_.push_back( new_section ); + section* new_section = sections_.back().get(); + new_section->set_index( static_cast( sections_.size() - 1 ) ); return new_section; } - -//------------------------------------------------------------------------------ - segment* create_segment() { - segment* new_segment; + //------------------------------------------------------------------------------ + segment* create_segment() + { unsigned char file_class = header->get_class(); if ( file_class == ELFCLASS64 ) { - new_segment = new segment_impl( &convertor ); - } else if ( file_class == ELFCLASS32 ) { - new_segment = new segment_impl( &convertor ); - } else { - return 0; + segments_.emplace_back( + new ( std::nothrow ) + segment_impl( &convertor, &addr_translator ) ); + } + else if ( file_class == ELFCLASS32 ) { + segments_.emplace_back( + new ( std::nothrow ) + segment_impl( &convertor, &addr_translator ) ); + } + else { + segments_.pop_back(); + return nullptr; } - new_segment->set_index( (Elf_Half)segments_.size() ); - segments_.push_back( new_segment ); + segment* new_segment = segments_.back().get(); + new_segment->set_index( static_cast( segments_.size() - 1 ) ); return new_segment; } -//------------------------------------------------------------------------------ - void create_mandatory_sections() { + //------------------------------------------------------------------------------ + void create_mandatory_sections() + { // Create null section without calling to 'add_section' as no string // section containing section names exists yet section* sec0 = create_section(); @@ -401,16 +486,27 @@ private: shstrtab->set_addr_align( 1 ); } -//------------------------------------------------------------------------------ - Elf_Half load_sections( std::istream& stream ) { - Elf_Half entry_size = header->get_section_entry_size(); - Elf_Half num = header->get_sections_num(); - Elf64_Off offset = header->get_sections_offset(); + //------------------------------------------------------------------------------ + bool load_sections( std::istream& stream, bool is_lazy ) + { + unsigned char file_class = header->get_class(); + Elf_Half entry_size = header->get_section_entry_size(); + Elf_Half num = header->get_sections_num(); + Elf64_Off offset = header->get_sections_offset(); + + if ( ( num != 0 && file_class == ELFCLASS64 && + entry_size < sizeof( Elf64_Shdr ) ) || + ( num != 0 && file_class == ELFCLASS32 && + entry_size < sizeof( Elf32_Shdr ) ) ) { + return false; + } for ( Elf_Half i = 0; i < num; ++i ) { section* sec = create_section(); - sec->load( stream, (std::streamoff)offset + i * entry_size ); - sec->set_index( i ); + sec->load( stream, + static_cast( offset ) + + static_cast( i ) * entry_size, + is_lazy ); // To mark that the section is not permitted to reassign address // during layout calculation sec->set_address( sec->get_address() ); @@ -423,114 +519,144 @@ private: for ( Elf_Half i = 0; i < num; ++i ) { Elf_Word section_offset = sections[i]->get_name_string_offset(); const char* p = str_reader.get_string( section_offset ); - if ( p != 0 ) { + if ( p != nullptr ) { sections[i]->set_name( p ); } } } - return num; + return true; } -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ //! Checks whether the addresses of the section entirely fall within the given segment. //! It doesn't matter if the addresses are memory addresses, or file offsets, //! they just need to be in the same address space - bool is_sect_in_seg ( Elf64_Off sect_begin, Elf_Xword sect_size, Elf64_Off seg_begin, Elf64_Off seg_end ) { - return seg_begin <= sect_begin - && sect_begin + sect_size <= seg_end - && sect_begin < seg_end; // this is important criteria when sect_size == 0 + static bool is_sect_in_seg( Elf64_Off sect_begin, + Elf_Xword sect_size, + Elf64_Off seg_begin, + Elf64_Off seg_end ) + { + return ( seg_begin <= sect_begin ) && + ( sect_begin + sect_size <= seg_end ) && + ( sect_begin < + seg_end ); // this is important criteria when sect_size == 0 // Example: seg_begin=10, seg_end=12 (-> covering the bytes 10 and 11) // sect_begin=12, sect_size=0 -> shall return false! } -//------------------------------------------------------------------------------ - bool load_segments( std::istream& stream ) { - Elf_Half entry_size = header->get_segment_entry_size(); - Elf_Half num = header->get_segments_num(); - Elf64_Off offset = header->get_segments_offset(); + //------------------------------------------------------------------------------ + bool load_segments( std::istream& stream, bool is_lazy ) + { + unsigned char file_class = header->get_class(); + Elf_Half entry_size = header->get_segment_entry_size(); + Elf_Half num = header->get_segments_num(); + Elf64_Off offset = header->get_segments_offset(); + + if ( ( num != 0 && file_class == ELFCLASS64 && + entry_size < sizeof( Elf64_Phdr ) ) || + ( num != 0 && file_class == ELFCLASS32 && + entry_size < sizeof( Elf32_Phdr ) ) ) { + return false; + } for ( Elf_Half i = 0; i < num; ++i ) { - segment* seg; - unsigned char file_class = header->get_class(); - if ( file_class == ELFCLASS64 ) { - seg = new segment_impl( &convertor ); - } else if ( file_class == ELFCLASS32 ) { - seg = new segment_impl( &convertor ); - } else { + segments_.emplace_back( + new ( std::nothrow ) segment_impl( + &convertor, &addr_translator ) ); + } + else if ( file_class == ELFCLASS32 ) { + segments_.emplace_back( + new ( std::nothrow ) segment_impl( + &convertor, &addr_translator ) ); + } + else { + segments_.pop_back(); + return false; + } + + segment* seg = segments_.back().get(); + + if ( !seg->load( stream, + static_cast( offset ) + + static_cast( i ) * entry_size, + is_lazy ) || + stream.fail() ) { + segments_.pop_back(); return false; } - seg->load( stream, (std::streamoff)offset + i * entry_size ); seg->set_index( i ); // Add sections to the segments (similar to readelfs algorithm) Elf64_Off segBaseOffset = seg->get_offset(); Elf64_Off segEndOffset = segBaseOffset + seg->get_file_size(); - Elf64_Off segVBaseAddr = seg->get_virtual_address(); - Elf64_Off segVEndAddr = segVBaseAddr + seg->get_memory_size(); - for( Elf_Half j = 0; j < sections.size(); ++j ) { - const section* psec = sections[j]; - + Elf64_Off segVBaseAddr = seg->get_virtual_address(); + Elf64_Off segVEndAddr = segVBaseAddr + seg->get_memory_size(); + for ( const auto& psec : sections ) { // SHF_ALLOC sections are matched based on the virtual address // otherwise the file offset is matched - if( psec->get_flags() & SHF_ALLOC - ? is_sect_in_seg( psec->get_address(), psec->get_size(), segVBaseAddr, segVEndAddr ) - : is_sect_in_seg( psec->get_offset(), psec->get_size(), segBaseOffset, segEndOffset )) { + if ( ( ( psec->get_flags() & SHF_ALLOC ) == SHF_ALLOC ) + ? is_sect_in_seg( psec->get_address(), + psec->get_size(), segVBaseAddr, + segVEndAddr ) + : is_sect_in_seg( psec->get_offset(), psec->get_size(), + segBaseOffset, segEndOffset ) ) { // Alignment of segment shall not be updated, to preserve original value // It will be re-calculated on saving. seg->add_section_index( psec->get_index(), 0 ); } } - - // Add section into the segments' container - segments_.push_back( seg ); } return true; } -//------------------------------------------------------------------------------ - bool save_header( std::ostream& stream ) { + //------------------------------------------------------------------------------ + bool save_header( std::ostream& stream ) const + { return header->save( stream ); } -//------------------------------------------------------------------------------ - bool save_sections( std::ostream& stream ) { - for ( unsigned int i = 0; i < sections_.size(); ++i ) { - section *sec = sections_.at(i); - + //------------------------------------------------------------------------------ + bool save_sections( std::ostream& stream ) const + { + for ( const auto& sec : sections_ ) { std::streampos headerPosition = - (std::streamoff)header->get_sections_offset() + - header->get_section_entry_size() * sec->get_index(); + static_cast( header->get_sections_offset() ) + + static_cast( + header->get_section_entry_size() ) * + sec->get_index(); - sec->save(stream,headerPosition,sec->get_offset()); + sec->save( stream, headerPosition, sec->get_offset() ); } return true; } -//------------------------------------------------------------------------------ - bool save_segments( std::ostream& stream ) { - for ( unsigned int i = 0; i < segments_.size(); ++i ) { - segment *seg = segments_.at(i); - - std::streampos headerPosition = header->get_segments_offset() + - header->get_segment_entry_size()*seg->get_index(); + //------------------------------------------------------------------------------ + bool save_segments( std::ostream& stream ) const + { + for ( const auto& seg : segments_ ) { + std::streampos headerPosition = + static_cast( header->get_segments_offset() ) + + static_cast( + header->get_segment_entry_size() ) * + seg->get_index(); seg->save( stream, headerPosition, seg->get_offset() ); } return true; } -//------------------------------------------------------------------------------ - bool is_section_without_segment( unsigned int section_index ) { + //------------------------------------------------------------------------------ + bool is_section_without_segment( unsigned int section_index ) const + { bool found = false; for ( unsigned int j = 0; !found && ( j < segments.size() ); ++j ) { - for ( unsigned int k = 0; - !found && ( k < segments[j]->get_sections_num() ); - ++k ) { + for ( Elf_Half k = 0; + !found && ( k < segments[j]->get_sections_num() ); ++k ) { found = segments[j]->get_section_index_at( k ) == section_index; } } @@ -538,14 +664,15 @@ private: return !found; } -//------------------------------------------------------------------------------ - bool is_subsequence_of( segment* seg1, segment* seg2 ) { + //------------------------------------------------------------------------------ + static bool is_subsequence_of( const segment* seg1, const segment* seg2 ) + { // Return 'true' if sections of seg1 are a subset of sections in seg2 const std::vector& sections1 = seg1->get_sections(); const std::vector& sections2 = seg2->get_sections(); bool found = false; - if ( sections1.size() < sections2.size() ) { + if ( sections1.size() < sections2.size() ) { found = std::includes( sections2.begin(), sections2.end(), sections1.begin(), sections1.end() ); } @@ -553,30 +680,32 @@ private: return found; } -//------------------------------------------------------------------------------ - std::vector get_ordered_segments( ) { + //------------------------------------------------------------------------------ + std::vector get_ordered_segments() const + { std::vector res; std::deque worklist; - res.reserve(segments.size()); - std::copy( segments_.begin(), segments_.end(), - std::back_inserter( worklist )) ; + res.reserve( segments.size() ); + for ( const auto& seg : segments ) { + worklist.emplace_back( seg.get() ); + } // Bring the segments which start at address 0 to the front size_t nextSlot = 0; - for( size_t i = 0; i < worklist.size(); ++i ) { - if( i != nextSlot && worklist[i]->is_offset_initialized() - && worklist[i]->get_offset() == 0 ) { - if (worklist[nextSlot]->get_offset() == 0) { + for ( size_t i = 0; i < worklist.size(); ++i ) { + if ( i != nextSlot && worklist[i]->is_offset_initialized() && + worklist[i]->get_offset() == 0 ) { + if ( worklist[nextSlot]->get_offset() == 0 ) { ++nextSlot; } - std::swap(worklist[i],worklist[nextSlot]); + std::swap( worklist[i], worklist[nextSlot] ); ++nextSlot; } } while ( !worklist.empty() ) { - segment *seg = worklist.front(); + segment* seg = worklist.front(); worklist.pop_front(); size_t i = 0; @@ -586,33 +715,37 @@ private: } } - if ( i < worklist.size() ) - worklist.push_back(seg); - else - res.push_back(seg); + if ( i < worklist.size() ) { + worklist.emplace_back( seg ); + } + else { + res.emplace_back( seg ); + } } return res; } - -//------------------------------------------------------------------------------ - bool layout_sections_without_segments( ) { + //------------------------------------------------------------------------------ + bool layout_sections_without_segments() + { for ( unsigned int i = 0; i < sections_.size(); ++i ) { if ( is_section_without_segment( i ) ) { - section *sec = sections_[i]; + const auto& sec = sections_[i]; Elf_Xword section_align = sec->get_addr_align(); - if ( section_align > 1 && current_file_pos % section_align != 0 ) { - current_file_pos += section_align - - current_file_pos % section_align; + if ( section_align > 1 && + current_file_pos % section_align != 0 ) { + current_file_pos += + section_align - current_file_pos % section_align; } - if ( 0 != sec->get_index() ) - sec->set_offset(current_file_pos); + if ( 0 != sec->get_index() ) { + sec->set_offset( current_file_pos ); + } if ( SHT_NOBITS != sec->get_type() && - SHT_NULL != sec->get_type() ) { + SHT_NULL != sec->get_type() ) { current_file_pos += sec->get_size(); } } @@ -621,13 +754,12 @@ private: return true; } - -//------------------------------------------------------------------------------ - void calc_segment_alignment( ) { - for( std::vector::iterator s = segments_.begin(); s != segments_.end(); ++s ) { - segment* seg = *s; - for ( int i = 0; i < seg->get_sections_num(); ++i ) { - section* sect = sections_[ seg->get_section_index_at(i) ]; + //------------------------------------------------------------------------------ + void calc_segment_alignment() const + { + for ( const auto& seg : segments_ ) { + for ( Elf_Half i = 0; i < seg->get_sections_num(); ++i ) { + const auto& sect = sections_[seg->get_section_index_at( i )]; if ( sect->get_addr_align() > seg->get_align() ) { seg->set_align( sect->get_addr_align() ); } @@ -635,121 +767,57 @@ private: } } -//------------------------------------------------------------------------------ - bool layout_segments_and_their_sections( ) { - std::vector worklist; - std::vector section_generated(sections.size(),false); + //------------------------------------------------------------------------------ + bool layout_segments_and_their_sections() + { + std::vector worklist; + std::vector section_generated( sections.size(), false ); // Get segments in a order in where segments which contain a // sub sequence of other segments are located at the end worklist = get_ordered_segments(); - for ( unsigned int i = 0; i < worklist.size(); ++i ) { + for ( auto* seg : worklist ) { Elf_Xword segment_memory = 0; Elf_Xword segment_filesize = 0; Elf_Xword seg_start_pos = current_file_pos; - segment* seg = worklist[i]; - // Special case: PHDR segment // This segment contains the program headers but no sections if ( seg->get_type() == PT_PHDR && seg->get_sections_num() == 0 ) { - seg_start_pos = header->get_segments_offset(); + seg_start_pos = header->get_segments_offset(); segment_memory = segment_filesize = - header->get_segment_entry_size() * header->get_segments_num(); + header->get_segment_entry_size() * + static_cast( header->get_segments_num() ); } // Special case: - // Segments which start with the NULL section and have further sections - else if ( seg->get_sections_num() > 1 - && sections[seg->get_section_index_at( 0 )]->get_type() == SHT_NULL ) { + else if ( seg->is_offset_initialized() && seg->get_offset() == 0 ) { seg_start_pos = 0; - if ( seg->get_sections_num() ) { + if ( seg->get_sections_num() > 0 ) { segment_memory = segment_filesize = current_file_pos; } } // New segments with not generated sections // have to be aligned - else if ( seg->get_sections_num() - && !section_generated[seg->get_section_index_at( 0 )] ) { + else if ( seg->get_sections_num() > 0 && + !section_generated[seg->get_section_index_at( 0 )] ) { Elf_Xword align = seg->get_align() > 0 ? seg->get_align() : 1; Elf64_Off cur_page_alignment = current_file_pos % align; - Elf64_Off req_page_alignment = seg->get_virtual_address() % align; - Elf64_Off error = req_page_alignment - cur_page_alignment; + Elf64_Off req_page_alignment = + seg->get_virtual_address() % align; + Elf64_Off error = req_page_alignment - cur_page_alignment; current_file_pos += ( seg->get_align() + error ) % align; seg_start_pos = current_file_pos; - } else if ( seg->get_sections_num() ) { - seg_start_pos = sections[seg->get_section_index_at( 0 )]->get_offset(); + } + else if ( seg->get_sections_num() > 0 ) { + seg_start_pos = + sections[seg->get_section_index_at( 0 )]->get_offset(); } // Write segment's data - for ( unsigned int j = 0; j < seg->get_sections_num(); ++j ) { - Elf_Half index = seg->get_section_index_at( j ); - - section* sec = sections[ index ]; - - // The NULL section is always generated - if ( SHT_NULL == sec->get_type()) { - section_generated[index] = true; - continue; - } - - Elf_Xword secAlign = 0; - // Fix up the alignment - if ( !section_generated[index] && sec->is_address_initialized() - && SHT_NOBITS != sec->get_type() - && SHT_NULL != sec->get_type() - && 0 != sec->get_size() ) { - // Align the sections based on the virtual addresses - // when possible (this is what matters for execution) - Elf64_Off req_offset = sec->get_address() - seg->get_virtual_address(); - Elf64_Off cur_offset = current_file_pos - seg_start_pos; - if ( req_offset < cur_offset) { - // something has gone awfully wrong, abort! - // secAlign would turn out negative, seeking backwards and overwriting previous data - return false; - } - secAlign = req_offset - cur_offset; - } else if (!section_generated[index] && !sec->is_address_initialized() ) { - // If no address has been specified then only the section - // alignment constraint has to be matched - Elf_Xword align = sec->get_addr_align(); - if (align == 0) { - align = 1; - } - Elf64_Off error = current_file_pos % align; - secAlign = ( align - error ) % align; - } else if (section_generated[index] ) { - // Alignment for already generated sections - secAlign = sec->get_offset() - seg_start_pos - segment_filesize; - } - - // Determine the segment file and memory sizes - // Special case .tbss section (NOBITS) in non TLS segment - if ( (sec->get_flags() & SHF_ALLOC) - && !( (sec->get_flags() & SHF_TLS) && (seg->get_type() != PT_TLS) - && ( SHT_NOBITS == sec->get_type())) ) - segment_memory += sec->get_size() + secAlign; - if ( SHT_NOBITS != sec->get_type() && SHT_NULL != sec->get_type() ) - segment_filesize += sec->get_size() + secAlign; - - // Nothing to be done when generating nested segments - if(section_generated[index]) { - continue; - } - - current_file_pos += secAlign; - - // Set the section addresses when missing - if ( !sec->is_address_initialized() ) - sec->set_address( seg->get_virtual_address() - + current_file_pos - seg_start_pos); - - if ( 0 != sec->get_index() ) - sec->set_offset(current_file_pos); - - if ( SHT_NOBITS != sec->get_type() && SHT_NULL != sec->get_type() ) - current_file_pos += sec->get_size(); - section_generated[index] = true; + if ( !write_segment_data( seg, section_generated, segment_memory, + segment_filesize, seg_start_pos ) ) { + return false; } seg->set_file_size( segment_filesize ); @@ -762,58 +830,149 @@ private: seg->set_memory_size( segment_memory ); } - seg->set_offset(seg_start_pos); + seg->set_offset( seg_start_pos ); } return true; } -//------------------------------------------------------------------------------ - bool layout_section_table() { + //------------------------------------------------------------------------------ + bool layout_section_table() + { // Simply place the section table at the end for now Elf64_Off alignmentError = current_file_pos % 4; current_file_pos += ( 4 - alignmentError ) % 4; - header->set_sections_offset(current_file_pos); + header->set_sections_offset( current_file_pos ); return true; } + //------------------------------------------------------------------------------ + bool write_segment_data( const segment* seg, + std::vector& section_generated, + Elf_Xword& segment_memory, + Elf_Xword& segment_filesize, + const Elf_Xword& seg_start_pos ) + { + for ( Elf_Half j = 0; j < seg->get_sections_num(); ++j ) { + Elf_Half index = seg->get_section_index_at( j ); -//------------------------------------------------------------------------------ -public: + section* sec = sections[index]; + + // The NULL section is always generated + if ( SHT_NULL == sec->get_type() ) { + section_generated[index] = true; + continue; + } + + Elf_Xword section_align = 0; + // Fix up the alignment + if ( !section_generated[index] && sec->is_address_initialized() && + SHT_NOBITS != sec->get_type() && SHT_NULL != sec->get_type() && + 0 != sec->get_size() ) { + // Align the sections based on the virtual addresses + // when possible (this is what matters for execution) + Elf64_Off req_offset = + sec->get_address() - seg->get_virtual_address(); + Elf64_Off cur_offset = current_file_pos - seg_start_pos; + if ( req_offset < cur_offset ) { + // something has gone awfully wrong, abort! + // section_align would turn out negative, seeking backwards and overwriting previous data + return false; + } + section_align = req_offset - cur_offset; + } + else if ( !section_generated[index] && + !sec->is_address_initialized() ) { + // If no address has been specified then only the section + // alignment constraint has to be matched + Elf_Xword align = sec->get_addr_align(); + if ( align == 0 ) { + align = 1; + } + Elf64_Off error = current_file_pos % align; + section_align = ( align - error ) % align; + } + else if ( section_generated[index] ) { + // Alignment for already generated sections + section_align = + sec->get_offset() - seg_start_pos - segment_filesize; + } + + // Determine the segment file and memory sizes + // Special case .tbss section (NOBITS) in non TLS segment + if ( ( ( sec->get_flags() & SHF_ALLOC ) == SHF_ALLOC ) && + !( ( ( sec->get_flags() & SHF_TLS ) == SHF_TLS ) && + ( seg->get_type() != PT_TLS ) && + ( SHT_NOBITS == sec->get_type() ) ) ) { + segment_memory += sec->get_size() + section_align; + } + + if ( SHT_NOBITS != sec->get_type() ) { + segment_filesize += sec->get_size() + section_align; + } + + // Nothing to be done when generating nested segments + if ( section_generated[index] ) { + continue; + } + + current_file_pos += section_align; + + // Set the section addresses when missing + if ( !sec->is_address_initialized() ) { + sec->set_address( seg->get_virtual_address() + + current_file_pos - seg_start_pos ); + } + + if ( 0 != sec->get_index() ) { + sec->set_offset( current_file_pos ); + } + + if ( SHT_NOBITS != sec->get_type() ) { + current_file_pos += sec->get_size(); + } + + section_generated[index] = true; + } + + return true; + } + + //------------------------------------------------------------------------------ + public: friend class Sections; - class Sections { - public: -//------------------------------------------------------------------------------ - Sections( elfio* parent_ ) : - parent( parent_ ) { + class Sections + { + public: + //------------------------------------------------------------------------------ + explicit Sections( elfio* parent ) : parent( parent ) {} + + //------------------------------------------------------------------------------ + Elf_Half size() const + { + return static_cast( parent->sections_.size() ); } -//------------------------------------------------------------------------------ - Elf_Half size() const { - return (Elf_Half)parent->sections_.size(); - } - -//------------------------------------------------------------------------------ - section* operator[]( unsigned int index ) const { - section* sec = 0; + //------------------------------------------------------------------------------ + section* operator[]( unsigned int index ) const + { + section* sec = nullptr; if ( index < parent->sections_.size() ) { - sec = parent->sections_[index]; + sec = parent->sections_[index].get(); } return sec; } -//------------------------------------------------------------------------------ - section* operator[]( const std::string& name ) const { - section* sec = 0; + //------------------------------------------------------------------------------ + section* operator[]( const std::string& name ) const + { + section* sec = nullptr; - std::vector::const_iterator it; - for ( it = parent->sections_.begin(); - it != parent->sections_.end(); - ++it ) { - if ( (*it)->get_name() == name ) { - sec = *it; + for ( const auto& it : parent->sections_ ) { + if ( it->get_name() == name ) { + sec = it.get(); break; } } @@ -821,104 +980,115 @@ public: return sec; } -//------------------------------------------------------------------------------ - section* add( const std::string& name ) { + //------------------------------------------------------------------------------ + section* add( const std::string& name ) const + { section* new_section = parent->create_section(); new_section->set_name( name ); Elf_Half str_index = parent->get_section_name_str_index(); - section* string_table( parent->sections_[str_index] ); + section* string_table( parent->sections_[str_index].get() ); string_section_accessor str_writer( string_table ); - Elf_Word pos = str_writer.add_string( name ); + Elf_Word pos = str_writer.add_string( name ); new_section->set_name_string_offset( pos ); return new_section; } -//------------------------------------------------------------------------------ - std::vector::iterator begin() { + //------------------------------------------------------------------------------ + std::vector>::iterator begin() + { return parent->sections_.begin(); } -//------------------------------------------------------------------------------ - std::vector::iterator end() { + //------------------------------------------------------------------------------ + std::vector>::iterator end() + { return parent->sections_.end(); } -//------------------------------------------------------------------------------ - std::vector::const_iterator begin() const { + //------------------------------------------------------------------------------ + std::vector>::const_iterator begin() const + { return parent->sections_.cbegin(); } -//------------------------------------------------------------------------------ - std::vector::const_iterator end() const { + //------------------------------------------------------------------------------ + std::vector>::const_iterator end() const + { return parent->sections_.cend(); } -//------------------------------------------------------------------------------ - private: + //------------------------------------------------------------------------------ + private: elfio* parent; - } sections; + }; + Sections sections; -//------------------------------------------------------------------------------ -public: + //------------------------------------------------------------------------------ friend class Segments; - class Segments { - public: -//------------------------------------------------------------------------------ - Segments( elfio* parent_ ) : - parent( parent_ ) { + class Segments + { + public: + //------------------------------------------------------------------------------ + explicit Segments( elfio* parent ) : parent( parent ) {} + + //------------------------------------------------------------------------------ + Elf_Half size() const + { + return static_cast( parent->segments_.size() ); } -//------------------------------------------------------------------------------ - Elf_Half size() const { - return (Elf_Half)parent->segments_.size(); + //------------------------------------------------------------------------------ + segment* operator[]( unsigned int index ) const + { + return parent->segments_[index].get(); } -//------------------------------------------------------------------------------ - segment* operator[]( unsigned int index ) const { - return parent->segments_[index]; - } + //------------------------------------------------------------------------------ + segment* add() { return parent->create_segment(); } - -//------------------------------------------------------------------------------ - segment* add() { - return parent->create_segment(); - } - -//------------------------------------------------------------------------------ - std::vector::iterator begin() { + //------------------------------------------------------------------------------ + std::vector>::iterator begin() + { return parent->segments_.begin(); } -//------------------------------------------------------------------------------ - std::vector::iterator end() { + //------------------------------------------------------------------------------ + std::vector>::iterator end() + { return parent->segments_.end(); } -//------------------------------------------------------------------------------ - std::vector::const_iterator begin() const { + //------------------------------------------------------------------------------ + std::vector>::const_iterator begin() const + { return parent->segments_.cbegin(); } -//------------------------------------------------------------------------------ - std::vector::const_iterator end() const { + //------------------------------------------------------------------------------ + std::vector>::const_iterator end() const + { return parent->segments_.cend(); } -//------------------------------------------------------------------------------ - private: + //------------------------------------------------------------------------------ + private: elfio* parent; - } segments; + }; + Segments segments; -//------------------------------------------------------------------------------ -private: - elf_header* header; - std::vector sections_; - std::vector segments_; - endianess_convertor convertor; + //------------------------------------------------------------------------------ + private: + std::unique_ptr pstream = nullptr; + std::unique_ptr header = nullptr; + std::vector> sections_; + std::vector> segments_; + endianess_convertor convertor; + address_translator addr_translator; + std::shared_ptr compression = nullptr; - Elf_Xword current_file_pos; + Elf_Xword current_file_pos = 0; }; } // namespace ELFIO @@ -927,9 +1097,8 @@ private: #include #include #include - -#ifdef _MSC_VER -#pragma warning ( pop ) -#endif +#include +#include +#include #endif // ELFIO_HPP diff --git a/source/elfio/elfio_array.hpp b/source/elfio/elfio_array.hpp new file mode 100644 index 0000000..190c075 --- /dev/null +++ b/source/elfio/elfio_array.hpp @@ -0,0 +1,88 @@ +/* +Copyright (C) 2001-present by Serge Lamikhov-Center + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#ifndef ELFIO_ARRAY_HPP +#define ELFIO_ARRAY_HPP + +#include + +namespace ELFIO { + +//------------------------------------------------------------------------------ +template class array_section_accessor_template +{ + public: + //------------------------------------------------------------------------------ + explicit array_section_accessor_template( const elfio& elf_file, + S* section ) + : elf_file( elf_file ), array_section( section ) + { + } + + //------------------------------------------------------------------------------ + Elf_Xword get_entries_num() const + { + Elf_Xword entry_size = sizeof( T ); + return array_section->get_size() / entry_size; + } + + //------------------------------------------------------------------------------ + bool get_entry( Elf_Xword index, Elf64_Addr& address ) const + { + if ( index >= get_entries_num() ) { // Is index valid + return false; + } + + const endianess_convertor& convertor = elf_file.get_convertor(); + + const T temp = *reinterpret_cast( array_section->get_data() + + index * sizeof( T ) ); + address = convertor( temp ); + + return true; + } + + //------------------------------------------------------------------------------ + void add_entry( Elf64_Addr address ) + { + const endianess_convertor& convertor = elf_file.get_convertor(); + + T temp = convertor( (T)address ); + array_section->append_data( reinterpret_cast( &temp ), + sizeof( temp ) ); + } + + private: + //------------------------------------------------------------------------------ + const elfio& elf_file; + S* array_section; +}; + +template +using array_section_accessor = array_section_accessor_template; +template +using const_array_section_accessor = + array_section_accessor_template; + +} // namespace ELFIO + +#endif // ELFIO_ARRAY_HPP diff --git a/source/elfio/elfio_dump.hpp b/source/elfio/elfio_dump.hpp index 015cff2..3310511 100644 --- a/source/elfio/elfio_dump.hpp +++ b/source/elfio/elfio_dump.hpp @@ -1,6 +1,5 @@ -// clang-format off /* -Copyright (C) 2001-2015 by Serge Lamikhov-Center +Copyright (C) 2001-present by Serge Lamikhov-Center Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -33,423 +32,688 @@ THE SOFTWARE. namespace ELFIO { - -static struct class_table_t { +static const struct class_table_t +{ const char key; const char* str; -} class_table [] = -{ +} class_table[] = { { ELFCLASS32, "ELF32" }, { ELFCLASS64, "ELF64" }, }; - -static struct endian_table_t { +static const struct endian_table_t +{ const char key; const char* str; -} endian_table [] = -{ - { ELFDATANONE, "None" }, +} endian_table[] = { + { ELFDATANONE, "None" }, { ELFDATA2LSB, "Little endian" }, - { ELFDATA2MSB, "Big endian" }, + { ELFDATA2MSB, "Big endian" }, }; +static const struct os_abi_table_t +{ + const unsigned char key; + const char* str; +} os_abi_table[] = { + { ELFOSABI_NONE, "UNIX System V" }, + { ELFOSABI_HPUX, "Hewlett-Packard HP-UX" }, + { ELFOSABI_NETBSD, "NetBSD" }, + { ELFOSABI_LINUX, "Linux" }, + { ELFOSABI_HURD, "GNU Hurd" }, + { ELFOSABI_SOLARIS, "Sun Solaris" }, + { ELFOSABI_AIX, "AIX" }, + { ELFOSABI_IRIX, "IRIX" }, + { ELFOSABI_FREEBSD, "FreeBSD" }, + { ELFOSABI_TRU64, "Compaq TRU64 UNIX" }, + { ELFOSABI_MODESTO, "Novell Modesto" }, + { ELFOSABI_OPENBSD, "Open BSD" }, + { ELFOSABI_OPENVMS, "Open VMS" }, + { ELFOSABI_NSK, "Hewlett-Packard Non-Stop Kernel" }, + { ELFOSABI_AROS, "Amiga Research OS" }, + { ELFOSABI_FENIXOS, "FenixOS" }, + { ELFOSABI_NUXI, "Nuxi CloudABI" }, + { ELFOSABI_OPENVOS, "OpenVOS" }, + { ELFOSABI_ARM, "ARM" }, + { ELFOSABI_STANDALONE, "Standalone (embedded)" }, +}; -static struct version_table_t { +static const struct version_table_t +{ const Elf64_Word key; const char* str; -} version_table [] = -{ - { EV_NONE , "None" }, +} version_table[] = { + { EV_NONE, "None" }, { EV_CURRENT, "Current" }, }; - -static struct type_table_t { +static const struct type_table_t +{ const Elf32_Half key; const char* str; -} type_table [] = -{ - { ET_NONE, "No file type" }, - { ET_REL , "Relocatable file" }, - { ET_EXEC, "Executable file" }, - { ET_DYN , "Shared object file" }, - { ET_CORE, "Core file" }, +} type_table[] = { + { ET_NONE, "No file type" }, { ET_REL, "Relocatable file" }, + { ET_EXEC, "Executable file" }, { ET_DYN, "Shared object file" }, + { ET_CORE, "Core file" }, }; - -static struct machine_table_t { +static const struct machine_table_t +{ const Elf64_Half key; const char* str; -} machine_table [] = -{ - { EM_NONE , "No machine" }, - { EM_M32 , "AT&T WE 32100" }, - { EM_SPARC , "SUN SPARC" }, - { EM_386 , "Intel 80386" }, - { EM_68K , "Motorola m68k family" }, - { EM_88K , "Motorola m88k family" }, - { EM_486 , "Intel 80486// Reserved for future use" }, - { EM_860 , "Intel 80860" }, - { EM_MIPS , "MIPS R3000 (officially, big-endian only)" }, - { EM_S370 , "IBM System/370" }, - { EM_MIPS_RS3_LE , "MIPS R3000 little-endian (Oct 4 1999 Draft) Deprecated" }, - { EM_res011 , "Reserved" }, - { EM_res012 , "Reserved" }, - { EM_res013 , "Reserved" }, - { EM_res014 , "Reserved" }, - { EM_PARISC , "HPPA" }, - { EM_res016 , "Reserved" }, - { EM_VPP550 , "Fujitsu VPP500" }, - { EM_SPARC32PLUS , "Sun's v8plus" }, - { EM_960 , "Intel 80960" }, - { EM_PPC , "PowerPC" }, - { EM_PPC64 , "64-bit PowerPC" }, - { EM_S390 , "IBM S/390" }, - { EM_SPU , "Sony/Toshiba/IBM SPU" }, - { EM_res024 , "Reserved" }, - { EM_res025 , "Reserved" }, - { EM_res026 , "Reserved" }, - { EM_res027 , "Reserved" }, - { EM_res028 , "Reserved" }, - { EM_res029 , "Reserved" }, - { EM_res030 , "Reserved" }, - { EM_res031 , "Reserved" }, - { EM_res032 , "Reserved" }, - { EM_res033 , "Reserved" }, - { EM_res034 , "Reserved" }, - { EM_res035 , "Reserved" }, - { EM_V800 , "NEC V800 series" }, - { EM_FR20 , "Fujitsu FR20" }, - { EM_RH32 , "TRW RH32" }, - { EM_MCORE , "Motorola M*Core // May also be taken by Fujitsu MMA" }, - { EM_RCE , "Old name for MCore" }, - { EM_ARM , "ARM" }, - { EM_OLD_ALPHA , "Digital Alpha" }, - { EM_SH , "Renesas (formerly Hitachi) / SuperH SH" }, - { EM_SPARCV9 , "SPARC v9 64-bit" }, - { EM_TRICORE , "Siemens Tricore embedded processor" }, - { EM_ARC , "ARC Cores" }, - { EM_H8_300 , "Renesas (formerly Hitachi) H8/300" }, - { EM_H8_300H , "Renesas (formerly Hitachi) H8/300H" }, - { EM_H8S , "Renesas (formerly Hitachi) H8S" }, - { EM_H8_500 , "Renesas (formerly Hitachi) H8/500" }, - { EM_IA_64 , "Intel IA-64 Processor" }, - { EM_MIPS_X , "Stanford MIPS-X" }, - { EM_COLDFIRE , "Motorola Coldfire" }, - { EM_68HC12 , "Motorola M68HC12" }, - { EM_MMA , "Fujitsu Multimedia Accelerator" }, - { EM_PCP , "Siemens PCP" }, - { EM_NCPU , "Sony nCPU embedded RISC processor" }, - { EM_NDR1 , "Denso NDR1 microprocesspr" }, - { EM_STARCORE , "Motorola Star*Core processor" }, - { EM_ME16 , "Toyota ME16 processor" }, - { EM_ST100 , "STMicroelectronics ST100 processor" }, - { EM_TINYJ , "Advanced Logic Corp. TinyJ embedded processor" }, - { EM_X86_64 , "Advanced Micro Devices X86-64 processor" }, - { EM_PDSP , "Sony DSP Processor" }, - { EM_PDP10 , "Digital Equipment Corp. PDP-10" }, - { EM_PDP11 , "Digital Equipment Corp. PDP-11" }, - { EM_FX66 , "Siemens FX66 microcontroller" }, - { EM_ST9PLUS , "STMicroelectronics ST9+ 8/16 bit microcontroller" }, - { EM_ST7 , "STMicroelectronics ST7 8-bit microcontroller" }, - { EM_68HC16 , "Motorola MC68HC16 Microcontroller" }, - { EM_68HC11 , "Motorola MC68HC11 Microcontroller" }, - { EM_68HC08 , "Motorola MC68HC08 Microcontroller" }, - { EM_68HC05 , "Motorola MC68HC05 Microcontroller" }, - { EM_SVX , "Silicon Graphics SVx" }, - { EM_ST19 , "STMicroelectronics ST19 8-bit cpu" }, - { EM_VAX , "Digital VAX" }, - { EM_CRIS , "Axis Communications 32-bit embedded processor" }, - { EM_JAVELIN , "Infineon Technologies 32-bit embedded cpu" }, - { EM_FIREPATH , "Element 14 64-bit DSP processor" }, - { EM_ZSP , "LSI Logic's 16-bit DSP processor" }, - { EM_MMIX , "Donald Knuth's educational 64-bit processor" }, - { EM_HUANY , "Harvard's machine-independent format" }, - { EM_PRISM , "SiTera Prism" }, - { EM_AVR , "Atmel AVR 8-bit microcontroller" }, - { EM_FR30 , "Fujitsu FR30" }, - { EM_D10V , "Mitsubishi D10V" }, - { EM_D30V , "Mitsubishi D30V" }, - { EM_V850 , "NEC v850" }, - { EM_M32R , "Renesas M32R (formerly Mitsubishi M32R)" }, - { EM_MN10300 , "Matsushita MN10300" }, - { EM_MN10200 , "Matsushita MN10200" }, - { EM_PJ , "picoJava" }, - { EM_OPENRISC , "OpenRISC 32-bit embedded processor" }, - { EM_ARC_A5 , "ARC Cores Tangent-A5" }, - { EM_XTENSA , "Tensilica Xtensa Architecture" }, - { EM_VIDEOCORE , "Alphamosaic VideoCore processor" }, - { EM_TMM_GPP , "Thompson Multimedia General Purpose Processor" }, - { EM_NS32K , "National Semiconductor 32000 series" }, - { EM_TPC , "Tenor Network TPC processor" }, - { EM_SNP1K , "Trebia SNP 1000 processor" }, - { EM_ST200 , "STMicroelectronics ST200 microcontroller" }, - { EM_IP2K , "Ubicom IP2022 micro controller" }, - { EM_MAX , "MAX Processor" }, - { EM_CR , "National Semiconductor CompactRISC" }, - { EM_F2MC16 , "Fujitsu F2MC16" }, - { EM_MSP430 , "TI msp430 micro controller" }, - { EM_BLACKFIN , "ADI Blackfin" }, - { EM_SE_C33 , "S1C33 Family of Seiko Epson processors" }, - { EM_SEP , "Sharp embedded microprocessor" }, - { EM_ARCA , "Arca RISC Microprocessor" }, - { EM_UNICORE , "Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University" }, - { EM_EXCESS , "eXcess: 16/32/64-bit configurable embedded CPU" }, - { EM_DXP , "Icera Semiconductor Inc. Deep Execution Processor" }, - { EM_ALTERA_NIOS2 , "Altera Nios II soft-core processor" }, - { EM_CRX , "National Semiconductor CRX" }, - { EM_XGATE , "Motorola XGATE embedded processor" }, - { EM_C166 , "Infineon C16x/XC16x processor" }, - { EM_M16C , "Renesas M16C series microprocessors" }, - { EM_DSPIC30F , "Microchip Technology dsPIC30F Digital Signal Controller" }, - { EM_CE , "Freescale Communication Engine RISC core" }, - { EM_M32C , "Renesas M32C series microprocessors" }, - { EM_res121 , "Reserved" }, - { EM_res122 , "Reserved" }, - { EM_res123 , "Reserved" }, - { EM_res124 , "Reserved" }, - { EM_res125 , "Reserved" }, - { EM_res126 , "Reserved" }, - { EM_res127 , "Reserved" }, - { EM_res128 , "Reserved" }, - { EM_res129 , "Reserved" }, - { EM_res130 , "Reserved" }, - { EM_TSK3000 , "Altium TSK3000 core" }, - { EM_RS08 , "Freescale RS08 embedded processor" }, - { EM_res133 , "Reserved" }, - { EM_ECOG2 , "Cyan Technology eCOG2 microprocessor" }, - { EM_SCORE , "Sunplus Score" }, - { EM_SCORE7 , "Sunplus S+core7 RISC processor" }, - { EM_DSP24 , "New Japan Radio (NJR) 24-bit DSP Processor" }, - { EM_VIDEOCORE3 , "Broadcom VideoCore III processor" }, - { EM_LATTICEMICO32, "RISC processor for Lattice FPGA architecture" }, - { EM_SE_C17 , "Seiko Epson C17 family" }, - { EM_TI_C6000 , "Texas Instruments TMS320C6000 DSP family" }, - { EM_TI_C2000 , "Texas Instruments TMS320C2000 DSP family" }, - { EM_TI_C5500 , "Texas Instruments TMS320C55x DSP family" }, - { EM_res143 , "Reserved" }, - { EM_res144 , "Reserved" }, - { EM_res145 , "Reserved" }, - { EM_res146 , "Reserved" }, - { EM_res147 , "Reserved" }, - { EM_res148 , "Reserved" }, - { EM_res149 , "Reserved" }, - { EM_res150 , "Reserved" }, - { EM_res151 , "Reserved" }, - { EM_res152 , "Reserved" }, - { EM_res153 , "Reserved" }, - { EM_res154 , "Reserved" }, - { EM_res155 , "Reserved" }, - { EM_res156 , "Reserved" }, - { EM_res157 , "Reserved" }, - { EM_res158 , "Reserved" }, - { EM_res159 , "Reserved" }, - { EM_MMDSP_PLUS , "STMicroelectronics 64bit VLIW Data Signal Processor" }, - { EM_CYPRESS_M8C , "Cypress M8C microprocessor" }, - { EM_R32C , "Renesas R32C series microprocessors" }, - { EM_TRIMEDIA , "NXP Semiconductors TriMedia architecture family" }, - { EM_QDSP6 , "QUALCOMM DSP6 Processor" }, - { EM_8051 , "Intel 8051 and variants" }, - { EM_STXP7X , "STMicroelectronics STxP7x family" }, - { EM_NDS32 , "Andes Technology compact code size embedded RISC processor family" }, - { EM_ECOG1 , "Cyan Technology eCOG1X family" }, - { EM_ECOG1X , "Cyan Technology eCOG1X family" }, - { EM_MAXQ30 , "Dallas Semiconductor MAXQ30 Core Micro-controllers" }, - { EM_XIMO16 , "New Japan Radio (NJR) 16-bit DSP Processor" }, - { EM_MANIK , "M2000 Reconfigurable RISC Microprocessor" }, - { EM_CRAYNV2 , "Cray Inc. NV2 vector architecture" }, - { EM_RX , "Renesas RX family" }, - { EM_METAG , "Imagination Technologies META processor architecture" }, - { EM_MCST_ELBRUS , "MCST Elbrus general purpose hardware architecture" }, - { EM_ECOG16 , "Cyan Technology eCOG16 family" }, - { EM_CR16 , "National Semiconductor CompactRISC 16-bit processor" }, - { EM_ETPU , "Freescale Extended Time Processing Unit" }, - { EM_SLE9X , "Infineon Technologies SLE9X core" }, - { EM_L1OM , "Intel L1OM" }, - { EM_INTEL181 , "Reserved by Intel" }, - { EM_INTEL182 , "Reserved by Intel" }, - { EM_res183 , "Reserved by ARM" }, - { EM_res184 , "Reserved by ARM" }, - { EM_AVR32 , "Atmel Corporation 32-bit microprocessor family" }, - { EM_STM8 , "STMicroeletronics STM8 8-bit microcontroller" }, - { EM_TILE64 , "Tilera TILE64 multicore architecture family" }, - { EM_TILEPRO , "Tilera TILEPro multicore architecture family" }, - { EM_MICROBLAZE , "Xilinx MicroBlaze 32-bit RISC soft processor core" }, - { EM_CUDA , "NVIDIA CUDA architecture " }, +} machine_table[] = { + { EM_NONE, "No machine" }, + { EM_M32, "AT&T WE 32100" }, + { EM_SPARC, "SUN SPARC" }, + { EM_386, "Intel 80386" }, + { EM_68K, "Motorola m68k family" }, + { EM_88K, "Motorola m88k family" }, + { EM_486, "Intel 80486// Reserved for future use" }, + { EM_860, "Intel 80860" }, + { EM_MIPS, "MIPS R3000 (officially, big-endian only)" }, + { EM_S370, "IBM System/370" }, + { EM_MIPS_RS3_LE, + "MIPS R3000 little-endian (Oct 4 1999 Draft) Deprecated" }, + { EM_res011, "Reserved" }, + { EM_res012, "Reserved" }, + { EM_res013, "Reserved" }, + { EM_res014, "Reserved" }, + { EM_PARISC, "HPPA" }, + { EM_res016, "Reserved" }, + { EM_VPP550, "Fujitsu VPP500" }, + { EM_SPARC32PLUS, "Sun's v8plus" }, + { EM_960, "Intel 80960" }, + { EM_PPC, "PowerPC" }, + { EM_PPC64, "64-bit PowerPC" }, + { EM_S390, "IBM S/390" }, + { EM_SPU, "Sony/Toshiba/IBM SPU" }, + { EM_res024, "Reserved" }, + { EM_res025, "Reserved" }, + { EM_res026, "Reserved" }, + { EM_res027, "Reserved" }, + { EM_res028, "Reserved" }, + { EM_res029, "Reserved" }, + { EM_res030, "Reserved" }, + { EM_res031, "Reserved" }, + { EM_res032, "Reserved" }, + { EM_res033, "Reserved" }, + { EM_res034, "Reserved" }, + { EM_res035, "Reserved" }, + { EM_V800, "NEC V800 series" }, + { EM_FR20, "Fujitsu FR20" }, + { EM_RH32, "TRW RH32" }, + { EM_MCORE, "Motorola M*Core // May also be taken by Fujitsu MMA" }, + { EM_RCE, "Old name for MCore" }, + { EM_ARM, "ARM" }, + { EM_OLD_ALPHA, "Digital Alpha" }, + { EM_SH, "Renesas (formerly Hitachi) / SuperH SH" }, + { EM_SPARCV9, "SPARC v9 64-bit" }, + { EM_TRICORE, "Siemens Tricore embedded processor" }, + { EM_ARC, "ARC Cores" }, + { EM_H8_300, "Renesas (formerly Hitachi) H8/300" }, + { EM_H8_300H, "Renesas (formerly Hitachi) H8/300H" }, + { EM_H8S, "Renesas (formerly Hitachi) H8S" }, + { EM_H8_500, "Renesas (formerly Hitachi) H8/500" }, + { EM_IA_64, "Intel IA-64 Processor" }, + { EM_MIPS_X, "Stanford MIPS-X" }, + { EM_COLDFIRE, "Motorola Coldfire" }, + { EM_68HC12, "Motorola M68HC12" }, + { EM_MMA, "Fujitsu Multimedia Accelerator" }, + { EM_PCP, "Siemens PCP" }, + { EM_NCPU, "Sony nCPU embedded RISC processor" }, + { EM_NDR1, "Denso NDR1 microprocesspr" }, + { EM_STARCORE, "Motorola Star*Core processor" }, + { EM_ME16, "Toyota ME16 processor" }, + { EM_ST100, "STMicroelectronics ST100 processor" }, + { EM_TINYJ, "Advanced Logic Corp. TinyJ embedded processor" }, + { EM_X86_64, "Advanced Micro Devices X86-64 processor" }, + { EM_PDSP, "Sony DSP Processor" }, + { EM_PDP10, "Digital Equipment Corp. PDP-10" }, + { EM_PDP11, "Digital Equipment Corp. PDP-11" }, + { EM_FX66, "Siemens FX66 microcontroller" }, + { EM_ST9PLUS, "STMicroelectronics ST9+ 8/16 bit microcontroller" }, + { EM_ST7, "STMicroelectronics ST7 8-bit microcontroller" }, + { EM_68HC16, "Motorola MC68HC16 Microcontroller" }, + { EM_68HC11, "Motorola MC68HC11 Microcontroller" }, + { EM_68HC08, "Motorola MC68HC08 Microcontroller" }, + { EM_68HC05, "Motorola MC68HC05 Microcontroller" }, + { EM_SVX, "Silicon Graphics SVx" }, + { EM_ST19, "STMicroelectronics ST19 8-bit cpu" }, + { EM_VAX, "Digital VAX" }, + { EM_CRIS, "Axis Communications 32-bit embedded processor" }, + { EM_JAVELIN, "Infineon Technologies 32-bit embedded cpu" }, + { EM_FIREPATH, "Element 14 64-bit DSP processor" }, + { EM_ZSP, "LSI Logic's 16-bit DSP processor" }, + { EM_MMIX, "Donald Knuth's educational 64-bit processor" }, + { EM_HUANY, "Harvard's machine-independent format" }, + { EM_PRISM, "SiTera Prism" }, + { EM_AVR, "Atmel AVR 8-bit microcontroller" }, + { EM_FR30, "Fujitsu FR30" }, + { EM_D10V, "Mitsubishi D10V" }, + { EM_D30V, "Mitsubishi D30V" }, + { EM_V850, "NEC v850" }, + { EM_M32R, "Renesas M32R (formerly Mitsubishi M32R)" }, + { EM_MN10300, "Matsushita MN10300" }, + { EM_MN10200, "Matsushita MN10200" }, + { EM_PJ, "picoJava" }, + { EM_OPENRISC, "OpenRISC 32-bit embedded processor" }, + { EM_ARC_A5, "ARC Cores Tangent-A5" }, + { EM_XTENSA, "Tensilica Xtensa Architecture" }, + { EM_VIDEOCORE, "Alphamosaic VideoCore processor" }, + { EM_TMM_GPP, "Thompson Multimedia General Purpose Processor" }, + { EM_NS32K, "National Semiconductor 32000 series" }, + { EM_TPC, "Tenor Network TPC processor" }, + { EM_SNP1K, "Trebia SNP 1000 processor" }, + { EM_ST200, "STMicroelectronics ST200 microcontroller" }, + { EM_IP2K, "Ubicom IP2022 micro controller" }, + { EM_MAX, "MAX Processor" }, + { EM_CR, "National Semiconductor CompactRISC" }, + { EM_F2MC16, "Fujitsu F2MC16" }, + { EM_MSP430, "TI msp430 micro controller" }, + { EM_BLACKFIN, "ADI Blackfin" }, + { EM_SE_C33, "S1C33 Family of Seiko Epson processors" }, + { EM_SEP, "Sharp embedded microprocessor" }, + { EM_ARCA, "Arca RISC Microprocessor" }, + { EM_UNICORE, "Microprocessor series from PKU-Unity Ltd. and MPRC of " + "Peking University" }, + { EM_EXCESS, "eXcess: 16/32/64-bit configurable embedded CPU" }, + { EM_DXP, "Icera Semiconductor Inc. Deep Execution Processor" }, + { EM_ALTERA_NIOS2, "Altera Nios II soft-core processor" }, + { EM_CRX, "National Semiconductor CRX" }, + { EM_XGATE, "Motorola XGATE embedded processor" }, + { EM_C166, "Infineon C16x/XC16x processor" }, + { EM_M16C, "Renesas M16C series microprocessors" }, + { EM_DSPIC30F, "Microchip Technology dsPIC30F Digital Signal Controller" }, + { EM_CE, "Freescale Communication Engine RISC core" }, + { EM_M32C, "Renesas M32C series microprocessors" }, + { EM_res121, "Reserved" }, + { EM_res122, "Reserved" }, + { EM_res123, "Reserved" }, + { EM_res124, "Reserved" }, + { EM_res125, "Reserved" }, + { EM_res126, "Reserved" }, + { EM_res127, "Reserved" }, + { EM_res128, "Reserved" }, + { EM_res129, "Reserved" }, + { EM_res130, "Reserved" }, + { EM_TSK3000, "Altium TSK3000 core" }, + { EM_RS08, "Freescale RS08 embedded processor" }, + { EM_res133, "Reserved" }, + { EM_ECOG2, "Cyan Technology eCOG2 microprocessor" }, + { EM_SCORE, "Sunplus Score" }, + { EM_SCORE7, "Sunplus S+core7 RISC processor" }, + { EM_DSP24, "New Japan Radio (NJR) 24-bit DSP Processor" }, + { EM_VIDEOCORE3, "Broadcom VideoCore III processor" }, + { EM_LATTICEMICO32, "RISC processor for Lattice FPGA architecture" }, + { EM_SE_C17, "Seiko Epson C17 family" }, + { EM_TI_C6000, "Texas Instruments TMS320C6000 DSP family" }, + { EM_TI_C2000, "Texas Instruments TMS320C2000 DSP family" }, + { EM_TI_C5500, "Texas Instruments TMS320C55x DSP family" }, + { EM_res143, "Reserved" }, + { EM_res144, "Reserved" }, + { EM_res145, "Reserved" }, + { EM_res146, "Reserved" }, + { EM_res147, "Reserved" }, + { EM_res148, "Reserved" }, + { EM_res149, "Reserved" }, + { EM_res150, "Reserved" }, + { EM_res151, "Reserved" }, + { EM_res152, "Reserved" }, + { EM_res153, "Reserved" }, + { EM_res154, "Reserved" }, + { EM_res155, "Reserved" }, + { EM_res156, "Reserved" }, + { EM_res157, "Reserved" }, + { EM_res158, "Reserved" }, + { EM_res159, "Reserved" }, + { EM_MMDSP_PLUS, "STMicroelectronics 64bit VLIW Data Signal Processor" }, + { EM_CYPRESS_M8C, "Cypress M8C microprocessor" }, + { EM_R32C, "Renesas R32C series microprocessors" }, + { EM_TRIMEDIA, "NXP Semiconductors TriMedia architecture family" }, + { EM_QDSP6, "QUALCOMM DSP6 Processor" }, + { EM_8051, "Intel 8051 and variants" }, + { EM_STXP7X, "STMicroelectronics STxP7x family" }, + { EM_NDS32, + "Andes Technology compact code size embedded RISC processor family" }, + { EM_ECOG1, "Cyan Technology eCOG1X family" }, + { EM_ECOG1X, "Cyan Technology eCOG1X family" }, + { EM_MAXQ30, "Dallas Semiconductor MAXQ30 Core Micro-controllers" }, + { EM_XIMO16, "New Japan Radio (NJR) 16-bit DSP Processor" }, + { EM_MANIK, "M2000 Reconfigurable RISC Microprocessor" }, + { EM_CRAYNV2, "Cray Inc. NV2 vector architecture" }, + { EM_RX, "Renesas RX family" }, + { EM_METAG, "Imagination Technologies META processor architecture" }, + { EM_MCST_ELBRUS, "MCST Elbrus general purpose hardware architecture" }, + { EM_ECOG16, "Cyan Technology eCOG16 family" }, + { EM_CR16, "National Semiconductor CompactRISC 16-bit processor" }, + { EM_ETPU, "Freescale Extended Time Processing Unit" }, + { EM_SLE9X, "Infineon Technologies SLE9X core" }, + { EM_L1OM, "Intel L1OM" }, + { EM_INTEL181, "Reserved by Intel" }, + { EM_INTEL182, "Reserved by Intel" }, + { EM_AARCH64, "ARM AArch64" }, + { EM_res184, "Reserved by ARM" }, + { EM_AVR32, "Atmel Corporation 32-bit microprocessor family" }, + { EM_STM8, "STMicroeletronics STM8 8-bit microcontroller" }, + { EM_TILE64, "Tilera TILE64 multicore architecture family" }, + { EM_TILEPRO, "Tilera TILEPro multicore architecture family" }, + { EM_MICROBLAZE, "Xilinx MicroBlaze 32-bit RISC soft processor core" }, + { EM_CUDA, "NVIDIA CUDA architecture " }, + { EM_TILEGX, "Tilera TILE-Gx multicore architecture family" }, + { EM_CLOUDSHIELD, "CloudShield architecture family" }, + { EM_COREA_1ST, "KIPO-KAIST Core-A 1st generation processor family" }, + { EM_COREA_2ND, "KIPO-KAIST Core-A 2nd generation processor family" }, + { EM_ARC_COMPACT2, "Synopsys ARCompact V2" }, + { EM_OPEN8, "Open8 8-bit RISC soft processor core" }, + { EM_RL78, "Renesas RL78 family" }, + { EM_VIDEOCORE5, "Broadcom VideoCore V processor" }, + { EM_78KOR, "Renesas 78KOR family" }, + { EM_56800EX, "Freescale 56800EX Digital Signal Controller (DSC)" }, + { EM_BA1, "Beyond BA1 CPU architecture" }, + { EM_BA2, "Beyond BA2 CPU architecture" }, + { EM_XCORE, "XMOS xCORE processor family" }, + { EM_MCHP_PIC, "Microchip 8-bit PIC(r) family" }, + { EM_INTEL205, "Reserved by Intel" }, + { EM_INTEL206, "Reserved by Intel" }, + { EM_INTEL207, "Reserved by Intel" }, + { EM_INTEL208, "Reserved by Intel" }, + { EM_INTEL209, "Reserved by Intel" }, + { EM_KM32, "KM211 KM32 32-bit processor" }, + { EM_KMX32, "KM211 KMX32 32-bit processor" }, + { EM_KMX16, "KM211 KMX16 16-bit processor" }, + { EM_KMX8, "KM211 KMX8 8-bit processor" }, + { EM_KVARC, "KM211 KVARC processor" }, + { EM_CDP, "Paneve CDP architecture family" }, + { EM_COGE, "Cognitive Smart Memory Processor" }, + { EM_COOL, "iCelero CoolEngine" }, + { EM_NORC, "Nanoradio Optimized RISC" }, + { EM_CSR_KALIMBA, "CSR Kalimba architecture family" }, + { EM_Z80, "Zilog Z80" }, + { EM_VISIUM, "Controls and Data Services VISIUMcore processor" }, + { EM_FT32, "FTDI Chip FT32 high performance 32-bit RISC architecture" }, + { EM_MOXIE, "Moxie processor family" }, + { EM_AMDGPU, "AMD GPU architecture" }, + { EM_RISCV, "RISC-V" }, + { EM_LANAI, "Lanai processor" }, + { EM_CEVA, "CEVA Processor Architecture Family" }, + { EM_CEVA_X2, "CEVA X2 Processor Family" }, + { EM_BPF, "Linux BPF – in-kernel virtual machine" }, + { EM_GRAPHCORE_IPU, "Graphcore Intelligent Processing Unit" }, + { EM_IMG1, "Imagination Technologies" }, + { EM_NFP, "Netronome Flow Processor (P)" }, + { EM_CSKY, "C-SKY processor family" }, + { EM_ARC_COMPACT3_64, "Synopsys ARCv2.3 64-bit" }, + { EM_MCS6502, "MOS Technology MCS 6502 processor" }, + { EM_ARC_COMPACT3, "Synopsys ARCv2.3 32-bit" }, + { EM_KVX, "Kalray VLIW core of the MPPA processor family" }, + { EM_65816, "WDC 65816/65C816" }, + { EM_LOONGARCH, "Loongson Loongarch" }, + { EM_KF32, "ChipON KungFu32" }, + { EM_MT, "Morpho Techologies MT processor" }, + { EM_ALPHA, "Alpha" }, + { EM_WEBASSEMBLY, "Web Assembly" }, + { EM_DLX, "OpenDLX" }, + { EM_XSTORMY16, "Sanyo XStormy16 CPU core" }, + { EM_IQ2000, "Vitesse IQ2000" }, + { EM_M32C_OLD, "M32C_OLD" }, + { EM_NIOS32, "Altera Nios" }, + { EM_CYGNUS_MEP, "Toshiba MeP Media Engine" }, + { EM_ADAPTEVA_EPIPHANY, "Adapteva EPIPHANY" }, + { EM_CYGNUS_FRV, "Fujitsu FR-V" }, + { EM_S12Z, "Freescale S12Z" }, }; - -static struct section_type_table_t { - const Elf64_Half key; - const char* str; -} section_type_table [] = +static const struct section_type_table_t { - { SHT_NULL , "NULL" }, - { SHT_PROGBITS , "PROGBITS" }, - { SHT_SYMTAB , "SYMTAB" }, - { SHT_STRTAB , "STRTAB" }, - { SHT_RELA , "RELA" }, - { SHT_HASH , "HASH" }, - { SHT_DYNAMIC , "DYNAMIC" }, - { SHT_NOTE , "NOTE" }, - { SHT_NOBITS , "NOBITS" }, - { SHT_REL , "REL" }, - { SHT_SHLIB , "SHLIB" }, - { SHT_DYNSYM , "DYNSYM" }, - { SHT_INIT_ARRAY , "INIT_ARRAY" }, - { SHT_FINI_ARRAY , "FINI_ARRAY" }, + const Elf64_Word key; + const char* str; +} section_type_table[] = { + { SHT_NULL, "NULL" }, + { SHT_PROGBITS, "PROGBITS" }, + { SHT_SYMTAB, "SYMTAB" }, + { SHT_STRTAB, "STRTAB" }, + { SHT_RELA, "RELA" }, + { SHT_HASH, "HASH" }, + { SHT_DYNAMIC, "DYNAMIC" }, + { SHT_NOTE, "NOTE" }, + { SHT_NOBITS, "NOBITS" }, + { SHT_REL, "REL" }, + { SHT_SHLIB, "SHLIB" }, + { SHT_DYNSYM, "DYNSYM" }, + { SHT_INIT_ARRAY, "INIT_ARRAY" }, + { SHT_FINI_ARRAY, "FINI_ARRAY" }, { SHT_PREINIT_ARRAY, "PREINIT_ARRAY" }, - { SHT_GROUP , "GROUP" }, - { SHT_SYMTAB_SHNDX , "SYMTAB_SHNDX " }, + { SHT_GROUP, "GROUP" }, + { SHT_SYMTAB_SHNDX, "SYMTAB_SHNDX" }, + { SHT_GNU_ATTRIBUTES, "GNU_ATTRIBUTES" }, + { SHT_GNU_HASH, "GNU_HASH" }, + { SHT_GNU_LIBLIST, "GNU_LIBLIST" }, + { SHT_CHECKSUM, "CHECKSUM" }, + { SHT_LOSUNW, "LOSUNW" }, + { SHT_SUNW_move, "SUNW_move" }, + { SHT_SUNW_COMDAT, "SUNW_COMDAT" }, + { SHT_SUNW_syminfo, "SUNW_syminfo" }, + { SHT_GNU_verdef, "GNU_verdef" }, + { SHT_GNU_verneed, "GNU_verneed" }, + { SHT_GNU_versym, "GNU_versym" }, + { SHT_ARM_EXIDX, "ARM_EXIDX" }, + { SHT_ARM_PREEMPTMAP, "ARM_PREEMPTMAP" }, + { SHT_ARM_ATTRIBUTES, "ARM_ATTRIBUTES" }, + { SHT_ARM_DEBUGOVERLAY, "ARM_DEBUGOVERLAY" }, + { SHT_ARM_OVERLAYSECTION, "ARM_OVERLAYSECTION" }, + }; - -static struct segment_type_table_t { +static const struct segment_type_table_t +{ const Elf_Word key; const char* str; -} segment_type_table [] = -{ - { PT_NULL , "NULL" }, - { PT_LOAD , "LOAD" }, +} segment_type_table[] = { + { PT_NULL, "NULL" }, + { PT_LOAD, "LOAD" }, { PT_DYNAMIC, "DYNAMIC" }, - { PT_INTERP , "INTERP" }, - { PT_NOTE , "NOTE" }, - { PT_SHLIB , "SHLIB" }, - { PT_PHDR , "PHDR" }, - { PT_TLS , "TLS" }, + { PT_INTERP, "INTERP" }, + { PT_NOTE, "NOTE" }, + { PT_SHLIB, "SHLIB" }, + { PT_PHDR, "PHDR" }, + { PT_TLS, "TLS" }, + { PT_GNU_EH_FRAME, "GNU_EH_FRAME" }, + { PT_GNU_STACK, "GNU_STACK" }, + { PT_GNU_RELRO, "GNU_RELRO" }, + { PT_GNU_PROPERTY, "GNU_PROPERTY" }, + { PT_GNU_MBIND_LO, "GNU_MBIND_LO" }, + { PT_GNU_MBIND_HI, "GNU_MBIND_HI" }, + { PT_PAX_FLAGS, "PAX_FLAGS" }, + { PT_OPENBSD_RANDOMIZE, "OPENBSD_RANDOMIZE" }, + { PT_OPENBSD_WXNEEDED, "OPENBSD_WXNEEDED " }, + { PT_OPENBSD_BOOTDATA, "OPENBSD_BOOTDATA " }, + { PT_SUNWBSS, "PT_SUNWBSS" }, + { PT_SUNWSTACK, "SUNWSTACK" }, }; - -static struct segment_flag_table_t { +static const struct segment_flag_table_t +{ const Elf_Word key; const char* str; -} segment_flag_table [] = -{ - { 0, "" }, - { 1, "X" }, - { 2, "W" }, - { 3, "WX" }, - { 4, "R" }, - { 5, "RX" }, - { 6, "RW" }, - { 7, "RWX" }, +} segment_flag_table[] = { + { 0, " " }, { 1, " E" }, { 2, " W " }, { 3, " WE" }, + { 4, "R " }, { 5, "R E" }, { 6, "RW " }, { 7, "RWE" }, }; - -static struct symbol_bind_t { +static const struct symbol_bind_t +{ const Elf_Word key; const char* str; -} symbol_bind_table [] = -{ - { STB_LOCAL , "LOCAL" }, - { STB_GLOBAL , "GLOBAL" }, - { STB_WEAK , "WEAK" }, - { STB_LOOS , "LOOS" }, - { STB_HIOS , "HIOS" }, - { STB_MULTIDEF, "MULTIDEF" }, - { STB_LOPROC , "LOPROC" }, - { STB_HIPROC , "HIPROC" }, +} symbol_bind_table[] = { + { STB_LOCAL, "LOCAL" }, { STB_GLOBAL, "GLOBAL" }, + { STB_WEAK, "WEAK" }, { STB_LOOS, "LOOS" }, + { STB_HIOS, "HIOS" }, { STB_MULTIDEF, "MULTIDEF" }, + { STB_LOPROC, "LOPROC" }, { STB_HIPROC, "HIPROC" }, }; - -static struct symbol_type_t { +static const struct symbol_type_t +{ const Elf_Word key; const char* str; -} symbol_type_table [] = -{ - { STT_NOTYPE , "NOTYPE" }, - { STT_OBJECT , "OBJECT" }, - { STT_FUNC , "FUNC" }, - { STT_SECTION, "SECTION" }, - { STT_FILE , "FILE" }, - { STT_COMMON , "COMMON" }, - { STT_TLS , "TLS" }, - { STT_LOOS , "LOOS" }, - { STT_HIOS , "HIOS" }, - { STT_LOPROC , "LOPROC" }, - { STT_HIPROC , "HIPROC" }, +} symbol_type_table[] = { + { STT_NOTYPE, "NOTYPE" }, { STT_OBJECT, "OBJECT" }, + { STT_FUNC, "FUNC" }, { STT_SECTION, "SECTION" }, + { STT_FILE, "FILE" }, { STT_COMMON, "COMMON" }, + { STT_TLS, "TLS" }, { STT_LOOS, "LOOS" }, + { STT_HIOS, "HIOS" }, { STT_LOPROC, "LOPROC" }, + { STT_HIPROC, "HIPROC" }, }; - -static struct dynamic_tag_t { +static const struct dynamic_tag_t +{ const Elf_Word key; const char* str; -} dynamic_tag_table [] = -{ - { DT_NULL , "NULL" }, - { DT_NEEDED , "NEEDED" }, - { DT_PLTRELSZ , "PLTRELSZ" }, - { DT_PLTGOT , "PLTGOT" }, - { DT_HASH , "HASH" }, - { DT_STRTAB , "STRTAB" }, - { DT_SYMTAB , "SYMTAB" }, - { DT_RELA , "RELA" }, - { DT_RELASZ , "RELASZ" }, - { DT_RELAENT , "RELAENT" }, - { DT_STRSZ , "STRSZ" }, - { DT_SYMENT , "SYMENT" }, - { DT_INIT , "INIT" }, - { DT_FINI , "FINI" }, - { DT_SONAME , "SONAME" }, - { DT_RPATH , "RPATH" }, - { DT_SYMBOLIC , "SYMBOLIC" }, - { DT_REL , "REL" }, - { DT_RELSZ , "RELSZ" }, - { DT_RELENT , "RELENT" }, - { DT_PLTREL , "PLTREL" }, - { DT_DEBUG , "DEBUG" }, - { DT_TEXTREL , "TEXTREL" }, - { DT_JMPREL , "JMPREL" }, - { DT_BIND_NOW , "BIND_NOW" }, - { DT_INIT_ARRAY , "INIT_ARRAY" }, - { DT_FINI_ARRAY , "FINI_ARRAY" }, - { DT_INIT_ARRAYSZ , "INIT_ARRAYSZ" }, - { DT_FINI_ARRAYSZ , "FINI_ARRAYSZ" }, - { DT_RUNPATH , "RUNPATH" }, - { DT_FLAGS , "FLAGS" }, - { DT_ENCODING , "ENCODING" }, - { DT_PREINIT_ARRAY , "PREINIT_ARRAY" }, +} dynamic_tag_table[] = { + { DT_NULL, "NULL" }, + { DT_NEEDED, "NEEDED" }, + { DT_PLTRELSZ, "PLTRELSZ" }, + { DT_PLTGOT, "PLTGOT" }, + { DT_HASH, "HASH" }, + { DT_STRTAB, "STRTAB" }, + { DT_SYMTAB, "SYMTAB" }, + { DT_RELA, "RELA" }, + { DT_RELASZ, "RELASZ" }, + { DT_RELAENT, "RELAENT" }, + { DT_STRSZ, "STRSZ" }, + { DT_SYMENT, "SYMENT" }, + { DT_INIT, "INIT" }, + { DT_FINI, "FINI" }, + { DT_SONAME, "SONAME" }, + { DT_RPATH, "RPATH" }, + { DT_SYMBOLIC, "SYMBOLIC" }, + { DT_REL, "REL" }, + { DT_RELSZ, "RELSZ" }, + { DT_RELENT, "RELENT" }, + { DT_PLTREL, "PLTREL" }, + { DT_DEBUG, "DEBUG" }, + { DT_TEXTREL, "TEXTREL" }, + { DT_JMPREL, "JMPREL" }, + { DT_BIND_NOW, "BIND_NOW" }, + { DT_INIT_ARRAY, "INIT_ARRAY" }, + { DT_FINI_ARRAY, "FINI_ARRAY" }, + { DT_INIT_ARRAYSZ, "INIT_ARRAYSZ" }, + { DT_FINI_ARRAYSZ, "FINI_ARRAYSZ" }, + { DT_RUNPATH, "RUNPATH" }, + { DT_FLAGS, "FLAGS" }, + { DT_ENCODING, "ENCODING" }, + { DT_PREINIT_ARRAY, "PREINIT_ARRAY" }, { DT_PREINIT_ARRAYSZ, "PREINIT_ARRAYSZ" }, - { DT_MAXPOSTAGS , "MAXPOSTAGS" }, + { DT_MAXPOSTAGS, "MAXPOSTAGS" }, + { DT_GNU_HASH, "GNU_HASH" }, + { DT_TLSDESC_PLT, "TLSDESC_PLT" }, + { DT_TLSDESC_GOT, "TLSDESC_GOT" }, + { DT_GNU_CONFLICT, "GNU_CONFLICT" }, + { DT_GNU_LIBLIST, "GNU_LIBLIST" }, + { DT_CONFIG, "CONFIG" }, + { DT_DEPAUDIT, "DEPAUDIT" }, + { DT_AUDIT, "AUDIT" }, + { DT_PLTPAD, "PLTPAD" }, + { DT_MOVETAB, "MOVETAB" }, + { DT_SYMINFO, "SYMINFO" }, + { DT_ADDRRNGHI, "ADDRRNGHI" }, + { DT_VERSYM, "VERSYM" }, + { DT_RELACOUNT, "RELACOUNT" }, + { DT_RELCOUNT, "RELCOUNT" }, + { DT_FLAGS_1, "FLAGS_1" }, + { DT_VERDEF, "VERDEF" }, + { DT_VERDEFNUM, "VERDEFNUM" }, + { DT_VERNEED, "VERNEED" }, + { DT_VERNEEDNUM, "VERNEEDNUM" }, }; +// clang-format off +static const struct note_tag_t +{ + struct note_values_t + { + Elf64_Word type; + std::string type_str; + std::string description; + }; + std::string name; + std::vector values; +} note_tag_table[] = { + { "", + { { NT_PRSTATUS, "NT_PRSTATUS", "prstatus struct" }, + { NT_FPREGSET, "NT_FPREGSET", "fpregset struct" }, + { NT_PRPSINFO, "NT_PRPSINFO", "prpsinfo struct" }, + { NT_TASKSTRUCT, "NT_TASKSTRUCT", "task struct" }, + { NT_AUXV, "NT_AUXV", "Elfxx_auxv_t" }, + { NT_PSTATUS, "NT_PSTATUS", "pstatus struct" }, + { NT_FPREGS, "NT_FPREGS", "fpregset struct" }, + { NT_PSINFO, "NT_PSINFO", "psinfo struct" }, + { NT_LWPSTATUS, "NT_LWPSTATUS", "lwpstatus_t struct" }, + { NT_LWPSINFO, "NT_LWPSINFO", "lwpsinfo_t struct" }, + { NT_WIN32PSTATUS, "NT_WIN32PSTATUS", "win32_pstatus struct" }, + } }, + { "LINUX", + { { NT_PRXFPREG, "NT_PRXFPREG", "Contains a user_xfpregs_struct;" }, + { NT_PPC_VMX, "NT_PPC_VMX", "PowerPC Altivec/VMX registers" }, + { NT_PPC_VSX, "NT_PPC_VSX", "PowerPC VSX registers" }, + { NT_PPC_TAR, "NT_PPC_TAR", "PowerPC Target Address Register" }, + { NT_PPC_PPR, "NT_PPC_PPR", "PowerPC Program Priority Register" }, + { NT_PPC_DSCR, "NT_PPC_DSCR", "PowerPC Data Stream Control Register" }, + { NT_PPC_EBB, "NT_PPC_EBB", "PowerPC Event Based Branch Registers" }, + { NT_PPC_PMU, "NT_PPC_PMU", "PowerPC Performance Monitor Registers" }, + { NT_PPC_TM_CGPR, "NT_PPC_TM_CGPR", "PowerPC TM checkpointed GPR Registers" }, + { NT_PPC_TM_CFPR, "NT_PPC_TM_CFPR", "PowerPC TM checkpointed FPR Registers" }, + { NT_PPC_TM_CVMX, "NT_PPC_TM_CVMX", "PowerPC TM checkpointed VMX Registers" }, + { NT_PPC_TM_CVSX, "NT_PPC_TM_CVSX", "PowerPC TM checkpointed VSX Registers" }, + { NT_PPC_TM_SPR, "NT_PPC_TM_SPR", "PowerPC TM Special Purpose Registers" }, + { NT_PPC_TM_CTAR, "NT_PPC_TM_CTAR", "PowerPC TM checkpointed TAR" }, + { NT_PPC_TM_CPPR, "NT_PPC_TM_CPPR", "PowerPC TM checkpointed PPR" }, + { NT_PPC_TM_CDSCR, "NT_PPC_TM_CDSCR", "PowerPC TM checkpointed Data SCR" }, + { NT_386_TLS, "NT_386_TLS", "x86 TLS information" }, + { NT_386_IOPERM, "NT_386_IOPERM", "x86 io permissions" }, + { NT_X86_XSTATE, "NT_X86_XSTATE", "x86 XSAVE extended state" }, + { NT_X86_CET, "NT_X86_CET", "x86 CET state" }, + { NT_S390_HIGH_GPRS, "NT_S390_HIGH_GPRS", "S/390 upper halves of GPRs " }, + { NT_S390_TIMER, "NT_S390_TIMER", "S390 timer" }, + { NT_S390_TODCMP, "NT_S390_TODCMP", "S390 TOD clock comparator" }, + { NT_S390_TODPREG, "NT_S390_TODPREG", "S390 TOD programmable register" }, + { NT_S390_CTRS, "NT_S390_CTRS", "S390 control registers" }, + { NT_S390_PREFIX, "NT_S390_PREFIX", "S390 prefix register" }, + { NT_S390_LAST_BREAK, "NT_S390_LAST_BREAK", "S390 breaking event address" }, + { NT_S390_SYSTEM_CALL, "NT_S390_SYSTEM_CALL", "S390 system call restart data" }, + { NT_S390_TDB, "NT_S390_TDB", "S390 transaction diagnostic block" }, + { NT_S390_VXRS_LOW, "NT_S390_VXRS_LOW", "S390 vector registers 0-15 upper half" }, + { NT_S390_VXRS_HIGH, "NT_S390_VXRS_HIGH", "S390 vector registers 16-31" }, + { NT_S390_GS_CB, "NT_S390_GS_CB", "s390 guarded storage registers" }, + { NT_S390_GS_BC, "NT_S390_GS_BC", "s390 guarded storage broadcast control block" }, + { NT_ARM_VFP, "NT_ARM_VFP", "ARM VFP registers" }, + { NT_ARM_TLS, "NT_ARM_TLS", "AArch TLS registers" }, + { NT_ARM_HW_BREAK, "NT_ARM_HW_BREAK", "AArch hardware breakpoint registers" }, + { NT_ARM_HW_WATCH, "NT_ARM_HW_WATCH", "AArch hardware watchpoint registers" }, + { NT_ARM_SVE, "NT_ARM_SVE", "AArch SVE registers. " }, + { NT_ARM_PAC_MASK, "NT_ARM_PAC_MASK", "AArch pointer authentication code masks" }, + { NT_ARM_PACA_KEYS, "NT_ARM_PACA_KEYS", "ARM pointer authentication address keys" }, + { NT_ARM_PACG_KEYS, "NT_ARM_PACG_KEYS", "ARM pointer authentication generic keys" }, + { NT_ARM_TAGGED_ADDR_CTRL, "NT_ARM_TAGGED_ADDR_CTRL", "AArch64 tagged address control (prctl())" }, + { NT_ARM_PAC_ENABLED_KEYS, "NT_ARM_PAC_ENABLED_KEYS", "AArch64 pointer authentication enabled keys (prctl())" }, + { NT_ARC_V2, "NT_ARC_V2", "ARC HS accumulator/extra registers. " }, + { NT_LARCH_CPUCFG, "NT_LARCH_CPUCFG", "LoongArch CPU config registers" }, + { NT_LARCH_CSR, "NT_LARCH_CSR", "LoongArch Control State Registers" }, + { NT_LARCH_LSX, "NT_LARCH_LSX", "LoongArch SIMD eXtension registers" }, + { NT_LARCH_LASX, "NT_LARCH_LASX", "LoongArch Advanced SIMD eXtension registers" }, + { NT_RISCV_CSR, "NT_RISCV_CSR", "RISC-V Control and Status Registers" }, + } }, + { "CORE", + { { NT_LARCH_LBT, "NT_LARCH_LBT", "LoongArch Binary Translation registers" } + } }, + { "FreeBSD", + { { NT_FREEBSD_THRMISC, "NT_FREEBSD_THRMISC", "Thread miscellaneous info." }, + { NT_FREEBSD_PROCSTAT_PROC, "NT_FREEBSD_PROCSTAT_PROC", "Procstat proc data." }, + { NT_FREEBSD_PROCSTAT_FILES, "NT_FREEBSD_PROCSTAT_FILES", "Procstat files data." }, + { NT_FREEBSD_PROCSTAT_VMMAP, "NT_FREEBSD_PROCSTAT_VMMAP", "Procstat vmmap data." }, + { NT_FREEBSD_PROCSTAT_GROUPS, "NT_FREEBSD_PROCSTAT_GROUPS", "Procstat groups data." }, + { NT_FREEBSD_PROCSTAT_UMASK, "NT_FREEBSD_PROCSTAT_UMASK", "Procstat umask data." }, + { NT_FREEBSD_PROCSTAT_RLIMIT, "NT_FREEBSD_PROCSTAT_RLIMIT", "Procstat rlimit data." }, + { NT_FREEBSD_PROCSTAT_OSREL, "NT_FREEBSD_PROCSTAT_OSREL", "Procstat osreldate data." }, + { NT_FREEBSD_PROCSTAT_PSSTRINGS, "NT_FREEBSD_PROCSTAT_PSSTRINGS", "Procstat ps_strings data." }, + { NT_FREEBSD_PROCSTAT_AUXV, "NT_FREEBSD_PROCSTAT_AUXV", "Procstat auxv data." }, + { NT_FREEBSD_PTLWPINFO, "NT_FREEBSD_PTLWPINFO", "Thread ptrace miscellaneous info." }, + } }, + { "NetBSD-CORE", + { { NT_NETBSDCORE_PROCINFO, "NT_NETBSDCORE_PROCINFO", "Has a struct procinfo" }, + { NT_NETBSDCORE_AUXV, "NT_NETBSDCORE_AUXV", "Has auxv data" }, + { NT_NETBSDCORE_LWPSTATUS, "NT_NETBSDCORE_LWPSTATUS", "Has LWPSTATUS data" }, + { NT_NETBSDCORE_FIRSTMACH, "NT_NETBSDCORE_FIRSTMACH", "start of machdep note types" }, + } }, + { "OpenBSD", + { { NT_OPENBSD_PROCINFO, "NT_OPENBSD_PROCINFO", "" }, + { NT_OPENBSD_AUXV, "NT_OPENBSD_AUXV", "" }, + { NT_OPENBSD_REGS, "NT_OPENBSD_REGS", "" }, + { NT_OPENBSD_FPREGS, "NT_OPENBSD_FPREGS", "" }, + { NT_OPENBSD_XFPREGS, "NT_OPENBSD_XFPREGS", "" }, + { NT_OPENBSD_WCOOKIE, "NT_OPENBSD_WCOOKIE", "" }, + } }, + { "SPU", + { { NT_SPU, "NT_SPU", "" } + } }, + { "GNU", + { + { NT_GNU_ABI_TAG, "NT_GNU_ABI_TAG", "GNU ABI tag" }, + { NT_GNU_HWCAP, "NT_GNU_HWCAP", "Used by ld.so and kernel vDSO" }, + { NT_GNU_BUILD_ID, "NT_GNU_BUILD_ID", "Build ID of the binary" }, + { NT_GNU_GOLD_VERSION, "NT_GNU_GOLD_VERSION", "Version of GNU gold used to link the binary" }, + { NT_GNU_PROPERTY_TYPE_0, "NT_GNU_PROPERTY_TYPE_0", "Property type 0" }, + // { NT_GNU_PROPERTY_TYPE_1, "NT_GNU_PROPERTY_TYPE_1", "Property type 1" }, + // { NT_GNU_PROPERTY_TYPE_2, "NT_GNU_PROPERTY_TYPE_2", "Property type 2" }, + // { NT_GNU_PROPERTY_TYPE_3, "NT_GNU_PROPERTY_TYPE_3", "Property type 3" }, + // { NT_GNU_PROPERTY_TYPE_4, "NT_GNU_PROPERTY_TYPE_4", "Property type 4" }, + // { NT_GNU_PROPERTY_TYPE_5, "NT_GNU_PROPERTY_TYPE_5", "Property type 5" }, + // { NT_GNU_PROPERTY_TYPE_6, "NT_GNU_PROPERTY_TYPE_6", "Property type 6" }, + // { NT_GNU_PROPERTY_TYPE_7, "NT_GNU_PROPERTY_TYPE_7", "Property type 7" }, + // { NT_GNU_PROPERTY_TYPE_8, "NT_GNU_PROPERTY_TYPE_8", "Property type 8" }, + // { NT_GNU_PROPERTY_TYPE_9, "NT_GNU_PROPERTY_TYPE_9", "Property type 9" }, + // { NT_GNU_PROPERTY_TYPE_10, "NT_GNU_PROPERTY_TYPE_10", "Property type 10" }, + // { NT_GNU_PROPERTY_TYPE_11, "NT_GNU_PROPERTY_TYPE_11", "Property type 11" }, + // { NT_GNU_PROPERTY_TYPE_12, "NT_GNU_PROPERTY_TYPE_12", "Property type 12" }, + // { NT_GNU_PROPERTY_TYPE_13, "NT_GNU_PROPERTY_TYPE_13", "Property type 13" }, + // { NT_GNU_PROPERTY_TYPE_14, "NT_GNU_PROPERTY_TYPE_14", "Property type 14" }, + } }, + // { "SOLARIS", + // { { NT_SOLARIS_AUXV, "NT_SOLARIS_AUXV", "" } + // } }, + // { "AIX", + // { { NT_AIX_AUXV, "NT_AIX_AUXV", "" } + // } }, + // { "IRIX", + // { { NT_IRIX_FPREGS, "NT_IRIX_FPREGS", "" } + // } }, +}; +// clang-format on + static const ELFIO::Elf_Xword MAX_DATA_ENTRIES = 64; //------------------------------------------------------------------------------ class dump { -#define DUMP_DEC_FORMAT( width ) std::setw(width) << std::setfill( ' ' ) << \ - std::dec << std::right -#define DUMP_HEX_FORMAT( width ) std::setw(width) << std::setfill( '0' ) << \ - std::hex << std::right -#define DUMP_STR_FORMAT( width ) std::setw(width) << std::setfill( ' ' ) << \ - std::hex << std::left +#define DUMP_DEC_FORMAT( width ) \ + std::setw( width ) << std::setfill( ' ' ) << std::dec << std::right +#define DUMP_HEX0x_FORMAT( width ) \ + "0x" << std::setw( width ) << std::setfill( '0' ) << std::hex << std::right +#define DUMP_HEX_FORMAT( width ) \ + std::setw( width ) << std::setfill( '0' ) << std::hex << std::right +#define DUMP_STR_FORMAT( width ) \ + std::setw( width ) << std::setfill( ' ' ) << std::hex << std::left public: -//------------------------------------------------------------------------------ - static void - header( std::ostream& out, const elfio& reader ) - { - if (!reader.get_header_size()) - { - return; - } - out << "ELF Header" << std::endl << std::endl - << " Class: " << str_class( reader.get_class() ) << std::endl - << " Encoding: " << str_endian( reader.get_encoding() ) << std::endl - << " ELFVersion: " << str_version( reader.get_elf_version() ) << std::endl - << " Type: " << str_type( reader.get_type() ) << std::endl - << " Machine: " << str_machine( reader.get_machine() ) << std::endl - << " Version: " << str_version( reader.get_version() ) << std::endl - << " Entry: " << "0x" << std::hex << reader.get_entry() << std::endl - << " Flags: " << "0x" << std::hex << reader.get_flags() << std::endl - << std::endl; - } + //------------------------------------------------------------------------------ + static void header( std::ostream& out, const elfio& reader ) + { + if ( !reader.get_header_size() ) { + return; + } + out << "ELF Header" << std::endl + << std::endl + << " Class: " << str_class( reader.get_class() ) << std::endl + << " Encoding: " << str_endian( reader.get_encoding() ) + << std::endl + << " ELFVersion: " << str_version( reader.get_elf_version() ) + << std::endl + << " OS/ABI: " << str_os_abi( reader.get_os_abi() ) + << std::endl + << " ABI Version:" << (int)reader.get_abi_version() << std::endl + << " Type: " << str_type( reader.get_type() ) << std::endl + << " Machine: " << str_machine( reader.get_machine() ) + << std::endl + << " Version: " << str_version( reader.get_version() ) + << std::endl + << " Entry: " + << "0x" << std::hex << reader.get_entry() << std::endl + << " Flags: " + << "0x" << std::hex << reader.get_flags() << std::endl + << std::endl; + } -//------------------------------------------------------------------------------ - static void - section_headers( std::ostream& out, const elfio& reader ) + //------------------------------------------------------------------------------ + static void section_headers( std::ostream& out, const elfio& reader ) { Elf_Half n = reader.sections.size(); @@ -459,335 +723,424 @@ class dump out << "Section Headers:" << std::endl; if ( reader.get_class() == ELFCLASS32 ) { // Output for 32-bit - out << "[ Nr ] Type Addr Size ES Flg Lk Inf Al Name" << std::endl; + out << "[ Nr ] Type Addr Size ES Flg " + "Lk Inf Al Name" + << std::endl; } - else { // Output for 64-bit - out << "[ Nr ] Type Addr Size ES Flg" << std::endl - << " Lk Inf Al Name" << std::endl; + else { // Output for 64-bit + out << "[ Nr ] Type Addr Size " + " Offset Flg" + << std::endl + << " ES Lk Inf Al Name" << std::endl; } - + for ( Elf_Half i = 0; i < n; ++i ) { // For all sections - section* sec = reader.sections[i]; + const section* sec = reader.sections[i]; section_header( out, i, sec, reader.get_class() ); } - - out << "Key to Flags: W (write), A (alloc), X (execute)\n\n" + + out << "Key to Flags: W (write), A (alloc), X (execute), " << std::endl; + out << " M (merge), S (strings), I (info)," << std::endl; + out << " L (link order), O (extra OS processing required)," + << std::endl; + out << " G (group), T (TLS), C (compressed), E (exclude)" << std::endl; } -//------------------------------------------------------------------------------ - static void - section_header( std::ostream& out, Elf_Half no, const section* sec, - unsigned char elf_class ) + //------------------------------------------------------------------------------ + static void section_header( std::ostream& out, + Elf_Half no, + const section* sec, + unsigned char elf_class ) { std::ios_base::fmtflags original_flags = out.flags(); + // clang-format off if ( elf_class == ELFCLASS32 ) { // Output for 32-bit - out << "[" - << DUMP_DEC_FORMAT( 5 ) << no - << "] " - << DUMP_STR_FORMAT( 17 ) << str_section_type( sec->get_type() ) << " " - << DUMP_HEX_FORMAT( 8 ) << sec->get_address() << " " - << DUMP_HEX_FORMAT( 8 ) << sec->get_size() << " " - << DUMP_HEX_FORMAT( 2 ) << sec->get_entry_size() << " " - << DUMP_STR_FORMAT( 3 ) << section_flags( sec->get_flags() ) << " " - << DUMP_HEX_FORMAT( 2 ) << sec->get_link() << " " - << DUMP_HEX_FORMAT( 3 ) << sec->get_info() << " " - << DUMP_HEX_FORMAT( 2 ) << sec->get_addr_align() << " " - << DUMP_STR_FORMAT( 17 ) << sec->get_name() << " " - << std::endl; + out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] " + << DUMP_STR_FORMAT( 17 ) << str_section_type( sec->get_type() ) + << " " << DUMP_HEX0x_FORMAT( 8 ) << sec->get_address() << " " + << DUMP_HEX0x_FORMAT( 8 ) << sec->get_size() << " " + << DUMP_HEX0x_FORMAT( 2 ) << sec->get_entry_size() << " " + << DUMP_STR_FORMAT( 3 ) << section_flags( sec->get_flags() ) + << " " << DUMP_HEX0x_FORMAT( 2 ) << sec->get_link() << " " + << DUMP_HEX0x_FORMAT( 3 ) << sec->get_info() << " " + << DUMP_HEX0x_FORMAT( 2 ) << sec->get_addr_align() << " " + << DUMP_STR_FORMAT( 17 ) << sec->get_name() << " " << std::endl; } - else { // Output for 64-bit - out << "[" - << DUMP_DEC_FORMAT( 5 ) << no - << "] " + else { // Output for 64-bit + out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] " << DUMP_STR_FORMAT( 17 ) << str_section_type( sec->get_type() ) << " " - << DUMP_HEX_FORMAT( 16 ) << sec->get_address() << " " - << DUMP_HEX_FORMAT( 16 ) << sec->get_size() << " " - << DUMP_HEX_FORMAT( 4 ) << sec->get_entry_size() << " " - << DUMP_STR_FORMAT( 3 ) << section_flags( sec->get_flags() ) << " " + << DUMP_HEX0x_FORMAT( 16 ) << sec->get_address() << " " + << DUMP_HEX0x_FORMAT( 16 ) << sec->get_size() << " " + << DUMP_HEX0x_FORMAT( 8 ) << sec->get_offset() << " " + << DUMP_STR_FORMAT( 3) << section_flags( sec->get_flags() ) << std::endl - << " " - << DUMP_HEX_FORMAT( 4 ) << sec->get_link() << " " - << DUMP_HEX_FORMAT( 4 ) << sec->get_info() << " " - << DUMP_HEX_FORMAT( 4 ) << sec->get_addr_align() << " " - << DUMP_STR_FORMAT( 17 ) << sec->get_name() << " " + << DUMP_STR_FORMAT( 8 ) << " " + << DUMP_HEX0x_FORMAT( 4 ) << sec->get_entry_size() << " " + << DUMP_HEX0x_FORMAT( 4 ) << sec->get_link() << " " + << DUMP_HEX0x_FORMAT( 4 ) << sec->get_info() << " " + << DUMP_HEX0x_FORMAT( 4 ) << sec->get_addr_align() << " " + << DUMP_STR_FORMAT( 17 ) << sec->get_name() << std::endl; } + // clang-format on - out.flags(original_flags); + out.flags( original_flags ); - return; + return; } -//------------------------------------------------------------------------------ - static void - segment_headers( std::ostream& out, const elfio& reader ) + //------------------------------------------------------------------------------ + static void segment_headers( std::ostream& out, const elfio& reader ) { Elf_Half n = reader.segments.size(); if ( n == 0 ) { return; } - out << "Segment headers:" << std::endl; + out << "Program Headers:" << std::endl; if ( reader.get_class() == ELFCLASS32 ) { // Output for 32-bit - out << "[ Nr ] Type VirtAddr PhysAddr FileSize Mem.Size Flags Align" + out << "[ Nr ] Type VirtAddr PhysAddr FileSize " + "Mem.Size Flags Align" << std::endl; } - else { // Output for 64-bit - out << "[ Nr ] Type VirtAddr PhysAddr Flags" << std::endl - << " FileSize Mem.Size Align" + else { // Output for 64-bit + out << "[ Nr ] Type Offset VirtAddr " + " PhysAddr" + + << std::endl + << " FileSize MemSize " + " Flags Align" << std::endl; } - + for ( Elf_Half i = 0; i < n; ++i ) { - segment* seg = reader.segments[i]; + const segment* seg = reader.segments[i]; segment_header( out, i, seg, reader.get_class() ); } - + out << std::endl; } -//------------------------------------------------------------------------------ - static void - segment_header( std::ostream& out, Elf_Half no, const segment* seg, - unsigned int elf_class ) + //------------------------------------------------------------------------------ + static void segment_header( std::ostream& out, + Elf_Half no, + const segment* seg, + unsigned int elf_class ) { std::ios_base::fmtflags original_flags = out.flags(); - + // clang-format off if ( elf_class == ELFCLASS32 ) { // Output for 32-bit - out << "[" - << DUMP_DEC_FORMAT( 5 ) << no - << "] " - << DUMP_STR_FORMAT( 14 ) << str_segment_type( seg->get_type() ) << " " - << DUMP_HEX_FORMAT( 8 ) << seg->get_virtual_address() << " " - << DUMP_HEX_FORMAT( 8 ) << seg->get_physical_address() << " " - << DUMP_HEX_FORMAT( 8 ) << seg->get_file_size() << " " - << DUMP_HEX_FORMAT( 8 ) << seg->get_memory_size() << " " - << DUMP_STR_FORMAT( 8 ) << str_segment_flag( seg->get_flags() ) << " " - << DUMP_HEX_FORMAT( 8 ) << seg->get_align() << " " + out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] " + << DUMP_STR_FORMAT( 14 ) << str_segment_type( seg->get_type() ) + << " " << DUMP_HEX0x_FORMAT( 8 ) << seg->get_virtual_address() + << " " << DUMP_HEX0x_FORMAT( 8 ) << seg->get_physical_address() + << " " << DUMP_HEX0x_FORMAT( 8 ) << seg->get_file_size() << " " + << DUMP_HEX0x_FORMAT( 8 ) << seg->get_memory_size() << " " + << DUMP_STR_FORMAT( 8 ) << str_segment_flag( seg->get_flags() ) + << " " << DUMP_HEX0x_FORMAT( 8 ) << seg->get_align() << " " << std::endl; } - else { // Output for 64-bit - out << "[" - << DUMP_DEC_FORMAT( 5 ) << no - << "] " - << DUMP_STR_FORMAT( 14 ) << str_segment_type( seg->get_type() ) << " " - << DUMP_HEX_FORMAT( 16 ) << seg->get_virtual_address() << " " - << DUMP_HEX_FORMAT( 16 ) << seg->get_physical_address() << " " - << DUMP_STR_FORMAT( 16 ) << str_segment_flag( seg->get_flags() ) << " " + else { // Output for 64-bit + out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] " + << DUMP_STR_FORMAT( 14 ) << str_segment_type( seg->get_type() ) << " " + << DUMP_HEX0x_FORMAT( 16 ) << seg->get_offset() << " " + << DUMP_HEX0x_FORMAT( 16 ) << seg->get_virtual_address() << " " + << DUMP_HEX0x_FORMAT( 16 ) << seg->get_physical_address() << std::endl - << " " - << DUMP_HEX_FORMAT( 16 ) << seg->get_file_size() << " " - << DUMP_HEX_FORMAT( 16 ) << seg->get_memory_size() << " " - << DUMP_HEX_FORMAT( 16 ) << seg->get_align() << " " + << DUMP_STR_FORMAT( 23 ) << " " + << DUMP_HEX0x_FORMAT( 16 ) << seg->get_file_size() << " " + << DUMP_HEX0x_FORMAT( 16 ) << seg->get_memory_size() << " " + << DUMP_STR_FORMAT( 3 ) << str_segment_flag( seg->get_flags() ) << " " + << DUMP_HEX0x_FORMAT( 1 ) << seg->get_align() << std::endl; } + // clang-format on - out.flags(original_flags); + out.flags( original_flags ); } - -//------------------------------------------------------------------------------ - static void - symbol_tables( std::ostream& out, const elfio& reader ) + + //------------------------------------------------------------------------------ + static void symbol_tables( std::ostream& out, const elfio& reader ) { - Elf_Half n = reader.sections.size(); - for ( Elf_Half i = 0; i < n; ++i ) { // For all sections - section* sec = reader.sections[i]; - if ( SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type() ) { - symbol_section_accessor symbols( reader, sec ); + for ( const auto& sec : reader.sections ) { // For all sections + if ( SHT_SYMTAB == sec->get_type() || + SHT_DYNSYM == sec->get_type() ) { + const_symbol_section_accessor symbols( reader, sec.get() ); - Elf_Xword sym_no = symbols.get_symbols_num(); - if ( sym_no > 0 ) { - out << "Symbol table (" << sec->get_name() << ")" << std::endl; - if ( reader.get_class() == ELFCLASS32 ) { // Output for 32-bit - out << "[ Nr ] Value Size Type Bind Sect Name" - << std::endl; - } - else { // Output for 64-bit - out << "[ Nr ] Value Size Type Bind Sect" << std::endl - << " Name" - << std::endl; - } - for ( Elf_Half i = 0; i < sym_no; ++i ) { - std::string name; - Elf64_Addr value = 0; - Elf_Xword size = 0; - unsigned char bind = 0; - unsigned char type = 0; - Elf_Half section = 0; - unsigned char other = 0; - symbols.get_symbol( i, name, value, size, bind, type, section, other ); - symbol_table( out, i, name, value, size, bind, type, section, reader.get_class() ); - } - - out << std::endl; + Elf_Xword sym_no = symbols.get_symbols_num(); + if ( sym_no == 0 ) { + continue; } - } - } - } - -//------------------------------------------------------------------------------ - static void - symbol_table( std::ostream& out, - Elf_Half no, - std::string& name, - Elf64_Addr value, - Elf_Xword size, - unsigned char bind, - unsigned char type, - Elf_Half section, - unsigned int elf_class ) - { - std::ios_base::fmtflags original_flags = out.flags(); - if ( elf_class == ELFCLASS32 ) { // Output for 32-bit - out << "[" - << DUMP_DEC_FORMAT( 5 ) << no - << "] " - << DUMP_HEX_FORMAT( 8 ) << value << " " - << DUMP_HEX_FORMAT( 8 ) << size << " " - << DUMP_STR_FORMAT( 7 ) << str_symbol_type( type ) << " " - << DUMP_STR_FORMAT( 8 ) << str_symbol_bind( bind ) << " " - << DUMP_DEC_FORMAT( 5 ) << section << " " - << DUMP_STR_FORMAT( 1 ) << name << " " - << std::endl; - } - else { // Output for 64-bit - out << "[" - << DUMP_DEC_FORMAT( 5 ) << no - << "] " - << DUMP_HEX_FORMAT( 16 ) << value << " " - << DUMP_HEX_FORMAT( 16 ) << size << " " - << DUMP_STR_FORMAT( 7 ) << str_symbol_type( type ) << " " - << DUMP_STR_FORMAT( 8 ) << str_symbol_bind( bind ) << " " - << DUMP_DEC_FORMAT( 5 ) << section << " " - << std::endl - << " " - << DUMP_STR_FORMAT( 1 ) << name << " " - << std::endl; - } - - out.flags(original_flags); - } - -//------------------------------------------------------------------------------ - static void - notes( std::ostream& out, const elfio& reader ) - { - Elf_Half no = reader.sections.size(); - for ( Elf_Half i = 0; i < no; ++i ) { // For all sections - section* sec = reader.sections[i]; - if ( SHT_NOTE == sec->get_type() ) { // Look at notes - note_section_accessor notes( reader, sec ); - int no_notes = notes.get_notes_num(); - if ( no > 0 ) { - out << "Note section (" << sec->get_name() << ")" << std::endl - << " No Type Name" + out << "Symbol table (" << sec->get_name() << ")" << std::endl; + if ( reader.get_class() == ELFCLASS32 ) { // Output for 32-bit + out << "[ Nr ] Value Size Type Bind " + " Sect Name" << std::endl; - for ( int j = 0; j < no_notes; ++j ) { // For all notes - Elf_Word type; - std::string name; - void* desc; - Elf_Word descsz; - - if ( notes.get_note(j, type, name, desc, descsz) ) { - // 'name' usually contains \0 at the end. Try to fix it - name = name.c_str(); - note( out, j, type, name ); - } - } - - out << std::endl; } + else { // Output for 64-bit + out << "[ Nr ] Value Size " + "Type Bind Sect" + << std::endl + << " Name" << std::endl; + } + for ( Elf_Xword i = 0; i < sym_no; ++i ) { + std::string name; + Elf64_Addr value = 0; + Elf_Xword size = 0; + unsigned char bind = 0; + unsigned char type = 0; + Elf_Half section = 0; + unsigned char other = 0; + symbols.get_symbol( i, name, value, size, bind, type, + section, other ); + symbol_table( out, i, name, value, size, bind, type, + section, reader.get_class() ); + } + + out << std::endl; } } } -//------------------------------------------------------------------------------ - static void - note( std::ostream& out, - int no, - Elf_Word type, - const std::string& name ) + //------------------------------------------------------------------------------ + static void symbol_table( std::ostream& out, + Elf_Xword no, + const std::string& name, + Elf64_Addr value, + Elf_Xword size, + unsigned char bind, + unsigned char type, + Elf_Half section, + unsigned int elf_class ) { - out << " [" - << DUMP_DEC_FORMAT( 2 ) << no - << "] " - << DUMP_HEX_FORMAT( 8 ) << type << " " - << DUMP_STR_FORMAT( 1 ) << name - << std::endl; + std::ios_base::fmtflags original_flags = out.flags(); + + if ( elf_class == ELFCLASS32 ) { // Output for 32-bit + out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] " + << DUMP_HEX0x_FORMAT( 8 ) << value << " " + << DUMP_HEX0x_FORMAT( 8 ) << size << " " << DUMP_STR_FORMAT( 7 ) + << str_symbol_type( type ) << " " << DUMP_STR_FORMAT( 8 ) + << str_symbol_bind( bind ) << " " << DUMP_DEC_FORMAT( 5 ) + << section << " " << DUMP_STR_FORMAT( 1 ) << name << " " + << std::endl; + } + else { // Output for 64-bit + out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] " + << DUMP_HEX0x_FORMAT( 16 ) << value << " " + << DUMP_HEX0x_FORMAT( 16 ) << size << " " + << DUMP_STR_FORMAT( 7 ) << str_symbol_type( type ) << " " + << DUMP_STR_FORMAT( 8 ) << str_symbol_bind( bind ) << " " + << DUMP_DEC_FORMAT( 5 ) << section << " " << std::endl + << " " << DUMP_STR_FORMAT( 1 ) << name << " " + << std::endl; + } + + out.flags( original_flags ); } - -//------------------------------------------------------------------------------ - static void - dynamic_tags( std::ostream& out, const elfio& reader ) + + //------------------------------------------------------------------------------ + static void notes( std::ostream& out, const elfio& reader ) { - Elf_Half n = reader.sections.size(); - for ( Elf_Half i = 0; i < n; ++i ) { // For all sections - section* sec = reader.sections[i]; + for ( const auto& sec : reader.sections ) { // For all sections + if ( SHT_NOTE == sec->get_type() ) { // Look at notes + note_section_accessor notes( reader, sec.get() ); + Elf_Word no_notes = notes.get_notes_num(); + + if ( no_notes == 0 ) + continue; + + out << "Note section (" << sec->get_name() << ")" << std::endl + << " No Name Data size Description" + << std::endl; + for ( Elf_Word j = 0; j < no_notes; ++j ) { // For all notes + Elf_Word type; + std::string name; + char* desc; + Elf_Word descsz; + + if ( notes.get_note( j, type, name, desc, descsz ) ) { + // 'name' usually contains \0 at the end. Remove it + name = name.c_str(); + note( out, j, type, name, desc, descsz ); + out << std::endl; + } + } + + out << std::endl; + } + } + + Elf_Half no = reader.segments.size(); + for ( Elf_Half i = 0; i < no; ++i ) { // For all segments + segment* seg = reader.segments[i]; + if ( PT_NOTE == seg->get_type() ) { // Look at notes + note_segment_accessor notes( reader, seg ); + Elf_Word no_notes = notes.get_notes_num(); + + if ( no_notes == 0 ) + continue; + + out << "Note segment (" << i << ")" << std::endl + << " No Name Data size Description" + << std::endl; + for ( Elf_Word j = 0; j < no_notes; ++j ) { // For all notes + Elf_Word type; + std::string name; + char* desc; + Elf_Word descsz; + + if ( notes.get_note( j, type, name, desc, descsz ) ) { + // 'name' usually contains \0 at the end. Remove it + name = name.c_str(); + note( out, j, type, name, desc, descsz ); + out << std::endl; + } + } + + out << std::endl; + } + } + } + + //------------------------------------------------------------------------------ + static void note( std::ostream& out, + int no, + Elf_Word type, + const std::string& name, + void* desc, + Elf_Word descsz ) + { + out << " [" << DUMP_DEC_FORMAT( 2 ) << no << "] "; + + const auto name_group = std::find_if( + std::begin( note_tag_table ), std::end( note_tag_table ), + [&name]( const note_tag_t& entry ) { return entry.name == name; } ); + + std::vector::const_iterator type_value; + if ( name_group != std::end( note_tag_table ) ) { + type_value = std::find_if( + name_group->values.begin(), name_group->values.end(), + [&type]( const note_tag_t::note_values_t& e ) { + return e.type == type; + } ); + } + + if ( name_group != std::end( note_tag_table ) && + type_value != name_group->values.end() ) { + out << DUMP_STR_FORMAT( 12 ) << name_group->name << " " + << DUMP_HEX0x_FORMAT( 8 ) << descsz << " " + << type_value->type_str << " (" << type_value->description + << ")"; + } + else { + out << DUMP_STR_FORMAT( 12 ) << name << " " + << DUMP_HEX0x_FORMAT( 8 ) << descsz << " " + << DUMP_HEX0x_FORMAT( 8 ) << type; + } + + if ( descsz != 0 ) { + for ( Elf_Word i = 0; i < descsz; ++i ) { + if ( i % 16 == 0 ) { + out << std::endl << " "; + } + out << DUMP_HEX_FORMAT( 2 ) + << (uint32_t)( (uint8_t*)( desc ) )[i]; + } + } + } + + //------------------------------------------------------------------------------ + static void modinfo( std::ostream& out, const elfio& reader ) + { + for ( const auto& sec : reader.sections ) { // For all sections + if ( ".modinfo" == sec->get_name() ) { // Look for the section + out << "Section .modinfo" << std::endl; + + const_modinfo_section_accessor modinfo( sec.get() ); + for ( Elf_Word i = 0; i < modinfo.get_attribute_num(); i++ ) { + std::string field; + std::string value; + if ( modinfo.get_attribute( i, field, value ) ) { + out << " " << std::setw( 20 ) << field + << std::setw( 0 ) << " = " << value << std::endl; + } + } + + out << std::endl; + break; + } + } + } + + //------------------------------------------------------------------------------ + static void dynamic_tags( std::ostream& out, const elfio& reader ) + { + for ( const auto& sec : reader.sections ) { // For all sections if ( SHT_DYNAMIC == sec->get_type() ) { - dynamic_section_accessor dynamic( reader, sec ); + dynamic_section_accessor dynamic( reader, sec.get() ); Elf_Xword dyn_no = dynamic.get_entries_num(); - if ( dyn_no > 0 ) { - out << "Dynamic section (" << sec->get_name() << ")" << std::endl; - out << "[ Nr ] Tag Name/Value" << std::endl; - for ( Elf_Xword i = 0; i < dyn_no; ++i ) { - Elf_Xword tag = 0; - Elf_Xword value = 0; - std::string str; - dynamic.get_entry( i, tag, value, str ); - dynamic_tag( out, i, tag, value, str, reader.get_class() ); - if ( DT_NULL == tag ) { - break; - } - } + if ( dyn_no == 0 ) + continue; - out << std::endl; + out << "Dynamic section (" << sec->get_name() << ")" + << std::endl; + out << "[ Nr ] Tag Name/Value" << std::endl; + for ( Elf_Xword i = 0; i < dyn_no; ++i ) { + Elf_Xword tag = 0; + Elf_Xword value = 0; + std::string str; + dynamic.get_entry( i, tag, value, str ); + dynamic_tag( out, i, tag, value, str, reader.get_class() ); + if ( DT_NULL == tag ) { + break; + } } + + out << std::endl; } } } - -//------------------------------------------------------------------------------ - static void - dynamic_tag( std::ostream& out, - Elf_Xword no, - Elf_Xword tag, - Elf_Xword value, - std::string str, - unsigned int /*elf_class*/ ) + + //------------------------------------------------------------------------------ + static void dynamic_tag( std::ostream& out, + Elf_Xword no, + Elf_Xword tag, + Elf_Xword value, + const std::string& str, + unsigned int /*elf_class*/ ) { - out << "[" - << DUMP_DEC_FORMAT( 5 ) << no - << "] " - << DUMP_STR_FORMAT( 16 ) << str_dynamic_tag( tag ) << " "; - if ( str.empty() ) { - out << DUMP_HEX_FORMAT( 16 ) << value << " "; - } - else { - out << DUMP_STR_FORMAT( 32 ) << str << " "; - } - out << std::endl; + out << "[" << DUMP_DEC_FORMAT( 5 ) << no << "] " + << DUMP_STR_FORMAT( 16 ) << str_dynamic_tag( tag ) << " "; + if ( str.empty() ) { + out << DUMP_HEX0x_FORMAT( 16 ) << value << " "; + } + else { + out << DUMP_STR_FORMAT( 32 ) << str << " "; + } + out << std::endl; } -//------------------------------------------------------------------------------ - static void - section_data( std::ostream& out, const section* sec ) + //------------------------------------------------------------------------------ + static void section_data( std::ostream& out, const section* sec ) { std::ios_base::fmtflags original_flags = out.flags(); out << sec->get_name() << std::endl; const char* pdata = sec->get_data(); - if ( pdata ){ + if ( pdata ) { ELFIO::Elf_Xword i; - for ( i = 0; i < std::min( sec->get_size(), MAX_DATA_ENTRIES ); ++i ) { + for ( i = 0; i < std::min( sec->get_size(), MAX_DATA_ENTRIES ); + ++i ) { if ( i % 16 == 0 ) { - out << "[" << DUMP_HEX_FORMAT( 8 ) << i << "]"; + out << "[" << DUMP_HEX0x_FORMAT( 8 ) << i << "]"; } - out << " " << DUMP_HEX_FORMAT( 2 ) << ( pdata[i] & 0x000000FF ); + out << " " << DUMP_HEX0x_FORMAT( 2 ) + << ( pdata[i] & 0x000000FF ); if ( i % 16 == 15 ) { out << std::endl; @@ -797,15 +1150,14 @@ class dump out << std::endl; } - out.flags(original_flags); + out.flags( original_flags ); } - return; + return; } -//------------------------------------------------------------------------------ - static void - section_datas( std::ostream& out, const elfio& reader ) + //------------------------------------------------------------------------------ + static void section_datas( std::ostream& out, const elfio& reader ) { Elf_Half n = reader.sections.size(); @@ -816,7 +1168,7 @@ class dump out << "Section Data:" << std::endl; for ( Elf_Half i = 1; i < n; ++i ) { // For all sections - section* sec = reader.sections[i]; + const section* sec = reader.sections[i]; if ( sec->get_type() == SHT_NOBITS ) { continue; } @@ -826,7 +1178,7 @@ class dump out << std::endl; } -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ static void segment_data( std::ostream& out, Elf_Half no, const segment* seg ) { @@ -836,12 +1188,14 @@ class dump const char* pdata = seg->get_data(); if ( pdata ) { ELFIO::Elf_Xword i; - for ( i = 0; i < std::min( seg->get_file_size(), MAX_DATA_ENTRIES ); ++i ) { + for ( i = 0; i < std::min( seg->get_file_size(), MAX_DATA_ENTRIES ); + ++i ) { if ( i % 16 == 0 ) { - out << "[" << DUMP_HEX_FORMAT( 8 ) << i << "]"; + out << "[" << DUMP_HEX0x_FORMAT( 8 ) << i << "]"; } - out << " " << DUMP_HEX_FORMAT( 2 ) << ( pdata[i] & 0x000000FF ); + out << " " << DUMP_HEX0x_FORMAT( 2 ) + << ( pdata[i] & 0x000000FF ); if ( i % 16 == 15 ) { out << std::endl; @@ -851,15 +1205,14 @@ class dump out << std::endl; } - out.flags(original_flags); + out.flags( original_flags ); } - return; + return; } -//------------------------------------------------------------------------------ - static void - segment_datas( std::ostream& out, const elfio& reader ) + //------------------------------------------------------------------------------ + static void segment_datas( std::ostream& out, const elfio& reader ) { Elf_Half n = reader.segments.size(); @@ -870,22 +1223,43 @@ class dump out << "Segment Data:" << std::endl; for ( Elf_Half i = 0; i < n; ++i ) { // For all sections - segment* seg = reader.segments[i]; + const segment* seg = reader.segments[i]; segment_data( out, i, seg ); } out << std::endl; } - - private: + //------------------------------------------------------------------------------ - template< typename T, typename K > - std::string - static - find_value_in_table( const T& table, const K& key ) +#define STR_FUNC_TABLE( name ) \ + template static std::string str_##name( const T key ) \ + { \ + return format_assoc( name##_table, key ); \ + } + + STR_FUNC_TABLE( class ) + STR_FUNC_TABLE( endian ) + STR_FUNC_TABLE( version ) + STR_FUNC_TABLE( os_abi ) + STR_FUNC_TABLE( type ) + STR_FUNC_TABLE( machine ) + STR_FUNC_TABLE( section_type ) + STR_FUNC_TABLE( segment_type ) + STR_FUNC_TABLE( segment_flag ) + STR_FUNC_TABLE( symbol_bind ) + STR_FUNC_TABLE( symbol_type ) + STR_FUNC_TABLE( dynamic_tag ) + +#undef STR_FUNC_TABLE + + private: + //------------------------------------------------------------------------------ + template + std::string static find_value_in_table( const T& table, const K& key ) { std::string res = "?"; - for ( unsigned int i = 0; i < sizeof( table )/sizeof( table[0] ); ++i ) { + for ( unsigned int i = 0; i < sizeof( table ) / sizeof( table[0] ); + ++i ) { if ( table[i].key == key ) { res = table[i].str; break; @@ -895,12 +1269,9 @@ class dump return res; } - -//------------------------------------------------------------------------------ - template< typename T, typename K > - static - std::string - format_assoc( const T& table, const K& key ) + //------------------------------------------------------------------------------ + template + static std::string format_assoc( const T& table, const K& key ) { std::string str = find_value_in_table( table, key ); if ( str == "?" ) { @@ -912,21 +1283,15 @@ class dump return str; } - -//------------------------------------------------------------------------------ - template< typename T > - static - std::string - format_assoc( const T& table, const char key ) + //------------------------------------------------------------------------------ + template + static std::string format_assoc( const T& table, const char key ) { return format_assoc( table, (const int)key ); } - -//------------------------------------------------------------------------------ - static - std::string - section_flags( Elf_Xword flags ) + //------------------------------------------------------------------------------ + static std::string section_flags( Elf_Xword flags ) { std::string ret = ""; if ( flags & SHF_WRITE ) { @@ -938,40 +1303,44 @@ class dump if ( flags & SHF_EXECINSTR ) { ret += "X"; } + if ( flags & SHF_MERGE ) { + ret += "M"; + } + if ( flags & SHF_STRINGS ) { + ret += "S"; + } + if ( flags & SHF_INFO_LINK ) { + ret += "I"; + } + if ( flags & SHF_LINK_ORDER ) { + ret += "L"; + } + if ( flags & SHF_OS_NONCONFORMING ) { + ret += "O"; + } + if ( flags & SHF_GROUP ) { + ret += "G"; + } + if ( flags & SHF_TLS ) { + ret += "T"; + } + if ( flags & SHF_COMPRESSED ) { + ret += "C"; + } + if ( flags & SHF_EXCLUDE ) { + ret += "E"; + } + if ( flags & SHF_GNU_MBIND ) { + ret += "D"; + } return ret; } - -//------------------------------------------------------------------------------ -#define STR_FUNC_TABLE( name ) \ - template< typename T > \ - static \ - std::string \ - str_##name( const T key ) \ - { \ - return format_assoc( name##_table, key ); \ - } - - STR_FUNC_TABLE( class ) - STR_FUNC_TABLE( endian ) - STR_FUNC_TABLE( version ) - STR_FUNC_TABLE( type ) - STR_FUNC_TABLE( machine ) - STR_FUNC_TABLE( section_type ) - STR_FUNC_TABLE( segment_type ) - STR_FUNC_TABLE( segment_flag ) - STR_FUNC_TABLE( symbol_bind ) - STR_FUNC_TABLE( symbol_type ) - STR_FUNC_TABLE( dynamic_tag ) - -#undef STR_FUNC_TABLE #undef DUMP_DEC_FORMAT -#undef DUMP_HEX_FORMAT +#undef DUMP_HEX0x_FORMAT #undef DUMP_STR_FORMAT }; // class dump - - -}; // namespace ELFIO +} // namespace ELFIO #endif // ELFIO_DUMP_HPP diff --git a/source/elfio/elfio_dynamic.hpp b/source/elfio/elfio_dynamic.hpp index 36de384..035e67d 100644 --- a/source/elfio/elfio_dynamic.hpp +++ b/source/elfio/elfio_dynamic.hpp @@ -1,6 +1,5 @@ -// clang-format off /* -Copyright (C) 2001-2015 by Serge Lamikhov-Center +Copyright (C) 2001-present by Serge Lamikhov-Center Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -24,60 +23,76 @@ THE SOFTWARE. #ifndef ELFIO_DYNAMIC_HPP #define ELFIO_DYNAMIC_HPP +#include + namespace ELFIO { //------------------------------------------------------------------------------ -template< class S > -class dynamic_section_accessor_template +template class dynamic_section_accessor_template { public: -//------------------------------------------------------------------------------ - dynamic_section_accessor_template( const elfio& elf_file_, S* section_ ) : - elf_file( elf_file_ ), - dynamic_section( section_ ) + //------------------------------------------------------------------------------ + explicit dynamic_section_accessor_template( const elfio& elf_file, + S* section ) + : elf_file( elf_file ), dynamic_section( section ), entries_num( 0 ) { } -//------------------------------------------------------------------------------ - Elf_Xword - get_entries_num() const + //------------------------------------------------------------------------------ + Elf_Xword get_entries_num() const { - Elf_Xword nRet = 0; - - if ( 0 != dynamic_section->get_entry_size() ) { - nRet = dynamic_section->get_size() / dynamic_section->get_entry_size(); + size_t needed_entry_size = -1; + if ( elf_file.get_class() == ELFCLASS32 ) { + needed_entry_size = sizeof( Elf32_Dyn ); + } + else { + needed_entry_size = sizeof( Elf64_Dyn ); } - return nRet; + if ( ( 0 == entries_num ) && + ( 0 != dynamic_section->get_entry_size() && + dynamic_section->get_entry_size() >= needed_entry_size ) ) { + entries_num = + dynamic_section->get_size() / dynamic_section->get_entry_size(); + Elf_Xword i; + Elf_Xword tag = DT_NULL; + Elf_Xword value = 0; + std::string str; + for ( i = 0; i < entries_num; i++ ) { + get_entry( i, tag, value, str ); + if ( tag == DT_NULL ) + break; + } + entries_num = std::min( entries_num, i + 1 ); + } + + return entries_num; } -//------------------------------------------------------------------------------ - bool - get_entry( Elf_Xword index, - Elf_Xword& tag, - Elf_Xword& value, - std::string& str ) const + //------------------------------------------------------------------------------ + bool get_entry( Elf_Xword index, + Elf_Xword& tag, + Elf_Xword& value, + std::string& str ) const { - if ( index >= get_entries_num() ) { // Is index valid + if ( index >= get_entries_num() ) { // Is index valid return false; } if ( elf_file.get_class() == ELFCLASS32 ) { - generic_get_entry_dyn< Elf32_Dyn >( index, tag, value ); + generic_get_entry_dyn( index, tag, value ); } else { - generic_get_entry_dyn< Elf64_Dyn >( index, tag, value ); + generic_get_entry_dyn( index, tag, value ); } - // If the tag may have a string table reference, prepare the string - if ( tag == DT_NEEDED || - tag == DT_SONAME || - tag == DT_RPATH || + // If the tag has a string table reference - prepare the string + if ( tag == DT_NEEDED || tag == DT_SONAME || tag == DT_RPATH || tag == DT_RUNPATH ) { - string_section_accessor strsec = - elf_file.sections[ get_string_table_index() ]; - const char* result = strsec.get_string( value ); - if ( 0 == result ) { + string_section_accessor strsec( + elf_file.sections[get_string_table_index()] ); + const char* result = strsec.get_string( (Elf_Word)value ); + if ( nullptr == result ) { str.clear(); return false; } @@ -90,59 +105,55 @@ class dynamic_section_accessor_template return true; } -//------------------------------------------------------------------------------ - void - add_entry( Elf_Xword tag, - Elf_Xword value ) + //------------------------------------------------------------------------------ + void add_entry( Elf_Xword tag, Elf_Xword value ) { if ( elf_file.get_class() == ELFCLASS32 ) { - generic_add_entry< Elf32_Dyn >( tag, value ); + generic_add_entry_dyn( tag, value ); } else { - generic_add_entry< Elf64_Dyn >( tag, value ); + generic_add_entry_dyn( tag, value ); } } -//------------------------------------------------------------------------------ - void - add_entry( Elf_Xword tag, - const std::string& str ) + //------------------------------------------------------------------------------ + void add_entry( Elf_Xword tag, const std::string& str ) { - string_section_accessor strsec = - elf_file.sections[ get_string_table_index() ]; + string_section_accessor strsec( + elf_file.sections[get_string_table_index()] ); Elf_Xword value = strsec.add_string( str ); add_entry( tag, value ); } -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ private: -//------------------------------------------------------------------------------ - Elf_Half - get_string_table_index() const + //------------------------------------------------------------------------------ + Elf_Half get_string_table_index() const { return (Elf_Half)dynamic_section->get_link(); } -//------------------------------------------------------------------------------ - template< class T > - void - generic_get_entry_dyn( Elf_Xword index, - Elf_Xword& tag, - Elf_Xword& value ) const + //------------------------------------------------------------------------------ + template + void generic_get_entry_dyn( Elf_Xword index, + Elf_Xword& tag, + Elf_Xword& value ) const { const endianess_convertor& convertor = elf_file.get_convertor(); // Check unusual case when dynamic section has no data - if( dynamic_section->get_data() == 0 || - ( index + 1 ) * dynamic_section->get_entry_size() > dynamic_section->get_size() ) { + if ( dynamic_section->get_data() == nullptr || + ( index + 1 ) * dynamic_section->get_entry_size() > + dynamic_section->get_size() || + dynamic_section->get_entry_size() < sizeof( T ) ) { tag = DT_NULL; value = 0; return; } const T* pEntry = reinterpret_cast( - dynamic_section->get_data() + - index * dynamic_section->get_entry_size() ); + dynamic_section->get_data() + + index * dynamic_section->get_entry_size() ); tag = convertor( pEntry->d_tag ); switch ( tag ) { case DT_NULL: @@ -188,10 +199,9 @@ class dynamic_section_accessor_template } } -//------------------------------------------------------------------------------ - template< class T > - void - generic_add_entry( Elf_Xword tag, Elf_Xword value ) + //------------------------------------------------------------------------------ + template + void generic_add_entry_dyn( Elf_Xword tag, Elf_Xword value ) { const endianess_convertor& convertor = elf_file.get_convertor(); @@ -202,7 +212,8 @@ class dynamic_section_accessor_template case DT_SYMBOLIC: case DT_TEXTREL: case DT_BIND_NOW: - value = 0; + entry.d_un.d_val = convertor( decltype( entry.d_un.d_val )( 0 ) ); + break; case DT_NEEDED: case DT_PLTRELSZ: case DT_RELASZ: @@ -219,7 +230,8 @@ class dynamic_section_accessor_template case DT_RUNPATH: case DT_FLAGS: case DT_PREINIT_ARRAYSZ: - entry.d_un.d_val = convertor( value ); + entry.d_un.d_val = + convertor( decltype( entry.d_un.d_val )( value ) ); break; case DT_PLTGOT: case DT_HASH: @@ -235,23 +247,27 @@ class dynamic_section_accessor_template case DT_FINI_ARRAY: case DT_PREINIT_ARRAY: default: - entry.d_un.d_ptr = convertor( value ); + entry.d_un.d_ptr = + convertor( decltype( entry.d_un.d_val )( value ) ); break; } - entry.d_tag = convertor( tag ); + entry.d_tag = convertor( decltype( entry.d_tag )( tag ) ); - dynamic_section->append_data( reinterpret_cast( &entry ), sizeof( entry ) ); + dynamic_section->append_data( reinterpret_cast( &entry ), + sizeof( entry ) ); } -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ private: - const elfio& elf_file; - S* dynamic_section; + const elfio& elf_file; + S* dynamic_section; + mutable Elf_Xword entries_num; }; using dynamic_section_accessor = dynamic_section_accessor_template
; -using const_dynamic_section_accessor = dynamic_section_accessor_template; +using const_dynamic_section_accessor = + dynamic_section_accessor_template; } // namespace ELFIO diff --git a/source/elfio/elfio_header.hpp b/source/elfio/elfio_header.hpp index e7b9a24..eccae13 100644 --- a/source/elfio/elfio_header.hpp +++ b/source/elfio/elfio_header.hpp @@ -1,6 +1,5 @@ -// clang-format off /* -Copyright (C) 2001-2015 by Serge Lamikhov-Center +Copyright (C) 2001-present by Serge Lamikhov-Center Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -31,55 +30,56 @@ namespace ELFIO { class elf_header { public: - virtual ~elf_header() {}; + virtual ~elf_header() = default; + virtual bool load( std::istream& stream ) = 0; virtual bool save( std::ostream& stream ) const = 0; // ELF header functions - ELFIO_GET_ACCESS_DECL( unsigned char, class ); - ELFIO_GET_ACCESS_DECL( unsigned char, elf_version ); - ELFIO_GET_ACCESS_DECL( unsigned char, encoding ); - ELFIO_GET_ACCESS_DECL( Elf_Half, header_size ); - ELFIO_GET_ACCESS_DECL( Elf_Half, section_entry_size ); - ELFIO_GET_ACCESS_DECL( Elf_Half, segment_entry_size ); + ELFIO_GET_ACCESS_DECL( unsigned char, class ); + ELFIO_GET_ACCESS_DECL( unsigned char, elf_version ); + ELFIO_GET_ACCESS_DECL( unsigned char, encoding ); + ELFIO_GET_ACCESS_DECL( Elf_Half, header_size ); + ELFIO_GET_ACCESS_DECL( Elf_Half, section_entry_size ); + ELFIO_GET_ACCESS_DECL( Elf_Half, segment_entry_size ); - ELFIO_GET_SET_ACCESS_DECL( Elf_Word, version ); - ELFIO_GET_SET_ACCESS_DECL( unsigned char, os_abi ); - ELFIO_GET_SET_ACCESS_DECL( unsigned char, abi_version ); - ELFIO_GET_SET_ACCESS_DECL( Elf_Half, type ); - ELFIO_GET_SET_ACCESS_DECL( Elf_Half, machine ); - ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags ); - ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, entry ); - ELFIO_GET_SET_ACCESS_DECL( Elf_Half, sections_num ); - ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, sections_offset ); - ELFIO_GET_SET_ACCESS_DECL( Elf_Half, segments_num ); - ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, segments_offset ); - ELFIO_GET_SET_ACCESS_DECL( Elf_Half, section_name_str_index ); + ELFIO_GET_SET_ACCESS_DECL( Elf_Word, version ); + ELFIO_GET_SET_ACCESS_DECL( unsigned char, os_abi ); + ELFIO_GET_SET_ACCESS_DECL( unsigned char, abi_version ); + ELFIO_GET_SET_ACCESS_DECL( Elf_Half, type ); + ELFIO_GET_SET_ACCESS_DECL( Elf_Half, machine ); + ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags ); + ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, entry ); + ELFIO_GET_SET_ACCESS_DECL( Elf_Half, sections_num ); + ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, sections_offset ); + ELFIO_GET_SET_ACCESS_DECL( Elf_Half, segments_num ); + ELFIO_GET_SET_ACCESS_DECL( Elf64_Off, segments_offset ); + ELFIO_GET_SET_ACCESS_DECL( Elf_Half, section_name_str_index ); }; - -template< class T > struct elf_header_impl_types; -template<> struct elf_header_impl_types { - typedef Elf32_Phdr Phdr_type; - typedef Elf32_Shdr Shdr_type; +template struct elf_header_impl_types; +template <> struct elf_header_impl_types +{ + using Phdr_type = Elf32_Phdr; + using Shdr_type = Elf32_Shdr; static const unsigned char file_class = ELFCLASS32; }; -template<> struct elf_header_impl_types { - typedef Elf64_Phdr Phdr_type; - typedef Elf64_Shdr Shdr_type; +template <> struct elf_header_impl_types +{ + using Phdr_type = Elf64_Phdr; + using Shdr_type = Elf64_Shdr; static const unsigned char file_class = ELFCLASS64; }; -template< class T > class elf_header_impl : public elf_header +template class elf_header_impl : public elf_header { public: - elf_header_impl( endianess_convertor* convertor_, - unsigned char encoding ) + //------------------------------------------------------------------------------ + elf_header_impl( endianess_convertor* convertor, + unsigned char encoding, + const address_translator* translator ) + : convertor( convertor ), translator( translator ) { - convertor = convertor_; - - std::fill_n( reinterpret_cast( &header ), sizeof( header ), '\0' ); - header.e_ident[EI_MAG0] = ELFMAG0; header.e_ident[EI_MAG1] = ELFMAG1; header.e_ident[EI_MAG2] = ELFMAG2; @@ -87,58 +87,65 @@ template< class T > class elf_header_impl : public elf_header header.e_ident[EI_CLASS] = elf_header_impl_types::file_class; header.e_ident[EI_DATA] = encoding; header.e_ident[EI_VERSION] = EV_CURRENT; - header.e_version = (*convertor)( (Elf_Word)EV_CURRENT ); + header.e_version = ( *convertor )( (Elf_Word)EV_CURRENT ); header.e_ehsize = ( sizeof( header ) ); - header.e_ehsize = (*convertor)( header.e_ehsize ); - header.e_shstrndx = (*convertor)( (Elf_Half)1 ); - header.e_phentsize = sizeof( typename elf_header_impl_types::Phdr_type ); - header.e_shentsize = sizeof( typename elf_header_impl_types::Shdr_type ); - header.e_phentsize = (*convertor)( header.e_phentsize ); - header.e_shentsize = (*convertor)( header.e_shentsize ); + header.e_ehsize = ( *convertor )( header.e_ehsize ); + header.e_shstrndx = ( *convertor )( (Elf_Half)1 ); + header.e_phentsize = + sizeof( typename elf_header_impl_types::Phdr_type ); + header.e_shentsize = + sizeof( typename elf_header_impl_types::Shdr_type ); + header.e_phentsize = ( *convertor )( header.e_phentsize ); + header.e_shentsize = ( *convertor )( header.e_shentsize ); } - bool - load( std::istream& stream ) + //------------------------------------------------------------------------------ + bool load( std::istream& stream ) override { - stream.seekg( 0 ); + stream.seekg( ( *translator )[0] ); stream.read( reinterpret_cast( &header ), sizeof( header ) ); - return (stream.gcount() == sizeof( header ) ); + return ( stream.gcount() == sizeof( header ) ); } - bool - save( std::ostream& stream ) const + //------------------------------------------------------------------------------ + bool save( std::ostream& stream ) const override { - stream.seekp( 0 ); - stream.write( reinterpret_cast( &header ), sizeof( header ) ); + stream.seekp( ( *translator )[0] ); + stream.write( reinterpret_cast( &header ), + sizeof( header ) ); return stream.good(); } + //------------------------------------------------------------------------------ // ELF header functions - ELFIO_GET_ACCESS( unsigned char, class, header.e_ident[EI_CLASS] ); - ELFIO_GET_ACCESS( unsigned char, elf_version, header.e_ident[EI_VERSION] ); - ELFIO_GET_ACCESS( unsigned char, encoding, header.e_ident[EI_DATA] ); - ELFIO_GET_ACCESS( Elf_Half, header_size, header.e_ehsize ); - ELFIO_GET_ACCESS( Elf_Half, section_entry_size, header.e_shentsize ); - ELFIO_GET_ACCESS( Elf_Half, segment_entry_size, header.e_phentsize ); + ELFIO_GET_ACCESS( unsigned char, class, header.e_ident[EI_CLASS] ); + ELFIO_GET_ACCESS( unsigned char, elf_version, header.e_ident[EI_VERSION] ); + ELFIO_GET_ACCESS( unsigned char, encoding, header.e_ident[EI_DATA] ); + ELFIO_GET_ACCESS( Elf_Half, header_size, header.e_ehsize ); + ELFIO_GET_ACCESS( Elf_Half, section_entry_size, header.e_shentsize ); + ELFIO_GET_ACCESS( Elf_Half, segment_entry_size, header.e_phentsize ); - ELFIO_GET_SET_ACCESS( Elf_Word, version, header.e_version); - ELFIO_GET_SET_ACCESS( unsigned char, os_abi, header.e_ident[EI_OSABI] ); - ELFIO_GET_SET_ACCESS( unsigned char, abi_version, header.e_ident[EI_ABIVERSION] ); - ELFIO_GET_SET_ACCESS( Elf_Half, type, header.e_type ); - ELFIO_GET_SET_ACCESS( Elf_Half, machine, header.e_machine ); - ELFIO_GET_SET_ACCESS( Elf_Word, flags, header.e_flags ); - ELFIO_GET_SET_ACCESS( Elf_Half, section_name_str_index, header.e_shstrndx ); - ELFIO_GET_SET_ACCESS( Elf64_Addr, entry, header.e_entry ); - ELFIO_GET_SET_ACCESS( Elf_Half, sections_num, header.e_shnum ); - ELFIO_GET_SET_ACCESS( Elf64_Off, sections_offset, header.e_shoff ); - ELFIO_GET_SET_ACCESS( Elf_Half, segments_num, header.e_phnum ); - ELFIO_GET_SET_ACCESS( Elf64_Off, segments_offset, header.e_phoff ); + ELFIO_GET_SET_ACCESS( Elf_Word, version, header.e_version ); + ELFIO_GET_SET_ACCESS( unsigned char, os_abi, header.e_ident[EI_OSABI] ); + ELFIO_GET_SET_ACCESS( unsigned char, + abi_version, + header.e_ident[EI_ABIVERSION] ); + ELFIO_GET_SET_ACCESS( Elf_Half, type, header.e_type ); + ELFIO_GET_SET_ACCESS( Elf_Half, machine, header.e_machine ); + ELFIO_GET_SET_ACCESS( Elf_Word, flags, header.e_flags ); + ELFIO_GET_SET_ACCESS( Elf_Half, section_name_str_index, header.e_shstrndx ); + ELFIO_GET_SET_ACCESS( Elf64_Addr, entry, header.e_entry ); + ELFIO_GET_SET_ACCESS( Elf_Half, sections_num, header.e_shnum ); + ELFIO_GET_SET_ACCESS( Elf64_Off, sections_offset, header.e_shoff ); + ELFIO_GET_SET_ACCESS( Elf_Half, segments_num, header.e_phnum ); + ELFIO_GET_SET_ACCESS( Elf64_Off, segments_offset, header.e_phoff ); private: - T header; - endianess_convertor* convertor; + T header = {}; + endianess_convertor* convertor = nullptr; + const address_translator* translator = nullptr; }; } // namespace ELFIO diff --git a/source/elfio/elfio_modinfo.hpp b/source/elfio/elfio_modinfo.hpp new file mode 100644 index 0000000..84deda6 --- /dev/null +++ b/source/elfio/elfio_modinfo.hpp @@ -0,0 +1,124 @@ +/* +Copyright (C) 2001-present by Serge Lamikhov-Center + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#ifndef ELFIO_MODINFO_HPP +#define ELFIO_MODINFO_HPP + +#include +#include + +namespace ELFIO { + +//------------------------------------------------------------------------------ +template class modinfo_section_accessor_template +{ + public: + //------------------------------------------------------------------------------ + explicit modinfo_section_accessor_template( S* section ) + : modinfo_section( section ) + { + process_section(); + } + + //------------------------------------------------------------------------------ + Elf_Word get_attribute_num() const { return (Elf_Word)content.size(); } + + //------------------------------------------------------------------------------ + bool + get_attribute( Elf_Word no, std::string& field, std::string& value ) const + { + if ( no < content.size() ) { + field = content[no].first; + value = content[no].second; + return true; + } + + return false; + } + + //------------------------------------------------------------------------------ + bool get_attribute( const std::string& field_name, + std::string& value ) const + { + for ( auto& i : content ) { + if ( field_name == i.first ) { + value = i.second; + return true; + } + } + + return false; + } + + //------------------------------------------------------------------------------ + Elf_Word add_attribute( const std::string& field, const std::string& value ) + { + Elf_Word current_position = 0; + + if ( modinfo_section ) { + // Strings are addeded to the end of the current section data + current_position = (Elf_Word)modinfo_section->get_size(); + + std::string attribute = field + "=" + value; + + modinfo_section->append_data( attribute + '\0' ); + content.emplace_back( field, value ); + } + + return current_position; + } + + //------------------------------------------------------------------------------ + private: + void process_section() + { + const char* pdata = modinfo_section->get_data(); + if ( pdata ) { + ELFIO::Elf_Xword i = 0; + while ( i < modinfo_section->get_size() ) { + while ( i < modinfo_section->get_size() && !pdata[i] ) + i++; + if ( i < modinfo_section->get_size() ) { + std::string info = pdata + i; + size_t loc = info.find( '=' ); + content.emplace_back( info.substr( 0, loc ), + info.substr( loc + 1 ) ); + + i += info.length(); + } + } + } + } + + //------------------------------------------------------------------------------ + private: + S* modinfo_section; + std::vector> content; +}; + +using modinfo_section_accessor = modinfo_section_accessor_template
; +using const_modinfo_section_accessor = + modinfo_section_accessor_template; + +} // namespace ELFIO + +#endif // ELFIO_MODINFO_HPP diff --git a/source/elfio/elfio_note.hpp b/source/elfio/elfio_note.hpp index fbfc51c..63ef102 100644 --- a/source/elfio/elfio_note.hpp +++ b/source/elfio/elfio_note.hpp @@ -1,6 +1,5 @@ -// clang-format off /* -Copyright (C) 2001-2015 by Serge Lamikhov-Center +Copyright (C) 2001-present by Serge Lamikhov-Center Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -39,73 +38,75 @@ namespace ELFIO { //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ -template< class S > +template class note_section_accessor_template { public: -//------------------------------------------------------------------------------ - note_section_accessor_template( const elfio& elf_file_, S* section_ ) : - elf_file( elf_file_ ), note_section( section_ ) + //------------------------------------------------------------------------------ + explicit note_section_accessor_template( const elfio& elf_file, S* section ) + : elf_file( elf_file ), notes( section ) { process_section(); } -//------------------------------------------------------------------------------ - Elf_Word - get_notes_num() const + //------------------------------------------------------------------------------ + Elf_Word get_notes_num() const { return (Elf_Word)note_start_positions.size(); } -//------------------------------------------------------------------------------ - bool - get_note( Elf_Word index, - Elf_Word& type, - std::string& name, - void*& desc, - Elf_Word& descSize ) const + //------------------------------------------------------------------------------ + bool get_note( Elf_Word index, + Elf_Word& type, + std::string& name, + char*& desc, + Elf_Word& descSize ) const { - if ( index >= note_section->get_size() ) { + if ( index >= ( notes->*F_get_size )() ) { return false; } - const char* pData = note_section->get_data() + note_start_positions[index]; - int align = sizeof( Elf_Word ); + const char* pData = notes->get_data() + note_start_positions[index]; + int align = sizeof( Elf_Word ); const endianess_convertor& convertor = elf_file.get_convertor(); - type = convertor( *(const Elf_Word*)( pData + 2*align ) ); + type = convertor( *(const Elf_Word*)( pData + 2 * (size_t)align ) ); Elf_Word namesz = convertor( *(const Elf_Word*)( pData ) ); descSize = convertor( *(const Elf_Word*)( pData + sizeof( namesz ) ) ); - Elf_Xword max_name_size = note_section->get_size() - note_start_positions[index]; - if ( namesz > max_name_size || - namesz + descSize > max_name_size ) { + + Elf_Xword max_name_size = + ( notes->*F_get_size )() - note_start_positions[index]; + if ( namesz < 1 || namesz > max_name_size || + (Elf_Xword)namesz + descSize > max_name_size ) { return false; } - name.assign( pData + 3*align, namesz - 1); + name.assign( pData + 3 * (size_t)align, namesz - 1 ); if ( 0 == descSize ) { - desc = 0; + desc = nullptr; } else { - desc = const_cast ( pData + 3*align + - ( ( namesz + align - 1 )/align )*align ); + desc = const_cast( pData + 3 * (size_t)align + + ( ( namesz + align - 1 ) / align ) * + (size_t)align ); } return true; } -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ void add_note( Elf_Word type, const std::string& name, - const void* desc, + const char* desc, Elf_Word descSize ) { const endianess_convertor& convertor = elf_file.get_convertor(); - int align = sizeof( Elf_Word ); - Elf_Word nameLen = (Elf_Word)name.size() + 1; - Elf_Word nameLenConv = convertor( nameLen ); + int align = sizeof( Elf_Word ); + Elf_Word nameLen = (Elf_Word)name.size() + 1; + Elf_Word nameLenConv = convertor( nameLen ); std::string buffer( reinterpret_cast( &nameLenConv ), align ); - Elf_Word descSizeConv = convertor( descSize ); + Elf_Word descSizeConv = convertor( descSize ); + buffer.append( reinterpret_cast( &descSizeConv ), align ); type = convertor( type ); buffer.append( reinterpret_cast( &type ), align ); @@ -113,58 +114,70 @@ class note_section_accessor_template buffer.append( 1, '\x00' ); const char pad[] = { '\0', '\0', '\0', '\0' }; if ( nameLen % align != 0 ) { - buffer.append( pad, align - nameLen % align ); + buffer.append( pad, (size_t)align - nameLen % align ); } - if ( desc != 0 && descSize != 0 ) { - buffer.append( reinterpret_cast( desc ), descSize ); + if ( desc != nullptr && descSize != 0 ) { + buffer.append( desc, descSize ); if ( descSize % align != 0 ) { - buffer.append( pad, align - descSize % align ); + buffer.append( pad, (size_t)align - descSize % align ); } } - note_start_positions.push_back( note_section->get_size() ); - note_section->append_data( buffer ); + note_start_positions.emplace_back( ( notes->*F_get_size )() ); + notes->append_data( buffer ); } private: -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ void process_section() { const endianess_convertor& convertor = elf_file.get_convertor(); - const char* data = note_section->get_data(); - Elf_Xword size = note_section->get_size(); - Elf_Xword current = 0; + const char* data = notes->get_data(); + Elf_Xword size = ( notes->*F_get_size )(); + Elf_Xword current = 0; note_start_positions.clear(); // Is it empty? - if ( 0 == data || 0 == size ) { + if ( nullptr == data || 0 == size ) { return; } - int align = sizeof( Elf_Word ); - while ( current + 3*align <= size ) { - note_start_positions.push_back( current ); - Elf_Word namesz = convertor( - *(const Elf_Word*)( data + current ) ); + Elf_Word align = sizeof( Elf_Word ); + while ( current + (Elf_Xword)3 * align <= size ) { + Elf_Word namesz = convertor( *(const Elf_Word*)( data + current ) ); Elf_Word descsz = convertor( - *(const Elf_Word*)( data + current + sizeof( namesz ) ) ); + *(const Elf_Word*)( data + current + sizeof( namesz ) ) ); + Elf_Word advance = + (Elf_Xword)3 * sizeof( Elf_Word ) + + ( ( namesz + align - 1 ) / align ) * (Elf_Xword)align + + ( ( descsz + align - 1 ) / align ) * (Elf_Xword)align; + if ( namesz < size && descsz < size && current + advance <= size ) { + note_start_positions.emplace_back( current ); + } + else { + break; + } - current += 3*sizeof( Elf_Word ) + - ( ( namesz + align - 1 ) / align ) * align + - ( ( descsz + align - 1 ) / align ) * align; + current += advance; } } -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ private: const elfio& elf_file; - S* note_section; + S* notes; std::vector note_start_positions; }; -using note_section_accessor = note_section_accessor_template
; -using const_note_section_accessor = note_section_accessor_template; +using note_section_accessor = + note_section_accessor_template; +using const_note_section_accessor = + note_section_accessor_template; +using note_segment_accessor = + note_section_accessor_template; +using const_note_segment_accessor = + note_section_accessor_template; } // namespace ELFIO diff --git a/source/elfio/elfio_relocation.hpp b/source/elfio/elfio_relocation.hpp index 641031a..2f39a36 100644 --- a/source/elfio/elfio_relocation.hpp +++ b/source/elfio/elfio_relocation.hpp @@ -1,6 +1,5 @@ -// clang-format off /* -Copyright (C) 2001-2015 by Serge Lamikhov-Center +Copyright (C) 2001-present by Serge Lamikhov-Center Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -26,8 +25,8 @@ THE SOFTWARE. namespace ELFIO { -template struct get_sym_and_type; -template<> struct get_sym_and_type< Elf32_Rel > +template struct get_sym_and_type; +template <> struct get_sym_and_type { static int get_r_sym( Elf_Xword info ) { @@ -38,7 +37,7 @@ template<> struct get_sym_and_type< Elf32_Rel > return ELF32_R_TYPE( (Elf_Word)info ); } }; -template<> struct get_sym_and_type< Elf32_Rela > +template <> struct get_sym_and_type { static int get_r_sym( Elf_Xword info ) { @@ -49,161 +48,219 @@ template<> struct get_sym_and_type< Elf32_Rela > return ELF32_R_TYPE( (Elf_Word)info ); } }; -template<> struct get_sym_and_type< Elf64_Rel > +template <> struct get_sym_and_type { - static int get_r_sym( Elf_Xword info ) - { - return ELF64_R_SYM( info ); - } - static int get_r_type( Elf_Xword info ) - { - return ELF64_R_TYPE( info ); - } + static int get_r_sym( Elf_Xword info ) { return ELF64_R_SYM( info ); } + static int get_r_type( Elf_Xword info ) { return ELF64_R_TYPE( info ); } }; -template<> struct get_sym_and_type< Elf64_Rela > +template <> struct get_sym_and_type { - static int get_r_sym( Elf_Xword info ) - { - return ELF64_R_SYM( info ); - } - static int get_r_type( Elf_Xword info ) - { - return ELF64_R_TYPE( info ); - } + static int get_r_sym( Elf_Xword info ) { return ELF64_R_SYM( info ); } + static int get_r_type( Elf_Xword info ) { return ELF64_R_TYPE( info ); } }; - //------------------------------------------------------------------------------ -template< class S > -class relocation_section_accessor_template +template class relocation_section_accessor_template { public: -//------------------------------------------------------------------------------ - relocation_section_accessor_template( const elfio& elf_file_, S* section_ ) : - elf_file( elf_file_ ), - relocation_section( section_ ) + //------------------------------------------------------------------------------ + explicit relocation_section_accessor_template( const elfio& elf_file, + S* section ) + : elf_file( elf_file ), relocation_section( section ) { } -//------------------------------------------------------------------------------ - Elf_Xword - get_entries_num() const + //------------------------------------------------------------------------------ + Elf_Xword get_entries_num() const { Elf_Xword nRet = 0; if ( 0 != relocation_section->get_entry_size() ) { - nRet = relocation_section->get_size() / relocation_section->get_entry_size(); + nRet = relocation_section->get_size() / + relocation_section->get_entry_size(); } return nRet; } -//------------------------------------------------------------------------------ - bool - get_entry( Elf_Xword index, - Elf64_Addr& offset, - Elf_Word& symbol, - Elf_Word& type, - Elf_Sxword& addend ) const + //------------------------------------------------------------------------------ + bool get_entry( Elf_Xword index, + Elf64_Addr& offset, + Elf_Word& symbol, + unsigned& type, + Elf_Sxword& addend ) const { - if ( index >= get_entries_num() ) { // Is index valid + if ( index >= get_entries_num() ) { // Is index valid return false; } if ( elf_file.get_class() == ELFCLASS32 ) { if ( SHT_REL == relocation_section->get_type() ) { - generic_get_entry_rel< Elf32_Rel >( index, offset, symbol, - type, addend ); + generic_get_entry_rel( index, offset, symbol, type, + addend ); } else if ( SHT_RELA == relocation_section->get_type() ) { - generic_get_entry_rela< Elf32_Rela >( index, offset, symbol, - type, addend ); + generic_get_entry_rela( index, offset, symbol, type, + addend ); } } else { if ( SHT_REL == relocation_section->get_type() ) { - generic_get_entry_rel< Elf64_Rel >( index, offset, symbol, - type, addend ); + generic_get_entry_rel( index, offset, symbol, type, + addend ); } else if ( SHT_RELA == relocation_section->get_type() ) { - generic_get_entry_rela< Elf64_Rela >( index, offset, symbol, - type, addend ); + generic_get_entry_rela( index, offset, symbol, type, + addend ); } } return true; } -//------------------------------------------------------------------------------ - bool - get_entry( Elf_Xword index, - Elf64_Addr& offset, - Elf64_Addr& symbolValue, - std::string& symbolName, - Elf_Word& type, - Elf_Sxword& addend, - Elf_Half& section) const + //------------------------------------------------------------------------------ + bool get_entry( Elf_Xword index, + Elf64_Addr& offset, + Elf64_Addr& symbolValue, + std::string& symbolName, + unsigned& type, + Elf_Sxword& addend, + Elf_Sxword& calcValue ) const { // Do regular job - Elf_Word symbol; - bool ret = get_entry( index, offset, symbol, type, addend ); + Elf_Word symbol = 0; + bool ret = get_entry( index, offset, symbol, type, addend ); // Find the symbol Elf_Xword size; unsigned char bind; unsigned char symbolType; + Elf_Half section; unsigned char other; - symbol_section_accessor symbols( elf_file, elf_file.sections[get_symbol_table_index()] ); - ret = ret && symbols.get_symbol( symbol, symbolName, symbolValue, - size, bind, symbolType, section, other ); + symbol_section_accessor symbols( + elf_file, elf_file.sections[get_symbol_table_index()] ); + ret = ret && symbols.get_symbol( symbol, symbolName, symbolValue, size, + bind, symbolType, section, other ); + + if ( ret ) { // Was it successful? + switch ( type ) { + case R_386_NONE: // none + calcValue = 0; + break; + case R_386_32: // S + A + calcValue = symbolValue + addend; + break; + case R_386_PC32: // S + A - P + calcValue = symbolValue + addend - offset; + break; + case R_386_GOT32: // G + A - P + calcValue = 0; + break; + case R_386_PLT32: // L + A - P + calcValue = 0; + break; + case R_386_COPY: // none + calcValue = 0; + break; + case R_386_GLOB_DAT: // S + case R_386_JMP_SLOT: // S + calcValue = symbolValue; + break; + case R_386_RELATIVE: // B + A + calcValue = addend; + break; + case R_386_GOTOFF: // S + A - GOT + calcValue = 0; + break; + case R_386_GOTPC: // GOT + A - P + calcValue = 0; + break; + default: // Not recognized symbol! + calcValue = 0; + break; + } + } return ret; } -//------------------------------------------------------------------------------ - void - add_entry( Elf64_Addr offset, Elf_Xword info ) + //------------------------------------------------------------------------------ + bool set_entry( Elf_Xword index, + Elf64_Addr offset, + Elf_Word symbol, + unsigned type, + Elf_Sxword addend ) { + if ( index >= get_entries_num() ) { // Is index valid + return false; + } + if ( elf_file.get_class() == ELFCLASS32 ) { - generic_add_entry< Elf32_Rel >( offset, info ); + if ( SHT_REL == relocation_section->get_type() ) { + generic_set_entry_rel( index, offset, symbol, type, + addend ); + } + else if ( SHT_RELA == relocation_section->get_type() ) { + generic_set_entry_rela( index, offset, symbol, type, + addend ); + } } else { - generic_add_entry< Elf64_Rel >( offset, info ); + if ( SHT_REL == relocation_section->get_type() ) { + generic_set_entry_rel( index, offset, symbol, type, + addend ); + } + else if ( SHT_RELA == relocation_section->get_type() ) { + generic_set_entry_rela( index, offset, symbol, type, + addend ); + } + } + + return true; + } + + //------------------------------------------------------------------------------ + void add_entry( Elf64_Addr offset, Elf_Xword info ) + { + if ( elf_file.get_class() == ELFCLASS32 ) { + generic_add_entry( offset, info ); + } + else { + generic_add_entry( offset, info ); } } -//------------------------------------------------------------------------------ - void - add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned char type ) + //------------------------------------------------------------------------------ + void add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned type ) { Elf_Xword info; if ( elf_file.get_class() == ELFCLASS32 ) { info = ELF32_R_INFO( (Elf_Xword)symbol, type ); } else { - info = ELF64_R_INFO((Elf_Xword)symbol, type ); + info = ELF64_R_INFO( (Elf_Xword)symbol, type ); } add_entry( offset, info ); } -//------------------------------------------------------------------------------ - void - add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend ) + //------------------------------------------------------------------------------ + void add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend ) { if ( elf_file.get_class() == ELFCLASS32 ) { - generic_add_entry< Elf32_Rela >( offset, info, addend ); + generic_add_entry( offset, info, addend ); } else { - generic_add_entry< Elf64_Rela >( offset, info, addend ); + generic_add_entry( offset, info, addend ); } } -//------------------------------------------------------------------------------ - void - add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned char type, - Elf_Sxword addend ) + //------------------------------------------------------------------------------ + void add_entry( Elf64_Addr offset, + Elf_Word symbol, + unsigned type, + Elf_Sxword addend ) { Elf_Xword info; if ( elf_file.get_class() == ELFCLASS32 ) { @@ -216,48 +273,63 @@ class relocation_section_accessor_template add_entry( offset, info, addend ); } -//------------------------------------------------------------------------------ - void - add_entry( string_section_accessor str_writer, - const char* str, - symbol_section_accessor sym_writer, - Elf64_Addr value, - Elf_Word size, - unsigned char sym_info, - unsigned char other, - Elf_Half shndx, - Elf64_Addr offset, - unsigned char type ) + //------------------------------------------------------------------------------ + void add_entry( string_section_accessor str_writer, + const char* str, + symbol_section_accessor sym_writer, + Elf64_Addr value, + Elf_Word size, + unsigned char sym_info, + unsigned char other, + Elf_Half shndx, + Elf64_Addr offset, + unsigned type ) { Elf_Word str_index = str_writer.add_string( str ); Elf_Word sym_index = sym_writer.add_symbol( str_index, value, size, - sym_info, other, shndx ); + sym_info, other, shndx ); add_entry( offset, sym_index, type ); } -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ + void swap_symbols( Elf_Xword first, Elf_Xword second ) + { + Elf64_Addr offset = 0; + Elf_Word symbol = 0; + unsigned rtype = 0; + Elf_Sxword addend = 0; + for ( Elf_Word i = 0; i < get_entries_num(); i++ ) { + get_entry( i, offset, symbol, rtype, addend ); + if ( symbol == first ) { + set_entry( i, offset, (Elf_Word)second, rtype, addend ); + } + if ( symbol == second ) { + set_entry( i, offset, (Elf_Word)first, rtype, addend ); + } + } + } + + //------------------------------------------------------------------------------ private: -//------------------------------------------------------------------------------ - Elf_Half - get_symbol_table_index() const + //------------------------------------------------------------------------------ + Elf_Half get_symbol_table_index() const { return (Elf_Half)relocation_section->get_link(); } -//------------------------------------------------------------------------------ - template< class T > - void - generic_get_entry_rel( Elf_Xword index, - Elf64_Addr& offset, - Elf_Word& symbol, - Elf_Word& type, - Elf_Sxword& addend ) const + //------------------------------------------------------------------------------ + template + void generic_get_entry_rel( Elf_Xword index, + Elf64_Addr& offset, + Elf_Word& symbol, + unsigned& type, + Elf_Sxword& addend ) const { const endianess_convertor& convertor = elf_file.get_convertor(); const T* pEntry = reinterpret_cast( - relocation_section->get_data() + - index * relocation_section->get_entry_size() ); + relocation_section->get_data() + + index * relocation_section->get_entry_size() ); offset = convertor( pEntry->r_offset ); Elf_Xword tmp = convertor( pEntry->r_info ); symbol = get_sym_and_type::get_r_sym( tmp ); @@ -265,20 +337,19 @@ class relocation_section_accessor_template addend = 0; } -//------------------------------------------------------------------------------ - template< class T > - void - generic_get_entry_rela( Elf_Xword index, - Elf64_Addr& offset, - Elf_Word& symbol, - Elf_Word& type, - Elf_Sxword& addend ) const + //------------------------------------------------------------------------------ + template + void generic_get_entry_rela( Elf_Xword index, + Elf64_Addr& offset, + Elf_Word& symbol, + unsigned& type, + Elf_Sxword& addend ) const { const endianess_convertor& convertor = elf_file.get_convertor(); const T* pEntry = reinterpret_cast( - relocation_section->get_data() + - index * relocation_section->get_entry_size() ); + relocation_section->get_data() + + index * relocation_section->get_entry_size() ); offset = convertor( pEntry->r_offset ); Elf_Xword tmp = convertor( pEntry->r_info ); symbol = get_sym_and_type::get_r_sym( tmp ); @@ -286,24 +357,76 @@ class relocation_section_accessor_template addend = convertor( pEntry->r_addend ); } -//------------------------------------------------------------------------------ - template< class T > - void - generic_add_entry( Elf64_Addr offset, Elf_Xword info ) + //------------------------------------------------------------------------------ + template + void generic_set_entry_rel( Elf_Xword index, + Elf64_Addr offset, + Elf_Word symbol, + unsigned type, + Elf_Sxword ) + { + const endianess_convertor& convertor = elf_file.get_convertor(); + + T* pEntry = const_cast( reinterpret_cast( + relocation_section->get_data() + + index * relocation_section->get_entry_size() ) ); + + if ( elf_file.get_class() == ELFCLASS32 ) { + pEntry->r_info = ELF32_R_INFO( (Elf_Xword)symbol, type ); + } + else { + pEntry->r_info = ELF64_R_INFO( (Elf_Xword)symbol, type ); + } + pEntry->r_offset = decltype( pEntry->r_offset )( offset ); + pEntry->r_offset = convertor( pEntry->r_offset ); + pEntry->r_info = convertor( pEntry->r_info ); + } + + //------------------------------------------------------------------------------ + template + void generic_set_entry_rela( Elf_Xword index, + Elf64_Addr offset, + Elf_Word symbol, + unsigned type, + Elf_Sxword addend ) + { + const endianess_convertor& convertor = elf_file.get_convertor(); + + T* pEntry = const_cast( reinterpret_cast( + relocation_section->get_data() + + index * relocation_section->get_entry_size() ) ); + + if ( elf_file.get_class() == ELFCLASS32 ) { + pEntry->r_info = ELF32_R_INFO( (Elf_Xword)symbol, type ); + } + else { + pEntry->r_info = ELF64_R_INFO( (Elf_Xword)symbol, type ); + } + pEntry->r_offset = decltype( pEntry->r_offset )( offset ); + pEntry->r_addend = decltype( pEntry->r_addend )( addend ); + pEntry->r_offset = convertor( pEntry->r_offset ); + pEntry->r_info = convertor( pEntry->r_info ); + pEntry->r_addend = convertor( pEntry->r_addend ); + } + + //------------------------------------------------------------------------------ + template + void generic_add_entry( Elf64_Addr offset, Elf_Xword info ) { const endianess_convertor& convertor = elf_file.get_convertor(); T entry; - entry.r_offset = offset; - entry.r_info = info; + entry.r_offset = decltype( entry.r_offset )( offset ); + entry.r_info = decltype( entry.r_info )( info ); entry.r_offset = convertor( entry.r_offset ); entry.r_info = convertor( entry.r_info ); - relocation_section->append_data( reinterpret_cast( &entry ), sizeof( entry ) ); + relocation_section->append_data( reinterpret_cast( &entry ), + sizeof( entry ) ); } -//------------------------------------------------------------------------------ - template< class T > + //------------------------------------------------------------------------------ + template void generic_add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend ) { @@ -317,17 +440,20 @@ class relocation_section_accessor_template entry.r_info = convertor( entry.r_info ); entry.r_addend = convertor( entry.r_addend ); - relocation_section->append_data( reinterpret_cast( &entry ), sizeof( entry ) ); + relocation_section->append_data( reinterpret_cast( &entry ), + sizeof( entry ) ); } -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ private: const elfio& elf_file; - S* relocation_section; + S* relocation_section = nullptr; }; -using relocation_section_accessor = relocation_section_accessor_template
; -using const_relocation_section_accessor = relocation_section_accessor_template; +using relocation_section_accessor = + relocation_section_accessor_template
; +using const_relocation_section_accessor = + relocation_section_accessor_template; } // namespace ELFIO diff --git a/source/elfio/elfio_section.hpp b/source/elfio/elfio_section.hpp index 52d3102..ed9281e 100644 --- a/source/elfio/elfio_section.hpp +++ b/source/elfio/elfio_section.hpp @@ -1,6 +1,5 @@ -// clang-format off /* -Copyright (C) 2001-2015 by Serge Lamikhov-Center +Copyright (C) 2001-present by Serge Lamikhov-Center Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -26,320 +25,342 @@ THE SOFTWARE. #include #include -#include "utils/logger.h" -#include +#include +#include namespace ELFIO { class section { friend class elfio; + public: - virtual ~section() {}; + virtual ~section() = default; - ELFIO_GET_ACCESS_DECL ( Elf_Half, index ); - ELFIO_GET_SET_ACCESS_DECL( std::string, name ); - ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type ); - ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, flags ); - ELFIO_GET_SET_ACCESS_DECL( Elf_Word, info ); - ELFIO_GET_SET_ACCESS_DECL( Elf_Word, link ); - ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, addr_align ); - ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, entry_size ); - ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, address ); - ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, size ); - ELFIO_GET_SET_ACCESS_DECL( Elf_Word, name_string_offset ); - ELFIO_GET_ACCESS_DECL ( Elf64_Off, offset ); - size_t stream_size; - size_t get_stream_size() const - { - return stream_size; - } + ELFIO_GET_ACCESS_DECL( Elf_Half, index ); + ELFIO_GET_SET_ACCESS_DECL( std::string, name ); + ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type ); + ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, flags ); + ELFIO_GET_SET_ACCESS_DECL( Elf_Word, info ); + ELFIO_GET_SET_ACCESS_DECL( Elf_Word, link ); + ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, addr_align ); + ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, entry_size ); + ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, address ); + ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, size ); + ELFIO_GET_SET_ACCESS_DECL( Elf_Word, name_string_offset ); + ELFIO_GET_ACCESS_DECL( Elf64_Off, offset ); - void set_stream_size(size_t value) - { - stream_size = value; - } - - virtual const char* get_data() const = 0; - virtual void set_data( const char* pData, Elf_Word size ) = 0; - virtual void set_data( const std::string& data ) = 0; - virtual void append_data( const char* pData, Elf_Word size ) = 0; - virtual void append_data( const std::string& data ) = 0; + virtual const char* get_data() const = 0; + virtual void set_data( const char* raw_data, Elf_Word size ) = 0; + virtual void set_data( const std::string& data ) = 0; + virtual void append_data( const char* raw_data, Elf_Word size ) = 0; + virtual void append_data( const std::string& data ) = 0; + virtual void + insert_data( Elf_Xword pos, const char* raw_data, Elf_Word size ) = 0; + virtual void insert_data( Elf_Xword pos, const std::string& data ) = 0; + virtual size_t get_stream_size() const = 0; + virtual void set_stream_size( size_t value ) = 0; protected: ELFIO_SET_ACCESS_DECL( Elf64_Off, offset ); - ELFIO_SET_ACCESS_DECL( Elf_Half, index ); + ELFIO_SET_ACCESS_DECL( Elf_Half, index ); - virtual void load( std::istream& stream, - std::streampos header_offset ) = 0; + virtual bool load( std::istream& stream, + std::streampos header_offset, + bool is_lazy ) = 0; virtual void save( std::ostream& stream, std::streampos header_offset, - std::streampos data_offset ) = 0; - virtual bool is_address_initialized() const = 0; + std::streampos data_offset ) = 0; + virtual bool is_address_initialized() const = 0; }; - -template< class T > -class section_impl : public section +template class section_impl : public section { public: -//------------------------------------------------------------------------------ - section_impl( const endianess_convertor* convertor_ ) : convertor( convertor_ ) + //------------------------------------------------------------------------------ + section_impl( const endianess_convertor* convertor, + const address_translator* translator, + const std::shared_ptr& compression ) + : convertor( convertor ), translator( translator ), + compression( compression ) { - std::fill_n( reinterpret_cast( &header ), sizeof( header ), '\0' ); - is_address_set = false; - data = 0; - data_size = 0; } -//------------------------------------------------------------------------------ - ~section_impl() - { - delete [] data; - } - -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ // Section info functions - ELFIO_GET_SET_ACCESS( Elf_Word, type, header.sh_type ); - ELFIO_GET_SET_ACCESS( Elf_Xword, flags, header.sh_flags ); - ELFIO_GET_SET_ACCESS( Elf_Xword, size, header.sh_size ); - ELFIO_GET_SET_ACCESS( Elf_Word, link, header.sh_link ); - ELFIO_GET_SET_ACCESS( Elf_Word, info, header.sh_info ); - ELFIO_GET_SET_ACCESS( Elf_Xword, addr_align, header.sh_addralign ); - ELFIO_GET_SET_ACCESS( Elf_Xword, entry_size, header.sh_entsize ); - ELFIO_GET_SET_ACCESS( Elf_Word, name_string_offset, header.sh_name ); - ELFIO_GET_ACCESS ( Elf64_Addr, address, header.sh_addr ); + ELFIO_GET_SET_ACCESS( Elf_Word, type, header.sh_type ); + ELFIO_GET_SET_ACCESS( Elf_Xword, flags, header.sh_flags ); + ELFIO_GET_SET_ACCESS( Elf_Xword, size, header.sh_size ); + ELFIO_GET_SET_ACCESS( Elf_Word, link, header.sh_link ); + ELFIO_GET_SET_ACCESS( Elf_Word, info, header.sh_info ); + ELFIO_GET_SET_ACCESS( Elf_Xword, addr_align, header.sh_addralign ); + ELFIO_GET_SET_ACCESS( Elf_Xword, entry_size, header.sh_entsize ); + ELFIO_GET_SET_ACCESS( Elf_Word, name_string_offset, header.sh_name ); + ELFIO_GET_ACCESS( Elf64_Addr, address, header.sh_addr ); + //------------------------------------------------------------------------------ + Elf_Half get_index() const override { return index; } + //------------------------------------------------------------------------------ + std::string get_name() const override { return name; } -//------------------------------------------------------------------------------ - Elf_Half - get_index() const + //------------------------------------------------------------------------------ + void set_name( const std::string& name_prm ) override { - return index; + this->name = name_prm; } - -//------------------------------------------------------------------------------ - std::string - get_name() const + //------------------------------------------------------------------------------ + void set_address( const Elf64_Addr& value ) override { - return name; - } - -//------------------------------------------------------------------------------ - void - set_name( std::string name_ ) - { - name = name_; - } - -//------------------------------------------------------------------------------ - void - set_address( Elf64_Addr value ) - { - header.sh_addr = value; - header.sh_addr = (*convertor)( header.sh_addr ); + header.sh_addr = decltype( header.sh_addr )( value ); + header.sh_addr = ( *convertor )( header.sh_addr ); is_address_set = true; } -//------------------------------------------------------------------------------ - bool - is_address_initialized() const + //------------------------------------------------------------------------------ + bool is_address_initialized() const override { return is_address_set; } + + //------------------------------------------------------------------------------ + const char* get_data() const override { - return is_address_set; + if ( is_lazy ) { + load_data(); + } + return data.get(); } -//------------------------------------------------------------------------------ - const char* - get_data() const - { - return data; - } - -//------------------------------------------------------------------------------ - void - set_data( const char* raw_data, Elf_Word size ) + //------------------------------------------------------------------------------ + void set_data( const char* raw_data, Elf_Word size ) override { if ( get_type() != SHT_NOBITS ) { - delete [] data; - data = new char[size]; - if ( 0 != data && 0 != raw_data ) { + data = std::unique_ptr( new ( std::nothrow ) char[size] ); + if ( nullptr != data.get() && nullptr != raw_data ) { data_size = size; - std::copy( raw_data, raw_data + size, data ); + std::copy( raw_data, raw_data + size, data.get() ); + } + else { + data_size = 0; } } - set_size( size ); + set_size( data_size ); + if ( translator->empty() ) { + set_stream_size( data_size ); + } } -//------------------------------------------------------------------------------ - void - set_data( const std::string& str_data ) + //------------------------------------------------------------------------------ + void set_data( const std::string& str_data ) override { return set_data( str_data.c_str(), (Elf_Word)str_data.size() ); } -//------------------------------------------------------------------------------ - void - append_data( const char* raw_data, Elf_Word size ) + //------------------------------------------------------------------------------ + void append_data( const char* raw_data, Elf_Word size ) override { - if ( get_type() != SHT_NOBITS ) { - if ( get_size() + size < data_size ) { - std::copy( raw_data, raw_data + size, data + get_size() ); - } - else { - data_size = 2*( data_size + size); - char* new_data; - new_data = new char[data_size]; - - if ( 0 != new_data ) { - std::copy( data, data + get_size(), new_data ); - std::copy( raw_data, raw_data + size, new_data + get_size() ); - delete [] data; - data = new_data; - } - } - set_size( get_size() + size ); - } + insert_data( get_size(), raw_data, size ); } -//------------------------------------------------------------------------------ - void - append_data( const std::string& str_data ) + //------------------------------------------------------------------------------ + void append_data( const std::string& str_data ) override { return append_data( str_data.c_str(), (Elf_Word)str_data.size() ); } -//------------------------------------------------------------------------------ - protected: -//------------------------------------------------------------------------------ - ELFIO_GET_SET_ACCESS( Elf64_Off, offset, header.sh_offset ); - -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ void - set_index( Elf_Half value ) + insert_data( Elf_Xword pos, const char* raw_data, Elf_Word size ) override { - index = value; - } + if ( get_type() != SHT_NOBITS ) { + if ( get_size() + size < data_size ) { + char* d = data.get(); + std::copy_backward( d + pos, d + get_size(), + d + get_size() + size ); + std::copy( raw_data, raw_data + size, d + pos ); + } + else { + data_size = 2 * ( data_size + size ); + std::unique_ptr new_data( + new ( std::nothrow ) char[data_size] ); -//------------------------------------------------------------------------------ - void - load( std::istream& stream, - std::streampos header_offset ) - { - std::fill_n( reinterpret_cast( &header ), sizeof( header ), '\0' ); - - stream.seekg ( 0, stream.end ); - set_stream_size ( stream.tellg() ); - - stream.seekg( header_offset ); - stream.read( reinterpret_cast( &header ), sizeof( header ) ); - - - Elf_Xword size = get_size(); - if ( 0 == data && SHT_NULL != get_type() && SHT_NOBITS != get_type() && size < get_stream_size()) { - - data = new char[size + 1]; - - if ( ( 0 != size ) && ( 0 != data ) ) { - stream.seekg( (*convertor)( header.sh_offset ) ); - if (get_flags() & 0x08000000){ - uint32_t uncompressed_size = size; - stream.read( (char *) &uncompressed_size, 4); - stream.read( data, size - 4); - - char* uncompressedData = new char[uncompressed_size + 1]; - - int ret = 0; - z_stream s; - memset(&s, 0, sizeof(s)); - - s.zalloc = Z_NULL; - s.zfree = Z_NULL; - s.opaque = Z_NULL; - - ret = inflateInit_(&s, ZLIB_VERSION, sizeof(s)); - if (ret != Z_OK) - return; - - s.avail_in = size - 4; - s.next_in = (Bytef *)data; - - s.avail_out = uncompressed_size; - s.next_out = (Bytef *)&uncompressedData[0]; - - ret = inflate(&s, Z_FINISH); - if (ret != Z_OK && ret != Z_STREAM_END){ - DEBUG_FUNCTION_LINE("NOOOO"); - } - - inflateEnd(&s); - - delete [] data; - data = uncompressedData; - data_size = uncompressed_size; - set_size(uncompressed_size); - data[data_size] = 0; // Ensure data is ended with 0 to avoid oob read - - }else{ - stream.read( data, size ); - data[size] = 0; // Ensure data is ended with 0 to avoid oob read - data_size = size; + if ( nullptr != new_data ) { + char* d = data.get(); + std::copy( d, d + pos, new_data.get() ); + std::copy( raw_data, raw_data + size, + new_data.get() + pos ); + std::copy( d + pos, d + get_size(), + new_data.get() + pos + size ); + data = std::move( new_data ); } - }else{ - set_size(0); - DEBUG_FUNCTION_LINE("Failed to allocate memory."); + else { + size = 0; + } + } + set_size( get_size() + size ); + if ( translator->empty() ) { + set_stream_size( get_stream_size() + size ); } } } -//------------------------------------------------------------------------------ - void - save( std::ostream& stream, - std::streampos header_offset, - std::streampos data_offset ) + //------------------------------------------------------------------------------ + void insert_data( Elf_Xword pos, const std::string& str_data ) override + { + return insert_data( pos, str_data.c_str(), (Elf_Word)str_data.size() ); + } + + size_t get_stream_size() const override { return stream_size; } + + //------------------------------------------------------------------------------ + void set_stream_size( size_t value ) override { stream_size = value; } + + //------------------------------------------------------------------------------ + protected: + //------------------------------------------------------------------------------ + ELFIO_GET_SET_ACCESS( Elf64_Off, offset, header.sh_offset ); + + //------------------------------------------------------------------------------ + void set_index( const Elf_Half& value ) override { index = value; } + + bool is_compressed() const + { + return ( ( get_flags() & SHF_RPX_DEFLATE ) || + ( get_flags() & SHF_COMPRESSED ) ) && + compression != nullptr; + } + + //------------------------------------------------------------------------------ + bool load( std::istream& stream, + std::streampos header_offset, + bool is_lazy_ ) override + { + pstream = &stream; + is_lazy = is_lazy_; + header = { 0 }; + + if ( translator->empty() ) { + stream.seekg( 0, std::istream::end ); + set_stream_size( size_t( stream.tellg() ) ); + } + else { + set_stream_size( std::numeric_limits::max() ); + } + + stream.seekg( ( *translator )[header_offset] ); + stream.read( reinterpret_cast( &header ), sizeof( header ) ); + + if ( !is_lazy || is_compressed() ) { + + bool ret = load_data(); + + if ( is_compressed() ) { + Elf_Xword size = get_size(); + Elf_Xword uncompressed_size = 0; + auto decompressed_data = compression->inflate( + data.get(), convertor, size, uncompressed_size ); + if ( decompressed_data != nullptr ) { + set_size( uncompressed_size ); + data = std::move( decompressed_data ); + } + } + + return ret; + } + + return true; + } + + bool load_data() const + { + is_lazy = false; + Elf_Xword size = get_size(); + if ( nullptr == data && SHT_NULL != get_type() && + SHT_NOBITS != get_type() && size < get_stream_size() ) { + data.reset( new ( std::nothrow ) char[size_t( size ) + 1] ); + + if ( ( 0 != size ) && ( nullptr != data ) ) { + pstream->seekg( + ( *translator )[( *convertor )( header.sh_offset )] ); + pstream->read( data.get(), size ); + if ( static_cast( pstream->gcount() ) != size ) { + data = nullptr; + return false; + } + + // refresh size because it may have changed if we had to decompress data + size = get_size(); + data.get()[size] = + 0; // Ensure data is ended with 0 to avoid oob read + data_size = decltype( data_size )( size ); + } + else { + data_size = 0; + } + } + + return true; + } + + //------------------------------------------------------------------------------ + void save( std::ostream& stream, + std::streampos header_offset, + std::streampos data_offset ) override { if ( 0 != get_index() ) { - header.sh_offset = data_offset; - header.sh_offset = (*convertor)( header.sh_offset ); + header.sh_offset = decltype( header.sh_offset )( data_offset ); + header.sh_offset = ( *convertor )( header.sh_offset ); } save_header( stream, header_offset ); if ( get_type() != SHT_NOBITS && get_type() != SHT_NULL && - get_size() != 0 && data != 0 ) { + get_size() != 0 && data != nullptr ) { save_data( stream, data_offset ); } } -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ private: -//------------------------------------------------------------------------------ - void - save_header( std::ostream& stream, - std::streampos header_offset ) const + //------------------------------------------------------------------------------ + void save_header( std::ostream& stream, std::streampos header_offset ) const { - stream.seekp( header_offset ); - stream.write( reinterpret_cast( &header ), sizeof( header ) ); + adjust_stream_size( stream, header_offset ); + stream.write( reinterpret_cast( &header ), + sizeof( header ) ); } -//------------------------------------------------------------------------------ - void - save_data( std::ostream& stream, - std::streampos data_offset ) const + //------------------------------------------------------------------------------ + void save_data( std::ostream& stream, std::streampos data_offset ) { - stream.seekp( data_offset ); - stream.write( get_data(), get_size() ); + adjust_stream_size( stream, data_offset ); + + if ( ( ( get_flags() & SHF_COMPRESSED ) || + ( get_flags() & SHF_RPX_DEFLATE ) ) && + compression != nullptr ) { + Elf_Xword decompressed_size = get_size(); + Elf_Xword compressed_size = 0; + auto compressed_ptr = compression->deflate( + data.get(), convertor, decompressed_size, compressed_size ); + stream.write( compressed_ptr.get(), compressed_size ); + } + else { + stream.write( get_data(), get_size() ); + } } -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ private: - T header; - Elf_Half index; - std::string name; - char* data; - Elf_Word data_size; - const endianess_convertor* convertor; - bool is_address_set; + mutable std::istream* pstream = nullptr; + T header = {}; + Elf_Half index = 0; + std::string name; + mutable std::unique_ptr data; + mutable Elf_Word data_size = 0; + const endianess_convertor* convertor = nullptr; + const address_translator* translator = nullptr; + const std::shared_ptr compression = nullptr; + bool is_address_set = false; + size_t stream_size = 0; + mutable bool is_lazy = false; }; } // namespace ELFIO diff --git a/source/elfio/elfio_segment.hpp b/source/elfio/elfio_segment.hpp index fa370fb..6b0f81d 100644 --- a/source/elfio/elfio_segment.hpp +++ b/source/elfio/elfio_segment.hpp @@ -1,6 +1,5 @@ -// clang-format off /* -Copyright (C) 2001-2015 by Serge Lamikhov-Center +Copyright (C) 2001-present by Serge Lamikhov-Center Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -26,107 +25,90 @@ THE SOFTWARE. #include #include +#include +#include namespace ELFIO { class segment { friend class elfio; - public: - virtual ~segment() {}; - ELFIO_GET_ACCESS_DECL ( Elf_Half, index ); - ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type ); - ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags ); - ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, align ); - ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, virtual_address ); + public: + virtual ~segment() = default; + + ELFIO_GET_ACCESS_DECL( Elf_Half, index ); + ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type ); + ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags ); + ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, align ); + ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, virtual_address ); ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, physical_address ); - ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, file_size ); - ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, memory_size ); + ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, file_size ); + ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, memory_size ); ELFIO_GET_ACCESS_DECL( Elf64_Off, offset ); virtual const char* get_data() const = 0; - virtual Elf_Half add_section_index( Elf_Half index, Elf_Xword addr_align ) = 0; - virtual Elf_Half get_sections_num() const = 0; - virtual Elf_Half get_section_index_at( Elf_Half num ) const = 0; - virtual bool is_offset_initialized() const = 0; + virtual Elf_Half add_section( section* psec, Elf_Xword addr_align ) = 0; + virtual Elf_Half add_section_index( Elf_Half index, + Elf_Xword addr_align ) = 0; + virtual Elf_Half get_sections_num() const = 0; + virtual Elf_Half get_section_index_at( Elf_Half num ) const = 0; + virtual bool is_offset_initialized() const = 0; protected: ELFIO_SET_ACCESS_DECL( Elf64_Off, offset ); - ELFIO_SET_ACCESS_DECL( Elf_Half, index ); - - virtual const std::vector& get_sections() const = 0; - virtual void load( std::istream& stream, std::streampos header_offset ) = 0; - virtual void save( std::ostream& stream, std::streampos header_offset, - std::streampos data_offset ) = 0; + ELFIO_SET_ACCESS_DECL( Elf_Half, index ); + + virtual const std::vector& get_sections() const = 0; + + virtual bool load( std::istream& stream, + std::streampos header_offset, + bool is_lazy ) = 0; + virtual void save( std::ostream& stream, + std::streampos header_offset, + std::streampos data_offset ) = 0; }; - //------------------------------------------------------------------------------ -template< class T > -class segment_impl : public segment +template class segment_impl : public segment { public: -//------------------------------------------------------------------------------ - segment_impl( endianess_convertor* convertor_ ) : - stream_size( 0 ), index( 0 ), data( 0 ), convertor( convertor_ ) + //------------------------------------------------------------------------------ + segment_impl( const endianess_convertor* convertor, + const address_translator* translator ) + : convertor( convertor ), translator( translator ) { - is_offset_set = false; - std::fill_n( reinterpret_cast( &ph ), sizeof( ph ), '\0' ); } -//------------------------------------------------------------------------------ - virtual ~segment_impl() - { - delete [] data; - } - -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ // Section info functions - ELFIO_GET_SET_ACCESS( Elf_Word, type, ph.p_type ); - ELFIO_GET_SET_ACCESS( Elf_Word, flags, ph.p_flags ); - ELFIO_GET_SET_ACCESS( Elf_Xword, align, ph.p_align ); - ELFIO_GET_SET_ACCESS( Elf64_Addr, virtual_address, ph.p_vaddr ); - ELFIO_GET_SET_ACCESS( Elf64_Addr, physical_address, ph.p_paddr ); - ELFIO_GET_SET_ACCESS( Elf_Xword, file_size, ph.p_filesz ); - ELFIO_GET_SET_ACCESS( Elf_Xword, memory_size, ph.p_memsz ); + ELFIO_GET_SET_ACCESS( Elf_Word, type, ph.p_type ); + ELFIO_GET_SET_ACCESS( Elf_Word, flags, ph.p_flags ); + ELFIO_GET_SET_ACCESS( Elf_Xword, align, ph.p_align ); + ELFIO_GET_SET_ACCESS( Elf64_Addr, virtual_address, ph.p_vaddr ); + ELFIO_GET_SET_ACCESS( Elf64_Addr, physical_address, ph.p_paddr ); + ELFIO_GET_SET_ACCESS( Elf_Xword, file_size, ph.p_filesz ); + ELFIO_GET_SET_ACCESS( Elf_Xword, memory_size, ph.p_memsz ); ELFIO_GET_ACCESS( Elf64_Off, offset, ph.p_offset ); - size_t stream_size; -//------------------------------------------------------------------------------ - size_t - get_stream_size() const + //------------------------------------------------------------------------------ + Elf_Half get_index() const override { return index; } + + //------------------------------------------------------------------------------ + const char* get_data() const override { - return stream_size; + if ( is_lazy ) { + load_data(); + } + return data.get(); } -//------------------------------------------------------------------------------ - void - set_stream_size(size_t value) + //------------------------------------------------------------------------------ + Elf_Half add_section_index( Elf_Half sec_index, + Elf_Xword addr_align ) override { - stream_size = value; - } - -//------------------------------------------------------------------------------ - Elf_Half - get_index() const - { - return index; - } - -//------------------------------------------------------------------------------ - const char* - get_data() const - { - return data; - } - -//------------------------------------------------------------------------------ - Elf_Half - add_section_index( Elf_Half sec_index, Elf_Xword addr_align ) - { - sections.push_back( sec_index ); + sections.emplace_back( sec_index ); if ( addr_align > get_align() ) { set_align( addr_align ); } @@ -134,108 +116,137 @@ class segment_impl : public segment return (Elf_Half)sections.size(); } -//------------------------------------------------------------------------------ - Elf_Half - get_sections_num() const + //------------------------------------------------------------------------------ + Elf_Half add_section( section* psec, Elf_Xword addr_align ) override + { + return add_section_index( psec->get_index(), addr_align ); + } + + //------------------------------------------------------------------------------ + Elf_Half get_sections_num() const override { return (Elf_Half)sections.size(); } -//------------------------------------------------------------------------------ - Elf_Half - get_section_index_at( Elf_Half num ) const + //------------------------------------------------------------------------------ + Elf_Half get_section_index_at( Elf_Half num ) const override { if ( num < sections.size() ) { return sections[num]; } - return Elf_Half(-1); + return Elf_Half( -1 ); } -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ protected: -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ - void - set_offset( Elf64_Off value ) + //------------------------------------------------------------------------------ + void set_offset( const Elf64_Off& value ) override { - ph.p_offset = value; - ph.p_offset = (*convertor)( ph.p_offset ); + ph.p_offset = decltype( ph.p_offset )( value ); + ph.p_offset = ( *convertor )( ph.p_offset ); is_offset_set = true; } -//------------------------------------------------------------------------------ - bool - is_offset_initialized() const - { - return is_offset_set; - } + //------------------------------------------------------------------------------ + bool is_offset_initialized() const override { return is_offset_set; } -//------------------------------------------------------------------------------ - const std::vector& - get_sections() const + //------------------------------------------------------------------------------ + const std::vector& get_sections() const override { return sections; } - -//------------------------------------------------------------------------------ - void - set_index( Elf_Half value ) + + //------------------------------------------------------------------------------ + void set_index( const Elf_Half& value ) override { index = value; } + + //------------------------------------------------------------------------------ + bool load( std::istream& stream, + std::streampos header_offset, + bool is_lazy_ ) override { - index = value; - } + pstream = &stream; + is_lazy = is_lazy_; -//------------------------------------------------------------------------------ - void - load( std::istream& stream, - std::streampos header_offset ) - { + if ( translator->empty() ) { + stream.seekg( 0, std::istream::end ); + set_stream_size( size_t( stream.tellg() ) ); + } + else { + set_stream_size( std::numeric_limits::max() ); + } - stream.seekg ( 0, stream.end ); - set_stream_size ( stream.tellg() ); - - stream.seekg( header_offset ); + stream.seekg( ( *translator )[header_offset] ); stream.read( reinterpret_cast( &ph ), sizeof( ph ) ); is_offset_set = true; - if ( PT_NULL != get_type() && 0 != get_file_size() ) { - stream.seekg( (*convertor)( ph.p_offset ) ); - Elf_Xword size = get_file_size(); - - if ( size > get_stream_size() ) { - data = 0; - } - else { - data = new char[size + 1]; - - if ( 0 != data ) { - stream.read( data, size ); - data[size] = 0; - } - } + if ( !is_lazy ) { + return load_data(); } + + return true; } -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ + bool load_data() const + { + is_lazy = false; + if ( PT_NULL == get_type() || 0 == get_file_size() ) { + return true; + } + + pstream->seekg( ( *translator )[( *convertor )( ph.p_offset )] ); + Elf_Xword size = get_file_size(); + + if ( size > get_stream_size() ) { + data = nullptr; + } + else { + data.reset( new ( std::nothrow ) char[(size_t)size + 1] ); + + if ( nullptr != data.get() && pstream->read( data.get(), size ) ) { + data.get()[size] = 0; + } + else { + data = nullptr; + return false; + } + } + + return true; + } + + //------------------------------------------------------------------------------ void save( std::ostream& stream, std::streampos header_offset, - std::streampos data_offset ) + std::streampos data_offset ) override { - ph.p_offset = data_offset; - ph.p_offset = (*convertor)(ph.p_offset); - stream.seekp( header_offset ); + ph.p_offset = decltype( ph.p_offset )( data_offset ); + ph.p_offset = ( *convertor )( ph.p_offset ); + adjust_stream_size( stream, header_offset ); stream.write( reinterpret_cast( &ph ), sizeof( ph ) ); } -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ + size_t get_stream_size() const { return stream_size; } + + //------------------------------------------------------------------------------ + void set_stream_size( size_t value ) { stream_size = value; } + + //------------------------------------------------------------------------------ private: - T ph; - Elf_Half index; - char* data; - std::vector sections; - endianess_convertor* convertor; - bool is_offset_set; + mutable std::istream* pstream = nullptr; + T ph = {}; + Elf_Half index = 0; + mutable std::unique_ptr data; + std::vector sections; + const endianess_convertor* convertor = nullptr; + const address_translator* translator = nullptr; + size_t stream_size = 0; + bool is_offset_set = false; + mutable bool is_lazy = false; }; } // namespace ELFIO diff --git a/source/elfio/elfio_strings.hpp b/source/elfio/elfio_strings.hpp index 5fc9bb1..09f5729 100644 --- a/source/elfio/elfio_strings.hpp +++ b/source/elfio/elfio_strings.hpp @@ -1,6 +1,5 @@ -// clang-format off /* -Copyright (C) 2001-2015 by Serge Lamikhov-Center +Copyright (C) 2001-present by Serge Lamikhov-Center Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -31,70 +30,67 @@ THE SOFTWARE. namespace ELFIO { //------------------------------------------------------------------------------ -template< class S > -class string_section_accessor_template +template class string_section_accessor_template { public: -//------------------------------------------------------------------------------ - string_section_accessor_template( S* section_ ) : - string_section( section_ ) + //------------------------------------------------------------------------------ + explicit string_section_accessor_template( S* section ) + : string_section( section ) { } - -//------------------------------------------------------------------------------ - const char* - get_string( Elf_Word index ) const + //------------------------------------------------------------------------------ + const char* get_string( Elf_Word index ) const { if ( string_section ) { - if ( index < string_section->get_size() ) { - const char* data = string_section->get_data(); - if ( 0 != data ) { + const char* data = string_section->get_data(); + if ( index < string_section->get_size() && nullptr != data ) { + size_t string_length = + strnlen( data + index, string_section->get_size() - index ); + if ( string_length < ( string_section->get_size() - index ) ) return data + index; - } } } - return 0; + return nullptr; } - -//------------------------------------------------------------------------------ - Elf_Word - add_string( const char* str ) + //------------------------------------------------------------------------------ + Elf_Word add_string( const char* str ) { Elf_Word current_position = 0; - - if (string_section) { + + if ( string_section ) { // Strings are addeded to the end of the current section data - current_position = (Elf_Word)string_section->get_size(); + current_position = + static_cast( string_section->get_size() ); if ( current_position == 0 ) { char empty_string = '\0'; string_section->append_data( &empty_string, 1 ); current_position++; } - string_section->append_data( str, (Elf_Word)std::strlen( str ) + 1 ); + string_section->append_data( + str, static_cast( std::strlen( str ) + 1 ) ); } return current_position; } - -//------------------------------------------------------------------------------ - Elf_Word - add_string( const std::string& str ) + //------------------------------------------------------------------------------ + Elf_Word add_string( const std::string& str ) { return add_string( str.c_str() ); } -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ private: S* string_section; }; using string_section_accessor = string_section_accessor_template
; -using const_string_section_accessor = string_section_accessor_template; +using const_string_section_accessor = + string_section_accessor_template; } // namespace ELFIO diff --git a/source/elfio/elfio_symbols.hpp b/source/elfio/elfio_symbols.hpp index 6205bd2..d868500 100644 --- a/source/elfio/elfio_symbols.hpp +++ b/source/elfio/elfio_symbols.hpp @@ -1,6 +1,5 @@ -// clang-format off /* -Copyright (C) 2001-2015 by Serge Lamikhov-Center +Copyright (C) 2001-present by Serge Lamikhov-Center Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -27,40 +26,52 @@ THE SOFTWARE. namespace ELFIO { //------------------------------------------------------------------------------ -template< class S > -class symbol_section_accessor_template +template class symbol_section_accessor_template { public: -//------------------------------------------------------------------------------ - symbol_section_accessor_template( const elfio& elf_file_, S* symbol_section_ ) : - elf_file( elf_file_ ), - symbol_section( symbol_section_ ) + //------------------------------------------------------------------------------ + explicit symbol_section_accessor_template( const elfio& elf_file, + S* symbol_section ) + : elf_file( elf_file ), symbol_section( symbol_section ) { find_hash_section(); } -//------------------------------------------------------------------------------ - Elf_Xword - get_symbols_num() const + //------------------------------------------------------------------------------ + Elf_Xword get_symbols_num() const { Elf_Xword nRet = 0; - if ( 0 != symbol_section->get_entry_size() ) { - nRet = symbol_section->get_size() / symbol_section->get_entry_size(); + + size_t minimum_symbol_size; + switch ( elf_file.get_class() ) { + case ELFCLASS32: + minimum_symbol_size = sizeof( Elf32_Sym ); + break; + case ELFCLASS64: + minimum_symbol_size = sizeof( Elf64_Sym ); + break; + default: + return nRet; + } + + if ( symbol_section->get_entry_size() >= minimum_symbol_size && + symbol_section->get_size() <= symbol_section->get_stream_size() ) { + nRet = + symbol_section->get_size() / symbol_section->get_entry_size(); } return nRet; } -//------------------------------------------------------------------------------ - bool - get_symbol( Elf_Xword index, - std::string& name, - Elf64_Addr& value, - Elf_Xword& size, - unsigned char& bind, - unsigned char& type, - Elf_Half& section_index, - unsigned char& other ) const + //------------------------------------------------------------------------------ + bool get_symbol( Elf_Xword index, + std::string& name, + Elf64_Addr& value, + Elf_Xword& size, + unsigned char& bind, + unsigned char& type, + Elf_Half& section_index, + unsigned char& other ) const { bool ret = false; @@ -76,46 +87,96 @@ class symbol_section_accessor_template return ret; } -//------------------------------------------------------------------------------ - bool - get_symbol( const std::string& name, - Elf64_Addr& value, - Elf_Xword& size, - unsigned char& bind, - unsigned char& type, - Elf_Half& section_index, - unsigned char& other ) const + //------------------------------------------------------------------------------ + bool get_symbol( const std::string& name, + Elf64_Addr& value, + Elf_Xword& size, + unsigned char& bind, + unsigned char& type, + Elf_Half& section_index, + unsigned char& other ) const { bool ret = false; if ( 0 != get_hash_table_index() ) { - Elf_Word nbucket = *(const Elf_Word*)hash_section->get_data(); - Elf_Word nchain = *(const Elf_Word*)( hash_section->get_data() + - sizeof( Elf_Word ) ); - Elf_Word val = elf_hash( (const unsigned char*)name.c_str() ); - - Elf_Word y = *(const Elf_Word*)( hash_section->get_data() + - ( 2 + val % nbucket ) * sizeof( Elf_Word ) ); - std::string str; - get_symbol( y, str, value, size, bind, type, section_index, other ); - while ( str != name && STN_UNDEF != y && y < nchain ) { - y = *(const Elf_Word*)( hash_section->get_data() + - ( 2 + nbucket + y ) * sizeof( Elf_Word ) ); - get_symbol( y, str, value, size, bind, type, section_index, other ); + if ( hash_section->get_type() == SHT_HASH ) { + ret = hash_lookup( name, value, size, bind, type, section_index, + other ); } - if ( str == name ) { - ret = true; + if ( hash_section->get_type() == SHT_GNU_HASH || + hash_section->get_type() == DT_GNU_HASH ) { + if ( elf_file.get_class() == ELFCLASS32 ) { + ret = gnu_hash_lookup( + name, value, size, bind, type, section_index, other ); + } + else { + ret = gnu_hash_lookup( + name, value, size, bind, type, section_index, other ); + } + } + } + + if ( !ret ) { + for ( Elf_Xword i = 0; !ret && i < get_symbols_num(); i++ ) { + std::string symbol_name; + if ( get_symbol( i, symbol_name, value, size, bind, type, + section_index, other ) ) { + if ( symbol_name == name ) { + ret = true; + } + } } } return ret; } -//------------------------------------------------------------------------------ - Elf_Word - add_symbol( Elf_Word name, Elf64_Addr value, Elf_Xword size, - unsigned char info, unsigned char other, - Elf_Half shndx ) + //------------------------------------------------------------------------------ + bool get_symbol( const Elf64_Addr& value, + std::string& name, + Elf_Xword& size, + unsigned char& bind, + unsigned char& type, + Elf_Half& section_index, + unsigned char& other ) const + { + + const endianess_convertor& convertor = elf_file.get_convertor(); + + Elf_Xword idx = 0; + bool match = false; + Elf64_Addr v = 0; + + if ( elf_file.get_class() == ELFCLASS32 ) { + match = generic_search_symbols( + [&]( const Elf32_Sym* sym ) { + return convertor( sym->st_value ) == value; + }, + idx ); + } + else { + match = generic_search_symbols( + [&]( const Elf64_Sym* sym ) { + return convertor( sym->st_value ) == value; + }, + idx ); + } + + if ( match ) { + return get_symbol( idx, name, v, size, bind, type, section_index, + other ); + } + + return false; + } + + //------------------------------------------------------------------------------ + Elf_Word add_symbol( Elf_Word name, + Elf64_Addr value, + Elf_Xword size, + unsigned char info, + unsigned char other, + Elf_Half shndx ) { Elf_Word nRet; @@ -129,110 +190,276 @@ class symbol_section_accessor_template } if ( elf_file.get_class() == ELFCLASS32 ) { - nRet = generic_add_symbol( name, value, size, info, other, - shndx ); + nRet = generic_add_symbol( name, value, size, info, + other, shndx ); } else { - nRet = generic_add_symbol( name, value, size, info, other, - shndx ); + nRet = generic_add_symbol( name, value, size, info, + other, shndx ); } return nRet; } -//------------------------------------------------------------------------------ - Elf_Word - add_symbol( Elf_Word name, Elf64_Addr value, Elf_Xword size, - unsigned char bind, unsigned char type, unsigned char other, - Elf_Half shndx ) + //------------------------------------------------------------------------------ + Elf_Word add_symbol( Elf_Word name, + Elf64_Addr value, + Elf_Xword size, + unsigned char bind, + unsigned char type, + unsigned char other, + Elf_Half shndx ) { - return add_symbol( name, value, size, ELF_ST_INFO( bind, type ), other, shndx ); + return add_symbol( name, value, size, ELF_ST_INFO( bind, type ), other, + shndx ); } -//------------------------------------------------------------------------------ - Elf_Word - add_symbol( string_section_accessor& pStrWriter, const char* str, - Elf64_Addr value, Elf_Xword size, - unsigned char info, unsigned char other, - Elf_Half shndx ) + //------------------------------------------------------------------------------ + Elf_Word add_symbol( string_section_accessor& pStrWriter, + const char* str, + Elf64_Addr value, + Elf_Xword size, + unsigned char info, + unsigned char other, + Elf_Half shndx ) { Elf_Word index = pStrWriter.add_string( str ); return add_symbol( index, value, size, info, other, shndx ); } -//------------------------------------------------------------------------------ - Elf_Word - add_symbol( string_section_accessor& pStrWriter, const char* str, - Elf64_Addr value, Elf_Xword size, - unsigned char bind, unsigned char type, unsigned char other, - Elf_Half shndx ) + //------------------------------------------------------------------------------ + Elf_Word add_symbol( string_section_accessor& pStrWriter, + const char* str, + Elf64_Addr value, + Elf_Xword size, + unsigned char bind, + unsigned char type, + unsigned char other, + Elf_Half shndx ) { - return add_symbol( pStrWriter, str, value, size, ELF_ST_INFO( bind, type ), other, shndx ); + return add_symbol( pStrWriter, str, value, size, + ELF_ST_INFO( bind, type ), other, shndx ); } -//------------------------------------------------------------------------------ - private: -//------------------------------------------------------------------------------ - void - find_hash_section() + //------------------------------------------------------------------------------ + Elf_Xword arrange_local_symbols( + std::function func = + nullptr ) + { + Elf_Xword nRet = 0; + + if ( elf_file.get_class() == ELFCLASS32 ) { + nRet = generic_arrange_local_symbols( func ); + } + else { + nRet = generic_arrange_local_symbols( func ); + } + + return nRet; + } + + //------------------------------------------------------------------------------ + private: + //------------------------------------------------------------------------------ + void find_hash_section() { - hash_section = 0; - hash_section_index = 0; Elf_Half nSecNo = elf_file.sections.size(); - for ( Elf_Half i = 0; i < nSecNo && 0 == hash_section_index; ++i ) { + for ( Elf_Half i = 0; i < nSecNo; ++i ) { const section* sec = elf_file.sections[i]; - if ( sec->get_link() == symbol_section->get_index() ) { + if ( sec->get_link() == symbol_section->get_index() && + ( sec->get_type() == SHT_HASH || + sec->get_type() == SHT_GNU_HASH || + sec->get_type() == DT_GNU_HASH ) ) { hash_section = sec; hash_section_index = i; + break; } } } -//------------------------------------------------------------------------------ - Elf_Half - get_string_table_index() const + //------------------------------------------------------------------------------ + Elf_Half get_string_table_index() const { return (Elf_Half)symbol_section->get_link(); } -//------------------------------------------------------------------------------ - Elf_Half - get_hash_table_index() const + //------------------------------------------------------------------------------ + Elf_Half get_hash_table_index() const { return hash_section_index; } + + //------------------------------------------------------------------------------ + bool hash_lookup( const std::string& name, + Elf64_Addr& value, + Elf_Xword& size, + unsigned char& bind, + unsigned char& type, + Elf_Half& section_index, + unsigned char& other ) const { - return hash_section_index; + bool ret = false; + const endianess_convertor& convertor = elf_file.get_convertor(); + + Elf_Word nbucket = *(const Elf_Word*)hash_section->get_data(); + nbucket = convertor( nbucket ); + Elf_Word nchain = + *(const Elf_Word*)( hash_section->get_data() + sizeof( Elf_Word ) ); + nchain = convertor( nchain ); + Elf_Word val = elf_hash( (const unsigned char*)name.c_str() ); + Elf_Word y = + *(const Elf_Word*)( hash_section->get_data() + + ( 2 + val % nbucket ) * sizeof( Elf_Word ) ); + y = convertor( y ); + std::string str; + get_symbol( y, str, value, size, bind, type, section_index, other ); + while ( str != name && STN_UNDEF != y && y < nchain ) { + y = *(const Elf_Word*)( hash_section->get_data() + + ( 2 + nbucket + y ) * sizeof( Elf_Word ) ); + y = convertor( y ); + get_symbol( y, str, value, size, bind, type, section_index, other ); + } + + if ( str == name ) { + ret = true; + } + + return ret; } -//------------------------------------------------------------------------------ - template< class T > - bool - generic_get_symbol( Elf_Xword index, - std::string& name, Elf64_Addr& value, - Elf_Xword& size, - unsigned char& bind, unsigned char& type, - Elf_Half& section_index, - unsigned char& other ) const + //------------------------------------------------------------------------------ + template + bool gnu_hash_lookup( const std::string& name, + Elf64_Addr& value, + Elf_Xword& size, + unsigned char& bind, + unsigned char& type, + Elf_Half& section_index, + unsigned char& other ) const + { + bool ret = false; + const endianess_convertor& convertor = elf_file.get_convertor(); + + uint32_t nbuckets = *( (uint32_t*)hash_section->get_data() + 0 ); + uint32_t symoffset = *( (uint32_t*)hash_section->get_data() + 1 ); + uint32_t bloom_size = *( (uint32_t*)hash_section->get_data() + 2 ); + uint32_t bloom_shift = *( (uint32_t*)hash_section->get_data() + 3 ); + nbuckets = convertor( nbuckets ); + symoffset = convertor( symoffset ); + bloom_size = convertor( bloom_size ); + bloom_shift = convertor( bloom_shift ); + + T* bloom_filter = + (T*)( hash_section->get_data() + 4 * sizeof( uint32_t ) ); + + uint32_t hash = elf_gnu_hash( (const unsigned char*)name.c_str() ); + uint32_t bloom_index = ( hash / ( 8 * sizeof( T ) ) ) % bloom_size; + T bloom_bits = + ( (T)1 << ( hash % ( 8 * sizeof( T ) ) ) ) | + ( (T)1 << ( ( hash >> bloom_shift ) % ( 8 * sizeof( T ) ) ) ); + + if ( ( convertor( bloom_filter[bloom_index] ) & bloom_bits ) != + bloom_bits ) + return ret; + + uint32_t bucket = hash % nbuckets; + auto* buckets = + (uint32_t*)( hash_section->get_data() + 4 * sizeof( uint32_t ) + + bloom_size * sizeof( T ) ); + auto* chains = + (uint32_t*)( hash_section->get_data() + 4 * sizeof( uint32_t ) + + bloom_size * sizeof( T ) + + nbuckets * sizeof( uint32_t ) ); + + if ( convertor( buckets[bucket] ) >= symoffset ) { + uint32_t chain_index = convertor( buckets[bucket] ) - symoffset; + uint32_t chain_hash = convertor( chains[chain_index] ); + std::string symname; + + while ( true ) { + if ( ( chain_hash >> 1 ) == ( hash >> 1 ) && + get_symbol( chain_index + symoffset, symname, value, size, + bind, type, section_index, other ) && + name == symname ) { + ret = true; + break; + } + + if ( chain_hash & 1 ) + break; + chain_hash = convertor( chains[++chain_index] ); + } + } + + return ret; + } + + //------------------------------------------------------------------------------ + template const T* generic_get_symbol_ptr( Elf_Xword index ) const + { + if ( 0 != symbol_section->get_data() && index < get_symbols_num() ) { + const T* pSym = reinterpret_cast( + symbol_section->get_data() + + index * symbol_section->get_entry_size() ); + + return pSym; + } + + return nullptr; + } + + //------------------------------------------------------------------------------ + template + bool generic_search_symbols( std::function match, + Elf_Xword& idx ) const + { + for ( Elf_Xword i = 0; i < get_symbols_num(); i++ ) { + const T* symPtr = generic_get_symbol_ptr( i ); + + if ( symPtr == nullptr ) + return false; + + if ( match( symPtr ) ) { + idx = i; + return true; + } + } + + return false; + } + + //------------------------------------------------------------------------------ + template + bool generic_get_symbol( Elf_Xword index, + std::string& name, + Elf64_Addr& value, + Elf_Xword& size, + unsigned char& bind, + unsigned char& type, + Elf_Half& section_index, + unsigned char& other ) const { bool ret = false; - if ( index < get_symbols_num() ) { + if ( nullptr != symbol_section->get_data() && + index < get_symbols_num() ) { const T* pSym = reinterpret_cast( symbol_section->get_data() + - index * symbol_section->get_entry_size() ); + index * symbol_section->get_entry_size() ); const endianess_convertor& convertor = elf_file.get_convertor(); - section* string_section = elf_file.sections[get_string_table_index()]; + section* string_section = + elf_file.sections[get_string_table_index()]; string_section_accessor str_reader( string_section ); - const char* pStr = str_reader.get_string( convertor( pSym->st_name ) ); - if ( 0 != pStr ) { + const char* pStr = + str_reader.get_string( convertor( pSym->st_name ) ); + if ( nullptr != pStr ) { name = pStr; } - value = convertor( pSym->st_value ); - size = convertor( pSym->st_size ); - bind = ELF_ST_BIND( pSym->st_info ); - type = ELF_ST_TYPE( pSym->st_info ); + value = convertor( pSym->st_value ); + size = convertor( pSym->st_size ); + bind = ELF_ST_BIND( pSym->st_info ); + type = ELF_ST_TYPE( pSym->st_info ); section_index = convertor( pSym->st_shndx ); - other = pSym->st_other; + other = pSym->st_other; ret = true; } @@ -240,20 +467,22 @@ class symbol_section_accessor_template return ret; } -//------------------------------------------------------------------------------ - template< class T > - Elf_Word - generic_add_symbol( Elf_Word name, Elf64_Addr value, Elf_Xword size, - unsigned char info, unsigned char other, - Elf_Half shndx ) + //------------------------------------------------------------------------------ + template + Elf_Word generic_add_symbol( Elf_Word name, + Elf64_Addr value, + Elf_Xword size, + unsigned char info, + unsigned char other, + Elf_Half shndx ) { const endianess_convertor& convertor = elf_file.get_convertor(); T entry; entry.st_name = convertor( name ); - entry.st_value = value; + entry.st_value = decltype( entry.st_value )( value ); entry.st_value = convertor( entry.st_value ); - entry.st_size = size; + entry.st_size = decltype( entry.st_size )( size ); entry.st_size = convertor( entry.st_size ); entry.st_info = convertor( info ); entry.st_other = convertor( other ); @@ -262,21 +491,71 @@ class symbol_section_accessor_template symbol_section->append_data( reinterpret_cast( &entry ), sizeof( entry ) ); - Elf_Word nRet = symbol_section->get_size() / sizeof( entry ) - 1; + Elf_Word nRet = + Elf_Word( symbol_section->get_size() / sizeof( entry ) - 1 ); return nRet; } -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ + template + Elf_Xword generic_arrange_local_symbols( + std::function func ) + { + const endianess_convertor& convertor = elf_file.get_convertor(); + + Elf_Word first_not_local = + 1; // Skip the first entry. It is always NOTYPE + Elf_Xword current = 0; + Elf_Xword count = get_symbols_num(); + + while ( true ) { + T* p1 = nullptr; + T* p2 = nullptr; + + while ( first_not_local < count ) { + p1 = const_cast( + generic_get_symbol_ptr( first_not_local ) ); + if ( ELF_ST_BIND( convertor( p1->st_info ) ) != STB_LOCAL ) + break; + ++first_not_local; + } + + current = first_not_local + 1; + while ( current < count ) { + p2 = const_cast( generic_get_symbol_ptr( current ) ); + if ( ELF_ST_BIND( convertor( p2->st_info ) ) == STB_LOCAL ) + break; + ++current; + } + + if ( first_not_local < count && current < count ) { + if ( func ) + func( first_not_local, current ); + + std::swap( *p1, *p2 ); + } + else { + // Update 'info' field of the section + symbol_section->set_info( first_not_local ); + break; + } + } + + return first_not_local; + } + + //------------------------------------------------------------------------------ private: const elfio& elf_file; S* symbol_section; - Elf_Half hash_section_index; - const section* hash_section; + Elf_Half hash_section_index{ 0 }; + const section* hash_section{ nullptr }; }; using symbol_section_accessor = symbol_section_accessor_template
; -using const_symbol_section_accessor = symbol_section_accessor_template; +using const_symbol_section_accessor = + symbol_section_accessor_template; } // namespace ELFIO diff --git a/source/elfio/elfio_utils.hpp b/source/elfio/elfio_utils.hpp index e567d41..1e99960 100644 --- a/source/elfio/elfio_utils.hpp +++ b/source/elfio/elfio_utils.hpp @@ -1,6 +1,5 @@ -// clang-format off /* -Copyright (C) 2001-2015 by Serge Lamikhov-Center +Copyright (C) 2001-present by Serge Lamikhov-Center Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -24,158 +23,130 @@ THE SOFTWARE. #ifndef ELFIO_UTILS_HPP #define ELFIO_UTILS_HPP -#define ELFIO_GET_ACCESS( TYPE, NAME, FIELD ) \ - TYPE get_##NAME() const \ - { \ - return (*convertor)( FIELD ); \ - } -#define ELFIO_SET_ACCESS( TYPE, NAME, FIELD ) \ - void set_##NAME( TYPE value ) \ - { \ - FIELD = value; \ - FIELD = (*convertor)( FIELD ); \ - } -#define ELFIO_GET_SET_ACCESS( TYPE, NAME, FIELD ) \ - TYPE get_##NAME() const \ - { \ - return (*convertor)( FIELD ); \ - } \ - void set_##NAME( TYPE value ) \ - { \ - FIELD = value; \ - FIELD = (*convertor)( FIELD ); \ - } +#include +#include -#define ELFIO_GET_ACCESS_DECL( TYPE, NAME ) \ - virtual TYPE get_##NAME() const = 0 +#define ELFIO_GET_ACCESS_DECL( TYPE, NAME ) virtual TYPE get_##NAME() const = 0 #define ELFIO_SET_ACCESS_DECL( TYPE, NAME ) \ - virtual void set_##NAME( TYPE value ) = 0 + virtual void set_##NAME( const TYPE& value ) = 0 -#define ELFIO_GET_SET_ACCESS_DECL( TYPE, NAME ) \ - virtual TYPE get_##NAME() const = 0; \ - virtual void set_##NAME( TYPE value ) = 0 +#define ELFIO_GET_SET_ACCESS_DECL( TYPE, NAME ) \ + virtual TYPE get_##NAME() const = 0; \ + virtual void set_##NAME( const TYPE& value ) = 0 + +#define ELFIO_GET_ACCESS( TYPE, NAME, FIELD ) \ + TYPE get_##NAME() const override { return ( *convertor )( FIELD ); } + +#define ELFIO_SET_ACCESS( TYPE, NAME, FIELD ) \ + void set_##NAME( const TYPE& value ) override \ + { \ + FIELD = decltype( FIELD )( value ); \ + FIELD = ( *convertor )( FIELD ); \ + } +#define ELFIO_GET_SET_ACCESS( TYPE, NAME, FIELD ) \ + TYPE get_##NAME() const override { return ( *convertor )( FIELD ); } \ + void set_##NAME( const TYPE& value ) override \ + { \ + FIELD = decltype( FIELD )( value ); \ + FIELD = ( *convertor )( FIELD ); \ + } namespace ELFIO { //------------------------------------------------------------------------------ -class endianess_convertor { +class endianess_convertor +{ public: -//------------------------------------------------------------------------------ - endianess_convertor() - { - need_conversion = false; - } - -//------------------------------------------------------------------------------ - void - setup( unsigned char elf_file_encoding ) + //------------------------------------------------------------------------------ + void setup( unsigned char elf_file_encoding ) { need_conversion = ( elf_file_encoding != get_host_encoding() ); } -//------------------------------------------------------------------------------ - uint64_t - operator()( uint64_t value ) const + //------------------------------------------------------------------------------ + uint64_t operator()( uint64_t value ) const + { + if ( !need_conversion ) { + return value; + } + value = ( ( value & 0x00000000000000FFuLL ) << 56 ) | + ( ( value & 0x000000000000FF00uLL ) << 40 ) | + ( ( value & 0x0000000000FF0000uLL ) << 24 ) | + ( ( value & 0x00000000FF000000uLL ) << 8 ) | + ( ( value & 0x000000FF00000000uLL ) >> 8 ) | + ( ( value & 0x0000FF0000000000uLL ) >> 24 ) | + ( ( value & 0x00FF000000000000uLL ) >> 40 ) | + ( ( value & 0xFF00000000000000uLL ) >> 56 ); + + return value; + } + + //------------------------------------------------------------------------------ + int64_t operator()( int64_t value ) const + { + if ( !need_conversion ) { + return value; + } + return (int64_t)( *this )( (uint64_t)value ); + } + + //------------------------------------------------------------------------------ + uint32_t operator()( uint32_t value ) const { if ( !need_conversion ) { return value; } value = - ( ( value & 0x00000000000000FFull ) << 56 ) | - ( ( value & 0x000000000000FF00ull ) << 40 ) | - ( ( value & 0x0000000000FF0000ull ) << 24 ) | - ( ( value & 0x00000000FF000000ull ) << 8 ) | - ( ( value & 0x000000FF00000000ull ) >> 8 ) | - ( ( value & 0x0000FF0000000000ull ) >> 24 ) | - ( ( value & 0x00FF000000000000ull ) >> 40 ) | - ( ( value & 0xFF00000000000000ull ) >> 56 ); + ( ( value & 0x000000FF ) << 24 ) | ( ( value & 0x0000FF00 ) << 8 ) | + ( ( value & 0x00FF0000 ) >> 8 ) | ( ( value & 0xFF000000 ) >> 24 ); return value; } -//------------------------------------------------------------------------------ - int64_t - operator()( int64_t value ) const + //------------------------------------------------------------------------------ + int32_t operator()( int32_t value ) const { if ( !need_conversion ) { return value; } - return (int64_t)(*this)( (uint64_t)value ); + return (int32_t)( *this )( (uint32_t)value ); } -//------------------------------------------------------------------------------ - uint32_t - operator()( uint32_t value ) const + //------------------------------------------------------------------------------ + uint16_t operator()( uint16_t value ) const { if ( !need_conversion ) { return value; } value = - ( ( value & 0x000000FF ) << 24 ) | - ( ( value & 0x0000FF00 ) << 8 ) | - ( ( value & 0x00FF0000 ) >> 8 ) | - ( ( value & 0xFF000000 ) >> 24 ); + (uint16_t)( ( value & 0x00FF ) << 8 ) | ( ( value & 0xFF00 ) >> 8 ); return value; } -//------------------------------------------------------------------------------ - int32_t - operator()( int32_t value ) const + //------------------------------------------------------------------------------ + int16_t operator()( int16_t value ) const { if ( !need_conversion ) { return value; } - return (int32_t)(*this)( (uint32_t)value ); + return (int16_t)( *this )( (uint16_t)value ); } -//------------------------------------------------------------------------------ - uint16_t - operator()( uint16_t value ) const - { - if ( !need_conversion ) { - return value; - } - value = - ( ( value & 0x00FF ) << 8 ) | - ( ( value & 0xFF00 ) >> 8 ); + //------------------------------------------------------------------------------ + int8_t operator()( int8_t value ) const { return value; } - return value; - } + //------------------------------------------------------------------------------ + uint8_t operator()( uint8_t value ) const { return value; } -//------------------------------------------------------------------------------ - int16_t - operator()( int16_t value ) const - { - if ( !need_conversion ) { - return value; - } - return (int16_t)(*this)( (uint16_t)value ); - } - -//------------------------------------------------------------------------------ - int8_t - operator()( int8_t value ) const - { - return value; - } - -//------------------------------------------------------------------------------ - uint8_t - operator()( uint8_t value ) const - { - return value; - } - -//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ private: -//------------------------------------------------------------------------------ - unsigned char - get_host_encoding() const + //------------------------------------------------------------------------------ + unsigned char get_host_encoding() const { static const int tmp = 1; - if ( 1 == *(const char*)&tmp ) { + if ( 1 == *reinterpret_cast( &tmp ) ) { return ELFDATA2LSB; } else { @@ -183,20 +154,65 @@ class endianess_convertor { } } -//------------------------------------------------------------------------------ - private: - bool need_conversion; + //------------------------------------------------------------------------------ + bool need_conversion = false; }; +//------------------------------------------------------------------------------ +struct address_translation +{ + address_translation( uint64_t start, uint64_t size, uint64_t mapped_to ) + : start( start ), size( size ), mapped_to( mapped_to ){}; + std::streampos start; + std::streampos size; + std::streampos mapped_to; +}; //------------------------------------------------------------------------------ -inline -uint32_t -elf_hash( const unsigned char *name ) +class address_translator { - uint32_t h = 0, g; - while ( *name ) { - h = (h << 4) + *name++; + public: + //------------------------------------------------------------------------------ + void set_address_translation( std::vector& addr_trans ) + { + addr_translations = addr_trans; + + std::sort( + addr_translations.begin(), addr_translations.end(), + []( address_translation& a, address_translation& b ) -> bool { + return a.start < b.start; + } ); + } + + //------------------------------------------------------------------------------ + std::streampos operator[]( std::streampos value ) const + { + if ( addr_translations.empty() ) { + return value; + } + + for ( auto& t : addr_translations ) { + if ( ( t.start <= value ) && ( ( value - t.start ) < t.size ) ) { + return value - t.start + t.mapped_to; + } + } + + return value; + } + + bool empty() const { return addr_translations.empty(); } + + private: + std::vector addr_translations; +}; + +//------------------------------------------------------------------------------ +inline uint32_t elf_hash( const unsigned char* name ) +{ + uint32_t h = 0; + uint32_t g = 0; + while ( *name != '\0' ) { + h = ( h << 4 ) + *name++; g = h & 0xf0000000; if ( g != 0 ) h ^= g >> 24; @@ -205,6 +221,83 @@ elf_hash( const unsigned char *name ) return h; } +//------------------------------------------------------------------------------ +inline uint32_t elf_gnu_hash( const unsigned char* s ) +{ + uint32_t h = 0x1505; + for ( unsigned char c = *s; c != '\0'; c = *++s ) + h = ( h << 5 ) + h + c; + return h; +} + +//------------------------------------------------------------------------------ +inline std::string to_hex_string( uint64_t value ) +{ + std::string str; + + while ( value ) { + auto digit = value & 0xF; + if ( digit < 0xA ) { + str = char( '0' + digit ) + str; + } + else { + str = char( 'A' + digit - 0xA ) + str; + } + value >>= 4; + } + + return "0x" + str; +} + +//------------------------------------------------------------------------------ +inline void adjust_stream_size( std::ostream& stream, std::streamsize offset ) +{ + stream.seekp( 0, std::ios_base::end ); + if ( stream.tellp() < offset ) { + std::streamsize size = offset - stream.tellp(); + stream.write( std::string( size_t( size ), '\0' ).c_str(), size ); + } + stream.seekp( offset ); +} + +/** + * Consumers should write an implementation of this class and pass an instance of it to the ELFIO::elfio constructor. + */ +class compression_interface +{ + public: + virtual ~compression_interface() = default; + /** + * decompresses a compressed section + * + * @param data the buffer of compressed data + * @param endianness_convertor pointer to an endianness_convertor instance, used to convert numbers to/from the target endianness. + * @param compressed_size the size of the data buffer, in bytes + * @param decompressed_size a reference to a variable where the decompressed buffer size will be stored. + * @returns a smart pointer to the decompressed data. + */ + virtual std::unique_ptr + inflate( const char* data, + const endianess_convertor* convertor, + Elf_Xword compressed_size, + Elf_Xword& uncompressed_size ) const = 0; + + /** + * compresses a section + * + * @param data the buffer of uncompressed data + * @param endianness_convertor pointer to an endianness_convertor instance, used to convert numbers to/from the target endianness. + * @param decompressed_size the size of the data buffer, in bytes + * @param compressed_size a reference to a variable where the compressed buffer size will be stored. + * @returns a smart pointer to the compressed data. + */ + virtual std::unique_ptr + deflate( const char* data, + const endianess_convertor* convertor, + Elf_Xword decompressed_size, + Elf_Xword& compressed_size ) const = 0; +}; + } // namespace ELFIO #endif // ELFIO_UTILS_HPP diff --git a/source/elfio/elfio_version.hpp b/source/elfio/elfio_version.hpp new file mode 100644 index 0000000..5b62d0d --- /dev/null +++ b/source/elfio/elfio_version.hpp @@ -0,0 +1 @@ +#define ELFIO_VERSION "3.12" diff --git a/source/elfio/elfio_versym.hpp b/source/elfio/elfio_versym.hpp new file mode 100644 index 0000000..9971caf --- /dev/null +++ b/source/elfio/elfio_versym.hpp @@ -0,0 +1,179 @@ +/* +Copyright (C) 2001-present by Serge Lamikhov-Center + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#ifndef ELFIO_VERSYM_HPP +#define ELFIO_VERSYM_HPP + +namespace ELFIO { + +//------------------------------------------------------------------------------ +template class versym_section_accessor_template +{ + public: + //------------------------------------------------------------------------------ + explicit versym_section_accessor_template( S* section ) + : versym_section( section ) + { + if ( section != nullptr ) { + entries_num = decltype( entries_num )( section->get_size() / + sizeof( Elf_Half ) ); + } + } + + //------------------------------------------------------------------------------ + Elf_Word get_entries_num() const + { + if ( versym_section ) { + return entries_num; + } + return 0; + } + + //------------------------------------------------------------------------------ + bool get_entry( Elf_Word no, Elf_Half& value ) const + { + if ( versym_section && ( no < get_entries_num() ) ) { + value = ( (Elf_Half*)versym_section->get_data() )[no]; + return true; + } + + return false; + } + + //------------------------------------------------------------------------------ + bool modify_entry( Elf_Word no, Elf_Half value ) + { + if ( versym_section && ( no < get_entries_num() ) ) { + ( (Elf_Half*)versym_section->get_data() )[no] = value; + return true; + } + + return false; + } + + //------------------------------------------------------------------------------ + bool add_entry( Elf_Half value ) + { + if ( !versym_section ) { + return false; + } + + versym_section->append_data( (const char*)&value, sizeof( Elf_Half ) ); + ++entries_num; + + return true; + } + + //------------------------------------------------------------------------------ + private: + S* versym_section = nullptr; + Elf_Word entries_num = 0; +}; + +using versym_section_accessor = versym_section_accessor_template
; +using const_versym_section_accessor = + versym_section_accessor_template; + +//------------------------------------------------------------------------------ +template class versym_r_section_accessor_template +{ + public: + //------------------------------------------------------------------------------ + versym_r_section_accessor_template( const elfio& elf_file, + S* versym_r_section ) + : elf_file( elf_file ), versym_r_section( versym_r_section ), + entries_num( 0 ) + { + // Find .dynamic section + const section* dynamic_section = elf_file.sections[".dynamic"]; + + if ( dynamic_section == nullptr ) { + return; + } + + const_dynamic_section_accessor dynamic_section_acc( elf_file, + dynamic_section ); + Elf_Xword dyn_sec_num = dynamic_section_acc.get_entries_num(); + for ( Elf_Xword i = 0; i < dyn_sec_num; ++i ) { + Elf_Xword tag; + Elf_Xword value; + std::string str; + + if ( dynamic_section_acc.get_entry( i, tag, value, str ) && + tag == DT_VERNEEDNUM ) { + entries_num = (Elf_Word)value; + break; + } + } + } + + //------------------------------------------------------------------------------ + Elf_Word get_entries_num() const { return entries_num; } + + //------------------------------------------------------------------------------ + bool get_entry( Elf_Word no, + Elf_Half& version, + std::string& file_name, + Elf_Word& hash, + Elf_Half& flags, + Elf_Half& other, + std::string& dep_name ) const + { + if ( versym_r_section == nullptr || ( no >= get_entries_num() ) ) { + return false; + } + + const_string_section_accessor string_section_acc( + elf_file.sections[versym_r_section->get_link()] ); + + Elfxx_Verneed* verneed = (Elfxx_Verneed*)versym_r_section->get_data(); + Elfxx_Vernaux* veraux = + (Elfxx_Vernaux*)( (char*)verneed + verneed->vn_aux ); + for ( Elf_Word i = 0; i < no; ++i ) { + verneed = (Elfxx_Verneed*)( (char*)verneed + verneed->vn_next ); + veraux = (Elfxx_Vernaux*)( (char*)verneed + verneed->vn_aux ); + } + + version = verneed->vn_version; + file_name = string_section_acc.get_string( verneed->vn_file ); + hash = veraux->vna_hash; + flags = veraux->vna_flags; + other = veraux->vna_other; + dep_name = string_section_acc.get_string( veraux->vna_name ); + + return true; + } + + //------------------------------------------------------------------------------ + private: + const elfio& elf_file; + S* versym_r_section = nullptr; + Elf_Word entries_num = 0; +}; + +using versym_r_section_accessor = versym_r_section_accessor_template
; +using const_versym_r_section_accessor = + versym_r_section_accessor_template; + +} // namespace ELFIO + +#endif // ELFIO_VERSYM_HPP diff --git a/source/plugin/PluginInformationFactory.cpp b/source/plugin/PluginInformationFactory.cpp index 8b6fa86..5cb998c 100644 --- a/source/plugin/PluginInformationFactory.cpp +++ b/source/plugin/PluginInformationFactory.cpp @@ -18,6 +18,8 @@ #include "PluginInformationFactory.h" #include "../utils/ElfUtils.h" #include "../utils/utils.h" +#include "utils/membuf.hpp" +#include "utils/wiiu_zlib.hpp" #include #include #include @@ -33,8 +35,11 @@ PluginInformationFactory::load(const std::shared_ptr &pluginData, re DEBUG_FUNCTION_LINE_ERR("Buffer was nullptr"); return {}; } - elfio reader; - if (!reader.load((char *) pluginData->buffer.get(), pluginData->length)) { + elfio reader(new wiiu_zlib); + membuf sbuf((char *) pluginData->buffer.get(), (char *) pluginData->buffer.get() + pluginData->length); + std::istream in(&sbuf); + + if (!reader.load(in)) { DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio"); return {}; } @@ -302,17 +307,31 @@ bool PluginInformationFactory::addImportRelocationData(const std::unique_ptrget_name().c_str()); relocation_section_accessor rel(reader, psec); for (uint32_t j = 0; j < (uint32_t) rel.get_entries_num(); ++j) { + Elf_Word symbol = 0; Elf64_Addr offset; Elf_Word type; Elf_Sxword addend; std::string sym_name; Elf64_Addr sym_value; - Elf_Half sym_section_index; - if (!rel.get_entry(j, offset, sym_value, sym_name, type, addend, sym_section_index)) { + if (!rel.get_entry(j, offset, symbol, type, addend)) { DEBUG_FUNCTION_LINE_ERR("Failed to get relocation"); return false; } + symbol_section_accessor symbols(reader, reader.sections[(Elf_Half) psec->get_link()]); + + // Find the symbol + Elf_Xword size; + unsigned char bind; + unsigned char symbolType; + Elf_Half sym_section_index; + unsigned char other; + + if (!symbols.get_symbol(symbol, sym_name, sym_value, size, + bind, symbolType, sym_section_index, other)) { + DEBUG_FUNCTION_LINE_ERR("Failed to get symbol"); + return false; + } auto adjusted_sym_value = (uint32_t) sym_value; if (adjusted_sym_value < 0xC0000000) { @@ -354,16 +373,30 @@ bool PluginInformationFactory::linkSection(const elfio &reader, uint32_t section DEBUG_FUNCTION_LINE_VERBOSE("Found relocation section %s", psec->get_name().c_str()); relocation_section_accessor rel(reader, psec); for (uint32_t j = 0; j < (uint32_t) rel.get_entries_num(); ++j) { + Elf_Word symbol = 0; Elf64_Addr offset; Elf_Word type; Elf_Sxword addend; std::string sym_name; Elf64_Addr sym_value; - Elf_Half sym_section_index; - if (!rel.get_entry(j, offset, sym_value, sym_name, type, addend, sym_section_index)) { + if (!rel.get_entry(j, offset, symbol, type, addend)) { DEBUG_FUNCTION_LINE_ERR("Failed to get relocation"); - break; + return false; + } + symbol_section_accessor symbols(reader, reader.sections[(Elf_Half) psec->get_link()]); + + // Find the symbol + Elf_Xword size; + unsigned char bind; + unsigned char symbolType; + Elf_Half sym_section_index; + unsigned char other; + + if (!symbols.get_symbol(symbol, sym_name, sym_value, size, + bind, symbolType, sym_section_index, other)) { + DEBUG_FUNCTION_LINE_ERR("Failed to get symbol"); + return false; } auto adjusted_sym_value = (uint32_t) sym_value; diff --git a/source/plugin/PluginMetaInformationFactory.cpp b/source/plugin/PluginMetaInformationFactory.cpp index 054431e..d595554 100644 --- a/source/plugin/PluginMetaInformationFactory.cpp +++ b/source/plugin/PluginMetaInformationFactory.cpp @@ -18,6 +18,9 @@ #include "PluginMetaInformationFactory.h" #include "elfio/elfio.hpp" #include "fs/FSUtils.h" +#include "utils/logger.h" +#include "utils/membuf.hpp" +#include "utils/wiiu_zlib.hpp" #include std::optional> PluginMetaInformationFactory::loadPlugin(const std::shared_ptr &pluginData) { @@ -25,8 +28,10 @@ std::optional> PluginMetaInformationFacto DEBUG_FUNCTION_LINE_ERR("Buffer is empty"); return {}; } - ELFIO::elfio reader; - if (!reader.load((char *) pluginData->buffer.get(), pluginData->length)) { + ELFIO::elfio reader(new wiiu_zlib); + membuf sbuf((char *) pluginData->buffer.get(), (char *) pluginData->buffer.get() + pluginData->length); + std::istream in(&sbuf); + if (!reader.load(in)) { DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio"); return {}; } @@ -34,7 +39,7 @@ std::optional> PluginMetaInformationFacto } std::optional> PluginMetaInformationFactory::loadPlugin(const std::string &filePath) { - ELFIO::elfio reader; + ELFIO::elfio reader(new wiiu_zlib); uint8_t *buffer = nullptr; uint32_t length = 0; @@ -43,7 +48,10 @@ std::optional> PluginMetaInformationFacto return {}; } - if (!reader.load((char *) buffer, length)) { + membuf sbuf((char *) buffer, (char *) buffer + length); + std::istream in(&sbuf); + + if (!reader.load(in)) { DEBUG_FUNCTION_LINE_ERR("Can't process PluginData in elfio"); return {}; } @@ -53,8 +61,12 @@ std::optional> PluginMetaInformationFacto } std::optional> PluginMetaInformationFactory::loadPlugin(char *buffer, size_t size) { - ELFIO::elfio reader; - if (!reader.load(buffer, size)) { + ELFIO::elfio reader(new wiiu_zlib); + + membuf sbuf((char *) buffer, (char *) buffer + size); + std::istream in(&sbuf); + + if (!reader.load(in)) { DEBUG_FUNCTION_LINE_ERR("Can't find or process ELF file"); return std::nullopt; } @@ -73,7 +85,7 @@ std::optional> PluginMetaInformationFacto ELFIO::section *psec = reader.sections[i]; // Calculate total size: - if ((psec->get_type() == SHT_PROGBITS || psec->get_type() == SHT_NOBITS) && (psec->get_flags() & SHF_ALLOC)) { + if ((psec->get_type() == ELFIO::SHT_PROGBITS || psec->get_type() == ELFIO::SHT_NOBITS) && (psec->get_flags() & ELFIO::SHF_ALLOC)) { uint32_t sectionSize = psec->get_size(); auto address = (uint32_t) psec->get_address(); if ((address >= 0x02000000) && address < 0x10000000) { diff --git a/source/utils/membuf.hpp b/source/utils/membuf.hpp new file mode 100644 index 0000000..cbc9011 --- /dev/null +++ b/source/utils/membuf.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include + +struct membuf : std::streambuf { + membuf(char *begin, char *end) { + this->setg(begin, begin, end); + } + + pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which = std::ios_base::in) override { + if (dir == std::ios_base::cur) + gbump(off); + else if (dir == std::ios_base::end) + setg(eback(), egptr() + off, egptr()); + else if (dir == std::ios_base::beg) + setg(eback(), eback() + off, egptr()); + return gptr() - eback(); + } + + pos_type seekpos(pos_type sp, std::ios_base::openmode which) override { + return seekoff(sp - pos_type(off_type(0)), std::ios_base::beg, which); + } +}; \ No newline at end of file diff --git a/source/utils/wiiu_zlib.hpp b/source/utils/wiiu_zlib.hpp new file mode 100644 index 0000000..4aff09f --- /dev/null +++ b/source/utils/wiiu_zlib.hpp @@ -0,0 +1,119 @@ +#pragma once + +/**************************************************************************** + * Copyright (C) 2018-2020 Nathan Strong + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ + +#include + +#include "elfio/elfio_utils.hpp" +#include "logger.h" +#include "utils.h" +#include + +class wiiu_zlib : public ELFIO::compression_interface { +public: + std::unique_ptr inflate(const char *data, const ELFIO::endianess_convertor *convertor, ELFIO::Elf_Xword compressed_size, ELFIO::Elf_Xword &uncompressed_size) const override { + read_uncompressed_size(data, convertor, uncompressed_size); + auto result = make_unique_nothrow((uint32_t) (uncompressed_size + 1)); + if (result == nullptr) { + return nullptr; + } + + int z_ret; + z_stream s = {nullptr}; + + s.zalloc = Z_NULL; + s.zfree = Z_NULL; + s.opaque = Z_NULL; + + if (inflateInit_(&s, ZLIB_VERSION, sizeof(s)) != Z_OK) { + return nullptr; + } + + s.avail_in = compressed_size - 4; + s.next_in = (Bytef *) data; + s.avail_out = uncompressed_size; + s.next_out = (Bytef *) result.get(); + + z_ret = ::inflate(&s, Z_FINISH); + inflateEnd(&s); + + if (z_ret != Z_OK && z_ret != Z_STREAM_END) { + return nullptr; + } + + result[uncompressed_size] = '\0'; + return result; + } + + std::unique_ptr deflate(const char *data, const ELFIO::endianess_convertor *convertor, ELFIO::Elf_Xword decompressed_size, ELFIO::Elf_Xword &compressed_size) const override { + auto result = make_unique_nothrow((uint32_t) (decompressed_size)); + if (result == nullptr) { + return nullptr; + } + + int z_ret = 0; + z_stream s = {nullptr}; + + s.zalloc = Z_NULL; + s.zfree = Z_NULL; + s.opaque = Z_NULL; + + if ((z_ret = deflateInit(&s, Z_DEFAULT_COMPRESSION)) != Z_OK) { + return nullptr; + } + + s.avail_in = decompressed_size; + s.next_in = (Bytef *) data; + s.avail_out = decompressed_size - 4; + s.next_out = (Bytef *) result.get() + 4; + + z_ret = ::deflate(&s, Z_FINISH); + compressed_size = decompressed_size - s.avail_out; + deflateEnd(&s); + + if (z_ret != Z_OK && z_ret != Z_STREAM_END) { + compressed_size = 0; + return nullptr; + } + + write_compressed_size(result, convertor, compressed_size); + result[compressed_size] = '\0'; + return result; + } + +private: + static void read_uncompressed_size(const char *&data, const ELFIO::endianess_convertor *convertor, ELFIO::Elf_Xword &uncompressed_size) { + union _int32buffer { + uint32_t word; + char bytes[4]; + } int32buffer; + memcpy(int32buffer.bytes, data, 4); + data += 4; + uncompressed_size = (*convertor)(int32buffer.word); + } + + static void write_compressed_size(std::unique_ptr &result, const ELFIO::endianess_convertor *convertor, ELFIO::Elf_Xword compressed_size) { + union _int32buffer { + uint32_t word; + char bytes[4]; + } int32buffer; + + int32buffer.word = (*convertor)(compressed_size); + memcpy(result.get(), int32buffer.bytes, 4); + } +}; \ No newline at end of file