-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
balign asm statement broken #298
Comments
You should see the correct alignment in an executable (ie, produced by the linker). I haven't gotten to the specific case of the https://www.sifive.com/blog/2017/08/21/all-aboard-part-2-relocations/ |
Hi @palmer-dabbelt, the bug report is based on this issue: YosysHQ/picorv32#50 The linker ultimately gives the error |
Here is the complete error I get in the original test case:
@palmer-dabbelt you are right, I can link the object file I get in the case of the above simple assembler input. I'll try to create a stand-alone test case that reproduces the linker error. |
Also: Maybe we can fix the "alignmentto" typo? :) |
Try this test case:
With current riscv-gnu-toolchain:
With an older version:
|
On Sat, Nov 18, 2017 at 10:54 AM, Palmer Dabbelt ***@***.***> wrote:
as produces object files, not executables. RISC-V handles alignment via
linker relaxation, so object files won't have the expected alignment. If
you 'objdump -dr a.out' you should see a R_RISCV_ALGIN relocation.
000000000000000a <foobar>:
a: 00000013 nop
a: R_RISCV_ALIGN *ABS*
...
You should see the correct alignment in an executable (ie, produced by the
linker). I haven't gotten to the specific case of the R_RISCV_ALIGN, but
there's a bit of blog content on some other relocations and on linker
relaxation
Except the reloc appears to be in the wrong place, after foobar when it
should be before. The assembler appears to be confused here, but it is
confused because we are in norvc mode, and we have 2-byte alignment, which
should never happen. One could call this programmer error. Or perhaps we
can do something in the assembler to make it work.
Jim
|
On Sat, Nov 18, 2017 at 10:25 AM, Clifford Wolf ***@***.***> wrote:
Consider the following assembler code:
j foobar
.ascii "xxxxx"
.byte 0x00
.balign 4
foobar:
nop
There are some conflicting goals here. We want to relax code at link time,
deleting unnecessary instructions, but this means that we can never know
alignment at assembly time. Also, we have some machines that support
2-byte instructions and some that don't. It is never safe to emit a 2-byte
nop on a target that only supports 4 byte instructions. So the assembler
gets confused here by your code.
One way to fix this is to explicitly indicate that you are in rvc mode.
j foobar
.option rvc
.ascii "xxxxx"
.byte 0x00
.balign 4
.option norvc
foobar:
nop
This produces the correct result.
Another way to fix the problem is to turn off relaxation.
.option norelax
j foobar
.ascii "xxxxx"
.byte 0x00
.balign 4
foobar:
nop
This also produces the correct result.
I don't know offhand if there is a way to make your original example work,
without breaking linker relaxation and/or rvc/norvc support. This would
require some investigation which would take some time.
Jim
|
On Sat, Nov 18, 2017 at 12:35 PM, Clifford Wolf ***@***.***> wrote:
$ riscv32-unknown-elf-gcc -march=rv32i -Os -ffreestanding -nostdlib -o test.elf test.s
/opt/riscv32i/lib/gcc/riscv32-unknown-elf/7.2.0/../../../../riscv32-unknown-elf/bin/ld: /tmp/ccdQLHYQ.o(.text+0x1a): 6 bytes required for alignmentto 8-byte boundary, but only 4 present
/opt/riscv32i/lib/gcc/riscv32-unknown-elf/7.2.0/../../../../riscv32-unknown-elf/bin/ld: can't relax section: Bad value
collect2: error: ld returned 1 exit status
This is the linker trying to tell you that you have a problem, because you
specifically requested no compressed instructions, and the only way we can
align this location in the text section is by emitting a compressed nop. I
think using .option rvc/norvc around the code is the right solution here,
and remember to put the .balign 4 before the .option norvc, because we
can't emit a 2-byte nop where only 4-byte instructions are allowed, so the
alignment has to come before you exit rvc mode.
The alignmentto typo is easy to fix. I've checked in a patch to the FSF
Binutils source tree.
https://sourceware.org/ml/binutils-cvs/2017-11/msg00167.html
This will eventually get pulled into the riscv-gnu-toolchain tree.
Jim
|
I thought the default filling byte for
Is stuff like this (risc-v specific implementation defined behavior) documented anywhere? Explicitly setting the filling byte to zero |
On Sat, Nov 18, 2017 at 5:52 PM, Clifford Wolf ***@***.***> wrote:
I thought the default filling byte for .balign is zero bytes, not nops.
But apparently this is implementation defined in .text sections. From
as.info:
The second expression (also absolute) gives the fill value to be
stored in the padding bytes. It (and the comma) may be omitted. If it
is omitted, the padding bytes are normally zero. However, on some
systems, if the section is marked as containing code and the fill value
is omitted, the space is filled with no-op instructions.
Is stuff like this (risc-v specific implementation defined behavior)
documented anywhere?
Emitting alignment directives to align branch target labels for better
performance is a common compiler optimization. At least it is nowadays.
So all targets with compiler support must emit nops for an alignment
directive in the text section. Though of course for some targets, a 0 fill
is a nop and they don't have to do anything special. Hence I would say
this is out-of-date docs that needs to be updated, not a risc-v specific
assembler feature. The "some" should be changed to "most".
There are target dependent sections in the gas manual, but they normally
only list target dependent options and pseudo-ops. The risc-v one only
mentions options. It needs to be expanded to mention the .option pseudo-op
and could probably also mention a few other things. That will have to be a
long term goal to improve the docs. Getting things working and properly
merged upstream is the immediate concern.
I think the only target doc that mentions nops for alignment is the i386
one, and that is because they have an option to choose whether you emit for
instance a single 7-byte nop instruction or 7 1-byte nop instructions. The
default is to emit a single multi-byte nop for every length from 1 to 14.
Though trying it, I see that it doesn't work anymore, which is no surprise,
since there is no good reason to ever use this option.
https://sourceware.org/binutils/docs-2.29/as/RISC_002dV_002dDependent.html#RISC_002dV_002dDependent
Explicitly setting the filling byte to zero .balign 4, 0 solves the issue
with my code.
That didn't occur to me, yes that works too.
Jim
|
I thought that's what Clearly the problem was that I had incorrect assumptions about the differences between the two directives. I always used something like So in the future I will now use
Yes please. :) I did not know about |
On Sat, Nov 18, 2017 at 7:55 PM, Clifford Wolf ***@***.***> wrote:
Clearly the problem was that I had incorrect assumptions about the
differences between the two directives. I always used something like .align
2 to pad with nops to a multiple of 4 and .balign 4 to pad with whatever
to a multiple of 4. But now I see that it's not even standardized if the
parameter to .align specifies the alignment in zero bits in the next
address or in bytes..
Yes, the problem with .align is a historical one, in that different vendor
assemblers had different conventions when gas was developed long ago. That
is why we have .balign and .p2align in gas, which are ambiguous about what
the alignment argument means. Otherwise, align, balign, and p2align all
behave the same.
Jim
|
Resolves the follow compilation error (payload variant for SiFive FU540 with U-Boot and embedded FDT): /usr/bin/ld: /build/platform/sifive/fu540/firmware/fw_payload.o(.text+0x1961): 15 bytes required for alignment to 16-byte boundary, but only 14 present /usr/bin/ld: can't relax section: bad value collect2: error: ld returned 1 exit status Noticed while compiling 5.4-rc3+ kernel in Fedora/RISCV. For more details see: riscv-collab/riscv-gnu-toolchain#298 Signed-off-by: David Abdurachmanov <david.abdurachmanov@sifive.com>
We get following compile error for FW_PAYLOAD with latest GCC binutils: fw_payload.o(.text+0x1961): 15 bytes required for alignment to 16-byte boundary, but only 14 present Further investigating, it turn-out to be a known issue with RISC-V GCC binutils. (Refer, riscv-collab/riscv-gnu-toolchain#298) As a work-around, we disable relaxation when including DTB and PAYLOAD binary in fw_payload.S. Reported-by: David Abdurachmanov <david.abdurachmanov@sifive.com> Signed-off-by: Anup Patel <anup.patel@wdc.com>
We get following compile error for FW_PAYLOAD with latest GCC binutils: fw_payload.o(.text+0x1961): 15 bytes required for alignment to 16-byte boundary, but only 14 present Further investigating, it turn-out to be a known issue with RISC-V GCC binutils. (Refer, riscv-collab/riscv-gnu-toolchain#298) As a work-around, we disable relaxation when including DTB and PAYLOAD binary in fw_payload.S. Reported-by: David Abdurachmanov <david.abdurachmanov@sifive.com> Signed-off-by: Anup Patel <anup.patel@wdc.com>
We get following compile error for FW_PAYLOAD with latest GCC binutils: fw_payload.o(.text+0x1961): 15 bytes required for alignment to 16-byte boundary, but only 14 present Further investigating, it turn-out to be a known issue with RISC-V GCC binutils. (Refer, riscv-collab/riscv-gnu-toolchain#298) As a work-around, we disable relaxation when including DTB and PAYLOAD binary in fw_payload.S. Reported-by: David Abdurachmanov <david.abdurachmanov@sifive.com> Signed-off-by: Anup Patel <anup.patel@wdc.com> Tested-by: David Abdurachmanov <david.abdurachmanov@sifive.com> Reviewed-by: Atish Patra <atish.patra@wdc.com>
Consider the following assembler code:
An older version of
riscv32-unknown-elf-as
produces the expected result (output ofriscv32-unknown-elf-objdump -d
):But with the current version of riscv-gnu-toolchain (bf5697a) I get the following result instead:
The symbol foobar is not aligned to a multiple of 4. It looks like the
.balign
statement was simply ignored.In both cases I just ran
riscv32-unknown-elf-as test.s
and thenriscv32-unknown-elf-objdump -d a.out
.The text was updated successfully, but these errors were encountered: