GP-713 added support for ELF PowerPC R_PPC_EMB_SDA21 relocation. Also revised PowerPC cspecs in support of EABI.

This commit is contained in:
ghidra1
2022-07-25 08:38:40 -04:00
parent ba83024c10
commit 0d54d2d7c3
8 changed files with 379 additions and 22 deletions

View File

@@ -87,6 +87,9 @@
</pentry>
</output>
<unaffected>
<register name="r1"/> <!-- stack pointer -->
<register name="r2"/> <!-- _SDA2_BASE_ -->
<register name="r13"/> <!-- _SDA_BASE_ -->
<register name="r14"/>
<register name="r15"/>
<register name="r16"/>
@@ -105,7 +108,8 @@
<register name="r29"/>
<register name="r30"/>
<register name="r31"/>
<register name="r1"/>
<register name="cr2"/>
<register name="cr3"/>
<register name="cr4"/>
</unaffected>
</prototype>

View File

@@ -87,6 +87,9 @@
</pentry>
</output>
<unaffected>
<register name="r1"/> <!-- stack pointer -->
<register name="r2"/> <!-- _SDA2_BASE_ -->
<register name="r13"/> <!-- _SDA_BASE_ -->
<register name="r14"/>
<register name="r15"/>
<register name="r16"/>
@@ -105,7 +108,9 @@
<register name="r29"/>
<register name="r30"/>
<register name="r31"/>
<register name="r1"/>
<register name="cr2"/>
<register name="cr3"/>
<register name="cr4"/>
</unaffected>
</prototype>
</default_proto>

View File

@@ -1733,12 +1733,20 @@ define pcodeop stdcixOp;
}
# binutils-descr: "lq", OP(56), OP_MASK, POWER4, PPC476, {RTQ, DQ, RAQ}
define pcodeop lqOp;
# ISA-cmt: lq - Load Quadword
# ISA-info: lq - Form "DQ" Page 751 Category "LSQ"
# binutils: power4.d: +0: e0 83 00 00 lq r4,0\(r3\)
# binutils: power4.d: +4: e0 83 00 00 lq r4,0\(r3\)
:lq RT,A,DQ is $(NOTVLE) & OP=56 & RT & A & DQ & BITS_0_3=0 { RT = lqOp(RT,A); }
:lq RT,A,DQ is $(NOTVLE) & OP=56 & RT & Dp & A & DQ & BITS_0_3=0 & regp [regpset = Dp+1;] {
ea:$(REGISTER_SIZE) = A + sext(DQ:2 << 4);
@if ENDIAN == "big"
RT = *:$(REGISTER_SIZE) ea;
regp = *:$(REGISTER_SIZE) (ea + $(REGISTER_SIZE));
@else
RT = *:$(REGISTER_SIZE) (ea + $(REGISTER_SIZE));
regp = *:$(REGISTER_SIZE) ea;
@endif
}
define pcodeop lvepxOp;
:lvepx RT,A,B is OP=31 & RT & A & B & XOP_1_10=295 & BIT_0=0 { RT = lvepxOp(RT,A,B); }
@@ -2038,7 +2046,6 @@ define pcodeop stfdpOp;
}
# binutils-descr: "stq", DSO(62,2), DS_MASK, POWER4, PPC476, {RSQ, DS, RA0}
define pcodeop stqOp;
# ISA-cmt: stq - Store Quadword
# ISA-info: stq - Form "DS" Page 751 Category "LSQ"
# binutils: power4.d: +50: f8 c7 00 02 stq r6,0\(r7\)
@@ -2046,9 +2053,15 @@ define pcodeop stqOp;
# binutils: power4.d: +58: f8 c7 ff f2 stq r6,-16\(r7\)
# binutils: power4.d: +5c: f8 c7 80 02 stq r6,-32768\(r7\)
# binutils: power4.d: +60: f8 c7 7f f2 stq r6,32752\(r7\)
:stq S,RA_OR_ZERO,DS is $(NOTVLE) & OP=62 & S & RA_OR_ZERO & DS & BITS_0_1=2 {
EA:$(REGISTER_SIZE) = RA_OR_ZERO + sext(DS:2 << 2);
*:16 EA = stqOp(S,RA_OR_ZERO,DS:2);
:stq RS,RA_OR_ZERO,DS is $(NOTVLE) & OP=62 & RS & Dp & RA_OR_ZERO & DS & BITS_0_1=2 & regp [regpset = Dp+1;] {
ea:$(REGISTER_SIZE) = RA_OR_ZERO + sext(DS:2 << 2);
@if ENDIAN == "big"
*:$(REGISTER_SIZE) ea = RS;
*:$(REGISTER_SIZE) (ea + $(REGISTER_SIZE)) = regp;
@else
*:$(REGISTER_SIZE) (ea + $(REGISTER_SIZE)) = RS;
*:$(REGISTER_SIZE) ea = regp;
@endif
}
define pcodeop stvepxOp;

View File

@@ -47,11 +47,22 @@ public class PowerPC64_ElfExtension extends ElfExtension {
public static final ElfDynamicType DT_PPC64_OPDSZ = new ElfDynamicType(0x70000002,
"DT_PPC64_OPDSZ", "Specify the size of the .opd section", ElfDynamicValueType.ADDRESS);
public static final ElfDynamicType DT_PPC64_OPT = new ElfDynamicType(0x70000003, "DT_PPC64_OPT",
"Specify whether various optimisations are possible", ElfDynamicValueType.VALUE);
"Specify whether various optimizations are possible", ElfDynamicValueType.VALUE);
// PPC64 ABI Version Flag Bits contained within ElfHeader e_flags
private static final int EF_PPC64_ABI = 3;
// DT_PPC64_OPT bits
private static final int PPC64_OPT_TLS = 1;
private static final int PPC64_OPT_MULTI_TOC = 2;
private static final int PPC64_OPT_LOCALENTRY = 4;
// ELFv2 ABI symbol st_other bits
// STO_PPC64_LOCAL specifies the number of instructions between a
// function's global entry point and local entry point
private static final int STO_PPC64_LOCAL_BIT = 5;
private static final int STO_PPC64_LOCAL_MASK = 0xE0;
public static final String TOC_BASE = "TOC_BASE"; // injected symbol to mark global TOC_BASE
@Override

View File

@@ -46,6 +46,11 @@ public class PowerPC_ElfExtension extends ElfExtension {
public static final ElfDynamicType DT_PPC_OPT = new ElfDynamicType(0x70000001, "DT_PPC_OPT",
"Specify that tls descriptors should be optimized", ElfDynamicValueType.VALUE);
// ELF header flags
private static final int EF_PPC_EMB = 0x80000000; // PowerPC embedded flag
private static final int EF_PPC_RELOCATABLE = 0x00010000;
private static final int EF_PPC_RELOCATABLE_LIB = 0x00008000;
// Program header (segment) flags
private static final int PF_PPC_VLE = 0x10000000;

View File

@@ -122,6 +122,44 @@ public class PowerPC64_ElfRelocationConstants {
public static final int R_PPC64_DTPREL16_HIGHEST = 105; // half16 #highest(@dtprel)
public static final int R_PPC64_DTPREL16_HIGHESTA = 106; // half16 #highesta(@dtprel)
public static final int R_PPC64_PLTSEQ_NOTOC = 121;
public static final int R_PPC64_PLTCALL_NOTOC = 122;
public static final int R_PPC64_PCREL_OPT = 123;
public static final int R_PPC64_D34 = 128;
public static final int R_PPC64_D34_LO = 129;
public static final int R_PPC64_D34_HI30 = 130;
public static final int R_PPC64_D34_HA30 = 131;
public static final int R_PPC64_PCREL34 = 132;
public static final int R_PPC64_GOT_PCREL34 = 133;
public static final int R_PPC64_PLT_PCREL34 = 134;
public static final int R_PPC64_PLT_PCREL34_NOTOC = 135;
public static final int R_PPC64_ADDR16_HIGHER34 = 136;
public static final int R_PPC64_ADDR16_HIGHERA34 = 137;
public static final int R_PPC64_ADDR16_HIGHEST34 = 138;
public static final int R_PPC64_ADDR16_HIGHESTA34 = 139;
public static final int R_PPC64_REL16_HIGHER34 = 140;
public static final int R_PPC64_REL16_HIGHERA34 = 141;
public static final int R_PPC64_REL16_HIGHEST34 = 142;
public static final int R_PPC64_REL16_HIGHESTA34 = 143;
public static final int R_PPC64_D28 = 144;
public static final int R_PPC64_PCREL28 = 145;
public static final int R_PPC64_TPREL34 = 146;
public static final int R_PPC64_DTPREL34 = 147;
public static final int R_PPC64_GOT_TLSGD_PCREL34 = 148;
public static final int R_PPC64_GOT_TLSLD_PCREL34 = 149;
public static final int R_PPC64_GOT_TPREL_PCREL34 = 150;
public static final int R_PPC64_GOT_DTPREL_PCREL34 = 151;
public static final int R_PPC64_REL16_HIGH = 240;
public static final int R_PPC64_REL16_HIGHA = 241;
public static final int R_PPC64_REL16_HIGHER = 242;
public static final int R_PPC64_REL16_HIGHERA = 243;
public static final int R_PPC64_REL16_HIGHEST = 244;
public static final int R_PPC64_REL16_HIGHESTA = 245;
public static final int R_PPC64_JMP_IREL = 247;
// Masks for manipulating Power PC relocation targets
public static final int PPC64_WORD32 = 0xFFFFFFFF;
public static final int PPC64_WORD30 = 0xFFFFFFFC;

View File

@@ -58,6 +58,85 @@ public class PowerPC_ElfRelocationConstants {
public static final int R_PPC_SECTOFF_HA = 36; // half16 #ha(R + A)
public static final int R_PPC_ADDR30 = 37; // word30 (S + A - P) >> 2
public static final int R_POWERPC_TLS = 67;
public static final int R_POWERPC_DTPMOD = 68;
public static final int R_POWERPC_TPREL16 = 69;
public static final int R_POWERPC_TPREL16_LO = 70;
public static final int R_POWERPC_TPREL16_HI = 71;
public static final int R_POWERPC_TPREL16_HA = 72;
public static final int R_POWERPC_TPREL = 73;
public static final int R_POWERPC_DTPREL16 = 74;
public static final int R_POWERPC_DTPREL16_LO = 75;
public static final int R_POWERPC_DTPREL16_HI = 76;
public static final int R_POWERPC_DTPREL16_HA = 77;
public static final int R_POWERPC_DTPREL = 78;
public static final int R_POWERPC_GOT_TLSGD16 = 79;
public static final int R_POWERPC_GOT_TLSGD16_LO = 80;
public static final int R_POWERPC_GOT_TLSGD16_HI = 81;
public static final int R_POWERPC_GOT_TLSGD16_HA = 82;
public static final int R_POWERPC_GOT_TLSLD16 = 83;
public static final int R_POWERPC_GOT_TLSLD16_LO = 84;
public static final int R_POWERPC_GOT_TLSLD16_HI = 85;
public static final int R_POWERPC_GOT_TLSLD16_HA = 86;
public static final int R_POWERPC_GOT_TPREL16 = 87;
public static final int R_POWERPC_GOT_TPREL16_LO = 88;
public static final int R_POWERPC_GOT_TPREL16_HI = 89;
public static final int R_POWERPC_GOT_TPREL16_HA = 90;
public static final int R_POWERPC_GOT_DTPREL16 = 91;
public static final int R_POWERPC_GOT_DTPREL16_LO = 92;
public static final int R_POWERPC_GOT_DTPREL16_HI = 93;
public static final int R_POWERPC_GOT_DTPREL16_HA = 94;
public static final int R_PPC_TLSGD = 95;
public static final int R_PPC_TLSLD = 96;
public static final int R_PPC_EMB_NADDR32 = 101; // uword32 (A - S)
public static final int R_PPC_EMB_NADDR16 = 102; // uhalf16 (A - S)
public static final int R_PPC_EMB_NADDR16_LO = 103; // uhalf16 #lo(A - S)
public static final int R_PPC_EMB_NADDR16_HI = 104; // uhalf16 #hi(A - S)
public static final int R_PPC_EMB_NADDR16_HA = 105; // uhalf16 #ha(A - S)
public static final int R_PPC_EMB_SDAI16 = 106; // uhalf16 T
public static final int R_PPC_EMB_SDA2I16 = 107; // uhalf16 U
public static final int R_PPC_EMB_SDA2REL = 108; // uhalf16 S + A - _SDA2_BASE_
public static final int R_PPC_EMB_SDA21 = 109; // ulow21
public static final int R_PPC_EMB_MRKREF = 110; // none
public static final int R_PPC_EMB_RELSEC16 = 111; // uhalf16 V + A
public static final int R_PPC_EMB_RELST_LO = 112; // uhalf16 #lo(W + A)
public static final int R_PPC_EMB_RELST_HI = 113; // uhalf16 #hi(W + A)
public static final int R_PPC_EMB_RELST_HA = 114; // uhalf16 #ha(W + A)
public static final int R_PPC_EMB_BIT_FLD = 115; // uword32
public static final int R_PPC_EMB_RELSDA = 116; // uhalf16
public static final int R_POWERPC_PLTSEQ = 119;
public static final int R_POWERPC_PLTCALL = 120;
public static final int R_PPC_VLE_REL8 = 216;
public static final int R_PPC_VLE_REL15 = 217;
public static final int R_PPC_VLE_REL24 = 218;
public static final int R_PPC_VLE_LO16A = 219;
public static final int R_PPC_VLE_LO16D = 220;
public static final int R_PPC_VLE_HI16A = 221;
public static final int R_PPC_VLE_HI16D = 222;
public static final int R_PPC_VLE_HA16A = 223;
public static final int R_PPC_VLE_HA16D = 224;
public static final int R_PPC_VLE_SDA21 = 225;
public static final int R_PPC_VLE_SDA21_LO = 226;
public static final int R_PPC_VLE_SDAREL_LO16A = 227;
public static final int R_PPC_VLE_SDAREL_LO16D = 228;
public static final int R_PPC_VLE_SDAREL_HI16A = 229;
public static final int R_PPC_VLE_SDAREL_HI16D = 230;
public static final int R_PPC_VLE_SDAREL_HA16A = 231;
public static final int R_PPC_VLE_SDAREL_HA16D = 232;
public static final int R_POWERPC_REL16DX_HA = 246;
public static final int R_POWERPC_IRELATIVE = 248;
public static final int R_POWERPC_REL16 = 249;
public static final int R_POWERPC_REL16_LO = 250;
public static final int R_POWERPC_REL16_HI = 251;
public static final int R_POWERPC_REL16_HA = 252;
public static final int R_POWERPC_GNU_VTINHERIT = 253;
public static final int R_POWERPC_GNU_VTENTRY = 254;
public static final int R_PPC_TOC16 = 255;
// Masks for manipulating Power PC relocation targets
public static final int PPC_WORD32 = 0xFFFFFFFF;
public static final int PPC_WORD30 = 0xFFFFFFFC;

View File

@@ -15,14 +15,22 @@
*/
package ghidra.app.util.bin.format.elf.relocation;
import java.math.BigInteger;
import java.util.Map;
import com.google.common.base.Predicate;
import ghidra.app.util.bin.format.elf.*;
import ghidra.app.util.bin.format.elf.extend.PowerPC_ElfExtension;
import ghidra.program.model.address.Address;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.Language;
import ghidra.program.model.lang.Register;
import ghidra.program.model.listing.ContextChangeException;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.util.exception.NotFoundException;
import ghidra.program.model.mem.*;
import ghidra.program.model.symbol.*;
import ghidra.util.exception.*;
public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
@@ -31,16 +39,25 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
return elf.e_machine() == ElfConstants.EM_PPC && elf.is32Bit();
}
@Override
public PowerPC_ElfRelocationContext createRelocationContext(ElfLoadHelper loadHelper,
ElfRelocationTable relocationTable, Map<ElfSymbol, Address> symbolMap) {
return new PowerPC_ElfRelocationContext(this, loadHelper, relocationTable, symbolMap);
}
@Override
public void relocate(ElfRelocationContext elfRelocationContext, ElfRelocation relocation,
Address relocationAddress) throws MemoryAccessException, NotFoundException {
ElfHeader elf = elfRelocationContext.getElfHeader();
PowerPC_ElfRelocationContext ppcRelocationContext =
(PowerPC_ElfRelocationContext) elfRelocationContext;
ElfHeader elf = ppcRelocationContext.getElfHeader();
if (elf.e_machine() != ElfConstants.EM_PPC || !elf.is32Bit()) {
return;
}
Program program = elfRelocationContext.getProgram();
Program program = ppcRelocationContext.getProgram();
Memory memory = program.getMemory();
int type = relocation.getType();
@@ -49,12 +66,12 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
}
int symbolIndex = relocation.getSymbolIndex();
Language language = elfRelocationContext.getProgram().getLanguage();
Language language = ppcRelocationContext.getProgram().getLanguage();
if (!"PowerPC".equals(language.getProcessor().toString()) ||
language.getLanguageDescription().getSize() != 32) {
markAsError(program, relocationAddress, Long.toString(type), null,
"Unsupported language for 32-bit PowerPC relocation",
elfRelocationContext.getLog());
ppcRelocationContext.getLog());
}
// NOTE: Based upon glibc source it appears that PowerPC only uses RELA relocations
@@ -72,7 +89,7 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
//
// // Relocation addend already includes original symbol value but needs to account
// // for any image base adjustment
// symbolValue = (int) elfRelocationContext.getImageBaseWordAdjustmentOffset();
// symbolValue = (int) ppcRelocationContext.getImageBaseWordAdjustmentOffset();
// }
// else {
Address symbolAddr = (elfRelocationContext.getSymbolAddress(sym));
@@ -162,7 +179,7 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
memory.setInt(relocationAddress, newValue);
break;
case PowerPC_ElfRelocationConstants.R_PPC_RELATIVE:
newValue = (int) elfRelocationContext.getImageBaseWordAdjustmentOffset() + addend;
newValue = (int) ppcRelocationContext.getImageBaseWordAdjustmentOffset() + addend;
memory.setInt(relocationAddress, newValue);
break;
case PowerPC_ElfRelocationConstants.R_PPC_REL32:
@@ -202,15 +219,200 @@ public class PowerPC_ElfRelocationHandler extends ElfRelocationHandler {
// not too far away since a fabricated GOT would be in the same block
// and we may only have room in the plt for two instructions.
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
elfRelocationContext.getLog());
ppcRelocationContext.getLog());
}
break;
case PowerPC_ElfRelocationConstants.R_PPC_EMB_SDA21:
// NOTE: PPC EABI V1.0 specifies this relocation on a 24-bit field address while
// GNU assumes a 32-bit field address. We cope with this difference by
// forcing a 32-bit alignment of the relocation address.
long alignedRelocOffset = relocationAddress.getOffset() & ~3;
relocationAddress = relocationAddress.getNewAddress(alignedRelocOffset);
oldValue = memory.getInt(relocationAddress);
Address symAddr = ppcRelocationContext.getSymbolAddress(sym);
MemoryBlock block = memory.getBlock(symAddr);
Integer sdaBase = null;
Integer gprID = null;
if (block != null) {
String blockName = block.getName();
if (".sdata".equals(blockName) || ".sbss".equals(blockName)) {
sdaBase = ppcRelocationContext.getSDABase();
gprID = 13;
}
else if (".sdata2".equals(blockName) || ".sbss2".equals(blockName)) {
sdaBase = ppcRelocationContext.getSDA2Base();
gprID = 2;
}
else if (".PPC.EMB.sdata0".equals(blockName) ||
".PPC.EMB.sbss0".equals(blockName)) {
sdaBase = 0;
gprID = 0;
}
else if (MemoryBlock.EXTERNAL_BLOCK_NAME.equals(blockName)) {
markAsError(program, relocationAddress, type, sym.getNameAsString(),
"Unsupported relocation for external symbol",
ppcRelocationContext.getLog());
break;
}
}
if (gprID == null || sdaBase == null) {
markAsError(program, relocationAddress, type, sym.getNameAsString(),
"Failed to identfy appropriate data block", ppcRelocationContext.getLog());
break;
}
newValue = (symbolValue - sdaBase + addend) & 0xffff;
newValue |= gprID << 16;
newValue |= oldValue & 0xffe00000;
memory.setInt(relocationAddress, newValue);
break;
default:
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
elfRelocationContext.getLog());
ppcRelocationContext.getLog());
break;
}
}
/**
* <code>PowerPC_ElfRelocationContext</code> provides extended relocation context..
*/
private static class PowerPC_ElfRelocationContext extends ElfRelocationContext {
private Integer sdaBase;
private Integer sda2Base;
protected PowerPC_ElfRelocationContext(ElfRelocationHandler handler,
ElfLoadHelper loadHelper, ElfRelocationTable relocationTable,
Map<ElfSymbol, Address> symbolMap) {
super(handler, loadHelper, relocationTable, symbolMap);
}
/**
* Get or establish _SDA_BASE_ value and apply as r13 context value to all memory blocks
* with execute permission.
* @return _SDA_BASE_ offset or null if unable to determine or establish
*/
Integer getSDABase() {
if (sdaBase != null) {
if (sdaBase == -1) {
return null;
}
return sdaBase;
}
sdaBase = getBaseOffset("_SDA_BASE_", ".sdata", ".sbss");
if (sdaBase == -1) {
getLog().appendMsg("ERROR: failed to establish _SDA_BASE_");
return null;
}
setRegisterContext("r13", BigInteger.valueOf(sdaBase), b -> b.isExecute());
return sdaBase;
}
/**
* Get or establish _SDA2_BASE_ value and apply as r2 context value to all memory blocks
* with execute permission.
* @return _SDA2_BASE_ offset or null if unable to determine or establish
*/
Integer getSDA2Base() {
if (sda2Base != null) {
if (sda2Base == -1) {
return null;
}
return sda2Base;
}
sda2Base = getBaseOffset("_SDA2_BASE_", ".sdata2", ".sbss2");
if (sda2Base == -1) {
getLog().appendMsg("ERROR: failed to establish _SDA2_BASE_");
return null;
}
setRegisterContext("r2", BigInteger.valueOf(sda2Base), b -> b.isExecute());
return sda2Base;
}
/**
* Apply register context to all memory blocks which satisfy blockPredicate check.
* @param regName register name
* @param value context value
* @param blockPredicate determine which memory blocks get context applied
*/
private void setRegisterContext(String regName, BigInteger value,
Predicate<MemoryBlock> blockPredicate) {
Register reg = program.getRegister(regName);
for (MemoryBlock block : program.getMemory().getBlocks()) {
if (block.isExecute()) {
try {
program.getProgramContext().setValue(reg, block.getStart(), block.getEnd(),
value);
}
catch (ContextChangeException e) {
throw new AssertException(e); // no instructions should exist yet
}
}
}
}
/**
* Establish base offset from symbol or range of specified memory blocks.
* @param symbolName base symbol name
* @param blockNames block names which may be used to establish base range
* @return base offset or -1 on failure
*/
private Integer getBaseOffset(String symbolName, String... blockNames) {
MessageLog log = getLog();
Symbol baseSymbol = SymbolUtilities.getLabelOrFunctionSymbol(program, symbolName,
msg -> log.appendMsg(msg));
if (baseSymbol != null) {
int baseOffset = (int) baseSymbol.getAddress().getOffset();
String absString = "";
if (baseSymbol.isPinned()) {
absString = "absolute ";
}
log.appendMsg(
"Using " + absString + symbolName + " of 0x" + Integer.toHexString(baseOffset));
return baseOffset;
}
Memory mem = program.getMemory();
AddressSpace defaultSpace = program.getAddressFactory().getDefaultAddressSpace();
AddressSet blockSet = new AddressSet();
for (String blockName : blockNames) {
MemoryBlock block = mem.getBlock(blockName);
if (block != null) {
if (!block.getStart().getAddressSpace().equals(defaultSpace)) {
log.appendMsg("ERROR: " + blockName + " not in default space");
return -1;
}
blockSet.add(block.getStart(), block.getEnd());
}
}
if (blockSet.isEmpty()) {
return -1;
}
Address baseAddr = blockSet.getMinAddress();
long range = blockSet.getMaxAddress().subtract(baseAddr) + 1;
if (range > Short.MAX_VALUE) {
// use aligned midpoint of range
baseAddr = baseAddr.add((range / 2) & ~0x0f);
}
try {
program.getSymbolTable().createLabel(baseAddr, symbolName, SourceType.ANALYSIS);
}
catch (InvalidInputException e) {
throw new AssertException(e);
}
int baseOffset = (int) baseAddr.getOffset();
log.appendMsg("Defined " + symbolName + " of 0x" + Integer.toHexString(baseOffset));
return baseOffset;
}
}
}