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

Commit bbe2390

Browse files
authored
Merge pull request #1 from fortanix/Vardhan/llvm/libunwind-x86_64-fortanix-unknown-sgx_support
Changes to allow libunwind to be linked to Rust x86_64-fortanix-unknown-sgx target
2 parents 6a075b6 + ade382b commit bbe2390

10 files changed

+1209
-9
lines changed

libunwind/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ if (LIBUNWIND_ENABLE_ASSERTIONS)
272272

273273
# On Release builds cmake automatically defines NDEBUG, so we
274274
# explicitly undefine it:
275-
if (uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE")
275+
if ((uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE") AND (NOT RUST_SGX))
276276
list(APPEND LIBUNWIND_COMPILE_FLAGS -UNDEBUG)
277277
endif()
278278
else()

libunwind/README_RUST_SGX.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Libunwind customizations for linking with x86_64-fortanix-unknown-sgx Rust target.
2+
3+
## Description
4+
### Initial Fork
5+
Initial Fork has been made from 5.0 release of llvm (commit: 6a075b6de4)
6+
### Detailed Description
7+
#### Header files that we do not include for this target
8+
1. pthread.h
9+
#### Library that we do not link to for this target.
10+
1. pthread (Locks used by libunwind is provided by rust stdlib for this target)
11+
12+
## Building unwind for rust-sgx target
13+
### Generate Make files:
14+
* `cd where you want to build libunwind`
15+
* `mkdir build`
16+
* `cd build`
17+
* `cmake -DCMAKE_BUILD_TYPE="RELEASE" -DRUST_SGX=1 -G "Unix Makefiles" -DLLVM_PATH=<path/to/llvm> <path/to/libunwind>`
18+
* `-DCMAKE_BUILD_TYPE="RELEASE"` could be removed to enable debug logs of libunwind.
19+
20+
### Build:
21+
* `make unwind_static`
22+
* `build/lib/` will have the built library.

libunwind/docs/BuildingLibunwind.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,8 @@ libunwind specific options
165165
.. option:: LIBUNWIND_SYSROOT
166166

167167
Sysroot for cross compiling
168+
169+
.. option:: LIBUNWIND_ENABLE_RUST_SGX:BOOL
170+
171+
**Default**: ``OFF``
172+

libunwind/src/CMakeLists.txt

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,10 @@ set(LIBUNWIND_C_SOURCES
99
UnwindLevel1.c
1010
UnwindLevel1-gcc-ext.c
1111
Unwind-sjlj.c)
12-
set_source_files_properties(${LIBUNWIND_C_SOURCES}
13-
PROPERTIES
14-
COMPILE_FLAGS "-std=c99")
1512

1613
set(LIBUNWIND_ASM_SOURCES
1714
UnwindRegistersRestore.S
1815
UnwindRegistersSave.S)
19-
set_source_files_properties(${LIBUNWIND_ASM_SOURCES}
20-
PROPERTIES
21-
LANGUAGE C)
2216

2317
set(LIBUNWIND_HEADERS
2418
AddressSpace.hpp
@@ -32,6 +26,7 @@ set(LIBUNWIND_HEADERS
3226
Registers.hpp
3327
UnwindCursor.hpp
3428
unwind_ext.h
29+
UnwindRustSgx.h
3530
${CMAKE_CURRENT_SOURCE_DIR}/../include/libunwind.h
3631
${CMAKE_CURRENT_SOURCE_DIR}/../include/unwind.h)
3732

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

42+
if (RUST_SGX)
43+
# Compile Flags
44+
add_definitions(-DRUST_SGX)
45+
add_definitions(-DU_FORTIFY_SOURCE)
46+
add_definitions(-D_FORTIFY_SOURCE=0)
47+
add_definitions(-D__NO_STRING_INLINES)
48+
add_definitions(-D__NO_MATH_INLINES)
49+
add_definitions(-D_LIBUNWIND_IS_BAREMETAL)
50+
list(APPEND LIBUNWIND_COMPILE_FLAGS -fno-stack-protector)
51+
list(APPEND LIBUNWIND_COMPILE_FLAGS -ffreestanding)
52+
list(APPEND LIBUNWIND_COMPILE_FLAGS -fexceptions)
53+
54+
# Sources
55+
list(APPEND LIBUNWIND_C_SOURCES UnwindRustSgx.c)
56+
list(APPEND LIBUNWIND_C_SOURCES UnwindRustSgxSnprintf.c)
57+
endif()
58+
59+
60+
set_source_files_properties(${LIBUNWIND_C_SOURCES}
61+
PROPERTIES
62+
COMPILE_FLAGS "-std=c99")
63+
set_source_files_properties(${LIBUNWIND_ASM_SOURCES}
64+
PROPERTIES
65+
LANGUAGE C)
66+
4767
set(LIBUNWIND_SOURCES
4868
${LIBUNWIND_CXX_SOURCES}
4969
${LIBUNWIND_C_SOURCES}
@@ -53,7 +73,7 @@ set(LIBUNWIND_SOURCES
5373
set(libraries ${LIBUNWINDCXX_ABI_LIBRARIES})
5474
append_if(libraries LIBUNWIND_HAS_C_LIB c)
5575
append_if(libraries LIBUNWIND_HAS_DL_LIB dl)
56-
if (LIBUNWIND_ENABLE_THREADS)
76+
if (LIBUNWIND_ENABLE_THREADS AND (NOT RUST_SGX))
5777
append_if(libraries LIBUNWIND_HAS_PTHREAD_LIB pthread)
5878
endif()
5979

libunwind/src/UnwindCursor.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include <stdint.h>
1717
#include <stdio.h>
1818
#include <stdlib.h>
19-
#ifndef _LIBUNWIND_HAS_NO_THREADS
19+
#if !defined(_LIBUNWIND_HAS_NO_THREADS) && !defined(RUST_SGX)
2020
#include <pthread.h>
2121
#endif
2222
#include <unwind.h>

libunwind/src/UnwindRustSgx.c

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
//===--------------------- UnwindRustSgx.c ----------------------------------===//
2+
//
3+
//// The LLVM Compiler Infrastructure
4+
////
5+
//// This file is dual licensed under the MIT and the University of Illinois Open
6+
//// Source Licenses. See LICENSE.TXT for details.
7+
////
8+
////
9+
////===----------------------------------------------------------------------===//
10+
11+
#define _GNU_SOURCE
12+
#include <link.h>
13+
14+
#include <elf.h>
15+
#include <stdarg.h>
16+
#include <stdio.h>
17+
#include <stddef.h>
18+
#include "UnwindRustSgx.h"
19+
20+
21+
#define max_log 256
22+
23+
24+
__attribute__((weak)) struct _IO_FILE *stderr = -1;
25+
26+
static int vwrite_err(const char *format, va_list ap)
27+
{
28+
char s[max_log];
29+
int len = 0;
30+
s[0]='\0';
31+
len = vsnprintf(s, max_log, format, ap);
32+
__rust_print_err((uint8_t *)s, len);
33+
return len;
34+
}
35+
36+
static int write_err(const char *format, ...)
37+
{
38+
int ret;
39+
va_list args;
40+
va_start(args, format);
41+
ret = vwrite_err(format, args);
42+
va_end(args);
43+
44+
45+
return ret;
46+
}
47+
48+
__attribute__((weak)) int fprintf (FILE *__restrict __stream,
49+
const char *__restrict __format, ...)
50+
{
51+
52+
int ret;
53+
if (__stream != stderr) {
54+
write_err("Rust SGX Unwind supports only writing to stderr\n");
55+
return -1;
56+
} else {
57+
va_list args;
58+
int ret = 0;
59+
va_start(args, __format);
60+
ret += vwrite_err(__format, args);
61+
va_end(args);
62+
}
63+
64+
return ret;
65+
}
66+
67+
__attribute__((weak)) int fflush (FILE *__stream)
68+
{
69+
// We do not need to do anything here.
70+
return 0;
71+
}
72+
73+
74+
75+
76+
__attribute__((weak)) void __assert_fail(const char * assertion,
77+
const char * file,
78+
unsigned int line,
79+
const char * function)
80+
{
81+
write_err("%s:%d %s %s\n", file, line, function, assertion);
82+
abort();
83+
}
84+
85+
86+
87+
// We do not report stack over flow detected.
88+
// Calling write_err uses more stack due to the way we have implemented it.
89+
// With possible enabling of stack probes, we should not
90+
// get into __stack_chk_fail() at all.
91+
__attribute__((weak)) void __stack_chk_fail() {
92+
abort();
93+
}
94+
95+
/*
96+
* Below are defined for all executibles compiled for
97+
* x86_64-fortanix-unknown-sgx rust target.
98+
* Ref: rust/src/libstd/sys/sgx/abi/entry.S
99+
*/
100+
101+
extern uint64_t TEXT_BASE;
102+
extern uint64_t TEXT_SIZE;
103+
extern uint64_t EH_FRM_HDR_BASE;
104+
extern uint64_t EH_FRM_HDR_SIZE;
105+
extern void IMAGE_BASE;
106+
107+
typedef Elf64_Phdr Elf_Phdr;
108+
int
109+
dl_iterate_phdr (int (*callback) (struct dl_phdr_info *,
110+
size_t, void *),
111+
void *data)
112+
{
113+
struct dl_phdr_info info;
114+
struct dl_phdr_info *pinfo = &info;
115+
Elf_Phdr phdr[2];
116+
int ret = 0;
117+
118+
119+
size_t text_size = TEXT_SIZE;
120+
size_t eh_base_size = EH_FRM_HDR_SIZE;
121+
122+
memset(pinfo, 0, sizeof(*pinfo));
123+
124+
pinfo->dlpi_addr = &IMAGE_BASE;
125+
pinfo->dlpi_phnum = 2;
126+
127+
pinfo->dlpi_phdr = phdr;
128+
memset(phdr, 0, 2*sizeof(*phdr));
129+
130+
131+
phdr[0].p_type = PT_LOAD;
132+
phdr[0].p_vaddr = (size_t)TEXT_BASE;
133+
phdr[0].p_memsz = text_size;
134+
135+
phdr[1].p_type = PT_GNU_EH_FRAME;
136+
phdr[1].p_vaddr = (size_t)EH_FRM_HDR_BASE;
137+
phdr[1].p_memsz = eh_base_size;
138+
139+
140+
ret = callback (&info, sizeof (struct dl_phdr_info), data);
141+
return ret;
142+
}
143+
144+
struct libwu_rs_alloc_meta {
145+
size_t alloc_size;
146+
// Should we put a signatre guard before ptr for oob access?
147+
unsigned char ptr[0];
148+
};
149+
150+
#define META_FROM_PTR(__PTR) (struct libwu_rs_alloc_meta *) \
151+
((unsigned char *)__PTR - offsetof(struct libwu_rs_alloc_meta, ptr))
152+
153+
void *libuw_malloc(size_t size)
154+
{
155+
struct libwu_rs_alloc_meta *meta;
156+
size_t alloc_size = size + sizeof(struct libwu_rs_alloc_meta);
157+
meta = (void *)__rust_alloc(alloc_size, sizeof(size_t));
158+
if (!meta) {
159+
return NULL;
160+
}
161+
meta->alloc_size = alloc_size;
162+
return (void *)meta->ptr;
163+
}
164+
165+
void libuw_free(void *p)
166+
{
167+
struct libwu_rs_alloc_meta *meta;
168+
if (!p) {
169+
return;
170+
}
171+
meta = META_FROM_PTR(p);
172+
__rust_dealloc((unsigned char *)meta, meta->alloc_size, sizeof(size_t));
173+
}

libunwind/src/UnwindRustSgx.h

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
//===--------------------- UnwindRustSgx.h ----------------------------------===//
2+
//
3+
//// The LLVM Compiler Infrastructure
4+
////
5+
//// This file is dual licensed under the MIT and the University of Illinois Open
6+
//// Source Licenses. See LICENSE.TXT for details.
7+
////
8+
////
9+
////===----------------------------------------------------------------------===//
10+
11+
#if !defined(UNWIND_RUST_SGX_H)
12+
#define UNWIND_RUST_SGX_H
13+
14+
#ifdef RUST_SGX
15+
16+
#define _GNU_SOURCE
17+
#include <link.h>
18+
#include <stdarg.h>
19+
#include <string.h>
20+
#include <stdint.h>
21+
22+
// We have to use RWLock from rust repo, it is defined in:
23+
// src/libstd/sys/sgx/rwlock.rs.
24+
// rwlock.rs has compile time check to ensure sizeof(RWLock) = 128.
25+
typedef struct {
26+
unsigned char opaque[128];
27+
} RWLock;
28+
29+
// The below is obtained by printing initialized bytes
30+
// for RWLock in rust repo: src/libstd/sys/sgx/rwlock.rs.
31+
#define RWLOCK_INIT { \
32+
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
33+
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
34+
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
35+
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
36+
0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
37+
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
38+
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
39+
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
40+
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
41+
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
42+
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
43+
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
44+
0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
45+
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
46+
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
47+
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
48+
}
49+
50+
// These are the functions exposed by SGX-Rust.
51+
// The rust changes are available at:
52+
#ifdef __cplusplus
53+
extern "C" {
54+
#endif
55+
int __rust_rwlock_rdlock(RWLock *rwlock);
56+
int __rust_rwlock_wrlock(RWLock *rwlock);
57+
int __rust_rwlock_unlock(RWLock *rwlock);
58+
unsigned char *__rust_alloc(size_t, size_t);
59+
void __rust_dealloc(unsigned char *, size_t, size_t);
60+
void __rust_print_err(uint8_t *m, int s);
61+
__attribute__((noreturn)) void __rust_abort(void);
62+
unsigned char *__rust_encl_address(size_t);
63+
#ifdef __cplusplus
64+
}
65+
#endif
66+
67+
#define abort __rust_abort
68+
69+
#undef pthread_rwlock_t
70+
#undef pthread_rwlock_rdlock
71+
#undef pthread_rwlock_wrlock
72+
#undef pthread_rwlock_unlock
73+
74+
#define pthread_rwlock_t RWLock
75+
#define PTHREAD_RWLOCK_INITIALIZER RWLOCK_INIT
76+
77+
78+
#define pthread_rwlock_rdlock __rust_rwlock_rdlock
79+
#define pthread_rwlock_wrlock __rust_rwlock_wrlock
80+
#define pthread_rwlock_unlock __rust_rwlock_unlock
81+
82+
83+
#define malloc libuw_malloc
84+
#define free libuw_free
85+
86+
#ifdef dl_iterate_phdr
87+
#undef dl_iterate_phdr
88+
#endif
89+
#define dl_iterate_phdr libuw_dl_iterate_phdr
90+
91+
#ifdef __cplusplus
92+
extern "C" {
93+
#endif
94+
95+
void *libuw_malloc(size_t size);
96+
97+
void libuw_free(void *p);
98+
99+
int
100+
libuw_dl_iterate_phdr (int (*callback) (struct dl_phdr_info *,
101+
size_t, void *), void *data);
102+
103+
#ifdef __cplusplus
104+
}
105+
#endif
106+
107+
#endif
108+
#endif

0 commit comments

Comments
 (0)