mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +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 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);
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 =
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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><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.
|
* This member currently holds 0 and has no defined meaning.
|
||||||
* @return no defined meaning
|
* @return no defined meaning
|
||||||
|
|
|
@ -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><<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) {
|
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><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 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><<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) {
|
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);
|
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();
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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)),
|
||||||
|
|
|
@ -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 = "";
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue