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(s: 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(msg: "Usage: elf-entry <elf-file>\n" ); |
44 | |
45 | file = fopen(filename: argv[1], modes: "r" ); |
46 | if (!file) { |
47 | perror(s: "Unable to open input file" ); |
48 | return EXIT_FAILURE; |
49 | } |
50 | |
51 | nread = fread(ptr: &hdr, size: 1, n: sizeof(hdr), stream: file); |
52 | if (nread != sizeof(hdr)) { |
53 | perror(s: "Unable to read input file" ); |
54 | fclose(stream: file); |
55 | return EXIT_FAILURE; |
56 | } |
57 | |
58 | if (memcmp(s1: hdr.ehdr32.e_ident, ELFMAG, SELFMAG)) { |
59 | fclose(stream: file); |
60 | die(msg: "Input is not an ELF\n" ); |
61 | } |
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: |
73 | fclose(stream: file); |
74 | die(msg: "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: |
90 | fclose(stream: file); |
91 | die(msg: "Invalid ELF encoding\n" ); |
92 | } |
93 | break; |
94 | |
95 | default: |
96 | fclose(stream: file); |
97 | die(msg: "Invalid ELF class\n" ); |
98 | } |
99 | |
100 | printf(format: "0x%016" PRIx64 "\n" , entry); |
101 | fclose(stream: file); |
102 | return EXIT_SUCCESS; |
103 | } |
104 | |