I'm trying to get dragonegg built and running on my mac. Using LLVM 3.5 and gcc 4.8, from the homebrew package manager.
Compiling dragonegg in per the readme (GCC=/usr/local/bin/gcc-4.8 LLVM_CONFIG=/usr/local/bin/llvm-config-3.5 make) ends with this error:
Compiling Cache.cpp
/Users/aelberg/Development/dragonegg-3.5.0.src/src/Cache.cpp:243:15: error: no matching function for call to 'operator new'
WeakVH *W = new (&(*slot)->V) WeakVH(V);
^ ~~~~~~~~~~~~~
note: candidate function not viable: requires 1 argument, but 2 were provided
1 error generated.
make: *** [Cache.o] Error 1
This seems to relate to the libc++ vs. libstdc++ issues that have been a problem compiling on the mac. And dragonegg will compile with GCC=/usr/local/bin/gcc-4.8 LLVM_CONFIG=/usr/local/bin/llvm-config-3.5 LDFLAGS="-L/usr/local/lib/ -L/usr/lib -L/usr/local/lib/llvm-3.5/usr/lib" CXX="/usr/local/bin/clang++-3.5 -stdlib=libc++" CXXFLAGS="-I/usr/local/lib/llvm-3.5/include/c++/v1" make
However, when I attempt to use dragonegg to compile anything, I get this unfortunate set of errors:
$ /usr/local/bin/gcc-4.8 -fplugin=/usr/local/lib/dragonegg_483_35.so hello.c
/var/folders/s1/_v14lsc56tv44hm304m07vn40000gq/T//ccPKylId.s:2:Unknown pseudo-op: .macosx_version_min
/var/folders/s1/_v14lsc56tv44hm304m07vn40000gq/T//ccPKylId.s:2:Rest of line ignored. 1st junk character valued 49 (1).
/var/folders/s1/_v14lsc56tv44hm304m07vn40000gq/T//ccPKylId.s:9:Unknown pseudo-op: .cfi_startproc
/var/folders/s1/_v14lsc56tv44hm304m07vn40000gq/T//ccPKylId.s:12:Unknown pseudo-op: .cfi_def_cfa_offset
/var/folders/s1/_v14lsc56tv44hm304m07vn40000gq/T//ccPKylId.s:12:Rest of line ignored. 1st junk character valued 49 (1).
/var/folders/s1/_v14lsc56tv44hm304m07vn40000gq/T//ccPKylId.s:14:Unknown pseudo-op: .cfi_offset
/var/folders/s1/_v14lsc56tv44hm304m07vn40000gq/T//ccPKylId.s:14:Rest of line ignored. 1st junk character valued 37 (%).
/var/folders/s1/_v14lsc56tv44hm304m07vn40000gq/T//ccPKylId.s:17:Unknown pseudo-op: .cfi_def_cfa_register
/var/folders/s1/_v14lsc56tv44hm304m07vn40000gq/T//ccPKylId.s:17:Rest of line ignored. 1st junk character valued 37 (%).
/var/folders/s1/_v14lsc56tv44hm304m07vn40000gq/T//ccPKylId.s:72:Unknown pseudo-op: .cfi_endproc
$ /usr/local/bin/gcc-4.8 hello.c
$ ./a.out
Hello World
This, obviously, seems unlikely to involve any of the settings in the compiler flags used to create dragonegg, since they all relate to C++.
Any suggestions?
The solution I found is to tell dragonegg to use llvm's assembler rather than the system assembler by adding -specs=[path to integrated=as.specs]. Per dragonegg's documentation this should neither be necessary, nor work, but it does.
Related
I'm trying to port some Linux C code to an Apple M1 Mac and have been encountering an issue with some inline assembly. And it has me stumped.
I have the following inline assembly block:
#define TEST asm volatile(\
"adr x0, label9 \n"\
: : : "x0");
And have encountered the following error:
test.c:73:5: error: unknown AArch64 fixup kind!
TEST
^
./ARM_branch_macros.h:2862:7: note: expanded from macro 'TEST'
"adr x0, label9 \n"\
^
<inline asm>:1:2: note: instantiated into assembly here
adr x0, label9
^
1 error generated.
make: *** [indirect_branch_latency.o] Error 1
I am using the following compiler:
Apple clang version 12.0.0 (clang-1200.0.32.27)
Target: arm64-apple-darwin20.1.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
With the command line:
clang -c -o test.o test.c -I. -w -g -lrt -O0 -static -DARM_ASSEMBLY
Any help would be greatly appreciated!
The ADR instruction stores the offset from the current PC value to the label you reference.
When you have an instruction that references a symbol in a different object file (or in a different section in the same object file), the assembler can't encode the exact offset directly as it doesn't know how the linker will lay them out, but has to leave a relocation in the object file, instructing the linker to fix up the instruction once the exact location of the symbol is known.
I think the issue here is simply that the MachO object file (which is used on apple platforms) format doesn't have a relocation type for fixing up an ADR instruction pointing at a symbol elsewhere. And even if it had that, the construct is pretty brittle - the symbol that it points at has to be within +/- 1 MB from the instruction referencing it - that's a limit that is pretty easy to hit.
To get access to a bigger range, an ADRP+ADD instruction pair is often used, which gives you a +/- 4 GB range, and the MachO format does support those.
The assembler syntax for them differs a bit between MachO and ELF (and COFF). For MachO, the syntax looks like this:
adrp x0, symbol#PAGE
add x0, x0, symbol#PAGEOFF
Or if you want to load from it at the same time:
adrp x0, symbol#PAGE
ldr x1, [x0, symbol#PAGEOFF]
On ELF (the object file format used on Linux) and COFF (windows, when assembling GNU style assembly with LLVM) platforms, the syntax looks like this:
adrp x0, symbol
add x0, x0, :lo12:symbol
[edit]
This was just kind of a though experiment I had where I wanted to see if I could trick the kernel in to executing an elf from an unnamed pipe with process substitution with /lib64/ld-linux-x86-64.so.2, I knew it was a shot in the dark but I was just hoping to see if anyone could give me an answer as to why it didn't work
$ /lib64/ld-linux-x86-64.so.2 <(gcc -c -xc <(echo $'#include <stdio.h>\n\nint main(){\nprintf("I work\\n");\nreturn 0;\n}') -o /dev/stdout)
/tmp/ccf5sMql.s: Assembler messages:
/tmp/ccf5sMql.s: Fatal error: can't write /dev/stdout: Illegal seek
as: BFD version 2.25.1-22.base.el7 assertion fail elf.c:2660
as: BFD version 2.25.1-22.base.el7 assertion fail elf.c:2660
/tmp/ccf5sMql.s: Fatal error: can't close /dev/stdout: Illegal seek
/dev/fd/63: error while loading shared libraries: /dev/fd/63: file too short
I figured that it may have been possible due to varying results I was getting.
$ /lib64/ld-linux-x86-64.so.2 <(gcc -fPIC -pie -xc <(echo $'#include
<stdio.h>\n\nint main(){\nprintf("I work\\n");\nreturn 0;\n}') -o
/dev/stdout|cat|perl -ne 'chomp;printf')
/dev/fd/63: error while loading shared libraries: /dev/fd/63: ELF load
command past end of file
$ /lib64/ld-linux-x86-64.so.2 <(gcc -fPIC -pie -xc <(echo $'#include
<stdio.h>\n\nint main(){\nprintf("I work\\n");\nreturn 0;\n}') -o
/dev/stdout|cat|perl -0 -ne 'chomp;printf')
/dev/fd/63: error while loading shared libraries: /dev/fd/63: ELF file ABI
version invalid
So I was playing around with ASM and noticed that you can't assemble or link output to stdout.
$ as /tmp/lol.s -o /dev/stdout
/tmp/lol.s: Assembler messages:
/tmp/lol.s: Fatal error: can't write /dev/stdout: Illegal seek
as: BFD version 2.25.1-22.base.el7 assertion fail elf.c:2660
as: BFD version 2.25.1-22.base.el7 assertion fail elf.c:2660
as /tmp/lol.s -o /tmp/test.o
$ ld /tmp/test.o -o what -lc
ld: warning: cannot find entry symbol _start; defaulting to 00000000004002a0
$ exec 9< <(ld /tmp/test.o -o /dev/stdout -lc)
ld: warning: cannot find entry symbol _start; defaulting to 00000000004002a0
ld: final link failed: Illegal seek
Given the code as follows:
.file "63"
.section .rodata
.LC0:
.string "I work"
.text
.globl main
.type main, #function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $.LC0, %edi
call puts
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-16)"
.section .note.GNU-stack,"",#progbits
.file "63"
.section .rodata
Can anyone tell me why it isn't possible to assemble objects or link objects to stdout? Please be as in depth as possible. To see the full process that a compiler goes to in order to generate that code, you can use the following:
$ exec 7< <(gcc -c -xc <(echo $'#include <stdio.h>\n\nint main(){\nprintf("I work\\n");\nreturn 0;\n}') -o /dev/stdout)
If you assemble and link the assembly I provided earlier and want to execute it properly you'll need to call /lib64/ld-linux-x86-64.so.2 /path/to/output otherwise it will just say bad elf interpreter.
# ./what
bash: ./what: /lib/ld64.so.1: bad ELF interpreter: No such file or directory
# /lib64/ld-linux-x86-64.so.2 ./what
I work
You can't pipe assembler output to stdout, because since immemorial times (1960s probably) assemblers work generally in two passes (and not only on input, but also on output). So ability to seek (both input and output, using lseek(2)) is required. Otherwise they would need to keep most of the input and output data in memory.
Remember that an object file contains not only data (e.g. machine instructions, read only constant) but also relocation information.
/tmp/lol.s: Fatal error: can't write /dev/stdout: Illegal seek
This illustrates that the as program needs to seek files (e.g. using lseek(2)).
Perhaps you want to generate machine code in memory. For that use some JIT compilation library like libgccjit or asmjit.
BTW, you might want to understand how gcc is compiling a simple C program. For that compile it with gcc -v and notice that some crt0 thing is linked.
If you considered using pipes for performance reasons, use some tmpfs filesystem instead. The files there stay in memory (so are lost at shutdown) and are quick because no disk IO is performed.
You could even generate some C file in such a file system, then ask gcc to compile it (perhaps as a plugin). See also this.
... If I could trick the kernel in to executing an elf from an unnamed pipe
No, you can't. An ELF executable needs to be seekable too, because the kernel is, at its execve(2) time, setting up a fresh virtual addresss space, using something close to mmap(2) internally. In other words, execve is setting up several memory mappings.
Study the virtual address space of your processes. Read proc(5), then try cat /proc/$$/maps (and replace $$ with a more interesting pid).
Reading Operating Systems: Three Easy Pieces (freely downloadable) should be interesting to you.
My program works fine on Ubuntu.
It encounters error when I compile it with gcc on a Solaris SPARC system.
I have several pieces of code like:
printf("endian_convert: %s\n", endian_convert);
asm("movl $8, %esi\n\t"
"movl $.LC0, %edi\n\t"
"movl $0, %eax");
This is the error I get on SPARC:
gcc -g -Wall -Werror -pedantic -Wextra src/utfconverter.c -o bin/utf
/usr/ccs/bin/as: "/var/tmp//cc9czJEf.s", line 957: error: unknown "%"-symbol
/usr/ccs/bin/as: "/var/tmp//cc9czJEf.s", line 957: error: statement syntax
.......
/usr/ccs/bin/as: "/var/tmp//cc9czJEf.s", line 1058: error: unknown "%"-symbol
/usr/ccs/bin/as: "/var/tmp//cc9czJEf.s", line 1058: error: statement syntax
*** Error code 1 make: Fatal error: Command failed for target `utf'
So, the "%" symbol is considered as unknown on SPARC?
How can I fix this and make it working on SPARC?
(The original version of the question didn't mention that the errors were from a SPARC Solaris system, and just called it C90 because the old version of gcc installed on it defaulted to -std=c90, leading to error messages about things that are illegal in C90.)
Wait a minute, "works fine on Ubuntu but not on C90"? /usr/ccs/bin/as (in your screenshot) looks like Solaris. That + the hostname is a clue that this might be a SPARC machine, not x86 at all.
Obviously x86 assembly isn't valid SPARC assembly syntax. It's a different CPU architecture.
If you'd used gcc foo.c -S and looked at the resulting foo.s asm output file, you'd see that it was full of SPARC asm, except for text inserted literally by your asm statements.
SPARC syntax does use % decorators on register names, but the register names are different. e.g. add %i0, %i1, %o0 adds input registers i0 and i1, storing the result in output register o0. (Input as in function arg and output as in function result. SPARC uses a sliding window onto a large virtual register file that might or might not spill to memory, depending on whether the CPU microarchitecture is out of registers when the save instruction runs.)
Remember that these errors are from the Solaris assembler, not from gcc. You're using gcc but it's using the system assembler instead of the GNU assembler.
Anyway, I recommend rewriting your code into pure portable C, rather than using #ifdef __x86__ to keep using that inline asm, or writing a SPARC port of it.
BTW, your asm statement looks horrible. A different version of gcc might store a different constant at .LC0, breaking your code. More importantly, you're not using input/output constraints to tell the compiler what value is where. If you're assuming it's ok to set eax in asm inside a function, that's incorrect. The function can and will inline, and then your asm is just floating free in the middle of wherever your function inlined. See the end of this answer for links to some GNU C inline asm tutorials.
Also, you don't need inline asm to endian-convert. You will get better asm from using endian.h functions like uint32_t le32toh(uint32_t little_endian_32bits); which use gcc builtins or inline asm to get the compiler to make optimal assembly output itself.
See also https://gcc.gnu.org/wiki/DontUseInlineAsm, which applies even if you did know how to use it properly.
I'm trying to get BLAS working with in a FORTRAN 77 program, but so far I've been unsuccesful and I can't figure out how to get going with this. For reference I'm doing this under Ubuntu 12.10.
This is the code of the program I'm trying to compile:
program blastest
implicit none
include 'cblas_f77.h'
end
The file cblas_f77.h resides in /usr/include, and there are both libblas.a and libblas.so (and a bunch of other BLAS related files) in /usr/lib.
How do you configure this to work properly?
So far, I've tried the following:
Note: adding -lblas to either of the options make no difference at all...
Just f77, no options (didn't really expect this to work, but what the heck...):
$ f77 blastest.f -o blastest
MAIN blastest:
Cannot open file cblas_f77.h
/usr/bin/f77: aborting compilation
f77 with include option to find the header file. Now, instead it fails on (despite the file name) not being coded with FORTRAN 77 in mind, so the first six columns are nonempty...
$ f77 blastest.f -o blastest -I/usr/include
MAIN blastest:
Error on line 1 of /usr/include/cblas_f77.h: nondigit in statement label field "/* "
Error on line 2 of /usr/include/cblas_f77.h: labeled continuation line (starts " * cbl")
Error on line 3 of /usr/include/cblas_f77.h: labeled continuation line (starts " * Wri")
...
Full output: http://pastebin.com/eZBzh9N5
Switched to gfortran, to be more flexible with the spacing in the header file:
$ gfortran blastest.f -o blastest -I/usr/include
Warning: cblas_f77.h:9: Illegal preprocessor directive
Warning: cblas_f77.h:10: Illegal preprocessor directive
Warning: cblas_f77.h:12: Illegal preprocessor directive
...
Full output: http://pastebin.com/P71Di9pR
OK, so I guessed I need -cpp to get the preprocessor working. That gave exactly the same output as above. Also, if you keep reading you see that the full output, the compiler is still complaining about labelled continuation lines further down...
I believe that you are using the C library "cblas". I would recompile with this command:
gfortran blastest.f -o blastest -L/usr/lib -lblas
and this should sort it all out. I do not believe (though i am not sure) that you need to make use of the "include" statement.
I'm trying to compile a simple operating system code we got on OS class. It works fine under Ubuntu but I'd like to compile it on OS X. The error I get is:
[compiling] arch/i386/arch/startup.S ...
arch/i386/arch/startup.S:8:Unknown pseudo-op: .extern
arch/i386/arch/startup.S:8:Rest of line ignored. 1st junk character valued 107 (k).
arch/i386/arch/startup.S:11:Expected comma after segment-name
arch/i386/arch/startup.S:13:Unknown pseudo-op: .global
arch/i386/arch/startup.S:13:Rest of line ignored. 1st junk character valued 97 (a).
This is the
source code of that file, and here is the makefile
So if anyone have an idea what to do I would appreciate it :)
As you're compiling using OS/X you'll be using X-Code's ancient version of as. This means you'll have to put up with some slightly older syntax. This other answer covers some of these problems.
At very least you're going to need to replace .global with .globl. You can remove .extern as all symbols are treated as external by default. For the section definition you should consult the gas manual; I believe the assembler is asking you to define the section flags.
I think it should be ".globl" not ".global"