9 #include "light_byteswap.h"
12 typedef Elf32_Nhdr Elf_Nhdr
;
15 static Elf64_Ehdr ehdr
;
17 #if __BYTE_ORDER == __LITTLE_ENDIAN
18 #define ELFDATANATIVE ELFDATA2LSB
19 #elif __BYTE_ORDER == __BIG_ENDIAN
20 #define ELFDATANATIVE ELFDATA2MSB
22 #error "Unknown machine endian"
25 static uint16_t file16_to_cpu(uint16_t val
)
27 if (ehdr
.e_ident
[EI_DATA
] != ELFDATANATIVE
)
32 static uint32_t file32_to_cpu(uint32_t val
)
34 if (ehdr
.e_ident
[EI_DATA
] != ELFDATANATIVE
)
39 static uint64_t file64_to_cpu(uint64_t val
)
41 if (ehdr
.e_ident
[EI_DATA
] != ELFDATANATIVE
)
46 static unsigned long read_elf32(int fd
)
50 off_t last_shdr_offset
;
52 unsigned long sht_end
, last_section_end
;
54 ret
= pread(fd
, &ehdr32
, sizeof(ehdr32
), 0);
55 if (ret
< 0 || (size_t)ret
!= sizeof(ehdr32
)) {
56 fprintf(stderr
, "Read of ELF header from %s failed: %s\n",
57 fname
, strerror(errno
));
61 ehdr
.e_shoff
= file32_to_cpu(ehdr32
.e_shoff
);
62 ehdr
.e_shentsize
= file16_to_cpu(ehdr32
.e_shentsize
);
63 ehdr
.e_shnum
= file16_to_cpu(ehdr32
.e_shnum
);
65 last_shdr_offset
= ehdr
.e_shoff
+ (ehdr
.e_shentsize
* (ehdr
.e_shnum
- 1));
66 ret
= pread(fd
, &shdr32
, sizeof(shdr32
), last_shdr_offset
);
67 if (ret
< 0 || (size_t)ret
!= sizeof(shdr32
)) {
68 fprintf(stderr
, "Read of ELF section header from %s failed: %s\n",
69 fname
, strerror(errno
));
73 /* ELF ends either with the table of section headers (SHT) or with a section. */
74 sht_end
= ehdr
.e_shoff
+ (ehdr
.e_shentsize
* ehdr
.e_shnum
);
75 last_section_end
= file64_to_cpu(shdr32
.sh_offset
) + file64_to_cpu(shdr32
.sh_size
);
76 return sht_end
> last_section_end
? sht_end
: last_section_end
;
79 static unsigned long read_elf64(int fd
)
83 off_t last_shdr_offset
;
85 unsigned long sht_end
, last_section_end
;
87 ret
= pread(fd
, &ehdr64
, sizeof(ehdr64
), 0);
88 if (ret
< 0 || (size_t)ret
!= sizeof(ehdr64
)) {
89 fprintf(stderr
, "Read of ELF header from %s failed: %s\n",
90 fname
, strerror(errno
));
94 ehdr
.e_shoff
= file64_to_cpu(ehdr64
.e_shoff
);
95 ehdr
.e_shentsize
= file16_to_cpu(ehdr64
.e_shentsize
);
96 ehdr
.e_shnum
= file16_to_cpu(ehdr64
.e_shnum
);
98 last_shdr_offset
= ehdr
.e_shoff
+ (ehdr
.e_shentsize
* (ehdr
.e_shnum
- 1));
99 ret
= pread(fd
, &shdr64
, sizeof(shdr64
), last_shdr_offset
);
100 if (ret
< 0 || (size_t)ret
!= sizeof(shdr64
)) {
101 fprintf(stderr
, "Read of ELF section header from %s failed: %s\n",
102 fname
, strerror(errno
));
106 /* ELF ends either with the table of section headers (SHT) or with a section. */
107 sht_end
= ehdr
.e_shoff
+ (ehdr
.e_shentsize
* ehdr
.e_shnum
);
108 last_section_end
= file64_to_cpu(shdr64
.sh_offset
) + file64_to_cpu(shdr64
.sh_size
);
109 return sht_end
> last_section_end
? sht_end
: last_section_end
;
112 unsigned long get_elf_size(const char *fname
)
116 static unsigned long size
= 0;
118 fd
= open(fname
, O_RDONLY
);
120 fprintf(stderr
, "Cannot open %s: %s\n",
121 fname
, strerror(errno
));
124 ret
= pread(fd
, ehdr
.e_ident
, EI_NIDENT
, 0);
125 if (ret
!= EI_NIDENT
) {
126 fprintf(stderr
, "Read of e_ident from %s failed: %s\n",
127 fname
, strerror(errno
));
130 if ((ehdr
.e_ident
[EI_DATA
] != ELFDATA2LSB
) &&
131 (ehdr
.e_ident
[EI_DATA
] != ELFDATA2MSB
))
133 fprintf(stderr
, "Unkown ELF data order %u\n",
134 ehdr
.e_ident
[EI_DATA
]);
137 if(ehdr
.e_ident
[EI_CLASS
] == ELFCLASS32
) {
138 size
= read_elf32(fd
);
139 } else if(ehdr
.e_ident
[EI_CLASS
] == ELFCLASS64
) {
140 size
= read_elf64(fd
);
142 fprintf(stderr
, "Unknown ELF class %u\n", ehdr
.e_ident
[EI_CLASS
]);