From 7403be83afe8620495a67fabd12790299232e94b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Poulhi=C3=A8s?= Date: Wed, 11 Jan 2023 19:39:25 +0100 Subject: [PATCH] Support for compiling to binary object (#3232) --- docs/API.md | 4 +- docs/AddingACompiler.md | 31 ++++++------ etc/config/ada.amazon.properties | 1 + etc/config/ada.defaults.properties | 3 +- etc/config/c++.amazon.properties | 23 ++------- etc/config/c++.defaults.properties | 1 + etc/config/c.amazon.properties | 42 +++++++++------- etc/config/c.defaults.properties | 1 + etc/config/d.amazon.properties | 1 + etc/config/d.defaults.properties | 1 + etc/config/rust.amazon.properties | 7 +++ lib/base-compiler.ts | 34 +++++++++---- lib/compiler-finder.ts | 2 + lib/compilers/ada.ts | 74 ++++++++++++++-------------- lib/compilers/cc65.ts | 13 ++++- lib/compilers/jakt.ts | 14 +++++- lib/compilers/llvm-mos.ts | 13 ++++- lib/compilers/racket.ts | 2 + lib/compilers/rust.ts | 2 + lib/compilers/z88dk.ts | 2 + lib/external-parsers/base.ts | 1 + lib/objdumper/base.ts | 10 +++- lib/options-handler.ts | 4 ++ lib/parsers/asm-parser-vc.js | 2 +- lib/parsers/asm-parser-vc6.js | 2 +- lib/parsers/asm-parser.ts | 23 ++++++++- lib/tooling/pahole-tool.js | 2 +- lib/tooling/readelf-tool.js | 2 +- static/panes/compiler.ts | 31 ++++++++++-- types/compiler.interfaces.ts | 1 + types/features/filters.interfaces.ts | 1 + views/options-output.pug | 1 + 32 files changed, 233 insertions(+), 118 deletions(-) diff --git a/docs/API.md b/docs/API.md index 5b65eb17d..84e2fdf80 100644 --- a/docs/API.md +++ b/docs/API.md @@ -65,6 +65,7 @@ To specify a compilation request as a JSON document, post it as the appropriate }, "filters": { "binary": false, + "binaryObject": false, "commentOnly": true, "demangle": true, "directives": true, @@ -121,8 +122,7 @@ probably not useful for most REST users. To force a cache bypass, set `bypassCache` in the root of the request to `true`. -Filters include `binary`, `labels`, `intel`, `directives` and `demangle`, which correspond to the UI buttons on the HTML -version. +Filters include `binary`, `binaryObject`, `labels`, `intel`, `directives` and `demangle`, which correspond to the UI buttons on the HTML version. With the tools array you can ask CE to execute certain tools available for the current compiler, and also supply arguments for this tool. diff --git a/docs/AddingACompiler.md b/docs/AddingACompiler.md index 18115cecd..6ef100dc2 100644 --- a/docs/AddingACompiler.md +++ b/docs/AddingACompiler.md @@ -84,21 +84,22 @@ once the site runs on the Amazon environment, the `&clang` group **will not** ha ### Configuration keys -| Key Name | Type | Description | -| ---------------- | ---------- | ---------------------------------------------------------------------------------------------------------------- | -| name | String | Human readable name of the compiler | -| exe | Path | Path to the executable | -| alias | Identifier | Another identifier for this compiler (mostly deprecated, used for backwards compatibility with very old CE URLs) | -| options | String | Additional compiler options passed to the compiler when running it | -| intelAsm | String | Flags used to select intel assembly format (if not detected automatically) | -| needsMulti | Boolean | Whether the compiler needs multi arch support (defaults to yes if the host has multiarch enabled) | -| supportsBinary | Boolean | Whether this compiler supports compiling to binary | -| supportsExecute | Boolean | Whether binary output from this compiler can be executed | -| versionFlag | String | The flag to pass to the compiler to make it emit its version | -| versionRe | RegExp | A regular expression used to capture the version from the version output | -| compilerType | String | The name of the class handling this compiler | -| interpreted | Boolean | Whether this is an interpreted language, and so the "compiler" is really an interpreter | -| executionWrapper | Path | Path to script that can execute the compiler's output (e.g. could run under `qemu` or `mpi_run` or similar) | +| Key Name | Type | Description | +|----------------------|------------|------------------------------------------------------------------------------------------------------------------| +| name | String | Human readable name of the compiler | +| exe | Path | Path to the executable | +| alias | Identifier | Another identifier for this compiler (mostly deprecated, used for backwards compatibility with very old CE URLs) | +| options | String | Additional compiler options passed to the compiler when running it | +| intelAsm | String | Flags used to select intel assembly format (if not detected automatically) | +| needsMulti | Boolean | Whether the compiler needs multi arch support (defaults to yes if the host has multiarch enabled) | +| supportsBinary | Boolean | Whether this compiler supports linking to binary (e.g. compile, assemble and link to final executable program) | +| supportsBinaryObject | Boolean | Whether this compiler supports compiling to binary object (e.g. compile and assemble to binary object) | +| supportsExecute | Boolean | Whether binary output from this compiler can be executed | +| versionFlag | String | The flag to pass to the compiler to make it emit its version | +| versionRe | RegExp | A regular expression used to capture the version from the version output | +| compilerType | String | The name of the class handling this compiler | +| interpreted | Boolean | Whether this is an interpreted language, and so the "compiler" is really an interpreter | +| executionWrapper | Path | Path to script that can execute the compiler's output (e.g. could run under `qemu` or `mpi_run` or similar) | The `compilerType` option is special: it refers to the Javascript class in `lib/compilers/*.js` which handles running and handling output for this compiler type. diff --git a/etc/config/ada.amazon.properties b/etc/config/ada.amazon.properties index 83e3bbca7..71c17ca0f 100644 --- a/etc/config/ada.amazon.properties +++ b/etc/config/ada.amazon.properties @@ -19,6 +19,7 @@ group.gnat.isSemVer=true group.gnat.licenseLink=https://gcc.gnu.org/onlinedocs/gcc/Copying.html group.gnat.licenseName=GNU General Public License group.gnat.licensePreamble=Copyright (c) 2007 Free Software Foundation, Inc. https://fsf.org/ +group.gnat.supportsBinaryObject=true compiler.gnat82.exe=/opt/compiler-explorer/gcc-8.2.0/bin/gnatmake compiler.gnat82.semver=8.2 diff --git a/etc/config/ada.defaults.properties b/etc/config/ada.defaults.properties index 7dc5e0858..36a4985f8 100644 --- a/etc/config/ada.defaults.properties +++ b/etc/config/ada.defaults.properties @@ -4,11 +4,12 @@ defaultCompiler=gnatdefault demangler=c++filt versionFlag=--version compilerType=ada - +group.gnat.supportsBinaryObject=true group.gnat.compilers=gnatdefault group.gnat.intelAsm=-masm=intel group.gnat.supportsBinary=true group.gnat.supportsExecute=true +group.gnat.supportsBinaryObject=true group.gnat.objdumper=objdump compiler.gnatdefault.exe=/usr/bin/gnatmake diff --git a/etc/config/c++.amazon.properties b/etc/config/c++.amazon.properties index 3f033bb0e..6ca25226f 100644 --- a/etc/config/c++.amazon.properties +++ b/etc/config/c++.amazon.properties @@ -27,6 +27,7 @@ group.gcc86.supportsPVS-Studio=true group.gcc86.licenseLink=https://gcc.gnu.org/onlinedocs/gcc/Copying.html group.gcc86.licenseName=GNU General Public License group.gcc86.licensePreamble=Copyright (c) 2007 Free Software Foundation, Inc. https://fsf.org/ +group.gcc86.supportsBinaryObject=true compiler.g412.exe=/opt/compiler-explorer/gcc-4.1.2/bin/g++ compiler.g412.semver=4.1.2 @@ -204,6 +205,7 @@ group.clang.supportsPVS-Studio=true group.clang.licenseName=LLVM Apache 2 group.clang.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT group.clang.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions +group.clang.supportsBinaryObject=true # Ancient clangs don't support GCC toolchain option compiler.clang30.exe=/opt/compiler-explorer/clang+llvm-3.0-x86_64-linux-Ubuntu-11_10/bin/clang++ @@ -863,6 +865,7 @@ compiler.zapcc190308.name=x86-64 Zapcc 190308 ############################### # Cross GCC group.cross.compilers=&ppcs:&mipss:&nanomips:&mrisc32:&msp:&gccarm:&avr:&rvgcc:&xtensaesp32:&xtensaesp32s2:&xtensaesp32s3:&platspec:&kalray:&s390x:&sh:&loongarch64:&c6x:&sparc:&sparc64:&sparcleon:&bpf +group.cross.supportsBinaryObject=true group.cross.supportsBinary=true group.cross.groupName=Cross GCC group.cross.supportsExecute=false @@ -916,8 +919,6 @@ group.sparc.compilers=&gccsparc # GCC for SPARC group.gccsparc.compilers=sparcg1220 -group.gccsparc.supportsBinary=true -group.gccsparc.supportsExecute=false group.gccsparc.baseName=SPARC gcc group.gccsparc.groupName=SPARC GCC group.gccsparc.isSemVer=true @@ -933,8 +934,6 @@ group.sparc64.compilers=&gccsparc64 # GCC for SPARC64 group.gccsparc64.compilers=sparc64g1220 -group.gccsparc64.supportsBinary=true -group.gccsparc64.supportsExecute=false group.gccsparc64.baseName=SPARC64 gcc group.gccsparc64.groupName=SPARC64 GCC group.gccsparc64.isSemVer=true @@ -950,8 +949,6 @@ group.sparcleon.compilers=&gccsparcleon # GCC for SPARC-LEON group.gccsparcleon.compilers=sparcleong1220 -group.gccsparcleon.supportsBinary=true -group.gccsparcleon.supportsExecute=false group.gccsparcleon.baseName=SPARC LEON gcc group.gccsparcleon.groupName=SPARC LEON GCC group.gccsparcleon.isSemVer=true @@ -967,8 +964,6 @@ group.c6x.compilers=&gccc6x # GCC for TI C6x group.gccc6x.compilers=c6xg1220 -group.gccc6x.supportsBinary=true -group.gccc6x.supportsExecute=false group.gccc6x.baseName=TI C6x gcc group.gccc6x.groupName=TI C6x GCC group.gccc6x.isSemVer=true @@ -983,8 +978,6 @@ compiler.c6xg1220.demangler=/opt/compiler-explorer/c6x/gcc-12.2.0/tic6x-elf/bin/ group.loongarch64.compilers=&gccloongarch64 # GCC for loongarch64 -group.gccloongarch64.supportsBinary=true -group.gccloongarch64.supportsExecute=false group.gccloongarch64.baseName=loongarch64 gcc group.gccloongarch64.groupName=loongarch64 gcc group.gccloongarch64.compilers=loongarch64g1220 @@ -1000,8 +993,6 @@ compiler.loongarch64g1220.demangler=/opt/compiler-explorer/loongarch64/gcc-12.2. group.sh.compilers=&gccsh # GCC for sh -group.gccsh.supportsBinary=true -group.gccsh.supportsExecute=false group.gccsh.baseName=sh gcc group.gccsh.groupName=sh gcc group.gccsh.compilers=shg494:shg950:shg1220 @@ -1027,8 +1018,6 @@ compiler.shg1220.demangler=/opt/compiler-explorer/sh/gcc-12.2.0/sh-unknown-elf/b group.s390x.compilers=&gccs390x # GCC for s390x -group.gccs390x.supportsBinary=true -group.gccs390x.supportsExecute=false group.gccs390x.baseName=s390x gcc group.gccs390x.groupName=s390x gcc group.gccs390x.compilers=gccs390x1120:s390xg1210:s390xg1220 @@ -1052,8 +1041,6 @@ compiler.s390xg1220.demangler=/opt/compiler-explorer/s390x/gcc-12.2.0/s390x-ibm- # Cross compilers for PPC group.ppcs.compilers=&ppc:&ppc64:&ppc64le group.ppcs.isSemVer=true -group.ppcs.supportsBinary=true -group.ppcs.supportsExecute=false ## POWER group.ppc.compilers=ppcg48:ppcg1120:ppcg1210:ppcg1220 @@ -1508,10 +1495,7 @@ compiler.avrg1220.demangler=/opt/compiler-explorer/avr/gcc-12.2.0/avr/bin/avr-c+ ############################### # GCC for MIPS group.mipss.compilers=&mips:&mipsel:&mips64:&mips64el - group.mipss.isSemVer=true -group.mipss.supportsBinary=true -group.mipss.supportsExecute=false ## MIPS group.mips.groupName=MIPS GCC @@ -1623,7 +1607,6 @@ compiler.mrisc32-gcc-trunk.objdumper=/opt/compiler-explorer/mrisc32-trunk/mrisc3 # GCC for RISC-V group.rvgcc.compilers=rv64-gcc1220:rv64-gcc1210:rv64-gcc1130:rv64-gcc1120:rv64-gcc1030:rv64-gcc1020:rv64-gcc940:rv64-gcc850:rv64-gcc820:rv32-gcc1220:rv32-gcc1210:rv32-gcc1130:rv32-gcc1120:rv32-gcc1030:rv32-gcc1020:rv32-gcc940:rv32-gcc850:rv32-gcc820 group.rvgcc.groupName=RISC-V GCC -group.rvgcc.supportsExecute=false group.rvgcc.isSemVer=true compiler.rv64-gcc820.exe=/opt/compiler-explorer/riscv64/gcc-8.2.0/riscv64-unknown-linux-gnu/bin/riscv64-unknown-linux-gnu-g++ diff --git a/etc/config/c++.defaults.properties b/etc/config/c++.defaults.properties index c12c92cb8..aae5b3c12 100644 --- a/etc/config/c++.defaults.properties +++ b/etc/config/c++.defaults.properties @@ -115,6 +115,7 @@ objdumper=objdump #androidNdk=/opt/google/android-ndk-r9c options= supportsBinary=true +supportsBinaryObject=true binaryHideFuncRe=^(__.*|_(init|start|fini)|(de)?register_tm_clones|call_gmon_start|frame_dummy|\.plt.*|_dl_relocate_static_pie)$ needsMulti=false stubRe=\bmain\b diff --git a/etc/config/c.amazon.properties b/etc/config/c.amazon.properties index 84f384cf9..d3c8c82af 100644 --- a/etc/config/c.amazon.properties +++ b/etc/config/c.amazon.properties @@ -148,7 +148,7 @@ group.cgcc-classic.baseName=x86 gcc group.cgcc-classic.supportsExecute=false group.cgcc-classic.supportsBinary=false group.cgcc-classic.licenseName=GNU CC GENERAL PUBLIC LICENSE (Clarified 11 Feb 1988) - +group.cgcc-classic.supportsBinaryObject=true compiler.cg127.exe=/opt/compiler-explorer/gcc-1.27/bin/gcc compiler.cg127.semver=1.27 @@ -506,6 +506,7 @@ group.cmosclang-trunk.groupName=llvm-mos (6502) clang group.cmosclang-trunk.options=-fno-lto -mllvm -zp-avail=224 group.cmosclang-trunk.instructionSet=6502 group.cmosclang-trunk.supportsBinary=true +group.cmosclang-trunk.supportsBinaryObject=false group.cmosclang-trunk.supportsExecute=false group.cmosclang-trunk.compilerType=llvmmos group.cmosclang-trunk.isSemVer=true @@ -544,6 +545,7 @@ compiler.cmos-osi-c1p-trunk.semver=osi-c1p group.rvcclang.compilers=&rv32cclang:&rv64cclang group.rvcclang.demangler=/opt/compiler-explorer/gcc-snapshot/bin/c++filt group.rvcclang.supportsBinary=true +group.rvcclang.supportsBinaryObject=true group.rvcclang.supportsExecute=false group.rvcclang.isSemVer=true group.rvcclang.licenseName=LLVM Apache 2 @@ -642,6 +644,7 @@ compiler.rv64-cclang.semver=(trunk) group.wasmcclang.compilers=wasm32cclang group.wasmcclang.groupName=Clang WebAssembly group.wasmcclang.supportsBinary=false +group.wasmcclang.supportsBinaryObject=false group.wasmcclang.licenseName=LLVM Apache 2 group.wasmcclang.licenseLink=https://github.com/llvm/llvm-project/blob/main/LICENSE.TXT group.wasmcclang.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions @@ -656,6 +659,7 @@ group.ppci.compilers=ppci055 group.ppci.groupName=ppci group.ppci.compilerType=ppci group.ppci.supportsBinary=false +group.ppci.supportsBinaryObject=false group.ppci.isSemVer=true group.ppci.baseName=ppci group.ppci.includeFlag=-I @@ -677,6 +681,7 @@ compiler.cicc1301.exe=/opt/compiler-explorer/intel/bin/icc compiler.cicc1301.semver=13.0.1 # intel 13.01 binary disabled: it just segfaults (no idea why) compiler.cicc1301.supportsBinary=false +compiler.cicc1301.supportsBinaryObject=false compiler.cicc16.exe=/opt/compiler-explorer/intel/xe_2016_update3/bin/icc compiler.cicc16.semver=16.0.3 compiler.cicc16.options=-x c -gcc-name=/opt/compiler-explorer/gcc-4.6.4/bin/gcc @@ -802,6 +807,7 @@ compiler.cicx202221.options=--gcc-toolchain=/opt/compiler-explorer/gcc-12.2.0 # Cross GCC group.ccross.compilers=&cppcs:&cmipss:&cnanomips:&cmrisc32:&cmsp:&cgccarm:&cavr:&rvcgcc:&cxtensaesp32:&cxtensaesp32s2:&cxtensaesp32s3:&cplatspec:&ckalray:&cs390x:&csh:&cloongarch64:&cc6x:&csparc:&csparc64:&csparcleon:&cbpf group.ccross.supportsBinary=false +group.ccross.supportsBinaryObject=true group.ccross.groupName=Cross GCC group.ccross.licenseLink=https://gcc.gnu.org/onlinedocs/gcc/Copying.html group.ccross.licenseName=GNU General Public License @@ -855,8 +861,6 @@ group.csparc.compilers=&cgccsparc # GCC for SPARC group.cgccsparc.compilers=csparcg1220 -group.cgccsparc.supportsBinary=true -group.cgccsparc.supportsExecute=false group.cgccsparc.baseName=SPARC gcc group.cgccsparc.groupName=SPARC GCC group.cgccsparc.isSemVer=true @@ -872,8 +876,6 @@ group.csparc64.compilers=&cgccsparc64 # GCC for SPARC64 group.cgccsparc64.compilers=csparc64g1220 -group.cgccsparc64.supportsBinary=true -group.cgccsparc64.supportsExecute=false group.cgccsparc64.baseName=SPARC64 gcc group.cgccsparc64.groupName=SPARC64 GCC group.cgccsparc64.isSemVer=true @@ -889,8 +891,6 @@ group.csparcleon.compilers=&cgccsparcleon # GCC for SPARC-LEON group.cgccsparcleon.compilers=csparcleong1220 -group.cgccsparcleon.supportsBinary=true -group.cgccsparcleon.supportsExecute=false group.cgccsparcleon.baseName=SPARC LEON gcc group.cgccsparcleon.groupName=SPARC LEON GCC group.cgccsparcleon.isSemVer=true @@ -907,8 +907,6 @@ group.cc6x.compilers=&cgccc6x # GCC for TI C6x group.cgccc6x.compilers=cc6xg1220 -group.cgccc6x.supportsBinary=true -group.cgccc6x.supportsExecute=false group.cgccc6x.baseName=TI C6x gcc group.cgccc6x.groupName=TI C6x GCC group.cgccc6x.isSemVer=true @@ -924,8 +922,6 @@ group.cloongarch64.compilers=&cgccloongarch64 # GCC for loongarch64 group.cgccloongarch64.compilers=cloongarch64g1220 -group.cgccloongarch64.supportsBinary=true -group.cgccloongarch64.supportsExecute=false group.cgccloongarch64.baseName=loongarch64 gcc group.cgccloongarch64.groupName=loongarch64 GCC group.cgccloongarch64.isSemVer=true @@ -941,8 +937,6 @@ group.csh.compilers=&cgccsh # GCC for sh group.cgccsh.compilers=cshg494:cshg950:cshg1220 -group.cgccsh.supportsBinary=true -group.cgccsh.supportsExecute=false group.cgccsh.baseName=sh gcc group.cgccsh.groupName=sh GCC group.cgccsh.isSemVer=true @@ -968,8 +962,6 @@ group.cs390x.compilers=&cgccs390x # GCC for s390x group.cgccs390x.compilers=cgccs390x112:cs390xg1210:cs390xg1220 -group.cgccs390x.supportsBinary=true -group.cgccs390x.supportsExecute=false group.cgccs390x.baseName=s390x gcc group.cgccs390x.groupName=s390x GCC group.cgccs390x.isSemVer=true @@ -991,8 +983,6 @@ compiler.cs390xg1220.demangler=/opt/compiler-explorer/s390x/gcc-12.2.0/s390x-ibm # Cross compilers for PPC group.cppcs.compilers=&cppc:&cppc64:&cppc64le group.cppcs.isSemVer=true -group.cppcs.supportsBinary=true -group.cppcs.supportsExecute=false group.cppc.compilers=cppcg1210:cppcg1120:cppcg48:cppcg1220 group.cppc.groupName=POWER @@ -1094,7 +1084,7 @@ compiler.cppc64leclang.semver=(snapshot) ############################### # GCC for ARM group.cgccarm.compilers=&cgcc32arm:&cgcc64arm:&cgcc64marm -group.cgccarm.supportsBinary=true +group.cgccarm.supportsBinaryObject=true group.cgccarm.supportsExecute=false # Some of the compilers don't like -isystem (as they assume the code must be C). # See https://github.com/compiler-explorer/compiler-explorer/issues/989 for discussion/ @@ -1114,6 +1104,7 @@ compiler.carm541.exe=/opt/compiler-explorer/gcc-arm-none-eabi-5_4-2016q3/bin/arm compiler.carm541.name=ARM gcc 5.4.1 (none) compiler.carm541.semver=5.4.1 compiler.carm541.supportsBinary=false +compiler.carm541.supportsBinaryObject=true compiler.carmg454.exe=/opt/compiler-explorer/arm/gcc-4.5.4/bin/arm-unknown-linux-gnueabi-gcc compiler.carmg454.name=ARM gcc 4.5.4 (linux) compiler.carmg454.semver=4.5.4 @@ -1127,6 +1118,7 @@ compiler.carm710.exe=/opt/compiler-explorer/arm/gcc-arm-none-eabi-7-2017-q4-majo compiler.carm710.name=ARM gcc 7.2.1 (none) compiler.carm710.semver=7.2.1 compiler.carm710.supportsBinary=false +compiler.carm710.supportsBinaryObject=true compiler.carmg640.exe=/opt/compiler-explorer/arm/gcc-6.4.0/arm-unknown-linux-gnueabi/bin/arm-unknown-linux-gnueabi-gcc compiler.carmg640.name=ARM gcc 6.4 (linux) compiler.carmg640.semver=6.4.0 @@ -1152,14 +1144,17 @@ compiler.carmce820.exe=/opt/compiler-explorer/arm-wince/gcc-ce-8.2.0/bin/arm-min compiler.carmce820.name=ARM gcc 8.2 (WinCE) compiler.carmce820.semver=8.2.0 compiler.carmce820.supportsBinary=false +compiler.carmce820.supportsBinaryObject=true compiler.carm831.exe=/opt/compiler-explorer/arm/gcc-arm-none-eabi-8-2019-q3-update/bin/arm-none-eabi-gcc compiler.carm831.name=ARM gcc 8.3.1 (none) compiler.carm831.semver=8.3.1 compiler.carm831.supportsBinary=false +compiler.carm831.supportsBinaryObject=true compiler.carm921.exe=/opt/compiler-explorer/arm/gcc-arm-none-eabi-9-2019-q4-major/bin/arm-none-eabi-gcc compiler.carm921.name=ARM gcc 9.2.1 (none) compiler.carm921.semver=9.2.1 compiler.carm921.supportsBinary=false +compiler.carm921.supportsBinaryObject=true compiler.carm1021.exe=/opt/compiler-explorer/arm/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-gcc compiler.carm1021.name=ARM gcc 10.2.1 (none) compiler.carm1021.semver=10.2.1 @@ -1176,6 +1171,7 @@ compiler.carm1121.exe=/opt/compiler-explorer/arm/gcc-arm-none-eabi-11.2-2022.02/ compiler.carm1121.name=ARM gcc 11.2.1 (none) compiler.carm1121.semver=11.2.1 compiler.carm1121.supportsBinary=false +compiler.carm1021.supportsBinaryObject=true compiler.carm930.exe=/opt/compiler-explorer/arm/gcc-9.3.0/arm-unknown-linux-gnueabihf/bin/arm-unknown-linux-gnueabihf-gcc compiler.carm930.name=ARM gcc 9.3 (linux) compiler.carm930.semver=9.3.0 @@ -1435,6 +1431,8 @@ compiler.cavrg464.semver=4.6.4 compiler.cavrg540.exe=/opt/compiler-explorer/avr/arduino-1.8.9/hardware/tools/avr/bin/avr-gcc compiler.cavrg540.semver=5.4.0 +compiler.cavrg540.supportsBinaryObject=true + compiler.cavrg540.objdumper=/opt/compiler-explorer/avr/arduino-1.8.9/hardware/tools/avr/bin/avr-objdump compiler.cavrg920.exe=/opt/compiler-explorer/avr/gcc-9.2.0/bin/avr-gcc @@ -1572,6 +1570,7 @@ group.cmrisc32.groupName=MRISC32 GCC group.cmrisc32.isSemVer=true group.cmrisc32.supportsBinary=true group.cmrisc32.supportsExecute=false +group.cmrisc32.supportsBinaryObject=true compiler.cmrisc32-gcc-trunk.exe=/opt/compiler-explorer/mrisc32-trunk/mrisc32-gnu-toolchain/bin/mrisc32-elf-gcc compiler.cmrisc32-gcc-trunk.name=MRISC32 gcc (trunk) @@ -1591,6 +1590,7 @@ compiler.rv64-cgcc820.alias=criscv820 compiler.rv64-cgcc820.semver=8.2.0 compiler.rv64-cgcc820.objdumper=/opt/compiler-explorer/riscv64/gcc-8.2.0/riscv64-unknown-linux-gnu/bin/riscv64-unknown-linux-gnu-objdump compiler.rv64-cgcc820.supportsBinary=true +compiler.rv64-cgcc820.supportsBinaryObject=true compiler.rv64-cgcc850.exe=/opt/compiler-explorer/riscv64/gcc-8.5.0/riscv64-unknown-linux-gnu/bin/riscv64-unknown-linux-gnu-gcc compiler.rv64-cgcc850.name=RISC-V rv64gc gcc 8.5.0 @@ -1609,6 +1609,7 @@ compiler.rv64-cgcc1020.name=RISC-V rv64gc gcc 10.2.0 compiler.rv64-cgcc1020.semver=10.2.0 compiler.rv64-cgcc1020.objdumper=/opt/compiler-explorer/riscv64/gcc-10.2.0/riscv64-unknown-linux-gnu/bin/riscv64-unknown-linux-gnu-objdump compiler.rv64-cgcc1020.supportsBinary=true +compiler.rv64-cgcc1020.supportsBinaryObject=true compiler.rv64-cgcc1030.exe=/opt/compiler-explorer/riscv64/gcc-10.3.0/riscv64-unknown-linux-gnu/bin/riscv64-unknown-linux-gnu-gcc compiler.rv64-cgcc1030.name=RISC-V rv64gc gcc 10.3.0 @@ -1646,6 +1647,7 @@ compiler.rv32-cgcc820.name=RISC-V rv32gc gcc 8.2.0 compiler.rv32-cgcc820.semver=8.2.0 compiler.rv32-cgcc820.objdumper=/opt/compiler-explorer/riscv32/gcc-8.2.0/riscv32-unknown-elf/bin/riscv32-unknown-elf-objdump compiler.rv32-cgcc820.supportsBinary=true +compiler.rv32-cgcc820.supportsBinaryObject=true compiler.rv32-cgcc850.exe=/opt/compiler-explorer/riscv32/gcc-8.5.0/riscv32-unknown-elf/bin/riscv32-unknown-elf-gcc compiler.rv32-cgcc850.name=RISC-V rv32gc gcc 8.5.0 @@ -1664,6 +1666,7 @@ compiler.rv32-cgcc1020.name=RISC-V rv32gc gcc 10.2.0 compiler.rv32-cgcc1020.semver=10.2.0 compiler.rv32-cgcc1020.objdumper=/opt/compiler-explorer/riscv32/gcc-10.2.0/riscv32-unknown-elf/bin/riscv32-unknown-elf-objdump compiler.rv32-cgcc1020.supportsBinary=true +compiler.rv32-cgcc1020.supportsBinaryObject=true compiler.rv32-cgcc1030.exe=/opt/compiler-explorer/riscv64/gcc-10.3.0/riscv64-unknown-linux-gnu/bin/riscv64-unknown-linux-gnu-gcc compiler.rv32-cgcc1030.name=RISC-V rv32gc gcc 10.3.0 @@ -1703,6 +1706,7 @@ group.cxtensaesp32.groupName=Xtensa ESP32 GCC group.cxtensaesp32.supportsBinary=false group.cxtensaesp32.instructionSet=xtensa group.cxtensaesp32.supportsAsmDocs=false +group.cxtensaesp32.supportsBinaryObject=true compiler.cesp32g2019r2.exe=/opt/compiler-explorer/xtensa/xtensa-esp32-elf-gcc8_2_0-esp-2019r2/bin/xtensa-esp32-elf-gcc compiler.cesp32g2019r2.objdumper=/opt/compiler-explorer/xtensa/xtensa-esp32-elf-gcc8_2_0-esp-2019r2/bin/xtensa-esp32-elf-objdump @@ -1730,6 +1734,7 @@ group.cxtensaesp32s2.groupName=Xtensa ESP32-S2 GCC group.cxtensaesp32s2.supportsBinary=false group.cxtensaesp32s2.instructionSet=xtensa group.cxtensaesp32s2.supportsAsmDocs=false +group.cxtensaesp32s2.supportsBinaryObject=true compiler.cesp32s2g2019r2.exe=/opt/compiler-explorer/xtensa/xtensa-esp32s2-elf-gcc8_2_0-esp-2019r2/bin/xtensa-esp32s2-elf-gcc compiler.cesp32s2g2019r2.objdumper=/opt/compiler-explorer/xtensa/xtensa-esp32s2-elf-gcc8_2_0-esp-2019r2/bin/xtensa-esp32s2-elf-objdump @@ -1757,6 +1762,7 @@ group.cxtensaesp32s3.groupName=Xtensa ESP32-S3 GCC group.cxtensaesp32s3.supportsBinary=false group.cxtensaesp32s3.instructionSet=xtensa group.cxtensaesp32s3.supportsAsmDocs=false +group.cxtensaesp32s3.supportsBinaryObject=true compiler.cesp32s3g2020r3.exe=/opt/compiler-explorer/xtensa/xtensa-esp32s3-elf-gcc8_4_0-esp-2020r3/bin/xtensa-esp32s3-elf-gcc compiler.cesp32s3g2020r3.objdumper=/opt/compiler-explorer/xtensa/xtensa-esp32s3-elf-gcc8_4_0-esp-2020r3/bin/xtensa-esp32s3-elf-objdump diff --git a/etc/config/c.defaults.properties b/etc/config/c.defaults.properties index 78e592a89..d901fd47d 100644 --- a/etc/config/c.defaults.properties +++ b/etc/config/c.defaults.properties @@ -5,6 +5,7 @@ demangler=c++filt objdumper=objdump postProcess= supportsBinary=true +supportsBinaryObject=true binaryHideFuncRe=^(__.*|_(init|start|fini)|(de)?register_tm_clones|call_gmon_start|frame_dummy|\.plt.*)$ stubRe=\bmain\b stubText=int main(void){return 0;/*stub provided by Compiler Explorer*/} diff --git a/etc/config/d.amazon.properties b/etc/config/d.amazon.properties index 46812c9a9..dc9de26d9 100644 --- a/etc/config/d.amazon.properties +++ b/etc/config/d.amazon.properties @@ -46,6 +46,7 @@ compiler.gdctrunk.semver=(trunk) group.gdccross.compilers=&gdcs390x:&gdcppc:&gdcppc64:&gdcppc64le:&gdcmips64:&gdcmips:&gdcmipsel:&gdcarm:&gdcarm64:&gdcriscv:&gdcriscv64 group.gdccross.supportsExecute=false group.gdccross.supportsBinary=true +group.gdccross.supportsBinaryObject=true ### GDC for RISCV group.gdcriscv.compilers=gdcriscv1220 diff --git a/etc/config/d.defaults.properties b/etc/config/d.defaults.properties index 9e6e37812..7e7888842 100644 --- a/etc/config/d.defaults.properties +++ b/etc/config/d.defaults.properties @@ -1,6 +1,7 @@ compilers=/usr/bin/gdc:/usr/bin/gdc-9 demangler=ddemangle supportsBinary=true +supportsBinaryObject=true objdumper=objdump stubRe=\bmain\b stubText=int main(){return 0;/*stub provided by Compiler Explorer*/} diff --git a/etc/config/rust.amazon.properties b/etc/config/rust.amazon.properties index a7748f436..0a766e6e0 100644 --- a/etc/config/rust.amazon.properties +++ b/etc/config/rust.amazon.properties @@ -14,6 +14,8 @@ group.rust.baseName=rustc group.rust.licenseLink=https://github.com/rust-lang/rust/blob/master/COPYRIGHT group.rust.licenseName=Dual-licensed under Apache 2.0 and MIT terms group.rust.licensePreamble=Rust is licensed under the Apache License, Version 2.0 or the MIT license +group.rust.supportsBinary=true +group.rust.supportsBinaryObject=true compiler.r1660.exe=/opt/compiler-explorer/rust-1.66.0/bin/rustc compiler.r1660.semver=1.66.0 compiler.r1650.exe=/opt/compiler-explorer/rust-1.65.0/bin/rustc @@ -163,6 +165,8 @@ compiler.gccrs-snapshot.notification=Rust GCC Frontend - Very early snapshot group.rustgcc.compilerType=gccrs group.rustgcc.compilers=gccrs-snapshot group.rustgcc.groupName=Rust-GCC +group.rustgcc.supportsBinary=true +group.rustgcc.supportsBinaryObject=true ## needed, until its support is on-par with rustc (at some arbitrary version). group.rustgcc.options=-frust-incomplete-and-experimental-compiler-do-not-use @@ -170,7 +174,9 @@ group.rustccggcc.compilers=rustccggcc-master compiler.rustccggcc-master.exe=/opt/compiler-explorer/rustc-cg-gcc-master/bin/rustc compiler.rustccggcc-master.semver=(rustc - GCC) group.rustccggcc.compilerType=rustc-cg-gcc +group.rustccggcc.supportsExecute=false group.rustccggcc.supportsBinary=false +group.rustccggcc.supportsBinaryObject=false compiler.mrustc-master.exe=/opt/compiler-explorer/mrustc-master/bin/mrustc compiler.mrustc-master.semver=(mrustc) @@ -178,6 +184,7 @@ group.mrustc.compilerType=mrustc group.mrustc.compilers=mrustc-master group.mrustc.supportsExecute=false group.mrustc.supportsBinary=false +group.mrustc.supportsBinaryObject=false ################################# ################################# diff --git a/lib/base-compiler.ts b/lib/base-compiler.ts index 3ad4cd3f6..ac7c53d32 100644 --- a/lib/base-compiler.ts +++ b/lib/base-compiler.ts @@ -399,6 +399,8 @@ export class BaseCompiler implements ICompiler { maxSize: number, intelAsm, demangle, + staticReloc: boolean, + dynamicReloc: boolean, filters: ParseFiltersAndOutputOptions, ) { outputFilename = this.getObjdumpOutputFilename(outputFilename); @@ -409,7 +411,7 @@ export class BaseCompiler implements ICompiler { } const objdumper = new this.objdumperClass(); - const args = objdumper.getDefaultArgs(outputFilename, demangle, intelAsm); + const args = objdumper.getDefaultArgs(outputFilename, demangle, intelAsm, staticReloc, dynamicReloc); if (this.externalparser) { const objResult = await this.externalparser.objdumpAndParseAssembly(result.dirPath, args, filters); @@ -599,10 +601,12 @@ export class BaseCompiler implements ICompiler { userOptions?: string[], ): string[] { let options = ['-g', '-o', this.filename(outputFilename)]; - if (this.compiler.intelAsm && filters.intel && !filters.binary) { + if (this.compiler.intelAsm && filters.intel && !filters.binary && !filters.binaryObject) { options = options.concat(this.compiler.intelAsm.split(' ')); } - if (!filters.binary) options = options.concat('-S'); + if (!filters.binary && !filters.binaryObject) options = options.concat('-S'); + else if (filters.binaryObject) options = options.concat('-c'); + return options; } @@ -1280,9 +1284,7 @@ export class BaseCompiler implements ICompiler { if (!isInExpandedCode && startOfExpandedCode.test(obj.text)) { isInExpandedCode = true; isInTree = false; - } - - if (!isInTree && startOfTree.test(obj.text)) { + } else if (!isInTree && startOfTree.test(obj.text)) { isInExpandedCode = false; isInTree = true; } @@ -1455,6 +1457,7 @@ export class BaseCompiler implements ICompiler { const outputFilename = this.getExecutableFilename(dirPath, this.outputFilebase, key); const buildFilters: ParseFiltersAndOutputOptions = Object.assign({}, key.filters); + buildFilters.binaryObject = false; buildFilters.binary = true; buildFilters.execute = true; @@ -1739,7 +1742,7 @@ export class BaseCompiler implements ICompiler { const makeGccDump = backendOptions.produceGccDump && backendOptions.produceGccDump.opened && this.compiler.supportsGccDump; - const downloads = await this.setupBuildEnvironment(key, dirPath, filters.binary); + const downloads = await this.setupBuildEnvironment(key, dirPath, filters.binary || filters.binaryObject); const [ asmResult, astResult, @@ -2154,6 +2157,10 @@ export class BaseCompiler implements ICompiler { for (const key in filters) { filters[key] = false; } + + if (filters.binaryObject && !this.compiler.supportsBinaryObject) { + delete filters.binaryObject; + } } if (files && files.length > 0) { @@ -2532,8 +2539,17 @@ but nothing was dumped. Possible causes are: const maxSize = this.env.ceProps('max-asm-size', 64 * 1024 * 1024); const optPromise = result.hasOptOutput ? this.processOptOutput(result.optPath) : ''; const asmPromise = - filters.binary && this.supportsObjdump() - ? this.objdump(outputFilename, result, maxSize, filters.intel, filters.demangle, filters) + (filters.binary || filters.binaryObject) && this.supportsObjdump() + ? this.objdump( + outputFilename, + result, + maxSize, + filters.intel, + filters.demangle, + filters.binaryObject, + false, + filters, + ) : (async () => { if (result.asmSize === undefined) { result.asm = ''; diff --git a/lib/compiler-finder.ts b/lib/compiler-finder.ts index ffa6c1c28..b26149da1 100644 --- a/lib/compiler-finder.ts +++ b/lib/compiler-finder.ts @@ -194,6 +194,7 @@ export class CompilerFinder { const ceToolsPath = props('ceToolsPath', './'); const supportsBinary = !!props('supportsBinary', true); + const supportsBinaryObject = !!props('supportsBinaryObject', false); const interpreted = !!props('interpreted', false); const supportsExecute = (interpreted || supportsBinary) && !!props('supportsExecute', true); const executionWrapper = props('executionWrapper', ''); @@ -257,6 +258,7 @@ export class CompilerFinder { adarts: props('adarts', ''), supportsDemangle: !!demangler, supportsBinary, + supportsBinaryObject, interpreted, supportsExecute, executionWrapper, diff --git a/lib/compilers/ada.ts b/lib/compilers/ada.ts index 89f500f4b..6c867e7ab 100644 --- a/lib/compilers/ada.ts +++ b/lib/compilers/ada.ts @@ -51,10 +51,23 @@ export class AdaCompiler extends BaseCompiler { return path.join(dirPath, 'example'); } - override getOutputFilename(dirPath) { + override getOutputFilename(dirPath: string, outputFilebase: string, key?: any): string { // The basename here must match the value used in the pragma Source_File // in the user provided source. - return path.join(dirPath, 'example.out'); + + // Beware that GNAT is picky on output filename: + // - the basename must match the unit name (emits error otherwise) + // - can't do "-c -o foo.out", output must end with .o + // - "foo.o" may be used by intermediary file, so "-o foo.o" will not + // work if building an executable. + + if (key && key.filters && key.filters.binary) { + return path.join(dirPath, 'example'); + } else if (key && key.filters && key.filters.binaryObject) { + return path.join(dirPath, 'example.o'); + } else { + return path.join(dirPath, 'example.s'); + } } override prepareArguments(userOptions, filters, backendOptions, inputFilename, outputFilename, libraries) { @@ -80,11 +93,11 @@ export class AdaCompiler extends BaseCompiler { gnatmake_opts.push(`--RTS=${this.compiler.adarts}`); } - if (backendOptions.produceGnatDebug && this.compiler.supportsGnatDebugViews) + if (!filters.execute && backendOptions.produceGnatDebug && this.compiler.supportsGnatDebugViews) // This is using stdout gnatmake_opts.push('-gnatGL'); - if (backendOptions.produceGnatDebugTree && this.compiler.supportsGnatDebugViews) + if (!filters.execute && backendOptions.produceGnatDebugTree && this.compiler.supportsGnatDebugViews) // This is also using stdout gnatmake_opts.push('-gnatdt'); @@ -95,9 +108,7 @@ export class AdaCompiler extends BaseCompiler { inputFilename, ); - if (filters.binary) { - gnatmake_opts.push('-o', outputFilename); - } else { + if (!filters.execute && !filters.binary && !filters.binaryObject) { gnatmake_opts.push( '-S', // Generate ASM '-c', // Compile only @@ -112,6 +123,24 @@ export class AdaCompiler extends BaseCompiler { gnatmake_opts.push(opt); } } + } else if (filters.binaryObject) { + gnatmake_opts.push( + '-c', // Compile only + ); + + // produce assembly output in outputFilename + compiler_opts.push('-o', outputFilename); + + if (this.compiler.intelAsm && filters.intel) { + for (const opt of this.compiler.intelAsm.split(' ')) { + gnatmake_opts.push(opt); + } + } + // if (this.compiler.intelAsm && filters.intel) { + // options = options.concat(this.compiler.intelAsm.split(' ')); + // } + } else { + gnatmake_opts.push('-o', outputFilename); } // Spread the options coming from outside (user, backend or config options) @@ -146,35 +175,4 @@ export class AdaCompiler extends BaseCompiler { return gnatmake_opts.concat('-cargs', compiler_opts, '-largs', linker_opts, '-bargs', binder_opts); } - - override async runCompiler( - compiler: string, - options: string[], - inputFilename: string, - execOptions: ExecutionOptions, - ): Promise { - if (!execOptions) { - execOptions = this.getDefaultExecOptions(); - } - - if (!execOptions.customCwd) { - execOptions.customCwd = path.dirname(inputFilename); - } - - // create a subdir so that files automatically created by GNAT don't - // conflict with anything else in parent dir. - const appHome = path.dirname(inputFilename); - const temp_dir = path.join(appHome, 'tempsub'); - await fs.mkdir(temp_dir); - - // Set the working directory to be the temp directory that has been created - execOptions.appHome = appHome; - execOptions.customCwd = temp_dir; - - const result = await this.exec(compiler, options, execOptions); - return { - ...this.transformToCompilationResult(result, inputFilename), - languageId: this.getCompilerResultLanguageId(), - }; - } } diff --git a/lib/compilers/cc65.ts b/lib/compilers/cc65.ts index bbb5467cb..8eb286a60 100644 --- a/lib/compilers/cc65.ts +++ b/lib/compilers/cc65.ts @@ -98,9 +98,20 @@ export class Cc65Compiler extends BaseCompiler { maxSize: number, intelAsm, demangle, + staticReloc, + dynamicReloc, filters: ParseFiltersAndOutputOptions, ) { - const res = await super.objdump(outputFilename, result, maxSize, intelAsm, demangle, filters); + const res = await super.objdump( + outputFilename, + result, + maxSize, + intelAsm, + demangle, + staticReloc, + dynamicReloc, + filters, + ); const dirPath = path.dirname(outputFilename); const nesFile = path.join(dirPath, 'example.nes'); diff --git a/lib/compilers/jakt.ts b/lib/compilers/jakt.ts index e9948fb88..a9ef1e3e5 100644 --- a/lib/compilers/jakt.ts +++ b/lib/compilers/jakt.ts @@ -49,9 +49,21 @@ export class JaktCompiler extends BaseCompiler { maxSize: number, intelAsm, demangle, + staticReloc, + dynamicReloc, filters: ParseFiltersAndOutputOptions, ) { - const objdumpResult = await super.objdump(outputFilename, result, maxSize, intelAsm, demangle, filters); + const objdumpResult = await super.objdump( + outputFilename, + result, + maxSize, + intelAsm, + demangle, + staticReloc, + dynamicReloc, + filters, + ); + objdumpResult.languageId = 'asm'; return objdumpResult; } diff --git a/lib/compilers/llvm-mos.ts b/lib/compilers/llvm-mos.ts index b5eb03686..af18a4dd7 100644 --- a/lib/compilers/llvm-mos.ts +++ b/lib/compilers/llvm-mos.ts @@ -62,6 +62,8 @@ export class LLVMMOSCompiler extends ClangCompiler { maxSize: number, intelAsm, demangle, + staticReloc, + dynamicReloc, filters: ParseFiltersAndOutputOptions, ) { if (!outputFilename.endsWith('.elf') && (await utils.fileExists(outputFilename + '.elf'))) { @@ -69,7 +71,16 @@ export class LLVMMOSCompiler extends ClangCompiler { } intelAsm = false; - const res = await super.objdump(outputFilename, result, maxSize, intelAsm, demangle, filters); + const res = await super.objdump( + outputFilename, + result, + maxSize, + intelAsm, + demangle, + staticReloc, + dynamicReloc, + filters, + ); if (this.compiler.exe.includes('nes')) { let nesFile = outputFilename; diff --git a/lib/compilers/racket.ts b/lib/compilers/racket.ts index f77ba783a..f67275eb4 100644 --- a/lib/compilers/racket.ts +++ b/lib/compilers/racket.ts @@ -97,6 +97,8 @@ export class RacketCompiler extends BaseCompiler { maxSize: number, intelAsm: any, demangle: any, + staticReloc, + dynamicReloc, filters: ParseFiltersAndOutputOptions, ): Promise { // Decompile to assembly via `raco decompile` with `disassemble` package diff --git a/lib/compilers/rust.ts b/lib/compilers/rust.ts index b0cb6484c..0fbce4e0c 100644 --- a/lib/compilers/rust.ts +++ b/lib/compilers/rust.ts @@ -138,6 +138,8 @@ export class RustCompiler extends BaseCompiler { if (this.linker) { options = options.concat(`-Clinker=${this.linker}`); } + } else if (filters.binaryObject) { + options = options.concat(['--crate-type', 'lib']); } else { if (!userRequestedEmit) { options = options.concat('--emit', 'asm'); diff --git a/lib/compilers/z88dk.ts b/lib/compilers/z88dk.ts index b5d73dd1a..ee388b9b9 100644 --- a/lib/compilers/z88dk.ts +++ b/lib/compilers/z88dk.ts @@ -116,6 +116,8 @@ export class z88dkCompiler extends BaseCompiler { maxSize: number, intelAsm, demangle, + staticReloc, + dynamicReloc, filters: ParseFiltersAndOutputOptions, ) { outputFilename = this.getObjdumpOutputFilename(outputFilename); diff --git a/lib/external-parsers/base.ts b/lib/external-parsers/base.ts index 4420ecb54..f1346569f 100644 --- a/lib/external-parsers/base.ts +++ b/lib/external-parsers/base.ts @@ -35,6 +35,7 @@ export class ExternalParserBase implements IExternalParser { if (fromStdin) parameters.push('-stdin'); if (filters.binary) parameters.push('-binary'); + if (filters.binaryObject) parameters.push('-binary'); if (filters.labels) parameters.push('-unused_labels'); if (filters.directives) parameters.push('-directives'); if (filters.commentOnly) parameters.push('-comment_only'); diff --git a/lib/objdumper/base.ts b/lib/objdumper/base.ts index 6d4559679..811b073cf 100644 --- a/lib/objdumper/base.ts +++ b/lib/objdumper/base.ts @@ -25,9 +25,17 @@ export abstract class BaseObjdumper { constructor(protected readonly intelAsmOptions: string[], protected readonly widthOptions: string[]) {} - getDefaultArgs(outputFilename: string, demangle?: boolean, intelAsm?: boolean) { + getDefaultArgs( + outputFilename: string, + demangle?: boolean, + intelAsm?: boolean, + staticReloc?: boolean, + dynamicReloc?: boolean, + ) { const args = ['-d', outputFilename, '-l', ...this.widthOptions]; + if (staticReloc) args.push('-r'); + if (dynamicReloc) args.push('-R'); if (demangle) args.push('-C'); if (intelAsm) args.push(...this.intelAsmOptions); diff --git a/lib/options-handler.ts b/lib/options-handler.ts index c7429c527..b6cff811e 100755 --- a/lib/options-handler.ts +++ b/lib/options-handler.ts @@ -72,6 +72,7 @@ type OptionsType = { defaultCompiler: Record; compileOptions: Record; supportsBinary: Record; + supportsBinaryObject: Record; supportsExecute: boolean; supportsLibraryCodeFilter: boolean; languages: Record; @@ -111,6 +112,7 @@ export class ClientOptionsHandler { compilerProps: CompilerProps['get']; ceProps: PropertyGetter; supportsBinary: Record; + supportsBinaryObject: Record; supportsExecutePerLanguage: Record; supportsExecute: boolean; supportsLibraryCodeFilterPerLanguage: Record; @@ -144,6 +146,7 @@ export class ClientOptionsHandler { const languages = compilerProps.languages; this.supportsBinary = this.compilerProps(languages, 'supportsBinary', true, res => !!res); + this.supportsBinaryObject = this.compilerProps(languages, 'supportsBinaryObject', true, res => !!res); this.supportsExecutePerLanguage = this.compilerProps(languages, 'supportsExecute', true, res => !!res); this.supportsExecute = Object.values(this.supportsExecutePerLanguage).some(Boolean); @@ -176,6 +179,7 @@ export class ClientOptionsHandler { defaultCompiler: this.compilerProps(languages, 'defaultCompiler', ''), compileOptions: this.compilerProps(languages, 'defaultOptions', ''), supportsBinary: this.supportsBinary, + supportsBinaryObject: this.supportsBinaryObject, supportsExecute: this.supportsExecute, supportsLibraryCodeFilter: this.supportsLibraryCodeFilter, languages: languages, diff --git a/lib/parsers/asm-parser-vc.js b/lib/parsers/asm-parser-vc.js index 0fb04f14c..1a2877e83 100644 --- a/lib/parsers/asm-parser-vc.js +++ b/lib/parsers/asm-parser-vc.js @@ -87,7 +87,7 @@ export class VcAsmParser extends AsmParser { } processAsm(asm, filters) { - if (filters.binary) { + if (filters.binary || filters.binaryObject) { return this.asmBinaryParser.processAsm(asm, filters); } diff --git a/lib/parsers/asm-parser-vc6.js b/lib/parsers/asm-parser-vc6.js index 0bacf61b2..669be05ea 100644 --- a/lib/parsers/asm-parser-vc6.js +++ b/lib/parsers/asm-parser-vc6.js @@ -89,7 +89,7 @@ export class Vc6AsmParser extends AsmParser { } processAsm(asm, filters) { - if (filters.binary) { + if (filters.binary || filters.binaryObject) { return this.asmBinaryParser.processAsm(asm, filters); } diff --git a/lib/parsers/asm-parser.ts b/lib/parsers/asm-parser.ts index 44c1b7af6..7e88d8d20 100644 --- a/lib/parsers/asm-parser.ts +++ b/lib/parsers/asm-parser.ts @@ -62,6 +62,8 @@ export class AsmParser extends AsmRegex implements IAsmParser { binaryHideFuncRe: RegExp | null; maxAsmLines: number; asmOpcodeRe: RegExp; + relocationRe: RegExp; + relocDataSymNameRe: RegExp; lineRe: RegExp; labelRe: RegExp; destRe: RegExp; @@ -117,6 +119,8 @@ export class AsmParser extends AsmRegex implements IAsmParser { } this.asmOpcodeRe = /^\s*(?
[\da-f]+):\s*(?([\da-f]{2} ?)+)\s*(?.*)/; + this.relocationRe = /^\s*(?
[\da-f]+):\s*(?(R_[\dA-Z_]+))\s*(?.*)/; + this.relocDataSymNameRe = /^(?[^\d-+][\w.]*)?\s*(?.*)$/; this.lineRe = /^(\/[^:]+):(?\d+).*/; // labelRe is made very greedy as it's also used with demangled objdump @@ -295,7 +299,9 @@ export class AsmParser extends AsmRegex implements IAsmParser { // Remove labels which do not have a definition. removeLabelsWithoutDefinition(asm, labelDefinitions) { for (const obj of asm) { - obj.labels = obj.labels.filter(label => labelDefinitions[label.name]); + if (obj.labels) { + obj.labels = obj.labels.filter(label => labelDefinitions[label.name]); + } } } @@ -325,7 +331,7 @@ export class AsmParser extends AsmRegex implements IAsmParser { } processAsm(asmResult, filters: ParseFiltersAndOutputOptions): ParsedAsmResult { - if (filters.binary) return this.processBinaryAsm(asmResult, filters); + if (filters.binary || filters.binaryObject) return this.processBinaryAsm(asmResult, filters); const startTime = process.hrtime.bigint(); @@ -709,6 +715,19 @@ export class AsmParser extends AsmRegex implements IAsmParser { labels: labelsInLine, }); } + + match = line.match(this.relocationRe); + if (match) { + const address = parseInt(match.groups.address, 16); + const relocname = match.groups.relocname; + const relocdata = match.groups.relocdata; + // value/addend matched but not used yet. + const match_value = relocdata.match(this.relocDataSymNameRe); + asm.push({ + text: ` ${relocname} ${relocdata}`, + address: address, + }); + } } this.removeLabelsWithoutDefinition(asm, labelDefinitions); diff --git a/lib/tooling/pahole-tool.js b/lib/tooling/pahole-tool.js index e7c320f59..95769354a 100644 --- a/lib/tooling/pahole-tool.js +++ b/lib/tooling/pahole-tool.js @@ -32,7 +32,7 @@ export class PaholeTool extends BaseTool { } async runTool(compilationInfo, inputFilepath, args) { - if (!compilationInfo.filters.binary) { + if (!compilationInfo.filters.binary || !compilationInfo.filters.binaryObject) { return this.createErrorResponse('Pahole requires a binary output'); } diff --git a/lib/tooling/readelf-tool.js b/lib/tooling/readelf-tool.js index 618e8ce6d..2f48a9253 100644 --- a/lib/tooling/readelf-tool.js +++ b/lib/tooling/readelf-tool.js @@ -32,7 +32,7 @@ export class ReadElfTool extends BaseTool { } async runTool(compilationInfo, inputFilename, args) { - if (!compilationInfo.filters.binary) { + if (!compilationInfo.filters.binary && !compilationInfo.filters.binaryObject) { return this.createErrorResponse('readelf requires an executable'); } diff --git a/static/panes/compiler.ts b/static/panes/compiler.ts index 867bfd7c2..d23ea4eb6 100644 --- a/static/panes/compiler.ts +++ b/static/panes/compiler.ts @@ -260,6 +260,8 @@ export class Compiler extends MonacoPane; private filterBinaryButton: JQuery; private filterBinaryTitle: JQuery; + private filterBinaryObjectButton: JQuery; + private filterBinaryObjectTitle: JQuery; private filterExecuteButton: JQuery; private filterExecuteTitle: JQuery; private filterLabelsButton: JQuery; @@ -1130,6 +1132,10 @@ export class Compiler extends MonacoPane { if (!this.compiler) return {}; const filters = this.filters.get(); + if (filters.binaryObject && !this.compiler.supportsBinaryObject) { + delete filters.binaryObject; + } + if (filters.binary && !this.compiler.supportsBinary) { delete filters.binary; } @@ -1487,7 +1493,10 @@ export class Compiler extends MonacoPane { if (obj.opcodes) { @@ -2243,6 +2252,9 @@ export class Compiler extends MonacoPane