Support x86_64 in the runtime loader.
* Added x86_64 linker script and relocation code. * Some 64-bit safety fixes to the heap code. * Added runtime_loader, libroot and bash to the x86_64 image. The boot script will be launched, but will panic shortly after because fork is broken.
This commit is contained in:
parent
bd8b78e6ee
commit
12b3e8a8a0
@ -19,7 +19,7 @@ if $(HAIKU_ATA_STACK) = 1 {
|
||||
IDE_ONLY = "" ;
|
||||
}
|
||||
|
||||
SYSTEM_BIN = ;
|
||||
SYSTEM_BIN = bash ;
|
||||
|
||||
SYSTEM_APPS = ;
|
||||
|
||||
@ -27,7 +27,7 @@ SYSTEM_PREFERENCES = ;
|
||||
|
||||
SYSTEM_DEMOS = ;
|
||||
|
||||
SYSTEM_LIBS = ;
|
||||
SYSTEM_LIBS = libroot.so ;
|
||||
|
||||
PRIVATE_SYSTEM_LIBS = ;
|
||||
|
||||
@ -74,13 +74,13 @@ AddLibrariesToHaikuHybridImage system lib
|
||||
AddFilesToHaikuImage system servers : $(SYSTEM_SERVERS) ;
|
||||
|
||||
# apps
|
||||
#AddFilesToHaikuImage system : runtime_loader ;
|
||||
AddFilesToHaikuImage system : runtime_loader ;
|
||||
AddFilesToHaikuImage system bin : $(SYSTEM_BIN) ;
|
||||
AddFilesToHaikuImage system apps : $(SYSTEM_APPS) ;
|
||||
AddFilesToHaikuImage system preferences : $(SYSTEM_PREFERENCES) ;
|
||||
AddFilesToHaikuImage system demos : $(SYSTEM_DEMOS) ;
|
||||
|
||||
#AddSymlinkToHaikuImage system bin : bash : sh ;
|
||||
AddSymlinkToHaikuImage system bin : bash : sh ;
|
||||
#AddSymlinkToHaikuImage system bin : less : more ;
|
||||
#AddSymlinkToHaikuImage system bin : gzip : gunzip ;
|
||||
#AddSymlinkToHaikuImage system bin : gzip : zcat ;
|
||||
|
53
src/system/ldscripts/x86_64/runtime_loader.ld
Normal file
53
src/system/ldscripts/x86_64/runtime_loader.ld
Normal file
@ -0,0 +1,53 @@
|
||||
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
|
||||
OUTPUT_ARCH(i386:x86-64)
|
||||
|
||||
ENTRY(runtime_loader)
|
||||
SEARCH_DIR("libgcc");
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x00200000 + SIZEOF_HEADERS;
|
||||
|
||||
.interp : { *(.interp) }
|
||||
.hash : { *(.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
|
||||
.rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
|
||||
.rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rela.init : { *(.rela.init) }
|
||||
.rela.fini : { *(.rela.fini) }
|
||||
.rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
|
||||
.rela.plt : { *(.rela.plt) }
|
||||
.init : { *(.init) } =0x90909090
|
||||
.plt : { *(.plt) }
|
||||
|
||||
/* text/read-only data */
|
||||
.text : { *(.text .text.* .gnu.linkonce.t.*) } =0x90909090
|
||||
|
||||
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
||||
|
||||
/* writable data */
|
||||
. = ALIGN (CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1));
|
||||
__data_start = .;
|
||||
PROVIDE(_data_start = .);
|
||||
.data : { *(.data .gnu.linkonce.d.*) }
|
||||
|
||||
__ctor_list = .;
|
||||
PROVIDE (_ctor_list = .);
|
||||
.ctors : { *(.ctors) }
|
||||
PROVIDE (__ctor_end = .);
|
||||
|
||||
|
||||
/* uninitialized data (in same segment as writable data) */
|
||||
PROVIDE (__bss_start = .);
|
||||
.bss : { *(.bss) }
|
||||
|
||||
. = ALIGN(0x1000);
|
||||
PROVIDE (_end = .);
|
||||
|
||||
/* Strip unnecessary stuff */
|
||||
/DISCARD/ : { *(.comment .note .eh_frame .dtors) }
|
||||
}
|
14
src/system/runtime_loader/arch/x86_64/Jamfile
Normal file
14
src/system/runtime_loader/arch/x86_64/Jamfile
Normal file
@ -0,0 +1,14 @@
|
||||
SubDir HAIKU_TOP src system runtime_loader arch x86_64 ;
|
||||
|
||||
UsePrivateHeaders runtime_loader ;
|
||||
UsePrivateSystemHeaders ;
|
||||
|
||||
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ;
|
||||
|
||||
StaticLibrary libruntime_loader_$(TARGET_ARCH).a :
|
||||
arch_relocate.cpp
|
||||
:
|
||||
<src!system!libroot!os!arch!$(TARGET_ARCH)>atomic.o
|
||||
<src!system!libroot!os!arch!$(TARGET_ARCH)>thread.o
|
||||
<src!system!libroot!posix!string!arch!$(TARGET_ARCH)>arch_string.o
|
||||
;
|
96
src/system/runtime_loader/arch/x86_64/arch_relocate.cpp
Normal file
96
src/system/runtime_loader/arch/x86_64/arch_relocate.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "runtime_loader_private.h"
|
||||
|
||||
#include <runtime_loader.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
static status_t
|
||||
relocate_rela(image_t* rootImage, image_t* image, Elf64_Rela* rel,
|
||||
size_t relLength, SymbolLookupCache* cache)
|
||||
{
|
||||
for (size_t i = 0; i < relLength / sizeof(Elf64_Rela); i++) {
|
||||
int type = ELF64_R_TYPE(rel[i].r_info);
|
||||
int symIndex = ELF64_R_SYM(rel[i].r_info);
|
||||
Elf64_Addr symAddr = 0;
|
||||
|
||||
// Resolve the symbol, if any.
|
||||
if (symIndex != 0) {
|
||||
Elf64_Sym* sym = SYMBOL(image, symIndex);
|
||||
|
||||
status_t status = resolve_symbol(rootImage, image, sym, cache,
|
||||
&symAddr);
|
||||
if (status != B_OK) {
|
||||
TRACE(("resolve symbol \"%s\" returned: %" B_PRId32 "\n",
|
||||
SYMNAME(image, sym), status));
|
||||
printf("resolve symbol \"%s\" returned: %" B_PRId32 "\n",
|
||||
SYMNAME(image, sym), status);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
// Address of the relocation.
|
||||
Elf64_Addr relocAddr = image->regions[0].delta + rel[i].r_offset;
|
||||
|
||||
// Calculate the relocation value.
|
||||
Elf64_Addr relocValue;
|
||||
switch(type) {
|
||||
case R_X86_64_NONE:
|
||||
continue;
|
||||
case R_X86_64_64:
|
||||
case R_X86_64_GLOB_DAT:
|
||||
case R_X86_64_JUMP_SLOT:
|
||||
relocValue = symAddr + rel[i].r_addend;
|
||||
break;
|
||||
case R_X86_64_PC32:
|
||||
relocValue = symAddr + rel[i].r_addend - rel[i].r_offset;
|
||||
break;
|
||||
case R_X86_64_RELATIVE:
|
||||
relocValue = image->regions[0].delta + rel[i].r_addend;
|
||||
break;
|
||||
default:
|
||||
TRACE(("unhandled relocation type %d\n", type));
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
|
||||
*(Elf64_Addr *)relocAddr = relocValue;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
arch_relocate_image(image_t* rootImage, image_t* image,
|
||||
SymbolLookupCache* cache)
|
||||
{
|
||||
status_t status;
|
||||
|
||||
// No REL on x86_64.
|
||||
|
||||
// Perform RELA relocations.
|
||||
if (image->rela) {
|
||||
status = relocate_rela(rootImage, image, image->rela, image->rela_len,
|
||||
cache);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
}
|
||||
|
||||
// PLT relocations (they are RELA on x86_64).
|
||||
if (image->pltrel) {
|
||||
status = relocate_rela(rootImage, image, (Elf64_Rela*)image->pltrel,
|
||||
image->pltrel_len, cache);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
@ -35,11 +35,11 @@ static const size_t kInitialHeapSize = 65536;
|
||||
|
||||
|
||||
struct free_chunk {
|
||||
uint32 size;
|
||||
size_t size;
|
||||
free_chunk *next;
|
||||
|
||||
uint32 Size() const;
|
||||
free_chunk *Split(uint32 splitSize);
|
||||
size_t Size() const;
|
||||
free_chunk *Split(size_t splitSize);
|
||||
bool IsTouching(free_chunk *link);
|
||||
free_chunk *Join(free_chunk *link);
|
||||
void Remove(free_chunk *previous = NULL);
|
||||
@ -50,7 +50,7 @@ struct free_chunk {
|
||||
};
|
||||
|
||||
|
||||
static uint32 sAvailable;
|
||||
static size_t sAvailable;
|
||||
static free_chunk sFreeAnchor;
|
||||
|
||||
|
||||
@ -58,10 +58,10 @@ static free_chunk sFreeAnchor;
|
||||
* in this chunk.
|
||||
*/
|
||||
|
||||
uint32
|
||||
size_t
|
||||
free_chunk::Size() const
|
||||
{
|
||||
return size - sizeof(uint32);
|
||||
return size - sizeof(size_t);
|
||||
}
|
||||
|
||||
|
||||
@ -70,13 +70,13 @@ free_chunk::Size() const
|
||||
*/
|
||||
|
||||
free_chunk *
|
||||
free_chunk::Split(uint32 splitSize)
|
||||
free_chunk::Split(size_t splitSize)
|
||||
{
|
||||
free_chunk *chunk = (free_chunk *)((uint8 *)this + sizeof(uint32) + splitSize);
|
||||
chunk->size = size - splitSize - sizeof(uint32);
|
||||
free_chunk *chunk = (free_chunk *)((uint8 *)this + sizeof(size_t) + splitSize);
|
||||
chunk->size = size - splitSize - sizeof(size_t);
|
||||
chunk->next = next;
|
||||
|
||||
size = splitSize + sizeof(uint32);
|
||||
size = splitSize + sizeof(size_t);
|
||||
|
||||
return chunk;
|
||||
}
|
||||
@ -167,7 +167,7 @@ free_chunk::AllocatedAddress() const
|
||||
free_chunk *
|
||||
free_chunk::SetToAllocated(void *allocated)
|
||||
{
|
||||
return (free_chunk *)((uint8 *)allocated - sizeof(uint32));
|
||||
return (free_chunk *)((uint8 *)allocated - sizeof(size_t));
|
||||
}
|
||||
|
||||
|
||||
@ -183,7 +183,7 @@ add_area(size_t size)
|
||||
if (area < B_OK)
|
||||
return area;
|
||||
|
||||
sAvailable += size - sizeof(uint32);
|
||||
sAvailable += size - sizeof(size_t);
|
||||
|
||||
// declare the whole heap as one chunk, and add it
|
||||
// to the free list
|
||||
@ -198,7 +198,7 @@ add_area(size_t size)
|
||||
|
||||
|
||||
static status_t
|
||||
grow_heap(uint32 bytes)
|
||||
grow_heap(size_t bytes)
|
||||
{
|
||||
// align the area size to an 32768 bytes boundary
|
||||
bytes = (bytes + 32767) & ~32767;
|
||||
@ -295,10 +295,10 @@ restart:
|
||||
goto restart;
|
||||
}
|
||||
|
||||
if (chunk->Size() > size + sizeof(free_chunk) + 4) {
|
||||
if (chunk->Size() > size + sizeof(free_chunk) + sizeof(size_t)) {
|
||||
// if this chunk is bigger than the requested size,
|
||||
// we split it to form two chunks (with a minimal
|
||||
// size of 4 allocatable bytes).
|
||||
// size of sizeof(size_t) allocatable bytes).
|
||||
|
||||
free_chunk *freeChunk = chunk->Split(size);
|
||||
last->next = freeChunk;
|
||||
@ -312,7 +312,7 @@ restart:
|
||||
last->next = chunk->next;
|
||||
}
|
||||
|
||||
sAvailable -= size + sizeof(uint32);
|
||||
sAvailable -= size + sizeof(size_t);
|
||||
|
||||
return chunk->AllocatedAddress();
|
||||
}
|
||||
|
@ -23,8 +23,16 @@
|
||||
#include "runtime_loader_private.h"
|
||||
|
||||
|
||||
#define RLD_PROGRAM_BASE 0x00200000
|
||||
/* keep in sync with app ldscript */
|
||||
// keep in sync with app ldscript
|
||||
#ifdef __x86_64__
|
||||
// runtime_loader potentially occupies 0x200000 - 0x600000 due to large
|
||||
// page segment alignment.
|
||||
# define RLD_PROGRAM_BASE 0x600000
|
||||
# define MAX_PAGE_SIZE 0x200000
|
||||
#else
|
||||
# define RLD_PROGRAM_BASE 0x200000
|
||||
# define MAX_PAGE_SIZE B_PAGE_SIZE
|
||||
#endif
|
||||
|
||||
|
||||
bool gInvalidImageIDs;
|
||||
@ -319,7 +327,7 @@ map_image(int fd, char const* path, image_t* image, bool fixed)
|
||||
|
||||
// Check whether the segments have an unreasonable amount of unused space
|
||||
// inbetween.
|
||||
if (reservedSize > length + 8 * 1024)
|
||||
if (reservedSize > length + MAX_PAGE_SIZE * 2)
|
||||
return B_BAD_DATA;
|
||||
|
||||
// reserve that space and allocate the areas from that one
|
||||
|
Loading…
Reference in New Issue
Block a user