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)
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 = .;
}
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?
I've got this code:
char* vidmem = (char*)0xb8000;
int main()
{
vidmem[0] = 'x';
}
but this acts like vidmem is not initalized. if instead i do something like this:
char* vidmem;
int main()
{
vidmem = (char*)0xb8000;
vidmem[0] = 'x';
}
this works perfectly. Why?
I use this lines to compile and link:
gcc -c main.c -o main.o -ffreestanding -fno-exceptions -m64
gcc -m64 -Wl,--build-id=none -static -nostdlib -nodefaultlibs -lgcc main.obj [...] -T linker.ld -o out.bin
using this linker file:
ENTRY(_start)
SECTIONS
{
. = 0x7C00;
.bss :
{
*(.bss);
}
.text :
{
*(.text);
}
}
There is actually some assembly code calling this C file but it should not matter. Am i doing something wrong with gcc? How can i fix it?
You haven't put your data or rodata sections in your linker script. Check your main.o file for what section vidmem is in and make sure you set that up correctly in your script.
Not only sections in the linked file are needed but also the initialization code which will copy the data.
In the linked script you also need to show there to place the data and there the values in the RO memory are stored( after the closing bracket
I'm using gcc to compile a printing function. But met the following 2 problems:
Whenever I apply a local array type variable, the linker would report and error of "undefined reference to `__stack_chk_fail'"
When I'm using "inline" to define a function, it report an error of "undefined reference to `strlen'"
My platform is Ubuntu 18.04, and gcc version is 7.3.0.
I present some of the problem codes:
In function "number()" I applied an "char" type array variable, which actually cause the 1st error:
char* number(char *str, long num, int base, int field_width, int precision, int type)
{
char *TempDgt = DigitsCptl, c, sign;
int i;
char TempStr[50];
....
return str;
}
The problem lies on "char TempStr[50];" and with the removal of it, the link succeed. Similar problem appears on "va_list args;" of the following code:
int color_printk(unsigned int FRcolor, unsigned int BKcolor, char * fmt, ...)
{
int count, i, line;
va_list args;
...
return i;
}
Second problem lies on function "strlen" as follow:
inline int strlen(char * String)
{
...
return __res;
}
This time the "inline" descriptor caused the problem.
Both of the problems occur at "ld" instruction, the following is my makefile:
Kernel:
# Clear previous files
- rm head.s head.o main.o system kernel.bin printk.o
# Compile head.S
gcc -E ./OSFiles/Codes/head.S > head.s
as --64 -o head.o head.s
# Compile main function
gcc -mcmodel=large -fno-builtin -m64 -c ./OSFiles/Codes/main.c
gcc -mcmodel=large -fno-builtin -m64 -c ./OSFiles/Codes/printk.c
# Link compiled files
ld -b elf64-x86-64 -z muldefs -o system head.o main.o printk.o -T ./OSFiles/Codes/Kernel.lds
# Dump out Kernel.bin
objcopy -I elf64-x86-64 -S -R ".eh_frame" -R ".comment" -O binary system Kernel.bin
And the .ids file:
OUTPUT_FORMAT("elf64-x86-64","elf64-x86-64","elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(_start)
SECTIONS
{
. = 0xffff800000000000 + 0x100000;
.text :
{
_text = .;
*(.text)
_etext = .;
}
.data :
{
_data = .;
*(.data)
_edata = .;
}
.bss :
{
_bss = .;
*(.bss)
_ebss = .;
}
_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.