logo

eh_frame and eh_frame_hdr

In the world of Linux systems programming (and specifically within the ELF binaries used by gVisor and the vDSO), .eh_frame_hdr is a special section of an executable or shared library used for stack unwinding.

The Context: Stack Unwinding

When a program is running, it creates a "stack." Each function call pushes a new "frame" onto that stack. Sometimes, the program needs to "unwind" the stack (look backward through the calls). This happens during:

  • C++ Exceptions: Finding the catch block for a throw.
  • Debugging: Generating a backtrace in gdb or when a program crashes (segfault).
  • Garbage Collection: Some languages need to scan the stack to find object references.
  • Profiling: Tools like perf need to see the call graph.

What is .eh_frame?

Historically, code used "Frame Pointers" (the ebp/rbp register) to keep track of the stack. However, modern compilers often optimize frame pointers away to free up a register for data.

Without frame pointers, you need a "map" to tell you: "If the instruction pointer is at address X, how do I find the previous function's stack frame?"

The .eh_frame section is that map. It contains Call Frame Information (CFI), which describes how to restore registers and find the return address for every location in the code.

What is .eh_frame_hdr (The Header)?

The .eh_frame section itself is a long, complex linked list of records (called FDEs—Frame Descriptor Entries). If a program crashes and you need to find the correct record for the current instruction:

  1. Without a header, you would have to start at the beginning of .eh_frame and scan every record until you found the one matching your current address. This is slow ( O ( N ) O(N) ).
  2. .eh_frame_hdr is an index (a binary search table) for the .eh_frame section.

It contains a sorted list of pairs: (code_address, eh_frame_record_address). This allows the system to use a binary search to find the correct unwinding information almost instantly ( O ( log N ) O(\log N) ).

Connection to vDSO

The vDSO must include an .eh_frame_hdr section.

Why? Imagine your program is inside a vDSO function like gettimeofday(). While it's there, a "Profiler" or a "Debugger" tries to take a stack trace. If the vDSO didn't have an .eh_frame_hdr, the debugger wouldn't know how to "step out" of the vDSO and back into your main program code. It would see the vDSO code as a "dead end," and your stack trace would be broken.

Summary

  • .eh_frame: The "map" that tells you how to move backward through function calls without frame pointers.
  • .eh_frame_hdr: The "index" that makes searching that map very fast.
  • Usage: Primarily for C++ exceptions and debugging tools.
  • Importance: It ensures that even when code is in a "special" place (like vDSO), the system still knows how the stack is structured.