Skip to content

Commit 983a07b

Browse files
authored
Merge pull request #308 from riscv/eclipse_memory_read
Fixing Eclipse block memory read
2 parents 60c37e1 + 9703c00 commit 983a07b

File tree

2 files changed

+82
-45
lines changed

2 files changed

+82
-45
lines changed

src/server/gdb_server.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ static int gdb_put_packet_inner(struct connection *connection,
390390
break;
391391
}
392392

393-
LOG_WARNING("Discard unexpected char %c", reply);
393+
LOG_DEBUG("Discard unexpected char %c", reply);
394394
}
395395
#endif
396396

src/target/riscv/riscv-013.c

Lines changed: 81 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2040,53 +2040,13 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
20402040
* Read the requested memory, taking care to execute every read exactly once,
20412041
* even if cmderr=busy is encountered.
20422042
*/
2043-
static int read_memory_progbuf(struct target *target, target_addr_t address,
2043+
static int read_memory_progbuf_inner(struct target *target, target_addr_t address,
20442044
uint32_t size, uint32_t count, uint8_t *buffer)
20452045
{
20462046
RISCV013_INFO(info);
20472047

20482048
int result = ERROR_OK;
20492049

2050-
LOG_DEBUG("reading %d words of %d bytes from 0x%" TARGET_PRIxADDR, count,
2051-
size, address);
2052-
2053-
select_dmi(target);
2054-
2055-
/* s0 holds the next address to write to
2056-
* s1 holds the next data value to write
2057-
*/
2058-
uint64_t s0, s1;
2059-
if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK)
2060-
return ERROR_FAIL;
2061-
if (register_read(target, &s1, GDB_REGNO_S1) != ERROR_OK)
2062-
return ERROR_FAIL;
2063-
2064-
if (execute_fence(target) != ERROR_OK)
2065-
return ERROR_FAIL;
2066-
2067-
/* Write the program (load, increment) */
2068-
struct riscv_program program;
2069-
riscv_program_init(&program, target);
2070-
switch (size) {
2071-
case 1:
2072-
riscv_program_lbr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
2073-
break;
2074-
case 2:
2075-
riscv_program_lhr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
2076-
break;
2077-
case 4:
2078-
riscv_program_lwr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
2079-
break;
2080-
default:
2081-
LOG_ERROR("Unsupported size: %d", size);
2082-
return ERROR_FAIL;
2083-
}
2084-
riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size);
2085-
2086-
if (riscv_program_ebreak(&program) != ERROR_OK)
2087-
return ERROR_FAIL;
2088-
riscv_program_write(&program);
2089-
20902050
/* Write address to S0, and execute buffer. */
20912051
result = register_write_direct(target, GDB_REGNO_S0, address);
20922052
if (result != ERROR_OK)
@@ -2214,7 +2174,7 @@ static int read_memory_progbuf(struct target *target, target_addr_t address,
22142174
1 << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET);
22152175
break;
22162176
default:
2217-
LOG_ERROR("error when reading memory, abstractcs=0x%08lx", (long)abstractcs);
2177+
LOG_DEBUG("error when reading memory, abstractcs=0x%08lx", (long)abstractcs);
22182178
riscv013_clear_abstract_error(target);
22192179
riscv_batch_free(batch);
22202180
result = ERROR_FAIL;
@@ -2272,13 +2232,90 @@ static int read_memory_progbuf(struct target *target, target_addr_t address,
22722232
write_to_buf(buffer + receive_addr - address, value, size);
22732233
log_memory_access(receive_addr, value, size, true);
22742234

2275-
riscv_set_register(target, GDB_REGNO_S0, s0);
2276-
riscv_set_register(target, GDB_REGNO_S1, s1);
22772235
return ERROR_OK;
22782236

22792237
error:
22802238
dmi_write(target, DMI_ABSTRACTAUTO, 0);
22812239

2240+
return result;
2241+
}
2242+
2243+
/**
2244+
* Read the requested memory, silently handling memory access errors.
2245+
*/
2246+
static int read_memory_progbuf(struct target *target, target_addr_t address,
2247+
uint32_t size, uint32_t count, uint8_t *buffer)
2248+
{
2249+
int result = ERROR_OK;
2250+
2251+
LOG_DEBUG("reading %d words of %d bytes from 0x%" TARGET_PRIxADDR, count,
2252+
size, address);
2253+
2254+
select_dmi(target);
2255+
2256+
memset(buffer, 0, count*size);
2257+
2258+
/* s0 holds the next address to write to
2259+
* s1 holds the next data value to write
2260+
*/
2261+
uint64_t s0, s1;
2262+
if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK)
2263+
return ERROR_FAIL;
2264+
if (register_read(target, &s1, GDB_REGNO_S1) != ERROR_OK)
2265+
return ERROR_FAIL;
2266+
2267+
if (execute_fence(target) != ERROR_OK)
2268+
return ERROR_FAIL;
2269+
2270+
/* Write the program (load, increment) */
2271+
struct riscv_program program;
2272+
riscv_program_init(&program, target);
2273+
switch (size) {
2274+
case 1:
2275+
riscv_program_lbr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
2276+
break;
2277+
case 2:
2278+
riscv_program_lhr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
2279+
break;
2280+
case 4:
2281+
riscv_program_lwr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0);
2282+
break;
2283+
default:
2284+
LOG_ERROR("Unsupported size: %d", size);
2285+
return ERROR_FAIL;
2286+
}
2287+
riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size);
2288+
2289+
if (riscv_program_ebreak(&program) != ERROR_OK)
2290+
return ERROR_FAIL;
2291+
riscv_program_write(&program);
2292+
2293+
result = read_memory_progbuf_inner(target, address, size, count, buffer);
2294+
2295+
if (result != ERROR_OK) {
2296+
/* The full read did not succeed, so we will try to read each word individually. */
2297+
/* This will not be fast, but reading outside actual memory is a special case anyway. */
2298+
/* It will make the toolchain happier, especially Eclipse Memory View as it reads ahead. */
2299+
target_addr_t address_i = address;
2300+
uint32_t size_i = size;
2301+
uint32_t count_i = 1;
2302+
uint8_t *buffer_i = buffer;
2303+
2304+
for (uint32_t i = 0; i < count; i++, address_i += size_i, buffer_i += size_i) {
2305+
result = read_memory_progbuf_inner(target, address_i, size_i, count_i, buffer_i);
2306+
2307+
/* The read of a single word failed, so we will just return 0 for that instead */
2308+
if (result != ERROR_OK) {
2309+
LOG_DEBUG("error reading single word of %d bytes from 0x%" TARGET_PRIxADDR,
2310+
size_i, address_i);
2311+
2312+
uint64_t value_i = 0;
2313+
write_to_buf(buffer_i, value_i, size_i);
2314+
}
2315+
}
2316+
result = ERROR_OK;
2317+
}
2318+
22822319
riscv_set_register(target, GDB_REGNO_S0, s0);
22832320
riscv_set_register(target, GDB_REGNO_S1, s1);
22842321
return result;

0 commit comments

Comments
 (0)