mborgerson / pyxbe

Python 3 library to read and write XBE files, the executable file format for the original Xbox game console
http://pyxbe.readthedocs.io/
MIT License
18 stars 10 forks source link

Map virtual address error on retail XBE #11

Closed LoveMHz closed 2 years ago

LoveMHz commented 2 years ago

While scanning through my collection of games I came across two troublesome retail XBEs. I haven't had a chance to dig into the issue, but I thought it was best to file an issue nonetheless.

Metal Slug 4 (USA, Europe) (En,Ja,Fr,De,Es,It)/Default.xbe Metal Slug 4 (Japan)/Default.xbe

pip3 show pyxbe                        
Name: pyxbe
Version: 0.0.2
File "/home/dustin/.local/lib/python3.9/site-packages/xbe/__init__.py", line 930, in from_file
    return cls(data)
  File "/home/dustin/.local/lib/python3.9/site-packages/xbe/__init__.py", line 614, in __init__
    self._init_from_data(data)
  File "/home/dustin/.local/lib/python3.9/site-packages/xbe/__init__.py", line 729, in _init_from_data
    tls_offset = self.vaddr_to_file_offset(self.header.tls_addr)
  File "/home/dustin/.local/lib/python3.9/site-packages/xbe/__init__.py", line 787, in vaddr_to_file_offset
    raise IndexError('Could not map virtual address to XBE file offset')
IndexError: Could not map virtual address to XBE file offset
thrimbor commented 2 years ago

I just took a look, and the issue is that Metal Slug 4 has two identically named sections (.rdata). I have never seen this before, and I don't know how that would even have happened in the build process - my understanding was that section names have to be unique. Even Ghidra does not display this correctly (/edit: or is this a ghidra-xbe issue?), it only shows one .rdata in the Program Trees view, you have to open Memory Map to see both. image

pyxbe uses a dictionary for the sections with the name as the key, so the second .rdata entry overwrites the first one. The first .rdata contains the TLS data though, this is why the mapping operation fails.

mborgerson commented 2 years ago

Amazing lol I'd like to keep the dict map for easy lookup. I guess for this pathological case we can throw a warning and change the name to something like .rdata_2.

thrimbor commented 2 years ago

I agree that a pragmatic solution is probably best. My initial idea would have been to put sections with identical names in a list and put that into the dictionary, but that would just move handling of this special case to the users of pyxbe.

mborgerson commented 2 years ago

Should be fixed now