Skip to content

Commit

Permalink
test: check contents of ELF symbol and relocation tables
Browse files Browse the repository at this point in the history
  • Loading branch information
boricj committed Jun 12, 2024
1 parent 869dcd5 commit 6cf8cd2
Show file tree
Hide file tree
Showing 5 changed files with 399 additions and 19 deletions.
67 changes: 67 additions & 0 deletions src/test/java/ghidra/DelinkerIntegrationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.AccessMode;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
Expand All @@ -40,6 +42,12 @@
import ghidra.app.util.bin.format.coff.CoffSectionHeader;
import ghidra.app.util.bin.format.elf.ElfException;
import ghidra.app.util.bin.format.elf.ElfHeader;
import ghidra.app.util.bin.format.elf.ElfRelocation;
import ghidra.app.util.bin.format.elf.ElfRelocationTable;
import ghidra.app.util.bin.format.elf.ElfSectionHeader;
import ghidra.app.util.bin.format.elf.ElfSectionHeaderConstants;
import ghidra.app.util.bin.format.elf.ElfSymbol;
import ghidra.app.util.bin.format.elf.ElfSymbolTable;
import ghidra.app.util.exporter.Exporter;
import ghidra.app.util.importer.MessageLog;
import ghidra.framework.GModule;
Expand Down Expand Up @@ -111,6 +119,65 @@ public ElfObjectFile(File file) throws ElfException, IOException {
public byte[] getSectionBytes(String name) throws IOException {
return header.getSection(name).getRawInputStream().readAllBytes();
}

public void hasSymbolAtAddress(String symbolTable, String symbolName, String sectionName,
int offset) {
ElfSymbolTable symtab = getSymbolTable(symbolTable);

List<ElfSymbol> symbols = Arrays.asList(symtab.getSymbols());
assertTrue(symbols.stream()
.filter(symbol -> symbol.getNameAsString().equals(symbolName))
.anyMatch(symbol -> {
ElfSectionHeader section =
header.getSections()[symbol.getSectionHeaderIndex()];
return section.getNameAsString().equals(sectionName) &&
symbol.getValue() == offset;
}));
}

public void hasUndefinedSymbol(String symbolTable, String symbolName) {
ElfSymbolTable symtab = getSymbolTable(symbolTable);

List<ElfSymbol> symbols = Arrays.asList(symtab.getSymbols());
assertTrue(symbols.stream()
.filter(symbol -> symbol.getNameAsString().equals(symbolName))
.anyMatch(symbol -> symbol
.getSectionHeaderIndex() == ElfSectionHeaderConstants.SHN_UNDEF));
}

public void hasRelocationAtAddress(String relTable, long offset, int type,
String symbolName, long value) {
ElfRelocationTable rel = getRelocationTable(relTable);
ElfSymbolTable symtab = rel.getAssociatedSymbolTable();

List<ElfRelocation> rels = Arrays.asList(rel.getRelocations());
assertTrue(rels.stream()
.filter(r -> r.getOffset() == offset)
.anyMatch(r -> r.getType() == type && r.getAddend() == value &&
symtab.getSymbol(r.getSymbolIndex()).getNameAsString().equals(symbolName)));
}

private ElfSymbolTable getSymbolTable(String name) {
ElfSymbolTable symtab = Arrays.asList(header.getSymbolTables())
.stream()
.filter(t -> t.getTableSectionHeader().getNameAsString().equals(name))
.findFirst()
.orElse(null);
assertNotNull(symtab);

return symtab;
}

private ElfRelocationTable getRelocationTable(String name) {
ElfRelocationTable relTable = Arrays.asList(header.getRelocationTables())
.stream()
.filter(t -> t.getTableSectionHeader().getNameAsString().equals(name))
.findFirst()
.orElse(null);
assertNotNull(relTable);

return relTable;
}
}

public class CoffObjectFile implements ObjectFile {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.junit.Test;

import ghidra.DelinkerIntegrationTest;
import ghidra.app.util.bin.format.elf.relocation.X86_32_ElfRelocationType;
import ghidra.app.util.exporter.ElfRelocatableObjectExporter;
import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.address.AddressSetView;
Expand All @@ -39,10 +40,46 @@ public void testExport_ctype_o() throws Exception {
File exportedFile = exportObjectFile(set, new ElfRelocatableObjectExporter(), null);

ObjectFile ctypeObjectFile = new ElfObjectFile(ctypeFile);
ObjectFile exportedObjectFile = new ElfObjectFile(exportedFile);
ElfObjectFile exported = new ElfObjectFile(exportedFile);

ctypeObjectFile.compareSectionBytes(".text", exportedObjectFile, ".text");
ctypeObjectFile.compareSectionSizes(".rel.text", exportedObjectFile, ".rel.text");
ctypeObjectFile.compareSectionBytes(".rodata", exportedObjectFile, ".rodata");
ctypeObjectFile.compareSectionBytes(".text", exported, ".text");
ctypeObjectFile.compareSectionSizes(".rel.text", exported, ".rel.text");
ctypeObjectFile.compareSectionBytes(".rodata", exported, ".rodata");

exported.hasSymbolAtAddress(".symtab", "isalnum", ".text", 0x00000000);
exported.hasSymbolAtAddress(".symtab", "isalpha", ".text", 0x0000001d);
exported.hasSymbolAtAddress(".symtab", "iscntrl", ".text", 0x0000003a);
exported.hasSymbolAtAddress(".symtab", "isdigit", ".text", 0x00000057);
exported.hasSymbolAtAddress(".symtab", "isgraph", ".text", 0x00000074);
exported.hasSymbolAtAddress(".symtab", "islower", ".text", 0x00000091);
exported.hasSymbolAtAddress(".symtab", "isprint", ".text", 0x000000ae);
exported.hasSymbolAtAddress(".symtab", "ispunct", ".text", 0x000000cd);
exported.hasSymbolAtAddress(".symtab", "isspace", ".text", 0x000000ea);
exported.hasSymbolAtAddress(".symtab", "isupper", ".text", 0x00000107);
exported.hasSymbolAtAddress(".symtab", "isxdigit", ".text", 0x00000124);
exported.hasSymbolAtAddress(".symtab", "_ctype_", ".rodata", 0x00000000);

exported.hasRelocationAtAddress(".rel.text", 0x0000000f,
X86_32_ElfRelocationType.R_386_32.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x0000002c,
X86_32_ElfRelocationType.R_386_32.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x00000049,
X86_32_ElfRelocationType.R_386_32.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x00000066,
X86_32_ElfRelocationType.R_386_32.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x00000083,
X86_32_ElfRelocationType.R_386_32.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x000000a0,
X86_32_ElfRelocationType.R_386_32.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x000000bd,
X86_32_ElfRelocationType.R_386_32.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x000000dc,
X86_32_ElfRelocationType.R_386_32.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x000000f9,
X86_32_ElfRelocationType.R_386_32.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x00000116,
X86_32_ElfRelocationType.R_386_32.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x00000133,
X86_32_ElfRelocationType.R_386_32.typeId(), "_ctype_", 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.junit.Test;

import ghidra.DelinkerIntegrationTest;
import ghidra.app.util.bin.format.elf.relocation.X86_32_ElfRelocationType;
import ghidra.app.util.exporter.ElfRelocatableObjectExporter;
import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.address.AddressSetView;
Expand Down Expand Up @@ -48,10 +49,78 @@ public void testExport_main_o() throws Exception {
Map.entry(0x21e, new byte[] { 0x1d, -1, -1, -1 }));

ObjectFile mainObjectFile = new ElfObjectFile(mainFile);
ObjectFile exportedObjectFile = new ElfObjectFile(exportedFile);
ElfObjectFile exported = new ElfObjectFile(exportedFile);

mainObjectFile.compareSectionBytes(".text", exportedObjectFile, ".text", text_patches);
mainObjectFile.compareSectionBytes(".rodata", exportedObjectFile, ".rodata");
mainObjectFile.compareSectionSizes(".rel.rodata", exportedObjectFile, ".rel.rodata");
mainObjectFile.compareSectionBytes(".text", exported, ".text", text_patches);
mainObjectFile.compareSectionBytes(".rodata", exported, ".rodata");
mainObjectFile.compareSectionSizes(".rel.rodata", exported, ".rel.rodata");

exported.hasSymbolAtAddress(".symtab", "sys_getpid", ".text", 0x00000000);
exported.hasSymbolAtAddress(".symtab", "sys_kill", ".text", 0x00000008);
exported.hasSymbolAtAddress(".symtab", "sys_write", ".text", 0x00000016);
exported.hasSymbolAtAddress(".symtab", "_nolibc_memcpy_up", ".text", 0x0000002a);
exported.hasSymbolAtAddress(".symtab", "fileno", ".text", 0x0000004a);
exported.hasSymbolAtAddress(".symtab", "_start", ".text", 0x00000061);
exported.hasSymbolAtAddress(".symtab", "write", ".text", 0x00000098);
exported.hasSymbolAtAddress(".symtab", "fputc", ".text", 0x000000bc);
exported.hasSymbolAtAddress(".symtab", "putchar", ".text", 0x000000f0);
exported.hasSymbolAtAddress(".symtab", "print_number", ".text", 0x000000fb);
exported.hasSymbolAtAddress(".symtab", "print_ascii_entry", ".text", 0x0000013f);
exported.hasSymbolAtAddress(".symtab", "main", ".text", 0x000001cc);
exported.hasSymbolAtAddress(".symtab", "s_ascii_properties", ".rodata", 0x00000000);
exported.hasSymbolAtAddress(".symtab", "NUM_ASCII_PROPERTIES", ".rodata", 0x00000050);
exported.hasSymbolAtAddress(".symtab", "COLUMNS", ".data", 0x00000000);

exported.hasUndefinedSymbol(".symtab", "_auxv");
exported.hasUndefinedSymbol(".symtab", "environ");
exported.hasUndefinedSymbol(".symtab", "errno");
exported.hasUndefinedSymbol(".symtab", "isalnum");
exported.hasUndefinedSymbol(".symtab", "isalpha");
exported.hasUndefinedSymbol(".symtab", "iscntrl");
exported.hasUndefinedSymbol(".symtab", "isdigit");
exported.hasUndefinedSymbol(".symtab", "isgraph");
exported.hasUndefinedSymbol(".symtab", "islower");
exported.hasUndefinedSymbol(".symtab", "isprint");
exported.hasUndefinedSymbol(".symtab", "ispunct");
exported.hasUndefinedSymbol(".symtab", "isspace");
exported.hasUndefinedSymbol(".symtab", "isupper");

exported.hasRelocationAtAddress(".rel.text", 0x00000053,
X86_32_ElfRelocationType.R_386_32.typeId(), "errno", 0);
exported.hasRelocationAtAddress(".rel.text", 0x0000006a,
X86_32_ElfRelocationType.R_386_32.typeId(), "environ", 0);
exported.hasRelocationAtAddress(".rel.text", 0x0000007c,
X86_32_ElfRelocationType.R_386_32.typeId(), "_auxv", 0);
exported.hasRelocationAtAddress(".rel.text", 0x000000b1,
X86_32_ElfRelocationType.R_386_32.typeId(), "errno", 0);
exported.hasRelocationAtAddress(".rel.text", 0x00000165,
X86_32_ElfRelocationType.R_386_PC32.typeId(), "isgraph", 0);
exported.hasRelocationAtAddress(".rel.text", 0x000001fa,
X86_32_ElfRelocationType.R_386_32.typeId(), "COLUMNS", 0);
exported.hasRelocationAtAddress(".rel.text", 0x00000215,
X86_32_ElfRelocationType.R_386_32.typeId(), "s_ascii_properties", 0);
exported.hasRelocationAtAddress(".rel.text", 0x00000224,
X86_32_ElfRelocationType.R_386_32.typeId(), "COLUMNS", 0);

exported.hasRelocationAtAddress(".rel.rodata", 0x00000000,
X86_32_ElfRelocationType.R_386_32.typeId(), "isgraph", 0);
exported.hasRelocationAtAddress(".rel.rodata", 0x00000008,
X86_32_ElfRelocationType.R_386_32.typeId(), "isprint", 0);
exported.hasRelocationAtAddress(".rel.rodata", 0x00000010,
X86_32_ElfRelocationType.R_386_32.typeId(), "iscntrl", 0);
exported.hasRelocationAtAddress(".rel.rodata", 0x00000018,
X86_32_ElfRelocationType.R_386_32.typeId(), "isspace", 0);
exported.hasRelocationAtAddress(".rel.rodata", 0x00000020,
X86_32_ElfRelocationType.R_386_32.typeId(), "ispunct", 0);
exported.hasRelocationAtAddress(".rel.rodata", 0x00000028,
X86_32_ElfRelocationType.R_386_32.typeId(), "isalnum", 0);
exported.hasRelocationAtAddress(".rel.rodata", 0x00000030,
X86_32_ElfRelocationType.R_386_32.typeId(), "isalpha", 0);
exported.hasRelocationAtAddress(".rel.rodata", 0x00000038,
X86_32_ElfRelocationType.R_386_32.typeId(), "isdigit", 0);
exported.hasRelocationAtAddress(".rel.rodata", 0x00000040,
X86_32_ElfRelocationType.R_386_32.typeId(), "isupper", 0);
exported.hasRelocationAtAddress(".rel.rodata", 0x00000048,
X86_32_ElfRelocationType.R_386_32.typeId(), "islower", 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.junit.Test;

import ghidra.DelinkerIntegrationTest;
import ghidra.app.util.bin.format.elf.relocation.MIPS_ElfRelocationType;
import ghidra.app.util.exporter.ElfRelocatableObjectExporter;
import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.address.AddressSetView;
Expand All @@ -39,10 +40,68 @@ public void testExport_ctype_o() throws Exception {
File exportedFile = exportObjectFile(set, new ElfRelocatableObjectExporter(), null);

ObjectFile ctypeObjectFile = new ElfObjectFile(ctypeFile);
ObjectFile exportedObjectFile = new ElfObjectFile(exportedFile);
ElfObjectFile exported = new ElfObjectFile(exportedFile);

ctypeObjectFile.compareSectionBytes(".text", exportedObjectFile, ".text");
ctypeObjectFile.compareSectionSizes(".rel.text", exportedObjectFile, ".rel.text");
ctypeObjectFile.compareSectionBytes(".rodata", exportedObjectFile, ".rodata");
ctypeObjectFile.compareSectionBytes(".text", exported, ".text");
ctypeObjectFile.compareSectionSizes(".rel.text", exported, ".rel.text");
ctypeObjectFile.compareSectionBytes(".rodata", exported, ".rodata");

exported.hasSymbolAtAddress(".symtab", "isalnum", ".text", 0x00000000);
exported.hasSymbolAtAddress(".symtab", "isalpha", ".text", 0x00000038);
exported.hasSymbolAtAddress(".symtab", "iscntrl", ".text", 0x00000070);
exported.hasSymbolAtAddress(".symtab", "isdigit", ".text", 0x000000a8);
exported.hasSymbolAtAddress(".symtab", "isgraph", ".text", 0x000000e0);
exported.hasSymbolAtAddress(".symtab", "islower", ".text", 0x00000118);
exported.hasSymbolAtAddress(".symtab", "isprint", ".text", 0x00000150);
exported.hasSymbolAtAddress(".symtab", "ispunct", ".text", 0x00000188);
exported.hasSymbolAtAddress(".symtab", "isspace", ".text", 0x000001c0);
exported.hasSymbolAtAddress(".symtab", "isupper", ".text", 0x000001f8);
exported.hasSymbolAtAddress(".symtab", "isxdigit", ".text", 0x00000230);
exported.hasSymbolAtAddress(".symtab", "_ctype_", ".rodata", 0x00000000);

exported.hasRelocationAtAddress(".rel.text", 0x00000010,
MIPS_ElfRelocationType.R_MIPS_HI16.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x00000014,
MIPS_ElfRelocationType.R_MIPS_LO16.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x00000048,
MIPS_ElfRelocationType.R_MIPS_HI16.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x0000004c,
MIPS_ElfRelocationType.R_MIPS_LO16.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x00000080,
MIPS_ElfRelocationType.R_MIPS_HI16.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x00000084,
MIPS_ElfRelocationType.R_MIPS_LO16.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x000000b8,
MIPS_ElfRelocationType.R_MIPS_HI16.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x000000bc,
MIPS_ElfRelocationType.R_MIPS_LO16.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x000000f0,
MIPS_ElfRelocationType.R_MIPS_HI16.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x000000f4,
MIPS_ElfRelocationType.R_MIPS_LO16.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x00000128,
MIPS_ElfRelocationType.R_MIPS_HI16.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x0000012c,
MIPS_ElfRelocationType.R_MIPS_LO16.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x00000160,
MIPS_ElfRelocationType.R_MIPS_HI16.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x00000164,
MIPS_ElfRelocationType.R_MIPS_LO16.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x00000198,
MIPS_ElfRelocationType.R_MIPS_HI16.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x0000019c,
MIPS_ElfRelocationType.R_MIPS_LO16.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x000001d0,
MIPS_ElfRelocationType.R_MIPS_HI16.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x000001d4,
MIPS_ElfRelocationType.R_MIPS_LO16.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x00000208,
MIPS_ElfRelocationType.R_MIPS_HI16.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x0000020c,
MIPS_ElfRelocationType.R_MIPS_LO16.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x00000240,
MIPS_ElfRelocationType.R_MIPS_HI16.typeId(), "_ctype_", 0);
exported.hasRelocationAtAddress(".rel.text", 0x00000244,
MIPS_ElfRelocationType.R_MIPS_LO16.typeId(), "_ctype_", 0);
}
}
Loading

0 comments on commit 6cf8cd2

Please sign in to comment.