I'm trying to run a simple linker script to understand how linking works and how i can implement function reordering with the linker script
Here is my C code
void A(){
printf("A\n");
}
void B(){
printf("B\n");
}
void main(){
B();
A();
}
Here is the linker script
SECTIONS
{
. = 0x10000;
.text : { *(.text) }
. = 0x8000000;
.data : { *(.data) }
.bss : { *(.bss) }
}
When i try to compile with this external linker script it gives me this error
/usr/lib64/libc_nonshared.a(elf-init.oS): In function `__libc_csu_init':
(.text+0x14): undefined reference to `__init_array_start'
/usr/lib64/libc_nonshared.a(elf-init.oS): In function `__libc_csu_init':
(.text+0x1c): undefined reference to `__init_array_end'
/usr/bin/ld: cl: hidden symbol `__init_array_end' isn't defined
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
My compile command is this
gcc -Wl,-no-whole-archive -ffunction-sections -T simple.ld cache_ex.c -o cl
Can you tell me what i'm doing wrong?
Related
I have one question about export golang source file as c-archive file when building. For example, we have 2 files for both c and golang.
// The Entry defined in golang, and build with cgo.
extern void Entry();
int main() {
// Entry();
return 0;
}
package main
import "C"
//export Entry
func Entry(magic int) {
}
//#cgo CFLAGS: -nostdlib -nostdinc -fno-builtin -fno-stack-protector -m32 -Wall -Wextra -Werror
func main() {
}
For c source files, it may be compiled like below.
gcc -nostdlib -nostdinc -fno-builtin -fno-stack-protector -m32 -Wall -Wextra -Werror -c entry/main.c -o entry/main.o
For golang source files, it will be compiled like below.
go build -o entry/entry.a -buildmode=c-archive entry/entry.go
After that, we would like to link it together as below. Unfortunately, it may depend on some more symbols from libc or even more libs from cgo.
ld -T./config/link.ld -m elf_i386 entry/main.o entry/entry.a -o unicorn/kernel
ld: entry/entry.a(000010.o): in function `x_cgo_thread_start':
/_/runtime/cgo/gcc_util.c:15: undefined reference to `malloc'
ld: /_/runtime/cgo/gcc_util.c:18: undefined reference to `stderr'
ld: entry/entry.a(000010.o): in function `fprintf':
/usr/include/bits/stdio2.h:105: undefined reference to `fwrite'
ld: entry/entry.a(000010.o): in function `x_cgo_thread_start':
/_/runtime/cgo/gcc_util.c:19: undefined reference to `abort'
ld: entry/entry.a(000005.o): in function `fatalf':
/_/runtime/cgo/gcc_fatalf.c:17: undefined reference to `stderr'
ld: entry/entry.a(000005.o): in function `fprintf':
/usr/include/bits/stdio2.h:105: undefined reference to `fwrite'
ld: entry/entry.a(000005.o): in function `vfprintf':
/usr/include/bits/stdio2.h:135: undefined reference to `__vfprintf_chk'
ld: entry/entry.a(000005.o): in function `fprintf':
/usr/include/bits/stdio2.h:105: undefined reference to `fputc'
ld: entry/entry.a(000005.o): in function `fatalf':
/_/runtime/cgo/gcc_fatalf.c:22: undefined reference to `abort'
ld: unicorn/kernel: hidden symbol `__stack_chk_fail_local' isn't defined
ld: final link failed: bad value
I am not sure for now if it is possible to compile the golang source files with fewer links to libc or cgo libraries. Here is the link.ld for reference. Thank you very much.
ENTRY(start)
OUTPUT_FORMAT("elf32-i386")
SECTIONS
{
.text 0x100000 :
{
code = .; _code = .; __code = .;
*(.text)
. = ALIGN(4096);
}
.data :
{
data = .; _data = .; __data = .;
*(.data)
*(.rodata)
. = ALIGN(4096);
}
.bss :
{
bss = .; _bss = .; __bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .; _end = .; __end = .;
}
If my GNU ld linker script has OUTPUT_FORMAT(binary) the ld --gc-sections command-line flag seems to be ignored:
$ cat gcs.c
extern void magic(void);
void callmagic(void) { magic(); }
int uanswer = 42;
int main(void) { return 0; }
$ cat ofbin.scr
OUTPUT_FORMAT(binary)
OUTPUT_ARCH(i386)
ENTRY(main)
SECTIONS {
. = 0x10000;
.text : { *(.text*) }
.data : { *(.data*) *(.rodata*) }
.bss : { *(.bss*); }
}
$ cat ofelf.scr
OUTPUT_FORMAT(elf32-i386)
OUTPUT_ARCH(i386)
ENTRY(main)
SECTIONS {
. = 0x10000;
.text : { *(.text*) }
.data : { *(.data*) *(.rodata*) }
.bss : { *(.bss*); }
}
$ gcc -m32 -nostdlib -nostartfiles -nodefaultlibs gcs.c -ffunction-sections -fdata-sections -Wl,--gc-sections,--print-gc-sections -Wl,-T,ofelf.scr
/usr/bin/ld: Removing unused section '.text.callmagic' in file '/tmp/ccSFoPYg.o'
/usr/bin/ld: Removing unused section '.data.uanswer' in file '/tmp/ccSFoPYg.o'
/usr/bin/ld: Removing unused section '.eh_frame' in file '/tmp/ccSFoPYg.o'
$ gcc -m32 -nostdlib -nostartfiles -nodefaultlibs gcs.c -ffunction-sections -fdata-sections -Wl,--gc-sections,--print-gc-sections -Wl,-T,ofbin.scr
/tmp/cceXCw2b.o: In function `callmagic':
gcs.c:(.text.callmagic+0x7): undefined reference to `magic'
collect2: error: ld returned 1 exit status
I'm using GNU ld 2.24 and GCC 4.8.4 on Ubuntu 14.04.
How can I make this .c file compile and link with OUTPUT_FORMAT(binary) and with the code of callmagic eliminated by --gc-sections?
It looks like this is impossible, and GNU ld ignores --gc-sections with OUTPUT_FORMAT(binary).
A possible workaround is using OUTPUT_FORMAT(elf32-i386) and post-processing the output ELF file, e.g. with objcopy -O binary a.out a.out.bin.
I have a very simple program (simple.c):
#include <stdio.h>
int main(){
int a = 4;
return 0;
}
I am trying to use a the following linker script (MEMORY):
MEMORY
{
m_text : ORIGIN = 0x0000000000400000, LENGTH = 0x0001FBF0
m_data : ORIGIN = 0x0000000000600000, LENGTH = 0x00004000
}
SECTIONS
{
.text :
{
*(.text) /* Program Code */
} > m_text
.data : { *(.data) } > m_data
.bss : { *(.bss) } > m_data
}
I am using following commands to compile and link:
gcc -c simple.c
ld -T MEMORY -o simple -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o /usr/lib/x86_64-linux-gnu/crtn.o simple.o
I am getting the following ERROR:
ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 0 has invalid symbol index 11
.
.
.
ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_line): relocation 0 has invalid symbol index 2
/usr/lib/x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x12): undefined reference to `__libc_csu_fini'
/usr/lib/x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x19): undefined reference to `__libc_csu_init'
/usr/lib/x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x25): undefined reference to `__libc_start_main'
simple.o: In function `main':
simple.c:(.text+0xa): undefined reference to `puts'
If I try to use :
ld -T MEMORY4 -o simple -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o /usr/lib/x86_64-linux-gnu/crtn.o simple.o -lc
It gives the ERROR
ld: cannot find -lc
Any suggestions? All I want to do is place my simple.c into some different memory region then default.
There are a couple of problems, but the main one is with your linker script doesn't have a .debug_info or .debug_line section.
I'm trying to compile this simple program with a custom linker script on an amd-64 linux machine
// main.c
#include <stdio.h>
#include <stdlib.h>
int main(void) {
printf("Hello World!\n");
int* x = malloc(sizeof(int));
while(1) {}
return 0;
}
and
// script.ld
SECTIONS
{
. = 0x100000000;
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss) }
}
but if I do gcc -T script.ld main.c -o main, I get
a lot of errors like
/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x12): relocation truncated to fit: R_X86_64_32S against symbol `__libc_csu_fini' defined in .text section in /usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS)
You are trying to link main at 0x100000000, which is above 4GB boundary, but GCC (and your libc) are not set up for -mcmodel=large.
The default is -mcmodel=medium, which implies that the program is linked into the lower 2GBs of address space.
You would need to build both main.c and crt1.o with -mcmodel=large in order to link your executable at 0x100000000.
Or just use -fPIE and -pie and your executable will load at arbitrary (but usually well above 4GB boundary) address.
I'm trying to learn linker script
Here are my files
caller.c
extern void hello();
void main()
{
hello();
}
helloasm.c
#include <stdio.h>
void hello()
{
printf("\nHELLO\n\n");
}
link.lds
SECTIONS
{
. = 0x10000;
.text : { *(.text) }
. = 0x8000000;
.data : { *(.data) }
.bss : { *(.bss) }
}
compile.sh
cc -S helloasm.c #generate assembly file
cc -c helloasm.s #generate object file
cc -c caller.c #generate object file
ld -o hello -T link.lds helloasm.o caller.o
when i'm using
cc caller.c helloasm.c
i'm getting the output
HELLO
but when the sh file is called
i'm getting error
**
helloasm.o: In function `hello':
helloasm.c:(.text+0xe): undefined reference to `puts'
**
can someone explain why puts function is undefined
GNU ld (GNU Binutils for Ubuntu) 2.23.2
gcc version 4.7.3 (Ubuntu/Linaro 4.7.3-1ubuntu1)