Posts

  • 3rd December 2023

Linker notes on PE/COFF

Updated in 2025-05.

This article describes linker notes about Portable Executable (PE) and Common Object File Format (COFF) used on Windows and UEFI environments.

In ELF, an object file can be a relocatable file, an executable file, or a shared object file. On Windows, the term "object file" usually refers to relocatable files like ELF. Such files use the Common Object File Format (COFF) while image files (e.g. executables and DLLs) use the Portable Executable (PE) format.

A look at linkers

MSVC Linker is the reference linker on Windows.

GNU ld supports Windows thanks to the MinGW effort. Here are some common BFD emulations for PE targets:

  • i386pe: For 32-bit Intel x86 architectures.
  • i386pep: For 64-bit Intel x86-64 architectures.
  • arm64pe: For 64-bit ARM (AArch64) architectures.

For instance, you can use a command like ld.bfd -m i386pep a.o b.o to link two object files into a PE executable. Many options on Linux can also be used when targeting PE/COFF.

The LLVM linker offers two modes of operation that are relevant to PE/COFF:

  • lld-link: In this mode, lld emulates the MSVC linker, making it a fast viable alternative.
  • ld.lld: When invoked with a PE emulation (like -m i386pep), lld emulates GNU ld. Code in lld/MinGW translates GNU ld options to link.exe options.

GNU ld implements relocatable linking that is not available in other linkers.

Input files

The input files to the linker can be object files, archive files, and import libraries. GNU ld and lld-link allow linking against DLL files without an import library.

…

Read more →
  • 31st October 2023

DSO undef and non-exported definition

DSO undef and non-exported def

If a DSO has an undefined STB_GLOBAL symbol that is defined in a relocatable object file but not exported, should the --no-allow-shlib-undefined feature report an error? You may want to check out Dependency related linker options for a discussion of this option and the symbol exporting rule.

…

Read more →
  • 15th October 2023
  • 24th September 2023

A deep dive into Clang's source file compilation

Clang is a C/C++ compiler that generates LLVM IR and utilizes LLVM to generate relocatable object files. Using the classic three-stage compiler structure, the stages can be described as follows:

C/C++ =(front end)=> LLVM IR =(middle end)=> LLVM IR (optimized) =(back end)=> relocatable object file

If we follow the internal representations of instructions, a more detailed diagram looks like this:

C/C++ =(front end)=> LLVM IR =(middle end)=> LLVM IR (optimized) =(instruction selector)=> MachineInstr =(AsmPrinter)=> MCInst =(assembler)=> relocatable object file

LLVM and Clang are designed as a collection of libraries. This post describes how different libraries work together to create the final relocatable object file. I will focus on how a function goes through the multiple compilation stages.

…

Read more →
  • 9th September 2023

Reflections on LLVM's switch to GitHub pull requests

Since 2012, LLVM has relied on its self-hosted Phabricator instance on Google Cloud Platform for code review, but now it's making a transition to GitHub pull requests. In this post, I'll share my perspective on this switch, highlighting GitHub offers significant benefits in some areas while having major drawbacks in the review process.

I may update this article as the process stabilizes further.

Transition to GitHub pull requests

The move to GitHub pull requests has been a topic of discussion over the past few years. Several lengthy threads on the subject have emerged:

…

Read more →
  • 4th September 2023

Toolchain notes on MIPS

This article describes some notes about MIPS with a focus on the ELF object file format, GCC, binutils, and LLVM/Clang.

In the llvm-project project, I sometimes find myself assigned as a reviewer for MIPS patches. I want to be transparent that I have no interest in MIPS, but my concern lies with the specific components that are impacted (Clang driver, ld.lld, MC, compiler-rt, etc.). Therefore, regrettably, I have to spend some time studying MIPS.

Using copper as a mirror, one can straighten their attire; using the past as a mirror, one can understand rise and fall; using people as a mirror, one can discern gains and losses. -- 贞观政要

…

Read more →
  • 25th August 2023

Clang -Wunused-command-line-argument

clangDriver is the library implementing the compiler driver for Clang. It utilitizes LLVMOption to process command line options. As options are processed when required, as opposed to use a large switch, Clang gets the ability to detect unused options straightforwardly.

…

Read more →
  • 20th August 2023

My involvement with LLVM 17

LLVM 17 will soon be relased. This post provides a summary of my contributions in this release cycle to record my learning progress.

…

Read more →
  • 30th July 2023

lld 17 ELF changes

LLVM 17 will be released. As usual, I maintain lld/ELF and have added some notes to https://github.com/llvm/llvm-project/blob/release/17.x/lld/docs/ReleaseNotes.rst. Here I will elaborate on some changes.

…

Read more →
  • 16th July 2023

Precompiled headers

C/C++ projects can benefit from using precompiled headers to improve compile time. GCC added support for precompiled headers in 2003 (version 3.4), and the current documentation can be found at https://gcc.gnu.org/onlinedocs/gcc/Precompiled-Headers.html.

Even with the emergence of C++ modules, precompiled headers remain relevant for several reasons:

  • Precompiled headers share implementation aspects with modules (e.g., AST serialization in Clang).
  • Many C++ projects rely on the traditional compilation model and are not converted to C++ modules.
  • Modules may possibly use some preamble-like technology to accelerate IDE-centric operations.
  • C doesn't have C++ modules.

This article focuses on Clang precompiled headers (PCH). Let's begin with an example.

…

Read more →