I want to use Note section of ELF file to propagate some information within my tool set. Similar method is used by Microsoft tools and by NASM in COFF modules, where payload data in section .drectve contains linker parameters, for instance the text /IMPORT:ExitProcess.
First I used NASM on Linux to create 32bit ELF module with Note section .drectve:
me@vm:~/$ cat NOTE32.asm
BITS 32
SECTION .drectve
DD 7 ; namesz = size of "ABCDEFG".
DD 8 ; descsz = size of payload.
DD 9 ; type = randomly chosen value.
DB "ABCDEFG",0 ; name = owner; aligned size=8.
DB "payload." ; desc = useful contents; aligned size=8.
me@vm:~/$ nasm -f ELF32 NOTE32.asm -o NOTE32.o
As NASM cannot create NOTE-type sections directly, I had to edit the output file with hexaeditor and rewrite section type from SHT_PROGBITS (1) to SHT_NOTE (7). Readelf then displayed my handcrafted note correctly, although it couldn't interpret my arbitrary chosen Owner and Type, of course:
me@vm:~/$ readelf -hSn NOTE32.o
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 64 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 5
Section header string table index: 2
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .drectve NOTE 00000000 000110 00001c 00 A 0 0 1
[ 2] .shstrtab STRTAB 00000000 000130 000024 00 0 0 1
[ 3] .symtab SYMTAB 00000000 000160 000030 10 4 3 4
[ 4] .strtab STRTAB 00000000 000190 00000c 00 0 0 1
Displaying notes found at file offset 0x00000110 with length 0x0000001c:
Owner Data size Description
ABCDEFG 0x00000008 Unknown note type: (0x00000009)
me@vm:~/$
So far, so good. Then I repeated the process with 64bit ELF module, where the fields in NOTE section are 8 bytes wide, according to chapter 9. of ELF-64 Object File Format on page 13:
Sections of type SHT_NOTE and segments of type PT_NOTE are used by compilers and other tools to mark an object file with special information that has special meaning to a particular tool set. These sections and segments contain any number of note entries, each of which is an array of 8-byte words in the byte order defined in the ELF file header. The format of a note entry is shown in Figure 7.
me@vm:~/$ cat NOTE64.asm
BITS 64
SECTION .drectve
DQ 7 ; namesz = size of "ABCDEFG".
DQ 8 ; descsz = size of payload.
DQ 9 ; type = randomly chosen value.
DB "ABCDEFG",0 ; name = owner; aligned size=8.
DB "payload." ; desc = useful contents; aligned size=8.
me@vm:~/$ nasm -f ELF64 NOTE64.asm -o NOTE64.o
Here is the file dump with SHT_PROGBITS at offset 84h manually rewritten to SHT_NOTE:
me@vm:~/$ xxd NOTE64.o
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............
00000010: 0100 3e00 0100 0000 0000 0000 0000 0000 ..>.............
00000020: 0000 0000 0000 0000 4000 0000 0000 0000 ........@.......
00000030: 0000 0000 4000 0000 0000 4000 0500 0200 ....@.....@.....
00000040: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000080: 0100 0000 0700 0000 0200 0000 0000 0000 ................
00000090: 0000 0000 0000 0000 8001 0000 0000 0000 ................
000000a0: 2800 0000 0000 0000 0000 0000 0000 0000 (...............
000000b0: 0800 0000 0000 0000 0800 0000 0000 0000 ................
000000c0: 0a00 0000 0300 0000 0000 0000 0000 0000 ................
000000d0: 0000 0000 0000 0000 b001 0000 0000 0000 ................
000000e0: 2400 0000 0000 0000 0000 0000 0000 0000 $...............
000000f0: 0100 0000 0000 0000 0000 0000 0000 0000 ................
00000100: 1400 0000 0200 0000 0000 0000 0000 0000 ................
00000110: 0000 0000 0000 0000 e001 0000 0000 0000 ................
00000120: 4800 0000 0000 0000 0400 0000 0300 0000 H...............
00000130: 0400 0000 0000 0000 1800 0000 0000 0000 ................
00000140: 1c00 0000 0300 0000 0000 0000 0000 0000 ................
00000150: 0000 0000 0000 0000 3002 0000 0000 0000 ........0.......
00000160: 0c00 0000 0000 0000 0000 0000 0000 0000 ................
00000170: 0100 0000 0000 0000 0000 0000 0000 0000 ................
00000180: 0700 0000 0000 0000 0800 0000 0000 0000 ................
00000190: 0900 0000 0000 0000 4142 4344 4546 4700 ........ABCDEFG.
000001a0: 7061 796c 6f61 642e 0000 0000 0000 0000 payload.........
000001b0: 002e 6472 6563 7476 6500 2e73 6873 7472 ..drectve..shstr
000001c0: 7461 6200 2e73 796d 7461 6200 2e73 7472 tab..symtab..str
000001d0: 7461 6200 0000 0000 0000 0000 0000 0000 tab.............
000001e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000001f0: 0000 0000 0000 0000 0100 0000 0400 f1ff ................
00000200: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000210: 0000 0000 0300 0100 0000 0000 0000 0000 ................
00000220: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000230: 004e 4f54 4536 342e 6173 6d00 0000 0000 .NOTE64.asm.....
me@vm:~/$
GNU readelf (GNU Binutils for Ubuntu) 2.26.1 interprets the 64bit NOTE section .drectve incorrectly:
me@vm:~/$ readelf -hSnW NOTE64.o
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 64 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 64 (bytes)
Number of section headers: 5
Section header string table index: 2
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .drectve NOTE 0000000000000000 000180 000028 08 A 0 0 8
[ 2] .shstrtab STRTAB 0000000000000000 0001b0 000024 00 0 0 1
[ 3] .symtab SYMTAB 0000000000000000 0001e0 000048 18 4 3 4
[ 4] .strtab STRTAB 0000000000000000 000230 00000c 00 0 0 1
Displaying notes found at file offset 0x00000180 with length 0x00000028:
Owner Data size Description
0x00000000 Unknown note type: (0x00000008)
readelf: Warning: note with invalid namesz and/or descsz found at offset 0x14
readelf: Warning: type: 0x474645, namesize: 0x00000000, descsize: 0x44434241
me@vm:~/$
Apparently readelf misinterprets the section contents at file offset 180h as two NOTE arrays of 32bit DWORDs, the second entry starting at file offset 194h.
I have also tried to change OS/ABI value from UNIX - System V (0) to UNIX - GNU (3) in ELF_header.e_ident.EI_OSABI but with no effect.
Now I am in dilemma whether I should
- generate DWORD fields in both ELF32 and ELF64 formats produced by my tool (which contradicts ELF64 specification), or
- keep QWORD fields in ELF64 and face readelf's complains.