[LLVMdev] Compiling user mode linux with LLVM

Matt Renzelmann mjr at cs.wisc.edu
Thu May 7 09:47:50 PDT 2009


I've recently started working on compiling UML with LLVM:  the goal is to
produce a bitcode version of vmlinux.

With some tweaks to the build process, I can use:
make ARCH=um CROSS_COMPILE=llvm- CFLAGS="-emit-llvm"

to produce vmlinux bitcode.

The question is with respect linker script support.  Since llvm-ld does not
support linker scripts--please correct me if I'm wrong--it's clear that some
work is necessary to get things running.

There was a thread on the mailing list last September about this question:
> Hi,
> I'm trying to compile linux kernel with llvm to generate llvm ir
> (bitcode). It seems like llvm-ld doesn't accept any linker scripts.
> How do I deal with vmlinux.lds in such a case? How did people who have
> compiled linux kernel with llvm deal with this in the past?

You need to add a bytecode linker stage before that.  You still need
the linker script for correctness, but you must use it in the final
link stage after you have generated a native .o file from the bitcode.

By the way, it you are still planning on jitting the kernel, you
should be warned that the linker script creates globals and arrays
that are referenced by the kernel code but otherwise will appear
nowhere in your bitcode...   You will have to rewrite the kernel's
initialization infastructure or write a pass to fix up the bitcode or


As an experiment, I've tried using llc to convert the vmlinux.bc output into
native assembly, then use "as" and "ld" to produce a native vmlinux, but the
ld step fails with:

ld: ./vmlinux_native.o: bad reloc symbol index (0x9c113c >= 0x4af6) for
offset 0x18585 in section `.text'
./vmlinux_native.o: could not read symbols: Bad value

I've not pursued this specific issue further since my goal is to run the
bitcode directly, e.g. via lli.

I'm also aware of the clever tricks the kernel uses that need to be
addressed, mentioned in the second paragraph of Andrew's above reply.  As an
example, the symbol __initcall_start is defined in a linker script
(vmlinux.lds) and is used in the kernel as part of the initialization.

Has anyone successfully modified the kernel initialization code to get UML
working with LLVM?  If so, I'm interested in the approach taken so as to
avoid wasting time.

Thanks and regards,
Matt Renzelmann

More information about the llvm-dev mailing list