mirror of
git://repo.or.cz/tinycc.git
synced 2026-07-04 10:28:45 +08:00
(merge) macOS11+ dynamic linker support
This commit is contained in:
commit
588d64c538
51
libtcc.c
51
libtcc.c
@ -855,6 +855,29 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Looks for the active developer SDK set by xcode-select (or the default
|
||||||
|
one set during installation.) */
|
||||||
|
#define SZPAIR(s) s "", sizeof(s)-1
|
||||||
|
ST_FUNC int tcc_add_macos_sdkpath(TCCState* s)
|
||||||
|
{
|
||||||
|
char *sdkroot = NULL, *pos = NULL;
|
||||||
|
void* xcs = dlopen("libxcselect.dylib", RTLD_GLOBAL | RTLD_LAZY);
|
||||||
|
CString path = {};
|
||||||
|
int (*f)(unsigned int, char**) = dlsym(xcs, "xcselect_host_sdk_path");
|
||||||
|
|
||||||
|
if (f) f(1, &sdkroot);
|
||||||
|
if (!sdkroot) return -1;
|
||||||
|
pos = strstr(sdkroot,"SDKs/MacOSX");
|
||||||
|
if (!pos) return -1;
|
||||||
|
cstr_cat(&path, sdkroot, pos-sdkroot);
|
||||||
|
cstr_cat(&path, SZPAIR("SDKs/MacOSX.sdk/usr/lib\0") );
|
||||||
|
tcc_add_library_path(s, (char*)path.data);
|
||||||
|
cstr_free(&path);
|
||||||
|
tcc_free(sdkroot);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#undef SZPAIR
|
||||||
|
|
||||||
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
|
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
|
||||||
{
|
{
|
||||||
s->output_type = output_type;
|
s->output_type = output_type;
|
||||||
@ -881,7 +904,11 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);
|
tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);
|
||||||
|
#ifdef TCC_TARGET_MACHO
|
||||||
|
if (tcc_add_macos_sdkpath(s) != 0) {
|
||||||
|
tcc_add_library_path(s, CONFIG_OSX_SDK_FALLBACK);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
# ifdef _WIN32
|
# ifdef _WIN32
|
||||||
if (!s->nostdlib && output_type != TCC_OUTPUT_OBJ)
|
if (!s->nostdlib && output_type != TCC_OUTPUT_OBJ)
|
||||||
@ -979,6 +1006,10 @@ static int tcc_glob_so(TCCState *s1, const char *pattern, char *buf, int size)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef TCC_TARGET_MACHO
|
||||||
|
ST_FUNC const char* macho_tbd_soname(const char* filename);
|
||||||
|
#endif
|
||||||
|
|
||||||
ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
||||||
{
|
{
|
||||||
int fd, ret = -1;
|
int fd, ret = -1;
|
||||||
@ -1006,7 +1037,9 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
|||||||
lseek(fd, 0, SEEK_SET);
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
|
||||||
#ifdef TCC_TARGET_MACHO
|
#ifdef TCC_TARGET_MACHO
|
||||||
if (0 == obj_type && 0 == strcmp(tcc_fileextension(filename), ".dylib"))
|
if (0 == obj_type
|
||||||
|
&& (0 == strcmp(tcc_fileextension(filename), ".dylib")
|
||||||
|
|| 0 == strcmp(tcc_fileextension(filename), ".tbd")))
|
||||||
obj_type = AFF_BINTYPE_DYN;
|
obj_type = AFF_BINTYPE_DYN;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1027,9 +1060,15 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
|||||||
case AFF_BINTYPE_DYN:
|
case AFF_BINTYPE_DYN:
|
||||||
if (s1->output_type == TCC_OUTPUT_MEMORY) {
|
if (s1->output_type == TCC_OUTPUT_MEMORY) {
|
||||||
#ifdef TCC_IS_NATIVE
|
#ifdef TCC_IS_NATIVE
|
||||||
void *dl = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
|
void* dl;
|
||||||
|
const char* soname = filename;
|
||||||
|
# ifdef TCC_TARGET_MACHO
|
||||||
|
if (!strcmp(tcc_fileextension(filename), ".tbd"))
|
||||||
|
soname = macho_tbd_soname(filename);
|
||||||
|
# endif
|
||||||
|
dl = dlopen(soname, RTLD_GLOBAL | RTLD_LAZY);
|
||||||
if (dl) {
|
if (dl) {
|
||||||
tcc_add_dllref(s1, filename)->handle = dl;
|
tcc_add_dllref(s1, soname)->handle = dl;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1142,8 +1181,8 @@ LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname)
|
|||||||
static const char * const libs[] = { "%s/%s.def", "%s/lib%s.def", "%s/%s.dll", "%s/lib%s.dll", "%s/lib%s.a", NULL };
|
static const char * const libs[] = { "%s/%s.def", "%s/lib%s.def", "%s/%s.dll", "%s/lib%s.dll", "%s/lib%s.a", NULL };
|
||||||
const char * const *pp = s->static_link ? libs + 4 : libs;
|
const char * const *pp = s->static_link ? libs + 4 : libs;
|
||||||
#elif defined TCC_TARGET_MACHO
|
#elif defined TCC_TARGET_MACHO
|
||||||
static const char * const libs[] = { "%s/lib%s.dylib", "%s/lib%s.a", NULL };
|
static const char * const libs[] = { "%s/lib%s.dylib", "%s/lib%s.tbd", "%s/lib%s.a", NULL };
|
||||||
const char * const *pp = s->static_link ? libs + 1 : libs;
|
const char * const *pp = s->static_link ? libs + 2 : libs;
|
||||||
#elif defined TARGETOS_OpenBSD
|
#elif defined TARGETOS_OpenBSD
|
||||||
static const char * const libs[] = { "%s/lib%s.so.*", "%s/lib%s.a", NULL };
|
static const char * const libs[] = { "%s/lib%s.so.*", "%s/lib%s.a", NULL };
|
||||||
const char * const *pp = s->static_link ? libs + 1 : libs;
|
const char * const *pp = s->static_link ? libs + 1 : libs;
|
||||||
|
|||||||
10
tcc.h
10
tcc.h
@ -42,6 +42,7 @@
|
|||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
# include <sys/time.h>
|
# include <sys/time.h>
|
||||||
|
# include <sys/stat.h>
|
||||||
# ifndef CONFIG_TCC_STATIC
|
# ifndef CONFIG_TCC_STATIC
|
||||||
# include <dlfcn.h>
|
# include <dlfcn.h>
|
||||||
# endif
|
# endif
|
||||||
@ -278,6 +279,15 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
|||||||
ALSO_TRIPLET(CONFIG_SYSROOT "/usr/" CONFIG_LDDIR) \
|
ALSO_TRIPLET(CONFIG_SYSROOT "/usr/" CONFIG_LDDIR) \
|
||||||
":" ALSO_TRIPLET(CONFIG_SYSROOT "/" CONFIG_LDDIR) \
|
":" ALSO_TRIPLET(CONFIG_SYSROOT "/" CONFIG_LDDIR) \
|
||||||
":" ALSO_TRIPLET(CONFIG_SYSROOT "/usr/local/" CONFIG_LDDIR)
|
":" ALSO_TRIPLET(CONFIG_SYSROOT "/usr/local/" CONFIG_LDDIR)
|
||||||
|
# ifdef TCC_TARGET_MACHO
|
||||||
|
# define CONFIG_OSX_SDK1 \
|
||||||
|
"/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk"
|
||||||
|
# define CONFIG_OSX_SDK2 \
|
||||||
|
"/Applications/Xcode.app/Developer/SDKs/MacOSX.sdk"
|
||||||
|
# define CONFIG_OSX_SDK_FALLBACK \
|
||||||
|
ALSO_TRIPLET(CONFIG_OSX_SDK1 "/usr/" CONFIG_LDDIR) \
|
||||||
|
":" ALSO_TRIPLET(CONFIG_OSX_SDK2 "/usr/" CONFIG_LDDIR)
|
||||||
|
# endif
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
121
tccmacho.c
121
tccmacho.c
@ -837,7 +837,102 @@ static uint32_t macho_swap32(uint32_t x)
|
|||||||
}
|
}
|
||||||
#define SWAP(x) (swap ? macho_swap32(x) : (x))
|
#define SWAP(x) (swap ? macho_swap32(x) : (x))
|
||||||
|
|
||||||
ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev)
|
ST_FUNC int macho_add_dllref(TCCState* s1, int lev, const char* soname)
|
||||||
|
{
|
||||||
|
/* if the dll is already loaded, do not load it */
|
||||||
|
DLLReference *dllref;
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < s1->nb_loaded_dlls; i++) {
|
||||||
|
dllref = s1->loaded_dlls[i];
|
||||||
|
if (!strcmp(soname, dllref->name)) {
|
||||||
|
/* but update level if needed */
|
||||||
|
if (lev < dllref->level)
|
||||||
|
dllref->level = lev;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
|
||||||
|
dllref->level = lev;
|
||||||
|
strcpy(dllref->name, soname);
|
||||||
|
dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define tbd_parse_movepast(s) \
|
||||||
|
(pos = (pos = strstr(pos, s)) ? pos + strlen(s) : NULL)
|
||||||
|
#define tbd_parse_movetoany(cs) (pos = strpbrk(pos, cs))
|
||||||
|
#define tbd_parse_skipws while (*pos && (*pos==' '||*pos=='\n')) ++pos
|
||||||
|
#define tbd_parse_tramplequote if(*pos=='\''||*pos=='"') tbd_parse_trample
|
||||||
|
#define tbd_parse_tramplespace if(*pos==' ') tbd_parse_trample
|
||||||
|
#define tbd_parse_trample *pos++=0
|
||||||
|
|
||||||
|
ST_FUNC const char* macho_tbd_soname(const char* filename) {
|
||||||
|
char *soname, *data, *pos, *ret;
|
||||||
|
struct stat sb;
|
||||||
|
int fd = open(filename,O_RDONLY);
|
||||||
|
if (fd<0) return filename;
|
||||||
|
fstat(fd,&sb);
|
||||||
|
data = load_data(fd, 0, sb.st_size+1);
|
||||||
|
data[sb.st_size]=0;
|
||||||
|
pos = data;
|
||||||
|
|
||||||
|
if (!tbd_parse_movepast("install-name: ")) return filename;
|
||||||
|
tbd_parse_skipws;
|
||||||
|
tbd_parse_tramplequote;
|
||||||
|
soname = pos;
|
||||||
|
if (!tbd_parse_movetoany("\n \"'")) return filename;
|
||||||
|
tbd_parse_trample;
|
||||||
|
ret = tcc_mallocz(strlen(soname)+1);
|
||||||
|
strcpy(ret, soname);
|
||||||
|
// soname = strdup(soname);
|
||||||
|
tcc_free(data);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ST_FUNC int macho_load_tbd(TCCState* s1, int fd, const char* filename, int lev)
|
||||||
|
{
|
||||||
|
char *soname, *data, *pos;
|
||||||
|
|
||||||
|
struct stat sb;
|
||||||
|
fstat(fd,&sb);
|
||||||
|
data = load_data(fd, 0, sb.st_size+1);
|
||||||
|
data[sb.st_size]=0;
|
||||||
|
pos = data;
|
||||||
|
|
||||||
|
if (!tbd_parse_movepast("install-name: ")) return -1;
|
||||||
|
tbd_parse_skipws;
|
||||||
|
tbd_parse_tramplequote;
|
||||||
|
soname = pos;
|
||||||
|
if (!tbd_parse_movetoany("\n \"'")) return -1;
|
||||||
|
tbd_parse_trample;
|
||||||
|
if (macho_add_dllref(s1, lev, soname) != 0) goto the_end;
|
||||||
|
|
||||||
|
while(pos) {
|
||||||
|
char* sym = NULL;
|
||||||
|
int cont = 1;
|
||||||
|
if (!tbd_parse_movepast("symbols: ")) break;
|
||||||
|
if (!tbd_parse_movepast("[")) break;
|
||||||
|
while (cont) {
|
||||||
|
tbd_parse_skipws;
|
||||||
|
tbd_parse_tramplequote;
|
||||||
|
sym = pos;
|
||||||
|
if (!tbd_parse_movetoany(",] \"'")) break;
|
||||||
|
tbd_parse_tramplequote;
|
||||||
|
tbd_parse_tramplespace;
|
||||||
|
tbd_parse_skipws;
|
||||||
|
if (*pos==0||*pos==']') cont=0;
|
||||||
|
tbd_parse_trample;
|
||||||
|
set_elf_sym(s1->dynsymtab_section, 0, 0,
|
||||||
|
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, SHN_UNDEF, sym);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
the_end:
|
||||||
|
tcc_free(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ST_FUNC int macho_load_dylib(TCCState * s1, int fd, const char* filename, int lev)
|
||||||
{
|
{
|
||||||
unsigned char buf[sizeof(struct mach_header_64)];
|
unsigned char buf[sizeof(struct mach_header_64)];
|
||||||
void *buf2;
|
void *buf2;
|
||||||
@ -853,7 +948,6 @@ ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev)
|
|||||||
uint32_t strsize = 0;
|
uint32_t strsize = 0;
|
||||||
uint32_t iextdef = 0;
|
uint32_t iextdef = 0;
|
||||||
uint32_t nextdef = 0;
|
uint32_t nextdef = 0;
|
||||||
DLLReference *dllref;
|
|
||||||
|
|
||||||
again:
|
again:
|
||||||
if (full_read(fd, buf, sizeof(buf)) != sizeof(buf))
|
if (full_read(fd, buf, sizeof(buf)) != sizeof(buf))
|
||||||
@ -934,20 +1028,8 @@ ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev)
|
|||||||
lc = (struct load_command*) ((char*)lc + lc->cmdsize);
|
lc = (struct load_command*) ((char*)lc + lc->cmdsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if the dll is already loaded, do not load it */
|
if (0 != macho_add_dllref(s1, lev, soname))
|
||||||
for(i = 0; i < s1->nb_loaded_dlls; i++) {
|
goto the_end;
|
||||||
dllref = s1->loaded_dlls[i];
|
|
||||||
if (!strcmp(soname, dllref->name)) {
|
|
||||||
/* but update level if needed */
|
|
||||||
if (lev < dllref->level)
|
|
||||||
dllref->level = lev;
|
|
||||||
goto the_end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
|
|
||||||
dllref->level = lev;
|
|
||||||
strcpy(dllref->name, soname);
|
|
||||||
dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
|
|
||||||
|
|
||||||
if (!nsyms || !nextdef)
|
if (!nsyms || !nextdef)
|
||||||
tcc_warning("%s doesn't export any symbols?", filename);
|
tcc_warning("%s doesn't export any symbols?", filename);
|
||||||
@ -972,3 +1054,10 @@ ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev)
|
|||||||
tcc_free(buf2);
|
tcc_free(buf2);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ST_FUNC int macho_load_dll(TCCState * s1, int fd, const char* filename, int lev)
|
||||||
|
{
|
||||||
|
return strcmp(tcc_fileextension(filename), ".tbd") == 0
|
||||||
|
? macho_load_tbd(s1, fd, filename, lev)
|
||||||
|
: macho_load_dylib(s1, fd, filename, lev);
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user