What is the difference between Import Address Table and Global Offset Table? - c

I tried googling them separately, but one thing stuck out the most. Is it just that IAT is for PE files and GoT is for ELF?

Is it just that IAT is for PE files and GoT is for ELF?
This is the main difference.
Another difference is that the GOT in ELF files may also contain entries describing symbols defined in the ELF file itself. This is typical for 32-bit shared libraries.
IATs in PE files contain only entries that describe symbols defined in other DLL files.

On Linux, the nm command can be used to see all symbols that must be imported from shared libraries. I compiled a small program called "main". Using the nm command, I can see the offsets of objects. Symbols prefixed with a 'T' are functions can be found in the "main" code, along with logical offset (Global Offset Table). Symbols prefixed with a 'U' are undefined, and must be imported (Import Address Table).
$ nm main
0000000100000d70 T _AddAlbum
U ___error
U ___stderrp
0000000100000000 T __mh_execute_header
U _fprintf
0000000100000e40 T _main
U _malloc
U _printf
U _realloc
U _strerror
U dyld_stub_binder
For more detail, use the objdump with the -x option:
$ objdump -x main
main: file format Mach-O 64-bit x86-64
Sections:
Idx Name Size Address Type
0 __text 0000018a 0000000100000d70 TEXT
1 __stubs 00000024 0000000100000efa TEXT
2 __stub_helper 0000004c 0000000100000f20 TEXT
3 __cstring 00000042 0000000100000f6c DATA
4 __unwind_info 00000048 0000000100000fb0 DATA
5 __nl_symbol_ptr 00000008 0000000100001000 DATA
6 __got 00000010 0000000100001008 DATA
7 __la_symbol_ptr 00000030 0000000100001018 DATA
SYMBOL TABLE:
0000000100000d70 g F __TEXT,__text _AddAlbum
0000000100000000 g F __TEXT,__text __mh_execute_header
0000000100000e40 g F __TEXT,__text _main
0000000000000000 *UND* ___error
0000000000000000 *UND* ___stderrp
0000000000000000 *UND* _fprintf
0000000000000000 *UND* _malloc
0000000000000000 *UND* _printf
0000000000000000 *UND* _realloc
0000000000000000 *UND* _strerror
0000000000000000 *UND* dyld_stub_binder
Mach header
magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
MH_MAGIC_64 X86_64 ALL LIB64 EXECUTE 15 1296 NOUNDEFS DYLDLINK TWOLEVEL PIE
Load command 0
cmd LC_SEGMENT_64
cmdsize 72
segname __PAGEZERO
vmaddr 0x0000000000000000
vmsize 0x0000000100000000
fileoff 0
filesize 0
maxprot ---
initprot ---
nsects 0
flags (none)
Load command 1
cmd LC_SEGMENT_64
cmdsize 472
segname __TEXT
vmaddr 0x0000000100000000
vmsize 0x0000000000001000
fileoff 0
filesize 4096
maxprot r-x
initprot r-x
nsects 5
flags (none)
Section
sectname __text
segname __TEXT
addr 0x0000000100000d70
size 0x000000000000018a
offset 3440
align 2^4 (16)
reloff 0
nreloc 0
type S_REGULAR
attributes PURE_INSTRUCTIONS SOME_INSTRUCTIONS
reserved1 0
reserved2 0
Section
sectname __stubs
segname __TEXT
addr 0x0000000100000efa
size 0x0000000000000024
offset 3834
align 2^1 (2)
reloff 0
nreloc 0
type S_SYMBOL_STUBS
attributes PURE_INSTRUCTIONS SOME_INSTRUCTIONS
reserved1 0 (index into indirect symbol table)
reserved2 6 (size of stubs)
Section
sectname __stub_helper
segname __TEXT
addr 0x0000000100000f20
size 0x000000000000004c
offset 3872
align 2^2 (4)
reloff 0
nreloc 0
type S_REGULAR
attributes PURE_INSTRUCTIONS SOME_INSTRUCTIONS
reserved1 0
reserved2 0
Section
sectname __cstring
segname __TEXT
addr 0x0000000100000f6c
size 0x0000000000000042
offset 3948
align 2^0 (1)
reloff 0
nreloc 0
type S_CSTRING_LITERALS
attributes (none)
reserved1 0
reserved2 0
Section
sectname __unwind_info
segname __TEXT
addr 0x0000000100000fb0
size 0x0000000000000048
offset 4016
align 2^2 (4)
reloff 0
nreloc 0
type S_REGULAR
attributes (none)
reserved1 0
reserved2 0
Load command 2
cmd LC_SEGMENT_64
cmdsize 312
segname __DATA
vmaddr 0x0000000100001000
vmsize 0x0000000000001000
fileoff 4096
filesize 4096
maxprot rw-
initprot rw-
nsects 3
flags (none)
Section
sectname __nl_symbol_ptr
segname __DATA
addr 0x0000000100001000
size 0x0000000000000008
offset 4096
align 2^3 (8)
reloff 0
nreloc 0
type S_NON_LAZY_SYMBOL_POINTERS
attributes (none)
reserved1 6 (index into indirect symbol table)
reserved2 0
Section
sectname __got
segname __DATA
addr 0x0000000100001008
size 0x0000000000000010
offset 4104
align 2^3 (8)
reloff 0
nreloc 0
type S_NON_LAZY_SYMBOL_POINTERS
attributes (none)
reserved1 7 (index into indirect symbol table)
reserved2 0
Section
sectname __la_symbol_ptr
segname __DATA
addr 0x0000000100001018
size 0x0000000000000030
offset 4120
align 2^3 (8)
reloff 0
nreloc 0
type S_LAZY_SYMBOL_POINTERS
attributes (none)
reserved1 9 (index into indirect symbol table)
reserved2 0
Load command 3
cmd LC_SEGMENT_64
cmdsize 72
segname __LINKEDIT
vmaddr 0x0000000100002000
vmsize 0x0000000000001000
fileoff 8192
filesize 572
maxprot r--
initprot r--
nsects 0
flags (none)
Load command 4
cmd LC_DYLD_INFO_ONLY
cmdsize 48
rebase_off 8192
rebase_size 8
bind_off 8200
bind_size 40
weak_bind_off 0
weak_bind_size 0
lazy_bind_off 8240
lazy_bind_size 96
export_off 8336
export_size 64
Load command 5
cmd LC_SYMTAB
cmdsize 24
symoff 8408
nsyms 11
stroff 8644
strsize 120
Load command 6
cmd LC_DYSYMTAB
cmdsize 80
ilocalsym 0
nlocalsym 0
iextdefsym 0
nextdefsym 3
iundefsym 3
nundefsym 8
tocoff 0
ntoc 0
modtaboff 0
nmodtab 0
extrefsymoff 0
nextrefsyms 0
indirectsymoff 8584
nindirectsyms 15
extreloff 0
nextrel 0
locreloff 0
nlocrel 0
Load command 7
cmd LC_LOAD_DYLINKER
cmdsize 32
name /usr/lib/dyld (offset 12)
Load command 8
cmd LC_UUID
cmdsize 24
uuid 55558635-5195-3609-B115-706912ED1DA7
Load command 9
cmd LC_BUILD_VERSION
cmdsize 32
platform macos
sdk 10.14
minos 10.14
ntools 1
tool ld
version 520.0
Load command 10
cmd LC_SOURCE_VERSION
cmdsize 16
version 0.0
Load command 11
cmd LC_MAIN
cmdsize 24
entryoff 3648
stacksize 0
Load command 12
cmd LC_LOAD_DYLIB
cmdsize 56
name /usr/lib/libSystem.B.dylib (offset 24)
time stamp 2 Wed Dec 31 17:00:02 1969
current version 1281.0.0
compatibility version 1.0.0
Load command 13
cmd LC_FUNCTION_STARTS
cmdsize 16
dataoff 8400
datasize 8
Load command 14
cmd LC_DATA_IN_CODE
cmdsize 16
dataoff 8408
datasize 0

Related

ELF64 loading & memory alignment

Any experts with a deep understanding of ELF loading, could you please explain to me why the following ELF file throws a Segmentation fault (errno=139)?
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: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x131a
Start of program headers: 64 (bytes into file)
Start of section headers: 232 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 3
Size of section headers: 64 (bytes)
Number of section headers: 8
Section header string table index: 7
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] null NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .init PROGBITS 000000000000131a 0000031a
0000000000000001 0000000000000000 AX 0 0 1
[ 2] .text PROGBITS 000000000000131b 0000031b
0000000000000096 0000000000000000 AX 0 0 1
[ 3] .fini PROGBITS 00000000000013b1 000003b1
0000000000000001 0000000000000000 AX 0 0 1
[ 4] .rodata PROGBITS 00000000000013b2 000003b2
0000000000000014 0000000000000000 A 0 0 1
[ 5] .data PROGBITS 00000000000013c6 000003c6
000000000000001e 0000000000000000 A 0 0 1
[ 6] .bss NOBITS 00000000000013e4 000003e4
0000000000000000 0000000000000000 WA 0 0 1
[ 7] strtab STRTAB 00000000000012e8 000002e8
0000000000000032 0000000000000000 AS 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
l (large), p (processor specific)
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x000000000000031a 0x000000000000131a 0x000000000000131a
0x0000000000000098 0x0000000000000098 R E 0x1000
LOAD 0x00000000000003b2 0x00000000000013b2 0x00000000000013b2
0x0000000000000014 0x0000000000000014 R 0x1000
LOAD 0x00000000000003c6 0x00000000000013c6 0x00000000000013c6
0x000000000000001e 0x000000000000101e RW 0x1000
Section to Segment mapping:
Segment Sections...
00 .init .text .fini
01 .rodata
02 .data .bss
The exact same executable with the following file alignment changes works fine:
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: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x10400
Start of program headers: 64 (bytes into file)
Start of section headers: 232 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 3
Size of section headers: 64 (bytes)
Number of section headers: 8
Section header string table index: 7
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] null NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .init PROGBITS 0000000000010400 00000400
0000000000000001 0000000000000000 AX 0 0 1
[ 2] .text PROGBITS 0000000000010800 00000800
0000000000000096 0000000000000000 AX 0 0 1
[ 3] .fini PROGBITS 0000000000010c00 00000c00
0000000000000001 0000000000000000 AX 0 0 1
[ 4] .rodata PROGBITS 0000000000011000 00001000
0000000000000014 0000000000000000 A 0 0 1
[ 5] .data PROGBITS 0000000000011400 00001400
000000000000001e 0000000000000000 A 0 0 1
[ 6] .bss NOBITS 0000000000011800 00001800
0000000000000000 0000000000000000 WA 0 0 1
[ 7] strtab STRTAB 00000000000102e8 000002e8
0000000000000032 0000000000000000 AS 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
l (large), p (processor specific)
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000400 0x0000000000010400 0x0000000000010400
0x0000000000000801 0x0000000000000801 R E 0x1
LOAD 0x0000000000001000 0x0000000000011000 0x0000000000011000
0x0000000000000014 0x0000000000000014 R 0x1
LOAD 0x0000000000001400 0x0000000000011400 0x0000000000011400
0x000000000000001e 0x000000000000101e RW 0x1
Section to Segment mapping:
Segment Sections...
00 .init .text .fini
01 .rodata
02 .data .bss
In both cases it holds that:
sh_addr mod sh_addralign = 0 and
p_vaddr mod PAGESIZE = p_offset. (Pagesize acquired with getconf PAGESIZE).
I appreciate your help - thank you very much in advance.
UPDATE:
I realized that my LOAD segments were overlapping in virtual memory in the first readelf printout that I posted. I have corrected this now, but for the now non-overlapping LOAD segments I still get a segmentation fault when my start virtual memory address for the first page is at 0x0 (same if it is at 0x1000, i.e. one page size higher):
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: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x31a
Start of program headers: 64 (bytes into file)
Start of section headers: 232 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 3
Size of section headers: 64 (bytes)
Number of section headers: 8
Section header string table index: 7
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] null NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .init PROGBITS 000000000000031a 0000031a
0000000000000001 0000000000000000 AX 0 0 0
[ 2] .text PROGBITS 000000000000031b 0000031b
0000000000000076 0000000000000000 AX 0 0 0
[ 3] .fini PROGBITS 0000000000000391 00000391
0000000000000001 0000000000000000 AX 0 0 0
[ 4] .rodata PROGBITS 0000000000001392 00000392
0000000000000014 0000000000000000 A 0 0 0
[ 5] .data PROGBITS 00000000000023a6 000003a6
000000000000001e 0000000000000000 A 0 0 0
[ 6] .bss NOBITS 00000000000023c4 000003c4
0000000000000000 0000000000000000 WA 0 0 0
[ 7] strtab STRTAB 00000000000002e8 000002e8
0000000000000032 0000000000000000 AS 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
l (large), p (processor specific)
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x000000000000031a 0x000000000000031a 0x000000000000031a
0x0000000000000078 0x0000000000000078 R E 0x1000
LOAD 0x0000000000000392 0x0000000000001392 0x0000000000001392
0x0000000000000014 0x0000000000000014 R 0x1000
LOAD 0x00000000000003a6 0x00000000000023a6 0x00000000000023a6
0x000000000000001e 0x0000000000000082 RW 0x1000
Section to Segment mapping:
Segment Sections...
00 .init .text .fini
01 .rodata
02 .data .bss
When I change the start address to 0x10000 (PAGESIZE * 16), then the segmentation fault disappears. Any ideas why that is?
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: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x1031a
Start of program headers: 64 (bytes into file)
Start of section headers: 232 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 3
Size of section headers: 64 (bytes)
Number of section headers: 8
Section header string table index: 7
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] null NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .init PROGBITS 000000000001031a 0000031a
0000000000000001 0000000000000000 AX 0 0 0
[ 2] .text PROGBITS 000000000001031b 0000031b
0000000000000076 0000000000000000 AX 0 0 0
[ 3] .fini PROGBITS 0000000000010391 00000391
0000000000000001 0000000000000000 AX 0 0 0
[ 4] .rodata PROGBITS 0000000000011392 00000392
0000000000000014 0000000000000000 A 0 0 0
[ 5] .data PROGBITS 00000000000123a6 000003a6
000000000000001e 0000000000000000 A 0 0 0
[ 6] .bss NOBITS 00000000000123c4 000003c4
0000000000000000 0000000000000000 WA 0 0 0
[ 7] strtab STRTAB 00000000000002e8 000002e8
0000000000000032 0000000000000000 AS 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
l (large), p (processor specific)
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x000000000000031a 0x000000000001031a 0x000000000001031a
0x0000000000000078 0x0000000000000078 R E 0x1000
LOAD 0x0000000000000392 0x0000000000011392 0x0000000000011392
0x0000000000000014 0x0000000000000014 R 0x1000
LOAD 0x00000000000003a6 0x00000000000123a6 0x00000000000123a6
0x000000000000001e 0x0000000000000082 RW 0x1000
Section to Segment mapping:
Segment Sections...
00 .init .text .fini
01 .rodata
02 .data .bss
UPDATE 2:
Thank you Employed Russian for your answer and ideas. I wanted to share the following update on my own research:
After digging a bit more, I ran across the following line in an Oracle document about program loading:
By default, 64–bit SPARC programs are linked with a starting address of 0x100000000. The whole program is located above 4 gigabytes, including its text, data, heap, stack, and shared object dependencies. This helps ensure that 64–bit programs are correct because the program will fault in the least significant 4 gigabytes of its address space if the program truncates any of its pointers. While 64–bit programs are linked above 4 gigabytes, you can still link programs below 4 gigabytes by using a mapfile and the -M option to the link-editor. See /usr/lib/ld/sparcv9/map.below4G.
(Source: https://docs.oracle.com/cd/E19120-01/open.solaris/819-0690/chapter6-34713/index.html)
Now I am aware the information from that link is awfully specific, but I was nonetheless wondering if there could be some more universal truth to this on other platforms, or at least point me in the right direction.
So I wrote a tiny test program in C and compiled it in two different ways:
gcc test.c - ELF type is ET_DYN / shared object file and no default virtual address offset is used for the LOAD segments:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x0005c8 0x0005c8 R 0x1000
LOAD 0x001000 0x0000000000001000 0x0000000000001000 0x0001c5 0x0001c5 R E 0x1000
LOAD 0x002000 0x0000000000002000 0x0000000000002000 0x000130 0x000130 R 0x1000
LOAD 0x002df0 0x0000000000003df0 0x0000000000003df0 0x000220 0x000228 RW 0x1000
gcc -static test.c - ELF type is ET_EXEC / executable and default virtual address offset of 0x400000 is used:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x0000000000400000 0x0000000000400000 0x000518 0x000518 R 0x1000
LOAD 0x001000 0x0000000000401000 0x0000000000401000 0x0936dd 0x0936dd R E 0x1000
LOAD 0x095000 0x0000000000495000 0x0000000000495000 0x02664d 0x02664d R 0x1000
LOAD 0x0bc0c0 0x00000000004bd0c0 0x00000000004bd0c0 0x005170 0x0068c0 RW 0x1000
Any ideas why that is? I know it possibly has to do with position-independent code, but I do not understand the necessity for an offset if absolute code is used (as in 2. above). Thanks.
When I change the start address to 0x10000 (PAGESIZE * 16), then the segmentation fault disappears. Any ideas why that is?
This was mentioned in the comments to this answer:
Why does loading at 0x10000 work but at 0x1000 doesn't? Does this depend on the kernel or the hardware? How do I pick the right number here?
Some code in the kernel doesn't like to use addresses below 0x10000, but I have not found that code.
I've tried to load a binary with first PT_LOAD.p_vaddr == 0x1000 into UML kernel (which is easy to debug), but that actually worked, so specific kernel code which prohibits this may be architecture-dependent.

libbpf: sec 'sockops': failed to find program symbol at offset 0

I'd like to use the bpftool prog load to load my program into kernel. However, some errors occurred.
# bpftool prog load sockmap_update_kern.o "/sys/fs/bpf/bpf_sockmap"
libbpf: sec 'sockops': failed to find program symbol at offset 0
Error: failed to open object file
The program compiles fine with LLVM version 6.0.0
#include <linux/bpf.h>
#include "bpf_helpers.h"
struct bpf_map_def SEC("maps") sock_map = {
.type = BPF_MAP_TYPE_SOCKMAP,
.key_size = sizeof(int),
.value_size = sizeof(int),
.max_entries = 10,
};
SEC("sockops")
int sock_map_update(struct bpf_sock_ops *ops)
{
__u32 op, family;
int key;
op = ops->op;
family = ops->family;
switch (op){
case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:
case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
if (family == 2){ //AF_INET
key = 1;
bpf_sock_map_update(ops, &sock_map, &key, BPF_ANY);
}
default:
break;
}
return 0;
}
char _license[] SEC("license") = "GPL";
# readelf -a sockmap_update_kern.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: Linux BPF
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 456 (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: 8
Section header string table index: 1
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .strtab STRTAB 0000000000000000 00000170
0000000000000051 0000000000000000 0 0 1
[ 2] .text PROGBITS 0000000000000000 00000040
0000000000000000 0000000000000000 AX 0 0 4
[ 3] sockops PROGBITS 0000000000000000 00000040
0000000000000088 0000000000000000 AX 0 0 8
[ 4] .relsockops REL 0000000000000000 00000160
0000000000000010 0000000000000010 7 3 8
[ 5] maps PROGBITS 0000000000000000 000000c8
000000000000001c 0000000000000000 WA 0 0 4
[ 6] license PROGBITS 0000000000000000 000000e4
0000000000000004 0000000000000000 WA 0 0 1
[ 7] .symtab SYMTAB 0000000000000000 000000e8
0000000000000078 0000000000000018 1 2 8
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
p (processor specific)
There are no section groups in this file.
There are no program headers in this file.
There is no dynamic section in this file.
Relocation section '.relsockops' at offset 0x160 contains 1 entry:
Offset Info Type Sym. Value Sym. Name
000000000058 000300000001 unrecognized: 1 0000000000000000 sock_map
The decoding of unwind sections for machine type Linux BPF is not currently supported.
Symbol table '.symtab' contains 5 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000078 0 NOTYPE LOCAL DEFAULT 3 LBB0_3
2: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 6 _license
3: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 5 sock_map
4: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 3 sock_map_update
No version information found in this file.
My kernel version is 5.3.0-42. I get it by apt-get install, so I guess there are some problems about the kernel. Could you give me some advise? Thanks in advance.
# uname -a
Linux iZ2zehe0r5ccv5sse5ib5fZ 5.3.0-42-generic #34~18.04.1-Ubuntu SMP Fri Feb 28 13:42:26 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

Information about Section Index field (st_shndx) in Section SHT_DYNSYM & SHT_SYMTAB

Toolchain:
Product: ARM Compiler 5.04
Component: ARM Compiler 5.04 update 1 (build 49)
From ELF Portable Formats Specification, Version 1.1,
Section Index field (st_shndx) contains:
Every symbol table entry is ‘‘defined’’ in relation to some section; this member holds the relevant section header table index.
I am compiling a simple object (exports one global data & routine) to understand various fields of ELF
Source code (test.c):
__declspec(dllexport) int x21 = 0x100;
__declspec(dllexport) void bar21(void)
{
x21++;
}
Build script used (build.bat)
armcc -c test.c
armlink --bpabi --dll -o test.dll test.o
fromelf -cdrsy -o test.txt test.dll
My query is about usage of st_shndx field of DYNSYM section & SYMTAB section.
Output file
(Removed few sections to keep it short)
** Section #1 'ER_RO' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR]
Size : 24 bytes (alignment 4)
Address: 0x00008000
$a
.text
bar21
0x00008000: e59f000c .... LDR r0,[pc,#12] ; [0x8014] = 0
0x00008004: e5901000 .... LDR r1,[r0,#0]
0x00008008: e2811001 .... ADD r1,r1,#1
0x0000800c: e5801000 .... STR r1,[r0,#0]
0x00008010: e12fff1e ../. BX lr
$d
0x00008014: 00000000 .... DCD 0
** Section #2 'ER_RW' (SHT_PROGBITS) [SHF_ALLOC + SHF_WRITE]
Size : 4 bytes (alignment 4)
Address: 0x00000000
0x000000: 00 01 00 00 ....
** Section #3 '.dynstr' (SHT_STRTAB)
Size : 32 bytes
** Section #4 '.dynsym' (SHT_DYNSYM)
Size : 80 bytes (alignment 4)
String table #3 '.dynstr'
Last local symbol no. 1
Symbol table .dynsym (4 symbols, 1 local)
# Symbol Name Value Bind Sec Type Vis Size
========================================================================
1 .data 0x00000000 Lc 1 Sect De 0x4
2 shared_2.dll 0x00000000 Gb Abs Data De
3 x21 0x00000000 Gb 1 Data Pr 0x4
4 bar21 0x00008000 Gb 2 Code Pr 0x14
** Section #5 '.hash' (SHT_HASH)
Size : 40 bytes (alignment 4)
Symbol table #4 '.dynsym'
<Section Truncated>
** Section #7 '.version' (SHT_GNU_versym)
Size : 10 bytes (alignment 4)
Symbol table #4 '.dynsym'
<Section Truncated>
** Section #8 '.version_d' (SHT_GNU_verdef)
Size : 56 bytes (alignment 4)
String table #3 '.dynstr'
<Section Truncated>
** Section #9 '.dynamic' (SHT_DYNAMIC)
Size : 120 bytes (alignment 4)
String table #3 '.dynstr'
<Section Truncated>
** Section #10 '.debug_frame' (SHT_PROGBITS)
Size : 68 bytes
** Section #11 '.symtab' (SHT_SYMTAB)
Size : 176 bytes (alignment 4)
String table #12 '.strtab'
Last local symbol no. 6
Symbol table .symtab (10 symbols, 6 local)
# Symbol Name Value Bind Sec Type Vis Size
========================================================================
1 $a 0x00008000 Lc 1 -- De
2 $d 0x00008014 Lc 1 -- De
3 $d.realdata 0x00000000 Lc 2 -- De
4 shared_2.c 0x00000000 Lc Abs File De
5 .text 0x00008000 Lc 1 Sect De
6 .data 0x00000000 Lc 2 Sect De 0x4
7 BuildAttributes$$ARM_ISAv4$S$PE$A:L22$X:L11$S22$IEEE1$~IW$USESV6$~STKCKD$USESV7$~SHL$OSPACE$EBA8$STANDARDLIB$REQ8$PRES8$EABIv2
0x00000000 Gb Abs -- Hi
8 shared_2.dll 0x00000000 Gb Abs Data De
9 x21 0x00000000 Gb 2 Data Pr 0x4
10 bar21 0x00008000 Gb 1 Code Pr 0x14
Section 1 is Code area (bar21 routine is present here)
Section 2 is RW area (x21 variable is present here)
Now, if we see st_shndx (section index -- marked as "Sec" in output above) field in DYNSYM section & SYMTAB section for these two variables is different.
For Example:
x21 in DYNSYM points to section 1 (code area) & in SYMTAB, it points to section 2 (RW area)
Can someone help me understand why? Or guide me to resource where I can get more information on this.
Regards,
Raju Udava

storage classes in C language [duplicate]

This question already has an answer here:
SIZE command in UNIX
(1 answer)
Closed 7 years ago.
In this program i am not declaring any variable still is showing data segment (BSS) size as 8 bytes.why ?
achul#achul:~/chennai/misclaneous$ vi memory.c
#include<stdio.h>
main()
{
}
achul#achul:~/chennai/misclaneous$ cc memory.c -o mem
achul#achul:~/chennai/misclaneous$ size mem
text data bss dec hex filename
1056 252 8 1316 524 mem
here i am not using any global variable as BSS is reserved for global variable only anyone plz ?
In a normal (hosted) environment, the .c files and compiled to object files, and this object files are linked with the standard clib. And the library contains a module (generally called crt0.o) that is natively loaded by the system, optionnaly decodes the command line and calls the function main passing argc, argv and environment, and also generally sets some global variables.
This crt0 module does contain global variables.
Here are couple of outputs
Below is a compiled object and not at all linked, purely the simple program above with no global content as indicated.
size t1.o
text data bss dec hex filename
62 0 0 62 3e t1.o
size --format=SysV t1.o
t1.o :
section size addr
.text 6 0
.data 0 0
.bss 0 0
.comment 42 0
.note.GNU-stack 0 0
.eh_frame 56 0
Total 104
And this Below is a complete executable likned with startup code and other supported stuff.
size a.out
text data bss dec hex filename
1115 552 8 1675 68b a.out
size --format=SysV a.out
a.out :
section size addr
.interp 28 4194872
.note.ABI-tag 32 4194900
.note.gnu.build-id 36 4194932
.gnu.hash 28 4194968
.dynsym 72 4195000
.dynstr 56 4195072
.gnu.version 6 4195128
.gnu.version_r 32 4195136
.rela.dyn 24 4195168
.rela.plt 48 4195192
.init 26 4195240
.plt 48 4195280
.text 370 4195328
.fini 9 4195700
.rodata 4 4195712
.eh_frame_hdr 52 4195716
.eh_frame 244 4195768
.init_array 8 6295056
.fini_array 8 6295064
.jcr 8 6295072
.dynamic 464 6295080
.got 8 6295544
.got.plt 40 6295552
.data 16 6295592
.bss 8 6295608
.comment 77 0
Total 1752

objdump won't show my ELF sections

I have a tool emitting an ELF, which as far as I can tell is compliant to the spec. Readelf output looks fine, but objdump refuses to disassemble anything.
I have simplified the input to a single global var, and "int main(void) { return 0;}" to aid debugging - the tiny section sizes are correct.
In particular, objdump seems unable to find the sections table:
$ arm-none-linux-gnueabi-readelf -S davidm.elf
There are 4 section headers, starting at offset 0x74:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text NULL ff000000 000034 00001c 00 AX 0 0 4
[ 2] .data NULL ff00001c 000050 000004 00 WA 0 0 4
[ 3] .shstrtab NULL 00000000 000114 000017 00 0 0 0
$ arm-none-linux-gnueabi-objdump -h davidm.elf
davidm.elf: file format elf32-littlearm
Sections:
Idx Name Size VMA LMA File off Algn
I also have another ELF, built from the exact same objects, only produced with regular toolchain use:
$ objdump -h kernel.elf
kernel.elf: file format elf32-littlearm
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 0000001c ff000000 ff000000 00008000 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000004 ff00001c ff00001c 0000801c 2**2
CONTENTS, ALLOC, LOAD, DATA
Even after I stripped .comment and .ARM.attributes sections (incase objdump requires them) from the 'known good' kernel.elf, it still happily lists the sections there, but not in my tool's davidm.elf.
I have confirmed the contents of the sections are identical between the two with readelf -x.
The only thing I can image is that the ELF file layout is different and breaks some expectations of BFD, which could explain why readelf (and my tool) processes it just fine but objdump has troubles.
Full readelf:
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: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0xff000000
Start of program headers: 84 (bytes into file)
Start of section headers: 116 (bytes into file)
Flags: 0x5000002, has entry point, Version5 EABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 1
Size of section headers: 40 (bytes)
Number of section headers: 4
Section header string table index: 3
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text NULL ff000000 000034 00001c 00 AX 0 0 4
[ 2] .data NULL ff00001c 000050 000004 00 WA 0 0 4
[ 3] .shstrtab NULL 00000000 000114 000017 00 0 0 0
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000034 0xff000000 0xff000000 0x00020 0x00020 RWE 0x8000
Section to Segment mapping:
Segment Sections...
00 .text .data
There is no dynamic section in this file.
There are no relocations in this file.
There are no unwind sections in this file.
No version information found in this file.
Could the aggressive packing of the on-disk layout be causing troubles? Am I in violation of some bytestream alignment restrictions BFD expects, documented or otherwise?
Lastly - this file is not intended to be mmap'd into an address space, a loader will memcpy segment data into the desired location, so there is no requirement to play mmap-friendly file-alignment tricks. Keeping the ELF small is more important.
Cheers,
DavidM
EDIT: I was asked to upload the file, and/or provide 'objdump -x'. So I've done both:
davidm.elf
$ objdump -x davidm.elf
davidm.elf: file format elf32-littlearm
davidm.elf
architecture: arm, flags 0x00000002:
EXEC_P
start address 0xff000000
Program Header:
LOAD off 0x00000034 vaddr 0xff000000 paddr 0xff000000 align 2**15
filesz 0x00000020 memsz 0x00000020 flags rwx
private flags = 5000002: [Version5 EABI] [has entry point]
Sections:
Idx Name Size VMA LMA File off Algn
SYMBOL TABLE:
no symbols
OK - finally figured it out.
After building and annotating/debugging libbfd (function elf_object_p()) in the context of a little test app, I found why it was not matching on any of BFD supported targets.
I had bad sh_type flags for the section headers: NULL. Emitting STRTAB or PROGBITS (and eventually NOBITS when I get that far) as appropriate and objdump happily walks my image.
Not really surprising, in retrospect - I'm more annoyed I didn't catch this in comparing readelf outputs than anything else :(
Thanks for the help all :)

Resources