kernel, linker, libc: Initial, probably horribly broken, support for some TLS situations
This commit is contained in:
parent
1c2de4d888
commit
230870ad7b
2
Makefile
2
Makefile
@ -101,6 +101,7 @@ KERNEL_OBJS += $(patsubst %.c,%.o,$(wildcard kernel/*/*/*.c))
|
|||||||
##
|
##
|
||||||
# Kernel objects from kernel/ assembly sources
|
# Kernel objects from kernel/ assembly sources
|
||||||
KERNEL_ASMOBJS = $(filter-out kernel/symbols.o,$(patsubst %.S,%.o,$(wildcard kernel/*.S)))
|
KERNEL_ASMOBJS = $(filter-out kernel/symbols.o,$(patsubst %.S,%.o,$(wildcard kernel/*.S)))
|
||||||
|
HEADERS = $(wildcard base/usr/include/kernel/*.h base/usr/include/kernel/*/*.h)
|
||||||
|
|
||||||
# Kernel
|
# Kernel
|
||||||
|
|
||||||
@ -141,7 +142,6 @@ fatbase/mod:
|
|||||||
##
|
##
|
||||||
# Modules need to be installed on the boot image
|
# Modules need to be installed on the boot image
|
||||||
MODULES = $(patsubst modules/%.c,fatbase/mod/%.ko,$(wildcard modules/*.c))
|
MODULES = $(patsubst modules/%.c,fatbase/mod/%.ko,$(wildcard modules/*.c))
|
||||||
HEADERS = $(wildcard base/usr/include/kernel/*.h base/usr/include/kernel/*/*.h)
|
|
||||||
|
|
||||||
fatbase/mod/%.ko: modules/%.c ${HEADERS} | fatbase/mod
|
fatbase/mod/%.ko: modules/%.c ${HEADERS} | fatbase/mod
|
||||||
${KCC} -nostdlib ${KCFLAGS} -c -o $@ $<
|
${KCC} -nostdlib ${KCFLAGS} -c -o $@ $<
|
||||||
|
37
apps/test-tls.c
Normal file
37
apps/test-tls.c
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <sys/sysfunc.h>
|
||||||
|
|
||||||
|
__thread int myvalue;
|
||||||
|
|
||||||
|
void * getaddressinthread(void * _unused) {
|
||||||
|
fprintf(stderr, "in thread before:\n");
|
||||||
|
fprintf(stderr, "&myvalue = %p\n", (void*)&myvalue);
|
||||||
|
fprintf(stderr, "myvalue = %d\n", myvalue);
|
||||||
|
myvalue = 1234;
|
||||||
|
fprintf(stderr, "in thread after:\n");
|
||||||
|
fprintf(stderr, "&myvalue = %p\n", (void*)&myvalue);
|
||||||
|
fprintf(stderr, "myvalue = %d\n", myvalue);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char * argv[]) {
|
||||||
|
|
||||||
|
myvalue = 42;
|
||||||
|
|
||||||
|
fprintf(stderr, "main thread before:\n");
|
||||||
|
fprintf(stderr, "&myvalue = %p\n", (void*)&myvalue);
|
||||||
|
fprintf(stderr, "myvalue = %d\n", myvalue);
|
||||||
|
|
||||||
|
pthread_t mythread;
|
||||||
|
pthread_create(&mythread, NULL, getaddressinthread, NULL);
|
||||||
|
|
||||||
|
void * retval;
|
||||||
|
pthread_join(mythread, &retval);
|
||||||
|
|
||||||
|
fprintf(stderr, "main thread after:\n");
|
||||||
|
fprintf(stderr, "&myvalue = %p\n", (void*)&myvalue);
|
||||||
|
fprintf(stderr, "myvalue = %d\n", myvalue);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -35,6 +35,8 @@ typedef struct thread {
|
|||||||
uint8_t padding[32]; /* I don't know */
|
uint8_t padding[32]; /* I don't know */
|
||||||
|
|
||||||
page_directory_t * page_directory; /* Page Directory */
|
page_directory_t * page_directory; /* Page Directory */
|
||||||
|
uintptr_t gsbase;
|
||||||
|
|
||||||
} thread_t;
|
} thread_t;
|
||||||
|
|
||||||
/* Portable image struct */
|
/* Portable image struct */
|
||||||
|
@ -75,6 +75,8 @@ extern uint8_t startswith(const char * str, const char * accept);
|
|||||||
extern void gdt_install(void);
|
extern void gdt_install(void);
|
||||||
extern void gdt_set_gate(uint8_t num, uint64_t base, uint64_t limit, uint8_t access, uint8_t gran);
|
extern void gdt_set_gate(uint8_t num, uint64_t base, uint64_t limit, uint8_t access, uint8_t gran);
|
||||||
extern void set_kernel_stack(uintptr_t stack);
|
extern void set_kernel_stack(uintptr_t stack);
|
||||||
|
extern void gdt_set_gsbase(uintptr_t base);
|
||||||
|
extern uintptr_t gdt_get_gsbase(void);
|
||||||
|
|
||||||
/* IDT */
|
/* IDT */
|
||||||
extern void idt_install(void);
|
extern void idt_install(void);
|
||||||
@ -86,7 +88,7 @@ extern void idt_set_gate(uint8_t num, void (*base)(void), uint16_t sel, uint8_t
|
|||||||
* the correct offsets as well.
|
* the correct offsets as well.
|
||||||
*/
|
*/
|
||||||
struct regs {
|
struct regs {
|
||||||
unsigned int gs, fs, es, ds;
|
unsigned int _unused, fs, es, ds;
|
||||||
unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax;
|
unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax;
|
||||||
unsigned int int_no, err_code;
|
unsigned int int_no, err_code;
|
||||||
unsigned int eip, cs, eflags, useresp, ss;
|
unsigned int eip, cs, eflags, useresp, ss;
|
||||||
|
@ -12,6 +12,12 @@ typedef struct {
|
|||||||
} pthread_t;
|
} pthread_t;
|
||||||
typedef unsigned int pthread_attr_t;
|
typedef unsigned int pthread_attr_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int volatile atomic_lock;
|
||||||
|
int volatile readers;
|
||||||
|
int writerPid;
|
||||||
|
} pthread_rwlock_t;
|
||||||
|
|
||||||
extern int pthread_create(pthread_t * thread, pthread_attr_t * attr, void *(*start_routine)(void *), void * arg);
|
extern int pthread_create(pthread_t * thread, pthread_attr_t * attr, void *(*start_routine)(void *), void * arg);
|
||||||
extern void pthread_exit(void * value);
|
extern void pthread_exit(void * value);
|
||||||
extern int pthread_kill(pthread_t thread, int sig);
|
extern int pthread_kill(pthread_t thread, int sig);
|
||||||
@ -38,5 +44,10 @@ extern int pthread_mutex_destroy(pthread_mutex_t *mutex);
|
|||||||
extern int pthread_attr_init(pthread_attr_t *attr);
|
extern int pthread_attr_init(pthread_attr_t *attr);
|
||||||
extern int pthread_attr_destroy(pthread_attr_t *attr);
|
extern int pthread_attr_destroy(pthread_attr_t *attr);
|
||||||
|
|
||||||
|
extern int pthread_rwlock_init(pthread_rwlock_t * lock, void * args);
|
||||||
|
extern int pthread_rwlock_wrlock(pthread_rwlock_t * lock);
|
||||||
|
extern int pthread_rwlock_rdlock(pthread_rwlock_t * lock);
|
||||||
|
extern int pthread_rwlock_unlock(pthread_rwlock_t * lock);
|
||||||
|
extern int pthread_rwlock_destroy(pthread_rwlock_t * lock);
|
||||||
|
|
||||||
_End_C_Header
|
_End_C_Header
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#define TOARU_SYS_FUNC_THREADNAME 11
|
#define TOARU_SYS_FUNC_THREADNAME 11
|
||||||
#define TOARU_SYS_FUNC_DEBUGPRINT 12
|
#define TOARU_SYS_FUNC_DEBUGPRINT 12
|
||||||
#define TOARU_SYS_FUNC_SETVGACURSOR 13
|
#define TOARU_SYS_FUNC_SETVGACURSOR 13
|
||||||
|
#define TOARU_SYS_FUNC_SETGSBASE 14
|
||||||
|
|
||||||
_Begin_C_Header
|
_Begin_C_Header
|
||||||
extern int sysfunc(int command, char ** args);
|
extern int sysfunc(int command, char ** args);
|
||||||
|
@ -30,9 +30,9 @@ typedef struct {
|
|||||||
|
|
||||||
/* In the future we may need to put a lock on the access of this */
|
/* In the future we may need to put a lock on the access of this */
|
||||||
static struct {
|
static struct {
|
||||||
gdt_entry_t entries[6];
|
gdt_entry_t entries[7];
|
||||||
gdt_pointer_t pointer;
|
gdt_pointer_t pointer;
|
||||||
tss_entry_t tss;
|
tss_entry_t tss;
|
||||||
} gdt __attribute__((used));
|
} gdt __attribute__((used));
|
||||||
|
|
||||||
extern void gdt_flush(uintptr_t);
|
extern void gdt_flush(uintptr_t);
|
||||||
@ -53,6 +53,17 @@ void gdt_set_gate(uint8_t num, uint64_t base, uint64_t limit, uint8_t access, ui
|
|||||||
ENTRY(num).access = access;
|
ENTRY(num).access = access;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gdt_set_gsbase(uintptr_t base) {
|
||||||
|
ENTRY(6).base_low = (base & 0xFFFF);
|
||||||
|
ENTRY(6).base_middle = (base >> 16) & 0xFF;
|
||||||
|
ENTRY(6).base_high = (base >> 24) & 0xFF;
|
||||||
|
asm volatile ("mov %0, %%gs" :: "r"((6 << 3) | 0x3));
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t gdt_get_gsbase(void) {
|
||||||
|
return (ENTRY(6).base_low) | (ENTRY(6).base_middle << 16) | (ENTRY(6).base_high << 24);
|
||||||
|
}
|
||||||
|
|
||||||
static void write_tss(int32_t num, uint16_t ss0, uint32_t esp0);
|
static void write_tss(int32_t num, uint16_t ss0, uint32_t esp0);
|
||||||
|
|
||||||
void gdt_install(void) {
|
void gdt_install(void) {
|
||||||
@ -65,8 +76,8 @@ void gdt_install(void) {
|
|||||||
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); /* Data segment */
|
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); /* Data segment */
|
||||||
gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); /* User code */
|
gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); /* User code */
|
||||||
gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); /* User data */
|
gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); /* User data */
|
||||||
|
|
||||||
write_tss(5, 0x10, 0x0);
|
write_tss(5, 0x10, 0x0);
|
||||||
|
gdt_set_gate(6, 0, 0xFFFFFFFF, 0xF2, 0xCF);
|
||||||
|
|
||||||
/* Go go go */
|
/* Go go go */
|
||||||
gdt_flush((uintptr_t)gdtp);
|
gdt_flush((uintptr_t)gdtp);
|
||||||
|
@ -784,6 +784,12 @@ static int sys_sysfunc(int fn, char ** args) {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
case 14:
|
||||||
|
PTR_VALIDATE(args);
|
||||||
|
current_process->thread.gsbase = (uintptr_t)args[0];
|
||||||
|
gdt_set_gsbase(current_process->thread.gsbase);
|
||||||
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
debug_print(ERROR, "Bad system function %d", fn);
|
debug_print(ERROR, "Bad system function %d", fn);
|
||||||
break;
|
break;
|
||||||
|
@ -218,6 +218,7 @@ uint32_t fork(void) {
|
|||||||
|
|
||||||
new_proc->thread.esp = esp;
|
new_proc->thread.esp = esp;
|
||||||
new_proc->thread.ebp = ebp;
|
new_proc->thread.ebp = ebp;
|
||||||
|
new_proc->thread.gsbase = current_process->thread.gsbase;
|
||||||
|
|
||||||
new_proc->is_tasklet = parent->is_tasklet;
|
new_proc->is_tasklet = parent->is_tasklet;
|
||||||
|
|
||||||
@ -272,6 +273,7 @@ int create_kernel_tasklet(tasklet_t tasklet, char * name, void * argp) {
|
|||||||
|
|
||||||
new_proc->thread.esp = esp;
|
new_proc->thread.esp = esp;
|
||||||
new_proc->thread.ebp = ebp;
|
new_proc->thread.ebp = ebp;
|
||||||
|
new_proc->thread.gsbase = current_process->thread.gsbase;
|
||||||
|
|
||||||
new_proc->thread.eip = (uintptr_t)tasklet;
|
new_proc->thread.eip = (uintptr_t)tasklet;
|
||||||
|
|
||||||
@ -339,6 +341,7 @@ clone(uintptr_t new_stack, uintptr_t thread_func, uintptr_t arg) {
|
|||||||
|
|
||||||
new_proc->thread.esp = esp;
|
new_proc->thread.esp = esp;
|
||||||
new_proc->thread.ebp = ebp;
|
new_proc->thread.ebp = ebp;
|
||||||
|
new_proc->thread.gsbase = current_process->thread.gsbase;
|
||||||
|
|
||||||
new_proc->is_tasklet = parent->is_tasklet;
|
new_proc->is_tasklet = parent->is_tasklet;
|
||||||
|
|
||||||
@ -405,6 +408,7 @@ void switch_task(uint8_t reschedule) {
|
|||||||
current_process->thread.eip = eip;
|
current_process->thread.eip = eip;
|
||||||
current_process->thread.esp = esp;
|
current_process->thread.esp = esp;
|
||||||
current_process->thread.ebp = ebp;
|
current_process->thread.ebp = ebp;
|
||||||
|
current_process->thread.gsbase = gdt_get_gsbase();
|
||||||
current_process->running = 0;
|
current_process->running = 0;
|
||||||
|
|
||||||
/* Save floating point state */
|
/* Save floating point state */
|
||||||
@ -432,6 +436,7 @@ void switch_next(void) {
|
|||||||
eip = current_process->thread.eip;
|
eip = current_process->thread.eip;
|
||||||
esp = current_process->thread.esp;
|
esp = current_process->thread.esp;
|
||||||
ebp = current_process->thread.ebp;
|
ebp = current_process->thread.ebp;
|
||||||
|
gdt_set_gsbase(current_process->thread.gsbase);
|
||||||
unswitch_fpu();
|
unswitch_fpu();
|
||||||
|
|
||||||
/* Validate */
|
/* Validate */
|
||||||
|
@ -32,6 +32,8 @@ enter_userspace:
|
|||||||
mov %eax, %ds
|
mov %eax, %ds
|
||||||
mov %eax, %es
|
mov %eax, %es
|
||||||
mov %eax, %fs
|
mov %eax, %fs
|
||||||
|
|
||||||
|
mov $0x33, %ax
|
||||||
mov %eax, %gs
|
mov %eax, %gs
|
||||||
/* %ss is handled by iret */
|
/* %ss is handled by iret */
|
||||||
|
|
||||||
|
@ -30,8 +30,11 @@ void _exit(int val){
|
|||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void __make_tls(void);
|
||||||
|
|
||||||
__attribute__((constructor))
|
__attribute__((constructor))
|
||||||
static void _libc_init(void) {
|
static void _libc_init(void) {
|
||||||
|
__make_tls();
|
||||||
__stdio_init_buffers();
|
__stdio_init_buffers();
|
||||||
|
|
||||||
unsigned int x = 0;
|
unsigned int x = 0;
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <sys/sysfunc.h>
|
||||||
|
|
||||||
DEFN_SYSCALL3(clone, SYS_CLONE, uintptr_t, uintptr_t, void *);
|
DEFN_SYSCALL3(clone, SYS_CLONE, uintptr_t, uintptr_t, void *);
|
||||||
DEFN_SYSCALL0(gettid, SYS_GETTID);
|
DEFN_SYSCALL0(gettid, SYS_GETTID);
|
||||||
@ -24,11 +25,39 @@ int gettid() {
|
|||||||
return syscall_gettid(); /* never fails */
|
return syscall_gettid(); /* never fails */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct pthread {
|
||||||
|
void * (*entry)(void *);
|
||||||
|
void * arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
void * ___tls_get_addr(void* input) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __make_tls(void) {
|
||||||
|
char * tlsSpace = calloc(1,4096);
|
||||||
|
char ** tlsSelf = (char **)(tlsSpace + 4096 - sizeof(char *));
|
||||||
|
*tlsSelf = (char*)tlsSelf;
|
||||||
|
sysfunc(TOARU_SYS_FUNC_SETGSBASE, (char*[]){(char*)tlsSelf});
|
||||||
|
}
|
||||||
|
|
||||||
|
void * __thread_start(void * thread) {
|
||||||
|
__make_tls();
|
||||||
|
struct pthread * me = ((pthread_t *)thread)->ret_val;
|
||||||
|
((pthread_t *)thread)->ret_val = 0;
|
||||||
|
return me->entry(me->arg);
|
||||||
|
}
|
||||||
|
|
||||||
int pthread_create(pthread_t * thread, pthread_attr_t * attr, void *(*start_routine)(void *), void * arg) {
|
int pthread_create(pthread_t * thread, pthread_attr_t * attr, void *(*start_routine)(void *), void * arg) {
|
||||||
char * stack = malloc(PTHREAD_STACK_SIZE);
|
char * stack = malloc(PTHREAD_STACK_SIZE);
|
||||||
uintptr_t stack_top = (uintptr_t)stack + PTHREAD_STACK_SIZE;
|
uintptr_t stack_top = (uintptr_t)stack + PTHREAD_STACK_SIZE;
|
||||||
|
|
||||||
thread->stack = stack;
|
thread->stack = stack;
|
||||||
thread->id = clone(stack_top, (uintptr_t)start_routine, arg);
|
struct pthread * data = malloc(sizeof(struct pthread));
|
||||||
|
data->entry = start_routine;
|
||||||
|
data->arg = arg;
|
||||||
|
thread->ret_val = data;
|
||||||
|
thread->id = clone(stack_top, (uintptr_t)__thread_start, thread);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
61
libc/pthread/pthread_rwlock.c
Normal file
61
libc/pthread/pthread_rwlock.c
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <syscall.h>
|
||||||
|
#include <syscall_nums.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#define ACQUIRE_LOCK() do { while (__sync_lock_test_and_set(&lock->atomic_lock, 0x01)) { syscall_yield(); } } while (0)
|
||||||
|
#define RELEASE_LOCK() do { __sync_lock_release(&lock->atomic_lock); } while (0)
|
||||||
|
|
||||||
|
int pthread_rwlock_init(pthread_rwlock_t * lock, void * args) {
|
||||||
|
lock->readers = 0;
|
||||||
|
lock->atomic_lock = 0;
|
||||||
|
if (args != NULL) {
|
||||||
|
fprintf(stderr, "pthread: pthread_rwlock_init arg unsupported\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_rwlock_wrlock(pthread_rwlock_t * lock) {
|
||||||
|
ACQUIRE_LOCK();
|
||||||
|
while (1) {
|
||||||
|
if (lock->readers == 0) {
|
||||||
|
lock->readers = -1;
|
||||||
|
lock->writerPid = syscall_getpid();
|
||||||
|
RELEASE_LOCK();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
syscall_yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_rwlock_rdlock(pthread_rwlock_t * lock) {
|
||||||
|
ACQUIRE_LOCK();
|
||||||
|
while (1) {
|
||||||
|
if (lock->readers >= 0) {
|
||||||
|
lock->readers++;
|
||||||
|
RELEASE_LOCK();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
syscall_yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_rwlock_unlock(pthread_rwlock_t * lock) {
|
||||||
|
ACQUIRE_LOCK();
|
||||||
|
if (lock->readers > 0) lock->readers--;
|
||||||
|
else if (lock->readers < 0) lock->readers = 0;
|
||||||
|
else fprintf(stderr, "pthread: bad lock state detected\n");
|
||||||
|
RELEASE_LOCK();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_rwlock_destroy(pthread_rwlock_t * lock) {
|
||||||
|
return 0;
|
||||||
|
}
|
@ -41,9 +41,7 @@ char *realpath(const char *path, char *resolved_path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!resolved_path) {
|
if (!resolved_path) {
|
||||||
/* Can't support this yet. */
|
resolved_path = malloc(PATH_MAX+1);
|
||||||
errno = -EINVAL;
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we're lucky, we can do this with no allocations, so let's start here... */
|
/* If we're lucky, we can do this with no allocations, so let's start here... */
|
||||||
|
@ -75,6 +75,8 @@ typedef int (*entry_point_t)(int, char *[], char**);
|
|||||||
static hashmap_t * dumb_symbol_table;
|
static hashmap_t * dumb_symbol_table;
|
||||||
static hashmap_t * glob_dat;
|
static hashmap_t * glob_dat;
|
||||||
static hashmap_t * objects_map;
|
static hashmap_t * objects_map;
|
||||||
|
static hashmap_t * tls_map;
|
||||||
|
static size_t current_tls_offset = 0;
|
||||||
|
|
||||||
/* Used for dlerror */
|
/* Used for dlerror */
|
||||||
static char * last_error = NULL;
|
static char * last_error = NULL;
|
||||||
@ -388,6 +390,7 @@ static int need_symbol_for_type(unsigned char type) {
|
|||||||
case 5:
|
case 5:
|
||||||
case 6:
|
case 6:
|
||||||
case 7:
|
case 7:
|
||||||
|
case 14:
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
@ -471,6 +474,20 @@ static int object_relocate(elf_t * object) {
|
|||||||
case 5: /* COPY */
|
case 5: /* COPY */
|
||||||
memcpy((void *)(table->r_offset + object->base), (void *)x, sym->st_size);
|
memcpy((void *)(table->r_offset + object->base), (void *)x, sym->st_size);
|
||||||
break;
|
break;
|
||||||
|
case 14: /* TLS_TPOFF */
|
||||||
|
x = *((ssize_t *)(table->r_offset + object->base));
|
||||||
|
if (!hashmap_has(tls_map, symname)) {
|
||||||
|
if (!sym->st_size) {
|
||||||
|
fprintf(stderr, "Haven't placed %s in static TLS yet but don't know its size?\n", symname);
|
||||||
|
}
|
||||||
|
current_tls_offset += sym->st_size; /* TODO alignment restrictions */
|
||||||
|
hashmap_set(tls_map, symname, (void*)(current_tls_offset));
|
||||||
|
x -= current_tls_offset;
|
||||||
|
} else {
|
||||||
|
x -= (size_t)hashmap_get(tls_map, symname);
|
||||||
|
}
|
||||||
|
memcpy((void *)(table->r_offset + object->base), &x, sizeof(uintptr_t));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
TRACE_LD("Unknown relocation type: %d", type);
|
TRACE_LD("Unknown relocation type: %d", type);
|
||||||
}
|
}
|
||||||
@ -751,6 +768,7 @@ int main(int argc, char * argv[]) {
|
|||||||
dumb_symbol_table = hashmap_create(10);
|
dumb_symbol_table = hashmap_create(10);
|
||||||
glob_dat = hashmap_create(10);
|
glob_dat = hashmap_create(10);
|
||||||
objects_map = hashmap_create(10);
|
objects_map = hashmap_create(10);
|
||||||
|
tls_map = hashmap_create(10);
|
||||||
|
|
||||||
/* Setup symbols for built-in exports */
|
/* Setup symbols for built-in exports */
|
||||||
ld_exports_t * ex = ld_builtin_exports;
|
ld_exports_t * ex = ld_builtin_exports;
|
||||||
|
Loading…
Reference in New Issue
Block a user