The information is stored in a binary in either the ELF Note format
inside a special section called .gnu.build.attributes
, or else
as ordinary strings inside a section called .annobin.notes
.
The readelf
program from the binutils
package can
extract and display these notes. (Adding the --wide
option is also helpful).
If the information is held in the ELF note format then readelf’s --notes option will display them. Here is an example of the output:
Displaying notes found in: .gnu.build.attributes Owner Data size Description GA$<version>3p3 0x00000010 OPEN Applies to region from 0x8a0 to 0x8c6 (hello.c) GA$<tool>gcc 7.2.1 20170915 0x00000000 OPEN Applies to region from 0x8a0 to 0x8c6 GA*GOW:0x452b 0x00000000 OPEN Applies to region from 0x8a0 to 0x8c6 GA*<stack prot>strong 0x00000000 OPEN Applies to region from 0x8a0 to 0x8c6 GA*GOW:0x412b 0x00000010 func Applies to region from 0x8c0 to 0x8c6 (baz)
This shows various different pieces of information, including the fact that the notes were produced using version 3 of the specification, and version 3 of the plugin. The binary was built by gcc version 7.2.1 and the -fstack-protector-strong option was enabled on the command line. The program was compiled with -O2 enabled except the baz() function which was compiled with -O0 instead.
The most complicated part of the notes is the owner field. This is used to encode the type of note as well as its value and possibly extra data as well. The format of the field is explained in detail in the Watermark specification, but it basically consists of the letters ‘G’ and ‘A’ followed by an encoding character (one of ‘*$!+’) and then a type character and finally the value.
The notes are always four byte aligned, even on 64-bit systems. This does mean that consumers of the notes may have to read 8-byte wide values from 4-byte aligned addresses, and that producers of the notes may have to generate unaligned relocs when creating them.
If the information is held as strings then readelf’s -p.annobin.notes option will display them. Here is an example of the output:
String dump of section '.annobin.notes': [ 0] AV:4.p.1200 [ c] RV:running gcc 12.2.1 20221121 [ 2b] BV:annobin gcc 12.2.1 20221121 [ 4a] PN:annobin [ 55] GW:0x290540 [ 61] SP:3
Most of the notes have a reasonably self explanatory name and value.
The exception are the version
and GOW
notes, which are
included in the table below.