Page 1 of 1
Error ld: cannot represent machine `elf32-i386'
Posted: Sun Aug 23, 2009 7:38 am
by zman97211
I have been playing around with entering protected mode from a simple custom kernel. I'm trying to create a 32-bit binary elf file as output which will be loaded and started by GRUB. The machine I'm running on is an Ubuntu installation on an AMD 64-bit processor. I have succesfully build this and booted it using NASM and DJGPP on Windows, before deciding to use Linux as by build environment. I have searched but can't find any help on this error message.
My source is a very short assembly file, compiled with NASM into "kernel.o".
"objdump -i" lists "elf32-i386" as one of the supported formats.
"objdump -x kernel.o" tells me that kernel.o's format is indeed elf32-i386.
I am invoking "ld -T link.ld".
It outputs
Code: Select all
ld: cannot represent machine `elf32-i386'
Here is the linker script I am using (I've played around with the format and arch lines with no success):
Code: Select all
OUTPUT_FORMAT(elf32-i386)
OUTPUT_ARCH(elf32-i386)
TARGET(elf32-i386)
INPUT(kernel.o)
OUTPUT(kernel.bin)
ENTRY(start)
phys = 0x00100000;
SECTIONS
{
.text phys : AT(phys) {
code = .;
*(.text)
*(.rodata)
. = ALIGN(4096);
}
.data : AT(phys + (data - code))
{
data = .;
*(.data)
. = ALIGN(4096);
}
.bss : AT(phys + (bss - code))
{
bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .;
}
I have successfully build other packages from source so I believe my build environment, binutils, etc should be functional.
Thanks in advance for the help! Below is the source for kernel.o in case it's important (I don't think it is).
Code: Select all
[BITS 32]
global start
start:
mov esp,_sys_stack
jmp stublet
ALIGN 4
mboot:
MULTIBOOT_PAGE_ALIGN equ 1<<0
MULTIBOOT_MEMORY_INFO equ 1<<1
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO
MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
stublet:
mov ebx,0xb8002
mov [ebx],byte 0x0f
mov [ebx+1],byte '*'
jmp $
SECTION .bss
resb 8192 ; This reserves 8KBytes of memory here
_sys_stack:
Re: Error ld: cannot represent machine `elf32-i386'
Posted: Sun Aug 23, 2009 8:42 am
by NickJohnson
In my linker script, I have the line "OUTPUT_FORMAT(elf32-i386)" instead of "OUTPUT_ARCH(elf32-i386)". Maybe that's your issue?
Either way, you should really build a cross compiler (which includes the linker) if you're going to be writing for a different architecture than the one you're using. Take a look
here.
Re: Error ld: cannot represent machine `elf32-i386'
Posted: Sun Aug 23, 2009 1:30 pm
by zman97211
I removed the OUTPUT_ARCH line and left in the OUTPUT_FORMAT line with no improvement.
I'm currently building the cross-compiler using the link you provided and I'll post the results when I have them.
Thanks!
Re: Error ld: cannot represent machine `elf32-i386'
Posted: Sun Aug 23, 2009 1:53 pm
by dc740
Try this:
OUTPUT_ARCH(i386)
I tested it with the James's tutorial and seems to be working... I didn't do it in C. I followed the tutorial doing everything in asm... but it should work anyway
good luck!
Re: Error ld: cannot represent machine `elf32-i386'
Posted: Sun Aug 23, 2009 4:06 pm
by zman97211
Ok. I made the cross-compiling binutils and gcc, but still no luck, same error.
I then changed the OUTPUT_ARCH(i386) as mentioned in the latest post, and got a successful link using my host system's linker! However, I received a warning from ld:
Code: Select all
ld: warning: cannot find entry symbol start; defaulting to 0000000000100000
The start symbol is global in my source and listed in my linker script as the entry point ENTRY(start), and listed with objdump -x kernel.o:
Code: Select all
kernel.o: file format elf32-i386
kernel.o
architecture: i386, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x00000000
Sections:
Idx Name Size VMA LMA File off Algn
0 .bss 00002000 00000000 00000000 00000160 2**2
ALLOC
1 .text 0000001d 00000000 00000000 00000160 2**4
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
SYMBOL TABLE:
00000000 l df *ABS* 00000000 kernel.asm
00000000 l d .bss 00000000 .bss
00000000 l d .text 00000000 .text
00000000 l *UND* 00000000 mboot
00000001 l *ABS* 00000000 MULTIBOOT_PAGE_ALIGN
00000002 l *ABS* 00000000 MULTIBOOT_MEMORY_INFO
1badb002 l *ABS* 00000000 MULTIBOOT_HEADER_MAGIC
00000003 l *ABS* 00000000 MULTIBOOT_HEADER_FLAGS
e4524ffb l *ABS* 00000000 MULTIBOOT_CHECKSUM
00000000 l *UND* 00000000 stublet
00002000 l .bss 00000000 _sys_stack
00000000 *UND* 00000000 code
00000000 *UND* 00000000 bss
00000000 *UND* 00000000 end
00000000 *UND* 00000000 start
RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
00000001 R_386_32 .bss
Also, my multiboot header does not work without the aout kludge, I just figured that out. I thought that by using an elf binary, which Grub should understand, the kludge wasn't required. I put it back in and was able to run my code with Bochs.
Back to the ld documentation....
Re: Error ld: cannot represent machine `elf32-i386'
Posted: Mon Aug 24, 2009 7:14 am
by NickJohnson
zman97211 wrote:Also, my multiboot header does not work without the aout kludge, I just figured that out. I thought that by using an elf binary, which Grub should understand, the kludge wasn't required. I put it back in and was able to run my code with Bochs.
I believe the header still has to be at the beginning of the binary, after the ELF header. In your layout, .bss is before .text, and therefore the header is in the middle of the binary. Try switching .text's and .bss's order in the linker script.
Re: Error ld: cannot represent machine `elf32-i386'
Posted: Mon Aug 24, 2009 7:52 am
by dc740
I think Nick is right. Here is a piece of my start.asm file
Code: Select all
; This is the kernel's entry point. We could either call main here,
; or we can use this to setup the stack or other nice stuff, like
; perhaps setting up the GDT and segments. Please note that interrupts
; are disabled at this point: More on interrupts later!
[BITS 32]
SECTION .data
; This part MUST be 4byte aligned, so we solve that issue using 'ALIGN 4'
ALIGN 4
mboot:
; Multiboot macros to make a few lines later more readable
MULTIBOOT_PAGE_ALIGN equ 1<<0
MULTIBOOT_MEMORY_INFO equ 1<<1
MULTIBOOT_AOUT_KLUDGE equ 1<<16
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_AOUT_KLUDGE
MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
EXTERN code, bss, end
; This is the GRUB Multiboot header. A boot signature
dd MULTIBOOT_HEADER_MAGIC
dd MULTIBOOT_HEADER_FLAGS
dd MULTIBOOT_CHECKSUM
; AOUT kludge - must be physical addresses. Make a note of these:
; The linker script fills in the data for these ones!
dd mboot
dd code
dd bss
dd end
dd start
section .text
global start
start:
;put your code here!!! :)
PS:I'm sure it looks familiar. I guess most of us start learning from tutorials before reading 98234798 articles and books about this beautiful art
Re: Error ld: cannot represent machine `elf32-i386'
Posted: Mon Aug 24, 2009 9:33 am
by zman97211
I appreciate all the help you guys have given me. I've now been able to set up a GDT using a segmented model and done a few basic tasks, but it has uncovered another issue I'm having now, which I'll describe in a new thread.
Steve