user space program relocation truncated to fit

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
lalith
Posts: 2
Joined: Mon Jul 24, 2017 7:59 am
Libera.chat IRC: laverin

user space program relocation truncated to fit

Post by lalith »

i am building a user space program but when i am linking the crtbegin.o and crtend.o i get linking errors

errors

1> /home/user/opt64/cross/lib/gcc/x86_64-elf/6.1.0/crtbegin.o: In function `deregister_tm_clones':
1> crtstuff.c:(.text+0x1): relocation truncated to fit: R_X86_64_32 against symbol `__TMC_END__' defined in .got section in debug/uptime
1> crtstuff.c:(.text+0x8): relocation truncated to fit: R_X86_64_32S against `.tm_clone_table'
1> crtstuff.c:(.text+0x21): relocation truncated to fit: R_X86_64_32 against `.tm_clone_table'
1> /home/user/opt64/cross/lib/gcc/x86_64-elf/6.1.0/crtbegin.o: In function `register_tm_clones':
1> crtstuff.c:(.text+0x41): relocation truncated to fit: R_X86_64_32 against symbol `__TMC_END__' defined in .got section in debug/uptime
1> crtstuff.c:(.text+0x49): relocation truncated to fit: R_X86_64_32S against `.tm_clone_table'
1> crtstuff.c:(.text+0x6f): relocation truncated to fit: R_X86_64_32 against `.tm_clone_table'
1> /home/user/opt64/cross/lib/gcc/x86_64-elf/6.1.0/crtbegin.o: In function `__do_global_dtors_aux':
1> crtstuff.c:(.text+0x98): relocation truncated to fit: R_X86_64_32 against symbol `__DTOR_END__' defined in .dtors section in /home/LALITHSAI/opt64/cross/lib/gcc/x86_64-elf/6.1.0/crtend.o
1> crtstuff.c:(.text+0x9e): relocation truncated to fit: R_X86_64_32 against `.dtors'
1> crtstuff.c:(.text+0xa5): relocation truncated to fit: R_X86_64_32S against `.dtors'
1> crtstuff.c:(.text+0xed): relocation truncated to fit: R_X86_64_32 against `.eh_frame'
1> crtstuff.c:(.text+0xf2): additional relocation overflows omitted from the output
1>collect2 : error : ld returned 1 exit status

the user shell program:

int main(int argc, char* argv[]){
if(argc == 1){
tlib::print_line("Usage: mkdir file_path");
return 1;
}

auto result = tlib::mkdir(argv[1]);

if(result < 0){
tlib::printf("mkdir: error: %s\n", std::error_message(-result));
}

return 0;
}
linker script:
ENTRY(_start)

SECTIONS {
. = 0x8000400000;

.text BLOCK(4096) : ALIGN(4096)
{
*(.start)
*(.text)
*(.text*)
}

. = 0x8000600000;

.data BLOCK(4096) : ALIGN(4096)
{
*(.data)

}

.rodata BLOCK(4096) : ALIGN(4096)
{
*(.rodata)
*(.rodata*)
}

.bss BLOCK(4096) : ALIGN(4096)
{
*(.bss)
}

}
crti file:
.intel_syntax noprefix

.section .init
.global _init
.type _init, @function
_init:
push rbp
mov rbp, rsp

/* gcc will nicely put the contents of crtbegin.o's .init section here. */

.section .fini
.global _fini
.type _fini, @function
_fini:
push rbp
mov rbp, rsp

/* gcc will nicely put the contents of crtbegin.o's .fini section here. */

crtn file:
.intel_syntax noprefix

.section .init
/* gcc will nicely put the contents of crtend.o's .init section here. */

pop rbp
ret

.section .fini
/* gcc will nicely put the contents of crtend.o's .fini section here. */

pop rbp
ret

crt0 file:
int main(int argc, char* argv[]);

extern "C" {

void __cxa_finalize(void* f);

void _init();
void _fini();

void _start(int argc, char* argv[]) __attribute__((section(".start")));

void _start(int argc, char* argv[]){
// Call the global constructors, if any
_init();

// Execute the main function
auto code = main(argc, argv);

// Call the global destructors, if any
_fini();

// Call the shared library destructors, if any
__cxa_finalize(nullptr);

// Kill the process with the correct exit code
tlib::exit(code);
}

#define ATEXIT_MAX_FUNCS 32

struct atexit_func_entry_t {
void (*destructor_func)(void *);
void *obj_ptr;
void *dso_handle;
};

atexit_func_entry_t __atexit_funcs[ATEXIT_MAX_FUNCS];
int __atexit_func_count = 0;

int __cxa_atexit(void (*f)(void *), void *objptr, void *dso){
if (__atexit_func_count >= ATEXIT_MAX_FUNCS) {
return -1;
}

__atexit_funcs[__atexit_func_count].destructor_func = f;
__atexit_funcs[__atexit_func_count].obj_ptr = objptr;
__atexit_funcs[__atexit_func_count].dso_handle = dso;
__atexit_func_count++;

return 0; /*I would prefer if functions returned 1 on success, but the ABI says...*/
}

void __cxa_finalize(void* f){
int i = __atexit_func_count;
if (!f){
while (i--){
if (__atexit_funcs.destructor_func){
(*__atexit_funcs.destructor_func)(__atexit_funcs.obj_ptr);
}
}
return;
}

for ( ; i >= 0; --i){
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
if (__atexit_funcs.destructor_func == f){
(*__atexit_funcs.destructor_func)(__atexit_funcs.obj_ptr);
__atexit_funcs.destructor_func = 0;
}
#pragma GCC diagnostic pop
}
}

}
command to linking:
PROGRAM_LINK_FLAGS=$(COMMON_CPP_FLAGS) $(FLAGS_64) $(WARNING_FLAGS) $(COMMON_LINK_FLAGS) -static -L../../tlib/debug/ -mcmodel=large -fPIC -z max-page-size=0x1000 -T ../linker.ld

$(CXX) -o debug/$(1) $(PROGRAM_LINK_FLAGS) ../../tlib/debug/src/crti.s.o $$(shell $(CXX) -print-file-name=crtbegin.o) $(O_FILES) -ltlib $$(shell $(CXX) -print-file-name=crtend.o) ../../tlib/debug/src/crtn.s.o
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: user space program relocation truncated to fit

Post by iansjack »

simeonz
Member
Member
Posts: 360
Joined: Fri Aug 19, 2016 10:28 pm

Re: user space program relocation truncated to fit

Post by simeonz »

The OP question was educational to me. Previously I assumed (rather naively) that rip relative relocations on x64 pretty much enable position independence even without "-fpic". It turns out that calls and accesses are covered, but address arithmetic is not.

One of the errors here is due to address subtraction in crtstuff.c. There is branch condition which involves the offset of one symbol from another symbol in the same section. The subtraction is between absolute addresses. It is true that the result could be made identical if rip relative relocations were used, but the compiler needs to work harder to infer this. If crtbegin.o is recompiled with fpic, it could fix some of the errors.

And another surprise for me. Normally, fpic uses indirection through GOT, which is not important performance penalty here, but is still redundant. The linker however has an optimization that eliminates the indirection in an executable and actually replaces a mov opcode with a lea opcode. It is described in the AMD64 ABI draft that is linked in this LLVM ticket.
Post Reply