diff options
Diffstat (limited to 'core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/ElfParser.java')
-rw-r--r-- | core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/elf/parser/ElfParser.java | 82 |
1 files changed, 68 insertions, 14 deletions
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 108ed1b40d6..65f1e2d2a13 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 @@ -8,11 +8,16 @@ * Contributors: * QNX Software Systems - Initial API and implementation * Anton Leherbauer (Wind River Systems) + * Hansruedi Patzen (IFS) *******************************************************************************/ package org.eclipse.cdt.utils.elf.parser; +import static org.eclipse.cdt.internal.core.ByteUtils.makeShort; +import static org.eclipse.cdt.internal.core.ByteUtils.makeInt; + import java.io.EOFException; import java.io.IOException; +import java.util.Arrays; import org.eclipse.cdt.core.AbstractCExtension; import org.eclipse.cdt.core.CCorePlugin; @@ -20,7 +25,10 @@ import org.eclipse.cdt.core.IBinaryParser; import org.eclipse.cdt.utils.AR; 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.PHdr; import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; /** */ @@ -46,19 +54,7 @@ public class ElfParser extends AbstractCExtension implements IBinaryParser { binary = createBinaryArchive(path); } else { try { - Elf.Attribute attribute = null; - if (hints != null && Elf.isElfHeader(hints)) { - try { - attribute = Elf.getAttributes(hints); - } catch (EOFException eof) { - // continue, the array was to small. - } - } - - //Take a second run at it if the data array failed. - if(attribute == null) { - attribute = Elf.getAttributes(path.toOSString()); - } + Attribute attribute = getAttribute(hints, path); if (attribute != null) { switch (attribute.getType()) { @@ -67,7 +63,7 @@ public class ElfParser extends AbstractCExtension implements IBinaryParser { break; case Attribute.ELF_TYPE_SHLIB : - binary = createBinaryShared(path); + binary = hasInterpProgramHeader(hints, path) ? createBinaryExecutable(path) : createBinaryShared(path); break; case Attribute.ELF_TYPE_OBJ : @@ -139,4 +135,62 @@ public class ElfParser extends AbstractCExtension implements IBinaryParser { protected IBinaryObject createBinaryCore(IPath path) throws IOException { return new ElfBinaryObject(this, path, IBinaryFile.CORE); } + + private static Elf.Attribute getAttribute(byte[] hints, IPath path) throws IOException { + if (Elf.isElfHeader(hints)) { + try { + return Elf.getAttributes(hints); + } catch (EOFException eof) { + // continue, the array was to small. + } + } + return Elf.getAttributes(path.toOSString()); + } + + private static boolean hasInterpProgramHeader(byte[] hints, IPath path) throws IOException { + if (Elf.isElfHeader(hints)) { + int e_phentsizeOffset = 0; + int e_phnumOffset = 0; + int e_ehsizeOffset = 0; + switch (hints[ELFhdr.EI_CLASS]) { + case ELFhdr.ELFCLASS32: + e_ehsizeOffset = 0x28; + e_phentsizeOffset = 0x2A; + e_phnumOffset = 0x2C; + break; + case ELFhdr.ELFCLASS64: + e_ehsizeOffset = 0x34; + e_phentsizeOffset = 0x36; + e_phnumOffset = 0x38; + break; + default: + CCorePlugin.log(IStatus.WARNING, "Unknown ELF header class in file: " + path.toOSString()); //$NON-NLS-1$ + return false; + } + if (e_phnumOffset + 2 < hints.length) { + boolean isle = (hints[ELFhdr.EI_DATA] == ELFhdr.ELFDATA2LSB); + short e_phentsize = makeShort(hints, e_phentsizeOffset, isle); + short e_phnum = makeShort(hints, e_phnumOffset, isle); + short e_ehsize = makeShort(hints, e_ehsizeOffset, isle); + int lastProgramHeaderOffset = e_ehsize + (e_phnum - 1) * e_phentsize; + for (int i = e_ehsize; i < Math.min(lastProgramHeaderOffset, hints.length) + 4; i += e_phentsize) { + if (makeInt(hints, i, isle) == PHdr.PT_INTERP) { + return true; + } + } + /* See if we checked every program header type */ + if (lastProgramHeaderOffset + 4 < hints.length) { + return false; + } + } + } + + try { + /* No PHdr.PT_INTERP found in the hints meaning we need to read the file itself */ + return Arrays.stream(new Elf(path.toOSString()).getPHdrs()).anyMatch(phdr -> phdr.p_type == PHdr.PT_INTERP); + } catch (IOException e) { + CCorePlugin.log(e); + } + return false; + } } |