diff --git a/README.md b/README.md index 02f336c..2e300ff 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ ``` $ cd ghidra_9.1.X/Ghidra/Processors -$ git clone https://github.com/yath/ghidra-xtensa Xtensa +$ git clone https://github.com/Ebiroll/ghidra-xtensa Xtensa $ cd Xtensa $ make $ @@ -19,9 +19,13 @@ Or download a pre-built release and unzip it to `Ghidra/Processors`. * Probably a lot in instructions I did not yet happen to encouter. Pull requests appreciated. +# More info +* https://github.com/Ebiroll/esp32_flash_loader +* https://medium.com/@olof.astrand/a-story-about-elfs-dwarfs-and-dragons-6de2a1df42ad +* https://medium.com/@olof.astrand/enter-home-dragon-with-ghidra-3ed7ddf75935 + # TODO -* Windowed Register Option * MAC16 Option * Loop Option -* ESP8266/ESP32 image loaders? + diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..c190f1f --- /dev/null +++ b/build.gradle @@ -0,0 +1,10 @@ +apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" +apply from: "$rootProject.projectDir/gradle/javaProject.gradle" +apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle" +apply from: "$rootProject.projectDir/gradle/processorProject.gradle" +apply plugin: 'eclipse' +eclipse.project.name = 'Processors Xtensa' + +dependencies { + compile project(':Base') +} diff --git a/data/languages/xtensa.cspec b/data/languages/xtensa.cspec index f7049a2..7c1b787 100644 --- a/data/languages/xtensa.cspec +++ b/data/languages/xtensa.cspec @@ -30,22 +30,22 @@ - + - + - + - + - + - + @@ -53,16 +53,16 @@ - + - + - + - + @@ -70,6 +70,15 @@ + + + + + + + + + diff --git a/data/languages/xtensa.dwarf b/data/languages/xtensa.dwarf index afe6a2e..1790648 100644 --- a/data/languages/xtensa.dwarf +++ b/data/languages/xtensa.dwarf @@ -2,6 +2,6 @@ - + diff --git a/data/languages/xtensa.sinc b/data/languages/xtensa.sinc index efe9420..0d93bf4 100644 --- a/data/languages/xtensa.sinc +++ b/data/languages/xtensa.sinc @@ -3,10 +3,20 @@ define alignment=1; define space ram type=ram_space size=4 default; define space register type=register_space size=4; +define space special_register type=ram_space size=4; +define space save_register type=ram_space size=4; + +# Address registers (AR). +define save_register offset=0x0000 size=4 [ + sa0 sa1 sa2 sa3 sa4 sa5 sa6 sa7 sa8 sa9 sa10 sa11 sa12 sa13 sa14 sa15 +]; + # Address registers (AR). define register offset=0x0000 size=4 [ a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 + i2 i3 i4 i5 i6 i7 + o2 o3 o4 o5 o6 o7 ]; # Floating Point registers (FR + FCR (control) + FSR (status)). @@ -27,6 +37,33 @@ define register offset=0x1000 size=4 [ pc ]; # Shift amount register. (TODO: other special registers) define register offset=0x2000 size=1 [ sar ]; + +#not all registers are 32Bit but for sake of simplicity they are here +define special_register offset=0 size=4 [ LBEG LEND LCOUNT OSAR BR LITBASE ]; +define special_register offset=48 size=4 [ SCOMPARE1 ]; +define special_register offset=64 size=4 [ ACCLO ACCHI ]; +define special_register offset=128 size=4 [ M0 M1 M2 M3 ]; +define special_register offset=288 size=4 [ WindowBase WindowStart ]; +define special_register offset=332 size=4 [ PTEVADDR ]; +define special_register offset=356 size=4 [ MMID RASID ITLBCFG DTLBCFG ]; +define special_register offset=384 size=4 [ IBREAKENABLE ]; +define special_register offset=388 size=4 [ MEMCTL ]; +define special_register offset=392 size=4 [ CACHEATTR ATOMCTL ]; +define special_register offset=416 size=4 [ DDR ]; +define special_register offset=424 size=4 [ MEPC MEPS MESAVE MESR MECR MEVADDR ]; +define special_register offset=512 size=4 [ IBREAKA0 IBREAKA1 ]; +define special_register offset=576 size=4 [ DBREAKA0 DBREAKA1 ]; +define special_register offset=640 size=4 [ DBREAKC0 DBREAKC1 ]; +define special_register offset=708 size=4 [ EPC1 EPC2 EPC3 EPC4 EPC5 EPC6 EPC7 ]; +define special_register offset=768 size=4 [ DEPC ]; +define special_register offset=776 size=4 [ EPS2 EPS3 EPS4 EPS5 EPS6 EPS7 ]; +define special_register offset=836 size=4 [ EXCSAVE1 EXCSAVE2 EXCSAVE3 EXCSAVE4 EXCSAVE5 EXCSAVE6 EXCSAVE7 ]; +define special_register offset=896 size=4 [ CPENABLE ]; +define special_register offset=900 size=4 [ INTERRUPT INTSET INTCLEAR INTENABLE ];# assuming it's a typo in the manual and INTERRUPT has number 225 +define special_register offset=920 size=4 [ PS VECBASE EXCCAUSE DEBUGCAUSE CCOUNT PRID ICOUNT ICOUNTLEVEL EXCVADDR ]; +define special_register offset=960 size=4 [ CCOMPARE0 CCOMPARE1 CCOMPARE2 ]; +define special_register offset=976 size=4 [ MISC0 MISC1 MISC2 MISC3 ]; + # Regular 24-bit instruction. define token insn(24) # Named opcode/register fields. @@ -67,7 +104,7 @@ define token insn(24) u1_12 = (12,12) u4_8.11 = (8,11) u8_4.11 = (4,11) - # s4_8.11 = (8,11) signed + s4_8.11 = (8,11) signed u2_6.7 = (6,7) u3_5.7 = (5,7) u4_4.7 = (4,7) @@ -94,6 +131,14 @@ define token narrowinsn(16) ; +#define token opbyte (8) +# op0_8 = (0,7) +#; + +#define token opword (16) +# op0_16 = (0,15) +#; + attach variables [ ar as at n_ar n_as n_at ] [ a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 ]; @@ -106,6 +151,9 @@ attach variables [ br bs bt ] [ b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 ]; +attach variables [ u8_8.15 ] [ LBEG LEND LCOUNT OSAR BR LITBASE _ _ _ _ _ _ SCOMPARE1 _ _ _ ACCLO ACCHI _ _ _ _ _ _ _ _ _ _ _ _ _ _ M0 M1 M2 M3 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ WindowBase WindowStart _ _ _ _ _ _ _ _ _ PTEVADDR _ _ _ _ _ MMID RASID ITLBCFG DTLBCFG _ _ _ IBREAKENABLE MEMCTL CACHEATTR ATOMCTL _ _ _ _ DDR _ MEPC MEPS MESAVE MESR MECR MEVADDR _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ IBREAKA0 IBREAKA1 _ _ _ _ _ _ _ _ _ _ _ _ _ _ DBREAKA0 DBREAKA1 _ _ _ _ _ _ _ _ _ _ _ _ _ _ DBREAKC0 DBREAKC1 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ EPC1 EPC2 EPC3 EPC4 EPC5 EPC6 EPC7 _ _ _ _ _ _ _ _ DEPC _ EPS2 EPS3 EPS4 EPS5 EPS6 EPS7 _ _ _ _ _ _ _ _ _ EXCSAVE1 EXCSAVE2 EXCSAVE3 EXCSAVE4 EXCSAVE5 EXCSAVE6 EXCSAVE7 _ _ _ _ _ _ _ _ CPENABLE INTERRUPT INTSET INTCLEAR INTENABLE _ PS VECBASE EXCCAUSE DEBUGCAUSE CCOUNT PRID ICOUNT ICOUNTLEVEL EXCVADDR _ CCOMPARE0 CCOMPARE1 CCOMPARE2 _ MISC0 MISC1 MISC2 MISC3 _ _ _ _ _ _ _ _ ]; + + # Various 32-bit pointers relative to PC. Any operands that are split across non-consecutive # bits are named foo_LL.LM_ML.MM, where LL is the least significant bits of the least # singificant operand half, LM the most significant bits of the least significant operand half, etc. @@ -138,11 +186,8 @@ u5_4.7_12: tmp is u1_12 & u4_4.7 [ tmp = (u1_12 << 4) | u4_4.7; ] { export * u5_8.11_4: tmp is u1_4 & u4_8.11 [ tmp = (u1_4 << 4) | u4_8.11; ] { export *[const]:1 tmp; } # Signed 12-bit (extended to 16) immediate, used by MOVI. -s16_16.23_8.11: tmp is u4_8.11 & u8_16.23 [ - # FIXME: This table, and the fields used, should be signed, but using s4_8.11 and s8_16.23 - # somehow confuses Ghidra. - tmp = (0xf000 * (u4_8.11 >> 3)) | # Sign-extend. - (u4_8.11 << 8) | u8_16.23; +s16_16.23_8.11: tmp is s4_8.11 & u8_16.23 [ + tmp = (s4_8.11 << 8) | u8_16.23; ] { export *[const]:2 tmp; } # An “asymmetric” immediate from -32..95, used by MOVI.N. @@ -167,25 +212,10 @@ n_u6_12.15_sb2: tmp is n_u4_12.15 [ tmp = n_u4_12.15 << 2; ] { export *[const]: s5_12.15_oex: tmp is u4_12.15 [ tmp = (2 << u4_12.15) * -1; ] { export *[const]:2 tmp; } # Some 4-bit immediates with mappings that can’t be (easily) expressed in a single disassembly action. -# FIXME: “foo: tmp is u4_foo [ tmp = u4_foo; ]” doesn’t work when a more special constructor exists. # n_u4_4.7 with 0 being -1, used by ADDI.N. -n_s4_4.7_nozero: tmp is n_u4_4.7 = 0 [ tmp = -1; ] { export *[const]:4 tmp; } -n_s4_4.7_nozero: tmp is n_u4_4.7 = 1 [ tmp = 1; ] { export *[const]:4 tmp; } -n_s4_4.7_nozero: tmp is n_u4_4.7 = 2 [ tmp = 2; ] { export *[const]:4 tmp; } -n_s4_4.7_nozero: tmp is n_u4_4.7 = 3 [ tmp = 3; ] { export *[const]:4 tmp; } -n_s4_4.7_nozero: tmp is n_u4_4.7 = 4 [ tmp = 4; ] { export *[const]:4 tmp; } -n_s4_4.7_nozero: tmp is n_u4_4.7 = 5 [ tmp = 5; ] { export *[const]:4 tmp; } -n_s4_4.7_nozero: tmp is n_u4_4.7 = 6 [ tmp = 6; ] { export *[const]:4 tmp; } -n_s4_4.7_nozero: tmp is n_u4_4.7 = 7 [ tmp = 7; ] { export *[const]:4 tmp; } -n_s4_4.7_nozero: tmp is n_u4_4.7 = 8 [ tmp = 8; ] { export *[const]:4 tmp; } -n_s4_4.7_nozero: tmp is n_u4_4.7 = 9 [ tmp = 9; ] { export *[const]:4 tmp; } -n_s4_4.7_nozero: tmp is n_u4_4.7 = 10 [ tmp = 10; ] { export *[const]:4 tmp; } -n_s4_4.7_nozero: tmp is n_u4_4.7 = 11 [ tmp = 11; ] { export *[const]:4 tmp; } -n_s4_4.7_nozero: tmp is n_u4_4.7 = 12 [ tmp = 12; ] { export *[const]:4 tmp; } -n_s4_4.7_nozero: tmp is n_u4_4.7 = 13 [ tmp = 13; ] { export *[const]:4 tmp; } -n_s4_4.7_nozero: tmp is n_u4_4.7 = 14 [ tmp = 14; ] { export *[const]:4 tmp; } -n_s4_4.7_nozero: tmp is n_u4_4.7 = 15 [ tmp = 15; ] { export *[const]:4 tmp; } +n_s4_4.7_nozero: tmp is n_u4_4.7 = 0 [ tmp = -1; ] { export *[const]:4 tmp; } +n_s4_4.7_nozero: tmp is n_u4_4.7 [ tmp = n_u4_4.7+0; ] { export *[const]:4 tmp; } # B4CONST(ar) (Branch Immediate) encodings, pg. 41 f. r_b4const: tmp is ar = 0 [ tmp = 0xffffffff; ] { export *[const]:4 tmp; } diff --git a/data/languages/xtensaInstructions.sinc b/data/languages/xtensaInstructions.sinc index c71b796..3f20661 100644 --- a/data/languages/xtensaInstructions.sinc +++ b/data/languages/xtensaInstructions.sinc @@ -303,6 +303,13 @@ macro extract_bit(val, bit, result) { # CALL0 - Non-windowed Call, pg. 297. :call0 srel_6.23_sb2 is srel_6.23_sb2 & u2_4.5 = 0 & op0 = 0b0101 { + #local dst = srel_6.23_sb2; + i2 = a2; + i3 = a3; + i4 = a4; + i5 = a5; + i6 = a6; + i7 = a7; a0 = inst_start + 3; call srel_6.23_sb2; } @@ -310,6 +317,12 @@ macro extract_bit(val, bit, result) { # CALLX0 - Non-windowed Call Register, pg. 304. :callx0 as is op2 = 0 & op1 = 0 & ar = 0 & as & u2_6.7 = 0b11 & u2_4.5 = 0 & op0 = 0 { local dst = as; + i2 = a2; + i3 = a3; + i4 = a4; + i5 = a5; + i6 = a6; + i7 = a7; a0 = inst_start + 3; call [dst]; } @@ -480,11 +493,13 @@ macro extract_bit(val, bit, result) { # ILL - Illegal Instruction, pg. 358. :ill is op2 = 0 & op1 = 0 & ar = 0 & as = 0 & at = 0 & op0 = 0 { ill(); + goto inst_start; } # ILL.N - Narrow Illegal Instruction, pg. 359. :ill.n is n_ar = 0b1111 & n_as = 0 & n_at = 0b0110 & n_op0 = 0b1101 { ill(); + goto inst_start; } # IPF - Instruction Cache Prefetch, pg. 360. @@ -829,7 +844,21 @@ macro extract_bit(val, bit, result) { # NSAU - Normalization Shift Amount Unsigned, pg. 462. (Count leading zeros) :nsau at, as is op2 = 0b0100 & op1 = 0 & ar = 0b1111 & as & at & op0 = 0 { - at = nsau(as); + local z4 = as[16,16] == 0; + + local t3 = zext(z4)*as[0,16] + zext(!z4)*as[16,16]; + local z3 = t3[8,8] == 0; + + local t2 = (z3)*t3[0,8] + (!z3)*t3[8,8]; + local z2 = t2[4,4] == 0; + + local t1 = (z2)*t2[0,4] + (!z2)*t2[4,4]; + local z1 = t1[2,2] == 0; + + local z0 = (z1)*(t1[1,1] == 0) + (!z1)*(t1[3,1] == 0); + local all0 = as == 0; + + at = zext((all0)*32 + (!all0)*(z4<<4 | z3<<3 | z2<<2 | z1<<1 | z0)); } # OEQ.S - Compare Single Equal, pg. 463. @@ -915,6 +944,7 @@ macro extract_bit(val, bit, result) { # RET.N - Narrow Non-Windowed Return, pg. 479. :ret.n is n_ar = 0b1111 & n_as = 0 & n_at = 0 & n_op0 = 0b1101 { return [a0]; + o2=a2; } # RFDD - Return from Debug and Dispatch, pg. 484. @@ -990,7 +1020,9 @@ macro extract_bit(val, bit, result) { # RSR - Read Special Register, pg. 500. :rsr at, u8_8.15 is op0 = 0 & op1 = 0b0011 & u8_8.15 & at & op0 = 0 { + local src:4 = zext(u8_8.15:1); at = rsr(u8_8.15:1); + at = *[special_register]:4 src; } # RSYNC - Register Read Synchronize, pg. 502. @@ -1069,16 +1101,17 @@ macro extract_bit(val, bit, result) { # SLL - Shift Left Logical, pg. 524. :sll ar, as is op2 = 0b1010 & op1 = 0b0001 & ar & as & at = 0 & op0 = 0 { - local sa:1 = 32 - (sar & 0xf); # XXX check this + local sa:1 = 32 - sar; ar = as << sa; } # SLLI - Shift Left Logical Immediate, pg. 525. -:slli ar, as, u5_4.7_20 is u3_21.23 = 0 & u5_4.7_20 & op1 = 0b0001 & ar & as & op0 = 0 { - local sa:1 = 32 - u5_4.7_20; # XXX check this +:slli ar, as, u5_4.7_20 is u3_21.23 = 0 & u1_20 & u5_4.7_20 & op1 = 0b0001 & ar & as & op0 = 0 { + local sa:1 = 32 - 16 * u1_20 - u5_4.7_20; ar = as << sa; } + # SRA - Shift Right Arithmetic, pg. 526. :sra ar, at is op2 = 0b1011 & op1 = 0b0001 & ar & as = 0 & at & op0 = 0 { ar = at s>> sar; @@ -1140,12 +1173,12 @@ macro extract_bit(val, bit, result) { # SSL - Set Shift Amount for Left Shift, pg. 538. :ssl as is op2 = 0b0100 & op1 = 0 & ar = 0b0001 & as & at = 0 & op0 = 0 { - sar = 32 - (as:1 & 0xf); + sar = 32 - (as:1 & 0x1f); } # SSR - Set Shift Amount for Right Shift, pg. 539. :ssr as is op2 = 0b0100 & op1 = 0 & ar = 0 & as & at = 0 & op0 = 0 { - sar = (as:1 & 0xf); + sar = (as:1 & 0x1f); } # SSX - Store Singe Indexed, pg. 540. @@ -1202,9 +1235,10 @@ macro extract_bit(val, bit, result) { br = nan(fs) || nan(ft) || fs f== ft; } -# UFLOAT.S - Convert Unsigned Fixed to Single, pg. 550. XXX: How is this different from float.as? +# UFLOAT.S - Convert Unsigned Fixed to Single, pg. 550. :ufloat.s fr, as, u4_4.7 is op2 = 0b1101 & op1 = 0b1010 & fr & as & u4_4.7 & op0 = 0 { - local f = int2float(as); + local tmp:8 = zext(as); + local f = int2float(tmp); local d = int2float(1:2 << u4_4.7:2); fr = d f/ f; } @@ -1226,10 +1260,14 @@ macro extract_bit(val, bit, result) { br = nan(fs) || nan(ft); } -# UTRUNC.S - Truncate Single to Fixed Unsigned, pg. 555. FIXME: difference to trunc.s? +# UTRUNC.S - Truncate Single to Fixed Unsigned, pg. 555. :utrunc.s ar, fs, u4_4.7 is op2 = 0b1110 & op1 = 0b1010 & ar & fs & u4_4.7 & op0 = 0 { local scale:4 = int2float(1:2 << u4_4.7:2); - ar = trunc(fs f* scale); + local tmp:8 = trunc(fs f* scale); + local posof = nan(fs) || (tmp >> 16) != 0; + local negof = tmp s< 0; + local noof = !posof && !negof; + ar = zext(posof)*0xffffffff + zext(negof)*0x80000000 + zext(noof)*tmp:4; } # WAITI - Wait Interrupt, pg. 556. @@ -1259,8 +1297,14 @@ macro extract_bit(val, bit, result) { # WSR - Write Special Register, pg. 561. :wsr at, u8_8.15 is op2 = 0b0001 & op1 = 0b0011 & u8_8.15 & at & op0 = 0 { + local dst:4 = zext(u8_8.15:1); + *[special_register]:4 dst = at; wsr(u8_8.15:1, at); } +#:WSR.^sr at is op2=0x1 & op1=0x3 & sr & at & op0=0x0 +#{ +# *[special_register]:4 sr = at; +#} # WUR - Write User Register, pg. 563. :wur at, u8_8.15 is op2 = 0b1111 & op1 = 0b0011 & u8_8.15 & at & op0 = 0 { @@ -1278,6 +1322,16 @@ macro extract_bit(val, bit, result) { } # XSR - Exchange Special Register, pg. 566. -:xsr at, u8_8.15 is op2 = 0b1110 & op1 = 0b0001 & u8_8.15 & at & op0 = 0 { +:xsr at, u8_8.15 is op2 = 0b0110 & op1 = 0b0001 & u8_8.15 & at & op0 = 0 { at = xsr(u8_8.15:1, at); } + +# PAD, dummy +#:pad is op0_16=0x0 { +#} + +# PAD, dummy +#:pad is op0_8=0x0 { +#} + + diff --git a/data/languages/xtensaTodo.sinc b/data/languages/xtensaTodo.sinc index b89eea5..b941c09 100644 --- a/data/languages/xtensaTodo.sinc +++ b/data/languages/xtensaTodo.sinc @@ -1,43 +1,161 @@ +macro pushVal(val32) { + local addr:4 = a1; + a1 = a1 - 4; + *:4 addr = val32; +} + +macro popVal(val32) { + local addr:4 = a1; + val32 = *:4 addr; + a1 = a1 + 4; +} + + +macro save() { + sa3 = a3; + sa4 = a4; + sa5 = a5; + sa6 = a6; + sa7 = a7; +} + +macro restore() { + a3 = sa3; + a4 = sa4; + a5 = sa5; + a6 = sa6; + a7 = sa7; +} + + ## Windowed Register Option ## # CALL4 - Call PC-relative, Rotate Window by 4, pg. 298. -:call4 srel_6.23_sb2 is srel_6.23_sb2 & u2_4.5 = 0b01 & op0 = 0b0101 unimpl +:call4 srel_6.23_sb2 is srel_6.23_sb2 & u2_4.5 = 0b01 & op0 = 0b0101 { + #local dst = srel_6.23_sb2; + i2=a6; + i3=a7; + i4=a8; + i5=a9; + a0 = inst_start + 3; + call srel_6.23_sb2; + a6=o2; +} # CALL8 - Call PC-relative, Rotate Window by 8, pg. 300. -:call8 srel_6.23_sb2 is srel_6.23_sb2 & u2_4.5 = 0b10 & op0 = 0b0101 unimpl +:call8 srel_6.23_sb2 is srel_6.23_sb2 & u2_4.5 = 0b10 & op0 = 0b0101 { + #local dst:4 = + i2=a10; + i3=a11; + i4=a12; + i5=a13; + i6=a14; + i7=a15; + a0 = inst_start + 3; + call srel_6.23_sb2; + a10=o2; +} # CALL12 - Call PC-relative, Rotate Window by 12, pg. 302. -:call12 srel_6.23_sb2 is srel_6.23_sb2 & u2_4.5 = 0b11 & op0 = 0b0101 unimpl - -# CALLX4 - Call Register, Rotate Window by 4, pg. 305. -:callx4 as is op2 = 0 & op1 = 0 & ar = 0 & as & u2_6.7 = 0b11 & u2_4.5 = 0b01 & op0 = 0 unimpl - -# CALLX8 - Call Register, Rotate Window by 8, pg. 307. -:callx8 as is op2 = 0 & op1 = 0 & ar = 0 & as & u2_6.7 = 0b11 & u2_4.5 = 0b10 & op0 = 0 unimpl - -# CALLX12 - Call Register, Rotate Window by 12, pg. 308. -:callx12 as is op2 = 0 & op1 = 0 & ar = 0 & as & u2_6.7 = 0b11 & u2_4.5 = 0b11 & op0 = 0 unimpl +:call12 srel_6.23_sb2 is srel_6.23_sb2 & u2_4.5 = 0b11 & op0 = 0b0101 { + #local dst = srel_6.23_sb2; + i2=a14; + i3=a15; + a0 = inst_start + 3; + call srel_6.23_sb2; + a14=o2; +} # ENTRY - Subroutine Entry, pg. 340. -:entry as, u15_12.23_sb3 is u15_12.23_sb3 & as & u2_6.7 = 0b00 & u2_4.5 = 0b11 & op0 = 0b0110 unimpl +:entry as, u15_12.23_sb3 is u15_12.23_sb3 & as & u2_6.7 = 0b00 & u2_4.5 = 0b11 & op0 = 0b0110 { + local amn = sext(u15_12.23_sb3); + a2=i2; + a3=i3; + a4=i4; + a5=i5; + a6=i6; + a7=i7; + #as = as + amn; + WindowBase = amn; + a1 = a1 - amn; +} + + + + +# CALLX4 - Call Register, Rotate Window by 4, pg. 305. +:callx4 as is op2 = 0 & op1 = 0 & ar = 0 & as & u2_6.7 = 0b11 & u2_4.5 = 0b01 & op0 = 0 { + local dst = as; + i2=a6; + i3=a7; + i4=a8; + i5=a9; + i6=a10; + i7=a11; + a0 = inst_start + 3; + call [dst]; + a6=o2; +} + +# CALLX8 - Call Register, Rotate Window by 8, pg. 307. +:callx8 as is op2 = 0 & op1 = 0 & ar = 0 & as & u2_6.7 = 0b11 & u2_4.5 = 0b10 & op0 = 0 { + local dst = as; + i2=a10; + i3=a11; + i4=a12; + i5=a13; + i6=a14; + i7=a15; + a0 = inst_start + 3; + call [dst]; + a10=o2; +} + +# CALLX12 - Call Register, Rotate Window by 12, pg. 308. +:callx12 as is op2 = 0 & op1 = 0 & ar = 0 & as & u2_6.7 = 0b11 & u2_4.5 = 0b11 & op0 = 0 { + local dst = as; + i2=a14; + i3=a15; + a0 = inst_start + 3; + call [dst]; + a14=o2; +} + + # L32E - Load 32-bit for Window Exceptions, pg. 376. -:l32e at, as, s5_12.15_oex is op2 = 0 & op1 = 0b1001 & s5_12.15_oex & as & at & op0 = 0 unimpl +:l32e at, as, s5_12.15_oex is op2 = 0 & op1 = 0b1001 & s5_12.15_oex & as & at & op0 = 0 { + +} # MOVSP - Move to Stack Pointer, pg. 427. :movsp at, as is op2 = 0 & op1 = 0 & ar = 0b0001 & as & at & op0 = 0 unimpl # RETW - Windowed Return, pg. 480. -:retw is op2 = 0 & ar = 0 & as = 0 & at = 0 & u2_18.19 = 0b10 & u2_16.17 = 0b01 & op0 = 0 unimpl +:retw is op2 = 0 & op1 = 0 & ar = 0 & as = 0 & u2_6.7 = 0b10 & u2_4.5 = 0b01 & op0 = 0 { +# Assume call8 + o2=a2; + a1 = a1 + WindowBase; + return [a0]; +} # RETW.N - Narrow Windowed Return, pg. 482. -:retw.n is n_ar = 0b1111 & n_as = 0 & n_at = 0b0001 & n_op0 = 0b1101 unimpl +:retw.n is n_ar = 0b1111 & n_as = 0 & n_at = 0b0001 & n_op0 = 0b1101 { + o2=a2; + a1 = a1 + WindowBase; + return [a0]; +} # ROTW - Rotate Window, pg. 496. -:rotw s4_4.7 is op2 = 0b0100 & op1 = 0 & ar = 0b1000 & as = 0 & s4_4.7 & op0 = 0 unimpl +:rotw s4_4.7 is op2 = 0b0100 & op1 = 0 & ar = 0b1000 & as = 0 & s4_4.7 & op0 = 0 { + WindowBase = WindowBase + s4_4.7; +} # S32E - Store 32-bit for Window Exceptions, pg. 508. -:s32e at, as, s5_12.15_oex is op2 = 0b0100 & op1 = 0b1001 & s5_12.15_oex & as & at & op0 = 0 unimpl +:s32e at, as, s5_12.15_oex is op2 = 0b0100 & op1 = 0b1001 & s5_12.15_oex & as & at & op0 = 0 { + #local vAddr:4 = as + s5_12.15_oex; + #*:4 vAddr = at; +} ## MAC16 option ## diff --git a/src/main/java/ghidra/app/util/bin/format/elf/relocation/Xtensa_ElfRelocationConstants.java b/src/main/java/ghidra/app/util/bin/format/elf/relocation/Xtensa_ElfRelocationConstants.java new file mode 100644 index 0000000..f74eb6d --- /dev/null +++ b/src/main/java/ghidra/app/util/bin/format/elf/relocation/Xtensa_ElfRelocationConstants.java @@ -0,0 +1,58 @@ +package ghidra.app.util.bin.format.elf.relocation; + +public class Xtensa_ElfRelocationConstants { + /* Xtensa processor ELF architecture-magic number */ + + // EM_XTENSA is already definded + public static final int EM_XTENSA_OLD = 0xABC7; + + /* Xtensa relocations defined by the ABIs */ + + public static final int R_XTENSA_NONE = 0; + public static final int R_XTENSA_32 = 1; + public static final int R_XTENSA_RTLD = 2; + public static final int R_XTENSA_GLOB_DAT = 3; + public static final int R_XTENSA_JMP_SLOT = 4; + public static final int R_XTENSA_RELATIVE = 5; + public static final int R_XTENSA_PLT = 6; + public static final int R_XTENSA_OP0 = 8; + public static final int R_XTENSA_OP1 = 9; + public static final int R_XTENSA_OP2 = 10; + public static final int R_XTENSA_ASM_EXPAND = 11; + public static final int R_XTENSA_ASM_SIMPLIFY = 12; + public static final int R_XTENSA_GNU_VTINHERIT = 15; + public static final int R_XTENSA_GNU_VTENTRY = 16; + public static final int R_XTENSA_DIFF8 = 17; + public static final int R_XTENSA_DIFF16 = 18; + public static final int R_XTENSA_DIFF32 = 19; + public static final int R_XTENSA_SLOT0_OP = 20; + public static final int R_XTENSA_SLOT1_OP = 21; + public static final int R_XTENSA_SLOT2_OP = 22; + public static final int R_XTENSA_SLOT3_OP = 23; + public static final int R_XTENSA_SLOT4_OP = 24; + public static final int R_XTENSA_SLOT5_OP = 25; + public static final int R_XTENSA_SLOT6_OP = 26; + public static final int R_XTENSA_SLOT7_OP = 27; + public static final int R_XTENSA_SLOT8_OP = 28; + public static final int R_XTENSA_SLOT9_OP = 29; + public static final int R_XTENSA_SLOT10_OP = 30; + public static final int R_XTENSA_SLOT11_OP = 31; + public static final int R_XTENSA_SLOT12_OP = 32; + public static final int R_XTENSA_SLOT13_OP = 33; + public static final int R_XTENSA_SLOT14_OP = 34; + public static final int R_XTENSA_SLOT0_ALT = 35; + public static final int R_XTENSA_SLOT1_ALT = 36; + public static final int R_XTENSA_SLOT2_ALT = 37; + public static final int R_XTENSA_SLOT3_ALT = 38; + public static final int R_XTENSA_SLOT4_ALT = 39; + public static final int R_XTENSA_SLOT5_ALT = 40; + public static final int R_XTENSA_SLOT6_ALT = 41; + public static final int R_XTENSA_SLOT7_ALT = 42; + public static final int R_XTENSA_SLOT8_ALT = 43; + public static final int R_XTENSA_SLOT9_ALT = 44; + public static final int R_XTENSA_SLOT10_ALT = 45; + public static final int R_XTENSA_SLOT11_ALT = 46; + public static final int R_XTENSA_SLOT12_ALT = 47; + public static final int R_XTENSA_SLOT13_ALT = 48; + public static final int R_XTENSA_SLOT14_ALT = 49; +} diff --git a/src/main/java/ghidra/app/util/bin/format/elf/relocation/Xtensa_ElfRelocationHandler.java b/src/main/java/ghidra/app/util/bin/format/elf/relocation/Xtensa_ElfRelocationHandler.java new file mode 100644 index 0000000..5882690 --- /dev/null +++ b/src/main/java/ghidra/app/util/bin/format/elf/relocation/Xtensa_ElfRelocationHandler.java @@ -0,0 +1,292 @@ +package ghidra.app.util.bin.format.elf.relocation; + +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 Xtensa_ElfRelocationHandler extends ElfRelocationHandler { + + @Override + public boolean canRelocate(ElfHeader elf) { + return elf.e_machine() == ElfConstants.EM_XTENSA || + elf.e_machine() == Xtensa_ElfRelocationConstants.EM_XTENSA_OLD; + } + + @Override + public void relocate(ElfRelocationContext elfRelocationContext, ElfRelocation relocation, Address relocationAddress) + throws MemoryAccessException, NotFoundException { + ElfHeader elf = elfRelocationContext.getElfHeader(); + if (!canRelocate(elf)) { + return; + } + + int type=relocation.getType(); + if (Xtensa_ElfRelocationConstants.R_XTENSA_NONE == type) { + return; + } + + Program program = elfRelocationContext.getProgram(); + Memory memory = program.getMemory(); + + long addend = relocation.hasAddend() ? relocation.getAddend() : memory.getInt(relocationAddress); + long offset = relocationAddress.getOffset(); + long base = elfRelocationContext.getImageBaseWordAdjustmentOffset(); + ElfSymbol sym = null; + long symbolValue = 0; + String symbolName = null; + + int symbolIndex = relocation.getSymbolIndex(); + if (symbolIndex != 0) { + sym = elfRelocationContext.getSymbol(symbolIndex); + } + + if (null != sym) { + symbolValue = elfRelocationContext.getSymbolValue(sym); + symbolName = sym.getNameAsString(); + } + + switch(type) { + case Xtensa_ElfRelocationConstants.R_XTENSA_32: + markAsWarning(program, relocationAddress, "R_XTENSA_32", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_RTLD: + markAsWarning(program, relocationAddress, "R_XTENSA_RTLD", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_GLOB_DAT: + markAsWarning(program, relocationAddress, "R_XTENSA_GLOB_DAT", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_JMP_SLOT: + markAsWarning(program, relocationAddress, "R_XTENSA_JMP_SLOT", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_RELATIVE: + markAsWarning(program, relocationAddress, "R_XTENSA_RELATIVE", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_PLT: + markAsWarning(program, relocationAddress, "R_XTENSA_PLT", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_OP0: + markAsWarning(program, relocationAddress, "R_XTENSA_OP0", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_OP1: + markAsWarning(program, relocationAddress, "R_XTENSA_OP1", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_OP2: + markAsWarning(program, relocationAddress, "R_XTENSA_OP2", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_ASM_EXPAND: + markAsWarning(program, relocationAddress, "R_XTENSA_ASM_EXPAND", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_ASM_SIMPLIFY: + markAsWarning(program, relocationAddress, "R_XTENSA_ASM_SIMPLIFY", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_GNU_VTINHERIT: + markAsWarning(program, relocationAddress, "R_XTENSA_GNU_VTINHERIT", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_GNU_VTENTRY: + markAsWarning(program, relocationAddress, "R_XTENSA_GNU_VTENTRY", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_DIFF8: + markAsWarning(program, relocationAddress, "R_XTENSA_DIFF8", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_DIFF16: + markAsWarning(program, relocationAddress, "R_XTENSA_DIFF16", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_DIFF32: + markAsWarning(program, relocationAddress, "R_XTENSA_DIFF32", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT0_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT0_OP", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT1_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT1_OP", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT2_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT2_OP", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT3_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT3_OP", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT4_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT4_OP", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT5_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT5_OP", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT6_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT6_OP", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT7_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT7_OP", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT8_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT8_OP", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT9_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT9_OP", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT10_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT10_OP", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT11_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT11_OP", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT12_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT12_OP", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT13_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT13_OP", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT14_OP: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT14_OP", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT0_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT0_ALT", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT1_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT1_ALT", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT2_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT2_ALT", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT3_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT3_ALT", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT4_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT4_ALT", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT5_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT5_ALT", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT6_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT6_ALT", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT7_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT7_ALT", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT8_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT8_ALT", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT9_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT9_ALT", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT10_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT10_ALT", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT11_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT11_ALT", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT12_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT12_ALT", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT13_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT13_ALT", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + case Xtensa_ElfRelocationConstants.R_XTENSA_SLOT14_ALT: + markAsWarning(program, relocationAddress, "R_XTENSA_SLOT14_ALT", + symbolName, symbolIndex, "TODO, needs support ", + elfRelocationContext.getLog()); + break; + default: + markAsUnhandled(program, relocationAddress, type, symbolIndex, + symbolName, elfRelocationContext.getLog()); + break; + } + } + +}