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