@@ -153,38 +153,47 @@ bool PROMImage::load_from_buffer(const u8 *data, size_t size) {
153153}
154154
155155bool PROMImage::parse_shdr_sections () {
156- // The first SHDR header is at offset 8 (after initial branch + nop)
157- constexpr size_t kFirstShdrOffset = 8 ;
158- constexpr size_t kShdrHeaderSize = 64 ; // SHDR_SIZE from definitions.h
156+ constexpr size_t kShdrHeaderSize =
157+ 68 ; // Actual SHDR header size (matches decompiled PROM structure)
158+ constexpr u32 kShdrMagic = 0x52444853 ; // "SHDR" little-endian
159159
160- if (image_.size () < kFirstShdrOffset + kShdrHeaderSize ) {
160+ if (image_.size () < kShdrHeaderSize + 8 ) {
161161 O2EMU_LOG_ERROR (" PROM image too small for SHDR header" );
162162 return false ;
163163 }
164164
165- size_t offset = kFirstShdrOffset ;
166165 sections_.clear ();
167166
168- while (offset + kShdrHeaderSize <= image_.size ()) {
169- const SHDRSectionHeader *shdr =
170- reinterpret_cast <const SHDRSectionHeader *>(image_.data () + offset);
171-
172- // Check magic: "SHDR" = 0x53484452 (big-endian), reads as 0x52444853 on LE
173- if (shdr->magic != 0x52444853 ) {
174- // Not a valid SHDR header, stop parsing
175- break ;
167+ // Scan the entire file for SHDR magic at offset+8 from section starts
168+ // Each section has: 8-byte prefix, then 64-byte SHDR header at
169+ // section_offset+8
170+ for (size_t file_offset = 8 ; file_offset + kShdrHeaderSize <= image_.size ();
171+ ++file_offset) {
172+ // Check for SHDR magic at this offset
173+ const u32 *magic_ptr =
174+ reinterpret_cast <const u32 *>(image_.data () + file_offset);
175+ if (*magic_ptr != kShdrMagic ) {
176+ continue ;
176177 }
177178
179+ // Found SHDR header at file_offset
180+ // Section starts at file_offset - 8
181+ size_t section_start = file_offset - 8 ;
182+
183+ const SHDRSectionHeader *shdr = reinterpret_cast <const SHDRSectionHeader *>(
184+ image_.data () + file_offset);
185+
178186 // Extract section info
179187 SectionInfo info;
180188 info.type = shdr->section_type ;
181- info.offset = offset + kShdrHeaderSize ;
189+ info.offset = section_start ;
182190 info.size = shdr->section_len ;
183191
184192 // Validate section bounds
185193 if (info.offset + info.size > image_.size ()) {
186- O2EMU_LOG_WARN_F (" Section at offset %zu exceeds file size" , offset);
187- break ;
194+ O2EMU_LOG_WARN_F (" Section at offset %zu exceeds file size (size=%u)" ,
195+ info.offset , info.size );
196+ continue ;
188197 }
189198
190199 // Extract name and version (null-terminated)
@@ -199,17 +208,21 @@ bool PROMImage::parse_shdr_sections() {
199208
200209 sections_.push_back (info);
201210
202- // Move to next SHDR header (aligned to 64 bytes)
203- offset += kShdrHeaderSize + info.size ;
204- // Align to 64-byte boundary
205- offset = (offset + kShdrHeaderSize - 1 ) & ~(kShdrHeaderSize - 1 );
211+ // Skip ahead to after this section to avoid re-detecting the same SHDR
212+ file_offset = info.offset + info.size ;
206213 }
207214
208215 if (sections_.empty ()) {
209216 O2EMU_LOG_ERROR (" No valid SHDR sections found" );
210217 return false ;
211218 }
212219
220+ // Sort sections by offset (should already be in order, but just in case)
221+ std::sort (sections_.begin (), sections_.end (),
222+ [](const SectionInfo &a, const SectionInfo &b) {
223+ return a.offset < b.offset ;
224+ });
225+
213226 O2EMU_LOG_INFO_F (" Parsed %zu SHDR sections" , sections_.size ());
214227 return true ;
215228}
0 commit comments