1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 06:02:11 +02:00

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 <matthew.khouzam@ericsson.com>
This commit is contained in:
Matthew Khouzam 2020-04-05 15:45:54 -04:00 committed by Alexander Fedorov
parent dd88f8ffca
commit 2b291399f5
11 changed files with 163 additions and 0 deletions

1
.gitattributes vendored
View file

@ -19,6 +19,7 @@ CONTRIBUTING text
*.h text *.h text
*.s text *.s text
*.S text *.S text
*.elf binary
# C-like configuration/scripts # C-like configuration/scripts
*.ac text *.ac text

View file

@ -35,6 +35,7 @@ Export-Package: org.eclipse.cdt.core.cdescriptor.tests,
Require-Bundle: org.eclipse.core.resources, Require-Bundle: org.eclipse.core.resources,
org.eclipse.cdt.core, org.eclipse.cdt.core,
org.junit, org.junit,
org.eclipse.jdt.junit4.runtime,
org.eclipse.core.runtime, org.eclipse.core.runtime,
org.eclipse.ui.ide, org.eclipse.ui.ide,
org.eclipse.ui, org.eclipse.ui,

View file

@ -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<Object[]> 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<String> 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<String> 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());
}
}

View file

@ -0,0 +1,2 @@
#just an example
gcc simple.c -g -o simple.elf

View file

@ -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.

View file

@ -0,0 +1,9 @@
int function(int argument)
{
return 2 * argument;
}
int main()
{
return function(2);
}

View file

@ -45,6 +45,7 @@ import org.eclipse.cdt.utils.StorableCdtVariablesTest;
import org.eclipse.cdt.utils.UNCPathConverterTest; import org.eclipse.cdt.utils.UNCPathConverterTest;
import org.eclipse.cdt.utils.WeakHashSetTest; import org.eclipse.cdt.utils.WeakHashSetTest;
import org.eclipse.cdt.utils.elf.ElfParserTest; import org.eclipse.cdt.utils.elf.ElfParserTest;
import org.eclipse.cdt.utils.elf.ElfTest;
import junit.framework.JUnit4TestAdapter; import junit.framework.JUnit4TestAdapter;
import junit.framework.Test; import junit.framework.Test;
@ -103,6 +104,7 @@ public class AutomatedIntegrationSuite extends TestSuite {
suite.addTest(UNCPathConverterTest.suite()); suite.addTest(UNCPathConverterTest.suite());
suite.addTest(TestScopeOfBuildConfigResourceChangesPreference.suite()); suite.addTest(TestScopeOfBuildConfigResourceChangesPreference.suite());
suite.addTest(ElfParserTest.suite()); suite.addTest(ElfParserTest.suite());
suite.addTest(new JUnit4TestAdapter(ElfTest.class));
// Add in PDOM tests // Add in PDOM tests
suite.addTest(PDOMTests.suite()); suite.addTest(PDOMTests.suite());