Linker script not working? - c

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.

Related

ARM cross compile for x86 error: relocation truncated to fit: R_x86_64_32 against '.rodata", how do I fix this?

I'm trying to cross compile a custom OS for x86 hardware on an ARM based system (Debian VM on M1 Mac). To compile I'm using "x86_64-linux-gnu-gcc" and for a linker I'm using "x86_64_linux-gnu-ld".
Note that this does build and compile normally when not on an ARM system. So an x86_64 system will compile and link correctly. I am trying to cross compile this because the ARM version of gcc does not like the x86 assembly boot code that we have (if you think this is the better approach and have tips for handling it this way please let me know).
The error I have comes up when trying to go through the linking process:
Linking for "kernel/kernel.bin"...
main/acpi.o: in function `__rsdp_search_range':
/home/project/kernel/main/acpi.c:63:(.text+0x13b): relocation truncated to fit: R_X86_64_32 against `.rodata'
main/acpi.o: in function `acpi_init':
/home/project/kernel/main/acpi.c:108:(.text+0x290): relocation truncated to fit: R_X86_64_32 against `.rodata'
/home/project/kernel/main/acpi.c:108:(.text+0x295): relocation truncated to fit: R_X86_64_32 against `.rodata'
/home/project/kernel/main/acpi.c:108:(.text+0x29a): relocation truncated to fit: R_X86_64_32 against `.rodata'
/home/project/kernel/main/acpi.c:108:(.text+0x2a4): relocation truncated to fit: R_X86_64_32 against `.rodata'
/home/project/kernel/main/acpi.c:114:(.text+0x327): additional relocation overflows omitted from the output
make[1]: *** [Makefile:34: kernel.bin] Error 1
make[1]: Leaving directory '/home/project/kernel'
make: *** [Makefile:6: all_kernel] Error 2
After trying to search for similar errors, I tried modifying the gcc flags. We already had -mcmodel=large, but i tested with the different variations. I also tested with -fPIC but none of these changes fixed the problem.
gcc flags:
cflags.x86-64 := -march=x86-64 -m64 -mno-red-zone -mcmodel=large -mno-sse3 -mno-ssse3 -mno-sse4.1 -mno-sse4.2 -mno-sse4 -mno-sse4a -mno-3dnow -mno-avx -mno-avx2
cflags.common := -fno-pie -ffreestanding -fno-builtin -nostdinc -std=c99 -g3 -gdwarf-3 -fno-stack-protector -fsigned-char -Iinclude
cflags.warnings := -Wall -Wredundant-decls -Wundef -Wpointer-arith -Wfloat-equal -Wnested-externs -Wvla -Winline -Wextra -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable -Wno-attributes
linker code:
OUTPUT_FORMAT(elf64-x86-64)
KERNEL_LMA = 0x00100000;
KERNEL_VMA = 0xffff800000000000;
ENTRY(_start)
STARTUP(entry/entry.o)
SECTIONS {
. = KERNEL_VMA + KERNEL_LMA;
k_start = .;
.text : AT(ADDR(.text) - KERNEL_VMA) {
_code = .;
*(.multiboot)
*(.text)
. = ALIGN(0x1000);
}
csd_start = .;
.csd : AT(ADDR(.csd) - KERNEL_VMA) {
*(.csd)
. = ALIGN(0x1000);
}
csd_end = .;
.init : AT(ADDR(.init) - KERNEL_VMA) {
kernel_start_init = .;
*(.init)
. = ALIGN(0x1000);
kernel_end_init = .;
}
.rodata : AT(ADDR(.rodata) - KERNEL_VMA) {
_rodata = .;
*(.rodata)
. = ALIGN(0x1000);
}
.data : AT(ADDR(.data) - KERNEL_VMA) {
_data = .;
*(.data)
. = ALIGN(0x1000);
}
_edata = .;
.bss : AT(ADDR(.bss) - KERNEL_VMA) {
_bss = .;
*(.bss)
*(COMMON)
. = ALIGN(0x1000);
}
_end = .;
/DISCARD/ : {
*(.comment)
*(note.*)
}
kernel_phys_off = k_start - KERNEL_LMA;
kernel_phys_base = k_start - kernel_phys_off;
kernel_phys_end = _end - kernel_phys_off;
kernel_page_tables = ((_end - k_start) / 0x80000) + 1; /* XXX might be 0x200000 */
kernel_text_sectors = ((_end - k_start) / 512) + 1;
}
Edit
Below is the __rsdp_search_range function, I dont necessarily think it is the problem because if I comment out this file, for instance, the error pops up elsewhere.
static rsdp_20_t *__rsdp_search_range(uintptr_t start, uintptr_t end)
{
uintptr_t rsdp_candidate = start;
while (rsdp_candidate <= end - sizeof(struct rsdp))
{
if (memcmp((void *)rsdp_candidate, rsdp_sig, sizeof(rsdp_sig)) == 0 &&
__acpi_checksum((uint8_t *)rsdp_candidate, sizeof(rsdp_20_t)) ==
0)
{
return (rsdp_20_t *)rsdp_candidate;
}
rsdp_candidate += RSDP_ALIGN;
}
return NULL;
}
I did try and remove -fno-pie and got the following error instead: x86_64-linux-gnu-ld: failed to convert GOTPCREL relocation; relink with --no-relax"

[Golang][Cgo] It is possible to build go source file with c-archive with less runtime libraries?

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 = .;
}

/usr/bin/ld: cannot find -lgcc_s

I have a problem I need help with.
I am currently trying to write a program to read out the address of a section I created.
add.c:
#include <stdio.h>
extern unsigned char arduino_handler_size[];
int main(){
printf("section `.arduino_handler` starts at %p and the 1st byte is %x\n",
arduino_handler_size, (unsigned int)arduino_handler_size[0]);
return 0;
}
arduino_handler.ld:
OUTPUT_FORMAT(elf64-x86-64)
ENTRY(main)
OUTPUT(Test)
SECTIONS
{
.text : { *(.text) }
. = ALIGN(0x1000);
.data : { *(.data) }
. = ALIGN(0x10000);
.bss : { *(.bss)}
. = ALIGN(0X10000);
.arduino_handler :
{
arduino_handler_size = 0x10;
arduino_handler_start = .;
. = . + arduino_handler_size;
arduino_handler_end = .;
}
}
When I run gcc -T arduino_handler.ld -N add.c I get the error:
/usr/bin/ld: cannot find -lgcc_s
/usr/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
I am working on:
Ubuntu 18.04.3 LTS
Kernel: 5.0.0-37-generic x86_64 bits: 64
I have tried changing the gcc version from 7 to 4.8 and back to 8. That sadly doesn't help.
The symbolic link for libgcc_s is not broken, but it still gives me an error.
How can I fix this?

How to run a linker script for GCC

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?

How to use ld --gc-sections with OUTPUT_FORMAT(binary)

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.

Resources