File extract_from_elf.c of Package petitboot
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <elf.h>
#ifndef __BIG_ENDIAN__
int main(void)
{
return 123;
}
#else
#ifdef DEBUG
#define dump_member64(struct,member) do {printf(#member":\t %016llx\n",(unsigned long long) struct.member); } while(0)
#define dump_member32(struct,member) do {printf(#member":\t %08lx\n",(unsigned long) struct.member); } while(0)
#else
#define dump_member64(struct,member)
#define dump_member32(struct,member)
#endif
static const char *elf_filename;
static const char *elf_section;
static const char *output_filename;
static void write_section_to_file(const unsigned char const *file, off_t sh_offset, size_t sh_size)
{
ssize_t ret;
int fd;
fd = open(output_filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd < 0) {
perror(output_filename);
return;
}
ret = write(fd, file + sh_offset, sh_size);
if (ret < 0)
perror(output_filename);
else if (ret < sh_size)
printf("wrote only %d of %u bytes to %s\n", ret, sh_size, output_filename);
close(fd);
}
static void read_elf64_sh(const unsigned char const *file, Elf64_Off e_shoff, Elf64_Half e_shentsize, Elf64_Half e_shnum, Elf64_Half e_shstrndx)
{
Elf64_Shdr sh;
const char const *name;
int i;
name = (const char const *)file + ((Elf64_Shdr *) (file + e_shoff + (e_shstrndx * e_shentsize)))->sh_offset;
for (i = 0; i < e_shnum; i++) {
memcpy(&sh, file + e_shoff + (i * e_shentsize), sizeof(sh));
if (strcmp(name + sh.sh_name, elf_section) == 0) {
#ifdef DEBUG
printf("sh #%d: '%s'\n", i, name + sh.sh_name);
#endif
dump_member64(sh, sh_name);
dump_member64(sh, sh_type);
dump_member64(sh, sh_flags);
dump_member64(sh, sh_addr);
dump_member64(sh, sh_offset);
dump_member64(sh, sh_size);
dump_member64(sh, sh_link);
dump_member64(sh, sh_info);
dump_member64(sh, sh_addralign);
dump_member64(sh, sh_entsize);
write_section_to_file(file, sh.sh_offset, sh.sh_size);
return;
}
}
}
static void read_elf64(const unsigned char const *file)
{
Elf64_Ehdr e;
memcpy(&e, file, sizeof(e));
dump_member64(e, e_type);
dump_member64(e, e_machine);
dump_member64(e, e_version);
dump_member64(e, e_entry);
dump_member64(e, e_phoff);
dump_member64(e, e_shoff);
dump_member64(e, e_flags);
dump_member64(e, e_ehsize);
dump_member64(e, e_phentsize);
dump_member64(e, e_phnum);
dump_member64(e, e_shentsize);
dump_member64(e, e_shnum);
dump_member64(e, e_shstrndx);
read_elf64_sh(file, e.e_shoff, e.e_shentsize, e.e_shnum, e.e_shstrndx);
}
static void read_elf32_sh(const unsigned char const *file, Elf32_Off e_shoff, Elf32_Half e_shentsize, Elf32_Half e_shnum, Elf32_Half e_shstrndx)
{
Elf32_Shdr sh;
const char const *name;
int i;
name = (const char const *)file + ((Elf32_Shdr *) (file + e_shoff + (e_shstrndx * e_shentsize)))->sh_offset;
for (i = 0; i < e_shnum; i++) {
memcpy(&sh, file + e_shoff + (i * e_shentsize), sizeof(sh));
if (strcmp(name + sh.sh_name, elf_section) == 0) {
#ifdef DEBUG
printf("sh #%d: '%s'\n", i, name + sh.sh_name);
#endif
dump_member32(sh, sh_name);
dump_member32(sh, sh_type);
dump_member32(sh, sh_flags);
dump_member32(sh, sh_addr);
dump_member32(sh, sh_offset);
dump_member32(sh, sh_size);
dump_member32(sh, sh_link);
dump_member32(sh, sh_info);
dump_member32(sh, sh_addralign);
dump_member32(sh, sh_entsize);
write_section_to_file(file, sh.sh_offset, sh.sh_size);
return;
}
}
}
static void read_elf32(const unsigned char const *file)
{
Elf32_Ehdr e;
memcpy(&e, file, sizeof(e));
dump_member32(e, e_type);
dump_member32(e, e_machine);
dump_member32(e, e_version);
dump_member32(e, e_entry);
dump_member32(e, e_phoff);
dump_member32(e, e_shoff);
dump_member32(e, e_flags);
dump_member32(e, e_ehsize);
dump_member32(e, e_phentsize);
dump_member32(e, e_phnum);
dump_member32(e, e_shentsize);
dump_member32(e, e_shnum);
dump_member32(e, e_shstrndx);
read_elf32_sh(file, e.e_shoff, e.e_shentsize, e.e_shnum, e.e_shstrndx);
}
static void read_elf_file(const unsigned char const *file)
{
if (file[EI_DATA] != ELFDATA2MSB)
return;
if (file[EI_MAG0] == ELFMAG0 && file[EI_MAG1] == ELFMAG1 && file[EI_MAG2] == ELFMAG2 && file[EI_MAG3] == ELFMAG3) {
switch (file[EI_CLASS]) {
case ELFCLASS64:
read_elf64(file);
break;
case ELFCLASS32:
read_elf32(file);
break;
}
}
}
int main(int argc, char *argv[])
{
struct stat sb;
const unsigned char const *file;
int fd, skip = 0;
for (fd = 1; fd < argc; fd++) {
if (skip)
skip = 0;
else if (argv[fd][0] == '-' && fd < argc) {
switch (argv[fd][1]) {
case 'e':
elf_section = argv[fd + 1];
skip = 1;
break;
case 'i':
elf_filename = argv[fd + 1];
skip = 1;
break;
case 'o':
output_filename = argv[fd + 1];
skip = 1;
break;
}
}
}
if (!(elf_filename && elf_section && output_filename)) {
printf("Usage: %s -i elf_filename -e elf_section -o output_filename \n", argv[0]);
return 42;
}
fd = open(elf_filename, O_RDONLY);
if (fd < 0)
return 1;
if (fstat(fd, &sb) < 0 || sb.st_size == 0)
return 2;
file = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (file == MAP_FAILED)
return 3;
read_elf_file(file);
return 0;
}
#endif