I have hand-written an ELF32 object file that I would like to link via. gcc but I get an undefined reference when I try to use my function/label. I have it defined in a test C file as extern
yet this does not change anything.
This object file contains the following assembly:
00000000 <func>:
0: 31 c0 xor %eax,%eax
2: 40 inc %eax
3: b3 2a mov $0x2a,%bl
5: cd 80 int $0x80
What you see here is the output from objdump -S test.o
which shows that objdump is very much capable of finding my .text
section.
My readelf
output is:
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: 128 (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: 1
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .shstrtab STRTAB 00000000 000034 000021 00 0 0 1
[ 2] .text PROGBITS 00000000 000060 000007 00 AX 0 0 16
[ 3] .strtab STRTAB 00000000 000070 00000d 00 0 0 1
[ 4] .symtab SYMTAB 00000000 000150 000040 10 3 4 4
Symbol table '.symtab' contains 4 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS test.S
2: 00000000 0 SECTION LOCAL DEFAULT 2
3: 00000000 0 NOTYPE GLOBAL DEFAULT 2 func
Which furthermore shows I have a valid symbol table and sections.
My question is, what are the exact conditions for an undefined reference to occur? What have I done incorrectly here that could lead to such an error? Is alignment for every section imperative? I've mostly done that already.
I have my symbol set to global, it is found by these two ELF analysis programs yet GCC still fails to recognise the symbol...
Here is the dump of the ELF file:
00000000: 7f45 4c46 0101 0100 0000 0000 0000 0000 .ELF............
00000010: 0100 0300 0100 0000 0000 0000 0000 0000 ................
00000020: 8000 0000 0000 0000 3400 0000 0000 2800 ........4.....(.
00000030: 0500 0100 002e 7368 7374 7274 6162 002e ......shstrtab..
00000040: 7465 7874 002e 7374 7274 6162 002e 7379 text..strtab..sy
00000050: 6d74 6162 0000 0000 0000 0000 0000 0000 mtab............
00000060: 31c0 40b3 2acd 8000 0000 0000 0000 0000 1.@.*...........
00000070: 0066 756e 6300 7465 7374 2e53 0000 0000 .func.test.S....
00000080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000a0: 0000 0000 0000 0000 0100 0000 0300 0000 ................
000000b0: 0000 0000 0000 0000 3400 0000 2100 0000 ........4...!...
000000c0: 0000 0000 0000 0000 0100 0000 0000 0000 ................
000000d0: 0b00 0000 0100 0000 0600 0000 0000 0000 ................
000000e0: 6000 0000 0700 0000 0000 0000 0000 0000 `...............
000000f0: 1000 0000 0000 0000 1100 0000 0300 0000 ................
00000100: 0000 0000 0000 0000 7000 0000 0d00 0000 ........p.......
00000110: 0000 0000 0000 0000 0100 0000 0000 0000 ................
00000120: 1900 0000 0200 0000 0000 0000 0000 0000 ................
00000130: 5001 0000 4000 0000 0300 0000 0400 0000 P...@...........
00000140: 0400 0000 1000 0000 0000 0000 0000 0000 ................
00000150: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000160: 0600 0000 0000 0000 0000 0000 0400 f1ff ................
00000170: 0000 0000 0000 0000 0000 0000 0300 0200 ................
00000180: 0100 0000 0000 0000 0000 0000 1000 0200 ................
I've tried already to change the function name, NOTYPE
to FUNC
and giving the symbol a size, yet nothing fixes the issue. The layout of the symbol table is exactly as my NASM-generated file gives me.
Edit: The file that I am trying to link with my ELF is giving the error:
/usr/bin/ld: foo.o: in function `main':
foo.c:(.text+0x18): undefined reference to `func'
collect2: error: ld returned 1 exit status
from running gcc -m32 foo.o test.o
Source code:
extern void func();
int
main(int argc,
char **argv)
{
func();
return 0;
}
And symbol table of this file after gcc -m32 -c foo.c -o foo.o
:
Symbol table '.symtab' contains 15 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS foo.c
2: 00000000 0 SECTION LOCAL DEFAULT 2
3: 00000000 0 SECTION LOCAL DEFAULT 4
4: 00000000 0 SECTION LOCAL DEFAULT 5
5: 00000000 0 SECTION LOCAL DEFAULT 6
6: 00000000 0 SECTION LOCAL DEFAULT 8
7: 00000000 0 SECTION LOCAL DEFAULT 9
8: 00000000 0 SECTION LOCAL DEFAULT 10
9: 00000000 0 SECTION LOCAL DEFAULT 7
10: 00000000 0 SECTION LOCAL DEFAULT 1
11: 00000000 38 FUNC GLOBAL DEFAULT 2 main
12: 00000000 0 FUNC GLOBAL HIDDEN 6 __x86.get_pc_thunk.ax
13: 00000000 0 NOTYPE GLOBAL DEFAULT UND _GLOBAL_OFFSET_TABLE_
14: 00000000 0 NOTYPE GLOBAL DEFAULT UND func
The error is best understood by using lld
to perform the link:
ld.lld -m elf_i386 -e main main.o test.o
ld.lld: error: test.o: non-local symbol (3) found at index < .symtab's sh_info (4)
From the Solaris Linker docs:
In each symbol table, all symbols with STB_LOCAL binding precede the weak and global symbols. As "Sections" describes, a symbol table section's sh_info section header member holds the symbol table index for the first non-local symbol.
You must set .symtab
s .sh_info
to 3, and then your test.o
will work.