mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-22 12:11:55 +00:00
GP-2213_emteere support for 24-bit spaces, byte addressed code space, hex importer fixes, AVR8 relocations
This commit is contained in:
parent
cd7599e3b9
commit
b34f43e685
@ -2999,14 +2999,14 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
||||
if (type != ElfSectionHeaderConstants.SHT_NOBITS &&
|
||||
(fileOffset < 0 || fileOffset >= fileBytes.getSize())) {
|
||||
log("Skipping section [" + elfSectionToLoad.getNameAsString() +
|
||||
"] with invalid file offset");
|
||||
"] with invalid file offset 0x" + Long.toHexString(fileOffset));
|
||||
continue;
|
||||
}
|
||||
long size = elfSectionToLoad.getSize();
|
||||
if (size <= 0 ||
|
||||
(type != ElfSectionHeaderConstants.SHT_NOBITS && size >= fileBytes.getSize())) {
|
||||
log("Skipping section [" + elfSectionToLoad.getNameAsString() +
|
||||
"] with invalid size");
|
||||
"] with invalid size 0x" + Long.toHexString(size));
|
||||
continue;
|
||||
}
|
||||
processSectionHeader(elfSectionToLoad, relocatableImageBaseProvider);
|
||||
|
@ -230,7 +230,7 @@ public class IntelHexLoader extends AbstractProgramLoader {
|
||||
}
|
||||
|
||||
String msg = memImage.createMemory(getName(), provider.getName(),
|
||||
isOverlay ? blockName : null, isOverlay, program, monitor);
|
||||
blockName, isOverlay, program, monitor);
|
||||
|
||||
if (msg.length() > 0) {
|
||||
log.appendMsg(msg);
|
||||
|
@ -96,6 +96,10 @@ class IntelHexMemImage {
|
||||
}
|
||||
break;
|
||||
case IntelHexRecord.END_OF_FILE_RECORD_TYPE:
|
||||
// if hit EOF record, everything after goes into an OTHER space
|
||||
// TODO maybe this should go into the data space?
|
||||
space = AddressSpace.OTHER_SPACE;
|
||||
base = space.getAddress(0);
|
||||
// nothing to do, we're at the end (or should we ensure further parses fail?)
|
||||
// log(line, "end of file");
|
||||
break;
|
||||
@ -180,7 +184,6 @@ class IntelHexMemImage {
|
||||
MessageLog log = new MessageLog();
|
||||
//this code is required to allow hex lines to not appear
|
||||
//in address order...
|
||||
int count = 0;
|
||||
AddressSetPartitioner partitioner = new AddressSetPartitioner(set, rangeMap, partitions);
|
||||
HashMap<AddressRange, byte[]> myRangeMap =
|
||||
new HashMap<AddressRange, byte[]>(partitioner.getPartionedRangeMap());
|
||||
@ -203,14 +206,14 @@ class IntelHexMemImage {
|
||||
System.arraycopy(rangeBytes, 0, data, pos, rangeBytes.length);
|
||||
for (int jj = 0; jj < rangeBytes.length; ++jj) {
|
||||
if (filled[pos + jj]) {
|
||||
System.err.println("OVERWRITE!");
|
||||
Msg.error(this, "Hex format Overwrite of bytes at " + range.getMinAddress().add(pos+jj));
|
||||
}
|
||||
filled[pos + jj] = true;
|
||||
}
|
||||
myRangeMap.remove(range);
|
||||
}
|
||||
|
||||
String name = blockName == null ? base.getAddressSpace().getName() : blockName;
|
||||
String name = blockName == null ? blockRange.getMinAddress().getAddressSpace().getName() : blockName;
|
||||
MemoryBlockUtils.createInitializedBlock(program, isOverlay, name,
|
||||
blockRange.getMinAddress(), new ByteArrayInputStream(data), data.length,
|
||||
"Generated by " + creator, progFile, true, !isOverlay, !isOverlay, log, monitor);
|
||||
|
@ -20,6 +20,12 @@
|
||||
<range space="mem" first="0x60" last="0xff"/>
|
||||
</volatile>
|
||||
|
||||
<context_data>
|
||||
<tracked_set space="code">
|
||||
<set name="R1" val="0"/>
|
||||
</tracked_set>
|
||||
</context_data>
|
||||
|
||||
<default_symbols>
|
||||
|
||||
<symbol name="RESET" address="code:0x0000" entry="true"/>
|
||||
@ -408,7 +414,8 @@
|
||||
<default_memory_blocks>
|
||||
<memory_block name="regalias" start_address="mem:0x00" length="0x20" initialized="false"/>
|
||||
<memory_block name="iospace" start_address="mem:0x20" length="0x1e0" initialized="false"/>
|
||||
<memory_block name="data" start_address="mem:0x200" length="0x2000" initialized="false"/>
|
||||
<memory_block name="sram" start_address="mem:0x200" length="0x4000" initialized="false"/>
|
||||
<memory_block name="codebyte" start_address="codebyte:0x0" length="0x40000" byte_mapped_address="code:0x0"/>
|
||||
</default_memory_blocks>
|
||||
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
endian="little"
|
||||
size="16"
|
||||
variant="default"
|
||||
version="1.2"
|
||||
version="1.3"
|
||||
slafile="avr8.sla"
|
||||
processorspec="avr8.pspec"
|
||||
manualindexfile="../manuals/AVR8.idx"
|
||||
@ -23,7 +23,7 @@
|
||||
endian="little"
|
||||
size="16"
|
||||
variant="extended"
|
||||
version="1.3"
|
||||
version="1.4"
|
||||
slafile="avr8e.sla"
|
||||
processorspec="avr8.pspec"
|
||||
manualindexfile="../manuals/AVR8.idx"
|
||||
@ -38,7 +38,7 @@
|
||||
endian="little"
|
||||
size="24"
|
||||
variant="atmega256"
|
||||
version="1.3"
|
||||
version="1.4"
|
||||
slafile="avr8eind.sla"
|
||||
processorspec="atmega256.pspec"
|
||||
manualindexfile="../manuals/AVR8.idx"
|
||||
@ -53,7 +53,7 @@
|
||||
endian="little"
|
||||
size="24"
|
||||
variant="Xmega"
|
||||
version="1.3"
|
||||
version="1.4"
|
||||
slafile="avr8xmega.sla"
|
||||
processorspec="avr8xmega.pspec"
|
||||
id="avr8:LE:24:xmega">
|
||||
|
@ -24,6 +24,12 @@
|
||||
<range space="mem" first="0x60" last="0xff"/>
|
||||
</volatile>
|
||||
|
||||
<context_data>
|
||||
<tracked_set space="code">
|
||||
<set name="R1" val="0"/>
|
||||
</tracked_set>
|
||||
</context_data>
|
||||
|
||||
<default_symbols>
|
||||
|
||||
<symbol name="Reset" address="code:0x0" entry="true"/>
|
||||
@ -162,6 +168,7 @@
|
||||
<memory_block name="regalias" start_address="mem:0x00" length="0x20" initialized="false"/>
|
||||
<memory_block name="iospace" start_address="mem:0x20" length="0xd0" initialized="false"/>
|
||||
<memory_block name="mem" start_address="mem:0x100" length="0xf00" initialized="false"/>
|
||||
<memory_block name="codebyte" start_address="codebyte:0x0" length="0x10000" byte_mapped_address="code:0x0"/>
|
||||
</default_memory_blocks>
|
||||
|
||||
|
||||
|
@ -31,10 +31,14 @@ define alignment=2;
|
||||
# decompiler. None-the-less, other than when loading the binary into
|
||||
# Ghidra, it's still preferable to see the name of IO locations used,
|
||||
# rather than code addresses, so leave mem space as the default.
|
||||
|
||||
define space code type=ram_space size=$(PCBYTESIZE) wordsize=2 default;
|
||||
define space register type=register_space size=2;
|
||||
define space mem type=ram_space size=2 wordsize=1;
|
||||
|
||||
# this is a byte address space that should be overlayed on top of the code space
|
||||
define space codebyte type=ram_space size=$(PCBYTESIZE) wordsize=1;
|
||||
|
||||
# Using decimal rather than hex to match specs
|
||||
# General registers start at 0 in the iospace for earlier avr8 processors
|
||||
# In the Xmega line, they are not accessible in mem, and are in a register space
|
||||
@ -53,8 +57,13 @@ define $(REGISTER_SPACE) offset=0 size=2 [
|
||||
X Y Z
|
||||
];
|
||||
|
||||
define $(REGISTER_SPACE) offset=0x10 size=4 [
|
||||
R19R18R17R16 R23R22R21R20
|
||||
define $(REGISTER_SPACE) offset=18 size=8 [
|
||||
R25R24R23R22R21R20R19R18
|
||||
];
|
||||
|
||||
define $(REGISTER_SPACE) offset=0 size=8 [
|
||||
R7R6R5R4R3R2R1R0
|
||||
R15R14R13R12R11R10R9R8
|
||||
];
|
||||
|
||||
# Technically, the stack pointer is in the i/o space so should be addressable with the
|
||||
@ -143,6 +152,7 @@ define token opword (16)
|
||||
ophi2 = (14,15)
|
||||
opbit13 = (13,13)
|
||||
opbit12 = (12,12)
|
||||
opbit10 = (10,10)
|
||||
opbit9 = ( 9, 9)
|
||||
opbit8 = ( 8, 8)
|
||||
opbit7 = ( 7, 7)
|
||||
@ -162,6 +172,7 @@ define token opword (16)
|
||||
op4to6 = ( 4, 6)
|
||||
op4to6_flag = ( 4, 6)
|
||||
op6to7 = ( 6, 7)
|
||||
op8to10 = ( 8,10)
|
||||
op9to10 = ( 9,10)
|
||||
op10to11 = (10,11)
|
||||
RdHi = ( 4, 7)
|
||||
@ -325,45 +336,28 @@ op1RrPair: op1RrPairLow is op1RrPairSel=0 & op1RrPairLow { tmp:2 = op1RrPairLow
|
||||
# manipulates the stack pointer it's important to get this correct.
|
||||
@if PCBYTESIZE == "2"
|
||||
macro pushPC(val) {
|
||||
local valb:1 = val(0);
|
||||
*[mem]:1 SP = valb;
|
||||
SP = SP - 1;
|
||||
valb = val(1);
|
||||
*[mem]:1 SP = valb;
|
||||
SP = SP - 1;
|
||||
*[mem]:2 SP = val;
|
||||
SP = SP - 1;
|
||||
}
|
||||
|
||||
macro popPC(val) {
|
||||
local valb:1 = 0;
|
||||
SP = SP + 1;
|
||||
val = *[mem]:2 SP;
|
||||
SP = SP + 1;
|
||||
val = *[mem]:1 SP;
|
||||
SP = SP + 1;
|
||||
valb = *[mem]:1 SP;
|
||||
val = (val << 8) + zext(valb);
|
||||
}
|
||||
|
||||
@else # PCBYTESIZE == 3
|
||||
macro pushPC(val) {
|
||||
local valb:1 = val(0);
|
||||
*[mem]:1 SP = valb;
|
||||
SP = SP - 1;
|
||||
valb = val(1);
|
||||
*[mem]:1 SP = valb;
|
||||
SP = SP - 1;
|
||||
valb = val(2);
|
||||
*[mem]:1 SP = valb;
|
||||
SP = SP - 2;
|
||||
*[mem]:3 SP = val;
|
||||
SP = SP - 1;
|
||||
}
|
||||
|
||||
macro popPC(val) {
|
||||
SP = SP + 1;
|
||||
val = *[mem]:1 SP;
|
||||
SP = SP + 1;
|
||||
local valb = *[mem]:1 SP;
|
||||
val = (val << 8) + zext(valb);
|
||||
SP = SP + 1;
|
||||
valb = *[mem]:1 SP;
|
||||
val = (val << 8) + zext(valb);
|
||||
SP = SP + 1;
|
||||
val = *[mem]:3 SP;
|
||||
SP = SP + 2;
|
||||
}
|
||||
|
||||
@endif
|
||||
@ -499,7 +493,7 @@ K6: val is oplow4 & op6to7 [ val = (op6to7 << 4) | oplow4; ] { tmp:1 = val; e
|
||||
|
||||
# K7 is used by lds
|
||||
K7addr: val is oplow4 & op9to10 & opbit8 [ val = ((1 ^ opbit8) << 7) | (opbit8 << 6) | (op9to10 << 4) | oplow4; ] {
|
||||
tmp:1 = val; export tmp;
|
||||
export *[mem]:1 val;
|
||||
}
|
||||
|
||||
# Join against various spaces for dataspace...
|
||||
@ -740,10 +734,10 @@ define pcodeop decrypt;
|
||||
:des op4to7 is phase=1 & ophi8=0x94 & oplow4=0xb & op4to7 {
|
||||
val:1 = op4to7;
|
||||
if (Hflg) goto <enc>;
|
||||
decrypt(val);
|
||||
R15R14R13R12R11R10R9R8 = decrypt(R7R6R5R4R3R2R1R0, val);
|
||||
goto inst_next;
|
||||
<enc>
|
||||
encrypt(val);
|
||||
R15R14R13R12R11R10R9R8 = encrypt(R7R6R5R4R3R2R1R0, val);
|
||||
}
|
||||
|
||||
@if HASEIND == "1"
|
||||
@ -764,23 +758,21 @@ define pcodeop decrypt;
|
||||
@if PCBYTESIZE == "3"
|
||||
:elpm is phase=1 & ophi16=0x95d8 {
|
||||
ptr:3 = zext(Z) | (zext(RAMPZ) << 16);
|
||||
tmp:2 = *[code]:2 (ptr >> 1);
|
||||
val:2 = (tmp >> (8 * (Z & 0x1)));
|
||||
R0 = val:1;
|
||||
local falseRead:1 = *[code]:2 (ptr >> 1);
|
||||
R0 = *[codebyte]:1 ptr;
|
||||
}
|
||||
|
||||
:elpm RdFull, Z is phase=1 & ophi7=0x48 & oplow4=0x6 & RdFull & Z {
|
||||
ptr:3 = zext(Z) | (zext(RAMPZ) << 16);
|
||||
tmp:2 = *[code]:2 (ptr >> 1);
|
||||
val:2 = (tmp >> (8 * (Z & 0x1)));
|
||||
RdFull = val:1;
|
||||
local falseRead:1 = *[code]:1 (ptr >> 1);
|
||||
RdFull = *[codebyte]:1 ptr;
|
||||
}
|
||||
|
||||
ElpmPlus: Z^"+" is Z {}
|
||||
:elpm RdFull, ElpmPlus is phase=1 & ophi7=0x48 & oplow4=0x7 & RdFull & ElpmPlus {
|
||||
ptr:3 = zext(Z) | (zext(RAMPZ) << 16);
|
||||
tmp:2 = *[code]:2 (ptr >> 1);
|
||||
val:2 = (tmp >> (8 * (Z & 0x1)));
|
||||
RdFull = val:1;
|
||||
local falseRead:1 = *[code]:1 (ptr >> 1);
|
||||
RdFull = *[codebyte]:1 ptr;
|
||||
ptr = ptr + 1;
|
||||
Z = ptr:2;
|
||||
RAMPZ = ptr[16,8];
|
||||
@ -862,6 +854,7 @@ ElpmPlus: Z^"+" is Z {}
|
||||
RdFull = *[mem]:1 tmp;
|
||||
}
|
||||
# ld Rd,Y; ld Rd,Z
|
||||
# Special case of ldd +q below - will conflict with -i sleigh compile
|
||||
:ld RdFull,RstPtr is phase=1 & ophi7=0x40 & oplow3=0x0 & RdFull & RstPtr {
|
||||
tmp:2 = RstPtr;
|
||||
RdFull = *[mem]:1 tmp;
|
||||
@ -883,9 +876,9 @@ LdPredec: "-"^RstPtr is RstPtr { RstPtr = RstPtr - 0x01; export RstPtr; }
|
||||
|
||||
# ldd Rd,Y+q
|
||||
# ldd Rd,Z+q
|
||||
LddYq: Rstq^"+"^q6 is Rstq & q6 { local ptr = Rstq + zext(q6); export ptr; }
|
||||
:ldd RdFull,LddYq is phase=1 & ophi2=0x2 & opbit12=0 & opbit9=0 & LddYq & RdFull {
|
||||
RdFull = *[mem]:1 LddYq;
|
||||
LddYZq: Rstq^"+"^q6 is phase=1 & Rstq & q6 { local ptr = Rstq + zext(q6); export ptr; }
|
||||
:ldd RdFull,LddYZq is phase=1 & ophi2=0x2 & opbit12=0 & opbit9=0 & opbit3 & LddYZq & RdFull {
|
||||
RdFull = *[mem]:1 LddYZq;
|
||||
}
|
||||
|
||||
# Rd,K
|
||||
@ -914,32 +907,28 @@ LddYq: Rstq^"+"^q6 is Rstq & q6 { local ptr = Rstq + zext(q6); export ptr; }
|
||||
@endif
|
||||
# lds Rd,k Seem to get some problems here... but 16-bit instruction isn't available on all atmega64.
|
||||
# Furthermore, it will sometimes conflict with ldd Z+q for q=0x2_
|
||||
#:lds RdHi,A7Ioaddr is ophi5=0x14 & RdHi & A7Ioaddr {
|
||||
# todo(); # Not currently implemented
|
||||
# RdHi = A7Ioaddr;
|
||||
#}
|
||||
# TODO: lpm semantic behavior needs verification !
|
||||
:lds RdHi,K7addr is phase=1 & ophi5=0x14 & RdHi & K7addr {
|
||||
RdHi = K7addr;
|
||||
}
|
||||
|
||||
# lpm R0
|
||||
:lpm R0 is phase=1 & ophi16=0x95c8 & R0 {
|
||||
ptr:$(PCBYTESIZE) = zext(Z);
|
||||
tmp:$(PCBYTESIZE) = *[code]:$(PCBYTESIZE) (ptr >> 1);
|
||||
val:$(PCBYTESIZE) = (tmp >> (8 * (Z & 0x1)));
|
||||
R0 = val:1;
|
||||
local falseRead:1 = *[code]:1 (ptr >> 1);
|
||||
R0 = *[codebyte]:$(PCBYTESIZE) ptr;
|
||||
}
|
||||
# lpm Rd,Z
|
||||
:lpm RdFull,Z is phase=1 & ophi7=0x48 & op1to3=0x2 & RdFull & Z & opbit0=0 {
|
||||
ptr:$(PCBYTESIZE) = zext(Z);
|
||||
tmp:$(PCBYTESIZE) = *[code]:$(PCBYTESIZE) (ptr >> 1);
|
||||
val:$(PCBYTESIZE) = (tmp >> (8 * (Z & 0x1)));
|
||||
RdFull = val:1;
|
||||
local falseRead:1 = *[code]:1 (ptr >> 1);
|
||||
RdFull = *[codebyte]:$(PCBYTESIZE) ptr;
|
||||
}
|
||||
# lpm Rd,Z+
|
||||
LpmPlus: Z^"+" is Z {}
|
||||
:lpm RdFull,LpmPlus is phase=1 & ophi7=0x48 & op1to3=0x2 & RdFull & LpmPlus & opbit0=1 {
|
||||
ptr:$(PCBYTESIZE) = zext(Z);
|
||||
tmp:$(PCBYTESIZE) = *[code]:$(PCBYTESIZE) (ptr >> 1);
|
||||
val:$(PCBYTESIZE) = (tmp >> (8 * (Z & 0x1)));
|
||||
RdFull = val:1;
|
||||
local falseRead:1 = *[code]:1 (ptr >> 1);
|
||||
RdFull = *[codebyte]:$(PCBYTESIZE) ptr;
|
||||
Z = Z + 1;
|
||||
}
|
||||
# lsl - just an assembly mnemonic for add
|
||||
@ -1118,14 +1107,16 @@ define pcodeop store_program_mem; # make this stand out.
|
||||
|
||||
:spm Z is phase=1 & ophi16=0x95e8 & Z {
|
||||
ptr:$(PCBYTESIZE) = zext(Z) << 1;
|
||||
*[code]:$(PCBYTESIZE) ptr = R1R0;
|
||||
local falseWrite:1 = *[code]:1 (ptr >> 1);
|
||||
*[codebyte]:$(PCBYTESIZE) ptr = R1R0;
|
||||
store_program_mem();
|
||||
}
|
||||
|
||||
SpmPlus: Z^"+" is Z {}
|
||||
:spm SpmPlus is phase=1 & ophi16=0x95f8 & SpmPlus {
|
||||
ptr:$(PCBYTESIZE) = zext(Z) << 1;
|
||||
*[code]:$(PCBYTESIZE) ptr = R1R0;
|
||||
local falseWrite:1 = *[code]:1 (ptr >> 1);
|
||||
*[codebyte]:$(PCBYTESIZE) ptr = R1R0;
|
||||
Z = Z + 1;
|
||||
store_program_mem();
|
||||
}
|
||||
@ -1154,11 +1145,11 @@ StPredec: "-"^RstPtr is RstPtr { RstPtr = RstPtr - 0x01; export RstPtr; }
|
||||
*[mem]:1 tmp = RdFull;
|
||||
}
|
||||
|
||||
# std Rd,Y+q; std Rd,Z+q
|
||||
StdYq: Rstq^"+"^q6 is Rstq & q6 { local ptr = Rstq + zext(q6); export ptr; }
|
||||
|
||||
:std StdYq, RdFull is phase=1 & ophi2=0x2 & opbit12=0 & opbit9=1 & RdFull & StdYq {
|
||||
*[mem]:1 StdYq = RdFull;
|
||||
# std Rd,Y+q
|
||||
# std Rd,Z+q
|
||||
StdYZq: Rstq^"+"^q6 is Rstq & q6 { local ptr = Rstq + zext(q6); export ptr; }
|
||||
:std StdYZq, RdFull is phase=1 & ophi2=0x2 & opbit12=0 & opbit9=1 & RdFull & opbit3 & StdYZq {
|
||||
*[mem]:1 StdYZq = RdFull;
|
||||
}
|
||||
|
||||
:sts next16memPtrVal1,RdFull is phase=1 & ophi7=0x49 & oplow4=0 & RdFull; next16memPtrVal1 {
|
||||
@ -1173,7 +1164,9 @@ StdYq: Rstq^"+"^q6 is Rstq & q6 { local ptr = Rstq + zext(q6); export ptr; }
|
||||
|
||||
@endif
|
||||
# see manual for computation of address for 16-bit STS
|
||||
:sts RdHi is phase=1 & ophi5=0x15 & RdHi { todo(); }
|
||||
:sts K7addr, RdHi is phase=1 & ophi5=0x15 & RdHi & K7addr {
|
||||
K7addr = RdHi;
|
||||
}
|
||||
:sub RdFull,RrFull is phase=1 & ophi6=0x6 & RdFull & RrFull {
|
||||
doSubtract(RdFull,RrFull,RdFull);
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
<global>
|
||||
<range space="code"/>
|
||||
<range space="mem"/>
|
||||
<range space="codebyte"/>
|
||||
</global>
|
||||
|
||||
<stackpointer register="SP" space="mem" growth="negative"/>
|
||||
@ -39,25 +40,18 @@
|
||||
<default_proto>
|
||||
<prototype name="__stdcall" extrapop="3" stackshift="3" strategy="register">
|
||||
<input>
|
||||
<!-- Stack used for vararg parameters only -->
|
||||
<pentry minsize="1" maxsize="2">
|
||||
<pentry minsize="1" maxsize="2">
|
||||
<register name="W"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="2">
|
||||
<register name="R23R22"/>
|
||||
</pentry>
|
||||
<pentry minsize="3" maxsize="4">
|
||||
<addr space="join" piece1="W" piece2="R23R22"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="2">
|
||||
<register name="R21R20"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="2">
|
||||
<register name="R19R18"/>
|
||||
</pentry>
|
||||
<pentry minsize="3" maxsize="4">
|
||||
<addr space="join" piece1="R21R20" piece2="R19R18"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="2">
|
||||
<register name="R17R16"/>
|
||||
</pentry>
|
||||
@ -73,6 +67,14 @@
|
||||
<pentry minsize="1" maxsize="2">
|
||||
<register name="R9R8"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="2">
|
||||
<register name="Z"/>
|
||||
</pentry>
|
||||
<!-- set to 20 on purpose, so that large values don't get assigned to stack -->
|
||||
<!-- They get allocated across register pairs, but layout algorithm too simple -->
|
||||
<pentry minsize="24" maxsize="500" align="1">
|
||||
<addr offset="20" space="stack"/>
|
||||
</pentry>
|
||||
</input>
|
||||
<output>
|
||||
<pentry minsize="1" maxsize="2">
|
||||
@ -81,6 +83,9 @@
|
||||
<pentry minsize="3" maxsize="4">
|
||||
<addr space="join" piece1="W" piece2="R23R22"/>
|
||||
</pentry>
|
||||
<pentry minsize="5" maxsize="8">
|
||||
<addr space="join" piece1="W" piece2="R23R22" piece3="R21R20" piece4="R19R18"/>
|
||||
</pentry>
|
||||
</output>
|
||||
<unaffected>
|
||||
<register name="SP"/>
|
||||
@ -101,8 +106,23 @@
|
||||
<register name="R15"/>
|
||||
<register name="R16"/>
|
||||
<register name="R17"/>
|
||||
<register name="Y"/>
|
||||
<register name="Y"/>
|
||||
</unaffected>
|
||||
<killedbycall>
|
||||
<register name="R0"/>
|
||||
<register name="R18"/>
|
||||
<register name="R19"/>
|
||||
<register name="R20"/>
|
||||
<register name="R21"/>
|
||||
<register name="R22"/>
|
||||
<register name="R23"/>
|
||||
<register name="Wlo"/>
|
||||
<register name="Whi"/>
|
||||
<register name="Xlo"/>
|
||||
<register name="Xhi"/>
|
||||
<register name="Zlo"/>
|
||||
<register name="Zhi"/>
|
||||
</killedbycall>
|
||||
</prototype>
|
||||
</default_proto>
|
||||
|
||||
|
@ -31,13 +31,14 @@
|
||||
|
||||
<global>
|
||||
<range space="code"/>
|
||||
<range space="codebyte"/>
|
||||
<range space="mem"/>
|
||||
</global>
|
||||
|
||||
<stackpointer register="SP" space="mem" growth="negative"/>
|
||||
|
||||
<default_proto>
|
||||
<prototype name="__stdcall" extrapop="2" stackshift="2" strategy="register">
|
||||
<prototype name="__stdcall" extrapop="" stackshift="2" strategy="register">
|
||||
<input>
|
||||
<pentry minsize="1" maxsize="2">
|
||||
<register name="W"/>
|
||||
@ -45,18 +46,12 @@
|
||||
<pentry minsize="1" maxsize="2">
|
||||
<register name="R23R22"/>
|
||||
</pentry>
|
||||
<pentry minsize="3" maxsize="4">
|
||||
<addr space="join" piece1="W" piece2="R23R22"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="2">
|
||||
<register name="R21R20"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="2">
|
||||
<register name="R19R18"/>
|
||||
</pentry>
|
||||
<pentry minsize="3" maxsize="4">
|
||||
<addr space="join" piece1="R21R20" piece2="R19R18"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="2">
|
||||
<register name="R17R16"/>
|
||||
</pentry>
|
||||
@ -72,6 +67,14 @@
|
||||
<pentry minsize="1" maxsize="2">
|
||||
<register name="R9R8"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="2">
|
||||
<register name="Z"/>
|
||||
</pentry>
|
||||
<!-- set to 20 on purpose, so that large values don't get assigned to stack -->
|
||||
<!-- They get allocated across register pairs, but layout algorithm too simple -->
|
||||
<pentry minsize="24" maxsize="500" align="1">
|
||||
<addr offset="20" space="stack"/>
|
||||
</pentry>
|
||||
</input>
|
||||
<output>
|
||||
<pentry minsize="1" maxsize="2">
|
||||
@ -80,6 +83,9 @@
|
||||
<pentry minsize="3" maxsize="4">
|
||||
<addr space="join" piece1="W" piece2="R23R22"/>
|
||||
</pentry>
|
||||
<pentry minsize="5" maxsize="8">
|
||||
<addr space="join" piece1="W" piece2="R23R22" piece3="R21R20" piece4="R19R18"/>
|
||||
</pentry>
|
||||
</output>
|
||||
<unaffected>
|
||||
<register name="SP"/>
|
||||
@ -102,15 +108,30 @@
|
||||
<register name="R17"/>
|
||||
<register name="Y"/>
|
||||
</unaffected>
|
||||
<killedbycall>
|
||||
<register name="R0"/>
|
||||
<register name="R18"/>
|
||||
<register name="R19"/>
|
||||
<register name="R20"/>
|
||||
<register name="R21"/>
|
||||
<register name="R22"/>
|
||||
<register name="R23"/>
|
||||
<register name="Wlo"/>
|
||||
<register name="Whi"/>
|
||||
<register name="Xlo"/>
|
||||
<register name="Xhi"/>
|
||||
<register name="Zlo"/>
|
||||
<register name="Zhi"/>
|
||||
</killedbycall>
|
||||
</prototype>
|
||||
</default_proto>
|
||||
|
||||
<prototype name="__stackcall" extrapop="3" stackshift="3" strategy="register">
|
||||
<input>
|
||||
<pentry minsize="1" maxsize="500" align="1">
|
||||
<addr offset="1" space="stack"/>
|
||||
</pentry>
|
||||
</input>
|
||||
<input>
|
||||
<pentry minsize="1" maxsize="500" align="1">
|
||||
<addr offset="3" space="stack"/>
|
||||
</pentry>
|
||||
</input>
|
||||
<output>
|
||||
<pentry minsize="1" maxsize="2">
|
||||
<register name="W"/>
|
||||
|
@ -5,6 +5,7 @@
|
||||
<compiler_spec>
|
||||
<global>
|
||||
<range space="code"/>
|
||||
<range space="codebyte"/>
|
||||
<range space="mem" first="40" last="0xffff"/>
|
||||
<!-- <range space="iospace"/> -->
|
||||
</global>
|
||||
@ -15,18 +16,18 @@
|
||||
<prototype name="__stdcall" extrapop="0" stackshift="0" strategy="register">
|
||||
<input>
|
||||
<pentry minsize="1" maxsize="4">
|
||||
<register name="R19R18R17R16"/>
|
||||
<addr space="join" piece1="R19R18" piece2="R17R16"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="2">
|
||||
<register name="R23R22R21R20"/>
|
||||
<pentry minsize="1" maxsize="4">
|
||||
<addr space="join" piece1="R23R22" piece2="R21R20"/>
|
||||
</pentry>
|
||||
<pentry minsize="1" maxsize="500" align="1">
|
||||
<addr offset="0" space="stack"/>
|
||||
</pentry>
|
||||
</input>
|
||||
<output>
|
||||
<pentry minsize="1" maxsize="2">
|
||||
<register name="R19R18R17R16"/>
|
||||
<pentry minsize="1" maxsize="4">
|
||||
<addr space="join" piece1="R19R18" piece2="R17R16"/>
|
||||
</pentry>
|
||||
</output>
|
||||
<unaffected>
|
||||
|
@ -7,6 +7,7 @@
|
||||
<compiler_spec>
|
||||
<global>
|
||||
<range space="code"/>
|
||||
<range space="codebyte"/>
|
||||
<range space="mem" first="40" last="0xffff"/>
|
||||
</global>
|
||||
<!-- SP is used for the code stack. Y is used for the data stack -->
|
||||
|
@ -20,6 +20,12 @@
|
||||
<range space="mem" first="0x40" last="0xfff"/>
|
||||
</volatile>
|
||||
|
||||
<context_data>
|
||||
<tracked_set space="code">
|
||||
<set name="R1" val="0"/>
|
||||
</tracked_set>
|
||||
</context_data>
|
||||
|
||||
<default_symbols>
|
||||
|
||||
|
||||
@ -1476,6 +1482,8 @@
|
||||
<default_memory_blocks>
|
||||
<memory_block name="iospace" start_address="mem:0x00" length="0x1000" initialized="false"/>
|
||||
<memory_block name="eeprom" start_address="mem:0x1000" length="0x1000" initialized="false"/>
|
||||
<memory_block name="sram" start_address="mem:0x2000" length="0x4000" initialized="false"/>
|
||||
<memory_block name="codebyte" start_address="codebyte:0x0" length="0x40000" byte_mapped_address="code:0x0"/>
|
||||
</default_memory_blocks>
|
||||
|
||||
|
||||
|
@ -0,0 +1,369 @@
|
||||
/* ###
|
||||
* 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 ghidra.app.util.bin.format.elf.relocation;
|
||||
|
||||
import ghidra.app.util.bin.format.elf.AVR8_ElfRelocationConstants;
|
||||
import ghidra.app.util.bin.format.elf.ElfConstants;
|
||||
import ghidra.app.util.bin.format.elf.ElfHeader;
|
||||
import ghidra.app.util.bin.format.elf.ElfRelocation;
|
||||
import ghidra.app.util.bin.format.elf.ElfSymbol;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.exception.NotFoundException;
|
||||
|
||||
public class AVR8_ElfRelocationHandler extends ElfRelocationHandler {
|
||||
|
||||
@Override
|
||||
public boolean canRelocate(ElfHeader elf) {
|
||||
return elf.e_machine() == ElfConstants.EM_AVR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relocate(ElfRelocationContext elfRelocationContext, ElfRelocation relocation,
|
||||
Address relocationAddress) throws MemoryAccessException, NotFoundException {
|
||||
|
||||
Program program = elfRelocationContext.getProgram();
|
||||
|
||||
Memory memory = program.getMemory();
|
||||
|
||||
int type = relocation.getType();
|
||||
int symbolIndex = relocation.getSymbolIndex();
|
||||
|
||||
long addend = relocation.getAddend(); // will be 0 for REL case
|
||||
|
||||
ElfHeader elf = elfRelocationContext.getElfHeader();
|
||||
if ((symbolIndex == 0) && (elf.e_machine() == ElfConstants.EM_AVR)) {
|
||||
// System.out.println("ZERO_SYMBOL_TYPE = " + type + ", Offset = " + offset + ",
|
||||
// Addend = " + addend);
|
||||
}
|
||||
else if (symbolIndex == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// WARNING: offset is in bytes
|
||||
// be careful, word address potentially with byte indexes
|
||||
long offset = relocationAddress.getOffset();
|
||||
|
||||
ElfSymbol sym = elfRelocationContext.getSymbol(symbolIndex);
|
||||
// WARNING: symbolValue here is not in bytes.
|
||||
// it is an addressable word offset for the symbols address space
|
||||
long symbolValue = elfRelocationContext.getSymbolValue(sym);
|
||||
String symbolName = sym.getNameAsString();
|
||||
|
||||
int oldValue = memory.getShort(relocationAddress);
|
||||
|
||||
if (elf.e_machine() != ElfConstants.EM_AVR) {
|
||||
return;
|
||||
}
|
||||
|
||||
int newValue = 0;
|
||||
|
||||
switch (type) {
|
||||
case AVR8_ElfRelocationConstants.R_AVR_NONE:
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_32:
|
||||
newValue = (((int) symbolValue + (int) addend) & 0xffffffff);
|
||||
memory.setInt(relocationAddress, newValue);
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_7_PCREL:
|
||||
newValue = (int) ((symbolValue * 2 + (int) addend - offset));
|
||||
newValue -= 2; // branch PC is offset+2
|
||||
|
||||
if ((newValue & 1) == 1) {
|
||||
markAsError(program, relocationAddress, type, symbolName,
|
||||
"relocation out of range", elfRelocationContext.getLog());
|
||||
return;
|
||||
}
|
||||
if (newValue > ((1 << 7) - 1) || (newValue < -(1 << 7))) {
|
||||
markAsError(program, relocationAddress, type, symbolName, "relocation overflow",
|
||||
elfRelocationContext.getLog());
|
||||
return;
|
||||
}
|
||||
newValue = (oldValue & 0xfc07) | (((newValue >> 1) << 3) & 0x3f8);
|
||||
memory.setShort(relocationAddress, (short) newValue);
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_13_PCREL:
|
||||
newValue = (int) ((symbolValue * 2 + (int) addend - offset));
|
||||
newValue -= 2; // branch PC is offset+2
|
||||
|
||||
if ((newValue & 1) == 1) {
|
||||
markAsError(program, relocationAddress, type, symbolName,
|
||||
"relocation out of range", elfRelocationContext.getLog());
|
||||
return;
|
||||
}
|
||||
newValue >>= 1;
|
||||
|
||||
if (newValue < -2048 || newValue > 2047) {
|
||||
markAsWarning(program, relocationAddress, symbolName, symbolName, symbolIndex,
|
||||
"possible relocation error", elfRelocationContext.getLog());
|
||||
}
|
||||
|
||||
newValue = (oldValue & 0xf000) | (newValue & 0xfff);
|
||||
memory.setShort(relocationAddress, (short) newValue);
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_16:
|
||||
newValue = ((int) symbolValue + (int) addend);
|
||||
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_16_PM:
|
||||
newValue = (((int) symbolValue * 2 + (int) addend));
|
||||
newValue >>= 1;
|
||||
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_LO8_LDI:
|
||||
newValue = (((int) symbolValue + (int) addend));
|
||||
newValue = (oldValue & 0xf0f0) | (newValue & 0xf) | ((newValue << 4) & 0xf00);
|
||||
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_HI8_LDI:
|
||||
newValue = (((int) symbolValue + (int) addend));
|
||||
newValue = (newValue >> 8) & 0xff;
|
||||
newValue = (oldValue & 0xf0f0) | (newValue & 0xf) | ((newValue << 4) & 0xf00);
|
||||
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_HH8_LDI:
|
||||
newValue = (((int) symbolValue + (int) addend));
|
||||
newValue = (newValue >> 16) & 0xff;
|
||||
newValue = (oldValue & 0xf0f0) | (newValue & 0xf) | ((newValue << 4) & 0xf00);
|
||||
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_LO8_LDI_NEG:
|
||||
newValue = (((int) symbolValue + (int) addend));
|
||||
newValue = -newValue;
|
||||
newValue = (oldValue & 0xf0f0) | (newValue & 0xf) | ((newValue << 4) & 0xf00);
|
||||
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_HI8_LDI_NEG:
|
||||
newValue = (((int) symbolValue + (int) addend));
|
||||
newValue = -newValue;
|
||||
newValue = (newValue >> 8) & 0xff;
|
||||
newValue = (oldValue & 0xf0f0) | (newValue & 0xf) | ((newValue << 4) & 0xf00);
|
||||
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_HH8_LDI_NEG:
|
||||
newValue = (((int) symbolValue + (int) addend));
|
||||
newValue = -newValue;
|
||||
newValue = (newValue >> 16) & 0xff;
|
||||
newValue = (oldValue & 0xf0f0) | (newValue & 0xf) | ((newValue << 4) & 0xf00);
|
||||
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_LO8_LDI_PM:
|
||||
newValue = (((int) symbolValue * 2 + (int) addend));
|
||||
if ((newValue & 1) == 1) {
|
||||
markAsError(program, relocationAddress, type, symbolName,
|
||||
"relocation out of range", elfRelocationContext.getLog());
|
||||
return;
|
||||
}
|
||||
newValue >>= 1;
|
||||
newValue = (oldValue & 0xf0f0) | (newValue & 0xf) | ((newValue << 4) & 0xf00);
|
||||
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_HI8_LDI_PM:
|
||||
newValue = (((int) symbolValue * 2 + (int) addend));
|
||||
if ((newValue & 1) == 1) {
|
||||
markAsError(program, relocationAddress, type, symbolName,
|
||||
"relocation out of range", elfRelocationContext.getLog());
|
||||
return;
|
||||
}
|
||||
newValue >>= 1;
|
||||
newValue = (newValue >> 8) & 0xff;
|
||||
newValue = (oldValue & 0xf0f0) | (newValue & 0xf) | ((newValue << 4) & 0xf00);
|
||||
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_HH8_LDI_PM:
|
||||
newValue = (((int) symbolValue * 2 + (int) addend));
|
||||
if ((newValue & 1) == 1) {
|
||||
markAsError(program, relocationAddress, type, symbolName,
|
||||
"relocation out of range", elfRelocationContext.getLog());
|
||||
return;
|
||||
}
|
||||
newValue >>= 1;
|
||||
newValue = (newValue >> 16) & 0xff;
|
||||
newValue = (oldValue & 0xf0f0) | (newValue & 0xf) | ((newValue << 4) & 0xf00);
|
||||
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_LO8_LDI_PM_NEG:
|
||||
newValue = (((int) symbolValue * 2 + (int) addend));
|
||||
newValue = -newValue;
|
||||
if ((newValue & 1) == 1) {
|
||||
markAsError(program, relocationAddress, type, symbolName,
|
||||
"relocation out of range", elfRelocationContext.getLog());
|
||||
return;
|
||||
}
|
||||
newValue >>= 1;
|
||||
newValue = (oldValue & 0xf0f0) | (newValue & 0xf) | ((newValue << 4) & 0xf00);
|
||||
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_HI8_LDI_PM_NEG:
|
||||
newValue = (((int) symbolValue * 2 + (int) addend));
|
||||
newValue = -newValue;
|
||||
if ((newValue & 1) == 1) {
|
||||
markAsError(program, relocationAddress, type, symbolName,
|
||||
"relocation out of range", elfRelocationContext.getLog());
|
||||
return;
|
||||
}
|
||||
newValue >>= 1;
|
||||
newValue = (newValue >> 8) & 0xff;
|
||||
newValue = (oldValue & 0xf0f0) | (newValue & 0xf) | ((newValue << 4) & 0xf00);
|
||||
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_HH8_LDI_PM_NEG:
|
||||
newValue = (((int) symbolValue * 2 + (int) addend));
|
||||
newValue = -newValue;
|
||||
if ((newValue & 1) == 1) {
|
||||
markAsError(program, relocationAddress, type, symbolName,
|
||||
"relocation out of range", elfRelocationContext.getLog());
|
||||
return;
|
||||
}
|
||||
newValue >>= 1;
|
||||
newValue = (newValue >> 16) & 0xff;
|
||||
newValue = (oldValue & 0xf0f0) | (newValue & 0xf) | ((newValue << 4) & 0xf00);
|
||||
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_CALL:
|
||||
newValue = (int) symbolValue * 2 + (int) addend;
|
||||
|
||||
if ((newValue & 1) == 1) {
|
||||
markAsError(program, relocationAddress, type, symbolName,
|
||||
"relocation out of range", elfRelocationContext.getLog());
|
||||
return;
|
||||
}
|
||||
newValue >>= 1;
|
||||
|
||||
int hiValue =
|
||||
oldValue | ((newValue & 0x10000) | ((newValue << 3) & 0x1f00000)) >> 16;
|
||||
memory.setShort(relocationAddress, (short) (hiValue & 0xffff));
|
||||
memory.setShort(relocationAddress.add(2), (short) (newValue & 0xffff));
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_LDI: /* data/eeprom */
|
||||
newValue = (((int) symbolValue + (int) addend));
|
||||
|
||||
if ((newValue & 0xffff) > 255) {
|
||||
markAsError(program, relocationAddress, type, symbolName,
|
||||
"relocation out of range", elfRelocationContext.getLog());
|
||||
}
|
||||
|
||||
newValue = (newValue >> 8) & 0xff;
|
||||
newValue = (oldValue & 0xf0f0) | (newValue & 0xf) | ((newValue << 4) & 0xf00);
|
||||
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_6: /* data/eeprom **/
|
||||
newValue = (((int) symbolValue + (int) addend));
|
||||
|
||||
if (((newValue & 0xffff) > 63) || (newValue < 0)) {
|
||||
markAsError(program, relocationAddress, type, symbolName,
|
||||
"relocation out of range", elfRelocationContext.getLog());
|
||||
}
|
||||
|
||||
newValue = (oldValue & 0xd3f8) | (newValue & 7) | ((newValue & (3 << 3)) << 7) |
|
||||
((newValue & (1 << 5)) << 8);
|
||||
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_6_ADIW:
|
||||
newValue = (((int) symbolValue + (int) addend));
|
||||
|
||||
if (((newValue & 0xffff) > 63) || (newValue < 0)) {
|
||||
markAsError(program, relocationAddress, type, symbolName,
|
||||
"relocation out of range", elfRelocationContext.getLog());
|
||||
}
|
||||
|
||||
newValue = (oldValue & 0xff30) | (newValue & 0xF) | ((newValue & 0x30) << 2);
|
||||
|
||||
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_DIFF8:
|
||||
case AVR8_ElfRelocationConstants.R_AVR_DIFF16:
|
||||
case AVR8_ElfRelocationConstants.R_AVR_DIFF32:
|
||||
// nothing to do
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_LDS_STS_16:
|
||||
newValue = (((int) symbolValue + (int) addend));
|
||||
|
||||
if (((newValue & 0xffff) < 0x40) || (newValue & 0xFFFF) > 0xbf) {
|
||||
markAsError(program, relocationAddress, type, symbolName,
|
||||
"relocation out of range", elfRelocationContext.getLog());
|
||||
}
|
||||
|
||||
newValue = newValue & 0x7f;
|
||||
newValue = (oldValue & 0x0f) | ((newValue & 0x30) << 5) | ((newValue & 0x40) << 2);
|
||||
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_PORT6:
|
||||
newValue = (((int) symbolValue + (int) addend));
|
||||
|
||||
if ((newValue & 0xffff) > 0x3f) {
|
||||
markAsError(program, relocationAddress, type, symbolName,
|
||||
"relocation out of range", elfRelocationContext.getLog());
|
||||
}
|
||||
|
||||
newValue = (oldValue & 0xf9f0) | ((newValue & 0x30) << 5) | (newValue & 0x0f);
|
||||
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_PORT5:
|
||||
newValue = (((int) symbolValue + (int) addend));
|
||||
|
||||
if ((newValue & 0xffff) > 0x1f) {
|
||||
markAsError(program, relocationAddress, type, symbolName,
|
||||
"relocation out of range", elfRelocationContext.getLog());
|
||||
}
|
||||
|
||||
newValue = (oldValue & 0xff07) | ((newValue & 0x1f) << 3);
|
||||
memory.setShort(relocationAddress, (short) (newValue & 0xffff));
|
||||
break;
|
||||
|
||||
case AVR8_ElfRelocationConstants.R_AVR_MS8_LDI:
|
||||
case AVR8_ElfRelocationConstants.R_AVR_MS8_LDI_NEG:
|
||||
case AVR8_ElfRelocationConstants.R_AVR_LO8_LDI_GS:
|
||||
case AVR8_ElfRelocationConstants.R_AVR_HI8_LDI_GS:
|
||||
case AVR8_ElfRelocationConstants.R_AVR_8:
|
||||
case AVR8_ElfRelocationConstants.R_AVR_8_LO8:
|
||||
case AVR8_ElfRelocationConstants.R_AVR_8_HI8:
|
||||
case AVR8_ElfRelocationConstants.R_AVR_8_HLO8:
|
||||
default:
|
||||
markAsUnhandled(program, relocationAddress, type, symbolIndex, symbolName,
|
||||
elfRelocationContext.getLog());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user