From 2b291399f5e9ba3882d49616cf4b1187b67e7745 Mon Sep 17 00:00:00 2001 From: Matthew Khouzam Date: Sun, 5 Apr 2020 15:45:54 -0400 Subject: Bug 561786 - Add unit tests for Elf Test on X86-64, i386, ppc64 and ppc32. Add Elf compiled executables to resources folder in order to ensure address coherence. Change-Id: Ie85636c9732cc41b6e5505ecf7acc783644bb442 Signed-off-by: Matthew Khouzam --- .../META-INF/MANIFEST.MF | 1 + .../misc/org/eclipse/cdt/utils/elf/ElfTest.java | 125 +++++++++++++++++++++ .../resources/elf/unit_test/Makefile | 2 + .../resources/elf/unit_test/readme.txt | 23 ++++ .../resources/elf/unit_test/simple-be32.elf | Bin 0 -> 69736 bytes .../resources/elf/unit_test/simple-be64.elf | Bin 0 -> 71144 bytes .../resources/elf/unit_test/simple-le32.elf | Bin 0 -> 8188 bytes .../resources/elf/unit_test/simple-le64.elf | Bin 0 -> 9576 bytes .../resources/elf/unit_test/simple.c | 9 ++ .../cdt/core/suite/AutomatedIntegrationSuite.java | 2 + 10 files changed, 162 insertions(+) create mode 100644 core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/utils/elf/ElfTest.java create mode 100644 core/org.eclipse.cdt.core.tests/resources/elf/unit_test/Makefile create mode 100644 core/org.eclipse.cdt.core.tests/resources/elf/unit_test/readme.txt create mode 100755 core/org.eclipse.cdt.core.tests/resources/elf/unit_test/simple-be32.elf create mode 100755 core/org.eclipse.cdt.core.tests/resources/elf/unit_test/simple-be64.elf create mode 100755 core/org.eclipse.cdt.core.tests/resources/elf/unit_test/simple-le32.elf create mode 100644 core/org.eclipse.cdt.core.tests/resources/elf/unit_test/simple-le64.elf create mode 100644 core/org.eclipse.cdt.core.tests/resources/elf/unit_test/simple.c (limited to 'core') diff --git a/core/org.eclipse.cdt.core.tests/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.core.tests/META-INF/MANIFEST.MF index 4c051c50dca..90068381a7a 100644 --- a/core/org.eclipse.cdt.core.tests/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.core.tests/META-INF/MANIFEST.MF @@ -35,6 +35,7 @@ Export-Package: org.eclipse.cdt.core.cdescriptor.tests, Require-Bundle: org.eclipse.core.resources, org.eclipse.cdt.core, org.junit, + org.eclipse.jdt.junit4.runtime, org.eclipse.core.runtime, org.eclipse.ui.ide, org.eclipse.ui, diff --git a/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/utils/elf/ElfTest.java b/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/utils/elf/ElfTest.java new file mode 100644 index 00000000000..0ac159bd2c8 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/misc/org/eclipse/cdt/utils/elf/ElfTest.java @@ -0,0 +1,125 @@ +/******************************************************************************* + * Copyright (c) 2020 Ericsson + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.cdt.utils.elf; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +import org.eclipse.cdt.utils.elf.Elf.Section; +import org.eclipse.cdt.utils.elf.Elf.Symbol; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +/** + * Elf reader test + * @author Matthew Khouzam + */ +@RunWith(Parameterized.class) +public class ElfTest { + + private static final String SYMTAB_NAME = ".symtab"; + + @Parameters(name = "{0}") + public static Collection elfArchitectures() { + return Arrays.asList(new Object[][] { + { "BE32", "resources/elf/unit_test/simple-be32.elf", 35, "0x00000000", "0x100001a8", 75, "0x10000518" }, + { "BE64", "resources/elf/unit_test/simple-be64.elf", 34, "0x0000000000000000", "0x0000000010000240", 69, + "0x000000001001fea0" }, + { "LE32", "resources/elf/unit_test/simple-le32.elf", 36, "0x00000000", "0x080481cc", 70, "0x080483e5" }, + { "LE64", "resources/elf/unit_test/simple-le64.elf", 36, "0x0000000000000000", "0x00000000004002b8", 68, + "0x00000000004004e4" }, }); + } + + private static final Collection functions = Arrays.asList("", "crtstuff.c", "simple.c", "crtstuff.c", + "_ITM_deregisterTMCloneTable", "__gmon_start__", "_Jv_RegisterClasses", "_ITM_registerTMCloneTable", + "_init", "_start", "deregister_tm_clones", "register_tm_clones", "__do_global_dtors_aux", "frame_dummy", + "function", "main", "__libc_csu_init", "__libc_csu_fini", "_fini", "_IO_stdin_used", "__FRAME_END__", + "__JCR_LIST__", "__JCR_END__", "_DYNAMIC", "data_start", "__data_start", "__dso_handle", "_edata", + "__bss_start", "__TMC_END__", "_end"); + + private final String arch; + private final Elf elf; + private final int nbSections; + private final String symtabBaseAddress; + private final String dynsymBaseAddress; + private final int nbSymbols; + private final String mainAddress; + + public ElfTest(String architecture, String path, int sections, String symBaseAddress, String dynBaseAddress, + int symbolCount, String mainAddr) throws IOException { + nbSections = sections; + elf = new Elf(path); + arch = architecture; + symtabBaseAddress = symBaseAddress; + dynsymBaseAddress = dynBaseAddress; + nbSymbols = symbolCount; + mainAddress = mainAddr; + } + + /** + * Test getting the sections + * @throws IOException + */ + @Test + public void testGetSections() throws IOException { + assertEquals(arch + ": " + "Number of sections", nbSections, elf.getSections().length); + Section sectionByName = elf.getSectionByName(SYMTAB_NAME); + assertNotNull(sectionByName); + assertEquals(arch + ": " + "symbol table", SYMTAB_NAME, sectionByName.toString()); + assertEquals(arch + ": " + "binary address", symtabBaseAddress, sectionByName.sh_addr.toHexAddressString()); + assertEquals(arch + ": " + "sh_name", 1, sectionByName.sh_name); + sectionByName = elf.getSectionByName(".dynsym"); + assertNotNull(sectionByName); + assertEquals(arch + ": " + "dynamic symbols", ".dynsym", sectionByName.toString()); + assertEquals(arch + ": " + "binary address", dynsymBaseAddress, sectionByName.sh_addr.toHexAddressString()); + assertEquals(arch + ": " + "sh_name", 78L, sectionByName.sh_name); + } + + /** + * Test getting symbols, this loads the symbols so it modifies the state of elf. + * @throws IOException + */ + @Test + public void testGetSymbols() throws IOException { + Section sectionByName = elf.getSectionByName(SYMTAB_NAME); + assertNotNull(sectionByName); + // never call Elf#LoadSymbols before this point + assertNull(arch + ": " + "Null symbols", elf.getSymbols()); + elf.loadSymbols(); + Symbol[] symbols = elf.getSymbols(); + assertNotNull(arch + ": " + "Symbols are set", symbols); + assertEquals(nbSymbols, symbols.length); + List functionList = Arrays.asList(symbols).stream().map(Symbol::toString).collect(Collectors.toList()); + for (String function : functions) { + assertTrue(arch + ": " + "Symbols does not contain \"" + function + '"', functionList.contains(function)); + } + Symbol symbol = null; + for (int i = 0; i < symbols.length; i++) { + if (symbols[i].toString().equals("main")) { + symbol = symbols[i]; + break; + } + } + assertNotNull(symbol); + assertEquals(arch + ": " + "Main address", mainAddress, symbol.st_value.toHexAddressString()); + } + +} diff --git a/core/org.eclipse.cdt.core.tests/resources/elf/unit_test/Makefile b/core/org.eclipse.cdt.core.tests/resources/elf/unit_test/Makefile new file mode 100644 index 00000000000..3bf7cf61345 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/resources/elf/unit_test/Makefile @@ -0,0 +1,2 @@ +#just an example +gcc simple.c -g -o simple.elf \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/resources/elf/unit_test/readme.txt b/core/org.eclipse.cdt.core.tests/resources/elf/unit_test/readme.txt new file mode 100644 index 00000000000..680713cecba --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/resources/elf/unit_test/readme.txt @@ -0,0 +1,23 @@ +## Adding elf files tests + +1- generate an elf file + +e.g. +`gcc simple.c -g -o simple-my_arch.elf + +where gcc is the appropriate compiler +examples of gcc in linux would be: +- aarch64-linux-gnu-gcc +- power-linux-gnu-gcc +... + +2- read certain fields: + +`readelf simple-my_arch.elf -s +or +`readelf simple-my_arch.elf -a + + +3- update ElfTest.java by adding the new architecture into the method "elfArchitectures" + +That is it. \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/resources/elf/unit_test/simple-be32.elf b/core/org.eclipse.cdt.core.tests/resources/elf/unit_test/simple-be32.elf new file mode 100755 index 00000000000..a94056380df Binary files /dev/null and b/core/org.eclipse.cdt.core.tests/resources/elf/unit_test/simple-be32.elf differ diff --git a/core/org.eclipse.cdt.core.tests/resources/elf/unit_test/simple-be64.elf b/core/org.eclipse.cdt.core.tests/resources/elf/unit_test/simple-be64.elf new file mode 100755 index 00000000000..0855753db3f Binary files /dev/null and b/core/org.eclipse.cdt.core.tests/resources/elf/unit_test/simple-be64.elf differ diff --git a/core/org.eclipse.cdt.core.tests/resources/elf/unit_test/simple-le32.elf b/core/org.eclipse.cdt.core.tests/resources/elf/unit_test/simple-le32.elf new file mode 100755 index 00000000000..89c539d3e36 Binary files /dev/null and b/core/org.eclipse.cdt.core.tests/resources/elf/unit_test/simple-le32.elf differ diff --git a/core/org.eclipse.cdt.core.tests/resources/elf/unit_test/simple-le64.elf b/core/org.eclipse.cdt.core.tests/resources/elf/unit_test/simple-le64.elf new file mode 100644 index 00000000000..be802b49046 Binary files /dev/null and b/core/org.eclipse.cdt.core.tests/resources/elf/unit_test/simple-le64.elf differ diff --git a/core/org.eclipse.cdt.core.tests/resources/elf/unit_test/simple.c b/core/org.eclipse.cdt.core.tests/resources/elf/unit_test/simple.c new file mode 100644 index 00000000000..ed52c24d253 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/resources/elf/unit_test/simple.c @@ -0,0 +1,9 @@ +int function(int argument) +{ + return 2 * argument; +} + +int main() +{ + return function(2); +} diff --git a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/suite/AutomatedIntegrationSuite.java b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/suite/AutomatedIntegrationSuite.java index cfa0142ad91..f8453660dce 100644 --- a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/suite/AutomatedIntegrationSuite.java +++ b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/suite/AutomatedIntegrationSuite.java @@ -45,6 +45,7 @@ import org.eclipse.cdt.utils.StorableCdtVariablesTest; import org.eclipse.cdt.utils.UNCPathConverterTest; import org.eclipse.cdt.utils.WeakHashSetTest; import org.eclipse.cdt.utils.elf.ElfParserTest; +import org.eclipse.cdt.utils.elf.ElfTest; import junit.framework.JUnit4TestAdapter; import junit.framework.Test; @@ -103,6 +104,7 @@ public class AutomatedIntegrationSuite extends TestSuite { suite.addTest(UNCPathConverterTest.suite()); suite.addTest(TestScopeOfBuildConfigResourceChangesPreference.suite()); suite.addTest(ElfParserTest.suite()); + suite.addTest(new JUnit4TestAdapter(ElfTest.class)); // Add in PDOM tests suite.addTest(PDOMTests.suite()); -- cgit v1.2.3