mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
Merge remote-tracking branch 'origin/Ghidra_10.2'
This commit is contained in:
commit
be36528218
21 changed files with 283 additions and 274 deletions
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -17,6 +17,8 @@ package ghidra.app.cmd.formats;
|
|||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import ghidra.app.plugin.core.analysis.AnalysisWorker;
|
||||
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
|
||||
import ghidra.app.util.bin.*;
|
||||
|
@ -379,12 +381,14 @@ public class ElfBinaryAnalysisCommand extends FlatProgramAPI
|
|||
}
|
||||
|
||||
String name = symbols[j].getNameAsString();
|
||||
long value = Integer.toUnsignedLong((int) symbols[j].getValue());
|
||||
if (StringUtils.isBlank(name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
Address currAddr = symbolTableAddr.add(j * symbolTable2.getEntrySize());
|
||||
listing.setComment(currAddr, CodeUnit.EOL_COMMENT,
|
||||
name + " at 0x" + Long.toHexString(value));
|
||||
name + " at 0x" + Long.toHexString(symbols[j].getValue()));
|
||||
}
|
||||
catch (Exception e) {
|
||||
messages.appendMsg("Could not markup symbol table: " + e);
|
||||
|
|
|
@ -180,14 +180,13 @@ public class DWARFAnalyzer extends AbstractAnalyzer {
|
|||
return false;
|
||||
}
|
||||
|
||||
DWARFSectionProvider dsp =
|
||||
DWARFSectionProviderFactory.createSectionProviderFor(program, monitor); // closed by DWARFProgram
|
||||
try (DWARFSectionProvider dsp =
|
||||
DWARFSectionProviderFactory.createSectionProviderFor(program, monitor)) {
|
||||
if (dsp == null) {
|
||||
Msg.info(this, "Unable to find DWARF information, skipping DWARF analysis");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
try (DWARFProgram prog = new DWARFProgram(program, importOptions, monitor, dsp)) {
|
||||
if (prog.getRegisterMappings() == null && importOptions.isImportFuncs()) {
|
||||
log.appendMsg(
|
||||
|
|
|
@ -249,7 +249,7 @@ public class DWARFProgram implements Closeable {
|
|||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
sectionProvider.close();
|
||||
sectionProvider = null;
|
||||
compUnits.clear();
|
||||
debugAbbrBR = null;
|
||||
debugInfoBR = null;
|
||||
|
|
|
@ -163,6 +163,8 @@ public class ElfDynamicType {
|
|||
|
||||
// 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",
|
||||
"GNU-style hash table", ElfDynamicValueType.ADDRESS);
|
||||
public static ElfDynamicType DT_TLSDESC_PLT =
|
||||
|
|
|
@ -876,6 +876,7 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
for (ElfSectionHeader symbolTableSectionHeader : sectionHeaders) {
|
||||
if (symbolTableSectionHeader.getType() == ElfSectionHeaderConstants.SHT_SYMTAB ||
|
||||
symbolTableSectionHeader.getType() == ElfSectionHeaderConstants.SHT_DYNSYM) {
|
||||
// || symbolTableSectionHeader.getType() == ElfSectionHeaderConstants.SHT_SUNW_LDYNSYM) {
|
||||
if (symbolTableSectionHeader.isInvalidOffset()) {
|
||||
continue;
|
||||
}
|
||||
|
@ -919,12 +920,26 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
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 {
|
||||
|
||||
ElfDynamicType dynamicHashType = getDynamicHashTableType();
|
||||
|
||||
if (!dynamicTable.containsDynamicValue(ElfDynamicType.DT_SYMTAB) ||
|
||||
!dynamicTable.containsDynamicValue(ElfDynamicType.DT_SYMENT) ||
|
||||
!(dynamicTable.containsDynamicValue(ElfDynamicType.DT_HASH) ||
|
||||
dynamicTable.containsDynamicValue(ElfDynamicType.DT_GNU_HASH))) {
|
||||
dynamicHashType == null) {
|
||||
if (dynamicStringTable != null) {
|
||||
Msg.warn(this, "Failed to parse DT_SYMTAB, missing dynamic dependency");
|
||||
}
|
||||
|
@ -951,11 +966,9 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
tableAddr = adjustAddressForPrelink(tableAddr);
|
||||
long tableEntrySize = dynamicTable.getDynamicValue(ElfDynamicType.DT_SYMENT);
|
||||
|
||||
// Use dynamic symbol hash table DT_HASH or DT_GNU_HASH to determine symbol table count/length
|
||||
boolean useGnuHash = dynamicTable.containsDynamicValue(ElfDynamicType.DT_GNU_HASH);
|
||||
long hashTableAddr =
|
||||
useGnuHash ? dynamicTable.getDynamicValue(ElfDynamicType.DT_GNU_HASH)
|
||||
: dynamicTable.getDynamicValue(ElfDynamicType.DT_HASH);
|
||||
// Use dynamic symbol hash table DT_HASH, DT_GNU_HASH, or DT_GNU_XHASH to
|
||||
// determine symbol table count/length
|
||||
long hashTableAddr = dynamicTable.getDynamicValue(dynamicHashType);
|
||||
hashTableAddr = adjustAddressForPrelink(hashTableAddr);
|
||||
|
||||
ElfProgramHeader symbolTableLoadHeader = getProgramLoadHeaderContaining(tableAddr);
|
||||
|
@ -966,7 +979,7 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
}
|
||||
ElfProgramHeader hashTableLoadHeader = getProgramLoadHeaderContaining(hashTableAddr);
|
||||
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));
|
||||
return null;
|
||||
}
|
||||
|
@ -977,9 +990,12 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
// determine symbol count from dynamic symbol hash table
|
||||
int symCount;
|
||||
long symbolHashTableOffset = hashTableLoadHeader.getOffset(hashTableAddr);
|
||||
if (useGnuHash) {
|
||||
if (dynamicHashType == ElfDynamicType.DT_GNU_HASH) {
|
||||
symCount = deriveGnuHashDynamicSymbolCount(symbolHashTableOffset);
|
||||
}
|
||||
else if (dynamicHashType == ElfDynamicType.DT_GNU_XHASH) {
|
||||
symCount = deriveGnuXHashDynamicSymbolCount(symbolHashTableOffset);
|
||||
}
|
||||
else {
|
||||
// DT_HASH table, nchain corresponds is same as symbol count
|
||||
symCount = reader.readInt(symbolHashTableOffset + 4); // nchain from DT_HASH
|
||||
|
@ -1036,6 +1052,22 @@ public class ElfHeader implements StructConverter, Writeable {
|
|||
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.
|
||||
* This is done against the byte provider since the
|
||||
|
|
|
@ -17,6 +17,8 @@ package ghidra.app.util.bin.format.elf;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.ByteArrayConverter;
|
||||
import ghidra.util.DataConverter;
|
||||
|
@ -48,6 +50,8 @@ import ghidra.util.exception.NotFoundException;
|
|||
*/
|
||||
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.*/
|
||||
public static final byte STB_LOCAL = 0;
|
||||
/**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
|
||||
*/
|
||||
public void initSymbolName(BinaryReader reader, ElfStringTable stringTable) {
|
||||
if (nameAsString == null) {
|
||||
if (nameAsString == null && stringTable != null) {
|
||||
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
|
||||
* stores an byte index into the string table where
|
||||
* 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() {
|
||||
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><no name></I> will be returned.
|
||||
* the name string is located.
|
||||
* @return the actual string name for this symbol or the literal string <I><no name></I>
|
||||
*/
|
||||
public String getFormattedName() {
|
||||
return StringUtils.isBlank(nameAsString) ? FORMATTED_NO_NAME : nameAsString;
|
||||
}
|
||||
|
||||
/**
|
||||
* This member currently holds 0 and has no defined meaning.
|
||||
* @return no defined meaning
|
||||
|
|
|
@ -205,11 +205,24 @@ public class ElfSymbolTable implements ElfFileSection, ByteArrayConverter {
|
|||
/**
|
||||
* Get the ELF symbol name which corresponds to the specified index.
|
||||
* @param symbolIndex symbol index
|
||||
* @return symbol name which corresponds to symbol index or <B><<NONE></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) {
|
||||
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><no name></I> will be returned.
|
||||
* @param symbolIndex symbol index
|
||||
* @return formatted symbol name which corresponds to symbol index or the
|
||||
* literal string <I><no name></I>
|
||||
*/
|
||||
public final String getFormattedSymbolName(int symbolIndex) {
|
||||
ElfSymbol sym = getSymbol(symbolIndex);
|
||||
return sym != null ? sym.getFormattedName() : ElfSymbol.FORMATTED_NO_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,6 +17,8 @@ package ghidra.app.util.bin.format.elf.relocation;
|
|||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import ghidra.app.util.bin.format.elf.*;
|
||||
import ghidra.app.util.bin.format.elf.extend.ElfLoadAdapter;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
|
@ -114,11 +116,15 @@ public class ElfRelocationContext {
|
|||
|
||||
String symName = getSymbolName(relocation.getSymbolIndex());
|
||||
|
||||
String nameMsg = "";
|
||||
if (!StringUtils.isBlank(symName)) {
|
||||
nameMsg = " to: " + symName;
|
||||
}
|
||||
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 +
|
||||
" 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.
|
||||
* @param symbolIndex symbol index
|
||||
* @return symbol name which corresponds to symbol index or <B><<NONE></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) {
|
||||
return symbolTable != null ? symbolTable.getSymbolName(symbolIndex) : "";
|
||||
return symbolTable != null ? symbolTable.getSymbolName(symbolIndex) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -126,7 +126,7 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
|
|||
}
|
||||
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,
|
||||
"EXTERNAL Data Elf Relocation with offset: at " + relocationAddress +
|
||||
" (External Location = " + symbolName + adjStr + ")");
|
||||
|
@ -149,7 +149,7 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
|
|||
public static void markAsUnhandled(Program program, Address relocationAddress, 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("Unhandled Elf Relocation: Type = " + type + " (0x" + Long.toHexString(type) +
|
||||
") at " + relocationAddress + " (Symbol = " + symbolName + ")");
|
||||
BookmarkManager bookmarkManager = program.getBookmarkManager();
|
||||
|
@ -184,7 +184,7 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
|
|||
public static void markAsUninitializedMemory(Program program, Address relocationAddress,
|
||||
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" +
|
||||
Long.toHexString(type) + ") at " + relocationAddress + " (Symbol = " + symbolName +
|
||||
") - uninitialized memory");
|
||||
|
@ -225,7 +225,7 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
|
|||
public static void markAsError(Program program, Address relocationAddress, String type,
|
||||
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 +
|
||||
", Symbol = " + symbolName + ": " + msg);
|
||||
BookmarkManager bookmarkManager = program.getBookmarkManager();
|
||||
|
@ -262,7 +262,7 @@ abstract public class ElfRelocationHandler implements ExtensionPoint {
|
|||
public static void markAsWarning(Program program, Address relocationAddress, String type,
|
||||
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 +
|
||||
", Symbol = " + symbolName + ": " + msg);
|
||||
BookmarkManager bookmarkManager = program.getBookmarkManager();
|
||||
|
|
|
@ -181,6 +181,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
|
||||
markupHashTable(monitor);
|
||||
markupGnuHashTable(monitor);
|
||||
markupGnuXHashTable(monitor);
|
||||
markupGnuBuildId(monitor);
|
||||
markupGnuDebugLink(monitor);
|
||||
|
||||
|
@ -536,7 +537,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
String comment = null;
|
||||
|
||||
comment = symbols[index].getNameAsString();
|
||||
if (comment == null) {
|
||||
if (StringUtils.isBlank(comment)) {
|
||||
comment = Long.toHexString(symbols[index].getValue());
|
||||
}
|
||||
|
||||
|
@ -1546,8 +1547,8 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
boolean usingFakeExternal = false;
|
||||
if (address == Address.NO_ADDRESS) {
|
||||
|
||||
if (symName == null) {
|
||||
continue; // unexpected
|
||||
if (StringUtils.isBlank(symName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check for @<version> or @@<version>
|
||||
|
@ -1574,7 +1575,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
evaluateElfSymbol(elfSymbol, address, usingFakeExternal);
|
||||
}
|
||||
catch (Exception e) {
|
||||
log("Error creating symbol: " + elfSymbol.getNameAsString() + " - " +
|
||||
log("Error creating symbol: " + elfSymbol.getFormattedName() + " - " +
|
||||
getMessage(e));
|
||||
}
|
||||
}
|
||||
|
@ -1598,7 +1599,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
|
||||
if (elfSymbol.isTLS()) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -1646,7 +1647,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
uSectionIndex = elfSymbol.getExtendedSectionHeaderIndex();
|
||||
if (uSectionIndex == 0) {
|
||||
log("Failed to read extended symbol section index: " +
|
||||
elfSymbol.getNameAsString() + " - value=0x" +
|
||||
elfSymbol.getFormattedName() + " - value=0x" +
|
||||
Long.toHexString(elfSymbol.getValue()));
|
||||
return null;
|
||||
}
|
||||
|
@ -1658,7 +1659,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
symSectionBase = findLoadAddress(symSection, 0);
|
||||
if (symSectionBase == null) {
|
||||
log("Unable to place symbol due to non-loaded section: " +
|
||||
elfSymbol.getNameAsString() + " - value=0x" +
|
||||
elfSymbol.getFormattedName() + " - value=0x" +
|
||||
Long.toHexString(elfSymbol.getValue()) + ", section=" +
|
||||
symSection.getNameAsString());
|
||||
return null;
|
||||
|
@ -1678,7 +1679,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
|
||||
// Unable to place symbol within relocatable if section missing/stripped
|
||||
else if (elf.isRelocatable()) {
|
||||
log("No Memory for symbol: " + elfSymbol.getNameAsString() +
|
||||
log("No Memory for symbol: " + elfSymbol.getFormattedName() +
|
||||
" - 0x" + Long.toHexString(elfSymbol.getValue()));
|
||||
return null;
|
||||
}
|
||||
|
@ -1717,7 +1718,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
// SHN_HIPROC 0xff1f
|
||||
// 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" +
|
||||
Integer.toHexString(Short.toUnsignedInt(sectionIndex)));
|
||||
return null;
|
||||
|
@ -1756,6 +1757,9 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
*/
|
||||
private Address findMemoryRegister(ElfSymbol elfSymbol) {
|
||||
String name = elfSymbol.getNameAsString();
|
||||
if (StringUtils.isBlank(name)) {
|
||||
return null;
|
||||
}
|
||||
Address regAddr = getMemoryRegister(name, elfSymbol.getValue());
|
||||
if (regAddr == null) {
|
||||
name = StringUtils.stripStart(name, "_");
|
||||
|
@ -1812,6 +1816,9 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
return false;
|
||||
}
|
||||
String symName = elfSymbol.getNameAsString();
|
||||
if (StringUtils.isBlank(symName)) {
|
||||
return false;
|
||||
}
|
||||
Symbol s = findExternalBlockSymbol(symName, externalBlockLimits.getMinAddress(),
|
||||
lastExternalBlockEntryAddress);
|
||||
if (s != null) {
|
||||
|
@ -1833,6 +1840,9 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
private boolean processVersionedExternal(ElfSymbol elfSymbol) {
|
||||
|
||||
String symName = elfSymbol.getNameAsString();
|
||||
if (StringUtils.isBlank(symName)) {
|
||||
return false;
|
||||
}
|
||||
int index = symName.indexOf("@");
|
||||
if (index < 0) {
|
||||
return false;
|
||||
|
@ -1929,26 +1939,26 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
// Remember where in memory Elf symbols have been mapped
|
||||
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()) {
|
||||
// Do not add section symbols to program symbol table
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -2029,30 +2039,25 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
|
||||
@Override
|
||||
public Function createOneByteFunction(String name, Address address, boolean isEntry) {
|
||||
|
||||
Function function = null;
|
||||
try {
|
||||
if (isEntry) {
|
||||
program.getSymbolTable().addExternalEntryPoint(address);
|
||||
}
|
||||
FunctionManager functionMgr = program.getFunctionManager();
|
||||
function = functionMgr.getFunctionAt(address);
|
||||
if (function == null) {
|
||||
function = functionMgr.createFunction(null, address, new AddressSet(address),
|
||||
SourceType.IMPORTED);
|
||||
}
|
||||
else if (!StringUtils.isEmpty(name)) {
|
||||
createSymbol(address, name, true, false, null);
|
||||
}
|
||||
}
|
||||
catch (Exception 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;
|
||||
}
|
||||
|
||||
|
@ -2392,7 +2397,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
|
||||
addr = addr.add(d.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());
|
||||
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,
|
||||
TaskMonitor monitor) {
|
||||
|
||||
|
@ -2431,13 +2510,13 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
|||
|
||||
ElfSymbol[] symbols = symbolTable.getSymbols();
|
||||
for (int i = 0; i < symbols.length; ++i) {
|
||||
int stringOffset = symbols[i].getName();
|
||||
if (stringOffset == 0) {
|
||||
String name = symbols[i].getNameAsString();
|
||||
if (StringUtils.isBlank(name)) {
|
||||
continue;
|
||||
}
|
||||
Data structData = array.getComponent(i);
|
||||
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()
|
||||
.addMemoryReference(valueData.getAddress(), refAddr, RefType.DATA,
|
||||
SourceType.ANALYSIS, 0);
|
||||
if (label != null) {
|
||||
if (!StringUtils.isBlank(label)) {
|
||||
// add label if no label exists of there is just a default label
|
||||
Symbol symbol = program.getSymbolTable().getPrimarySymbol(refAddr);
|
||||
if (symbol == null || symbol.getSource() == SourceType.DEFAULT) {
|
||||
|
|
|
@ -26,6 +26,7 @@ import ghidra.app.cmd.function.AddStackVarCmd;
|
|||
import ghidra.app.cmd.refs.AddStackRefCmd;
|
||||
import ghidra.program.database.ProgramBuilder;
|
||||
import ghidra.program.database.ProgramDB;
|
||||
import ghidra.program.database.symbol.SymbolManager;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.data.PointerDataType;
|
||||
import ghidra.program.model.lang.PrototypeModel;
|
||||
|
@ -75,6 +76,7 @@ public class FunctionManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
|||
|
||||
functionManager.createFunction(name, entryPt, body, SourceType.USER_DEFINED);
|
||||
Function f = functionManager.getFunctionAt(entryPt);
|
||||
assertEquals(name, f.getName());
|
||||
assertEquals(entryPt, f.getEntryPoint());
|
||||
assertEquals(body, f.getBody());
|
||||
return f;
|
||||
|
@ -83,8 +85,19 @@ public class FunctionManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
|||
@Test
|
||||
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)));
|
||||
|
||||
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
|
||||
try {
|
||||
functionManager.createFunction("foo1", addr(50), new AddressSet(addr(50), addr(100)),
|
||||
|
|
|
@ -19,6 +19,8 @@ import java.io.IOException;
|
|||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import db.*;
|
||||
import generic.FilteredIterator;
|
||||
import ghidra.program.database.DBObjectCache;
|
||||
|
@ -356,7 +358,7 @@ public class FunctionManagerDB implements FunctionManager {
|
|||
throw new OverlappingFunctionException(entryPoint);
|
||||
}
|
||||
|
||||
if (name == null || name.length() == 0 ||
|
||||
if (StringUtils.isBlank(name) ||
|
||||
SymbolUtilities.isReservedDynamicLabelName(name, program.getAddressFactory())) {
|
||||
source = SourceType.DEFAULT;
|
||||
name = "";
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package ghidra.app.util.bin.format.elf.extend;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import ghidra.app.util.bin.format.elf.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.lang.Language;
|
||||
|
@ -59,6 +61,9 @@ public class AARCH64_ElfExtension extends ElfExtension {
|
|||
}
|
||||
|
||||
String symName = elfSymbol.getNameAsString();
|
||||
if (StringUtils.isBlank(symName)) {
|
||||
return address;
|
||||
}
|
||||
|
||||
if ("$x".equals(symName) || symName.startsWith("$x.")) {
|
||||
elfLoadHelper.markAsCode(address);
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package ghidra.app.util.bin.format.elf.relocation;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import ghidra.app.util.bin.format.elf.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Function;
|
||||
|
@ -255,7 +257,7 @@ public class AARCH64_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
if (!isPltSym) {
|
||||
setValue(memory, relocationAddress, symAddress.getOffset(), is64bit);
|
||||
}
|
||||
if (isPltSym || isExternalSym) {
|
||||
if ((isPltSym || isExternalSym) && !StringUtils.isBlank(symbolName)) {
|
||||
Function extFunction =
|
||||
elfRelocationContext.getLoadHelper().createExternalFunctionLinkage(
|
||||
symbolName, symAddress, null);
|
||||
|
|
|
@ -19,6 +19,8 @@ import java.io.IOException;
|
|||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import ghidra.app.util.Option;
|
||||
import ghidra.app.util.bin.format.elf.*;
|
||||
import ghidra.app.util.opinion.Loader;
|
||||
|
@ -148,6 +150,9 @@ public class ARM_ElfExtension extends ElfExtension {
|
|||
Program program = elfLoadHelper.getProgram();
|
||||
|
||||
String symName = elfSymbol.getNameAsString();
|
||||
if (StringUtils.isBlank(symName)) {
|
||||
return address;
|
||||
}
|
||||
|
||||
try {
|
||||
Register tmodeRegister = program.getRegister("TMode");
|
||||
|
|
|
@ -17,6 +17,8 @@ package ghidra.app.util.bin.format.elf.extend;
|
|||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import ghidra.app.util.bin.format.elf.*;
|
||||
import ghidra.app.util.bin.format.elf.ElfDynamicType.ElfDynamicValueType;
|
||||
import ghidra.app.util.bin.format.elf.relocation.MIPS_Elf64Relocation;
|
||||
|
@ -361,6 +363,11 @@ public class MIPS_ElfExtension extends ElfExtension {
|
|||
return address;
|
||||
}
|
||||
|
||||
String symName = elfSymbol.getNameAsString();
|
||||
if (StringUtils.isBlank(symName)) {
|
||||
return address;
|
||||
}
|
||||
|
||||
if (elfSymbol.getType() == ElfSymbol.STT_FUNC) {
|
||||
|
||||
Program program = elfLoadHelper.getProgram();
|
||||
|
@ -371,8 +378,7 @@ public class MIPS_ElfExtension extends ElfExtension {
|
|||
}
|
||||
|
||||
if (!isExternal && (elfSymbol.getOther() & STO_MIPS_PLT) != 0) {
|
||||
elfLoadHelper.createExternalFunctionLinkage(elfSymbol.getNameAsString(), address,
|
||||
null);
|
||||
elfLoadHelper.createExternalFunctionLinkage(symName, address, null);
|
||||
}
|
||||
}
|
||||
return address;
|
||||
|
@ -784,9 +790,11 @@ public class MIPS_ElfExtension extends ElfExtension {
|
|||
ElfDefaultGotPltMarkup.setConstant(pointerData);
|
||||
if (elfSymbols[i].isFunction() && elfSymbols[i].getSectionHeaderIndex() == 0) {
|
||||
// ensure that external function/thunk are created in absence of sections
|
||||
String symName = elfSymbols[i].getNameAsString();
|
||||
if (!StringUtils.isBlank(symName)) {
|
||||
Address refAddr = (Address) pointerData.getValue();
|
||||
elfLoadHelper.createExternalFunctionLinkage(elfSymbols[i].getNameAsString(),
|
||||
refAddr, gotEntryAddr);
|
||||
elfLoadHelper.createExternalFunctionLinkage(symName, refAddr, gotEntryAddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -987,8 +987,7 @@ public class MIPS_ElfRelocationHandler extends ElfRelocationHandler {
|
|||
// failed to allocate section GOT entry for symbol
|
||||
markAsError(mipsRelocationContext.getProgram(), got16reloc.relocAddr,
|
||||
Integer.toString(got16reloc.relocType), symbolName,
|
||||
"Relocation Failed, unable to allocate GOT entry for relocation symbol: " +
|
||||
symbolName,
|
||||
"Relocation Failed, unable to allocate GOT entry for relocation symbol",
|
||||
mipsRelocationContext.getLog());
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -18,11 +18,14 @@ package ghidra.app.util.bin.format.elf.extend;
|
|||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import ghidra.app.util.bin.format.elf.*;
|
||||
import ghidra.app.util.bin.format.elf.ElfDynamicType.ElfDynamicValueType;
|
||||
import ghidra.app.util.bin.format.elf.relocation.PowerPC64_ElfRelocationConstants;
|
||||
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.QWordDataType;
|
||||
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.
|
||||
// 4-byte instructions are assumed.l
|
||||
|
||||
String name = elfSymbol.getNameAsString();
|
||||
Function localFunction = null;
|
||||
|
||||
int localOffset = PPC64_ABIV2_GLOBAL_ENTRY_OFFSET[(elfSymbol.getOther() & 0xe0) >>> 5] * 4;
|
||||
if (localOffset != 0) {
|
||||
|
||||
// generate local symbol TODO: this should really be done after demangling
|
||||
String name = elfSymbol.getNameAsString();
|
||||
String localName = "." + name;
|
||||
// generate local function
|
||||
String localName = "";
|
||||
if (!StringUtils.isBlank(name)) {
|
||||
// NOTE: this naming could cause issues with mangled name use
|
||||
localName = "." + name;
|
||||
}
|
||||
try {
|
||||
Address localFunctionAddr = address.add(localOffset);
|
||||
localFunction = elfLoadHelper.createOneByteFunction(null, localFunctionAddr, false);
|
||||
if (localFunction != null &&
|
||||
localFunction.getSymbol().getSource() == SourceType.DEFAULT) {
|
||||
elfLoadHelper.createSymbol(localFunctionAddr, localName, true, false, null);
|
||||
}
|
||||
localFunction =
|
||||
elfLoadHelper.createOneByteFunction(localName, localFunctionAddr, false);
|
||||
|
||||
// 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 " +
|
||||
address + "}";
|
||||
elfLoadHelper.getProgram().getListing().setComment(localFunctionAddr,
|
||||
CodeUnit.PRE_COMMENT, cmt);
|
||||
}
|
||||
catch (AddressOutOfBoundsException | InvalidInputException e) {
|
||||
catch (Exception e) {
|
||||
elfLoadHelper.log("Failed to generate local function symbol " + localName + " at " +
|
||||
address + "+" + localOffset);
|
||||
}
|
||||
}
|
||||
|
||||
Function f =
|
||||
elfLoadHelper.createOneByteFunction(elfSymbol.getNameAsString(), address, false);
|
||||
Function f = elfLoadHelper.createOneByteFunction(name, address, false);
|
||||
if (f != null && localFunction != null) {
|
||||
f.setThunkedFunction(localFunction);
|
||||
return null; // symbol creation handled
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue