Merge remote-tracking branch 'origin/Ghidra_10.2'

This commit is contained in:
Ryan Kurtz 2022-10-21 13:43:22 -04:00
commit be36528218
21 changed files with 283 additions and 274 deletions

View file

@ -1,58 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//Writes a list of the addresses of all call sites to a file.
//@category machineLearning
import java.io.*;
import ghidra.app.script.GhidraScript;
import ghidra.program.model.listing.*;
import ghidra.program.model.pcode.PcodeOp;
public class DumpCalls extends GhidraScript {
private static final String DATA_DIR = "/local/calls";
@Override
protected void run() throws Exception {
File outFile = new File(DATA_DIR + File.separator + currentProgram.getName() + "_calls");
FileWriter fWriter = new FileWriter(outFile);
BufferedWriter bWriter = new BufferedWriter(fWriter);
InstructionIterator fIter = currentProgram.getListing().getInstructions(true);
int numCalls = 0;
int numInstructions = 0;
while (fIter.hasNext()) {
Instruction inst = fIter.next();
if (inst.getPcode() == null || inst.getPcode().length == 0) {
continue;
}
numInstructions++;
for (int i = 0; i < inst.getPcode().length; i++) {
PcodeOp pCode = inst.getPcode()[i];
int opCode = pCode.getOpcode();
if (opCode == PcodeOp.CALL || opCode == PcodeOp.CALLIND) {
//printf("Inst: %s at %s\n", inst.toString(), inst.getAddress());
numCalls++;
bWriter.write(inst.getAddress().toString() + "\n");
}
}
}
printf("total num calls: %d\n", numCalls);
printf("total num instructions: %d\n", numInstructions);
bWriter.close();
}
}

View file

@ -1,47 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//Writes a list of the addresses of all function starts and their sizes to a file
//@category machineLearning
import java.io.*;
import ghidra.app.script.GhidraScript;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.FunctionIterator;
public class DumpFunctionStarts extends GhidraScript {
private static final String DATA_DIR = "/local/funcstarts/stripped";
@Override
protected void run() throws Exception {
File outFile =
new File(DATA_DIR + File.separator + currentProgram.getName() + "_stripped_funcs");
FileWriter fWriter = new FileWriter(outFile);
BufferedWriter bWriter = new BufferedWriter(fWriter);
FunctionIterator fIter = currentProgram.getFunctionManager().getFunctions(true);
while (fIter.hasNext()) {
Function func = fIter.next();
if (func.isExternal()) {
continue;
}
long size = func.getBody().getNumAddresses();
bWriter.write(func.getEntryPoint().toString() + "," + size + "\n");
}
bWriter.close();
}
}

View file

@ -1,74 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.IOException;
import java.nio.file.Paths;
import org.tribuo.*;
import org.tribuo.classification.Label;
import org.tribuo.classification.LabelFactory;
import org.tribuo.classification.dtree.CARTClassificationTrainer;
import org.tribuo.classification.ensemble.VotingCombiner;
import org.tribuo.classification.evaluation.LabelEvaluation;
import org.tribuo.classification.evaluation.LabelEvaluator;
import org.tribuo.common.tree.RandomForestTrainer;
import org.tribuo.data.csv.CSVLoader;
import org.tribuo.ensemble.EnsembleModel;
import org.tribuo.evaluation.TrainTestSplitter;
public class ExampleTribuoRunner {
public static void main(String args[]) throws IOException {
var irisHeaders =
new String[] { "sepalLength", "sepalWidth", "petalLength", "petalWidth", "species" };
DataSource<Label> irisData = new CSVLoader<>(new LabelFactory()).loadDataSource(
Paths.get("/home/jmworth/ml/bezdekIris.data"), /* Output column */ irisHeaders[4],
/* Column headers */ irisHeaders);
// Split iris data into training set (70%) and test set (30%)
var splitIrisData =
new TrainTestSplitter<>(irisData, /* Train fraction */ 0.7, /* RNG seed */ 1L);
var trainData = new MutableDataset<>(splitIrisData.getTrain());
var testData = new MutableDataset<>(splitIrisData.getTest());
// We can train a decision tree
var cartTrainer = new CARTClassificationTrainer(100, (float) 0.2, 0);
var decisionTree = cartTrainer.train(trainData);
//Model<Label> tree = cartTrainer.train(trainData);
var trainer = new RandomForestTrainer<>(cartTrainer, // trainer - the tree trainer
new VotingCombiner(), // combiner - the combining function for the ensemble
10 // numMembers - the number of ensemble members to train
);
EnsembleModel<Label> tree = trainer.train(trainData);
// Finally we make predictions on unseen data
// Each prediction is a map from the output names (i.e. the labels) to the scores/probabilities
Prediction<Label> prediction = tree.predict(testData.getExample(0));
// Or we can evaluate the full test dataset, calculating the accuracy, F1 etc.
LabelEvaluation evaluation = new LabelEvaluator().evaluate(tree, testData);
// we can inspect the evaluation manually
double acc = evaluation.accuracy();
// which returns 0.978
// or print a formatted evaluation string
System.out.println(evaluation.toString());
}
}

View file

@ -17,6 +17,8 @@ package ghidra.app.cmd.formats;
import java.util.Arrays; import java.util.Arrays;
import org.apache.commons.lang3.StringUtils;
import ghidra.app.plugin.core.analysis.AnalysisWorker; import ghidra.app.plugin.core.analysis.AnalysisWorker;
import ghidra.app.plugin.core.analysis.AutoAnalysisManager; import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
import ghidra.app.util.bin.*; import ghidra.app.util.bin.*;
@ -379,12 +381,14 @@ public class ElfBinaryAnalysisCommand extends FlatProgramAPI
} }
String name = symbols[j].getNameAsString(); String name = symbols[j].getNameAsString();
long value = Integer.toUnsignedLong((int) symbols[j].getValue()); if (StringUtils.isBlank(name)) {
continue;
}
try { try {
Address currAddr = symbolTableAddr.add(j * symbolTable2.getEntrySize()); Address currAddr = symbolTableAddr.add(j * symbolTable2.getEntrySize());
listing.setComment(currAddr, CodeUnit.EOL_COMMENT, listing.setComment(currAddr, CodeUnit.EOL_COMMENT,
name + " at 0x" + Long.toHexString(value)); name + " at 0x" + Long.toHexString(symbols[j].getValue()));
} }
catch (Exception e) { catch (Exception e) {
messages.appendMsg("Could not markup symbol table: " + e); messages.appendMsg("Could not markup symbol table: " + e);

View file

@ -180,14 +180,13 @@ public class DWARFAnalyzer extends AbstractAnalyzer {
return false; return false;
} }
DWARFSectionProvider dsp = try (DWARFSectionProvider dsp =
DWARFSectionProviderFactory.createSectionProviderFor(program, monitor); // closed by DWARFProgram DWARFSectionProviderFactory.createSectionProviderFor(program, monitor)) {
if (dsp == null) { if (dsp == null) {
Msg.info(this, "Unable to find DWARF information, skipping DWARF analysis"); Msg.info(this, "Unable to find DWARF information, skipping DWARF analysis");
return false; return false;
} }
try {
try (DWARFProgram prog = new DWARFProgram(program, importOptions, monitor, dsp)) { try (DWARFProgram prog = new DWARFProgram(program, importOptions, monitor, dsp)) {
if (prog.getRegisterMappings() == null && importOptions.isImportFuncs()) { if (prog.getRegisterMappings() == null && importOptions.isImportFuncs()) {
log.appendMsg( log.appendMsg(

View file

@ -249,7 +249,7 @@ public class DWARFProgram implements Closeable {
@Override @Override
public void close() throws IOException { public void close() throws IOException {
sectionProvider.close(); sectionProvider = null;
compUnits.clear(); compUnits.clear();
debugAbbrBR = null; debugAbbrBR = null;
debugInfoBR = null; debugInfoBR = null;

View file

@ -163,6 +163,8 @@ public class ElfDynamicType {
// Address Range (??): 0x6ffffe00 - 0x6ffffeff // Address Range (??): 0x6ffffe00 - 0x6ffffeff
public static ElfDynamicType DT_GNU_XHASH = addDefaultDynamicType(0x6ffffef4, "DT_GNU_XHASH",
"GNU-style extended hash table", ElfDynamicValueType.ADDRESS);
public static ElfDynamicType DT_GNU_HASH = addDefaultDynamicType(0x6ffffef5, "DT_GNU_HASH", public static ElfDynamicType DT_GNU_HASH = addDefaultDynamicType(0x6ffffef5, "DT_GNU_HASH",
"GNU-style hash table", ElfDynamicValueType.ADDRESS); "GNU-style hash table", ElfDynamicValueType.ADDRESS);
public static ElfDynamicType DT_TLSDESC_PLT = public static ElfDynamicType DT_TLSDESC_PLT =

View file

@ -876,6 +876,7 @@ public class ElfHeader implements StructConverter, Writeable {
for (ElfSectionHeader symbolTableSectionHeader : sectionHeaders) { for (ElfSectionHeader symbolTableSectionHeader : sectionHeaders) {
if (symbolTableSectionHeader.getType() == ElfSectionHeaderConstants.SHT_SYMTAB || if (symbolTableSectionHeader.getType() == ElfSectionHeaderConstants.SHT_SYMTAB ||
symbolTableSectionHeader.getType() == ElfSectionHeaderConstants.SHT_DYNSYM) { symbolTableSectionHeader.getType() == ElfSectionHeaderConstants.SHT_DYNSYM) {
// || symbolTableSectionHeader.getType() == ElfSectionHeaderConstants.SHT_SUNW_LDYNSYM) {
if (symbolTableSectionHeader.isInvalidOffset()) { if (symbolTableSectionHeader.isInvalidOffset()) {
continue; continue;
} }
@ -919,12 +920,26 @@ public class ElfHeader implements StructConverter, Writeable {
symbolTableList.toArray(symbolTables); symbolTableList.toArray(symbolTables);
} }
private ElfDynamicType getDynamicHashTableType() {
if (dynamicTable.containsDynamicValue(ElfDynamicType.DT_HASH)) {
return ElfDynamicType.DT_HASH;
}
if (dynamicTable.containsDynamicValue(ElfDynamicType.DT_GNU_HASH)) {
return ElfDynamicType.DT_GNU_HASH;
}
if (dynamicTable.containsDynamicValue(ElfDynamicType.DT_GNU_XHASH)) {
return ElfDynamicType.DT_GNU_XHASH;
}
return null;
}
private ElfSymbolTable parseDynamicSymbolTable() throws IOException { private ElfSymbolTable parseDynamicSymbolTable() throws IOException {
ElfDynamicType dynamicHashType = getDynamicHashTableType();
if (!dynamicTable.containsDynamicValue(ElfDynamicType.DT_SYMTAB) || if (!dynamicTable.containsDynamicValue(ElfDynamicType.DT_SYMTAB) ||
!dynamicTable.containsDynamicValue(ElfDynamicType.DT_SYMENT) || !dynamicTable.containsDynamicValue(ElfDynamicType.DT_SYMENT) ||
!(dynamicTable.containsDynamicValue(ElfDynamicType.DT_HASH) || dynamicHashType == null) {
dynamicTable.containsDynamicValue(ElfDynamicType.DT_GNU_HASH))) {
if (dynamicStringTable != null) { if (dynamicStringTable != null) {
Msg.warn(this, "Failed to parse DT_SYMTAB, missing dynamic dependency"); Msg.warn(this, "Failed to parse DT_SYMTAB, missing dynamic dependency");
} }
@ -951,11 +966,9 @@ public class ElfHeader implements StructConverter, Writeable {
tableAddr = adjustAddressForPrelink(tableAddr); tableAddr = adjustAddressForPrelink(tableAddr);
long tableEntrySize = dynamicTable.getDynamicValue(ElfDynamicType.DT_SYMENT); long tableEntrySize = dynamicTable.getDynamicValue(ElfDynamicType.DT_SYMENT);
// Use dynamic symbol hash table DT_HASH or DT_GNU_HASH to determine symbol table count/length // Use dynamic symbol hash table DT_HASH, DT_GNU_HASH, or DT_GNU_XHASH to
boolean useGnuHash = dynamicTable.containsDynamicValue(ElfDynamicType.DT_GNU_HASH); // determine symbol table count/length
long hashTableAddr = long hashTableAddr = dynamicTable.getDynamicValue(dynamicHashType);
useGnuHash ? dynamicTable.getDynamicValue(ElfDynamicType.DT_GNU_HASH)
: dynamicTable.getDynamicValue(ElfDynamicType.DT_HASH);
hashTableAddr = adjustAddressForPrelink(hashTableAddr); hashTableAddr = adjustAddressForPrelink(hashTableAddr);
ElfProgramHeader symbolTableLoadHeader = getProgramLoadHeaderContaining(tableAddr); ElfProgramHeader symbolTableLoadHeader = getProgramLoadHeaderContaining(tableAddr);
@ -966,7 +979,7 @@ public class ElfHeader implements StructConverter, Writeable {
} }
ElfProgramHeader hashTableLoadHeader = getProgramLoadHeaderContaining(hashTableAddr); ElfProgramHeader hashTableLoadHeader = getProgramLoadHeaderContaining(hashTableAddr);
if (hashTableLoadHeader == null) { if (hashTableLoadHeader == null) {
errorConsumer.accept("Failed to locate DT_HASH or DT_GNU_HASH in memory at 0x" + errorConsumer.accept("Failed to locate DT_HASH, DT_GNU_HASH, or DT_GNU_XHASH in memory at 0x" +
Long.toHexString(hashTableAddr)); Long.toHexString(hashTableAddr));
return null; return null;
} }
@ -977,9 +990,12 @@ public class ElfHeader implements StructConverter, Writeable {
// determine symbol count from dynamic symbol hash table // determine symbol count from dynamic symbol hash table
int symCount; int symCount;
long symbolHashTableOffset = hashTableLoadHeader.getOffset(hashTableAddr); long symbolHashTableOffset = hashTableLoadHeader.getOffset(hashTableAddr);
if (useGnuHash) { if (dynamicHashType == ElfDynamicType.DT_GNU_HASH) {
symCount = deriveGnuHashDynamicSymbolCount(symbolHashTableOffset); symCount = deriveGnuHashDynamicSymbolCount(symbolHashTableOffset);
} }
else if (dynamicHashType == ElfDynamicType.DT_GNU_XHASH) {
symCount = deriveGnuXHashDynamicSymbolCount(symbolHashTableOffset);
}
else { else {
// DT_HASH table, nchain corresponds is same as symbol count // DT_HASH table, nchain corresponds is same as symbol count
symCount = reader.readInt(symbolHashTableOffset + 4); // nchain from DT_HASH symCount = reader.readInt(symbolHashTableOffset + 4); // nchain from DT_HASH
@ -1036,6 +1052,22 @@ public class ElfHeader implements StructConverter, Writeable {
return maxSymbolIndex; return maxSymbolIndex;
} }
/**
* Walk DT_GNU_XHASH table to determine dynamic symbol count
* @param gnuHashTableOffset DT_GNU_XHASH table file offset
* @return dynamic symbol count
* @throws IOException file read error
*/
private int deriveGnuXHashDynamicSymbolCount(long gnuHashTableOffset) throws IOException {
// Elf32_Word ngnusyms; // number of entries in chains (and xlat); dynsymcount=symndx+ngnusyms
// Elf32_Word nbuckets; // number of hash table buckets
// Elf32_Word symndx; // number of initial .dynsym entires skipped in chains[] (and xlat[])
int ngnusyms = reader.readInt(gnuHashTableOffset);
int symndx = reader.readInt(gnuHashTableOffset + 8);
return symndx + ngnusyms;
}
/** /**
* Perform offset region check against byte provider. * Perform offset region check against byte provider.
* This is done against the byte provider since the * This is done against the byte provider since the

View file

@ -17,6 +17,8 @@ package ghidra.app.util.bin.format.elf;
import java.io.IOException; import java.io.IOException;
import org.apache.commons.lang3.StringUtils;
import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.ByteArrayConverter; import ghidra.app.util.bin.ByteArrayConverter;
import ghidra.util.DataConverter; import ghidra.util.DataConverter;
@ -48,6 +50,8 @@ import ghidra.util.exception.NotFoundException;
*/ */
public class ElfSymbol implements ByteArrayConverter { public class ElfSymbol implements ByteArrayConverter {
public static final String FORMATTED_NO_NAME = "<no name>";
/**Local symbols are not visible outside the object file containing their definition.*/ /**Local symbols are not visible outside the object file containing their definition.*/
public static final byte STB_LOCAL = 0; public static final byte STB_LOCAL = 0;
/**Global symbols are visible to all object files being combined.*/ /**Global symbols are visible to all object files being combined.*/
@ -227,7 +231,7 @@ public class ElfSymbol implements ByteArrayConverter {
* @param stringTable stringTable to initialize symbol name * @param stringTable stringTable to initialize symbol name
*/ */
public void initSymbolName(BinaryReader reader, ElfStringTable stringTable) { public void initSymbolName(BinaryReader reader, ElfStringTable stringTable) {
if (nameAsString == null) { if (nameAsString == null && stringTable != null) {
nameAsString = stringTable.readString(reader, st_name); nameAsString = stringTable.readString(reader, st_name);
} }
} }
@ -460,12 +464,23 @@ public class ElfSymbol implements ByteArrayConverter {
* Returns the actual string name for this symbol. The symbol only * Returns the actual string name for this symbol. The symbol only
* stores an byte index into the string table where * stores an byte index into the string table where
* the name string is located. * the name string is located.
* @return the actual string name for this symbol * @return the actual string name for this symbol (may be null or empty string)
*/ */
public String getNameAsString() { public String getNameAsString() {
return nameAsString; return nameAsString;
} }
/**
* Returns the formatted string name for this symbol. If the name is blank or
* can not be resolved due to a missing string table the literal string
* <I>&lt;no name&gt;</I> will be returned.
* the name string is located.
* @return the actual string name for this symbol or the literal string <I>&lt;no name&gt;</I>
*/
public String getFormattedName() {
return StringUtils.isBlank(nameAsString) ? FORMATTED_NO_NAME : nameAsString;
}
/** /**
* This member currently holds 0 and has no defined meaning. * This member currently holds 0 and has no defined meaning.
* @return no defined meaning * @return no defined meaning

View file

@ -203,13 +203,26 @@ public class ElfSymbolTable implements ElfFileSection, ByteArrayConverter {
} }
/** /**
* Get the ELF symbol name which corresponds to the specified index. * Get the ELF symbol name which corresponds to the specified index.
* @param symbolIndex symbol index * @param symbolIndex symbol index
* @return symbol name which corresponds to symbol index or <B>&lt<NONE&gt;</B> if out of range * @return symbol name which corresponds to symbol index or null if out of range
*/ */
public final String getSymbolName(int symbolIndex) { public final String getSymbolName(int symbolIndex) {
ElfSymbol sym = getSymbol(symbolIndex); ElfSymbol sym = getSymbol(symbolIndex);
return sym != null ? sym.getNameAsString() : ""; return sym != null ? sym.getNameAsString() : null;
}
/**
* Get the formatted ELF symbol name which corresponds to the specified index.
* If the name is blank or can not be resolved due to a missing string table the
* literal string <I>&lt;no name&gt;</I> will be returned.
* @param symbolIndex symbol index
* @return formatted symbol name which corresponds to symbol index or the
* literal string <I>&lt;no name&gt;</I>
*/
public final String getFormattedSymbolName(int symbolIndex) {
ElfSymbol sym = getSymbol(symbolIndex);
return sym != null ? sym.getFormattedName() : ElfSymbol.FORMATTED_NO_NAME;
} }
/** /**

View file

@ -17,6 +17,8 @@ package ghidra.app.util.bin.format.elf.relocation;
import java.util.Map; import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import ghidra.app.util.bin.format.elf.*; import ghidra.app.util.bin.format.elf.*;
import ghidra.app.util.bin.format.elf.extend.ElfLoadAdapter; import ghidra.app.util.bin.format.elf.extend.ElfLoadAdapter;
import ghidra.app.util.importer.MessageLog; import ghidra.app.util.importer.MessageLog;
@ -114,11 +116,15 @@ public class ElfRelocationContext {
String symName = getSymbolName(relocation.getSymbolIndex()); String symName = getSymbolName(relocation.getSymbolIndex());
String nameMsg = "";
if (!StringUtils.isBlank(symName)) {
nameMsg = " to: " + symName;
}
program.getBookmarkManager().setBookmark(relocationAddress, BookmarkType.ERROR, program.getBookmarkManager().setBookmark(relocationAddress, BookmarkType.ERROR,
"Relocation", "No handler to process ELF Relocation to : " + symName); "Relocation", "No handler to process ELF Relocation" + nameMsg);
loadHelper.log("WARNING: At " + relocationAddress + loadHelper.log("WARNING: At " + relocationAddress +
" no handler to process ELF Relocations to " + symName); " no handler to process ELF Relocation" + nameMsg);
} }
/** /**
@ -209,10 +215,10 @@ public class ElfRelocationContext {
/** /**
* Get the ELF symbol name which corresponds to the specified index. * Get the ELF symbol name which corresponds to the specified index.
* @param symbolIndex symbol index * @param symbolIndex symbol index
* @return symbol name which corresponds to symbol index or <B>&lt<NONE&gt;</B> if out of range * @return symbol name which corresponds to symbol index or null if out of range
*/ */
public final String getSymbolName(int symbolIndex) { public final String getSymbolName(int symbolIndex) {
return symbolTable != null ? symbolTable.getSymbolName(symbolIndex) : ""; return symbolTable != null ? symbolTable.getSymbolName(symbolIndex) : null;
} }
/** /**

View file

@ -126,7 +126,7 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
} }
String adjStr = sign + "0x" + Long.toHexString(adjustment); String adjStr = sign + "0x" + Long.toHexString(adjustment);
symbolName = StringUtils.isEmpty(symbolName) ? "<no name>" : symbolName; symbolName = StringUtils.isEmpty(symbolName) ? ElfSymbol.FORMATTED_NO_NAME : symbolName;
Msg.warn(ElfRelocationHandler.class, Msg.warn(ElfRelocationHandler.class,
"EXTERNAL Data Elf Relocation with offset: at " + relocationAddress + "EXTERNAL Data Elf Relocation with offset: at " + relocationAddress +
" (External Location = " + symbolName + adjStr + ")"); " (External Location = " + symbolName + adjStr + ")");
@ -149,7 +149,7 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
public static void markAsUnhandled(Program program, Address relocationAddress, long type, public static void markAsUnhandled(Program program, Address relocationAddress, long type,
long symbolIndex, String symbolName, MessageLog log) { long symbolIndex, String symbolName, MessageLog log) {
symbolName = StringUtils.isEmpty(symbolName) ? "<no name>" : symbolName; symbolName = StringUtils.isEmpty(symbolName) ? ElfSymbol.FORMATTED_NO_NAME : symbolName;
log.appendMsg("Unhandled Elf Relocation: Type = " + type + " (0x" + Long.toHexString(type) + log.appendMsg("Unhandled Elf Relocation: Type = " + type + " (0x" + Long.toHexString(type) +
") at " + relocationAddress + " (Symbol = " + symbolName + ")"); ") at " + relocationAddress + " (Symbol = " + symbolName + ")");
BookmarkManager bookmarkManager = program.getBookmarkManager(); BookmarkManager bookmarkManager = program.getBookmarkManager();
@ -184,7 +184,7 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
public static void markAsUninitializedMemory(Program program, Address relocationAddress, public static void markAsUninitializedMemory(Program program, Address relocationAddress,
long type, long symbolIndex, String symbolName, MessageLog log) { long type, long symbolIndex, String symbolName, MessageLog log) {
symbolName = StringUtils.isEmpty(symbolName) ? "<no name>" : symbolName; symbolName = StringUtils.isEmpty(symbolName) ? ElfSymbol.FORMATTED_NO_NAME : symbolName;
log.appendMsg("Unable to perform relocation: Type = " + type + " (0x" + log.appendMsg("Unable to perform relocation: Type = " + type + " (0x" +
Long.toHexString(type) + ") at " + relocationAddress + " (Symbol = " + symbolName + Long.toHexString(type) + ") at " + relocationAddress + " (Symbol = " + symbolName +
") - uninitialized memory"); ") - uninitialized memory");
@ -225,7 +225,7 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
public static void markAsError(Program program, Address relocationAddress, String type, public static void markAsError(Program program, Address relocationAddress, String type,
String symbolName, String msg, MessageLog log) { String symbolName, String msg, MessageLog log) {
symbolName = StringUtils.isEmpty(symbolName) ? "<no name>" : symbolName; symbolName = StringUtils.isEmpty(symbolName) ? ElfSymbol.FORMATTED_NO_NAME : symbolName;
log.appendMsg("Elf Relocation Error: Type = " + type + " at " + relocationAddress + log.appendMsg("Elf Relocation Error: Type = " + type + " at " + relocationAddress +
", Symbol = " + symbolName + ": " + msg); ", Symbol = " + symbolName + ": " + msg);
BookmarkManager bookmarkManager = program.getBookmarkManager(); BookmarkManager bookmarkManager = program.getBookmarkManager();
@ -262,7 +262,7 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
public static void markAsWarning(Program program, Address relocationAddress, String type, public static void markAsWarning(Program program, Address relocationAddress, String type,
String symbolName, long symbolIndex, String msg, MessageLog log) { String symbolName, long symbolIndex, String msg, MessageLog log) {
symbolName = StringUtils.isEmpty(symbolName) ? "<no name>" : symbolName; symbolName = StringUtils.isEmpty(symbolName) ? ElfSymbol.FORMATTED_NO_NAME : symbolName;
log.appendMsg("Elf Relocation Warning: Type = " + type + " at " + relocationAddress + log.appendMsg("Elf Relocation Warning: Type = " + type + " at " + relocationAddress +
", Symbol = " + symbolName + ": " + msg); ", Symbol = " + symbolName + ": " + msg);
BookmarkManager bookmarkManager = program.getBookmarkManager(); BookmarkManager bookmarkManager = program.getBookmarkManager();

View file

@ -181,6 +181,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
markupHashTable(monitor); markupHashTable(monitor);
markupGnuHashTable(monitor); markupGnuHashTable(monitor);
markupGnuXHashTable(monitor);
markupGnuBuildId(monitor); markupGnuBuildId(monitor);
markupGnuDebugLink(monitor); markupGnuDebugLink(monitor);
@ -536,7 +537,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
String comment = null; String comment = null;
comment = symbols[index].getNameAsString(); comment = symbols[index].getNameAsString();
if (comment == null) { if (StringUtils.isBlank(comment)) {
comment = Long.toHexString(symbols[index].getValue()); comment = Long.toHexString(symbols[index].getValue());
} }
@ -1546,8 +1547,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
boolean usingFakeExternal = false; boolean usingFakeExternal = false;
if (address == Address.NO_ADDRESS) { if (address == Address.NO_ADDRESS) {
if (symName == null) { if (StringUtils.isBlank(symName)) {
continue; // unexpected continue;
} }
// check for @<version> or @@<version> // check for @<version> or @@<version>
@ -1574,7 +1575,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
evaluateElfSymbol(elfSymbol, address, usingFakeExternal); evaluateElfSymbol(elfSymbol, address, usingFakeExternal);
} }
catch (Exception e) { catch (Exception e) {
log("Error creating symbol: " + elfSymbol.getNameAsString() + " - " + log("Error creating symbol: " + elfSymbol.getFormattedName() + " - " +
getMessage(e)); getMessage(e));
} }
} }
@ -1598,7 +1599,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
if (elfSymbol.isTLS()) { if (elfSymbol.isTLS()) {
// TODO: Investigate support for TLS symbols // TODO: Investigate support for TLS symbols
log("Unsupported Thread-Local Symbol not loaded: " + elfSymbol.getNameAsString()); log("Unsupported Thread-Local Symbol not loaded: " + elfSymbol.getFormattedName());
return null; return null;
} }
@ -1646,7 +1647,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
uSectionIndex = elfSymbol.getExtendedSectionHeaderIndex(); uSectionIndex = elfSymbol.getExtendedSectionHeaderIndex();
if (uSectionIndex == 0) { if (uSectionIndex == 0) {
log("Failed to read extended symbol section index: " + log("Failed to read extended symbol section index: " +
elfSymbol.getNameAsString() + " - value=0x" + elfSymbol.getFormattedName() + " - value=0x" +
Long.toHexString(elfSymbol.getValue())); Long.toHexString(elfSymbol.getValue()));
return null; return null;
} }
@ -1658,7 +1659,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
symSectionBase = findLoadAddress(symSection, 0); symSectionBase = findLoadAddress(symSection, 0);
if (symSectionBase == null) { if (symSectionBase == null) {
log("Unable to place symbol due to non-loaded section: " + log("Unable to place symbol due to non-loaded section: " +
elfSymbol.getNameAsString() + " - value=0x" + elfSymbol.getFormattedName() + " - value=0x" +
Long.toHexString(elfSymbol.getValue()) + ", section=" + Long.toHexString(elfSymbol.getValue()) + ", section=" +
symSection.getNameAsString()); symSection.getNameAsString());
return null; return null;
@ -1678,7 +1679,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
// Unable to place symbol within relocatable if section missing/stripped // Unable to place symbol within relocatable if section missing/stripped
else if (elf.isRelocatable()) { else if (elf.isRelocatable()) {
log("No Memory for symbol: " + elfSymbol.getNameAsString() + log("No Memory for symbol: " + elfSymbol.getFormattedName() +
" - 0x" + Long.toHexString(elfSymbol.getValue())); " - 0x" + Long.toHexString(elfSymbol.getValue()));
return null; return null;
} }
@ -1717,7 +1718,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
// SHN_HIPROC 0xff1f // SHN_HIPROC 0xff1f
// SHN_HIRESERVE 0xffff // SHN_HIRESERVE 0xffff
log("Unable to place symbol: " + elfSymbol.getNameAsString() + log("Unable to place symbol: " + elfSymbol.getFormattedName() +
" - value=0x" + Long.toHexString(elfSymbol.getValue()) + ", section-index=0x" + " - value=0x" + Long.toHexString(elfSymbol.getValue()) + ", section-index=0x" +
Integer.toHexString(Short.toUnsignedInt(sectionIndex))); Integer.toHexString(Short.toUnsignedInt(sectionIndex)));
return null; return null;
@ -1756,6 +1757,9 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
*/ */
private Address findMemoryRegister(ElfSymbol elfSymbol) { private Address findMemoryRegister(ElfSymbol elfSymbol) {
String name = elfSymbol.getNameAsString(); String name = elfSymbol.getNameAsString();
if (StringUtils.isBlank(name)) {
return null;
}
Address regAddr = getMemoryRegister(name, elfSymbol.getValue()); Address regAddr = getMemoryRegister(name, elfSymbol.getValue());
if (regAddr == null) { if (regAddr == null) {
name = StringUtils.stripStart(name, "_"); name = StringUtils.stripStart(name, "_");
@ -1812,6 +1816,9 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
return false; return false;
} }
String symName = elfSymbol.getNameAsString(); String symName = elfSymbol.getNameAsString();
if (StringUtils.isBlank(symName)) {
return false;
}
Symbol s = findExternalBlockSymbol(symName, externalBlockLimits.getMinAddress(), Symbol s = findExternalBlockSymbol(symName, externalBlockLimits.getMinAddress(),
lastExternalBlockEntryAddress); lastExternalBlockEntryAddress);
if (s != null) { if (s != null) {
@ -1833,6 +1840,9 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
private boolean processVersionedExternal(ElfSymbol elfSymbol) { private boolean processVersionedExternal(ElfSymbol elfSymbol) {
String symName = elfSymbol.getNameAsString(); String symName = elfSymbol.getNameAsString();
if (StringUtils.isBlank(symName)) {
return false;
}
int index = symName.indexOf("@"); int index = symName.indexOf("@");
if (index < 0) { if (index < 0) {
return false; return false;
@ -1929,26 +1939,26 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
// Remember where in memory Elf symbols have been mapped // Remember where in memory Elf symbols have been mapped
setElfSymbolAddress(elfSymbol, address); setElfSymbolAddress(elfSymbol, address);
if (address.isConstantAddress()) {
// Do not add constant symbols to program symbol table
// define as equate instead
try {
program.getEquateTable()
.createEquate(elfSymbol.getNameAsString(), address.getOffset());
}
catch (DuplicateNameException | InvalidInputException e) {
// ignore
}
return;
}
if (elfSymbol.isSection()) { if (elfSymbol.isSection()) {
// Do not add section symbols to program symbol table // Do not add section symbols to program symbol table
return; return;
} }
String name = elfSymbol.getNameAsString(); String name = elfSymbol.getNameAsString();
if (name == null) { if (StringUtils.isBlank(name)) {
return;
}
if (address.isConstantAddress()) {
// Do not add constant symbols to program symbol table
// define as equate instead
try {
program.getEquateTable()
.createEquate(name, address.getOffset());
}
catch (DuplicateNameException | InvalidInputException e) {
// ignore
}
return; return;
} }
@ -2029,30 +2039,25 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
@Override @Override
public Function createOneByteFunction(String name, Address address, boolean isEntry) { public Function createOneByteFunction(String name, Address address, boolean isEntry) {
Function function = null; Function function = null;
try { try {
if (isEntry) {
program.getSymbolTable().addExternalEntryPoint(address);
}
FunctionManager functionMgr = program.getFunctionManager(); FunctionManager functionMgr = program.getFunctionManager();
function = functionMgr.getFunctionAt(address); function = functionMgr.getFunctionAt(address);
if (function == null) { if (function == null) {
function = functionMgr.createFunction(null, address, new AddressSet(address), function = functionMgr.createFunction(null, address, new AddressSet(address),
SourceType.IMPORTED); SourceType.IMPORTED);
} }
else if (!StringUtils.isEmpty(name)) {
createSymbol(address, name, true, false, null);
}
} }
catch (Exception e) { catch (Exception e) {
log("Error while creating function at " + address + ": " + getMessage(e)); log("Error while creating function at " + address + ": " + getMessage(e));
} }
try {
if (name != null) {
createSymbol(address, name, true, false, null);
}
if (isEntry) {
program.getSymbolTable().addExternalEntryPoint(address);
}
}
catch (Exception e) {
log("Error while creating symbol " + name + " at " + address + ": " + getMessage(e));
}
return function; return function;
} }
@ -2392,7 +2397,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
addr = addr.add(d.getLength()); addr = addr.add(d.getLength());
d = listing.createData(addr, new ArrayDataType(dt, (int) nbucket, dt.getLength())); d = listing.createData(addr, new ArrayDataType(dt, (int) nbucket, dt.getLength()));
d.setComment(CodeUnit.EOL_COMMENT, "GNU Hash Table - chains"); d.setComment(CodeUnit.EOL_COMMENT, "GNU Hash Table - buckets");
addr = addr.add(d.getLength()); addr = addr.add(d.getLength());
listing.setComment(addr, CodeUnit.EOL_COMMENT, "GNU Hash Table - chain"); listing.setComment(addr, CodeUnit.EOL_COMMENT, "GNU Hash Table - chain");
@ -2416,6 +2421,80 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
} }
private void markupGnuXHashTable(TaskMonitor monitor) {
ElfDynamicTable dynamicTable = elf.getDynamicTable();
if (dynamicTable == null ||
!dynamicTable.containsDynamicValue(ElfDynamicType.DT_GNU_XHASH)) {
return;
}
DataType dt = DWordDataType.dataType;
Address hashTableAddr = null;
try {
long value = dynamicTable.getDynamicValue(ElfDynamicType.DT_GNU_XHASH);
if (value == 0) {
return; // table has been stripped
}
hashTableAddr = getDefaultAddress(elf.adjustAddressForPrelink(value));
// Elf32_Word ngnusyms; // number of entries in chains (and xlat); dynsymcount=symndx+ngnusyms
Address addr = hashTableAddr;
Data d = listing.createData(addr, dt);
d.setComment(CodeUnit.EOL_COMMENT, "GNU XHash Table - ngnusyms");
long ngnusyms = d.getScalar(0).getUnsignedValue();
// Elf32_Word nbuckets; // number of hash table buckets
addr = addr.add(d.getLength());
d = listing.createData(addr, dt);
d.setComment(CodeUnit.EOL_COMMENT, "GNU XHash Table - nbuckets");
long nbuckets = d.getScalar(0).getUnsignedValue();
// Elf32_Word symndx; // number of initial .dynsym entires skipped in chains[] (and xlat[])
addr = addr.add(d.getLength());
d = listing.createData(addr, dt);
d.setComment(CodeUnit.EOL_COMMENT, "GNU XHash Table - symndx");
// Elf32_Word maskwords; // number of ElfW(Addr) words in bitmask
addr = addr.add(d.getLength());
d = listing.createData(addr, dt);
d.setComment(CodeUnit.EOL_COMMENT, "GNU XHash Table - maskwords");
long maskwords = d.getScalar(0).getUnsignedValue();
// Elf32_Word shift2; // bit shift of hashval for second Bloom filter bit
addr = addr.add(d.getLength());
d = listing.createData(addr, dt);
d.setComment(CodeUnit.EOL_COMMENT, "GNU XHash Table - shift2");
// ElfW(Addr) bitmask[maskwords]; // 2 bit Bloom filter on hashval
addr = addr.add(d.getLength());
DataType bloomDataType = elf.is64Bit() ? QWordDataType.dataType : DWordDataType.dataType;
d = listing.createData(addr,
new ArrayDataType(bloomDataType, (int) maskwords, bloomDataType.getLength()));
d.setComment(CodeUnit.EOL_COMMENT, "GNU XHash Table - bitmask");
// Elf32_Word buckets[nbuckets]; // indices into chains[]
addr = addr.add(d.getLength());
d = listing.createData(addr, new ArrayDataType(dt, (int) nbuckets, dt.getLength()));
d.setComment(CodeUnit.EOL_COMMENT, "GNU XHash Table - buckets");
// Elf32_Word chains[ngnusyms]; // consecutive hashvals in a given bucket; last entry in chain has LSB set
addr = addr.add(d.getLength());
d = listing.createData(addr, new ArrayDataType(dt, (int) ngnusyms, dt.getLength()));
d.setComment(CodeUnit.EOL_COMMENT, "GNU XHash Table - chains");
// Elf32_Word xlat[ngnusyms]; // parallel to chains[]; index into .dynsym
addr = addr.add(d.getLength());
d = listing.createData(addr, new ArrayDataType(dt, (int) ngnusyms, dt.getLength()));
d.setComment(CodeUnit.EOL_COMMENT, "GNU XHash Table - xlat");
}
catch (Exception e) {
log("Failed to properly markup GNU Hash table at " + hashTableAddr + ": " +
getMessage(e));
return;
}
}
private void markupSymbolTable(Address symbolTableAddr, ElfSymbolTable symbolTable, private void markupSymbolTable(Address symbolTableAddr, ElfSymbolTable symbolTable,
TaskMonitor monitor) { TaskMonitor monitor) {
@ -2431,13 +2510,13 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
ElfSymbol[] symbols = symbolTable.getSymbols(); ElfSymbol[] symbols = symbolTable.getSymbols();
for (int i = 0; i < symbols.length; ++i) { for (int i = 0; i < symbols.length; ++i) {
int stringOffset = symbols[i].getName(); String name = symbols[i].getNameAsString();
if (stringOffset == 0) { if (StringUtils.isBlank(name)) {
continue; continue;
} }
Data structData = array.getComponent(i); Data structData = array.getComponent(i);
if (structData != null) { if (structData != null) {
structData.setComment(CodeUnit.EOL_COMMENT, symbols[i].getNameAsString()); structData.setComment(CodeUnit.EOL_COMMENT, name);
} }
} }
} }
@ -2533,7 +2612,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
program.getReferenceManager() program.getReferenceManager()
.addMemoryReference(valueData.getAddress(), refAddr, RefType.DATA, .addMemoryReference(valueData.getAddress(), refAddr, RefType.DATA,
SourceType.ANALYSIS, 0); SourceType.ANALYSIS, 0);
if (label != null) { if (!StringUtils.isBlank(label)) {
// add label if no label exists of there is just a default label // add label if no label exists of there is just a default label
Symbol symbol = program.getSymbolTable().getPrimarySymbol(refAddr); Symbol symbol = program.getSymbolTable().getPrimarySymbol(refAddr);
if (symbol == null || symbol.getSource() == SourceType.DEFAULT) { if (symbol == null || symbol.getSource() == SourceType.DEFAULT) {

View file

@ -26,6 +26,7 @@ import ghidra.app.cmd.function.AddStackVarCmd;
import ghidra.app.cmd.refs.AddStackRefCmd; import ghidra.app.cmd.refs.AddStackRefCmd;
import ghidra.program.database.ProgramBuilder; import ghidra.program.database.ProgramBuilder;
import ghidra.program.database.ProgramDB; import ghidra.program.database.ProgramDB;
import ghidra.program.database.symbol.SymbolManager;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.data.PointerDataType; import ghidra.program.model.data.PointerDataType;
import ghidra.program.model.lang.PrototypeModel; import ghidra.program.model.lang.PrototypeModel;
@ -75,6 +76,7 @@ public class FunctionManagerTest extends AbstractGhidraHeadedIntegrationTest {
functionManager.createFunction(name, entryPt, body, SourceType.USER_DEFINED); functionManager.createFunction(name, entryPt, body, SourceType.USER_DEFINED);
Function f = functionManager.getFunctionAt(entryPt); Function f = functionManager.getFunctionAt(entryPt);
assertEquals(name, f.getName());
assertEquals(entryPt, f.getEntryPoint()); assertEquals(entryPt, f.getEntryPoint());
assertEquals(body, f.getBody()); assertEquals(body, f.getBody());
return f; return f;
@ -83,8 +85,19 @@ public class FunctionManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testCreateFunction() throws Exception { public void testCreateFunction() throws Exception {
SymbolManager symbolTable = program.getSymbolTable();
symbolTable.createLabel(addr(100), "foo", SourceType.USER_DEFINED);
createFunction("foo", addr(100), new AddressSet(addr(100), addr(200))); createFunction("foo", addr(100), new AddressSet(addr(100), addr(200)));
Symbol[] symbols = symbolTable.getSymbols(addr(100));
assertEquals(1, symbols.length); // label should be converted to function
Symbol s = symbolTable.createLabel(addr(100), "foo", SourceType.USER_DEFINED);
assertEquals(SymbolType.FUNCTION, s.getSymbolType());
symbols = symbolTable.getSymbols(addr(100));
assertEquals(1, symbols.length); // should still be just a function
// Overlapping functions - not allowed // Overlapping functions - not allowed
try { try {
functionManager.createFunction("foo1", addr(50), new AddressSet(addr(50), addr(100)), functionManager.createFunction("foo1", addr(50), new AddressSet(addr(50), addr(100)),

View file

@ -19,6 +19,8 @@ import java.io.IOException;
import java.util.*; import java.util.*;
import java.util.function.Predicate; import java.util.function.Predicate;
import org.apache.commons.lang3.StringUtils;
import db.*; import db.*;
import generic.FilteredIterator; import generic.FilteredIterator;
import ghidra.program.database.DBObjectCache; import ghidra.program.database.DBObjectCache;
@ -356,7 +358,7 @@ public class FunctionManagerDB implements FunctionManager {
throw new OverlappingFunctionException(entryPoint); throw new OverlappingFunctionException(entryPoint);
} }
if (name == null || name.length() == 0 || if (StringUtils.isBlank(name) ||
SymbolUtilities.isReservedDynamicLabelName(name, program.getAddressFactory())) { SymbolUtilities.isReservedDynamicLabelName(name, program.getAddressFactory())) {
source = SourceType.DEFAULT; source = SourceType.DEFAULT;
name = ""; name = "";

View file

@ -15,6 +15,8 @@
*/ */
package ghidra.app.util.bin.format.elf.extend; package ghidra.app.util.bin.format.elf.extend;
import org.apache.commons.lang3.StringUtils;
import ghidra.app.util.bin.format.elf.*; import ghidra.app.util.bin.format.elf.*;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.lang.Language; import ghidra.program.model.lang.Language;
@ -59,6 +61,9 @@ public class AARCH64_ElfExtension extends ElfExtension {
} }
String symName = elfSymbol.getNameAsString(); String symName = elfSymbol.getNameAsString();
if (StringUtils.isBlank(symName)) {
return address;
}
if ("$x".equals(symName) || symName.startsWith("$x.")) { if ("$x".equals(symName) || symName.startsWith("$x.")) {
elfLoadHelper.markAsCode(address); elfLoadHelper.markAsCode(address);

View file

@ -15,6 +15,8 @@
*/ */
package ghidra.app.util.bin.format.elf.relocation; package ghidra.app.util.bin.format.elf.relocation;
import org.apache.commons.lang3.StringUtils;
import ghidra.app.util.bin.format.elf.*; import ghidra.app.util.bin.format.elf.*;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Function; import ghidra.program.model.listing.Function;
@ -255,7 +257,7 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
if (!isPltSym) { if (!isPltSym) {
setValue(memory, relocationAddress, symAddress.getOffset(), is64bit); setValue(memory, relocationAddress, symAddress.getOffset(), is64bit);
} }
if (isPltSym || isExternalSym) { if ((isPltSym || isExternalSym) && !StringUtils.isBlank(symbolName)) {
Function extFunction = Function extFunction =
elfRelocationContext.getLoadHelper().createExternalFunctionLinkage( elfRelocationContext.getLoadHelper().createExternalFunctionLinkage(
symbolName, symAddress, null); symbolName, symAddress, null);

View file

@ -19,6 +19,8 @@ import java.io.IOException;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.List; import java.util.List;
import org.apache.commons.lang3.StringUtils;
import ghidra.app.util.Option; import ghidra.app.util.Option;
import ghidra.app.util.bin.format.elf.*; import ghidra.app.util.bin.format.elf.*;
import ghidra.app.util.opinion.Loader; import ghidra.app.util.opinion.Loader;
@ -148,6 +150,9 @@ public class ARM_ElfExtension extends ElfExtension {
Program program = elfLoadHelper.getProgram(); Program program = elfLoadHelper.getProgram();
String symName = elfSymbol.getNameAsString(); String symName = elfSymbol.getNameAsString();
if (StringUtils.isBlank(symName)) {
return address;
}
try { try {
Register tmodeRegister = program.getRegister("TMode"); Register tmodeRegister = program.getRegister("TMode");

View file

@ -17,6 +17,8 @@ package ghidra.app.util.bin.format.elf.extend;
import java.math.BigInteger; import java.math.BigInteger;
import org.apache.commons.lang3.StringUtils;
import ghidra.app.util.bin.format.elf.*; import ghidra.app.util.bin.format.elf.*;
import ghidra.app.util.bin.format.elf.ElfDynamicType.ElfDynamicValueType; import ghidra.app.util.bin.format.elf.ElfDynamicType.ElfDynamicValueType;
import ghidra.app.util.bin.format.elf.relocation.MIPS_Elf64Relocation; import ghidra.app.util.bin.format.elf.relocation.MIPS_Elf64Relocation;
@ -361,6 +363,11 @@ public class MIPS_ElfExtension extends ElfExtension {
return address; return address;
} }
String symName = elfSymbol.getNameAsString();
if (StringUtils.isBlank(symName)) {
return address;
}
if (elfSymbol.getType() == ElfSymbol.STT_FUNC) { if (elfSymbol.getType() == ElfSymbol.STT_FUNC) {
Program program = elfLoadHelper.getProgram(); Program program = elfLoadHelper.getProgram();
@ -371,8 +378,7 @@ public class MIPS_ElfExtension extends ElfExtension {
} }
if (!isExternal && (elfSymbol.getOther() & STO_MIPS_PLT) != 0) { if (!isExternal && (elfSymbol.getOther() & STO_MIPS_PLT) != 0) {
elfLoadHelper.createExternalFunctionLinkage(elfSymbol.getNameAsString(), address, elfLoadHelper.createExternalFunctionLinkage(symName, address, null);
null);
} }
} }
return address; return address;
@ -784,9 +790,11 @@ public class MIPS_ElfExtension extends ElfExtension {
ElfDefaultGotPltMarkup.setConstant(pointerData); ElfDefaultGotPltMarkup.setConstant(pointerData);
if (elfSymbols[i].isFunction() && elfSymbols[i].getSectionHeaderIndex() == 0) { if (elfSymbols[i].isFunction() && elfSymbols[i].getSectionHeaderIndex() == 0) {
// ensure that external function/thunk are created in absence of sections // ensure that external function/thunk are created in absence of sections
Address refAddr = (Address) pointerData.getValue(); String symName = elfSymbols[i].getNameAsString();
elfLoadHelper.createExternalFunctionLinkage(elfSymbols[i].getNameAsString(), if (!StringUtils.isBlank(symName)) {
refAddr, gotEntryAddr); Address refAddr = (Address) pointerData.getValue();
elfLoadHelper.createExternalFunctionLinkage(symName, refAddr, gotEntryAddr);
}
} }
} }
} }

View file

@ -987,8 +987,7 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
// failed to allocate section GOT entry for symbol // failed to allocate section GOT entry for symbol
markAsError(mipsRelocationContext.getProgram(), got16reloc.relocAddr, markAsError(mipsRelocationContext.getProgram(), got16reloc.relocAddr,
Integer.toString(got16reloc.relocType), symbolName, Integer.toString(got16reloc.relocType), symbolName,
"Relocation Failed, unable to allocate GOT entry for relocation symbol: " + "Relocation Failed, unable to allocate GOT entry for relocation symbol",
symbolName,
mipsRelocationContext.getLog()); mipsRelocationContext.getLog());
return; return;
} }

View file

@ -18,11 +18,14 @@ package ghidra.app.util.bin.format.elf.extend;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.List; import java.util.List;
import org.apache.commons.lang3.StringUtils;
import ghidra.app.util.bin.format.elf.*; import ghidra.app.util.bin.format.elf.*;
import ghidra.app.util.bin.format.elf.ElfDynamicType.ElfDynamicValueType; import ghidra.app.util.bin.format.elf.ElfDynamicType.ElfDynamicValueType;
import ghidra.app.util.bin.format.elf.relocation.PowerPC64_ElfRelocationConstants; import ghidra.app.util.bin.format.elf.relocation.PowerPC64_ElfRelocationConstants;
import ghidra.app.util.opinion.ElfLoader; import ghidra.app.util.opinion.ElfLoader;
import ghidra.program.model.address.*; import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressOverflowException;
import ghidra.program.model.data.PointerDataType; import ghidra.program.model.data.PointerDataType;
import ghidra.program.model.data.QWordDataType; import ghidra.program.model.data.QWordDataType;
import ghidra.program.model.lang.*; import ghidra.program.model.lang.*;
@ -486,34 +489,35 @@ public class PowerPC64_ElfExtension extends ElfExtension {
// Handle V2 ABI - st_other signals local entry vs. global entry behavior and offset. // Handle V2 ABI - st_other signals local entry vs. global entry behavior and offset.
// 4-byte instructions are assumed.l // 4-byte instructions are assumed.l
String name = elfSymbol.getNameAsString();
Function localFunction = null; Function localFunction = null;
int localOffset = PPC64_ABIV2_GLOBAL_ENTRY_OFFSET[(elfSymbol.getOther() & 0xe0) >>> 5] * 4; int localOffset = PPC64_ABIV2_GLOBAL_ENTRY_OFFSET[(elfSymbol.getOther() & 0xe0) >>> 5] * 4;
if (localOffset != 0) { if (localOffset != 0) {
// generate local function
// generate local symbol TODO: this should really be done after demangling String localName = "";
String name = elfSymbol.getNameAsString(); if (!StringUtils.isBlank(name)) {
String localName = "." + name; // NOTE: this naming could cause issues with mangled name use
localName = "." + name;
}
try { try {
Address localFunctionAddr = address.add(localOffset); Address localFunctionAddr = address.add(localOffset);
localFunction = elfLoadHelper.createOneByteFunction(null, localFunctionAddr, false); localFunction =
if (localFunction != null && elfLoadHelper.createOneByteFunction(localName, localFunctionAddr, false);
localFunction.getSymbol().getSource() == SourceType.DEFAULT) {
elfLoadHelper.createSymbol(localFunctionAddr, localName, true, false, null);
}
// TODO: global function should be a thunk to the local function - need analyzer to do this // TODO: global function should be a thunk to the local function - need analyzer to do this
String cmt = "local function entry for global function " + name + " at {@address " + String cmt = "local function entry for global function " + name + " at {@address " +
address + "}"; address + "}";
elfLoadHelper.getProgram().getListing().setComment(localFunctionAddr, elfLoadHelper.getProgram().getListing().setComment(localFunctionAddr,
CodeUnit.PRE_COMMENT, cmt); CodeUnit.PRE_COMMENT, cmt);
} }
catch (AddressOutOfBoundsException | InvalidInputException e) { catch (Exception e) {
elfLoadHelper.log("Failed to generate local function symbol " + localName + " at " + elfLoadHelper.log("Failed to generate local function symbol " + localName + " at " +
address + "+" + localOffset); address + "+" + localOffset);
} }
} }
Function f = Function f = elfLoadHelper.createOneByteFunction(name, address, false);
elfLoadHelper.createOneByteFunction(elfSymbol.getNameAsString(), address, false);
if (f != null && localFunction != null) { if (f != null && localFunction != null) {
f.setThunkedFunction(localFunction); f.setThunkedFunction(localFunction);
return null; // symbol creation handled return null; // symbol creation handled