Fix broken disassembly of floating point immediates on big endian hosts#2222
Merged
kabeor merged 1 commit intocapstone-engine:nextfrom Dec 21, 2023
Merged
Fix broken disassembly of floating point immediates on big endian hosts#2222kabeor merged 1 commit intocapstone-engine:nextfrom
kabeor merged 1 commit intocapstone-engine:nextfrom
Conversation
Disassembling single floating points with immediate values currently gives wrong results on big endian hosts (like s390x), e.g.: ./cstool/cstool m68k40 'f2 3c 44 22 40 49 0e 56' 0 f2 3c 44 22 40 49 0e 56 fadd.s #0.000000, fp0 While it should be (like on x86): ./cstool/cstool m68k40 'f2 3c 44 22 40 49 0e 56' 0 f2 3c 44 22 40 49 0e 56 fadd.s capstone-engine#3.141500, fp0 The problem is that these single float values are supposed to be stored in the 32-bit "simm" field of struct cs_m68k_op (see e.g. the printing of M68K_FPU_SIZE_SINGLE in printAddressingMode() in M68KInstPrinter.c), but currently the immediate is only written to the 64-bit "imm" field of the union in cs_m68k_op. This works on little endian systems, since the least significant bytes overlap in the union there. For example, let's assume that the value 0x01020304 gets written to "imm": 04 03 02 01 00 00 00 00 uint64_t imm xx xx xx xx xx xx xx xx double dimm; xx xx xx xx .. .. .. .. float simm; But on big endian hosts, the important bytes do not overlap, so "simm" is always zero there: 00 00 00 00 01 02 03 04 uint64_t imm xx xx xx xx xx xx xx xx double dimm; xx xx xx xx .. .. .. .. float simm; To fix the problem, let's always set "simm" explicitly, this works on both, big endian and little endian hosts. Thanks to Michal Schulz for his initial analysis of the problem (in capstone-engine#1710) and to Travis Finkenauer for providing an easy example to reproduce the issue (in capstone-engine#1931). Closes: capstone-engine#1710
Rot127
approved these changes
Dec 20, 2023
Collaborator
Rot127
left a comment
There was a problem hiding this comment.
LGTM. Though what is about case 0x5 and the default case?
Aren't they broken as well? If yes, it would be great if you could quickly fix them here as well.
Contributor
Author
|
@Rot127 : case 0x05 is fine since it is about double floats that have 64 bit length - so this aliases perfectly well with the "imm" that gets written by get_ea_mode_op(). And the "default" case does not seem to use get_ea_mode_op() at all, i.e. it does not set the "imm" field at all, so I assume that's not affected. |
Collaborator
|
@kabeor Please take a look. |
Member
|
Looks cool, thanks! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Disassembling single floating points with immediate values currently gives wrong results on big endian hosts (like s390x), e.g.:
While it should be (like on x86):
The problem is that these single float values are supposed to be stored in the 32-bit "simm" field of struct cs_m68k_op (see e.g. the printing of M68K_FPU_SIZE_SINGLE in printAddressingMode() in M68KInstPrinter.c), but currently the immediate is only written to the 64-bit "imm" field of the union in cs_m68k_op. This works on little endian systems, since the least significant bytes overlap in the union there. For example, let's assume that the value 0x01020304 gets written to "imm":
But on big endian hosts, the important bytes do not overlap, so "simm" is always zero there:
To fix the problem, let's always set "simm" explicitly, this works on both, big endian and little endian hosts.
Thanks to Michal Schulz for his initial analysis of the problem (in #1710) and to Travis Finkenauer for providing an easy example to reproduce the issue (in #1931).
Closes: #1710