Decompollaborate / spimdisasm

MIPS disassembler
https://pypi.org/project/spimdisasm/
MIT License
45 stars 13 forks source link

Question: Missing .glabel for Jump Labels #148

Closed dlbuhtig4096 closed 9 months ago

dlbuhtig4096 commented 9 months ago

Hello there,

I am working a disassembly project targets N64, that make use of splat, which depends on spimdisasm. But I notice that it's generating .L* without .glabel .L*, for example:

glabel obj2Shell
/* 1AFE8 8001A3E8 27BDFD08 */  addiu      $sp, $sp, -0x2F8
/* 1AFEC 8001A3EC AFB1003C */  sw         $s1, 0x3C($sp)
/* 1AFF0 8001A3F0 AFBF005C */  sw         $ra, 0x5C($sp)
/* 1AFF4 8001A3F4 AFBE0058 */  sw         $fp, 0x58($sp)
/* 1AFF8 8001A3F8 AFB70054 */  sw         $s7, 0x54($sp)
/* 1AFFC 8001A3FC AFB60050 */  sw         $s6, 0x50($sp)
/* 1B000 8001A400 AFB5004C */  sw         $s5, 0x4C($sp)
/* 1B004 8001A404 AFB40048 */  sw         $s4, 0x48($sp)
/* 1B008 8001A408 AFB30044 */  sw         $s3, 0x44($sp)
/* 1B00C 8001A40C AFB20040 */  sw         $s2, 0x40($sp)
/* 1B010 8001A410 AFB00038 */  sw         $s0, 0x38($sp)
/* 1B014 8001A414 E7B90030 */  swc1       $f25, 0x30($sp)
/* 1B018 8001A418 E7B80034 */  swc1       $f24, 0x34($sp)
/* 1B01C 8001A41C E7B70028 */  swc1       $f23, 0x28($sp)
/* 1B020 8001A420 E7B6002C */  swc1       $f22, 0x2C($sp)
/* 1B024 8001A424 E7B50020 */  swc1       $f21, 0x20($sp)
/* 1B028 8001A428 E7B40024 */  swc1       $f20, 0x24($sp)
/* 1B02C 8001A42C AFA402F8 */  sw         $a0, 0x2F8($sp)
/* 1B030 8001A430 AFA502FC */  sw         $a1, 0x2FC($sp)
/* 1B034 8001A434 AFA60300 */  sw         $a2, 0x300($sp)
/* 1B038 8001A438 AFA70304 */  sw         $a3, 0x304($sp)
/* 1B03C 8001A43C 10800365 */  beqz       $a0, .L8001B1D4
/* 1B040 8001A440 27B102FC */   addiu     $s1, $sp, 0x2FC
/* 1B044 8001A444 2413000F */  addiu      $s3, $zero, 0xF
/* 1B048 8001A448 2412FFFC */  addiu      $s2, $zero, -0x4
.L8001A44C:
/* 1B04C 8001A44C 8FAF02F8 */  lw         $t7, 0x2F8($sp)
/* 1B050 8001A450 00000000 */  nop
/* 1B054 8001A454 25F8FFFF */  addiu      $t8, $t7, -0x1
/* 1B058 8001A458 2F01003A */  sltiu      $at, $t8, 0x3A
/* 1B05C 8001A45C 10200353 */  beqz       $at, .L8001B1AC
/* 1B060 8001A460 0018C080 */   sll       $t8, $t8, 2
/* 1B064 8001A464 3C018009 */  lui        $at, (0x80090000 >> 16)
/* 1B068 8001A468 00380821 */  addu       $at, $at, $t8
/* 1B06C 8001A46C 8C383130 */  lw         $t8, 0x3130($at)

in which .L8001B1AC is referenced in rodata:

/* 93D9C 8009319C 8001ACF4 */ .word 0x8001ACF4
/* 93DA0 800931A0 8001B1AC */ .word .L8001B1AC
/* 93DA4 800931A4 8001AD78 */ .word 0x8001AD78

This results in undefined reference on linking the objects, as .L8001B1AC cannot be seen by the linker.

I have look into the source code of splat, where they emit asm code via:

class CommonSegAsm(CommonSegCodeSubsegment):
# ... snip ... 
    def split(self, rom_bytes: bytes):
        if not self.rom_start == self.rom_end and self.spim_section is not None:
            out_path = self.out_path()
            if out_path:
                out_path.parent.mkdir(parents=True, exist_ok=True)

                self.print_file_boundaries()

                with open(out_path, "w", newline="\n") as f:
                    for line in self.get_file_header():
                        f.write(line + "\n")
                    f.write(self.spim_section.disassemble())

and turns out the assembly was directly emitted by spimdisasm.

I have tried anaconda3 and standalone python 3.11.7, however both of them produced the exact same results. Hence I am wondering if I have made any mistake on config or env setup. I am using windows 11 with spimdisasm 1.20.0, and spimdisasm.common.GlobalConfig was:

GlobalConfigType(DISASSEMBLE_UNKNOWN_INSTRUCTIONS=False, PRODUCE_SYMBOLS_PLUS_OFFSET=True, TRUST_USER_FUNCTIONS=True, TRUST_JAL_FUNCTIONS=True, RODATA_STRING_GUESSER_LEVEL=1, DATA_STRING_GUESSER_LEVEL=2, PASCAL_RODATA_STRING_GUESSER_LEVEL=0, PASCAL_DATA_STRING_GUESSER_LEVEL=0, AUTOGENERATED_NAMES_BASED_ON_SECTION_TYPE=False, AUTOGENERATED_NAMES_BASED_ON_DATA_TYPE=False, AUTOGENERATED_NAMES_BASED_ON_FILE_NAME=False, SEQUENTIAL_LABEL_NAMES=False, LEGACY_SYM_ADDR_ZERO_PADDING=False, CUSTOM_SUFFIX='', COMPILER=<Compiler.IDO: 'IDO'>, DETECT_REDUNDANT_FUNCTION_END=True, ENDIAN=<InputEndian.BIG: 'big'>, ENDIAN_DATA=None, ENDIAN_RODATA=None, ABI=<Abi.O32: 'O32'>, ARCHLEVEL=<ArchLevel.MIPS3: 3>, INPUT_FILE_TYPE=<InputFileType.BINARY: 'binary'>, GP_VALUE=0, PIC=False, EMIT_CPLOAD=True, EMIT_INLINE_RELOC=False, SYMBOL_FINDER_FILTER_LOW_ADDRESSES=True, SYMBOL_FINDER_FILTER_ADDRESSES_ADDR_LOW=2147483648, SYMBOL_FINDER_FILTER_HIGH_ADDRESSES=True, SYMBOL_FINDER_FILTER_ADDRESSES_ADDR_HIGH=3221225472, SYMBOL_FINDER_FILTERED_ADDRESSES_AS_CONSTANTS=True, SYMBOL_FINDER_FILTERED_ADDRESSES_AS_HILO=False, ALLOW_UNKSEGMENT=True, ALLOW_ALL_ADDENDS_ON_DATA=True, ALLOW_ALL_CONSTANTS_ON_DATA=True, ASM_COMMENT=True, ASM_COMMENT_OFFSET_WIDTH=0, GLABEL_ASM_COUNT=False, ASM_REFERENCEE_SYMBOLS=False, ASM_TEXT_LABEL='glabel', ASM_TEXT_ALT_LABEL='glabel', ASM_JTBL_LABEL='glabel', ASM_DATA_LABEL='glabel', ASM_USE_SYMBOL_LABEL=True, ASM_TEXT_ENT_LABEL='', ASM_TEXT_END_LABEL='', ASM_TEXT_FUNC_AS_LABEL=False, ASM_DATA_SYM_AS_LABEL=False, ASM_EMIT_SIZE_DIRECTIVE=False, ASM_USE_PRELUDE=True, ASM_GENERATED_BY=True, PRINT_NEW_FILE_BOUNDARIES=False, USE_DOT_BYTE=True, USE_DOT_SHORT=True, LINE_ENDS='\n', PANIC_RANGE_CHECK=False, CREATE_DATA_PADS=True, CREATE_RODATA_PADS=False, QUIET=False, VERBOSE=False, PRINT_FUNCTION_ANALYSIS_DEBUG_INFO=False, PRINT_SYMBOL_FINDER_DEBUG_INFO=False, PRINT_UNPAIRED_LUIS_DEBUG_INFO=False, REMOVE_POINTERS=False, IGNORE_BRANCHES=False, IGNORE_WORD_LIST=set(), WRITE_BINARY=False)

Many thanks for the help.

AngheloAlf commented 9 months ago

Hey! Thanks for the bug report!

Sadly I can't reproduce the issue myself. I cloned the repo and followed the README instructions and the build produces an OK instead of a linker error.

On a further inspection of the generated assembly.

Seems like we are running the same spimdisasm version.

Which splat version did you use to test this? Try to check if yours is somehow outdated. Seems like the splat submodule I used is 0.21.6. You can check the splat version by simply running it, it will print something like this:

splat 0.21.6 (powered by spimdisasm 1.20.0)

My Python version is 3.10.12 and I'm running on a native Linux distro. Are you running this on native Windows 11 or are you using WSL? Both spimdisasm and splat should behave the regarding the Python version or OS it runs on, otherwise it would be pretty worrying.

lmk if you have any more info to try to reproduce this issue

RevoSucks commented 9 months ago

I am talking to them on discord and they are using Msys to run this. I use 3.10.6 and they use Python 3.11.5 and I tried 3.11.7 and that didnt reproduce it (I couldnt find an exact apt-get of 3.11.5 from WSL aptget). I also made sure to make my requirements.txt versions match their module versions and that didnt reproduce it issue. It's gotta be either some weird 3.11.5 bug (cascading into a spimdisasm issue) or a horrible environment issue as a result of using msys.

AngheloAlf commented 9 months ago

How does Msys handle Python? Is it like its own shell or is it running on a plain Windows cmd/powershell?

You could try running splat on a cmd/powershell directly instead of passing through Msys to see if that's somehow related

dlbuhtig4096 commented 9 months ago

How does Msys handle Python? Is it like its own shell or is it running on a plain Windows cmd/powershell?

You could try running splat on a cmd/powershell directly instead of passing through Msys to see if that's somehow related

No I have run the script in cmd and anaconda3 prompt, both produced the exact same result. And I have tried standalone python 3.11.7 as well, the problem presists.

dlbuhtig4096 commented 9 months ago

I have tried to run splat on Ubuntu VM, and it seems generating proper disassembly without linking issues. Does spimdisasm make use of unix shell or system features internally? I thought the package was OS-independent.

AngheloAlf commented 9 months ago

Neither spimdisasm or splat use any OS dependent feature, so it should behave the same everywhere. That said, I installed Windows 11 on a virtual machine with Python 3.11.5 and I managed to reproduce the bug. I'll try to see what causes this

mkst commented 9 months ago

Not sure that it helps, but I am unable to reproduce this issue under MSYS2 MinGW x64 on Windows 10. Python 3.11.7, I see the symbols resolved correctly:

marks@DESKTOP-AOUBO9E MINGW64 ~/TSA
$ grep -n3 8009319C  asm/data/93680.rodata.s
344-/* 93D90 80093190 8001ABB8 */ .word .L8001ABB8
345-/* 93D94 80093194 8001ABF4 */ .word .L8001ABF4
346-/* 93D98 80093198 8001AC74 */ .word .L8001AC74
347:/* 93D9C 8009319C 8001ACF4 */ .word .L8001ACF4
348-/* 93DA0 800931A0 8001B1AC */ .word .L8001B1AC
349-/* 93DA4 800931A4 8001AD78 */ .word .L8001AD78
350-/* 93DA8 800931A8 8001ADB8 */ .word .L8001ADB8

marks@DESKTOP-AOUBO9E MINGW64 ~/TSA
$ grep -R jtbl_80093130 asm
asm/177F0.s:/* 1B064 8001A464 3C018009 */  lui        $at, %hi(jtbl_80093130)
asm/177F0.s:/* 1B06C 8001A46C 8C383130 */  lw         $t8, %lo(jtbl_80093130)($at)
asm/data/93680.rodata.s:glabel jtbl_80093130
dlbuhtig4096 commented 9 months ago

Not sure that it helps, but I am unable to reproduce this issue under MSYS2 MinGW x64 on Windows 10. Python 3.11.7, I see the symbols resolved correctly:

marks@DESKTOP-AOUBO9E MINGW64 ~/TSA
$ grep -n3 8009319C  asm/data/93680.rodata.s
344-/* 93D90 80093190 8001ABB8 */ .word .L8001ABB8
345-/* 93D94 80093194 8001ABF4 */ .word .L8001ABF4
346-/* 93D98 80093198 8001AC74 */ .word .L8001AC74
347:/* 93D9C 8009319C 8001ACF4 */ .word .L8001ACF4
348-/* 93DA0 800931A0 8001B1AC */ .word .L8001B1AC
349-/* 93DA4 800931A4 8001AD78 */ .word .L8001AD78
350-/* 93DA8 800931A8 8001ADB8 */ .word .L8001ADB8

marks@DESKTOP-AOUBO9E MINGW64 ~/TSA
$ grep -R jtbl_80093130 asm
asm/177F0.s:/* 1B064 8001A464 3C018009 */  lui        $at, %hi(jtbl_80093130)
asm/177F0.s:/* 1B06C 8001A46C 8C383130 */  lw         $t8, %lo(jtbl_80093130)($at)
asm/data/93680.rodata.s:glabel jtbl_80093130

I think the issue is not related to the shell as long as spimdisasm and splat are not using shell internally. Have you tried to run python via cmd or anaconda prompt? This could be an unknown python bug for Windows 11 if that worked for you as well.

mkst commented 9 months ago

We (well, Anghelo) have been debugging and it looks to be due to the "long" datatype being 32 bits under Windows, but 64 bits under Linux, which causes the symbol address to be calculated incorrectly.

I didn't encounter the problem because the rabbitizer wheel was compiled locally when I pip installed, but you & Anghelo got the pre built wheel from pypi.

Watch this space for a new release...

dlbuhtig4096 commented 9 months ago

We (well, Anghelo) have been debugging and it looks to be due to the "long" datatype being 32 bits under Windows, but 64 bits under Linux, which causes the symbol address to be calculated incorrectly.

I didn't encounter the problem because the rabbitizer wheel was compiled locally when I pip installed, but you & Anghelo got the pre built wheel from pypi.

Watch this space for a new release...

Oh it's a bug from rabbitizer. Then I would have to build it by myself and replace the long with long long?

mkst commented 9 months ago

Rabbitizer will need to be updated and released - if you want to test the fix out beforehand, you can change this line https://github.com/Decompollaborate/rabbitizer/blob/c6e988affab6790a7a497e7c68a50bb58e78e1c1/rabbitizer/rabbitizer_type_LoPairingInfo.c#L26 from T_LONG to T_LONGLONG and rebuild the wheel (I think pip install .) once you've made that change.

dlbuhtig4096 commented 9 months ago

Okay, many thanks for the help. Shall we close this issue now?

AngheloAlf commented 9 months ago

I made a new release of rabbitizer that should address this issue (https://github.com/Decompollaborate/rabbitizer/pull/51 and https://github.com/Decompollaborate/rabbitizer/pull/52)

Could you please install the latest version of rabbitizer and tell us if the issue still persists? To make sure you install the latest version you can run this:

python3 -m pip install "rabbitizer==1.8.3"
dlbuhtig4096 commented 9 months ago

Could confirm that the issue has gone after installing the latest version of rabbitizer.

AngheloAlf commented 9 months ago

Cool! glad that it finally got solved