Open umbertov opened 1 year ago
Or does it need a source code modification?
I suspect it needs a source modification, specifically in Parse
:
https://github.com/SRI-CSL/gllvm/blob/49c0709a810dbac31ea931f99d008e116c18de6a/shared/parser.go#L159
That function is aware of a bunch of flags; it probably needs to be made aware of --target
.
it probably needs to be made aware of --target
That's what i thought as well, I am unfamiliar with the codebase though, and I am not sure which callback i should assign it to: it might be compileLinkBinaryCallback
, but I am not sure about that. Do you have a suggestion? Or perhaps i just go with trial & error?
Do you have a suggestion? Or perhaps i just go with trial & error?
I'd trial and error it 🙂 -- compileLinkBinaryCallback
sounds correct, but I haven't made any contributions to that bit in a while so I can't state that confidently.
Yes my guess is that it is both compile and link. If you do fix it, can you please make a pull request?
Yes, I'm planning to have a look at it today, if I'm successful you'll find a pull request :smile:
EDIT: Just found a workaround, see next message
Hello, I made the modification in this commit. I added the following code:
"-target": {1, pr.compileLinkBinaryCallback},
Note: the flag is -target
here instead of the previously mentioned --target
. Clang accepts either one of them, but i had some error when using --target
and didn't want to lose focus troubleshooting.
It is almost there, meaning that an aarch64 ELF executable is created, but no .llvm_bc
section is added to the executable! This is because the final objcopy
still fails.
gclang -target aarch64-linux-gnu /tmp/prova/a.c
# outputs:
objcopy: Unable to recognise the format of the input file `.a.c.o'
WARNING:attachBitcodePathToObject: objcopy [--add-section .llvm_bc=/tmp/gllvm3259057631 .a.c.o] failed because exit status 1
You can see that a warning is printed. The a.out
file is however created, and it is a valid aarch64 executable:
file a.out
a.out: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, not stripped
But it won't contain the .llvm_bc
section, in fact get-bc
fails:
get-bc a.out
ERROR:Error reading the .llvm_bc section of ELF file a.out.
it is verifiable independently via readelf
:
readelf -S a.out | grep .llvm_bc # no output
I suspect that the -target
flag in parser.go
should be marked with the callback objectFileCallback
in addition to compileLinkBinaryCallback
.
Is there a way to do this callback composition easily?
Just found out that for some reason, objcopy
(GNU toolchain) is the default, not llvm-objcopy
from the LLVM toolchain.
In order to get proper cross-compilation to work end-to-end, i need to set the environment variable GLLVM_OBJCOPY
to llvm-objcopy
.
So this works on my fork:
GLLVM_OBJCOPY=llvm-objcopy gclang -target aarch64-linux-gnu a.c
If for some reason you want to use the GNU objcopy
, you'll need to install a cross GCC toolchain and do:
GLLVM_OBJCOPY=aarch64-linux-gnu-objcopy gclang -target aarch64-linux-gnu a.c
I found out that the decision is carried in injectPath()
inside the shared/compiler.go
file, in lines 211-224:
if runtime.GOOS == osDARWIN {
if len(LLVMLd) > 0 {
attachCmd = LLVMLd
} else {
attachCmd = "ld"
}
attachCmdArgs = []string{"-r", "-keep_private_externs", objFile, "-sectcreate", DarwinSegmentName, DarwinSectionName, tmpFile.Name(), "-o", objFile}
} else {
if len(LLVMObjcopy) > 0 {
attachCmd = LLVMObjcopy
} else {
attachCmd = "objcopy"
}
attachCmdArgs = []string{"--add-section", ELFSectionName + "=" + tmpFile.Name(), objFile}
}
In particular, the culprit seems to be attachCmd = "objcopy"
as the fallback case when the OS is not Mac, and LLVMObjcopy
is not set, which in turn is set in shared/environment.go
and corresponds to the GLLVM_OBJCOPY
environment variable.
I may be opinionated here, but i think that you should default to llvm-objcopy
instead of objcopy
, because the former comes from LLVM toolchain, supports all targets and it is more than reasonable to assume that it is going to be present on the system. The GNU objcopy
in turn needs to be built for each specific architecture, so you'd have to install it explicitly along with a cross toolchain, and call the prefixed executable (i.e. aarch64-linux-gnu-objcopy
).
I'll look at this more closely later today and tomorrow. I am fine with the objcopy thing, but the main thing is it will need to be documented in the README.md, especially the environment variable. But thanks for all your effort!
So it wouldn't hurt to go the extra yards to support the --target=ARCHSTRING would it? That would have to be done with a pattern like:
{`^--target=.+$`, flagInfo{0, pr.compileLinkUnaryCallback}},
Thanks Ian! It is actually my first time writing real Go code, so i didn't quite know what Go's idiomatic way was, I just went with trial & error and found -target
to work immediately.
Tomorrow morning I'll get back at the pull request & add this change & remove the llvm-objcopy
default.
Perhaps we should also add a couple lines in the README.md mentioning that cross compilation is supported, but needs the GLLVM_OBJCOPY env var as well?
On a side note (again, first time Golang user), i noticed that when i forked the project, the change in URL messed up all the import github.com/SRI-CSL/*
statements, and i had to sed 's/SRI-CSL/umbertov/g'
all the files in the repo to make go install
not complain about missing imports. Is there a handy way to avoid that?
Yes the url thing is a pain in the ass. I know of no way around it, but my go-fu is on the wain.
Yes mentioning cross-compiling requires GLLVM_OBJCOPY would be good and may save someone else some pain!
Hello, I am already using
gclang
/gclang++
successfully on a project for which LLVM bytecode is extracted, processed and finally lowered to (native) machine code.I need to perform the exact same task, but in a cross-compilation setting. I expected this to be rather easy since by Clang's design, it is sufficient to pass a
--target=my_architecture
as a flag when building. As it turns out,gclang
does not recognize this flag, and ends up with a bad call toobjcopy
.Minimal reproducible example
You just need the simplest possible C program to reproduce this. I wrote the program in the file
a.c
:Then we run
clang
ona.c
and verify that an aarch64 executable is successfully created:Doing the exact same with
gclang
results in an error:I paste the error below:
If i run
gclang
with the-v
flag, i get:Is there an easy user-side fix to this problem? Or does it need a source code modification? This problem is mentioned in #63 , and it is hinted to have a look at parser.go, but the author didn't follow up, and i didn't find relevant pull requests.