librz/bin: fix patching relocations for RISC-V ELFs
* fix unused return value in patch_relocs_riscv and unreachable code in extension parser
This commit is contained in:
parent
09cab090f6
commit
8d459b218d
3 changed files with 124 additions and 64 deletions
|
|
@ -9,8 +9,8 @@
|
||||||
* RISC-V Extension Parser Using a Trie trick
|
* RISC-V Extension Parser Using a Trie trick
|
||||||
* Generated from arch/RISCV/RISCVGenSubtargetInfo.inc in Capstone sources
|
* Generated from arch/RISCV/RISCVGenSubtargetInfo.inc in Capstone sources
|
||||||
*
|
*
|
||||||
* This function parses a single RISC-V extension name and ORs the corresponding
|
* This function parses a single RISC-V extension name and returns the corresponding
|
||||||
* feature flags with an accumulator 'mode'.
|
* feature flag.
|
||||||
*
|
*
|
||||||
* Trie Diagram:
|
* Trie Diagram:
|
||||||
* ROOT
|
* ROOT
|
||||||
|
|
@ -556,13 +556,27 @@ typedef enum {
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
/* Macro: Conditionally invoke a macro if the current character is not on a given blacklist*/
|
||||||
|
#define DO_IF_NOT_ANY_OF(blacklist, thing) \
|
||||||
|
do { \
|
||||||
|
bool __will_do__ = true; \
|
||||||
|
char *__curr__ = blacklist; \
|
||||||
|
while (*__curr__ != '\0') { \
|
||||||
|
if (*p == *__curr__++) { \
|
||||||
|
__will_do__ = false; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
if (__will_do__) { \
|
||||||
|
thing; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main parse routine: Try to consume a RISC-V extension name from the architecture string at a given position.
|
* Main parse routine: Try to consume a RISC-V extension name from the architecture string at a given position.
|
||||||
*
|
*
|
||||||
* @param arch_str: The full architecture string
|
* @param arch_str: The full architecture string
|
||||||
* @param idx: Pointer to current index (will be updated to show consumed length)
|
* @param idx: Pointer to current index (will be updated to show consumed length)
|
||||||
* @param mode: Pointer to the feature accumulator (will be ORed with the feature flag if extension found)
|
* @param mode: Pointer to the feature result * @return: Parse result indicating why parsing stopped and whether a match was found
|
||||||
* @return: Parse result indicating why parsing stopped and whether a match was found
|
|
||||||
*
|
*
|
||||||
* Stopping conditions:
|
* Stopping conditions:
|
||||||
* - '\0' (end of string)
|
* - '\0' (end of string)
|
||||||
|
|
@ -1031,7 +1045,7 @@ try_consume_riscv_ext_from(const char *ext_name, size_t *idx, ut64 *mode) {
|
||||||
}
|
}
|
||||||
} else if (*p == 'h') {
|
} else if (*p == 'h') {
|
||||||
p++;
|
p++;
|
||||||
STOP_WITH_MATCH(RISCV_FeatureStdExtZfh);
|
DO_IF_NOT_ANY_OF("m", STOP_WITH_MATCH(RISCV_FeatureStdExtZfh));
|
||||||
|
|
||||||
/* State: 'zfh' expecting [m] */
|
/* State: 'zfh' expecting [m] */
|
||||||
if (*p == 'm') {
|
if (*p == 'm') {
|
||||||
|
|
@ -1087,7 +1101,7 @@ try_consume_riscv_ext_from(const char *ext_name, size_t *idx, ut64 *mode) {
|
||||||
/* State: 'zhin' expecting [x] */
|
/* State: 'zhin' expecting [x] */
|
||||||
if (*p == 'x') {
|
if (*p == 'x') {
|
||||||
p++;
|
p++;
|
||||||
STOP_WITH_MATCH(RISCV_FeatureStdExtZhinx);
|
DO_IF_NOT_ANY_OF("m", STOP_WITH_MATCH(RISCV_FeatureStdExtZhinx));
|
||||||
|
|
||||||
/* State: 'zhinx' expecting [m] */
|
/* State: 'zhinx' expecting [m] */
|
||||||
if (*p == 'm') {
|
if (*p == 'm') {
|
||||||
|
|
@ -1473,12 +1487,12 @@ try_consume_riscv_ext_from(const char *ext_name, size_t *idx, ut64 *mode) {
|
||||||
}
|
}
|
||||||
} else if (*p == 'k') {
|
} else if (*p == 'k') {
|
||||||
p++;
|
p++;
|
||||||
STOP_WITH_MATCH(RISCV_FeatureStdExtZk);
|
DO_IF_NOT_ANY_OF("nrst", STOP_WITH_MATCH(RISCV_FeatureStdExtZk));
|
||||||
|
|
||||||
/* State: 'zk' expecting [nrst] */
|
/* State: 'zk' expecting [nrst] */
|
||||||
if (*p == 'n') {
|
if (*p == 'n') {
|
||||||
p++;
|
p++;
|
||||||
STOP_WITH_MATCH(RISCV_FeatureStdExtZkn);
|
DO_IF_NOT_ANY_OF("deh", STOP_WITH_MATCH(RISCV_FeatureStdExtZkn));
|
||||||
|
|
||||||
/* State: 'zkn' expecting [deh] */
|
/* State: 'zkn' expecting [deh] */
|
||||||
if (*p == 'd') {
|
if (*p == 'd') {
|
||||||
|
|
@ -1499,7 +1513,7 @@ try_consume_riscv_ext_from(const char *ext_name, size_t *idx, ut64 *mode) {
|
||||||
STOP_WITH_MATCH(RISCV_FeatureStdExtZkr);
|
STOP_WITH_MATCH(RISCV_FeatureStdExtZkr);
|
||||||
} else if (*p == 's') {
|
} else if (*p == 's') {
|
||||||
p++;
|
p++;
|
||||||
STOP_WITH_MATCH(RISCV_FeatureStdExtZks);
|
DO_IF_NOT_ANY_OF("eh", STOP_WITH_MATCH(RISCV_FeatureStdExtZks));
|
||||||
|
|
||||||
/* State: 'zks' expecting [eh] */
|
/* State: 'zks' expecting [eh] */
|
||||||
if (*p == 'e') {
|
if (*p == 'e') {
|
||||||
|
|
@ -1686,7 +1700,7 @@ try_consume_riscv_ext_from(const char *ext_name, size_t *idx, ut64 *mode) {
|
||||||
}
|
}
|
||||||
} else if (*p == 'h') {
|
} else if (*p == 'h') {
|
||||||
p++;
|
p++;
|
||||||
STOP_WITH_MATCH(RISCV_FeatureStdExtZvfh);
|
DO_IF_NOT_ANY_OF("m", STOP_WITH_MATCH(RISCV_FeatureStdExtZvfh));
|
||||||
|
|
||||||
/* State: 'zvfh' expecting [m] */
|
/* State: 'zvfh' expecting [m] */
|
||||||
if (*p == 'm') {
|
if (*p == 'm') {
|
||||||
|
|
@ -1725,7 +1739,7 @@ try_consume_riscv_ext_from(const char *ext_name, size_t *idx, ut64 *mode) {
|
||||||
STOP_WITH_MATCH(RISCV_FeatureStdExtZvkg);
|
STOP_WITH_MATCH(RISCV_FeatureStdExtZvkg);
|
||||||
} else if (*p == 'n') {
|
} else if (*p == 'n') {
|
||||||
p++;
|
p++;
|
||||||
STOP_WITH_MATCH(RISCV_FeatureStdExtZvkn);
|
DO_IF_NOT_ANY_OF("cegh", STOP_WITH_MATCH(RISCV_FeatureStdExtZvkn));
|
||||||
|
|
||||||
/* State: 'zvkn' expecting [cegh] */
|
/* State: 'zvkn' expecting [cegh] */
|
||||||
if (*p == 'c') {
|
if (*p == 'c') {
|
||||||
|
|
@ -1763,7 +1777,7 @@ try_consume_riscv_ext_from(const char *ext_name, size_t *idx, ut64 *mode) {
|
||||||
}
|
}
|
||||||
} else if (*p == 's') {
|
} else if (*p == 's') {
|
||||||
p++;
|
p++;
|
||||||
STOP_WITH_MATCH(RISCV_FeatureStdExtZvks);
|
DO_IF_NOT_ANY_OF("cegh", STOP_WITH_MATCH(RISCV_FeatureStdExtZvks));
|
||||||
|
|
||||||
/* State: 'zvks' expecting [cegh] */
|
/* State: 'zvks' expecting [cegh] */
|
||||||
if (*p == 'c') {
|
if (*p == 'c') {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include "elf/glibc_elf.h"
|
#include "elf/glibc_elf.h"
|
||||||
#include "rz_types.h"
|
#include "rz_types.h"
|
||||||
#include "rz_types_base.h"
|
#include "rz_types_base.h"
|
||||||
|
#include "rz_util/rz_assert.h"
|
||||||
#include "rz_util/rz_buf.h"
|
#include "rz_util/rz_buf.h"
|
||||||
#include "rz_util/rz_log.h"
|
#include "rz_util/rz_log.h"
|
||||||
|
|
||||||
|
|
@ -2342,25 +2343,31 @@ static void patch_reloc_riscv(RZ_INOUT RzBuffer *buf_patched, const ut64 patch_a
|
||||||
case R_RISCV_NONE:
|
case R_RISCV_NONE:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case R_RISCV_32:
|
case R_RISCV_32: {
|
||||||
val = S + A;
|
val = S + A;
|
||||||
rz_buf_write_ble32_at(buf_patched, patch_addr, val, big_endian);
|
bool success = rz_buf_write_ble32_at(buf_patched, patch_addr, val, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case R_RISCV_64:
|
case R_RISCV_64: {
|
||||||
val = S + A;
|
val = S + A;
|
||||||
rz_buf_write_ble64_at(buf_patched, patch_addr, val, big_endian);
|
bool success = rz_buf_write_ble64_at(buf_patched, patch_addr, val, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case R_RISCV_RELATIVE:
|
case R_RISCV_RELATIVE:
|
||||||
val = A + B;
|
val = A + B;
|
||||||
switch (bits) {
|
switch (bits) {
|
||||||
case 32:
|
case 32: {
|
||||||
rz_buf_write_ble32_at(buf_patched, patch_addr, val, big_endian);
|
bool success = rz_buf_write_ble32_at(buf_patched, patch_addr, val, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
break;
|
break;
|
||||||
case 64:
|
}
|
||||||
rz_buf_write_ble64_at(buf_patched, patch_addr, val, big_endian);
|
case 64: {
|
||||||
|
bool success = rz_buf_write_ble64_at(buf_patched, patch_addr, val, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
RZ_LOG_WARN("Unsupported number of bits for R_RISCV_RELATIVE: %d, only 32 bits and 64 bits are supported", bits);
|
RZ_LOG_WARN("Unsupported number of bits for R_RISCV_RELATIVE: %d, only 32 bits and 64 bits are supported", bits);
|
||||||
return;
|
return;
|
||||||
|
|
@ -2412,22 +2419,28 @@ static void patch_reloc_riscv(RZ_INOUT RzBuffer *buf_patched, const ut64 patch_a
|
||||||
|
|
||||||
case R_RISCV_JUMP_SLOT:
|
case R_RISCV_JUMP_SLOT:
|
||||||
switch (bits) {
|
switch (bits) {
|
||||||
case 32:
|
case 32: {
|
||||||
rz_buf_write_ble32_at(buf_patched, patch_addr, S, big_endian);
|
bool success = rz_buf_write_ble32_at(buf_patched, patch_addr, S, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
break;
|
break;
|
||||||
case 64:
|
}
|
||||||
rz_buf_write_ble64_at(buf_patched, patch_addr, S, big_endian);
|
case 64: {
|
||||||
|
bool success = rz_buf_write_ble64_at(buf_patched, patch_addr, S, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
RZ_LOG_WARN("Unsupported number of bits for R_RISCV_JUMP_SLOT: %d, only 32 bits and 64 bits are supported", bits);
|
RZ_LOG_WARN("Unsupported number of bits for R_RISCV_JUMP_SLOT: %d, only 32 bits and 64 bits are supported", bits);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RISCV_32_PCREL:
|
case R_RISCV_32_PCREL: {
|
||||||
val = S + A - P;
|
val = S + A - P;
|
||||||
rz_buf_write_ble32_at(buf_patched, patch_addr, val, big_endian);
|
bool success = rz_buf_write_ble32_at(buf_patched, patch_addr, val, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case R_RISCV_GOT_HI20: {
|
case R_RISCV_GOT_HI20: {
|
||||||
val = fs->G + fs->GOT + A - P;
|
val = fs->G + fs->GOT + A - P;
|
||||||
|
|
@ -2506,91 +2519,111 @@ static void patch_reloc_riscv(RZ_INOUT RzBuffer *buf_patched, const ut64 patch_a
|
||||||
rz_buf_read_ble8_at(buf_patched, patch_addr, &old_val, big_endian);
|
rz_buf_read_ble8_at(buf_patched, patch_addr, &old_val, big_endian);
|
||||||
ut64 result = ((ut64)old_val) + S + A;
|
ut64 result = ((ut64)old_val) + S + A;
|
||||||
unsigned long long addr = patch_addr;
|
unsigned long long addr = patch_addr;
|
||||||
rz_buf_write_ble8_offset(buf_patched, &addr, (ut8)result, big_endian);
|
bool success = rz_buf_write_ble8_offset(buf_patched, &addr, (ut8)result, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case R_RISCV_ADD16: {
|
case R_RISCV_ADD16: {
|
||||||
ut16 old_val = 0;
|
ut16 old_val = 0;
|
||||||
rz_buf_read_ble16_at(buf_patched, patch_addr, &old_val, big_endian);
|
bool success = rz_buf_read_ble16_at(buf_patched, patch_addr, &old_val, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
ut64 result = ((ut64)old_val) + S + A;
|
ut64 result = ((ut64)old_val) + S + A;
|
||||||
rz_buf_write_ble16_at(buf_patched, patch_addr, (ut16)result, big_endian);
|
success = rz_buf_write_ble16_at(buf_patched, patch_addr, (ut16)result, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case R_RISCV_ADD32: {
|
case R_RISCV_ADD32: {
|
||||||
ut32 old_val = 0;
|
ut32 old_val = 0;
|
||||||
rz_buf_read_ble32_at(buf_patched, patch_addr, &old_val, big_endian);
|
bool success = rz_buf_read_ble32_at(buf_patched, patch_addr, &old_val, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
ut64 result = ((ut64)old_val) + S + A;
|
ut64 result = ((ut64)old_val) + S + A;
|
||||||
rz_buf_write_ble32_at(buf_patched, patch_addr, (ut32)result, big_endian);
|
success = rz_buf_write_ble32_at(buf_patched, patch_addr, (ut32)result, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case R_RISCV_ADD64: {
|
case R_RISCV_ADD64: {
|
||||||
ut64 old_val = 0;
|
ut64 old_val = 0;
|
||||||
rz_buf_read_ble64_at(buf_patched, patch_addr, &old_val, big_endian);
|
bool success = rz_buf_read_ble64_at(buf_patched, patch_addr, &old_val, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
ut64 result = old_val + S + A;
|
ut64 result = old_val + S + A;
|
||||||
rz_buf_write_ble64_at(buf_patched, patch_addr, result, big_endian);
|
success = rz_buf_write_ble64_at(buf_patched, patch_addr, result, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case R_RISCV_SUB8: {
|
case R_RISCV_SUB8: {
|
||||||
ut8 old_val = 0;
|
ut8 old_val = 0;
|
||||||
rz_buf_read_ble8_at(buf_patched, patch_addr, &old_val, big_endian);
|
bool success = rz_buf_read_ble8_at(buf_patched, patch_addr, &old_val, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
ut64 result = ((ut64)old_val) - S - A;
|
ut64 result = ((ut64)old_val) - S - A;
|
||||||
unsigned long long addr = patch_addr;
|
unsigned long long addr = patch_addr;
|
||||||
rz_buf_write_ble8_offset(buf_patched, &addr, (ut8)result, big_endian);
|
success = rz_buf_write_ble8_offset(buf_patched, &addr, (ut8)result, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case R_RISCV_SUB16: {
|
case R_RISCV_SUB16: {
|
||||||
ut16 old_val = 0;
|
ut16 old_val = 0;
|
||||||
rz_buf_read_ble16_at(buf_patched, patch_addr, &old_val, big_endian);
|
bool success = rz_buf_read_ble16_at(buf_patched, patch_addr, &old_val, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
ut64 result = ((ut64)old_val) - S - A;
|
ut64 result = ((ut64)old_val) - S - A;
|
||||||
rz_buf_write_ble16_at(buf_patched, patch_addr, (ut16)result, big_endian);
|
success = rz_buf_write_ble16_at(buf_patched, patch_addr, (ut16)result, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case R_RISCV_SUB32: {
|
case R_RISCV_SUB32: {
|
||||||
ut32 old_val = 0;
|
ut32 old_val = 0;
|
||||||
rz_buf_read_ble32_at(buf_patched, patch_addr, &old_val, big_endian);
|
bool success = rz_buf_read_ble32_at(buf_patched, patch_addr, &old_val, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
ut64 result = ((ut64)old_val) - S - A;
|
ut64 result = ((ut64)old_val) - S - A;
|
||||||
rz_buf_write_ble32_at(buf_patched, patch_addr, (ut32)result, big_endian);
|
success = rz_buf_write_ble32_at(buf_patched, patch_addr, (ut32)result, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case R_RISCV_SUB64: {
|
case R_RISCV_SUB64: {
|
||||||
ut64 old_val = 0;
|
ut64 old_val = 0;
|
||||||
rz_buf_read_ble64_at(buf_patched, patch_addr, &old_val, big_endian);
|
bool success = rz_buf_read_ble64_at(buf_patched, patch_addr, &old_val, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
ut64 result = ((ut64)old_val) - S - A;
|
ut64 result = ((ut64)old_val) - S - A;
|
||||||
rz_buf_write_ble64_at(buf_patched, patch_addr, result, big_endian);
|
success = rz_buf_write_ble64_at(buf_patched, patch_addr, result, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case R_RISCV_SET8: {
|
case R_RISCV_SET8: {
|
||||||
val = S + A;
|
val = S + A;
|
||||||
unsigned long long addr = patch_addr;
|
unsigned long long addr = patch_addr;
|
||||||
rz_buf_write_ble8_offset(buf_patched, &addr, (ut8)val, big_endian);
|
bool success = rz_buf_write_ble8_offset(buf_patched, &addr, (ut8)val, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_RISCV_SET16: {
|
case R_RISCV_SET16: {
|
||||||
val = S + A;
|
val = S + A;
|
||||||
rz_buf_write_ble16_at(buf_patched, patch_addr, (ut16)val, big_endian);
|
bool success = rz_buf_write_ble16_at(buf_patched, patch_addr, (ut16)val, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_RISCV_SET32: {
|
case R_RISCV_SET32: {
|
||||||
val = S + A;
|
val = S + A;
|
||||||
rz_buf_write_ble32_at(buf_patched, patch_addr, (ut32)val, big_endian);
|
bool success = rz_buf_write_ble32_at(buf_patched, patch_addr, (ut32)val, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case R_RISCV_SET6:
|
case R_RISCV_SET6:
|
||||||
case R_RISCV_SUB6: {
|
case R_RISCV_SUB6: {
|
||||||
ut8 old_val = 0;
|
ut8 old_val = 0;
|
||||||
rz_buf_read_ble8_at(buf_patched, patch_addr, &old_val, big_endian);
|
bool success = rz_buf_read_ble8_at(buf_patched, patch_addr, &old_val, big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
val = S + A;
|
val = S + A;
|
||||||
ut8 result = (rel_type == R_RISCV_SET6) ? val : ((old_val & 0x3F) - val);
|
ut8 result = (rel_type == R_RISCV_SET6) ? val : ((old_val & 0x3F) - val);
|
||||||
rz_buf_write_ble8_at(buf_patched, patch_addr, (old_val & 0xC0) | (result & 0x3F), big_endian);
|
success = rz_buf_write_ble8_at(buf_patched, patch_addr, (old_val & 0xC0) | (result & 0x3F), big_endian);
|
||||||
|
rz_return_if_fail(success);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,11 @@
|
||||||
"""
|
"""
|
||||||
RISC-V Extension Trie-Based Parser Generator
|
RISC-V Extension Trie-Based Parser Generator
|
||||||
|
|
||||||
Given a list of RISCV_FeatureStdExt* enums, generates C code that:
|
Given a list of RISCV_FeatureStdExt* enums (by passing arch/RISCV/RISCVGenSubtargetInfo.inc), it generates C code that:
|
||||||
1. Parses extension names using a trie data structure
|
1. Parses extension names using a trie data structure (to efficiently exploit common prefixes)
|
||||||
2. ORs the corresponding enum value with a running accumulator
|
2. Increments the current index given to the parsing routine and returns an enum representing the extension parsed
|
||||||
3. Includes an ASCII art tree visualization of the trie
|
3. Includes an ASCII art tree visualization of the trie
|
||||||
4. Annotates branches with parse state
|
4. Annotates parsing control flow branches with parse state
|
||||||
5. Uses macros to reduce boilerplate
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -130,15 +129,17 @@ def generate_c_code(trie: Trie, extensions: List[Tuple[str, str]]) -> str:
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
# Non-leaf node - check if this is also a valid end point
|
# Non-leaf node - check if this is also a valid end point
|
||||||
if node.enum_name:
|
|
||||||
lines.append(f"{indent}STOP_WITH_MATCH({node.enum_name});")
|
|
||||||
lines.append("")
|
|
||||||
|
|
||||||
# Process children - add state comment only before branching
|
|
||||||
sorted_children = sorted(node.children.items())
|
sorted_children = sorted(node.children.items())
|
||||||
expected_chars = [c for c, _ in sorted_children]
|
expected_chars = [c for c, _ in sorted_children]
|
||||||
expected_str = "".join(expected_chars)
|
expected_str = "".join(expected_chars)
|
||||||
|
|
||||||
|
if node.enum_name:
|
||||||
|
lines.append(
|
||||||
|
f'{indent}DO_IF_NOT_ANY_OF("{expected_str}", STOP_WITH_MATCH({node.enum_name}));'
|
||||||
|
)
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
|
# Process children - add state comment only before branching
|
||||||
lines.append(f"{indent}/* State: '{path}' expecting [{expected_str}] */")
|
lines.append(f"{indent}/* State: '{path}' expecting [{expected_str}] */")
|
||||||
|
|
||||||
for i, (char, child) in enumerate(sorted_children):
|
for i, (char, child) in enumerate(sorted_children):
|
||||||
|
|
@ -184,8 +185,8 @@ def generate_c_code(trie: Trie, extensions: List[Tuple[str, str]]) -> str:
|
||||||
" * Generated from arch/RISCV/RISCVGenSubtargetInfo.inc in Capstone sources \n"
|
" * Generated from arch/RISCV/RISCVGenSubtargetInfo.inc in Capstone sources \n"
|
||||||
)
|
)
|
||||||
full_code += " * \n"
|
full_code += " * \n"
|
||||||
full_code += " * This function parses a single RISC-V extension name and ORs the corresponding\n"
|
full_code += " * This function parses a single RISC-V extension name and returns the corresponding\n"
|
||||||
full_code += " * feature flags with an accumulator 'mode'.\n"
|
full_code += " * feature flag.\n"
|
||||||
full_code += " * \n"
|
full_code += " * \n"
|
||||||
full_code += " * Trie Diagram:\n"
|
full_code += " * Trie Diagram:\n"
|
||||||
full_code += tree_comment + "\n"
|
full_code += tree_comment + "\n"
|
||||||
|
|
@ -271,6 +272,21 @@ def generate_c_code(trie: Trie, extensions: List[Tuple[str, str]]) -> str:
|
||||||
full_code += " } \\\n"
|
full_code += " } \\\n"
|
||||||
full_code += " } while (0)\n\n"
|
full_code += " } while (0)\n\n"
|
||||||
|
|
||||||
|
full_code += "/* Macro: Conditionally invoke a macro if the current character is not on a given blacklist*/\n"
|
||||||
|
full_code += "#define DO_IF_NOT_ANY_OF(blacklist, thing) \\\n"
|
||||||
|
full_code += " do { \\\n"
|
||||||
|
full_code += " bool __will_do__ = true; \\\n"
|
||||||
|
full_code += " char *__curr__ = blacklist; \\\n"
|
||||||
|
full_code += " while (*__curr__ != '\\0') { \\\n"
|
||||||
|
full_code += " if (*p == *__curr__++) { \\\n"
|
||||||
|
full_code += " __will_do__ = false; \\\n"
|
||||||
|
full_code += " } \\\n"
|
||||||
|
full_code += " } \\\n"
|
||||||
|
full_code += " if (__will_do__) { \\\n"
|
||||||
|
full_code += " thing; \\\n"
|
||||||
|
full_code += " } \\\n"
|
||||||
|
full_code += " } while (0)\n\n"
|
||||||
|
|
||||||
full_code += "/**\n"
|
full_code += "/**\n"
|
||||||
full_code += (
|
full_code += (
|
||||||
" * Main parse routine: Try to consume a RISC-V extension name "
|
" * Main parse routine: Try to consume a RISC-V extension name "
|
||||||
|
|
@ -282,10 +298,7 @@ def generate_c_code(trie: Trie, extensions: List[Tuple[str, str]]) -> str:
|
||||||
" * @param idx: Pointer to current index "
|
" * @param idx: Pointer to current index "
|
||||||
"(will be updated to show consumed length)\n"
|
"(will be updated to show consumed length)\n"
|
||||||
)
|
)
|
||||||
full_code += (
|
full_code += " * @param mode: Pointer to the feature result"
|
||||||
" * @param mode: Pointer to the feature accumulator "
|
|
||||||
"(will be ORed with the feature flag if extension found)\n"
|
|
||||||
)
|
|
||||||
full_code += " * @return: Parse result indicating why parsing stopped and whether a match was found\n"
|
full_code += " * @return: Parse result indicating why parsing stopped and whether a match was found\n"
|
||||||
full_code += " * \n"
|
full_code += " * \n"
|
||||||
full_code += " * Stopping conditions:\n"
|
full_code += " * Stopping conditions:\n"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue