From f8e99df355fd2e23fa62b7aa781e546fe881b7da Mon Sep 17 00:00:00 2001
From: Joerg Wunsch <j@uriah.heep.sax.de>
Date: Wed, 18 Apr 2012 15:47:57 +0000
Subject: [PATCH] * fileio.c (elf_get_scn): Rather than trying to just match
 whether any given section maps straight to a program header segment, use a
 more sophisticated decision that matches any section as long as it fits into
 the segment.  This is needed for situations where the program header segment
 spans a larger area than the section data provided.  (This can e.g. happen in
 an ELF file that contains no data at address 0, like a bootloader only.)

git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@1079 81a1dc3b-b13d-400b-aceb-764788c761c2
---
 ChangeLog | 10 ++++++++++
 fileio.c  | 28 ++++++++++++++++++++++++++--
 2 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 37fac2da..65a04946 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2012-04-18  Joerg Wunsch <j.gnu@uriah.heep.sax.de>
+
+	* fileio.c (elf_get_scn): Rather than trying to just match whether
+	any given section maps straight to a program header segment, use a
+	more sophisticated decision that matches any section as long as it
+	fits into the segment.  This is needed for situations where the
+	program header segment spans a larger area than the section data
+	provided.  (This can e.g. happen in an ELF file that contains no
+	data at address 0, like a bootloader only.)
+
 2012-04-13  Joerg Wunsch <j.gnu@uriah.heep.sax.de>
 
 	bug #28744: Can't load bootloader to xmega128a1 (part 2, fix for
diff --git a/fileio.c b/fileio.c
index 3c5dc59e..0f859f19 100644
--- a/fileio.c
+++ b/fileio.c
@@ -687,6 +687,28 @@ static int srec2b(char * infile, FILE * inf,
 }
 
 #ifdef HAVE_LIBELF
+/*
+ * Determine whether the ELF file section pointed to by `sh' fits
+ * completely into the program header segment pointed to by `ph'.
+ *
+ * Assumes the section has been checked already before to actually
+ * contain data (SHF_ALLOC, SHT_PROGBITS, sh_size > 0).
+ *
+ * Sometimes, program header segments might be larger than the actual
+ * file sections.  On VM architectures, this is used to allow mmapping
+ * the entire ELF file "as is" (including things like the program
+ * header table itself).
+ */
+static inline
+int is_section_in_segment(Elf32_Shdr *sh, Elf32_Phdr *ph)
+{
+    if (sh->sh_offset < ph->p_offset)
+        return 0;
+    if (sh->sh_offset + sh->sh_size > ph->p_offset + ph->p_filesz)
+        return 0;
+    return 1;
+}
+
 /*
  * Return the ELF section descriptor that corresponds to program
  * header `ph'.  The program header is expected to be of p_type
@@ -711,8 +733,10 @@ static Elf_Scn *elf_get_scn(Elf *e, Elf32_Phdr *ph, Elf32_Shdr **shptr)
         sh->sh_type != SHT_PROGBITS)
       /* we are only interested in PROGBITS, ALLOC sections */
       continue;
-    if (ph->p_vaddr == sh->sh_addr &&
-        ph->p_offset == sh->sh_offset) {
+    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;