Strange code generation by x86_64-pc-linux-gnu-gcc

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
hendric

Strange code generation by x86_64-pc-linux-gnu-gcc

Post by hendric »

Hi all,I'm now busy implementing early_kprintf aimed to print strings into screen.For test I write a simple function as follow:

Code: Select all

int early_kprintf(char* fmt,char* fmt2,...)
{
???return 0;
}
After compiling by x86_64-pc-linux-gnu-gcc(with version 3.4.0), I tried to link all .o files.But "relocationg truncated to fit: .text 0x6fe+.text" error again happened.I ran objdump to dump the very .o file,I found it strange:

Code: Select all

00000000000006b0 <early_kprintf>:
 6b0:???55                   ???push   %rbp
 6b1:???48 89 e5             ???mov    %rsp,%rbp
 6b4:???48 81 ec d0 00 00 00 ???sub    $0xd0,%rsp
 6bb:???48 89 bd 48 ff ff ff ???mov    %rdi,0xffffffffffffff48(%rbp)
 6c2:???48 89 95 60 ff ff ff ???mov    %rdx,0xffffffffffffff60(%rbp)
 6c9:???48 89 8d 68 ff ff ff ???mov    %rcx,0xffffffffffffff68(%rbp)
 6d0:???4c 89 85 70 ff ff ff ???mov    %r8,0xffffffffffffff70(%rbp)
 6d7:???4c 89 8d 78 ff ff ff ???mov    %r9,0xffffffffffffff78(%rbp)
 6de:???0f b6 c0             ???movzbl %al,%eax
 6e1:???48 89 85 38 ff ff ff ???mov    %rax,0xffffffffffffff38(%rbp)
 6e8:???48 8b 95 38 ff ff ff ???mov    0xffffffffffffff38(%rbp),%rdx
 6ef:???48 8d 04 95 00 00 00 ???lea    0x0(,%rdx,4),%rax
 6f6:???00 
 6f7:???48 c7 85 38 ff ff ff ???movq   $0x0,0xffffffffffffff38(%rbp)
 6fe:???00 00 00 00 
 702:???48 29 85 38 ff ff ff ???sub    %rax,0xffffffffffffff38(%rbp)
 709:???48 8d 45 ff          ???lea    0xffffffffffffffff(%rbp),%rax
 70d:???48 8b 95 38 ff ff ff ???mov    0xffffffffffffff38(%rbp),%rdx
 714:???ff e2                ???jmpq   *%edx
 716:???0f 29 78 f1          ???movaps %xmm7,0xfffffffffffffff1(%rax)
 71a:???0f 29 70 e1          ???movaps %xmm6,0xffffffffffffffe1(%rax)
 71e:???0f 29 68 d1          ???movaps %xmm5,0xffffffffffffffd1(%rax)
 722:???0f 29 60 c1          ???movaps %xmm4,0xffffffffffffffc1(%rax)
 726:???0f 29 58 b1          ???movaps %xmm3,0xffffffffffffffb1(%rax)
 72a:???0f 29 50 a1          ???movaps %xmm2,0xffffffffffffffa1(%rax)
 72e:???0f 29 48 91          ???movaps %xmm1,0xffffffffffffff91(%rax)
 732:???0f 29 40 81          ???movaps %xmm0,0xffffffffffffff81(%rax)
 736:???48 89 b5 40 ff ff ff ???mov    %rsi,0xffffffffffffff40(%rbp)
 73d:???b8 00 00 00 00       ???mov    $0x0,%eax
 742:???c9                   ???leaveq 
 743:???c3                   ???retq  
I think it strange that why GCC refers to xmm registers.And I found no resolutions from GCC doc-book.Any help is appreciated.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Strange code generation by x86_64-pc-linux-gnu-gcc

Post by Pype.Clicker »

hendric wrote: 6b1: 48 89 e5 mov %rsp,%rbp
6b4: 48 81 ec d0 00 00 00 sub $0xd0,%rsp
6bb: 48 89 bd 48 ff ff ff mov %rdi,0xffffffffffffff48(%rbp)
6c2: 48 89 95 60 ff ff ff mov %rdx,0xffffffffffffff60(%rbp)
6c9: 48 89 8d 68 ff ff ff mov %rcx,0xffffffffffffff68(%rbp)
Do you see any reason why the compiler felt obliged to add prefixes (0x48 is a x86_64 prefix in the spirit of 0x66 and 0x67 on ia32, no?) everywhere ?
6ef: 48 8d 04 95 00 00 00 lea 0x0(,%rdx,4),%rax
6f6: 00
6f7: 48 c7 85 38 ff ff ff movq $0x0,0xffffffffffffff38(%rbp)
6fe: 00 00 00 00
that sounds highly suspicious to me, such as if the disassembler didn't get what was going on and has a trailing (and unused) nul byte.

... or have you observed that "objdump" likes to split disassembly over 2 lines when the individual bytes for one operation grows over N bytes ?
702: 48 29 85 38 ff ff ff sub %rax,0xffffffffffffff38(%rbp)
709: 48 8d 45 ff lea 0xffffffffffffffff(%rbp),%rax
70d: 48 8b 95 38 ff ff ff mov 0xffffffffffffff38(%rbp),%rdx
714: ff e2 jmpq *%edx
Hm, the "jmpq" is inconditionnal, i suppose, that means whatever comes after this is just padding... right ?

If you ask me, the whole thing looks terribly like a exception setup/resume code ...
durand
Member
Member
Posts: 193
Joined: Wed Dec 21, 2005 12:00 am
Location: South Africa
Contact:

Re:Strange code generation by x86_64-pc-linux-gnu-gcc

Post by durand »

Yeah, be careful of the output from objdump. I've had situations myself where the disassembled output is not correct. This is very obvious when disassembling real mode code. If you check the bug reports for that, you'll see a lot of them.

This is probably unrelated to your problem, just letting someone know.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Strange code generation by x86_64-pc-linux-gnu-gcc

Post by Pype.Clicker »

just a thought: what objdump do you use for that ? one you rebuilt yourself (when i'm toying with a cross-compiler, i usually have to use a cross-objdump aswell) or a native one for your platform ?

Maybe you want to compare that objdump with the output of "gcc <yourfile> -S" which only produce the assembly code and doesn't go further.
User avatar
Colonel Kernel
Member
Member
Posts: 1437
Joined: Tue Oct 17, 2006 6:06 pm
Location: Vancouver, BC, Canada
Contact:

Re:Strange code generation by x86_64-pc-linux-gnu-gcc

Post by Colonel Kernel »

I've had the same kind of problems, which is why I use ndisasm instead of objdump... Is there anything similar for x86-64?
Top three reasons why my OS project died:
  1. Too much overtime at work
  2. Got married
  3. My brain got stuck in an infinite loop while trying to design the memory manager
Don't let this happen to you!
hendric

Re:Strange code generation by x86_64-pc-linux-gnu-gcc

Post by hendric »

Pype.Clicker wrote:
hendric wrote: 6b1: 48 89 e5 mov %rsp,%rbp
6b4: 48 81 ec d0 00 00 00 sub $0xd0,%rsp
6bb: 48 89 bd 48 ff ff ff mov %rdi,0xffffffffffffff48(%rbp)
6c2: 48 89 95 60 ff ff ff mov %rdx,0xffffffffffffff60(%rbp)
6c9: 48 89 8d 68 ff ff ff mov %rcx,0xffffffffffffff68(%rbp)
Do you see any reason why the compiler felt obliged to add prefixes (0x48 is a x86_64 prefix in the spirit of 0x66 and 0x67 on ia32, no?) everywhere ?
Yea I found that gcc added REX prefix everywhere but the program worked very well.
6ef: 48 8d 04 95 00 00 00 lea 0x0(,%rdx,4),%rax
6f6: 00
6f7: 48 c7 85 38 ff ff ff movq $0x0,0xffffffffffffff38(%rbp)
6fe: 00 00 00 00
that sounds highly suspicious to me, such as if the disassembler didn't get what was going on and has a trailing (and unused) nul byte.

... or have you observed that "objdump" likes to split disassembly over 2 lines when the individual bytes for one operation grows over N bytes ?
Yea I observed the situation.But I do not know why objdump split the disassembly.
702: 48 29 85 38 ff ff ff sub %rax,0xffffffffffffff38(%rbp)
709: 48 8d 45 ff lea 0xffffffffffffffff(%rbp),%rax
70d: 48 8b 95 38 ff ff ff mov 0xffffffffffffff38(%rbp),%rdx
714: ff e2 jmpq *%edx
Hm, the "jmpq" is inconditionnal, i suppose, that means whatever comes after this is just padding... right ?

If you ask me, the whole thing looks terribly like a exception setup/resume code ...
I felt highly strange about the jmp instruction.The function early_kprintf is an empty function but I don't know why gcc generated so many code even though I enabled O3.Maybe you are right,the data after jmp instruction maybe padding data,there's no reason for gcc to refer to xmm registers!
hendric

Re:Strange code generation by x86_64-pc-linux-gnu-gcc

Post by hendric »

Colonel Kernel wrote: I've had the same kind of problems, which is why I use ndisasm instead of objdump... Is there anything similar for x86-64?
As far as I know,ndisasm can only disassemble i8086 disassembly but x86_64.
Maybe you want to compare that objdump with the output of "gcc <yourfile> -S" which only produce the assembly code and doesn't go further.
Yea I 've tried about it.The assembly generated by gcc is the same to objdump.But I still found no resolutions about the "relocation truncated to fit" error because I don't know what to relocate :(
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:Strange code generation by x86_64-pc-linux-gnu-gcc

Post by Candy »

Probably nothing, but did you use x86_64-pc-linux-ld or ld?
hendric

Re:Strange code generation by x86_64-pc-linux-gnu-gcc

Post by hendric »

Candy wrote: Probably nothing, but did you use x86_64-pc-linux-ld or ld?
I used x86_64-pc-linux-gnu-ld as my linker.
guest

Re:Strange code generation by x86_64-pc-linux-gnu-gcc

Post by guest »

Truncating relocations usually occurs when mixing different code types (eg. 16bit and 32bit). You may want to check all your GCC and LD commands, make sure they're all in -m64 mode. Be sure that any assembly is written in YASM "[BITS 64]" with the "-m amd64 -f elf64" commandline or AT&T (x86_64-pc-linux-gnu-as) ".code 64"

[If Pype.Clicker is right, you may also want to throw in "-fno-exceptions" on gcc and "-nostdlib -lgcc" on ld commandlines]
hendric

Re:Strange code generation by x86_64-pc-linux-gnu-gcc

Post by hendric »

guest wrote: Truncating relocations usually occurs when mixing different code types (eg. 16bit and 32bit). You may want to check all your GCC and LD commands, make sure they're all in -m64 mode. Be sure that any assembly is written in YASM "[BITS 64]" with the "-m amd64 -f elf64" commandline or AT&T (x86_64-pc-linux-gnu-as) ".code 64"

[If Pype.Clicker is right, you may also want to throw in "-fno-exceptions" on gcc and "-nostdlib -lgcc" on ld commandlines]
I've followed your suggestion but it was not effective. But I found gcc under x86_64 really has different behavior from normal gcc . Say, gcc under x86_64 uses 3 registers to pass parameter even thouth cdecl attribute is specified,at least for functions with ramdon parameters.
I feel disappointed at x86_64 gcc. I decide to implement early_kprintf directly via assembly :(
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:Strange code generation by x86_64-pc-linux-gnu-gcc

Post by Candy »

hendric wrote: I've followed your suggestion but it was not effective. But I found gcc under x86_64 really has different behavior from normal gcc . Say, gcc under x86_64 uses 3 registers to pass parameter even thouth cdecl attribute is specified,at least for functions with ramdon parameters.
I feel disappointed at x86_64 gcc. I decide to implement early_kprintf directly via assembly :(
Try reading the 64-bit ABI, which specifies exactly what you noticed. It's nearly identical to the IA64 ABI, which you can find easily on google.
Post Reply