Skip to content

Instantly share code, notes, and snippets.

@matwey
Created January 24, 2023 17:02
Show Gist options
  • Save matwey/6175accc18b7a6cc0f07c71766cd0ce2 to your computer and use it in GitHub Desktop.
Save matwey/6175accc18b7a6cc0f07c71766cd0ce2 to your computer and use it in GitHub Desktop.
Convert raw AVR binary firmware to ELF format loadable to QEMU
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/mman.h>
#include <libelf.h>
int main (int argc, char** argv) {
if (argc < 2) {
fprintf(stderr, "Usage: %s input.bin output.elf\n", argv[0]);
return 1;
}
char* binary = argv[1];
char* filename = argv[2];
struct stat s;
int fd_input = open(binary, O_RDONLY);
if (fd_input < 0) {
fprintf(stderr, "Cannot open file %s: %s\n", binary, strerror(errno));
return 1;
}
fstat(fd_input, &s);
size_t b_size = s.st_size;
unsigned char *b_ptr = (unsigned char*) mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd_input, 0);
if (b_ptr == NULL) {
fprintf(stderr, "Cannot read file %s: %s\n", binary, strerror(errno));
return 1;
}
int fd = open(filename, O_WRONLY | O_CREAT, 0755);
if (fd < 0) {
fprintf(stderr, "Cannot open file %s: %s\n", filename, strerror(errno));
return 1;
}
elf_version(EV_CURRENT);
Elf *elf = elf_begin(fd, ELF_C_WRITE, NULL);
if (elf == NULL) {
fprintf(stderr, "Cannot create ELF: %s\n", elf_errmsg(elf_errno()));
close(fd);
return 1;
}
Elf32_Ehdr *ehdr = elf32_newehdr(elf);
if (ehdr == NULL) {
fprintf(stderr, "Cannot create EHDR: %s\n", elf_errmsg(elf_errno()));
elf_end(elf);
return 1;
}
ehdr->e_type = ET_EXEC;
ehdr->e_machine = EM_AVR;
ehdr->e_version = EV_CURRENT;
ehdr->e_flags = 0x4;
Elf_Scn *text_scn = elf_newscn(elf);
if (text_scn == NULL) {
fprintf(stderr, "Cannot create .text section: %s\n", elf_errmsg(elf_errno()));
elf_end(elf);
return 1;
}
Elf32_Shdr *text = elf32_getshdr(text_scn);
if (text == NULL) {
fprintf(stderr, "Cannot get .text section: %s\n", elf_errmsg(elf_errno()));
elf_end(elf);
return 1;
}
Elf_Data *text_data = elf_newdata(text_scn);
if (text_data == NULL) {
fprintf(stderr, "Cannot create data for .text section: %s\n", elf_errmsg(elf_errno()));
elf_end(elf);
return 1;
}
text_data->d_buf = b_ptr;
text_data->d_type = ELF_T_BYTE;
text_data->d_size = b_size;
text_data->d_align = 1;
text_data->d_version = EV_CURRENT;
text->sh_name = 1;
text->sh_type = SHT_PROGBITS;
text->sh_flags = SHF_ALLOC | SHF_EXECINSTR;
Elf_Scn *shstrtab_scn = elf_newscn(elf);
if (shstrtab_scn == NULL) {
fprintf(stderr, "Cannot create .shstrtab section: %s\n", elf_errmsg(elf_errno()));
elf_end(elf);
return 1;
}
Elf_Data *strtab_data = elf_newdata(shstrtab_scn);
if (strtab_data == NULL) {
fprintf(stderr, "Cannot create data for .shstrtab section: %s\n", elf_errmsg(elf_errno()));
elf_end(elf);
return 1;
}
char strtab_buf[] = "\0.text\0.shstrtab\0";
strtab_data->d_buf = strtab_buf;
strtab_data->d_type = ELF_T_BYTE;
strtab_data->d_size = sizeof(strtab_buf) / sizeof(strtab_buf[0]);
strtab_data->d_align = 1;
strtab_data->d_version = EV_CURRENT;
Elf32_Shdr *shstrtab = elf32_getshdr(shstrtab_scn);
if (shstrtab == NULL) {
fprintf(stderr, "Cannot get .shstrtab section: %s\n", elf_errmsg(elf_errno()));
elf_end(elf);
return 1;
}
shstrtab->sh_name = 7;
shstrtab->sh_type = SHT_STRTAB;
ehdr->e_shstrndx = elf_ndxscn(shstrtab_scn);
Elf32_Phdr *phdr = elf32_newphdr(elf, 1);
if (phdr == NULL) {
fprintf(stderr, "Cannot create PHDR: %s\n", elf_errmsg(elf_errno()));
elf_end(elf);
return 1;
}
phdr->p_type = PT_LOAD;
phdr->p_vaddr = 0;
phdr->p_paddr = 0;
phdr->p_flags = PF_R | PF_X;
if (elf_update(elf, ELF_C_NULL) < 0) {
fprintf(stderr, "Cannot write ELF: %s\n", elf_errmsg(elf_errno()));
elf_end(elf);
return 1;
}
phdr->p_offset = text->sh_offset;
phdr->p_filesz = text->sh_size;
phdr->p_memsz = text->sh_size;
if (elf_update(elf, ELF_C_WRITE) < 0) {
fprintf(stderr, "Cannot write ELF to disk: %s\n", elf_errmsg(elf_errno()));
elf_end(elf);
return 1;
}
elf_end(elf);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment