Paul Burton | e245767 | 2018-08-29 11:01:30 -0700 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | #include <byteswap.h> |
| 3 | #include <elf.h> |
| 4 | #include <endian.h> |
| 5 | #include <inttypes.h> |
| 6 | #include <stdint.h> |
| 7 | #include <stdio.h> |
| 8 | #include <stdlib.h> |
| 9 | #include <string.h> |
| 10 | |
| 11 | #ifdef be32toh |
| 12 | /* If libc provides [bl]e{32,64}toh() then we'll use them */ |
| 13 | #elif BYTE_ORDER == LITTLE_ENDIAN |
| 14 | # define be32toh(x) bswap_32(x) |
| 15 | # define le32toh(x) (x) |
| 16 | # define be64toh(x) bswap_64(x) |
| 17 | # define le64toh(x) (x) |
| 18 | #elif BYTE_ORDER == BIG_ENDIAN |
| 19 | # define be32toh(x) (x) |
| 20 | # define le32toh(x) bswap_32(x) |
| 21 | # define be64toh(x) (x) |
| 22 | # define le64toh(x) bswap_64(x) |
| 23 | #endif |
| 24 | |
| 25 | __attribute__((noreturn)) |
| 26 | static void die(const char *msg) |
| 27 | { |
| 28 | fputs(msg, stderr); |
| 29 | exit(EXIT_FAILURE); |
| 30 | } |
| 31 | |
| 32 | int main(int argc, const char *argv[]) |
| 33 | { |
| 34 | uint64_t entry; |
| 35 | size_t nread; |
| 36 | FILE *file; |
| 37 | union { |
| 38 | Elf32_Ehdr ehdr32; |
| 39 | Elf64_Ehdr ehdr64; |
| 40 | } hdr; |
| 41 | |
| 42 | if (argc != 2) |
| 43 | die("Usage: elf-entry <elf-file>\n"); |
| 44 | |
| 45 | file = fopen(argv[1], "r"); |
| 46 | if (!file) { |
| 47 | perror("Unable to open input file"); |
| 48 | return EXIT_FAILURE; |
| 49 | } |
| 50 | |
| 51 | nread = fread(&hdr, 1, sizeof(hdr), file); |
| 52 | if (nread != sizeof(hdr)) { |
| 53 | perror("Unable to read input file"); |
Kaige Li | f33a0b9 | 2020-05-14 20:59:41 +0800 | [diff] [blame] | 54 | fclose(file); |
Paul Burton | e245767 | 2018-08-29 11:01:30 -0700 | [diff] [blame] | 55 | return EXIT_FAILURE; |
| 56 | } |
| 57 | |
Kaige Li | f33a0b9 | 2020-05-14 20:59:41 +0800 | [diff] [blame] | 58 | if (memcmp(hdr.ehdr32.e_ident, ELFMAG, SELFMAG)) { |
| 59 | fclose(file); |
Paul Burton | e245767 | 2018-08-29 11:01:30 -0700 | [diff] [blame] | 60 | die("Input is not an ELF\n"); |
Kaige Li | f33a0b9 | 2020-05-14 20:59:41 +0800 | [diff] [blame] | 61 | } |
Paul Burton | e245767 | 2018-08-29 11:01:30 -0700 | [diff] [blame] | 62 | |
| 63 | switch (hdr.ehdr32.e_ident[EI_CLASS]) { |
| 64 | case ELFCLASS32: |
| 65 | switch (hdr.ehdr32.e_ident[EI_DATA]) { |
| 66 | case ELFDATA2LSB: |
| 67 | entry = le32toh(hdr.ehdr32.e_entry); |
| 68 | break; |
| 69 | case ELFDATA2MSB: |
| 70 | entry = be32toh(hdr.ehdr32.e_entry); |
| 71 | break; |
| 72 | default: |
Kaige Li | f33a0b9 | 2020-05-14 20:59:41 +0800 | [diff] [blame] | 73 | fclose(file); |
Paul Burton | e245767 | 2018-08-29 11:01:30 -0700 | [diff] [blame] | 74 | die("Invalid ELF encoding\n"); |
| 75 | } |
| 76 | |
| 77 | /* Sign extend to form a canonical address */ |
| 78 | entry = (int64_t)(int32_t)entry; |
| 79 | break; |
| 80 | |
| 81 | case ELFCLASS64: |
| 82 | switch (hdr.ehdr32.e_ident[EI_DATA]) { |
| 83 | case ELFDATA2LSB: |
| 84 | entry = le64toh(hdr.ehdr64.e_entry); |
| 85 | break; |
| 86 | case ELFDATA2MSB: |
| 87 | entry = be64toh(hdr.ehdr64.e_entry); |
| 88 | break; |
| 89 | default: |
Kaige Li | f33a0b9 | 2020-05-14 20:59:41 +0800 | [diff] [blame] | 90 | fclose(file); |
Paul Burton | e245767 | 2018-08-29 11:01:30 -0700 | [diff] [blame] | 91 | die("Invalid ELF encoding\n"); |
| 92 | } |
| 93 | break; |
| 94 | |
| 95 | default: |
Kaige Li | f33a0b9 | 2020-05-14 20:59:41 +0800 | [diff] [blame] | 96 | fclose(file); |
Paul Burton | e245767 | 2018-08-29 11:01:30 -0700 | [diff] [blame] | 97 | die("Invalid ELF class\n"); |
| 98 | } |
| 99 | |
| 100 | printf("0x%016" PRIx64 "\n", entry); |
Kaige Li | f33a0b9 | 2020-05-14 20:59:41 +0800 | [diff] [blame] | 101 | fclose(file); |
Paul Burton | e245767 | 2018-08-29 11:01:30 -0700 | [diff] [blame] | 102 | return EXIT_SUCCESS; |
| 103 | } |