X86-64: Difference between revisions

Jump to navigation Jump to search
2,773 bytes added ,  13 years ago
added "Linking a 64-bit ELF64 kernel against a 32-bit ELF32 bootstrap (for use with Multiboot)" section
[unchecked revision][unchecked revision]
mNo edit summary
(added "Linking a 64-bit ELF64 kernel against a 32-bit ELF32 bootstrap (for use with Multiboot)" section)
Line 64:
 
This LP64 means Longs and Pointers are 64bits wide. LL is a special case and means long-long...
 
== Linking a 64-bit ELF64 kernel against a 32-bit ELF32 bootstrap (for use with Multiboot) ==
 
<source lang="bash">
 
# I assume that you've already compiled and linked your 64-bit kernel
 
 
# your 64-bit kernel
kernel64="build/kernel64.bin"
 
# its base address -- make sure it doesn't overlap with the kernel32 sections!
kernel64_baseaddress="0x00140000"
 
# the symbols from it you want available in your 32-bit loader
kernel64export32_symbols="k_GDT k_GDTptr k_PML4 k_PML3 k_PML2 k_PML1_first8M kinit64 k_multibootdata k64_sbss k64_ebss k_pages k_npages"
 
 
kernel64export32_ldscript=`mktemp`
kernel64_section=`mktemp`
 
 
# generate .kernel64 section's data
readelf -SW "$kernel64" | python -c "`cat <<EOF
import re, sys
regex=r"\[\s*\d+\]\s*(?!NULL)(\S+)\s+(PROGBITS|NOBITS)\s+([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s+([0-9a-fA-F]+)"
baseaddress=$kernel64_baseaddress
k64f = open("$kernel64", "r")
f = open("$kernel64_section", "w")
for line in sys.stdin:
r = re.search(regex, line)
if not r:
continue
section, stype, LMA, offset, size = r.groups()
LMA, offset, size = map(lambda s: int(s, 16), (LMA, offset, size))
if LMA < baseaddress:
raise ValueError("section ('%s' offset=0x%08x size=0x%08x ) at address < 0x%x" % (section, offset, size, baseaddress))
k64f.seek(offset)
if stype == "PROGBITS":
f.seek(LMA-baseaddress)
f.write(k64f.read(size))
f.close()
EOF`" || fail
 
# export wanted symbols from kernel64
readelf -sW "$kernel64" | python -c "`cat <<EOF
import re, sys
regex=r"\s*\:\s+([0-9a-fA-F]+)\s+\d+\s+\S+\s+\S+\s+\S+\s+\S+\s+(\S+)"
syms=filter(len,"$kernel64export32_symbols".split(" "))
f = open("$kernel64export32_ldscript", "w")
for line in sys.stdin:
r = re.search(regex, line)
if not r:
continue
val, sym = r.groups()
if not sym in syms:
continue
val = int(val, 16)
if val > 0xffffffff:
raise ValueError("symbol value must be below 0xffffffff limit")
f.write('"%s" = %s;\n' % (sym, hex(val)))
f.close()
EOF`" || fail
 
 
# now we have to build the 32-bit loader
 
# your actual lines may vary, change to your needs
gcc -m32 -Wall -Wextra -nostdlib -nostartfiles -nodefaultlibs -Isrc -O5 -fno-strict-aliasing -c \
src/start64/start64.c -o build/start64/start64.o
nasm -f elf32 \
src/start64/loader32.asm -o build/start64/loader32.o
 
# add the contents of $kernel64_section as a section in one of the 32-bit object files
objcopy --add-section .kernel64="$kernel64_section" \
--set-section-flag .kernel64=alloc,data,load,contents \
build/start64/loader32.o || fail
 
# link the previous two files, taking care to include (-T) the autogenerated syms file
ld -melf_i386 -T src/start64/linker.ld -T "$kernel64export32_ldscript" -o kernel.bin \
build/start64/start64.o build/start64/loader32.o || fail
 
</source>
 
 
Anonymous user
Cookies help us deliver our services. By using our services, you agree to our use of cookies.

Navigation menu