* fileio.c: Rework the way ELF file sections are considered: while

scanning the program header table, the offsets from a program
header entry must never be used directly when checking the bounds
of the current AVR memory region.  Instead, they must always be
checked based on the corresponding section's entry.  That way,
Xmega devices now properly take into account whether the segment
fits into any of the application/apptable/boot memory region.



git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@1085 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
joerg_wunsch 2012-04-24 15:41:02 +00:00
parent 98d2f6fff8
commit 80dd0439a8
2 changed files with 93 additions and 29 deletions

View File

@ -1,3 +1,13 @@
2012-04-24 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* fileio.c: Rework the way ELF file sections are considered: while
scanning the program header table, the offsets from a program
header entry must never be used directly when checking the bounds
of the current AVR memory region. Instead, they must always be
checked based on the corresponding section's entry. That way,
Xmega devices now properly take into account whether the segment
fits into any of the application/apptable/boot memory region.
2012-04-20 Joerg Wunsch <j.gnu@uriah.heep.sax.de> 2012-04-20 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
bug #30756: When setting SUT to 64ms on XMEGA, avrdude doesn't bug #30756: When setting SUT to 64ms on XMEGA, avrdude doesn't

View File

@ -766,7 +766,10 @@ static int elf_mem_limits(AVRMEM *mem, struct avrpart * p,
rv = -1; rv = -1;
} }
} else { } else {
if (strcmp(mem->desc, "flash") == 0) { if (strcmp(mem->desc, "flash") == 0 ||
strcmp(mem->desc, "boot") == 0 ||
strcmp(mem->desc, "application") == 0 ||
strcmp(mem->desc, "apptable") == 0) {
*lowbound = 0; *lowbound = 0;
*highbound = 0x7ffff; /* max 8 MiB */ *highbound = 0x7ffff; /* max 8 MiB */
*fileoff = 0; *fileoff = 0;
@ -820,6 +823,30 @@ static int elf2b(char * infile, FILE * inf,
return -1; return -1;
} }
/*
* The Xmega memory regions for "boot", "application", and
* "apptable" are actually sub-regions of "flash". Refine the
* applicable limits. This allows to select only the appropriate
* sections out of an ELF file that contains section data for more
* than one sub-segment.
*/
if ((p->flags & AVRPART_HAS_PDI) != 0 &&
(strcmp(mem->desc, "boot") == 0 ||
strcmp(mem->desc, "application") == 0 ||
strcmp(mem->desc, "apptable") == 0)) {
AVRMEM *flashmem = avr_locate_mem(p, "flash");
if (flashmem == NULL) {
fprintf(stderr,
"%s: ERROR: No \"flash\" memory region found, "
"cannot compute bounds of \"%s\" sub-region.\n",
progname, mem->desc);
return -1;
}
/* The config file offsets are PDI offsets, rebase to 0. */
low = mem->offset - flashmem->offset;
high = low + mem->size - 1;
}
if (elf_version(EV_CURRENT) == EV_NONE) { if (elf_version(EV_CURRENT) == EV_NONE) {
fprintf(stderr, fprintf(stderr,
"%s: ERROR: ELF library initialization failed: %s\n", "%s: ERROR: ELF library initialization failed: %s\n",
@ -913,6 +940,14 @@ static int elf2b(char * infile, FILE * inf,
goto done; goto done;
} }
size_t sndx;
if (elf_getshstrndx(e, &sndx) != 0) {
fprintf(stderr,
"%s: ERROR: Error obtaining section name string table: %s\n",
progname, elf_errmsg(-1));
sndx = 0;
}
/* /*
* Walk the program header table, pick up entries that are of type * Walk the program header table, pick up entries that are of type
* PT_LOAD, and have a non-zero p_filesz. * PT_LOAD, and have a non-zero p_filesz.
@ -928,8 +963,32 @@ static int elf2b(char * infile, FILE * inf,
" p_vaddr 0x%x, p_paddr 0x%x, p_filesz %d\n", " p_vaddr 0x%x, p_paddr 0x%x, p_filesz %d\n",
progname, i, ph[i].p_vaddr, ph[i].p_paddr, ph[i].p_filesz); progname, i, ph[i].p_vaddr, ph[i].p_paddr, ph[i].p_filesz);
} }
if (ph[i].p_paddr >= low &&
ph[i].p_paddr < high) { Elf32_Shdr *sh;
Elf_Scn *s = elf_get_scn(e, ph + i, &sh);
if (s == NULL)
continue;
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*";
}
unsigned int lma;
lma = ph[i].p_paddr + sh->sh_offset - ph[i].p_offset;
if (verbose >= 2) {
fprintf(stderr,
"%s: Found section \"%s\", LMA 0x%x, sh_size %u\n",
progname, sname, lma, sh->sh_size);
}
if (lma >= low &&
lma + sh->sh_size < high) {
/* OK */ /* OK */
} else { } else {
if (verbose >= 2) { if (verbose >= 2) {
@ -948,20 +1007,15 @@ static int elf2b(char * infile, FILE * inf,
* from it, using the "foff" offset obtained above. * from it, using the "foff" offset obtained above.
*/ */
if (mem->size != 1 && if (mem->size != 1 &&
ph[i].p_paddr - low + ph[i].p_filesz > mem->size) { sh->sh_size > mem->size) {
fprintf(stderr, fprintf(stderr,
"%s: ERROR: program header entry #%d does not fit into \"%s\" memory:\n" "%s: ERROR: section \"%s\" does not fit into \"%s\" memory:\n"
" 0x%x + %u > %u\n", " 0x%x + %u > %u\n",
progname, i, mem->desc, ph[i].p_paddr, ph[i].p_filesz, mem->size); progname, sname, mem->desc,
lma, sh->sh_size, mem->size);
continue; continue;
} }
Elf32_Shdr *sh;
Elf_Scn *s = elf_get_scn(e, ph + i, &sh);
if (s == NULL)
continue;
if ((sh->sh_flags & SHF_ALLOC) && sh->sh_size) {
Elf_Data *d = NULL; Elf_Data *d = NULL;
while ((d = elf_getdata(s, d)) != NULL) { while ((d = elf_getdata(s, d)) != NULL) {
if (verbose >= 2) { if (verbose >= 2) {
@ -991,7 +1045,7 @@ static int elf2b(char * infile, FILE * inf,
} else { } else {
unsigned int idx; unsigned int idx;
idx = ph[i].p_paddr - low + d->d_off; idx = lma - low + d->d_off;
if ((int)(idx + d->d_size) > rv) if ((int)(idx + d->d_size) > rv)
rv = idx + d->d_size; rv = idx + d->d_size;
if (verbose >= 3) { if (verbose >= 3) {