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 = "" ;
|
IDE_ONLY = "" ;
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSTEM_BIN = ;
|
SYSTEM_BIN = bash ;
|
||||||
|
|
||||||
SYSTEM_APPS = ;
|
SYSTEM_APPS = ;
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ SYSTEM_PREFERENCES = ;
|
|||||||
|
|
||||||
SYSTEM_DEMOS = ;
|
SYSTEM_DEMOS = ;
|
||||||
|
|
||||||
SYSTEM_LIBS = ;
|
SYSTEM_LIBS = libroot.so ;
|
||||||
|
|
||||||
PRIVATE_SYSTEM_LIBS = ;
|
PRIVATE_SYSTEM_LIBS = ;
|
||||||
|
|
||||||
@ -74,13 +74,13 @@ AddLibrariesToHaikuHybridImage system lib
|
|||||||
AddFilesToHaikuImage system servers : $(SYSTEM_SERVERS) ;
|
AddFilesToHaikuImage system servers : $(SYSTEM_SERVERS) ;
|
||||||
|
|
||||||
# apps
|
# apps
|
||||||
#AddFilesToHaikuImage system : runtime_loader ;
|
AddFilesToHaikuImage system : runtime_loader ;
|
||||||
AddFilesToHaikuImage system bin : $(SYSTEM_BIN) ;
|
AddFilesToHaikuImage system bin : $(SYSTEM_BIN) ;
|
||||||
AddFilesToHaikuImage system apps : $(SYSTEM_APPS) ;
|
AddFilesToHaikuImage system apps : $(SYSTEM_APPS) ;
|
||||||
AddFilesToHaikuImage system preferences : $(SYSTEM_PREFERENCES) ;
|
AddFilesToHaikuImage system preferences : $(SYSTEM_PREFERENCES) ;
|
||||||
AddFilesToHaikuImage system demos : $(SYSTEM_DEMOS) ;
|
AddFilesToHaikuImage system demos : $(SYSTEM_DEMOS) ;
|
||||||
|
|
||||||
#AddSymlinkToHaikuImage system bin : bash : sh ;
|
AddSymlinkToHaikuImage system bin : bash : sh ;
|
||||||
#AddSymlinkToHaikuImage system bin : less : more ;
|
#AddSymlinkToHaikuImage system bin : less : more ;
|
||||||
#AddSymlinkToHaikuImage system bin : gzip : gunzip ;
|
#AddSymlinkToHaikuImage system bin : gzip : gunzip ;
|
||||||
#AddSymlinkToHaikuImage system bin : gzip : zcat ;
|
#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 {
|
struct free_chunk {
|
||||||
uint32 size;
|
size_t size;
|
||||||
free_chunk *next;
|
free_chunk *next;
|
||||||
|
|
||||||
uint32 Size() const;
|
size_t Size() const;
|
||||||
free_chunk *Split(uint32 splitSize);
|
free_chunk *Split(size_t splitSize);
|
||||||
bool IsTouching(free_chunk *link);
|
bool IsTouching(free_chunk *link);
|
||||||
free_chunk *Join(free_chunk *link);
|
free_chunk *Join(free_chunk *link);
|
||||||
void Remove(free_chunk *previous = NULL);
|
void Remove(free_chunk *previous = NULL);
|
||||||
@ -50,7 +50,7 @@ struct free_chunk {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static uint32 sAvailable;
|
static size_t sAvailable;
|
||||||
static free_chunk sFreeAnchor;
|
static free_chunk sFreeAnchor;
|
||||||
|
|
||||||
|
|
||||||
@ -58,10 +58,10 @@ static free_chunk sFreeAnchor;
|
|||||||
* in this chunk.
|
* in this chunk.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uint32
|
size_t
|
||||||
free_chunk::Size() const
|
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 *
|
||||||
free_chunk::Split(uint32 splitSize)
|
free_chunk::Split(size_t splitSize)
|
||||||
{
|
{
|
||||||
free_chunk *chunk = (free_chunk *)((uint8 *)this + sizeof(uint32) + splitSize);
|
free_chunk *chunk = (free_chunk *)((uint8 *)this + sizeof(size_t) + splitSize);
|
||||||
chunk->size = size - splitSize - sizeof(uint32);
|
chunk->size = size - splitSize - sizeof(size_t);
|
||||||
chunk->next = next;
|
chunk->next = next;
|
||||||
|
|
||||||
size = splitSize + sizeof(uint32);
|
size = splitSize + sizeof(size_t);
|
||||||
|
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
@ -167,7 +167,7 @@ free_chunk::AllocatedAddress() const
|
|||||||
free_chunk *
|
free_chunk *
|
||||||
free_chunk::SetToAllocated(void *allocated)
|
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)
|
if (area < B_OK)
|
||||||
return area;
|
return area;
|
||||||
|
|
||||||
sAvailable += size - sizeof(uint32);
|
sAvailable += size - sizeof(size_t);
|
||||||
|
|
||||||
// declare the whole heap as one chunk, and add it
|
// declare the whole heap as one chunk, and add it
|
||||||
// to the free list
|
// to the free list
|
||||||
@ -198,7 +198,7 @@ add_area(size_t size)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
grow_heap(uint32 bytes)
|
grow_heap(size_t bytes)
|
||||||
{
|
{
|
||||||
// align the area size to an 32768 bytes boundary
|
// align the area size to an 32768 bytes boundary
|
||||||
bytes = (bytes + 32767) & ~32767;
|
bytes = (bytes + 32767) & ~32767;
|
||||||
@ -295,10 +295,10 @@ restart:
|
|||||||
goto 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,
|
// if this chunk is bigger than the requested size,
|
||||||
// we split it to form two chunks (with a minimal
|
// 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);
|
free_chunk *freeChunk = chunk->Split(size);
|
||||||
last->next = freeChunk;
|
last->next = freeChunk;
|
||||||
@ -312,7 +312,7 @@ restart:
|
|||||||
last->next = chunk->next;
|
last->next = chunk->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
sAvailable -= size + sizeof(uint32);
|
sAvailable -= size + sizeof(size_t);
|
||||||
|
|
||||||
return chunk->AllocatedAddress();
|
return chunk->AllocatedAddress();
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,16 @@
|
|||||||
#include "runtime_loader_private.h"
|
#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;
|
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
|
// Check whether the segments have an unreasonable amount of unused space
|
||||||
// inbetween.
|
// inbetween.
|
||||||
if (reservedSize > length + 8 * 1024)
|
if (reservedSize > length + MAX_PAGE_SIZE * 2)
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
|
|
||||||
// reserve that space and allocate the areas from that one
|
// reserve that space and allocate the areas from that one
|
||||||
|
Loading…
Reference in New Issue
Block a user