Reads a data symbol file and adds its contents into this context's reference data symbols.
| 729 | |
| 730 | // Reads a data symbol file and adds its contents into this context's reference data symbols. |
| 731 | bool N64Recomp::Context::read_data_reference_syms(const std::filesystem::path& data_syms_file_path) { |
| 732 | try { |
| 733 | const toml::table data_syms_file_data = toml::parse_file(data_syms_file_path.u8string()); |
| 734 | const toml::node_view data_sections_value = data_syms_file_data["section"]; |
| 735 | |
| 736 | if (!data_sections_value.is_array()) { |
| 737 | return false; |
| 738 | } |
| 739 | |
| 740 | // Create a mapping of rom address to section to ensure that the same section indexes are used for both function and data reference symbols. |
| 741 | std::unordered_map<uint32_t, uint16_t> ref_section_indices_by_vrom; |
| 742 | |
| 743 | for (uint16_t section_index = 0; section_index < reference_sections.size(); section_index++) { |
| 744 | ref_section_indices_by_vrom.emplace(reference_sections[section_index].rom_addr, section_index); |
| 745 | } |
| 746 | |
| 747 | const toml::array* data_sections = data_sections_value.as_array(); |
| 748 | |
| 749 | data_sections->for_each([this, &ref_section_indices_by_vrom](auto&& el) { |
| 750 | if constexpr (toml::is_table<decltype(el)>) { |
| 751 | std::optional<uint64_t> rom_addr = el["rom"].template value<uint64_t>(); |
| 752 | std::optional<uint32_t> vram_addr = el["vram"].template value<uint32_t>(); |
| 753 | std::optional<uint32_t> size = el["size"].template value<uint32_t>(); |
| 754 | std::optional<std::string> name = el["name"].template value<std::string>(); |
| 755 | |
| 756 | if (!vram_addr.has_value() || !size.has_value() || !name.has_value()) { |
| 757 | throw toml::parse_error("Section entry missing required field(s)", el.source()); |
| 758 | } |
| 759 | |
| 760 | uint16_t ref_section_index; |
| 761 | if (!rom_addr.has_value()) { |
| 762 | ref_section_index = N64Recomp::SectionAbsolute; // Non-relocatable bss section or absolute symbols, mark this as an absolute symbol |
| 763 | } |
| 764 | else if (rom_addr.value() > 0xFFFFFFFF) { |
| 765 | throw toml::parse_error("Section has invalid ROM address", el.source()); |
| 766 | } |
| 767 | else { |
| 768 | // Find the matching section from the function reference symbol file to ensure |
| 769 | auto find_section_it = ref_section_indices_by_vrom.find(rom_addr.value()); |
| 770 | if (find_section_it != ref_section_indices_by_vrom.end()) { |
| 771 | ref_section_index = find_section_it->second; |
| 772 | } |
| 773 | else { |
| 774 | ref_section_index = N64Recomp::SectionAbsolute; // Not in the function symbol reference file, so this section can be treated as non-relocatable. |
| 775 | } |
| 776 | } |
| 777 | |
| 778 | static ReferenceSection dummy_absolute_section { |
| 779 | .rom_addr = 0, |
| 780 | .ram_addr = 0, |
| 781 | .size = 0, |
| 782 | .relocatable = 0 |
| 783 | }; |
| 784 | const ReferenceSection& ref_section = ref_section_index == N64Recomp::SectionAbsolute ? dummy_absolute_section : this->reference_sections[ref_section_index]; |
| 785 | |
| 786 | // Sanity check this section against the matching one in the function reference symbol file if one exists. |
| 787 | if (ref_section_index != N64Recomp::SectionAbsolute) { |
| 788 | if (ref_section.ram_addr != vram_addr.value()) { |
no test coverage detected