diff --git a/elf.h b/elf.h index a78db186..b76fe1fa 100644 --- a/elf.h +++ b/elf.h @@ -2908,6 +2908,8 @@ typedef Elf32_Addr Elf32_Conflict; #define R_X86_64_NUM 43 +/* x86-64 sh_type values. */ +#define SHT_X86_64_UNWIND 0x70000001 /* Unwind information. */ /* AM33 relocations. */ #define R_MN10300_NONE 0 /* No reloc. */ diff --git a/lib/bcheck.c b/lib/bcheck.c index c2ca3768..2887a576 100644 --- a/lib/bcheck.c +++ b/lib/bcheck.c @@ -1147,7 +1147,7 @@ void __attribute__((destructor)) __bound_exit(void) dprintf(stderr, "%s, %s():\n", __FILE__, __FUNCTION__); if (inited) { -#if !defined(_WIN32) && !defined(__APPLE__) +#if !defined(_WIN32) && !defined(__APPLE__) && !defined(__OpenBSD__) if (print_heap) { extern void __libc_freeres (void); __libc_freeres (); diff --git a/tcc.h b/tcc.h index 196654a9..837cbdd8 100644 --- a/tcc.h +++ b/tcc.h @@ -285,7 +285,11 @@ extern char **environ; # if defined(TCC_MUSL) # define CONFIG_TCC_ELFINTERP "/lib/ld-musl-x86_64.so.1" # else -# define CONFIG_TCC_ELFINTERP "/lib64/ld-linux-x86-64.so.2" +# if defined(__OpenBSD__) +# define CONFIG_TCC_ELFINTERP "/usr/libexec/ld.so" +# else +# define CONFIG_TCC_ELFINTERP "/lib64/ld-linux-x86-64.so.2" +# endif # endif # elif defined(TCC_TARGET_RISCV64) # define CONFIG_TCC_ELFINTERP "/lib/ld-linux-riscv64-lp64d.so.1" diff --git a/tccelf.c b/tccelf.c index 48d7794c..6a6aaee0 100644 --- a/tccelf.c +++ b/tccelf.c @@ -1413,7 +1413,9 @@ ST_FUNC void tcc_add_runtime(TCCState *s1) #ifdef CONFIG_TCC_BCHECK if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL) { tcc_add_library_err(s1, "pthread"); +#if !defined(__OpenBSD__) tcc_add_library_err(s1, "dl"); +#endif tcc_add_support(s1, "bcheck.o"); } #endif @@ -1992,7 +1994,7 @@ static void put_dt(Section *dynamic, int dt, addr_t val) } static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp, - Section *dynamic) + Section *dynamic, Section *note) { ElfW(Phdr) *ph; @@ -2019,6 +2021,19 @@ static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp, ph->p_align = interp->sh_addralign; } + if (note) { + ph = &phdr[phnum - 2]; + + ph->p_type = PT_NOTE; + ph->p_offset = note->sh_offset; + ph->p_vaddr = note->sh_addr; + ph->p_paddr = ph->p_vaddr; + ph->p_filesz = note->sh_size; + ph->p_memsz = note->sh_size; + ph->p_flags = PF_R; + ph->p_align = note->sh_addralign; + } + /* if dynamic section, then add corresponding program header */ if (dynamic) { ph = &phdr[phnum - 1]; @@ -2051,6 +2066,13 @@ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf) put_dt(dynamic, DT_RELA, dyninf->rel_addr); put_dt(dynamic, DT_RELASZ, dyninf->rel_size); put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel)); +#ifdef __OpenBSD__ + put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr); + put_dt(dynamic, DT_PLTRELSZ, dyninf->rel_size); + put_dt(dynamic, DT_JMPREL, dyninf->rel_addr); + put_dt(dynamic, DT_PLTREL, DT_RELA); + put_dt(dynamic, DT_BIND_NOW, 1); /* Dirty hack */ +#endif #else #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr); @@ -2372,6 +2394,25 @@ static void create_arm_attribute_section(TCCState *s1) } #endif +#ifdef __OpenBSD__ +static Section *create_openbsd_note_section(TCCState *s1) +{ + Section *s = find_section (s1, ".note.openbsd.ident"); + + if (s->data_offset == 0) { + unsigned char *ptr = section_ptr_add(s, sizeof(ElfW(Nhdr)) + 8 + 4); + ElfW(Nhdr) *note = (ElfW(Nhdr) *) ptr; + + s->sh_type = SHT_NOTE; + note->n_namesz = 8; + note->n_descsz = 4; + note->n_type = ELF_NOTE_OS_GNU; + strcpy (ptr + sizeof(ElfW(Nhdr)), "OpenBSD"); + } + return s; +} +#endif + /* Output an elf, coff or binary file */ /* XXX: suppress unneeded sections */ static int elf_output_file(TCCState *s1, const char *filename) @@ -2379,13 +2420,18 @@ static int elf_output_file(TCCState *s1, const char *filename) int ret, phnum, shnum, file_type, file_offset, *sec_order; struct dyn_inf dyninf = {0}; ElfW(Phdr) *phdr; - Section *strsec, *interp, *dynamic, *dynstr; + Section *strsec, *interp, *dynamic, *dynstr, *note = NULL; + + file_type = s1->output_type; #ifdef TCC_TARGET_ARM create_arm_attribute_section (s1); #endif +#ifdef __OpenBSD__ + if (file_type != TCC_OUTPUT_OBJ) + note = create_openbsd_note_section (s1); +#endif - file_type = s1->output_type; s1->nb_errors = 0; ret = -1; phdr = NULL; @@ -2497,6 +2543,8 @@ static int elf_output_file(TCCState *s1, const char *filename) phnum = i < s1->nb_sections ? 6 : 5; } + phnum += note != NULL; + /* allocate program segment headers */ phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr))); @@ -2515,7 +2563,7 @@ static int elf_output_file(TCCState *s1, const char *filename) /* Fill remaining program header and finalize relocation related to dynamic linking. */ if (file_type != TCC_OUTPUT_OBJ) { - fill_unloadable_phdr(phdr, phnum, interp, dynamic); + fill_unloadable_phdr(phdr, phnum, interp, dynamic, note); if (dynamic) { ElfW(Sym) *sym; dynamic->data_offset = dyninf.data_offset; @@ -2703,6 +2751,10 @@ ST_FUNC int tcc_load_object_file(TCCState *s1, if (sh->sh_type != SHT_PROGBITS && #ifdef TCC_ARM_EABI sh->sh_type != SHT_ARM_EXIDX && +#endif +#ifdef __OpenBSD__ + sh->sh_type != SHT_X86_64_UNWIND && + sh->sh_type != SHT_NOTE && #endif sh->sh_type != SHT_NOBITS && sh->sh_type != SHT_PREINIT_ARRAY && diff --git a/tccrun.c b/tccrun.c index f453f3f3..e57c1e8c 100644 --- a/tccrun.c +++ b/tccrun.c @@ -88,8 +88,23 @@ LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr) unlink(tmpfname); ftruncate(fd, size); +#ifdef __OpenBSD__ + { /* OpenBSD uses random 64 addresses that are far apart. This does not + work for the x86_64 target. + This might be a problem in the future for other targets. */ + static char *prw = (char *) 0x100000000; + char *pex = prw + 0x40000000; + + ptr = mmap (prw, size, PROT_READ|PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0); + prx = mmap (pex, size, PROT_READ|PROT_EXEC, MAP_SHARED | MAP_FIXED, fd, 0); + tcc_enter_state (s1); + prw += 0x100000000; + tcc_exit_state(); + } +#else ptr = mmap (NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); prx = mmap (NULL, size, PROT_READ|PROT_EXEC, MAP_SHARED, fd, 0); +#endif if (ptr == MAP_FAILED || prx == MAP_FAILED) tcc_error("tccrun: could not map memory"); dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, (void*)(addr_t)size); diff --git a/tests/tcctest.c b/tests/tcctest.c index 71089b52..0ccfdf2e 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -2313,7 +2313,7 @@ int fib(int n) return fib(n-1) + fib(n-2); } -#if __GNUC__ == 3 +#if __GNUC__ == 3 || __GNUC__ == 4 # define aligned_function 0 #else void __attribute__((aligned(16))) aligned_function(int i) {}