Skip to content

Commit 2231e7d

Browse files
Add relocation patching for AVR
1 parent a10e7cb commit 2231e7d

File tree

1 file changed

+212
-1
lines changed

1 file changed

+212
-1
lines changed

librz/bin/format/elf/elf_relocs_patching.c

Lines changed: 212 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
// SPDX-License-Identifier: LGPL-3.0-only
55

66
#include "elf.h"
7+
#include "elf/glibc_elf.h"
8+
#include "rz_util/rz_bits.h"
79

810
typedef struct reloc_formular_symbols_t {
911
ut64 A; // Appendend
@@ -2011,6 +2013,213 @@ static void patch_reloc_alpha(RZ_INOUT RzBuffer *buf_patched, const ut64 patch_a
20112013
}
20122014
}
20132015

2016+
static void patch_reloc_avr(RZ_INOUT RzBuffer *buf_patched, const ut64 patch_addr, const int rel_type, bool big_endian, const RelocFormularSymbols *fs) {
2017+
rz_return_if_fail(buf_patched && fs);
2018+
2019+
ut8 buf[2] = { 0 };
2020+
st64 offset = 0;
2021+
ut16 opcode = 0;
2022+
ut32 nbytes = 2;
2023+
2024+
ut64 val = fs->S + fs->A;
2025+
2026+
switch (rel_type) {
2027+
case R_AVR_NONE:
2028+
return;
2029+
case R_AVR_32:
2030+
rz_buf_write_ble32_at(buf_patched, patch_addr, val, big_endian);
2031+
break;
2032+
case R_AVR_7_PCREL:
2033+
rz_buf_read_at(buf_patched, patch_addr, buf, nbytes);
2034+
offset = (val - fs->P - 2) / 2;
2035+
opcode = rz_read_ble16(buf, big_endian) | rz_bits_spread(0x3F8, offset);
2036+
rz_write_ble16(buf, opcode, big_endian);
2037+
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
2038+
break;
2039+
case R_AVR_13_PCREL:
2040+
rz_buf_read_at(buf_patched, patch_addr, buf, nbytes);
2041+
offset = (val - fs->P - 2) / 2;
2042+
opcode = rz_read_ble16(buf, big_endian) | rz_bits_spread(0xFFF, offset);
2043+
rz_write_ble16(buf, opcode, big_endian);
2044+
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
2045+
break;
2046+
case R_AVR_16:
2047+
rz_buf_write_ble16_at(buf_patched, patch_addr, val, big_endian);
2048+
break;
2049+
case R_AVR_16_PM:
2050+
rz_buf_write_ble16_at(buf_patched, patch_addr, val / 2, big_endian);
2051+
break;
2052+
case R_AVR_LO8_LDI:
2053+
/* fall through */
2054+
case R_AVR_LDI:
2055+
rz_buf_read_at(buf_patched, patch_addr, buf, nbytes);
2056+
offset = val & 0xFF;
2057+
opcode = rz_read_ble16(buf, big_endian) | rz_bits_spread(0xF0F, offset);
2058+
rz_write_ble16(buf, opcode, big_endian);
2059+
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
2060+
break;
2061+
case R_AVR_HI8_LDI:
2062+
rz_buf_read_at(buf_patched, patch_addr, buf, nbytes);
2063+
offset = (val >> 8) & 0xFF;
2064+
opcode = rz_read_ble16(buf, big_endian) | rz_bits_spread(0xF0F, offset);
2065+
rz_write_ble16(buf, opcode, big_endian);
2066+
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
2067+
break;
2068+
case R_AVR_HH8_LDI:
2069+
rz_buf_read_at(buf_patched, patch_addr, buf, nbytes);
2070+
offset = (val >> 16) & 0xFF;
2071+
opcode = rz_read_ble16(buf, big_endian) | rz_bits_spread(0xF0F, offset);
2072+
rz_write_ble16(buf, opcode, big_endian);
2073+
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
2074+
break;
2075+
case R_AVR_LO8_LDI_NEG:
2076+
rz_buf_read_at(buf_patched, patch_addr, buf, nbytes);
2077+
offset = (-val) & 0xFF;
2078+
opcode = rz_read_ble16(buf, big_endian) | rz_bits_spread(0xF0F, offset);
2079+
rz_write_ble16(buf, opcode, big_endian);
2080+
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
2081+
break;
2082+
case R_AVR_HI8_LDI_NEG:
2083+
rz_buf_read_at(buf_patched, patch_addr, buf, nbytes);
2084+
offset = ((-val) >> 8) & 0xFF;
2085+
opcode = rz_read_ble16(buf, big_endian) | rz_bits_spread(0xF0F, offset);
2086+
rz_write_ble16(buf, opcode, big_endian);
2087+
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
2088+
break;
2089+
case R_AVR_HH8_LDI_NEG:
2090+
rz_buf_read_at(buf_patched, patch_addr, buf, nbytes);
2091+
offset = ((-val) >> 16) & 0xFF;
2092+
opcode = rz_read_ble16(buf, big_endian) | rz_bits_spread(0xF0F, offset);
2093+
rz_write_ble16(buf, opcode, big_endian);
2094+
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
2095+
break;
2096+
case R_AVR_LO8_LDI_PM:
2097+
/* fall through */
2098+
case R_AVR_LO8_LDI_GS:
2099+
rz_buf_read_at(buf_patched, patch_addr, buf, nbytes);
2100+
offset = val & 0xFF;
2101+
opcode = rz_read_ble16(buf, big_endian) | rz_bits_spread(0xF0F, offset / 2);
2102+
rz_write_ble16(buf, opcode, big_endian);
2103+
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
2104+
break;
2105+
case R_AVR_HI8_LDI_PM:
2106+
/* fall through */
2107+
case R_AVR_HI8_LDI_GS:
2108+
rz_buf_read_at(buf_patched, patch_addr, buf, nbytes);
2109+
offset = (val >> 8) & 0xFF;
2110+
opcode = rz_read_ble16(buf, big_endian) | rz_bits_spread(0xF0F, offset / 2);
2111+
rz_write_ble16(buf, opcode, big_endian);
2112+
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
2113+
break;
2114+
case R_AVR_HH8_LDI_PM:
2115+
rz_buf_read_at(buf_patched, patch_addr, buf, nbytes);
2116+
offset = (val >> 16) & 0xFF;
2117+
opcode = rz_read_ble16(buf, big_endian) | rz_bits_spread(0xF0F, offset / 2);
2118+
rz_write_ble16(buf, opcode, big_endian);
2119+
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
2120+
break;
2121+
case R_AVR_LO8_LDI_PM_NEG:
2122+
rz_buf_read_at(buf_patched, patch_addr, buf, nbytes);
2123+
offset = (-val) & 0xFF;
2124+
opcode = rz_read_ble16(buf, big_endian) | rz_bits_spread(0xF0F, offset / 2);
2125+
rz_write_ble16(buf, opcode, big_endian);
2126+
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
2127+
break;
2128+
case R_AVR_HI8_LDI_PM_NEG:
2129+
rz_buf_read_at(buf_patched, patch_addr, buf, nbytes);
2130+
offset = ((-val) >> 8) & 0xFF;
2131+
opcode = rz_read_ble16(buf, big_endian) | rz_bits_spread(0xF0F, offset / 2);
2132+
rz_write_ble16(buf, opcode, big_endian);
2133+
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
2134+
break;
2135+
case R_AVR_HH8_LDI_PM_NEG:
2136+
rz_buf_read_at(buf_patched, patch_addr, buf, nbytes);
2137+
offset = ((-val) >> 16) & 0xFF;
2138+
opcode = rz_read_ble16(buf, big_endian) | rz_bits_spread(0xF0F, offset / 2);
2139+
rz_write_ble16(buf, opcode, big_endian);
2140+
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
2141+
break;
2142+
case R_AVR_CALL:
2143+
nbytes = 4;
2144+
rz_buf_read_at(buf_patched, patch_addr, buf, nbytes);
2145+
val = val / 2;
2146+
break;
2147+
case R_AVR_6:
2148+
rz_buf_read_at(buf_patched, patch_addr, buf, nbytes);
2149+
opcode = rz_read_ble16(buf, big_endian) | rz_bits_spread(0x2C07, val);
2150+
rz_write_ble16(buf, opcode, big_endian);
2151+
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
2152+
break;
2153+
case R_AVR_6_ADIW:
2154+
rz_buf_read_at(buf_patched, patch_addr, buf, nbytes);
2155+
opcode = rz_read_ble16(buf, big_endian) | rz_bits_spread(0xCF, val);
2156+
rz_write_ble16(buf, opcode, big_endian);
2157+
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
2158+
break;
2159+
case R_AVR_MS8_LDI:
2160+
rz_buf_read_at(buf_patched, patch_addr, buf, nbytes);
2161+
offset = (val >> 24) & 0xFF;
2162+
opcode = rz_read_ble16(buf, big_endian) | rz_bits_spread(0xF0F, offset);
2163+
rz_write_ble16(buf, opcode, big_endian);
2164+
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
2165+
break;
2166+
case R_AVR_MS8_LDI_NEG:
2167+
rz_buf_read_at(buf_patched, patch_addr, buf, nbytes);
2168+
offset = ((-val) >> 24) & 0xFF;
2169+
opcode = rz_read_ble16(buf, big_endian) | rz_bits_spread(0xF0F, offset);
2170+
rz_write_ble16(buf, opcode, big_endian);
2171+
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
2172+
break;
2173+
case R_AVR_8:
2174+
/* fall through */
2175+
case R_AVR_8_LO8:
2176+
offset = val & 0xFF;
2177+
rz_buf_write_ble32_at(buf_patched, patch_addr, offset, big_endian);
2178+
break;
2179+
case R_AVR_8_HI8:
2180+
offset = (val >> 8) & 0xFF;
2181+
rz_buf_write_ble32_at(buf_patched, patch_addr, offset, big_endian);
2182+
break;
2183+
case R_AVR_8_HLO8:
2184+
offset = (val >> 16) & 0xFF;
2185+
rz_buf_write_ble32_at(buf_patched, patch_addr, offset, big_endian);
2186+
break;
2187+
case R_AVR_DIFF8:
2188+
/* fall through */
2189+
case R_AVR_DIFF16:
2190+
/* fall through */
2191+
case R_AVR_DIFF32:
2192+
/* Value already written by assembler */
2193+
break;
2194+
case R_AVR_LDS_STS_16:
2195+
rz_buf_read_at(buf_patched, patch_addr, buf, nbytes);
2196+
offset = (val - 0x40) & 0x7F;
2197+
offset = (val & 0x0f) | ((val & 0x30) << 5) | ((val & 0x40) << 2);
2198+
opcode = rz_read_ble16(buf, big_endian) | offset;
2199+
rz_write_ble16(buf, opcode, big_endian);
2200+
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
2201+
break;
2202+
case R_AVR_PORT6:
2203+
rz_buf_read_at(buf_patched, patch_addr, buf, nbytes);
2204+
opcode = rz_read_ble16(buf, big_endian) | rz_bits_spread(0x60F, val);
2205+
rz_write_ble16(buf, opcode, big_endian);
2206+
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
2207+
break;
2208+
case R_AVR_PORT5:
2209+
rz_buf_read_at(buf_patched, patch_addr, buf, nbytes);
2210+
opcode = rz_read_ble16(buf, big_endian) | rz_bits_spread(0xF8, val);
2211+
rz_write_ble16(buf, opcode, big_endian);
2212+
rz_buf_write_at(buf_patched, patch_addr, buf, nbytes);
2213+
break;
2214+
case R_AVR_32_PCREL:
2215+
rz_buf_write_ble32_at(buf_patched, patch_addr, val - fs->P, big_endian);
2216+
break;
2217+
default:
2218+
UNHANDL_DEF("AVR", rel_type);
2219+
break;
2220+
}
2221+
}
2222+
20142223
#undef UNHANDL
20152224
#undef UNHANDL_DEF
20162225

@@ -2080,6 +2289,9 @@ void Elf_(rz_bin_elf_patch_relocation)(RZ_NONNULL ELFOBJ *bin, RZ_NONNULL RzBinE
20802289
case EM_SPARCV9:
20812290
patch_reloc_sparc(bin->buf_patched, patch_addr, rel->type, big_endian, &formular_sym);
20822291
break;
2292+
case EM_AVR:
2293+
patch_reloc_avr(bin->buf_patched, patch_addr, rel->type, big_endian, &formular_sym);
2294+
break;
20832295
case EM_M32: ARCH_MISSING("EM_M32");
20842296
case EM_68K: ARCH_MISSING("EM_68K");
20852297
case EM_88K: ARCH_MISSING("EM_88K");
@@ -2135,7 +2347,6 @@ void Elf_(rz_bin_elf_patch_relocation)(RZ_NONNULL ELFOBJ *bin, RZ_NONNULL RzBinE
21352347
case EM_MMIX: ARCH_MISSING("EM_MMIX");
21362348
case EM_HUANY: ARCH_MISSING("EM_HUANY");
21372349
case EM_PRISM: ARCH_MISSING("EM_PRISM");
2138-
case EM_AVR: ARCH_MISSING("EM_AVR");
21392350
case EM_FR30: ARCH_MISSING("EM_FR30");
21402351
case EM_D10V: ARCH_MISSING("EM_D10V");
21412352
case EM_D30V: ARCH_MISSING("EM_D30V");

0 commit comments

Comments
 (0)