Я попробовал это, и Elf32_Shdr.sh_addr не совпадает с Elf32_Shdr.sh_offset в моем примере. Он сдвинут на 0x08040000, который является виртуальным начальным адресом программы в памяти.
Elf32_Shdr.sh_offset - 0x00000570 для раздела «.text», а Elf32_Shdr.sh_addr - 0x08048570 для того же раздела.
Как вы цитировали из документации, Elf32_Shdr.sh_offset - это «смещение байта от начала файла до первого байта в функции»:
$> hexdump -C -s 0x00000570 -n 64 elffile
00000570 31 ed 5e 89 e1 83 e4 f0 50 54 52 68 b0 88 04 08 |1.^.....PTRh....|
00000580 68 c0 88 04 08 51 56 68 66 88 04 08 e8 3b ff ff |h....QVhf....;..|
00000590 ff f4 90 90 90 90 90 90 90 90 90 90 90 90 90 90 |................|
000005a0 55 89 e5 83 ec 08 80 3d 44 a0 04 08 00 74 0c eb |U......=D....t..|
и Elf32_Shdr.sh_addr - это «адрес, по которому должен находиться первый байт». Это виртуальный адрес данных в памяти:
(gdb) print/x *(char[64] *) 0x08048570
$4 = {
0x31, 0xed, 0x5e, 0x89, 0xe1, 0x83, 0xe4, 0xf0, 0x50, 0x54, 0x52, 0x68, 0xb0, 0x88, 0x04, 0x08,
0x68, 0xc0, 0x88, 0x04, 0x08, 0x51, 0x56, 0x68, 0x66, 0x88, 0x04, 0x08, 0xe8, 0x3b, 0xff, 0xff,
0xff, 0xf4, 0x90 <repeats 14 times>,
0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0x80, 0x3d, 0x44, 0xa0, 0x04, 0x08, 0x00, 0x74, 0x0c, 0xeb}