X86-64: Difference between revisions
Jump to navigation
Jump to search
[unchecked revision] | [unchecked revision] |
Content deleted Content added
mNo edit summary |
added "Linking a 64-bit ELF64 kernel against a 32-bit ELF32 bootstrap (for use with Multiboot)" section |
||
Line 64: | Line 64: | ||
This LP64 means Longs and Pointers are 64bits wide. LL is a special case and means long-long... |
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> |
|||