| 221 | } |
| 222 | |
| 223 | ELFIO::section* read_sections(N64Recomp::Context& context, ELFIO::section*& mdebug_section_out, const N64Recomp::ElfParsingConfig& elf_config, const ELFIO::elfio& elf_file) { |
| 224 | ELFIO::section* symtab_section = nullptr; |
| 225 | std::vector<SegmentEntry> segments{}; |
| 226 | segments.resize(elf_file.segments.size()); |
| 227 | bool has_reference_symbols = context.has_reference_symbols(); |
| 228 | |
| 229 | // Copy the data for each segment into the segment entry list |
| 230 | for (size_t segment_index = 0; segment_index < elf_file.segments.size(); segment_index++) { |
| 231 | const auto& segment = *elf_file.segments[segment_index]; |
| 232 | segments[segment_index].data_offset = segment.get_offset(); |
| 233 | segments[segment_index].physical_address = segment.get_physical_address(); |
| 234 | segments[segment_index].memory_size = segment.get_file_size(); |
| 235 | } |
| 236 | |
| 237 | //// Sort the segments by physical address |
| 238 | //std::sort(segments.begin(), segments.end(), |
| 239 | // [](const SegmentEntry& lhs, const SegmentEntry& rhs) { |
| 240 | // return lhs.data_offset < rhs.data_offset; |
| 241 | // } |
| 242 | //); |
| 243 | |
| 244 | std::unordered_map<std::string, ELFIO::section*> reloc_sections_by_name; |
| 245 | std::unordered_map<std::string, ELFIO::section*> bss_sections_by_name; |
| 246 | |
| 247 | // First pass over the sections to find the load addresses and track the minimum load address value. This mimics the objcopy raw binary output behavior. |
| 248 | uint32_t min_load_address = (uint32_t)-1; |
| 249 | for (const auto& section : elf_file.sections) { |
| 250 | auto& section_out = context.sections[section->get_index()]; |
| 251 | ELFIO::Elf_Word type = section->get_type(); |
| 252 | ELFIO::Elf_Xword flags = section->get_flags(); |
| 253 | ELFIO::Elf_Xword section_size = section->get_size(); |
| 254 | |
| 255 | // Check if this section will end up in the ROM. It must not be a nobits (NOLOAD) type, must have the alloc flag set and must have a nonzero size. |
| 256 | if (type != ELFIO::SHT_NOBITS && (flags & ELFIO::SHF_ALLOC) && section_size != 0) { |
| 257 | std::optional<size_t> segment_index = get_segment(segments, section_size, section->get_offset()); |
| 258 | if (!segment_index.has_value()) { |
| 259 | fmt::print(stderr, "Could not find segment that section {} belongs to!\n", section->get_name()); |
| 260 | return nullptr; |
| 261 | } |
| 262 | |
| 263 | const SegmentEntry& segment = segments[segment_index.value()]; |
| 264 | // Calculate the load address of the section based on that of the segment. |
| 265 | // This will get modified afterwards in the next pass to offset by the minimum load address. |
| 266 | section_out.rom_addr = segment.physical_address + (section->get_offset() - segment.data_offset); |
| 267 | // Track the minimum load address. |
| 268 | min_load_address = std::min(min_load_address, section_out.rom_addr); |
| 269 | } |
| 270 | else { |
| 271 | // Otherwise mark this section as having an invalid rom address |
| 272 | section_out.rom_addr = (uint32_t)-1; |
| 273 | } |
| 274 | } |
| 275 | |
| 276 | // Iterate over every section to record rom addresses and find the symbol table |
| 277 | for (const auto& section : elf_file.sections) { |
| 278 | auto& section_out = context.sections[section->get_index()]; |
| 279 | //fmt::print(" {}: {} @ 0x{:08X}, 0x{:08X}\n", section->get_index(), section->get_name(), section->get_address(), context.rom.size()); |
| 280 | // Set the rom address of this section to the current accumulated ROM size |
no test coverage detected