Clang - Emitting both bitcode and object files

Hello, I am trying to emit bitcode files using clang.

I am trying to compile EFI drivers, which are PE32 executables. wllvm 1 and gllvm 2 do not support PE32; hence they cannot attach the bitcode in the final object files.

For this reason, I am trying to pass flags to clang used by the project’s build system. I cannot modify the build system but play with the compiler flags.

Passing -c -emit-llvm produces .bc files as I wanted, but it does not create object files, making the build system fail the building process. Passing -S requires -o, and I do not have a way to specify the output filename manually.

What are my options here to produce .bc files without modifying the build system? Is there a clang flag that emits both the compiled object and its bitcode separately?


Not that I know of. The .bc files would have to be run through clang again, either explicitly to create object files, or treated as inputs to the linker (which can then use LTO to compile them and link into the final executable).

1 Like

That’s what I was suspecting, but I hoped there was some obscure flag I could use.

There isn’t a flag to emit them into two different files (that I know of), but you should be able to pass -fembed-bitcode=all on the command line to embed the bitcode within the object file and then pull it out with llvm-objcopy. May be more or less elegant depending upon what you’re trying to do.

That sounds very promising for my use-case.

I have compiled the project with -fembed-bitcode=all, but I cannot find a way to use llvm-objcopy to extract the bitcode from the object file.

How does -fembed-bitcode embed the bitcode in the final executable?

Thank you very much!

This is the output of llvm-objdump of one of the object files:

$ llvm-objdump-17 /tmp/efi -x

/tmp/efi:	file format coff-x86-64
architecture: x86_64
start address: 0x0000000000000000
Characteristics 0x2e
	line numbers stripped
	symbols stripped
	large address aware

Time/Date               Wed Dec 31 16:00:00 1969
Magic                   020b	(PE32+)
MajorLinkerVersion      0
MinorLinkerVersion      0
SizeOfCode              0000000000019b40
SizeOfInitializedData   0000000000007180
SizeOfUninitializedData 0000000000000000
AddressOfEntryPoint     000000000000ce00
BaseOfCode              0000000000000240
ImageBase               0000000000000000
SectionAlignment        00000040
FileAlignment           00000040
MajorOSystemVersion     0
MinorOSystemVersion     0
MajorImageVersion       0
MinorImageVersion       0
MajorSubsystemVersion   0
MinorSubsystemVersion   0
Win32Version            00000000
SizeOfImage             00020f00
SizeOfHeaders           00000200
CheckSum                00000000
Subsystem               0000000a	(EFI application)
DllCharacteristics      00000000
SizeOfStackReserve      0000000000000000
SizeOfStackCommit       0000000000000000
SizeOfHeapReserve       0000000000000000
SizeOfHeapCommit        0000000000000000
LoaderFlags             00000000
NumberOfRvaAndSizes     00000010

The Data Directory
Entry 0 0000000000000000 00000000 Export Directory [.edata (or where ever we found it)]
Entry 1 0000000000000000 00000000 Import Directory [parts of .idata]
Entry 2 0000000000000000 00000000 Resource Directory [.rsrc]
Entry 3 0000000000000000 00000000 Exception Directory [.pdata]
Entry 4 0000000000000000 00000000 Security Directory
Entry 5 0000000000020e40 000000c0 Base Relocation Directory [.reloc]
Entry 6 0000000000020d78 0000001c Debug Directory
Entry 7 0000000000000000 00000000 Description Directory
Entry 8 0000000000000000 00000000 Special Directory
Entry 9 0000000000000000 00000000 Thread Storage Directory [.tls]
Entry a 0000000000000000 00000000 Load Configuration Directory
Entry b 0000000000000000 00000000 Bound Import Directory
Entry c 0000000000000000 00000000 Import Address Table Directory
Entry d 0000000000000000 00000000 Delay Import Directory
Entry e 0000000000000000 00000000 CLR Runtime Header
Entry f 0000000000000000 00000000 Reserved

Idx Name          Size     VMA              Type
  0 .text         00019b40 0000000000000240 TEXT
  1 .data         000070c0 0000000000019d80 DATA
  2 .reloc        000000c0 0000000000020e40 DATA


The -fembed-bitcode=all flag creates a .llvmbc and a .llvmcmd section. The command to get the bitcode should be llvm-objcopy --dump-section=.llvmbc=<path to output bitcode file> <path to object file>.

It seems I’m out of luck with COFF files:

$ llvm-objcopy-17 --dump-section=.llvmbc=a.bc OvmfX64/DEBUG_CLANG38/X64/SetupBrowser.efi                                                                                                                   
llvm-objcopy-17: error: option is not supported for COFF