From e38c6ed229e9510b0956d12a59133a71f94cf841 Mon Sep 17 00:00:00 2001 From: Sahil Siddiq Date: Thu, 8 Feb 2024 01:21:47 +0530 Subject: [PATCH 1/8] ARM: Implement search for public (aeabi) attributes subsection get_cpu_arm() scans through the ".ARM.attributes" section of the ELF file to find the "aeabi" subsection. This subsection contains general build attributes that records data about the compatibility of the ELF file. --- librz/bin/format/elf/elf_info.c | 54 ++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/librz/bin/format/elf/elf_info.c b/librz/bin/format/elf/elf_info.c index df6675c586f..852e6336941 100644 --- a/librz/bin/format/elf/elf_info.c +++ b/librz/bin/format/elf/elf_info.c @@ -845,6 +845,56 @@ static char *get_cpu_mips(ELFOBJ *bin) { return strdup(" Unknown mips ISA"); } +static char *read_arm_attributes_section(char *ptr, ut32 bytes_to_read, bool isbig) { + /* TODO */ + return strdup(" Unknown arm ISA"); +} + +/** + * Processor-specific section types explained in: + * 1. https://github.com/ARM-software/abi-aa/blob/main/aaelf32/aaelf32.rst + * 2. https://github.com/ARM-software/abi-aa/blob/main/addenda32/addenda32.rst + */ +static char *get_cpu_arm(ELFOBJ *bin) { + RzBinElfSection *section = Elf_(rz_bin_elf_get_section_with_name)(bin, ".ARM.attributes"); + if (!section) { + return strdup(" Unknown arm ISA"); + } + + ut64 offset = section->offset; + ut64 size = section->size; + if (size < 1) { + return strdup(" Unknown arm ISA"); + } + + char *result = malloc(size + 1); + if (!result) { + return strdup(" Unknown arm ISA"); + } + + if (rz_buf_read_at(bin->b, offset, (ut8 *)result, size) < 1) { + free(result); + return strdup(" Unknown arm ISA"); + } + + char *subsection_ptr = result + 1; // Point to the first subsection (first byte is the format-version) + bool isbig = Elf_(rz_bin_elf_is_big_endian)(bin); + + while (subsection_ptr - result < size) { + char *ptr = subsection_ptr; + ut32 subsection_size = rz_read_ble32(ptr, isbig); + ptr += 4; + + if (!strcmp(ptr, "aeabi")) { + ptr += strlen("aeabi") + 1; // +1 for the null byte + return read_arm_attributes_section(ptr, subsection_size - 10, isbig); + } + subsection_ptr += subsection_size; + } + + return strdup(" Unknown arm ISA"); +} + static bool is_elf_class64(ELFOBJ *bin) { return bin->ehdr.e_ident[EI_CLASS] == ELFCLASS64; } @@ -1460,7 +1510,7 @@ RZ_OWN char *Elf_(rz_bin_elf_get_arch)(RZ_NONNULL ELFOBJ *bin) { * \param elf type * \return allocated string * - * Only work on mips right now. Use the elf header to deduce the cpu + * Only work on mips and arm right now. Use the elf header to deduce the cpu */ RZ_OWN char *Elf_(rz_bin_elf_get_cpu)(RZ_NONNULL ELFOBJ *bin) { rz_return_val_if_fail(bin, NULL); @@ -1471,6 +1521,8 @@ RZ_OWN char *Elf_(rz_bin_elf_get_cpu)(RZ_NONNULL ELFOBJ *bin) { if (bin->ehdr.e_machine == EM_MIPS) { return get_cpu_mips(bin); + } else if (bin->ehdr.e_machine == EM_ARM) { + return get_cpu_arm(bin); } return NULL; From aead5d7ed5e05c209d7fd28655c56d3055562ee4 Mon Sep 17 00:00:00 2001 From: Sahil Siddiq Date: Mon, 19 Feb 2024 01:53:19 +0530 Subject: [PATCH 2/8] ARM: Parse aeabi subsection Rename "read_arm_attributes_section()" to "read_arm_aeabi_section()". This function searches for the "TAG_FILE" sub-subsection. --- librz/bin/format/elf/elf_info.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/librz/bin/format/elf/elf_info.c b/librz/bin/format/elf/elf_info.c index 852e6336941..423437b6419 100644 --- a/librz/bin/format/elf/elf_info.c +++ b/librz/bin/format/elf/elf_info.c @@ -845,8 +845,27 @@ static char *get_cpu_mips(ELFOBJ *bin) { return strdup(" Unknown mips ISA"); } -static char *read_arm_attributes_section(char *ptr, ut32 bytes_to_read, bool isbig) { - /* TODO */ +static char *read_arm_build_attributes(char *ptr, ut32 bytes_to_read, bool isbig) { + while (bytes_to_read > 0) { + /* TODO: Search for TAG_CPU_ARCH and Tag_CPU_ARCH_PROFILE */ + } + return strdup(" Unknown arm ISA"); +} + +static char *read_arm_aeabi_section(char *ptr, ut32 bytes_to_read, bool isbig) { + while (bytes_to_read > 0) { + ut8 sub_subsection = *ptr; + ut32 sub_subsection_size = rz_read_ble32(ptr + 1, isbig); + + if (sub_subsection == ARM_TAG_FILE) { + char *str = read_arm_build_attributes(ptr + 5, sub_subsection_size - 5, isbig); + if (strcmp(str, " Unknown arm ISA")) { + return str; + } + } + ptr += sub_subsection_size; + bytes_to_read -= sub_subsection_size; + } return strdup(" Unknown arm ISA"); } @@ -887,7 +906,7 @@ static char *get_cpu_arm(ELFOBJ *bin) { if (!strcmp(ptr, "aeabi")) { ptr += strlen("aeabi") + 1; // +1 for the null byte - return read_arm_attributes_section(ptr, subsection_size - 10, isbig); + return read_arm_aeabi_section(ptr, subsection_size - 10, isbig); } subsection_ptr += subsection_size; } From 5075a5f99d014dbec19fb04cb70e5cb8d680d376 Mon Sep 17 00:00:00 2001 From: Sahil Siddiq Date: Mon, 19 Feb 2024 01:45:56 +0530 Subject: [PATCH 3/8] ARM: Add macros defining tags in the public attributes subsection Each tag's value is defined as a null-terminated string or a uleb128-encoded number. This info will be required while searching for "TAG_CPU_ARCH" and "Tag_CPU_ARCH_PROFILE" in the "ARM_TAG_FILE" sub-subsection. --- librz/bin/format/elf/glibc_elf.h | 69 ++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/librz/bin/format/elf/glibc_elf.h b/librz/bin/format/elf/glibc_elf.h index 63b8bb91f82..436350fe93f 100644 --- a/librz/bin/format/elf/glibc_elf.h +++ b/librz/bin/format/elf/glibc_elf.h @@ -2712,6 +2712,75 @@ enum { #define SHT_ARM_PREEMPTMAP (SHT_LOPROC + 2) /* Preemption details. */ #define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3) /* ARM attributes section. */ +/* Constants defining public attributes sub-subsections. */ +#define ARM_TAG_FILE 1 +#define ARM_TAG_SECTION 2 +#define ARM_TAG_SYMBOL 3 + +/* ARM target-related attributes. */ +#define TAG_CPU_RAW_NAME 4 +#define TAG_CPU_NAME 5 +#define TAG_CPU_ARCH 6 +#define Tag_CPU_ARCH_PROFILE 7 +#define TAG_ARM_ISA_USE 8 +#define TAG_THUMB_ISA_USE 9 +#define TAG_FP_ARCH 10 +#define TAG_WMMX_ARCH 11 +#define TAG_ADVANCED_SIMD_ARCH 12 +#define TAG_CPU_UNALIGNED_ACCESS 34 +#define TAG_FP_HP_EXTENSION 36 +#define TAG_VFP_HP_EXTENSION 36 /* Deprecated version of TAG_FP_HP_EXTENSION */ +#define TAG_MPEXTENSION_USE 42 +#define TAG_DIV_USE 44 +#define TAG_DSP_EXTENSION 46 +#define TAG_MVE_ARCH 48 +#define TAG_PAC_EXTENSION 50 +#define TAG_BTI_EXTENSION 52 +#define TAG_T2EE_USE 66 +#define TAG_VIRTUALIZATION_USE 68 + +/* ARM procedure call-related attributes. */ +#define TAG_PCS_CONFIG 13 +#define TAG_ABI_PCS_R9_USE 14 +#define TAG_ABI_PCS_RW_DATA 15 +#define TAG_ABI_PCS_RO_DATA 16 +#define TAG_ABI_PCS_GOT_USE 17 +#define TAG_ABI_PCS_WCHAR_T 18 +#define TAG_ABI_FP_ROUNDING 19 +#define TAG_ABI_FP_DENORMAL 20 +#define TAG_ABI_FP_EXCEPTIONS 21 +#define TAG_ABI_FP_USER_EXCEPTIONS 22 +#define TAG_ABI_FP_NUMBER_MODEL 23 +#define TAG_ABI_ALIGN_NEEDED 24 +#define TAG_ABI_ALIGN_PRESERVED 25 +#define TAG_ABI_ENUM_SIZE 26 +#define TAG_ABI_HARDFP_USE 27 +#define TAG_ABI_VFP_ARGS 28 +#define TAG_ABI_WMMX_ARGS 29 +#define TAG_ABI_FP_16BIT_FORMAT 38 +#define TAG_FRAMEPOINTER_USE 72 +#define TAG_BTI_USE 74 + +/* ARM miscellaneous attributes. */ +#define TAG_PACRET_USE 76 + +/* ARM optimization attributes. */ +#define TAG_ABI_OPTIMIZATION_GOALS 30 +#define TAG_ABI_FP_OPTIMIZATION_GOALS 31 + +/* ARM generic compatibility tag. */ +#define TAG_COMPATIBILITY 32 + +/* ARM secondary compatibility tag. */ +#define TAG_ALSO_COMPATIBLE_WITH 65 + +/* ARM conformance tag. */ +#define TAG_CONFORMANCE 67 + +/* ARM no defaults tag. */ +#define TAG_NODEFAULTS 64 + + /* AArch64 relocs. */ #define RZ_AARCH64_NONE 0 /* No relocation. */ From d6e014299e127db6a5590ed5b2d87de5c54adf1a Mon Sep 17 00:00:00 2001 From: Sahil Siddiq Date: Tue, 20 Feb 2024 01:55:24 +0530 Subject: [PATCH 4/8] ARM: Add macros for ARM CPU arch version and profile --- librz/bin/format/elf/glibc_elf.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/librz/bin/format/elf/glibc_elf.h b/librz/bin/format/elf/glibc_elf.h index 436350fe93f..1d67c8a4575 100644 --- a/librz/bin/format/elf/glibc_elf.h +++ b/librz/bin/format/elf/glibc_elf.h @@ -2780,6 +2780,38 @@ enum { /* ARM no defaults tag. */ #define TAG_NODEFAULTS 64 +/* ARM CPU Arch Version */ +#define ARM_VER_PRE_V4 0 +#define ARM_VER_V4 1 +#define ARM_VER_V4T 2 +#define ARM_VER_V5T 3 +#define ARM_VER_V5TE 4 +#define ARM_VER_V5TEJ 5 +#define ARM_VER_V6 6 +#define ARM_VER_V6KZ 7 +#define ARM_VER_V6T2 8 +#define ARM_VER_V6K 9 +#define ARM_VER_V7 10 +#define ARM_VER_V6_M 11 +#define ARM_VER_V6S_M 12 +#define ARM_VER_V7E_M 13 +#define ARM_VER_V8_A 14 +#define ARM_VER_V8_R 15 +#define ARM_VER_V8_M_BASELINE 16 +#define ARM_VER_V8_M_MAINLINE 17 +#define ARM_VER_V8_1_A 18 +#define ARM_VER_V8_2_A 19 +#define ARM_VER_V8_3_A 20 +#define ARM_VER_V8_1_M_MAINLINE 21 +#define ARM_VER_V9_A 22 + +/* ARM CPU Arch Profile */ +#define ARM_PROFILE_0 0 +#define ARM_PROFILE_A 0x41 +#define ARM_PROFILE_R 0x52 +#define ARM_PROFILE_M 0x4d +#define ARM_PROFILE_S 0x53 + /* AArch64 relocs. */ From 943892f898f127cc0f67b2108cf65b779685fc0e Mon Sep 17 00:00:00 2001 From: Sahil Siddiq Date: Tue, 27 Feb 2024 00:48:57 +0530 Subject: [PATCH 5/8] Minor changes in ARM tags --- librz/bin/format/elf/glibc_elf.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/librz/bin/format/elf/glibc_elf.h b/librz/bin/format/elf/glibc_elf.h index 1d67c8a4575..c88b5690bf3 100644 --- a/librz/bin/format/elf/glibc_elf.h +++ b/librz/bin/format/elf/glibc_elf.h @@ -2721,7 +2721,7 @@ enum { #define TAG_CPU_RAW_NAME 4 #define TAG_CPU_NAME 5 #define TAG_CPU_ARCH 6 -#define Tag_CPU_ARCH_PROFILE 7 +#define TAG_CPU_ARCH_PROFILE 7 #define TAG_ARM_ISA_USE 8 #define TAG_THUMB_ISA_USE 9 #define TAG_FP_ARCH 10 @@ -2729,7 +2729,6 @@ enum { #define TAG_ADVANCED_SIMD_ARCH 12 #define TAG_CPU_UNALIGNED_ACCESS 34 #define TAG_FP_HP_EXTENSION 36 -#define TAG_VFP_HP_EXTENSION 36 /* Deprecated version of TAG_FP_HP_EXTENSION */ #define TAG_MPEXTENSION_USE 42 #define TAG_DIV_USE 44 #define TAG_DSP_EXTENSION 46 From cd134e24570d5814710f6766a1e5a4272153f999 Mon Sep 17 00:00:00 2001 From: Sahil Siddiq Date: Wed, 6 Mar 2024 00:51:00 +0530 Subject: [PATCH 6/8] ARM: Read arm build attributes * Read arm build attributes * Incorporate reviewed changes --- librz/bin/format/elf/elf_info.c | 76 ++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/librz/bin/format/elf/elf_info.c b/librz/bin/format/elf/elf_info.c index 423437b6419..e398cd8fcc5 100644 --- a/librz/bin/format/elf/elf_info.c +++ b/librz/bin/format/elf/elf_info.c @@ -4,7 +4,9 @@ // SPDX-FileCopyrightText: 2008-2020 alvaro_fe // SPDX-License-Identifier: LGPL-3.0-only +#include "core/core_private.h" #include "elf.h" +#include "rz_types_base.h" #define EF_MIPS_ABI_O32 0x00001000 /* O32 ABI. */ #define EF_MIPS_ABI_O64 0x00002000 /* O32 extended for 64 bit. */ @@ -847,14 +849,84 @@ static char *get_cpu_mips(ELFOBJ *bin) { static char *read_arm_build_attributes(char *ptr, ut32 bytes_to_read, bool isbig) { while (bytes_to_read > 0) { - /* TODO: Search for TAG_CPU_ARCH and Tag_CPU_ARCH_PROFILE */ + ut64 arm_tag = 0; + int len = 0; + rz_uleb128_decode((ut8 *)ptr, &len, &arm_tag); + ptr += len; + bytes_to_read -= len; + arm_tag = arm_tag % 128; + switch (arm_tag) { + case TAG_CPU_ARCH: { + ut64 cpu_arch = 0; + rz_uleb128_decode((ut8 *)ptr, &len, &cpu_arch); + ptr += len; + bytes_to_read -= len; + switch (cpu_arch) { + case ARM_VER_V8_A: + case ARM_VER_V8_1_A: + case ARM_VER_V8_2_A: + case ARM_VER_V8_3_A: + case ARM_VER_V9_A: + break; + } + } + case TAG_CPU_ARCH_PROFILE: + return strdup("Tag_CPU_ARCH_PROFILE"); + case TAG_CPU_RAW_NAME: + case TAG_CPU_NAME: + case TAG_COMPATIBILITY: + len = strlen(ptr) + 1; + bytes_to_read -= len; + ptr += len; + break; + case TAG_ARM_ISA_USE: + case TAG_THUMB_ISA_USE: + case TAG_FP_ARCH: + case TAG_WMMX_ARCH: + case TAG_ADVANCED_SIMD_ARCH: + case TAG_PCS_CONFIG: + case TAG_ABI_PCS_R9_USE: + case TAG_ABI_PCS_RW_DATA: + case TAG_ABI_PCS_RO_DATA: + case TAG_ABI_PCS_GOT_USE: + case TAG_ABI_PCS_WCHAR_T: + case TAG_ABI_ENUM_SIZE: + case TAG_ABI_ALIGN_NEEDED: + case TAG_ABI_ALIGN_PRESERVED: + case TAG_ABI_FP_ROUNDING: + case TAG_ABI_FP_DENORMAL: + case TAG_ABI_FP_EXCEPTIONS: + case TAG_ABI_FP_USER_EXCEPTIONS: + case TAG_ABI_FP_NUMBER_MODEL: + case TAG_ABI_HARDFP_USE: + case TAG_ABI_VFP_ARGS: + case TAG_ABI_WMMX_ARGS: + case TAG_ABI_OPTIMIZATION_GOALS: + case TAG_ABI_FP_OPTIMIZATION_GOALS: + rz_uleb128_decode((ut8 *)ptr, &len, NULL); + ptr += len; + bytes_to_read -= len; + break; + default: + if (arm_tag > 32) { + if (arm_tag & 1) { + len = strlen(ptr) + 1; + bytes_to_read -= len; + ptr += len; + } else { + rz_uleb128_decode((ut8 *)ptr, &len, NULL); + ptr += len; + bytes_to_read -= len; + } + } + } } return strdup(" Unknown arm ISA"); } static char *read_arm_aeabi_section(char *ptr, ut32 bytes_to_read, bool isbig) { while (bytes_to_read > 0) { - ut8 sub_subsection = *ptr; + ut8 sub_subsection = rz_read_ble8(ptr); // Will always be 1, 2 or 3, hence no need for uleb128 decoding. ut32 sub_subsection_size = rz_read_ble32(ptr + 1, isbig); if (sub_subsection == ARM_TAG_FILE) { From 2b71498ff117ab24410ba586704b4e1b648eea25 Mon Sep 17 00:00:00 2001 From: Sahil Siddiq Date: Wed, 6 Mar 2024 00:53:02 +0530 Subject: [PATCH 7/8] ARM: Add structure for arm cpu translation --- librz/bin/format/elf/elf_info.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/librz/bin/format/elf/elf_info.c b/librz/bin/format/elf/elf_info.c index e398cd8fcc5..5ef0682c52e 100644 --- a/librz/bin/format/elf/elf_info.c +++ b/librz/bin/format/elf/elf_info.c @@ -39,6 +39,11 @@ struct cpu_mips_translation { const char *name; }; +struct cpu_arm_translation { + Elf_(Half) arch; + const char *name; +}; + struct arch_translation { Elf_(Half) arch; const char *name; @@ -243,6 +248,32 @@ static const struct cpu_mips_translation cpu_mips_translation_table[] = { { EF_MIPS_ARCH_64R2, "mips64r2" }, }; +static const struct cpu_arm_translation cpu_arm_translation_table[] = { + { ARM_VER_PRE_V4, "ARM Pre-v4"}, + { ARM_VER_V4, "ARM v4"}, + { ARM_VER_V4T, "ARM v4T"}, + { ARM_VER_V5T, "ARM v5T"}, + { ARM_VER_V5TE, "ARM v5TE"}, + { ARM_VER_V5TEJ, "ARM v5TEJ"}, + { ARM_VER_V6, "ARM v6"}, + { ARM_VER_V6KZ, "ARM v6KZ"}, + { ARM_VER_V6T2, "ARM v6T2"}, + { ARM_VER_V6K, "ARM v6K"}, + { ARM_VER_V7, "ARM v7"}, + { ARM_VER_V6_M, "ARM v6-M"}, + { ARM_VER_V6S_M, "ARM v6S-M"}, + { ARM_VER_V7E_M, "ARM v7E-M"}, + { ARM_VER_V8_A, "ARM v8-A"}, + { ARM_VER_V8_R, "ARM v8-R"}, + { ARM_VER_V8_M_BASELINE, "ARM v8-M.baseline"}, + { ARM_VER_V8_M_MAINLINE, "ARM v8-M.mainline"}, + { ARM_VER_V8_1_A, "ARM v8.1-A"}, + { ARM_VER_V8_2_A, "ARM v8.2-A"}, + { ARM_VER_V8_3_A, "ARM v8.3-A"}, + { ARM_VER_V8_1_M_MAINLINE, "ARM v8.1-M.mainline"}, + { ARM_VER_V9_A, "ARM v9-A"}, +}; + static const struct arch_translation arch_translation_table[] = { { EM_ARC, "arc" }, { EM_ARC_A5, "arc" }, From 9dbf2073189dec38c666f538d33bde15a5251a01 Mon Sep 17 00:00:00 2001 From: Sahil Siddiq Date: Wed, 6 Mar 2024 01:42:13 +0530 Subject: [PATCH 8/8] ARM: Get arch name --- librz/bin/format/elf/elf_info.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/librz/bin/format/elf/elf_info.c b/librz/bin/format/elf/elf_info.c index 5ef0682c52e..aa4095c861b 100644 --- a/librz/bin/format/elf/elf_info.c +++ b/librz/bin/format/elf/elf_info.c @@ -892,14 +892,12 @@ static char *read_arm_build_attributes(char *ptr, ut32 bytes_to_read, bool isbig rz_uleb128_decode((ut8 *)ptr, &len, &cpu_arch); ptr += len; bytes_to_read -= len; - switch (cpu_arch) { - case ARM_VER_V8_A: - case ARM_VER_V8_1_A: - case ARM_VER_V8_2_A: - case ARM_VER_V8_3_A: - case ARM_VER_V9_A: - break; + for (size_t i = 0; i < RZ_ARRAY_SIZE(cpu_arm_translation_table); i++) { + if (cpu_arch == cpu_arm_translation_table[i].arch) { + return strdup(cpu_arm_translation_table[i].name); + } } + break; } case TAG_CPU_ARCH_PROFILE: return strdup("Tag_CPU_ARCH_PROFILE");