From 0ae632070fde8d7cea6095303555c50c1692baf8 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Thu, 1 Dec 2022 20:21:33 +0000 Subject: [PATCH 1/8] Rewrite elf2b() in equivalent way absorbing elf_get_scn() --- src/fileio.c | 82 +++++++++++++++------------------------------------- 1 file changed, 24 insertions(+), 58 deletions(-) diff --git a/src/fileio.c b/src/fileio.c index 79fccd5c..4eff1b92 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -708,41 +708,6 @@ int is_section_in_segment(Elf32_Shdr *sh, Elf32_Phdr *ph) return 1; } -/* - * Return the ELF section descriptor that corresponds to program - * header `ph'. The program header is expected to be of p_type - * PT_LOAD, and to have a nonzero p_filesz. (PT_LOAD sections with a - * zero p_filesz are typically RAM sections that are not initialized - * by file data, e.g. ".bss".) - */ -static Elf_Scn *elf_get_scn(Elf *e, Elf32_Phdr *ph, Elf32_Shdr **shptr) -{ - Elf_Scn *s = NULL; - - while ((s = elf_nextscn(e, s)) != NULL) { - Elf32_Shdr *sh; - size_t ndx = elf_ndxscn(s); - if ((sh = elf32_getshdr(s)) == NULL) { - pmsg_error("unable to read section #%u header: %s\n", (unsigned int)ndx, elf_errmsg(-1)); - continue; - } - if ((sh->sh_flags & SHF_ALLOC) == 0 || - sh->sh_type != SHT_PROGBITS) - /* we are only interested in PROGBITS, ALLOC sections */ - continue; - if (sh->sh_size == 0) - /* we are not interested in empty sections */ - continue; - if (is_section_in_segment(sh, ph)) { - /* yeah, we found it */ - *shptr = sh; - return s; - } - } - - pmsg_error("cannot find a matching section for program header entry @p_vaddr 0x%x\n", ph->p_vaddr); - return NULL; -} static int elf_mem_limits(const AVRMEM *mem, const AVRPART *p, unsigned int *lowbound, @@ -919,36 +884,37 @@ static int elf2b(const char *infile, FILE *inf, * PT_LOAD, and have a non-zero p_filesz. */ for (i = 0; i < eh->e_phnum; i++) { - if (ph[i].p_type != PT_LOAD || - ph[i].p_filesz == 0) + if (ph[i].p_type != PT_LOAD || ph[i].p_filesz == 0) continue; pmsg_notice2("considering PT_LOAD program header entry #%d:\n" " p_vaddr 0x%x, p_paddr 0x%x, p_filesz %d\n", (int) i, ph[i].p_vaddr, ph[i].p_paddr, ph[i].p_filesz); - Elf32_Shdr *sh; - Elf_Scn *s = elf_get_scn(e, ph + i, &sh); - if (s == NULL) - continue; + Elf_Scn *scn = NULL; + while ((scn = elf_nextscn(e, scn)) != NULL) { + size_t ndx = elf_ndxscn(scn); + Elf32_Shdr *sh = elf32_getshdr(scn); - if ((sh->sh_flags & SHF_ALLOC) && sh->sh_size) { - const char *sname; - - if (sndx != 0) { - sname = elf_strptr(e, sndx, sh->sh_name); - } else { - sname = "*unknown*"; + if (sh == NULL) { + pmsg_error("unable to read section #%u header: %s\n", (unsigned int) ndx, elf_errmsg(-1)); + continue; } + // Only interested in PROGBITS, ALLOC sections + if ((sh->sh_flags & SHF_ALLOC) == 0 || sh->sh_type != SHT_PROGBITS) + continue; + // Not interested in empty sections + if (sh->sh_size == 0) + continue; + // Section must belong to this segment + if (!is_section_in_segment(sh, ph+i)) + continue; - unsigned int lma; - lma = ph[i].p_paddr + sh->sh_offset - ph[i].p_offset; + const char *sname = sndx? elf_strptr(e, sndx, sh->sh_name): "*unknown*"; + unsigned int lma = ph[i].p_paddr + sh->sh_offset - ph[i].p_offset; pmsg_notice2("found section %s, LMA 0x%x, sh_size %u\n", sname, lma, sh->sh_size); - if (lma >= low && - lma + sh->sh_size < high) { - /* OK */ - } else { + if(!(lma >= low && lma + sh->sh_size < high)) { msg_notice2(" => skipping, inappropriate for %s memory region\n", mem->desc); continue; } @@ -967,17 +933,16 @@ static int elf2b(const char *infile, FILE *inf, } Elf_Data *d = NULL; - while ((d = elf_getdata(s, d)) != NULL) { + while ((d = elf_getdata(scn, d)) != NULL) { msg_notice2(" Data block: d_buf %p, d_off 0x%x, d_size %ld\n", - d->d_buf, (unsigned int)d->d_off, (long) d->d_size); + d->d_buf, (unsigned int)d->d_off, (long) d->d_size); if (mem->size == 1) { if (d->d_off != 0) { pmsg_error("unexpected data block at offset != 0\n"); } else if (foff >= d->d_size) { pmsg_error("ELF file section does not contain byte at offset %d\n", foff); } else { - msg_notice2(" Extracting one byte from file offset %d\n", - foff); + msg_notice2(" Extracting one byte from file offset %d\n", foff); mem->buf[0] = ((unsigned char *)d->d_buf)[foff]; mem->tags[0] = TAG_ALLOCATED; rv = 1; @@ -994,6 +959,7 @@ static int elf2b(const char *infile, FILE *inf, memset(mem->tags + idx, TAG_ALLOCATED, d->d_size); } } + break; // Stop after first section in program header } } done: From 3b30e5d424fdcbd9f1b550c3f69359e9a462e673 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Thu, 1 Dec 2022 20:28:56 +0000 Subject: [PATCH 2/8] Fix elf2b() to consider all sections in segments --- src/fileio.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/fileio.c b/src/fileio.c index 4eff1b92..33f258cb 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -959,7 +959,6 @@ static int elf2b(const char *infile, FILE *inf, memset(mem->tags + idx, TAG_ALLOCATED, d->d_size); } } - break; // Stop after first section in program header } } done: From 2e98ee3a1c2e89d779e86caec7fb9aa7d00a3ebf Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Fri, 2 Dec 2022 18:28:19 +0000 Subject: [PATCH 3/8] Check elf section fits into memory and fail elf2b() on elf handling errors --- src/fileio.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/fileio.c b/src/fileio.c index 33f258cb..97e31683 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -772,7 +772,7 @@ static int elf2b(const char *infile, FILE *inf, int bufsize, unsigned int fileoffset) { Elf *e; - int rv = -1; + int rv = 0, size = 0; unsigned int low, high, foff; if (elf_mem_limits(mem, p, &low, &high, &foff) != 0) { @@ -897,6 +897,7 @@ static int elf2b(const char *infile, FILE *inf, if (sh == NULL) { pmsg_error("unable to read section #%u header: %s\n", (unsigned int) ndx, elf_errmsg(-1)); + rv = -1; continue; } // Only interested in PROGBITS, ALLOC sections @@ -927,8 +928,9 @@ static int elf2b(const char *infile, FILE *inf, * from it, using the "foff" offset obtained above. */ if (mem->size != 1 && sh->sh_size > (unsigned) mem->size) { - pmsg_error("section %s does not fit into %s memory:\n" - " 0x%x + %u > %u\n", sname, mem->desc, lma, sh->sh_size, mem->size); + pmsg_error("section %s of size %u does not fit into %s of size %d\n", + sname, sh->sh_size, mem->desc, mem->size); + rv = -1; continue; } @@ -939,31 +941,38 @@ static int elf2b(const char *infile, FILE *inf, if (mem->size == 1) { if (d->d_off != 0) { pmsg_error("unexpected data block at offset != 0\n"); + rv = -1; } else if (foff >= d->d_size) { pmsg_error("ELF file section does not contain byte at offset %d\n", foff); + rv = -1; } else { msg_notice2(" Extracting one byte from file offset %d\n", foff); mem->buf[0] = ((unsigned char *)d->d_buf)[foff]; mem->tags[0] = TAG_ALLOCATED; - rv = 1; + size = 1; } } else { - unsigned int idx; + int idx = lma-low + d->d_off; + int end = idx + d->d_size; - idx = lma - low + d->d_off; - if ((int)(idx + d->d_size) > rv) - rv = idx + d->d_size; - msg_debug(" Writing %ld bytes to mem offset 0x%x\n", - (long) d->d_size, idx); - memcpy(mem->buf + idx, d->d_buf, d->d_size); - memset(mem->tags + idx, TAG_ALLOCATED, d->d_size); + if(idx >= 0 && idx < mem->size && end >= 0 && end <= mem->size && end-idx >= 0) { + if (end > size) + size = end; + imsg_debug("writing %d bytes to mem offset 0x%x\n", end-idx, idx); + memcpy(mem->buf + idx, d->d_buf, end-idx); + memset(mem->tags + idx, TAG_ALLOCATED, end-idx); + } else { + pmsg_error("section %s [0x%04x, 0x%04x] does not fit into %s [0, 0x%04x]\n", + sname, idx, (int) (idx + d->d_size-1), mem->desc, mem->size-1); + rv = -1; + } } } } } done: (void)elf_end(e); - return rv; + return rv<0? rv: size; } #endif /* HAVE_LIBELF */ From f688baabb770645002d6a3cdf64770662c83f058 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Fri, 2 Dec 2022 18:45:47 +0000 Subject: [PATCH 4/8] Improve error messaging --- src/fileio.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/fileio.c b/src/fileio.c index 97e31683..d9a1d1d0 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -887,8 +887,8 @@ static int elf2b(const char *infile, FILE *inf, if (ph[i].p_type != PT_LOAD || ph[i].p_filesz == 0) continue; - pmsg_notice2("considering PT_LOAD program header entry #%d:\n" - " p_vaddr 0x%x, p_paddr 0x%x, p_filesz %d\n", (int) i, ph[i].p_vaddr, ph[i].p_paddr, ph[i].p_filesz); + pmsg_notice2("considering PT_LOAD program header entry #%d\n", (int) i); + imsg_notice2("p_vaddr 0x%x, p_paddr 0x%x, p_filesz %d\n", ph[i].p_vaddr, ph[i].p_paddr, ph[i].p_filesz); Elf_Scn *scn = NULL; while ((scn = elf_nextscn(e, scn)) != NULL) { @@ -916,7 +916,7 @@ static int elf2b(const char *infile, FILE *inf, pmsg_notice2("found section %s, LMA 0x%x, sh_size %u\n", sname, lma, sh->sh_size); if(!(lma >= low && lma + sh->sh_size < high)) { - msg_notice2(" => skipping, inappropriate for %s memory region\n", mem->desc); + imsg_notice2("skipping %s (inappropriate for %s)\n", sname, mem->desc); continue; } /* @@ -936,7 +936,7 @@ static int elf2b(const char *infile, FILE *inf, Elf_Data *d = NULL; while ((d = elf_getdata(scn, d)) != NULL) { - msg_notice2(" Data block: d_buf %p, d_off 0x%x, d_size %ld\n", + imsg_notice2("data block: d_buf %p, d_off 0x%x, d_size %ld\n", d->d_buf, (unsigned int)d->d_off, (long) d->d_size); if (mem->size == 1) { if (d->d_off != 0) { @@ -946,7 +946,7 @@ static int elf2b(const char *infile, FILE *inf, pmsg_error("ELF file section does not contain byte at offset %d\n", foff); rv = -1; } else { - msg_notice2(" Extracting one byte from file offset %d\n", foff); + imsg_notice2("extracting one byte from file offset %d\n", foff); mem->buf[0] = ((unsigned char *)d->d_buf)[foff]; mem->tags[0] = TAG_ALLOCATED; size = 1; From 23dddef64badfa9078bc8fad5cdf3d91b29fd684 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Fri, 2 Dec 2022 19:03:06 +0000 Subject: [PATCH 5/8] Mark unused function parameters as such --- src/fileio.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/fileio.c b/src/fileio.c index d9a1d1d0..24047e7a 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -118,10 +118,9 @@ char * fileio_fmtstr(FILEFMT format) } -static int b2ihex(const unsigned char *inbuf, int bufsize, - int recsize, int startaddr, - const char *outfile, FILE *outf, FILEFMT ffmt) -{ +static int b2ihex(const unsigned char *inbuf, int bufsize, int recsize, + int startaddr, const char *outfile_unused, FILE *outf, FILEFMT ffmt) { + const unsigned char *buf; unsigned int nextaddr; int n, nbytes, n_64k; @@ -397,10 +396,9 @@ static int ihex2b(const char *infile, FILE *inf, } } -static int b2srec(const unsigned char *inbuf, int bufsize, - int recsize, int startaddr, - const char *outfile, FILE *outf) -{ +static int b2srec(const unsigned char *inbuf, int bufsize, int recsize, + int startaddr, const char *outfile_unused, FILE *outf) { + const unsigned char *buf; unsigned int nextaddr; int n, nbytes, addr_width; @@ -767,10 +765,9 @@ static int elf_mem_limits(const AVRMEM *mem, const AVRPART *p, } -static int elf2b(const char *infile, FILE *inf, - const AVRMEM *mem, const AVRPART *p, - int bufsize, unsigned int fileoffset) -{ +static int elf2b(const char *infile, FILE *inf, const AVRMEM *mem, + const AVRPART *p, int bufsize_unused, unsigned int fileoffset_unused) { + Elf *e; int rv = 0, size = 0; unsigned int low, high, foff; @@ -1045,9 +1042,9 @@ static int fileio_rbin(struct fioparms *fio, } -static int fileio_imm(struct fioparms *fio, - const char *fname, FILE *f, const AVRMEM *mem, int size) -{ +static int fileio_imm(struct fioparms *fio, const char *fname, FILE *f_unused, + const AVRMEM *mem, int size) { + int rc = 0; char *e, *p, *filename; unsigned long b; From 6b03d7dc5aa520329cc378d284598e8790b80fae Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Sat, 3 Dec 2022 13:37:44 +0000 Subject: [PATCH 6/8] Correct upper flash boundary for 8-bit AVR parts in elf_mem_limits() --- src/fileio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fileio.c b/src/fileio.c index 24047e7a..b2f29bf7 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -728,11 +728,11 @@ static int elf_mem_limits(const AVRMEM *mem, const AVRPART *p, strcmp(mem->desc, "application") == 0 || strcmp(mem->desc, "apptable") == 0) { *lowbound = 0; - *highbound = 0x7ffff; /* max 8 MiB */ + *highbound = 0x7Fffff; // Max 8 MiB *fileoff = 0; } else if (strcmp(mem->desc, "eeprom") == 0) { *lowbound = 0x810000; - *highbound = 0x81ffff; /* max 64 KiB */ + *highbound = 0x81ffff; // Max 64 KiB *fileoff = 0; } else if (strcmp(mem->desc, "lfuse") == 0) { *lowbound = 0x820000; From db0258a7d8e6b2067f99d7127d7ce32d23c92846 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Sat, 10 Dec 2022 23:28:56 +0000 Subject: [PATCH 7/8] Add fuses, usersig, userrow, signature and data to elf_mem_limits() --- src/fileio.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/fileio.c b/src/fileio.c index b2f29bf7..77cedbe3 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -730,11 +730,15 @@ static int elf_mem_limits(const AVRMEM *mem, const AVRPART *p, *lowbound = 0; *highbound = 0x7Fffff; // Max 8 MiB *fileoff = 0; + } else if (strcmp(mem->desc, "data") == 0) { // Volatile SRAM for XMEGA (not the .data section) + *lowbound = 0x802000; + *highbound = 0x80ffff; + *fileoff = 0; } else if (strcmp(mem->desc, "eeprom") == 0) { *lowbound = 0x810000; *highbound = 0x81ffff; // Max 64 KiB *fileoff = 0; - } else if (strcmp(mem->desc, "lfuse") == 0) { + } else if (strcmp(mem->desc, "lfuse") == 0 || strcmp(mem->desc, "fuses") == 0) { *lowbound = 0x820000; *highbound = 0x82ffff; *fileoff = 0; @@ -752,10 +756,18 @@ static int elf_mem_limits(const AVRMEM *mem, const AVRPART *p, *lowbound = 0x820000; *highbound = 0x82ffff; *fileoff = mem->desc[4] - '0'; - } else if (strncmp(mem->desc, "lock", 4) == 0) { + } else if (strncmp(mem->desc, "lock", 4) == 0) { // Lock or lockbits *lowbound = 0x830000; *highbound = 0x83ffff; *fileoff = 0; + } else if (strcmp(mem->desc, "signature") == 0) { // Read only + *lowbound = 0x840000; + *highbound = 0x84ffff; + *fileoff = 0; + } else if (strncmp(mem->desc, "user", 4) == 0) { // Usersig or userrow + *lowbound = 0x850000; + *highbound = 0x85ffff; + *fileoff = 0; } else { rv = -1; } From e4f10a33ab1d1d32367b97065a4efe577a8d5218 Mon Sep 17 00:00:00 2001 From: Stefan Rueger Date: Tue, 13 Dec 2022 23:59:58 +0000 Subject: [PATCH 8/8] Clarify comment --- src/fileio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fileio.c b/src/fileio.c index 77cedbe3..482bb3a6 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -730,7 +730,7 @@ static int elf_mem_limits(const AVRMEM *mem, const AVRPART *p, *lowbound = 0; *highbound = 0x7Fffff; // Max 8 MiB *fileoff = 0; - } else if (strcmp(mem->desc, "data") == 0) { // Volatile SRAM for XMEGA (not the .data section) + } else if (strcmp(mem->desc, "data") == 0) { // SRAM for XMEGAs *lowbound = 0x802000; *highbound = 0x80ffff; *fileoff = 0;