OSDev.org

The Place to Start for Operating System Developers
It is currently Tue Apr 16, 2024 6:14 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 10 posts ] 
Author Message
 Post subject: Kernel in ELF Format - Potential Linker Issue?
PostPosted: Thu Jan 07, 2016 6:21 pm 
Offline

Joined: Wed Jan 06, 2016 7:44 pm
Posts: 5
Just to see if it is possible, I decided to try to build the Bare Bones kernel using only tools from the LLVM project (i.e., clang instead of gcc and lld instead of ld). After much battling with the toolchain, I was able to link a kernel binary together, package an iso with GRUB, and attempted to execute it in virtualbox. This resulted in
Code:
Error 7: Loading below 1MB is not supported


After getting more information about the binary via readelf and objdump, I believe what I'm seeing is a bug in the lld linker, but I am trying to make sure I fully understand exactly what went wrong.

I found two things of note from readelf, the first is the program header table:
Code:
Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  INTERP         0x0008e5 0x000008e5 0x000008e5 0x0001c 0x0001c R   0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x000000 0x00000000 0x00000000 0x00b50 0x00b50 R E 0x1000
  LOAD           0x001000 0x00001000 0x00001000 0x00000 0x14010 RW  0x1000
  DYNAMIC        0x000b20 0x00000b20 0x00000b20 0x00030 0x00030 R   0x4

From what I understand, it looks like the executable section is set up to load at 0x00000000 which is what is causing the Error 7 mentioned above (if my understanding is correct).

Second, the .symtab appears to be corrupted:
Code:
Symbol table '.symtab' contains 1 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00010101     0 NOTYPE  LOCAL  DEFAULT  UND <corrupt>

and the symbols that I would have expected to be there appear in a separate symbol table called .hash:
Code:
Symbol table '.hash' contains 66 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 00000930     0 OBJECT  LOCAL  DEFAULT   11 .LCPI4_0
     2: 00000940    16 OBJECT  LOCAL  DEFAULT   11 .LCPI4_1
     3: 00000950    16 OBJECT  LOCAL  DEFAULT   11 .LCPI4_2
     4: 00000960    16 OBJECT  LOCAL  DEFAULT   11 .LCPI4_3
     5: 00000970    16 OBJECT  LOCAL  DEFAULT   11 .LCPI4_4
     6: 00000980    16 OBJECT  LOCAL  DEFAULT   11 .LCPI4_5
     7: 00000990    16 OBJECT  LOCAL  DEFAULT   11 .LCPI4_6
     8: 000009a0    16 OBJECT  LOCAL  DEFAULT   11 .LCPI4_7
     9: 000009b0    16 OBJECT  LOCAL  DEFAULT   11 .LCPI4_8
    10: 000009c0    16 OBJECT  LOCAL  DEFAULT   11 .LCPI4_9
    11: 000009d0    16 OBJECT  LOCAL  DEFAULT   11 .LCPI6_0
    12: 000009e0    16 OBJECT  LOCAL  DEFAULT   11 .LCPI6_1
    13: 000009f0    16 OBJECT  LOCAL  DEFAULT   11 .LCPI6_2
    14: 00000a00    16 OBJECT  LOCAL  DEFAULT   11 .LCPI6_3
    15: 00000a10    16 OBJECT  LOCAL  DEFAULT   11 .LCPI6_4
    16: 00000a20    16 OBJECT  LOCAL  DEFAULT   11 .LCPI6_5
    17: 00000a30    16 OBJECT  LOCAL  DEFAULT   11 .LCPI6_6
    18: 00000a40    16 OBJECT  LOCAL  DEFAULT   11 .LCPI6_7
    19: 00000a50    16 OBJECT  LOCAL  DEFAULT   11 .LCPI6_8
    20: 00000a60    16 OBJECT  LOCAL  DEFAULT   11 .LCPI6_9
    21: 00000a70    16 OBJECT  LOCAL  DEFAULT   11 .LCPI7_0
    22: 00000a80    16 OBJECT  LOCAL  DEFAULT   11 .LCPI7_1
    23: 00000a90    16 OBJECT  LOCAL  DEFAULT   11 .LCPI7_2
    24: 00000aa0    16 OBJECT  LOCAL  DEFAULT   11 .LCPI7_3
    25: 00000ab0    16 OBJECT  LOCAL  DEFAULT   11 .LCPI7_4
    26: 00000ac0    16 OBJECT  LOCAL  DEFAULT   11 .LCPI7_5
    27: 00000ad0    16 OBJECT  LOCAL  DEFAULT   11 .LCPI7_6
    28: 00000ae0    16 OBJECT  LOCAL  DEFAULT   11 .LCPI7_7
    29: 00000af0    16 OBJECT  LOCAL  DEFAULT   11 .LCPI7_8
    30: 00000b00    16 OBJECT  LOCAL  DEFAULT   11 .LCPI7_9
    31: 00000b10     0 OBJECT  LOCAL  DEFAULT   11 .L.str
    32: 00001000     0 OBJECT  LOCAL  DEFAULT   14 stack_bottom
    33: 00005000 65536 OBJECT  LOCAL  DEFAULT   14 stack_top
    34: 00000000     0 OBJECT  LOCAL  HIDDEN   ABS __preinit_array_start
    35: 00000000     0 OBJECT  LOCAL  HIDDEN   ABS __preinit_array_end
    36: 00000000     0 OBJECT  LOCAL  HIDDEN   ABS __init_array_start
    37: 00000000     0 OBJECT  LOCAL  HIDDEN   ABS __init_array_end
    38: 00000000     0 OBJECT  LOCAL  HIDDEN   ABS __fini_array_start
    39: 00000000     0 OBJECT  LOCAL  HIDDEN   ABS __fini_array_end
    40: 00000001     0 OBJECT  LOCAL  DEFAULT  ABS ALIGN
    41: e4524ffb     0 OBJECT  LOCAL  DEFAULT  ABS CHECKSUM
    42: 00000003     0 OBJECT  LOCAL  DEFAULT  ABS FLAGS
    43: 1badb002     0 OBJECT  LOCAL  DEFAULT  ABS MAGIC
    44: 00000002     0 OBJECT  LOCAL  DEFAULT  ABS MEMINFO
    45: 00000000     0 OBJECT  LOCAL  DEFAULT  ABS kernel.c
    46: 000000c0    14 FUNC    GLOBAL DEFAULT    1 _start
    47: 000000d0    32 FUNC    GLOBAL DEFAULT    1 make_color
    48: 000000f0    32 FUNC    GLOBAL DEFAULT    1 make_vgaentry
    49: 00000110    32 FUNC    GLOBAL DEFAULT    1 strlen
    50: 00000130   128 FUNC    GLOBAL DEFAULT    1 terminal_initialize
    51: 000001b0   464 FUNC    GLOBAL DEFAULT    1 move_buffer_up
    52: 00000380    48 FUNC    GLOBAL DEFAULT    1 terminal_write_char_at
    53: 000003b0   560 FUNC    GLOBAL DEFAULT    1 terminal_write_char
    54: 000005e0   640 FUNC    GLOBAL DEFAULT    1 terminal_write_str
    55: 00000860   133 FUNC    GLOBAL DEFAULT    1 kernel_main
    56: 00015000     4 OBJECT  GLOBAL DEFAULT   14 terminal_buffer
    57: 00015004     1 OBJECT  GLOBAL DEFAULT   14 terminal_color
    58: 00015008     4 OBJECT  GLOBAL DEFAULT   14 terminal_column
    59: 0001500c     4 OBJECT  GLOBAL DEFAULT   14 terminal_row
    60: 00001000     0 OBJECT  GLOBAL DEFAULT  ABS __bss_start
    61: 00015010     0 OBJECT  GLOBAL DEFAULT  ABS __bss_end
    62: 00015010     0 OBJECT  GLOBAL DEFAULT  ABS _end
    63: 00015010     0 OBJECT  GLOBAL DEFAULT  ABS end
    64: 00000000     0 OBJECT  GLOBAL DEFAULT  ABS __rela_iplt_start
    65: 00000000     0 OBJECT  GLOBAL DEFAULT  ABS __rela_iplt_end


Trying to run the binary through objdump simply exits with the error
Code:
objdump: durian.bin: Bad value


Is my understanding correct that the lld linker has not linked this binary together into a well-formed ELF executable?

(P.S. I know that I can just build a usable gcc cross-compiler to get this up and working. I'm ultimately less interested in getting this to boot than am I understanding what went wrong in the compilation/linking process.)


Top
 Profile  
 
 Post subject: Re: Kernel in ELF Format - Potential Linker Issue?
PostPosted: Thu Jan 07, 2016 8:10 pm 
Offline
Member
Member

Joined: Mon Feb 02, 2015 7:11 pm
Posts: 898
shickey wrote:
Code:
Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  INTERP         0x0008e5 0x000008e5 0x000008e5 0x0001c 0x0001c R   0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]



That is a problem. Your ELF is targeted at 64 bits Linux. You want to build a free-standing 32 bits ELF binary.

_________________
https://github.com/kiznit/rainbow-os


Top
 Profile  
 
 Post subject: Re: Kernel in ELF Format - Potential Linker Issue?
PostPosted: Thu Jan 07, 2016 8:20 pm 
Offline

Joined: Wed Jan 06, 2016 7:44 pm
Posts: 5
Oh, good eye. This seems odd, though, since the ELF header shows that it's targeting a 32-bit Intel 80386 architecture. Here's the readelf output:
Code:
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0xc0
  Start of program headers:          52 (bytes into file)
  Start of section headers:          9392 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         4
  Size of section headers:           40 (bytes)
  Number of section headers:         15
  Section header string table index: 4


Top
 Profile  
 
 Post subject: Re: Kernel in ELF Format - Potential Linker Issue?
PostPosted: Thu Jan 07, 2016 8:35 pm 
Offline

Joined: Wed Jan 06, 2016 7:44 pm
Posts: 5
Ah, okay! I think I solved that problem for the moment. Here are readelf program headers now:
Code:
Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x00000000 0x00000000 0x004aa 0x004aa R E 0x1000
  LOAD           0x001000 0x00001000 0x00001000 0x00000 0x04010 RW  0x1000


Still, same `Error 7: Loading below 1MB is not supported` when I attempt to run it.


Top
 Profile  
 
 Post subject: Re: Kernel in ELF Format - Potential Linker Issue?
PostPosted: Thu Jan 07, 2016 8:38 pm 
Offline
Member
Member

Joined: Mon Feb 02, 2015 7:11 pm
Posts: 898
Then link your ELF above 1M. =) It's at 0x00000000 right now...

_________________
https://github.com/kiznit/rainbow-os


Top
 Profile  
 
 Post subject: Re: Kernel in ELF Format - Potential Linker Issue?
PostPosted: Thu Jan 07, 2016 9:03 pm 
Offline

Joined: Wed Jan 06, 2016 7:44 pm
Posts: 5
Ha. Yup. I did just that now before I saw your message and I think I'm making progress finally. I thought I had set the offset correctly in my linker script:
Code:
ENTRY(_start)
SECTIONS
{
 
  . = 1M;
 
  .text BLOCK(4K) : ALIGN(4K)
  {
    *(.multiboot)
    *(.text)
  }
 
  .rodata BLOCK(4K) : ALIGN(4K)
  {
    *(.rodata)
  }
 
  .data BLOCK(4K) : ALIGN(4K)
  {
    *(.data)
  }
 
  .bss BLOCK(4K) : ALIGN(4K)
  {
    *(COMMON)
    *(.bss)
    *(.bootstrap_stack)
  }
 
}


But I was able to get it to work by passing --image-base 0x100000 directly to lld on the command line. Now I'm getting a triple-fault when I boot:
Code:
[Multiboot-elf, <0x100000:0x1000:0x4010>, shtab=0x106190(bad), entry=0x1000600])

But hey, progress!


Top
 Profile  
 
 Post subject: Re: Kernel in ELF Format - Potential Linker Issue?
PostPosted: Fri Jan 08, 2016 1:15 am 
Offline
Member
Member

Joined: Wed Sep 19, 2012 3:43 am
Posts: 91
Location: The Netherlands
It could be me misunderstanding things but I think you should specify the base address as a hex value in your linker script:
Code:
ENTRY(_start)
SECTIONS
{
 
  . = 0x100000;
 
  .text BLOCK(4K) : ALIGN(4K)
  {
........


Top
 Profile  
 
 Post subject: Re: Kernel in ELF Format - Potential Linker Issue?
PostPosted: Fri Jan 08, 2016 1:21 am 
Offline
Member
Member

Joined: Mon Feb 02, 2015 7:11 pm
Posts: 898
No, the following is perfectly valid:

Code:
    . = 1M;

_________________
https://github.com/kiznit/rainbow-os


Top
 Profile  
 
 Post subject: Re: Kernel in ELF Format - Potential Linker Issue?
PostPosted: Fri Jan 08, 2016 8:25 am 
Offline
Member
Member
User avatar

Joined: Thu Mar 27, 2014 3:57 am
Posts: 568
Location: Moscow, Russia
Make sure you use "clang --target=i686-pc-none-elf". Personally, I use a GNU binutils + clang setup.

_________________
"If you don't fail at least 90 percent of the time, you're not aiming high enough."
- Alan Kay


Top
 Profile  
 
 Post subject: Re: Kernel in ELF Format - Potential Linker Issue?
PostPosted: Fri Jan 08, 2016 6:11 pm 
Offline

Joined: Wed Jan 06, 2016 7:44 pm
Posts: 5
Thanks, all. Roman, yeah, I've been using that target triple which looks like it's creating the right object files. At this point, I'm thinking that the major thing going on here is that lld has poor support for all but the simplest linker scripts. I've removed the
Code:
. = 1M;

entirely and am instead passing the --image-base flag on the command line which seems to be doing the trick much better. Interestingly, removing the *(.multiboot) declaration from the .text section seems to have fixed the corrupt .symtab issue and I'm no longer getting the `(bad)` indicator about .shtab upon booting (though, the kernel is still crashing immediately). Looks like objdump is also finally able to read the binary. Getting closer...


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 10 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], Majestic-12 [Bot] and 1028 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group