Bug 569581 - Rethrow IOException in ElfParser.hasInterpProgramHeader()

This change adjusts behavior in ElfParser.hasInterpProgramHeader()
(added for bug 512822) to throw an IOException that occurred, as opposed
to logging the exception and continuing. This excludes exceptions thrown
by Elf.getSections() indicating that ELFhdr.ELFCLASSNONE is read; a new,
more specific IOException type is defined to allow handling this as a
special case.

A "generic" IOException indicates an I/O problem with the binary. E.g.
the binary can be deleted by the user or by Eclipse, while being visited
in CModelManager. If hasInterpProgramHeader() returns instead of
throwing, more problems can occur "later on".

Change-Id: I8852d9cbaa17dc97f668bb1666e9b046bbde1fca
Signed-off-by: Simeon Andreev <simeon.danailov.andreev@gmail.com>
diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/Elf.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/Elf.java
index c633447..42f67a6 100644
--- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/Elf.java
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/Elf.java
@@ -1029,6 +1029,9 @@
 		return slist.toArray(new Section[0]);
 	}
 
+	/**
+	 * @throws ElfClassNoneException if {@link ELFhdr#ELFCLASSNONE} header is read
+	 */
 	public Section[] getSections() throws IOException {
 		if (sections == null) {
 			if (ehdr.e_shoff == 0) {
@@ -1063,7 +1066,7 @@
 					break;
 				case ELFhdr.ELFCLASSNONE:
 				default:
-					throw new IOException("Unknown ELF class " + ehdr.e_ident[ELFhdr.EI_CLASS]); //$NON-NLS-1$
+					throw new ElfClassNoneException("Unknown ELF class " + ehdr.e_ident[ELFhdr.EI_CLASS]); //$NON-NLS-1$
 				}
 
 				sections[i].sh_link = efile.readIntE();
@@ -1081,7 +1084,7 @@
 					break;
 				case ELFhdr.ELFCLASSNONE:
 				default:
-					throw new IOException("Unknown ELF class " + ehdr.e_ident[ELFhdr.EI_CLASS]); //$NON-NLS-1$
+					throw new ElfClassNoneException("Unknown ELF class " + ehdr.e_ident[ELFhdr.EI_CLASS]); //$NON-NLS-1$
 				}
 			}
 		}
@@ -1316,4 +1319,16 @@
 		}
 		return result;
 	}
+
+	/**
+	 * Exception indicating that {@link ELFhdr#ELFCLASSNONE} header is read.
+	 *
+	 * @since 7.1
+	 */
+	public static class ElfClassNoneException extends IOException {
+
+		ElfClassNoneException(String message) {
+			super(message);
+		}
+	}
 }
diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/ElfParser.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/ElfParser.java
index c1c245a..0e4da98 100644
--- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/ElfParser.java
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/ElfParser.java
@@ -29,6 +29,7 @@
 import org.eclipse.cdt.utils.elf.Elf;
 import org.eclipse.cdt.utils.elf.Elf.Attribute;
 import org.eclipse.cdt.utils.elf.Elf.ELFhdr;
+import org.eclipse.cdt.utils.elf.Elf.ElfClassNoneException;
 import org.eclipse.cdt.utils.elf.Elf.PHdr;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IStatus;
@@ -177,7 +178,7 @@
 		try {
 			/* No PHdr.PT_INTERP found in the hints meaning we need to read the file itself */
 			return Arrays.stream(getPHdrs(path)).anyMatch(phdr -> phdr.p_type == PHdr.PT_INTERP);
-		} catch (IOException e) {
+		} catch (ElfClassNoneException e) {
 			CCorePlugin.log(e);
 		}
 		return false;