| 1490 |
1513 |
|
if (fseek(file, 0, SEEK_END) != 0) { |
| 1491 |
1514 |
|
fclose(file); |
| 1492 |
1515 |
|
bail("failed to seek program '%s'", filepath); |
| 1493 |
1516 |
|
} |
| 1494 |
1517 |
|
long size = ftell(file); |
| 1495 |
|
- |
if (size <= 0 || size > PROGRAM_SIZE) { |
|
1518 |
+ |
if (size <= 0) { |
| 1496 |
1519 |
|
fclose(file); |
| 1497 |
|
- |
bail( |
| 1498 |
|
- |
"invalid file size: %ld; maximum program size is %d bytes", |
| 1499 |
|
- |
size, |
| 1500 |
|
- |
PROGRAM_SIZE |
| 1501 |
|
- |
); |
| 1502 |
|
- |
} |
| 1503 |
|
- |
if (program_base + (u32)size > DATA_MEMORY_START) { |
| 1504 |
|
- |
fclose(file); |
| 1505 |
|
- |
bail("text section exceeds available program memory"); |
|
1520 |
+ |
bail("invalid file size: %ld", size); |
| 1506 |
1521 |
|
} |
| 1507 |
1522 |
|
if (fseek(file, 0, SEEK_SET) != 0) { |
| 1508 |
1523 |
|
fclose(file); |
| 1509 |
1524 |
|
bail("failed to rewind program '%s'", filepath); |
| 1510 |
1525 |
|
} |
| 1511 |
1526 |
|
|
| 1512 |
|
- |
usize read = fread(&memory[program_base], 1, size, file); |
| 1513 |
|
- |
fclose(file); |
| 1514 |
|
- |
if (read != (size_t)size) |
| 1515 |
|
- |
bail("could not read entire file"); |
| 1516 |
|
- |
|
| 1517 |
|
- |
program_bytes = (u32)size; |
| 1518 |
|
- |
cpu->programsize = (u32)size / sizeof(instr_t); |
| 1519 |
|
- |
|
| 1520 |
1527 |
|
u32 data_limit = DATA_MEMORY_START + g_opts.data_memory_size; |
| 1521 |
1528 |
|
if (data_limit > g_opts.memory_size) |
| 1522 |
1529 |
|
data_limit = g_opts.memory_size; |
| 1523 |
1530 |
|
|
| 1524 |
|
- |
data_bytes = load_section( |
| 1525 |
|
- |
filepath, "rw.data", DATA_MEMORY_START, data_limit, "rw.data" |
| 1526 |
|
- |
); |
| 1527 |
|
- |
cpu->pc = program_base; |
|
1531 |
+ |
u8 header[IMAGE_HEADER_SIZE]; |
|
1532 |
+ |
size_t header_read = fread(header, 1, sizeof(header), file); |
|
1533 |
+ |
bool is_image = |
|
1534 |
+ |
header_read >= sizeof(u32) && decode_u32_le(header) == IMAGE_MAGIC; |
|
1535 |
+ |
|
|
1536 |
+ |
if (is_image) { |
|
1537 |
+ |
if (header_read != sizeof(header)) { |
|
1538 |
+ |
fclose(file); |
|
1539 |
+ |
bail("truncated Radiance image header"); |
|
1540 |
+ |
} |
|
1541 |
+ |
|
|
1542 |
+ |
u32 version = decode_u32_le(&header[4]); |
|
1543 |
+ |
program_bytes = decode_u32_le(&header[8]); |
|
1544 |
+ |
rodata_bytes = decode_u32_le(&header[12]); |
|
1545 |
+ |
data_bytes = decode_u32_le(&header[16]); |
|
1546 |
+ |
|
|
1547 |
+ |
if (version != IMAGE_VERSION) { |
|
1548 |
+ |
fclose(file); |
|
1549 |
+ |
bail("unsupported Radiance image version: %u", version); |
|
1550 |
+ |
} |
|
1551 |
+ |
if (program_bytes == 0 || program_bytes % sizeof(instr_t) != 0) { |
|
1552 |
+ |
fclose(file); |
|
1553 |
+ |
bail( |
|
1554 |
+ |
"invalid text section size in Radiance image: %u", program_bytes |
|
1555 |
+ |
); |
|
1556 |
+ |
} |
|
1557 |
+ |
u64 image_size = |
|
1558 |
+ |
(u64)IMAGE_HEADER_SIZE + program_bytes + rodata_bytes + data_bytes; |
|
1559 |
+ |
if (image_size != (u64)size) { |
|
1560 |
+ |
fclose(file); |
|
1561 |
+ |
bail( |
|
1562 |
+ |
"Radiance image size does not match header: file has %ld " |
|
1563 |
+ |
"bytes, header requires %llu", |
|
1564 |
+ |
size, |
|
1565 |
+ |
(unsigned long long)image_size |
|
1566 |
+ |
); |
|
1567 |
+ |
} |
|
1568 |
+ |
if (program_bytes > PROGRAM_SIZE) { |
|
1569 |
+ |
fclose(file); |
|
1570 |
+ |
bail( |
|
1571 |
+ |
"text section too large: %u bytes; maximum is %u bytes", |
|
1572 |
+ |
program_bytes, |
|
1573 |
+ |
PROGRAM_SIZE |
|
1574 |
+ |
); |
|
1575 |
+ |
} |
|
1576 |
+ |
if ((u64)DATA_RO_OFFSET + rodata_bytes > DATA_MEMORY_START) { |
|
1577 |
+ |
fclose(file); |
|
1578 |
+ |
bail("read-only data section exceeds available program memory"); |
|
1579 |
+ |
} |
|
1580 |
+ |
program_base = align(DATA_RO_OFFSET + rodata_bytes, WORD_SIZE); |
|
1581 |
+ |
if ((u64)program_base + program_bytes > DATA_MEMORY_START) { |
|
1582 |
+ |
fclose(file); |
|
1583 |
+ |
bail("text section exceeds available program memory"); |
|
1584 |
+ |
} |
|
1585 |
+ |
if ((u64)DATA_MEMORY_START + data_bytes > data_limit) { |
|
1586 |
+ |
fclose(file); |
|
1587 |
+ |
bail("read-write data section exceeds available data memory"); |
|
1588 |
+ |
} |
|
1589 |
+ |
|
|
1590 |
+ |
load_image_section(file, program_base, program_bytes, "text"); |
|
1591 |
+ |
load_image_section( |
|
1592 |
+ |
file, DATA_RO_OFFSET, rodata_bytes, "read-only data" |
|
1593 |
+ |
); |
|
1594 |
+ |
load_image_section( |
|
1595 |
+ |
file, DATA_MEMORY_START, data_bytes, "read-write data" |
|
1596 |
+ |
); |
|
1597 |
+ |
} else { |
|
1598 |
+ |
/* Legacy flat binaries use optional sidecar data files. */ |
|
1599 |
+ |
rewind(file); |
|
1600 |
+ |
rodata_bytes = load_section( |
|
1601 |
+ |
filepath, "ro.data", DATA_RO_OFFSET, DATA_MEMORY_START, "ro.data" |
|
1602 |
+ |
); |
|
1603 |
+ |
program_base = align(DATA_RO_OFFSET + rodata_bytes, WORD_SIZE); |
|
1604 |
+ |
if (size > PROGRAM_SIZE) { |
|
1605 |
+ |
fclose(file); |
|
1606 |
+ |
bail( |
|
1607 |
+ |
"invalid file size: %ld; maximum program size is %d bytes", |
|
1608 |
+ |
size, |
|
1609 |
+ |
PROGRAM_SIZE |
|
1610 |
+ |
); |
|
1611 |
+ |
} |
|
1612 |
+ |
if ((u64)program_base + (u32)size > DATA_MEMORY_START) { |
|
1613 |
+ |
fclose(file); |
|
1614 |
+ |
bail("text section exceeds available program memory"); |
|
1615 |
+ |
} |
|
1616 |
+ |
program_bytes = (u32)size; |
|
1617 |
+ |
load_image_section(file, program_base, program_bytes, "program"); |
|
1618 |
+ |
data_bytes = load_section( |
|
1619 |
+ |
filepath, "rw.data", DATA_MEMORY_START, data_limit, "rw.data" |
|
1620 |
+ |
); |
|
1621 |
+ |
} |
|
1622 |
+ |
fclose(file); |
|
1623 |
+ |
|
|
1624 |
+ |
cpu->programsize = program_bytes / sizeof(instr_t); |
|
1625 |
+ |
cpu->pc = program_base; |
| 1528 |
1626 |
|
} |
| 1529 |
1627 |
|
|
| 1530 |
1628 |
|
/* Execute a single instruction. */ |
| 1531 |
1629 |
|
static void cpu_execute(struct cpu *cpu, enum display display, bool headless) { |
| 1532 |
1630 |
|
if (cpu_out_of_bounds(cpu)) { |