Conversation
There was a problem hiding this comment.
All reported issues were addressed across 7 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
0d1e98b to
3c3998d
Compare
There was a problem hiding this comment.
1 issue found across 7 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="tests/riscv-abi.sh">
<violation number="1" location="tests/riscv-abi.sh:149">
P2: An unvalidated `binding` argument is inserted into a command string executed by `eval`, so invoking this test script with a crafted third argument executes arbitrary shell commands. Validate the value against `lazy|now` or shell-escape it before constructing the command.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
Since the original codebase already implemented the immediate binding flag for the x86-64 and AArch64 architectures, this commit introduces a "-z" option so that the Arm32 and RV32 targets can also use immediate binding. When the command-line arguments contain "-z now", the compiler sets its internal flag (imm_binding) to true and generates the Elf32_Dyn/Elf64_Dyn objects to enable exectuables to perform immediate binding at runtime. For 64-bit targets, immediate binding is always used under the dynamic linking mode as is.
Since the compiler supports the "-z" option for lazy or immediate binding, a new "BINDING" variable has benn added to the Makefile so that users can choose which binding mode to use. For example, users can build dynamically linked compilers with immediate binding as follows: $ make DYNLINK=1 BINDING=now
Since the compiler has implemented dynamic linking with immediate binding, the test suites have been enhance to validate immediate binding mode. The approach is to add an additional command-line argument to determine which mode, lazy or immediate, is enabled during the tests.
c0c2484 to
e75d599
Compare
| # the stage 0 and stage 2 compilers. | ||
| host-x86: | ||
| name: ${{ matrix.architecture }}/${{ matrix.link_mode }} (${{ matrix.compiler }}) | ||
| name: ${{ matrix.architecture }}/${{ matrix.link_mode }}/${{ matrix.link_mode == 'dynamic' && (matrix.binding_mode == 'immediate' && 'immediate' || 'default') || 'none' }} (${{ matrix.compiler }}) |
There was a problem hiding this comment.
Naming:
- static linking mode:
<arch>/static/none. - dynamic linking mode:
<arch>/dynamic/<default or immediate>
The default binding mode for each architecture is as follows:
- Arm32: lazy binding
- RISC-V: lazy binding
- x64: immediate binding
- Arm64: immediate binding
These conditions make the workflow modifications somewhat complex. |
Since the test scripts can validate either lazy binding or immediate binding via an additional argument, the CI workflows are improved so that dynamic linking with immediate binding can be validated on the Arm32 and RISC-V architectures. Primary changes and considerations: - Add an additional 'binding_mode' parameter so that the GitHub Actions workflows cab verify immediate binding for Arm32 and RISC-V. - When CI tests the static linking mode, the 'binding_mode' parameter is ignored because static linking involves neither lazy nor immediate binding. - The x86-64 and Arm64 architectures use immediate binding by default, so neither of them tests lazy binding.
e75d599 to
c4fbf69
Compare
| compiler: [gcc, clang] | ||
| architecture: [arm, arm64, riscv, x64] | ||
| link_mode: [static, dynamic] | ||
| include: |
There was a problem hiding this comment.
An include entry whose keys all match an existing combination is merged into that combination instead of creating a new job, so these four entries convert the existing arm/dynamic and riscv/dynamic jobs into immediate-binding runs rather than adding jobs. The default lazy path then has no dynamic coverage on Arm32 or RV32 at all, and the include blocks in sanitizer, host-arm and host-arm-sanitizer behave the same way. Adding binding_mode: [lazy] to the matrix makes the immediate entries conflict, so they expand into separate jobs and the lazy jobs survive.
| include: | ||
| - architecture: arm | ||
| link_mode: dynamic | ||
| binding_mode: immedaite |
There was a problem hiding this comment.
immedaite never matches the matrix.binding_mode == 'immediate' test that computes BINDING, so this entry merges into the existing arm/dynamic job and leaves it on lazy binding. The native Arm64 runner is the only place a real loader resolves these relocations, so immediate binding ends up untested where it matters most.
| binding_mode: immedaite | |
| binding_mode: immediate |
| check-stage2: $(OUT)/$(STAGE2) tests/driver.sh | ||
| $(VECHO) " TEST STAGE 2\n" | ||
| tests/driver.sh 2 $(DYNLINK) | ||
| tests/driver.sh 2 $(DYNLINK) $(BINDING) |
There was a problem hiding this comment.
check-stage0 and check-stage2 forward $(BINDING), but check-sanitizer below still calls tests/driver.sh 0 $(DYNLINK), so the sanitizer jobs that set BINDING=now run the suite with lazy binding. Pass $(BINDING) there as well.
| elf_write_dyn(dynamic_sections.elf_dynamic, 0x18, 0x0); /* DT_BIND_NOW */ | ||
| elf_write_dyn(dynamic_sections.elf_dynamic, 0x1e, 0x8); /* DF_BIND_NOW */ | ||
| #endif | ||
| if (imm_binding) { |
There was a problem hiding this comment.
The comment above this branch still states the old compile-time rule. On Arm32 and RV32 the PLT does arrange the GOT[1]/GOT[2] hand-off, and these entries are emitted because the user asked for -z now, not because lazy resolution is impossible. Reword it to say the binding mode is selected by imm_binding and forced on the targets whose PLT has no lazy path.
| */ | ||
| case ELF_MACHINE_X86_64: | ||
| case ELF_MACHINE_AARCH64: | ||
| imm_binding = true; |
There was a problem hiding this comment.
An explicit -z lazy is parsed, accepted, and then silently overridden here, so the user gets immediate binding with no diagnostic, unlike the other incompatible option pairs that usage_error rejects. -z without --dynlink is likewise accepted and does nothing. Recording whether -z was given, then rejecting -z lazy on these targets and -z without --dynlink, keeps the option contract honest.
| "Usage: shecc [-I directory] [-o output] [+m] [--dot] [--dump-ir] " | ||
| "[--warn-string-literals] [--std=c99] [--no-libc] " | ||
| "[--dynlink] [-E] <input.c>\n"); | ||
| "[--dynlink] [-z <lazy | now>] [-E] <input.c>\n"); |
There was a problem hiding this comment.
The usage string gains -z, but the usage line and option list in README.md still document the old set, and docs/dynamic-linking.md still lists "DT_BIND_NOW (force immediate binding) is not set" under Limitations, which is wrong for every target once this lands. Both belong in this change.
|
|
||
| if [ $# -ge 2 ] && [ "$2" = "1" ]; then | ||
| readonly SHECC_CFLAGS="--dynlink" | ||
| readonly SHECC_CFLAGS="--dynlink ${3:-lazy}" |
There was a problem hiding this comment.
SHECC_CFLAGS gets the binding mode without the -z that introduces it, so shecc sees a bare lazy or now operand. That operand is parsed as an input file and then overwritten by the real source that follows it, so make check BINDING=now runs the whole driver suite with lazy binding and reports success.
| readonly SHECC_CFLAGS="--dynlink ${3:-lazy}" | |
| readonly SHECC_CFLAGS="--dynlink -z ${3:-lazy}" |
Since the immediate binding has already been implemented for the x86-64 and AArch64 architectures, the proposed changes extend its use by introducing a new "-z" command-line option, allowing the Arm32 and RV32 targets to also generate dynamically linked executables with immediate binding.
For the two 64-bit targets, immediate binding is always used under the dynamic linking mode as is.
The update usage:
TODO:
Summary by cubic
Adds a
-z <lazy|now>option (defaultlazy) so Arm32 and RISC-V dynamic executables can use immediate binding, matching x86-64 and AArch64.nowin dynamic mode, so-z lazyis ignored there.BINDINGand passes it to builds, driver tests, and ABI tests.-z;tests/driver.shdoesn't, so the binding value reaches shecc as an extra source file and driver-based dynamic runs fail.host-armArm32 entry misspellsimmediateasimmedaite, so that job still runs lazy.Written for commit c4fbf69. Summary will update on new commits.