Skip to content
This repository was archived by the owner on Nov 6, 2022. It is now read-only.

Changes to allow libunwind to be linked to Rust x86_64-fortanix-unknown-sgx target #1

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libunwind/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ if (LIBUNWIND_ENABLE_ASSERTIONS)

# On Release builds cmake automatically defines NDEBUG, so we
# explicitly undefine it:
if (uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE")
if ((uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE") AND (NOT RUST_SGX))
list(APPEND LIBUNWIND_COMPILE_FLAGS -UNDEBUG)
endif()
else()
Expand Down
22 changes: 22 additions & 0 deletions libunwind/README_RUST_SGX.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Libunwind customizations for linking with x86_64-fortanix-unknown-sgx Rust target.

## Description
### Initial Fork
Initial Fork has been made from 5.0 release of llvm (commit: 6a075b6de4)
### Detailed Description
#### Header files that we do not include for this target
1. pthread.h
#### Library that we do not link to for this target.
1. pthread (Locks used by libunwind is provided by rust stdlib for this target)

## Building unwind for rust-sgx target
### Generate Make files:
* `cd where you want to build libunwind`
* `mkdir build`
* `cd build`
* `cmake -DCMAKE_BUILD_TYPE="RELEASE" -DRUST_SGX=1 -G "Unix Makefiles" -DLLVM_PATH=<path/to/llvm> <path/to/libunwind>`
* `-DCMAKE_BUILD_TYPE="RELEASE"` could be removed to enable debug logs of libunwind.

### Build:
* `make unwind_static`
* `build/lib/` will have the built library.
5 changes: 5 additions & 0 deletions libunwind/docs/BuildingLibunwind.rst
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,8 @@ libunwind specific options
.. option:: LIBUNWIND_SYSROOT

Sysroot for cross compiling

.. option:: LIBUNWIND_ENABLE_RUST_SGX:BOOL

**Default**: ``OFF``

34 changes: 27 additions & 7 deletions libunwind/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,10 @@ set(LIBUNWIND_C_SOURCES
UnwindLevel1.c
UnwindLevel1-gcc-ext.c
Unwind-sjlj.c)
set_source_files_properties(${LIBUNWIND_C_SOURCES}
PROPERTIES
COMPILE_FLAGS "-std=c99")

set(LIBUNWIND_ASM_SOURCES
UnwindRegistersRestore.S
UnwindRegistersSave.S)
set_source_files_properties(${LIBUNWIND_ASM_SOURCES}
PROPERTIES
LANGUAGE C)

set(LIBUNWIND_HEADERS
AddressSpace.hpp
Expand All @@ -32,6 +26,7 @@ set(LIBUNWIND_HEADERS
Registers.hpp
UnwindCursor.hpp
unwind_ext.h
UnwindRustSgx.h
${CMAKE_CURRENT_SOURCE_DIR}/../include/libunwind.h
${CMAKE_CURRENT_SOURCE_DIR}/../include/unwind.h)

Expand All @@ -44,6 +39,31 @@ if (MSVC_IDE)
source_group("Header Files" FILES ${LIBUNWIND_HEADERS})
endif()

if (RUST_SGX)
# Compile Flags
add_definitions(-DRUST_SGX)
add_definitions(-DU_FORTIFY_SOURCE)
add_definitions(-D_FORTIFY_SOURCE=0)
add_definitions(-D__NO_STRING_INLINES)
add_definitions(-D__NO_MATH_INLINES)
add_definitions(-D_LIBUNWIND_IS_BAREMETAL)
list(APPEND LIBUNWIND_COMPILE_FLAGS -fno-stack-protector)
list(APPEND LIBUNWIND_COMPILE_FLAGS -ffreestanding)
list(APPEND LIBUNWIND_COMPILE_FLAGS -fexceptions)

# Sources
list(APPEND LIBUNWIND_C_SOURCES UnwindRustSgx.c)
list(APPEND LIBUNWIND_C_SOURCES UnwindRustSgxSnprintf.c)
endif()


set_source_files_properties(${LIBUNWIND_C_SOURCES}
PROPERTIES
COMPILE_FLAGS "-std=c99")
set_source_files_properties(${LIBUNWIND_ASM_SOURCES}
PROPERTIES
LANGUAGE C)

set(LIBUNWIND_SOURCES
${LIBUNWIND_CXX_SOURCES}
${LIBUNWIND_C_SOURCES}
Expand All @@ -53,7 +73,7 @@ set(LIBUNWIND_SOURCES
set(libraries ${LIBUNWINDCXX_ABI_LIBRARIES})
append_if(libraries LIBUNWIND_HAS_C_LIB c)
append_if(libraries LIBUNWIND_HAS_DL_LIB dl)
if (LIBUNWIND_ENABLE_THREADS)
if (LIBUNWIND_ENABLE_THREADS AND (NOT RUST_SGX))
append_if(libraries LIBUNWIND_HAS_PTHREAD_LIB pthread)
endif()

Expand Down
2 changes: 1 addition & 1 deletion libunwind/src/UnwindCursor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef _LIBUNWIND_HAS_NO_THREADS
#if !defined(_LIBUNWIND_HAS_NO_THREADS) && !defined(RUST_SGX)
#include <pthread.h>
#endif
#include <unwind.h>
Expand Down
173 changes: 173 additions & 0 deletions libunwind/src/UnwindRustSgx.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
//===--------------------- UnwindRustSgx.c ----------------------------------===//
//
//// The LLVM Compiler Infrastructure
////
//// This file is dual licensed under the MIT and the University of Illinois Open
//// Source Licenses. See LICENSE.TXT for details.
////
////
////===----------------------------------------------------------------------===//

#define _GNU_SOURCE
#include <link.h>

#include <elf.h>
#include <stdarg.h>
#include <stdio.h>
#include <stddef.h>
#include "UnwindRustSgx.h"


#define max_log 256


__attribute__((weak)) struct _IO_FILE *stderr = -1;

static int vwrite_err(const char *format, va_list ap)
{
char s[max_log];
int len = 0;
s[0]='\0';
len = vsnprintf(s, max_log, format, ap);
__rust_print_err((uint8_t *)s, len);
return len;
}

static int write_err(const char *format, ...)
{
int ret;
va_list args;
va_start(args, format);
ret = vwrite_err(format, args);
va_end(args);


return ret;
}

__attribute__((weak)) int fprintf (FILE *__restrict __stream,
const char *__restrict __format, ...)
{

int ret;
if (__stream != stderr) {
write_err("Rust SGX Unwind supports only writing to stderr\n");
return -1;
} else {
va_list args;
int ret = 0;
va_start(args, __format);
ret += vwrite_err(__format, args);
va_end(args);
}

return ret;
}

__attribute__((weak)) int fflush (FILE *__stream)
{
// We do not need to do anything here.
return 0;
}




__attribute__((weak)) void __assert_fail(const char * assertion,
const char * file,
unsigned int line,
const char * function)
{
write_err("%s:%d %s %s\n", file, line, function, assertion);
abort();
}



// We do not report stack over flow detected.
// Calling write_err uses more stack due to the way we have implemented it.
// With possible enabling of stack probes, we should not
// get into __stack_chk_fail() at all.
__attribute__((weak)) void __stack_chk_fail() {
abort();
}

/*
* Below are defined for all executibles compiled for
* x86_64-fortanix-unknown-sgx rust target.
* Ref: rust/src/libstd/sys/sgx/abi/entry.S
*/

extern uint64_t TEXT_BASE;
extern uint64_t TEXT_SIZE;
extern uint64_t EH_FRM_HDR_BASE;
extern uint64_t EH_FRM_HDR_SIZE;
extern void IMAGE_BASE;

typedef Elf64_Phdr Elf_Phdr;
int
dl_iterate_phdr (int (*callback) (struct dl_phdr_info *,
size_t, void *),
void *data)
{
struct dl_phdr_info info;
struct dl_phdr_info *pinfo = &info;
Elf_Phdr phdr[2];
int ret = 0;


size_t text_size = TEXT_SIZE;
size_t eh_base_size = EH_FRM_HDR_SIZE;

memset(pinfo, 0, sizeof(*pinfo));

pinfo->dlpi_addr = &IMAGE_BASE;
pinfo->dlpi_phnum = 2;

pinfo->dlpi_phdr = phdr;
memset(phdr, 0, 2*sizeof(*phdr));


phdr[0].p_type = PT_LOAD;
phdr[0].p_vaddr = (size_t)TEXT_BASE;
phdr[0].p_memsz = text_size;

phdr[1].p_type = PT_GNU_EH_FRAME;
phdr[1].p_vaddr = (size_t)EH_FRM_HDR_BASE;
phdr[1].p_memsz = eh_base_size;


ret = callback (&info, sizeof (struct dl_phdr_info), data);
return ret;
}

struct libwu_rs_alloc_meta {
size_t alloc_size;
// Should we put a signatre guard before ptr for oob access?
unsigned char ptr[0];
};

#define META_FROM_PTR(__PTR) (struct libwu_rs_alloc_meta *) \
((unsigned char *)__PTR - offsetof(struct libwu_rs_alloc_meta, ptr))

void *libuw_malloc(size_t size)
{
struct libwu_rs_alloc_meta *meta;
size_t alloc_size = size + sizeof(struct libwu_rs_alloc_meta);
meta = (void *)__rust_alloc(alloc_size, sizeof(size_t));
if (!meta) {
return NULL;
}
meta->alloc_size = alloc_size;
return (void *)meta->ptr;
}

void libuw_free(void *p)
{
struct libwu_rs_alloc_meta *meta;
if (!p) {
return;
}
meta = META_FROM_PTR(p);
__rust_dealloc((unsigned char *)meta, meta->alloc_size, sizeof(size_t));
}
108 changes: 108 additions & 0 deletions libunwind/src/UnwindRustSgx.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
//===--------------------- UnwindRustSgx.h ----------------------------------===//
//
//// The LLVM Compiler Infrastructure
////
//// This file is dual licensed under the MIT and the University of Illinois Open
//// Source Licenses. See LICENSE.TXT for details.
////
////
////===----------------------------------------------------------------------===//

#if !defined(UNWIND_RUST_SGX_H)
#define UNWIND_RUST_SGX_H

#ifdef RUST_SGX

#define _GNU_SOURCE
#include <link.h>
#include <stdarg.h>
#include <string.h>
#include <stdint.h>

// We have to use RWLock from rust repo, it is defined in:
// src/libstd/sys/sgx/rwlock.rs.
// rwlock.rs has compile time check to ensure sizeof(RWLock) = 128.
typedef struct {
unsigned char opaque[128];
} RWLock;

// The below is obtained by printing initialized bytes
// for RWLock in rust repo: src/libstd/sys/sgx/rwlock.rs.
#define RWLOCK_INIT { \
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
}

// These are the functions exposed by SGX-Rust.
// The rust changes are available at:
#ifdef __cplusplus
extern "C" {
#endif
int __rust_rwlock_rdlock(RWLock *rwlock);
int __rust_rwlock_wrlock(RWLock *rwlock);
int __rust_rwlock_unlock(RWLock *rwlock);
unsigned char *__rust_alloc(size_t, size_t);
void __rust_dealloc(unsigned char *, size_t, size_t);
void __rust_print_err(uint8_t *m, int s);
__attribute__((noreturn)) void __rust_abort(void);
unsigned char *__rust_encl_address(size_t);
#ifdef __cplusplus
}
#endif

#define abort __rust_abort

#undef pthread_rwlock_t
#undef pthread_rwlock_rdlock
#undef pthread_rwlock_wrlock
#undef pthread_rwlock_unlock

#define pthread_rwlock_t RWLock
#define PTHREAD_RWLOCK_INITIALIZER RWLOCK_INIT


#define pthread_rwlock_rdlock __rust_rwlock_rdlock
#define pthread_rwlock_wrlock __rust_rwlock_wrlock
#define pthread_rwlock_unlock __rust_rwlock_unlock


#define malloc libuw_malloc
#define free libuw_free

#ifdef dl_iterate_phdr
#undef dl_iterate_phdr
#endif
#define dl_iterate_phdr libuw_dl_iterate_phdr

#ifdef __cplusplus
extern "C" {
#endif

void *libuw_malloc(size_t size);

void libuw_free(void *p);

int
libuw_dl_iterate_phdr (int (*callback) (struct dl_phdr_info *,
size_t, void *), void *data);

#ifdef __cplusplus
}
#endif

#endif
#endif
Loading