-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Features: * creates symbols for global variables * creates symbols for functions
- Loading branch information
0 parents
commit e9d8c6c
Showing
22 changed files
with
829 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
build | ||
dist | ||
bin | ||
.gradle | ||
.project | ||
.classpath | ||
.settings | ||
.antProperties.xml |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// Builds a Ghidra Extension for a given Ghidra installation. | ||
// | ||
// An absolute path to the Ghidra installation directory must be supplied either by setting the | ||
// GHIDRA_INSTALL_DIR environment variable or Gradle project property: | ||
// | ||
// > export GHIDRA_INSTALL_DIR=<Absolute path to Ghidra> | ||
// > gradle | ||
// | ||
// or | ||
// | ||
// > gradle -PGHIDRA_INSTALL_DIR=<Absolute path to Ghidra> | ||
// | ||
// Gradle should be invoked from the directory of the project to build. Please see the | ||
// application.gradle.version property in <GHIDRA_INSTALL_DIR>/Ghidra/application.properties | ||
// for the correction version of Gradle to use for the Ghidra installation you specify. | ||
|
||
//----------------------START "DO NOT MODIFY" SECTION------------------------------ | ||
def ghidraInstallDir | ||
|
||
if (System.env.GHIDRA_INSTALL_DIR) { | ||
ghidraInstallDir = System.env.GHIDRA_INSTALL_DIR | ||
} | ||
else if (project.hasProperty("GHIDRA_INSTALL_DIR")) { | ||
ghidraInstallDir = project.getProperty("GHIDRA_INSTALL_DIR") | ||
} | ||
|
||
if (ghidraInstallDir) { | ||
apply from: new File(ghidraInstallDir).getCanonicalPath() + "/support/buildExtension.gradle" | ||
} | ||
else { | ||
throw new GradleException("GHIDRA_INSTALL_DIR is not defined!") | ||
} | ||
//----------------------END "DO NOT MODIFY" SECTION------------------------------- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
name=@extname@ | ||
description=Analyser for DWARF1 debug information | ||
author=Rafal Harabien | ||
createdOn= | ||
version=@extversion@ |
60 changes: 60 additions & 0 deletions
60
src/main/java/com/github/rafalh/ghidra/dwarfone/DWARF1Analyzer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/* ### | ||
* 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. | ||
*/ | ||
package com.github.rafalh.ghidra.dwarfone; | ||
|
||
import ghidra.app.services.AbstractAnalyzer; | ||
import ghidra.app.services.AnalyzerType; | ||
import ghidra.app.util.bin.format.dwarf4.next.sectionprovider.ElfSectionProvider; | ||
import ghidra.app.util.importer.MessageLog; | ||
import ghidra.framework.options.Options; | ||
import ghidra.program.model.address.AddressSetView; | ||
import ghidra.program.model.listing.Program; | ||
import ghidra.util.exception.CancelledException; | ||
import ghidra.util.task.TaskMonitor; | ||
|
||
/** | ||
* Analyzer of DWARF1 debug information. | ||
*/ | ||
public class DWARF1Analyzer extends AbstractAnalyzer { | ||
|
||
public DWARF1Analyzer() { | ||
super("DWARF1 Analyzer", "Analyzer of DWARF debug data in version 1", AnalyzerType.BYTE_ANALYZER); | ||
setDefaultEnablement(false); | ||
setSupportsOneTimeAnalysis(); | ||
} | ||
|
||
@Override | ||
public boolean canAnalyze(Program program) { | ||
var sectionProvider = ElfSectionProvider.createSectionProviderFor(program); | ||
return sectionProvider.hasSection(SectionNames.DEBUG); | ||
} | ||
|
||
@Override | ||
public void registerOptions(Options options, Program program) { | ||
|
||
options.registerOption("Option name goes here", false, null, | ||
"Option description goes here"); | ||
} | ||
|
||
@Override | ||
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log) | ||
throws CancelledException { | ||
|
||
var programAnalyzer = new DWARF1ProgramAnalyzer(program, monitor, log); | ||
programAnalyzer.process(); | ||
return true; | ||
} | ||
} |
132 changes: 132 additions & 0 deletions
132
src/main/java/com/github/rafalh/ghidra/dwarfone/DWARF1ProgramAnalyzer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
package com.github.rafalh.ghidra.dwarfone; | ||
|
||
import java.io.IOException; | ||
import java.util.Optional; | ||
|
||
import com.github.rafalh.ghidra.dwarfone.model.AddrAttributeValue; | ||
import com.github.rafalh.ghidra.dwarfone.model.AttributeName; | ||
import com.github.rafalh.ghidra.dwarfone.model.BlockAttributeValue; | ||
import com.github.rafalh.ghidra.dwarfone.model.DebugInfoEntry; | ||
import com.github.rafalh.ghidra.dwarfone.model.LocationAtomOp; | ||
import com.github.rafalh.ghidra.dwarfone.model.LocationDescription; | ||
import com.github.rafalh.ghidra.dwarfone.model.StringAttributeValue; | ||
|
||
import ghidra.app.util.bin.BinaryReader; | ||
import ghidra.app.util.bin.ByteArrayProvider; | ||
import ghidra.app.util.bin.ByteProvider; | ||
import ghidra.app.util.bin.format.dwarf4.next.sectionprovider.ElfSectionProvider; | ||
import ghidra.app.util.importer.MessageLog; | ||
import ghidra.program.model.address.Address; | ||
import ghidra.program.model.listing.Program; | ||
import ghidra.program.model.symbol.SourceType; | ||
import ghidra.util.exception.InvalidInputException; | ||
import ghidra.util.task.TaskMonitor; | ||
|
||
public class DWARF1ProgramAnalyzer { | ||
private final Program program; | ||
private final TaskMonitor monitor; | ||
private final MessageLog log; | ||
|
||
public DWARF1ProgramAnalyzer(Program program, TaskMonitor monitor, MessageLog log) { | ||
this.program = program; | ||
this.monitor = monitor; | ||
this.log = log; | ||
} | ||
|
||
public boolean process() { | ||
var sectionProvider = ElfSectionProvider.createSectionProviderFor(program); | ||
try { | ||
var debug = sectionProvider.getSectionAsByteProvider(SectionNames.DEBUG); | ||
processDebugSection(debug); | ||
//log.appendMsg("Finished parsing DWARF1"); | ||
return true; | ||
} catch (IOException e) { | ||
log.appendException(e); | ||
return false; | ||
} | ||
} | ||
|
||
private boolean isLittleEndian() { | ||
return !program.getLanguage().isBigEndian(); | ||
} | ||
|
||
private void processDebugSection(ByteProvider bp) throws IOException { | ||
BinaryReader br = new BinaryReader(bp, isLittleEndian()); | ||
while (br.getPointerIndex() < bp.length() && !monitor.isCancelled()) { | ||
var die = new DebugInfoEntry(br); | ||
processDebugInfoEntry(die); | ||
} | ||
} | ||
|
||
private void processDebugInfoEntry(DebugInfoEntry die) throws IOException { | ||
//log.appendMsg(die.toString()); | ||
switch (die.getTag()) { | ||
case GLOBAL_VARIABLE: | ||
processGlobalVariable(die); | ||
break; | ||
case GLOBAL_SUBROUTINE: | ||
processGlobalSubrountine(die); | ||
break; | ||
default: | ||
// skip other tags | ||
} | ||
} | ||
|
||
private LocationDescription decodeLocation(byte[] encodedLocation) throws IOException { | ||
var bp = new ByteArrayProvider(encodedLocation); | ||
return LocationDescription.read(bp, isLittleEndian()); | ||
} | ||
|
||
private Long offsetFromLocation(LocationDescription location) { | ||
var locationAtoms = location.getAtoms(); | ||
if (locationAtoms.size() == 1 && locationAtoms.get(0).getOp() == LocationAtomOp.ADDR) { | ||
return locationAtoms.get(0).getArg(); | ||
} | ||
log.appendMsg("Complex location not supported: " + locationAtoms); | ||
return null; | ||
} | ||
|
||
private void processGlobalVariable(DebugInfoEntry die) throws IOException { | ||
Optional<StringAttributeValue> nameAttributeOptional = die.getAttribute(AttributeName.NAME); | ||
Optional<BlockAttributeValue> locationAttributeOptional = die.getAttribute(AttributeName.LOCATION); | ||
if (nameAttributeOptional.isEmpty() || locationAttributeOptional.isEmpty()) { | ||
return; | ||
} | ||
String name = nameAttributeOptional.get().get(); | ||
byte[] encodedLocation = locationAttributeOptional.get().get(); | ||
LocationDescription location = decodeLocation(encodedLocation); | ||
Long offset = offsetFromLocation(location); | ||
//log.appendMsg(name + " " + Long.toHexString(offset)); | ||
Address addr = toAddr(offset); | ||
try { | ||
program.getSymbolTable().createLabel(addr, name, SourceType.IMPORTED); | ||
} catch (InvalidInputException e) { | ||
log.appendException(e); | ||
} | ||
} | ||
|
||
private void processGlobalSubrountine(DebugInfoEntry die) { | ||
Optional<StringAttributeValue> nameAttributeOptional = die.getAttribute(AttributeName.NAME); | ||
Optional<AddrAttributeValue> lowPcAttributeOptional = die.getAttribute(AttributeName.LOW_PC); | ||
Optional<AddrAttributeValue> highPcAttributeOptional = die.getAttribute(AttributeName.HIGH_PC); | ||
if (nameAttributeOptional.isEmpty() || lowPcAttributeOptional.isEmpty() || highPcAttributeOptional.isEmpty()) { | ||
return; | ||
} | ||
String name = nameAttributeOptional.get().get(); | ||
long lowPc = lowPcAttributeOptional.get().get(); | ||
//long highPc = highPcAttributeOptional.get().get(); | ||
//log.appendMsg(name + " " + Long.toHexString(lowPc.longValue())); | ||
|
||
Address addr = toAddr(lowPc); | ||
try { | ||
program.getSymbolTable().createLabel(addr, name, SourceType.IMPORTED); | ||
} catch (InvalidInputException e) { | ||
log.appendException(e); | ||
} | ||
} | ||
|
||
private final Address toAddr(Number offset) { | ||
return program.getAddressFactory().getDefaultAddressSpace().getAddress( | ||
offset.longValue(), true); | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
src/main/java/com/github/rafalh/ghidra/dwarfone/SectionNames.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package com.github.rafalh.ghidra.dwarfone; | ||
|
||
public class SectionNames { | ||
public static final String DEBUG = "debug"; | ||
} |
18 changes: 18 additions & 0 deletions
18
src/main/java/com/github/rafalh/ghidra/dwarfone/model/AddrAttributeValue.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package com.github.rafalh.ghidra.dwarfone.model; | ||
|
||
public class AddrAttributeValue implements AttributeValue { | ||
private final long addr; | ||
|
||
public AddrAttributeValue(long addr) { | ||
this.addr = addr; | ||
} | ||
|
||
public long get() { | ||
return addr; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "addr(" + Long.toString(addr) + ")"; | ||
} | ||
} |
81 changes: 81 additions & 0 deletions
81
src/main/java/com/github/rafalh/ghidra/dwarfone/model/AttributeName.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package com.github.rafalh.ghidra.dwarfone.model; | ||
|
||
import java.util.Map; | ||
import java.util.function.Function; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.Stream; | ||
|
||
public enum AttributeName { | ||
SIBLING(0x0010), | ||
LOCATION(0x0020), | ||
NAME(0x0030), | ||
FUND_TYPE(0x0050), | ||
MOD_FUND_TYPE(0x0060), | ||
USER_DEF_TYPE(0x0070), | ||
MOD_U_D_TYPE(0x0080), | ||
ORDERING(0x0090), | ||
SUBSCR_DATA(0x00A0), | ||
BYTE_SIZE(0x00B0), | ||
BIT_OFFSET(0x00C0), | ||
BIT_SIZE(0x00D0), | ||
ELEMENT_LIST(0x00F0), | ||
STMT_LIST(0x0100), | ||
LOW_PC(0x0110), | ||
HIGH_PC(0x0120), | ||
LANGUAGE(0x0130), | ||
MEMBER(0x0140), | ||
DISCR(0x0150), | ||
DISCR_VALUE(0x0160), | ||
STRING_LENGTH(0x0190), | ||
COMMON_REFERENCE(0x01A0), | ||
COMP_DIR(0x01B0), | ||
CONST_VALUE(0x01C0), | ||
CONTAINING_TYPE(0x01D0), | ||
DEFAULT_VALUE(0x01E0), | ||
FRIENDS(0x01F0), | ||
INLINE(0x0200), | ||
IS_OPTIONAL(0x0210), | ||
LOWER_BOUND(0x0220), | ||
PROGRAM(0x0230), | ||
PRIVATE(0x0240), | ||
PRODUCER(0x0250), | ||
PROTECTED(0x0260), | ||
PROTOTYPED(0x0270), | ||
PUBLIC(0x0280), | ||
PURE_VIRTUAL(0x0290), | ||
RETURN_ADDRBLOCK2(0x02A0), | ||
SPECIFICATIONREFERENCE(0x02B0), | ||
START_SCOPE(0x02C0), | ||
STRIDE_SIZE(0x02E0), | ||
UPPER_BOUND(0x02F0), | ||
VIRTUAL(0x0300), | ||
USER(null); | ||
|
||
public static final int MASK = 0xFFF0; | ||
private static final int LO_USER = 0x2000; | ||
private static final int HI_USER = 0x3ff0; | ||
private static final Map<Integer, AttributeName> VALUE_MAP; | ||
|
||
private Integer value; | ||
|
||
static { | ||
VALUE_MAP = Stream.of(AttributeName.values()) | ||
.filter(at -> at.value != null) | ||
.collect(Collectors.toUnmodifiableMap(at -> at.value, Function.identity())); | ||
} | ||
|
||
AttributeName(Integer value) { | ||
this.value = value; | ||
} | ||
|
||
public static AttributeName decode(int value) { | ||
if (value >= LO_USER && value <= HI_USER) { | ||
return USER; | ||
} | ||
AttributeName at = VALUE_MAP.get(value); | ||
if (at == null) { | ||
throw new IllegalArgumentException("invalid attribute value " + value); | ||
} | ||
return at; | ||
} | ||
} |
4 changes: 4 additions & 0 deletions
4
src/main/java/com/github/rafalh/ghidra/dwarfone/model/AttributeValue.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package com.github.rafalh.ghidra.dwarfone.model; | ||
|
||
public interface AttributeValue { | ||
} |
13 changes: 13 additions & 0 deletions
13
src/main/java/com/github/rafalh/ghidra/dwarfone/model/BlockAttributeValue.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package com.github.rafalh.ghidra.dwarfone.model; | ||
|
||
public class BlockAttributeValue implements AttributeValue { | ||
private final byte[] block; | ||
|
||
public BlockAttributeValue(byte[] block) { | ||
this.block = block; | ||
} | ||
|
||
public byte[] get() { | ||
return block; | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
src/main/java/com/github/rafalh/ghidra/dwarfone/model/ConstAttributeValue.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package com.github.rafalh.ghidra.dwarfone.model; | ||
|
||
import java.util.Objects; | ||
|
||
public class ConstAttributeValue implements AttributeValue { | ||
private final Number value; | ||
|
||
public ConstAttributeValue(Number value) { | ||
this.value = value; | ||
} | ||
|
||
public Number get() { | ||
return value; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return Objects.toString(value); | ||
} | ||
} |
Oops, something went wrong.