Skip to content

Commit f838a3c

Browse files
committed
Make library executable; Minimize Plugin deps(!!); other minor tweaks
1 parent 8467b29 commit f838a3c

File tree

10 files changed

+134
-40
lines changed

10 files changed

+134
-40
lines changed

CMakeLists.txt

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,32 @@
11
cmake_minimum_required(VERSION 2.6)
22

3-
project(j2 LANGUAGES C)
3+
project(jj LANGUAGES C)
44

55
add_definitions(-std=gnu99)
66
add_definitions(-ggdb3)
77
add_definitions(-fdebug-types-section)
88
add_definitions(-fno-eliminate-unused-debug-types)
9-
add_definitions(-DLTTNG)
109
add_definitions(-fdebug-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}/=)
10+
add_definitions(-ftls-model=local-dynamic)
1111

1212
include_directories(.)
1313

1414
#add_definitions(-O3)
1515
#add_definitions(-gdwarf-4)
1616

17-
add_library(reflect SHARED trace.c util.c cll.c listree.c reflect.c compile.c vm.c extensions.c)
18-
add_executable(jj jj.c)
19-
target_link_libraries(jj reflect dwarf elf dw dl ffi pthread urcu urcu-bp urcu-common lttng-ust lttng-ctl lttng-ust-tracepoint)
17+
# build a shared library that is also an executable(!!)
18+
add_library(reflect SHARED trace.c util.c cll.c listree.c reflect.c compile.c vm.c extensions.c jj.c)
19+
target_compile_options(reflect PUBLIC "-fPIC")
20+
target_link_libraries(reflect "-pie -Wl,-E")
21+
22+
target_link_libraries(reflect dwarf elf dw dl ffi pthread)
23+
24+
add_definitions(-DLTTNG)
25+
target_link_libraries(reflect urcu urcu-bp urcu-common lttng-ust lttng-ctl lttng-ust-tracepoint)
2026

21-
set_property(TARGET reflect jj PROPERTY POSITION_INDEPENDENT_CODE ON)
27+
# build a demo executable that dynamically links reflection as a plugin
28+
add_executable(jj jj_plugin.c)
29+
target_link_libraries(jj dl)
2230

2331
install(TARGETS reflect jj
2432
RUNTIME DESTINATION bin COMPONENT j2

bootstrap.edict

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
[a b int_add! a@ limit int_nequal! slowloop!]@slowloop
2121
[int! @limit limit@ int! 0@ @a int! 1@ @b slowloop! | locals!]@slowbench
2222

23-
[vm_eval(ROOT [ROOT<ARG0 decaps! stack! ! encaps! <RETURN>@>] [square(3)]) stack!]@async_test1
23+
[square(3)]@square3
24+
[vm_eval(ROOT [ROOT<ARG0 decaps! stack! ! encaps! <RETURN>@>] [square3!]) stack!]@async_test1
2425

2526
[[]<@thunk @root @sig encaps(vm_continuation(encaps(sig) root thunk))>/]@continuation
2627
[[]<@continuation @arg vm_async(continuation arg)@thread>]@async
@@ -35,6 +36,8 @@
3536
stack!
3637
]@async_test7
3738

39+
[vm_eval(ROOT [ROOT<ARG0 decaps! stack! ! encaps! <RETURN>@>] [testimport3!]) stack!]@async_test8
40+
3841
[minus(1)]@decrement
3942

4043
[[[repl(get_stdin!)|]! repeat!]@repeat repeat!]/

extensions.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,7 @@ extern void vm_try(int exp) { if (exp) vm_throw(LTV_NULL); }
7474

7575
extern FILE *file_open(char *filename,char *opts) { return fopen(filename,opts); }
7676
extern void file_close(FILE *fp) { fclose(fp); }
77-
extern void pinglib(char *filename)
78-
{
77+
extern void pinglib(char *filename) {
7978
void *dlhandle=dlopen(filename,RTLD_LAZY | RTLD_GLOBAL | RTLD_NODELETE | RTLD_DEEPBIND);
8079
if (!dlhandle)
8180
fprintf(OUTFILE,"dlopen error: handle %x %s\n",dlhandle,dlerror());

jj.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,14 @@
3333
* not, see <http://www.gnu.org/licenses/>.
3434
*/
3535

36+
#include "reflect.h" // cif_init
3637
#include "vm.h"
3738

3839
const char *bootstrap=
3940
"[@input_stream [brl(input_stream) ! lambda!]@lambda lambda! |]@repl\n" // define repl
4041
"ROOT<repl(get_stdin())> [RETURN] ARG0 @"; // read from stdin
4142

42-
int main(int argc, char *argv[]) { return vm_bootstrap(argc>1?argv[1]:(char *) bootstrap); }
43+
int main(int argc, char *argv[]) {
44+
cif_init(1); // must dlopen NULL when running as executable
45+
return vm_bootstrap(argc > 1 ? argv[1] : (char *)bootstrap);
46+
}

jj_plugin.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* j2 - A simple concatenative programming language that can understand
3+
* the structure of and dynamically link with compatible C binaries.
4+
*
5+
* Copyright (C) 2011 Jason Nyberg <jasonnyberg@gmail.com>
6+
* Copyright (C) 2018 Jason Nyberg <jasonnyberg@gmail.com> (dual-licensed)
7+
* (C) Copyright 2019 Hewlett Packard Enterprise Development LP.
8+
*
9+
* This file is part of j2.
10+
*
11+
* This file is free software; you can redistribute it and/or modify
12+
* it under the terms of either
13+
*
14+
* * the GNU Lesser General Public License as published by the Free
15+
* Software Foundation; either version 3 of the License, or (at
16+
* your option) any later version
17+
*
18+
* or
19+
*
20+
* * the GNU General Public License as published by the Free
21+
* Software Foundation; either version 3 of the License, or (at
22+
* your option) any later version
23+
*
24+
* or both in parallel, as here.
25+
*
26+
* j2 is distributed in the hope that it will be useful, but
27+
* WITHOUT ANY WARRANTY; without even the implied warranty of
28+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29+
* General Public License for more details.
30+
*
31+
* You should have received copies of the GNU General Public License and
32+
* the GNU Lesser General Public License along with this program. If
33+
* not, see <http://www.gnu.org/licenses/>.
34+
*/
35+
36+
/*
37+
#include "vm.h"
38+
39+
const char *bootstrap=
40+
"[@input_stream [brl(input_stream) ! lambda!]@lambda lambda! |]@repl\n" // define repl
41+
"ROOT<repl(get_stdin())> [RETURN] ARG0 @"; // read from stdin
42+
43+
int main(int argc, char *argv[]) { return vm_bootstrap(argc>1?argv[1]:(char *) bootstrap); }
44+
*/
45+
46+
47+
#include <stdio.h>
48+
#include <dlfcn.h> // dlopen/dlsym/dlclose
49+
50+
const char *bootstrap =
51+
"[@input_stream [brl(input_stream) ! lambda!]@lambda lambda! |]@repl\n" // define repl
52+
"ROOT<repl(get_stdin())> [RETURN] ARG0 @";
53+
54+
int main(int argc, char *argv[]) {
55+
int status = 0;
56+
void *dlhandle = NULL;
57+
58+
dlerror(); // reset
59+
dlhandle = dlopen("libreflect.so", RTLD_LAZY | RTLD_GLOBAL | RTLD_NODELETE | RTLD_DEEPBIND);
60+
if (!dlhandle) {
61+
printf("dlopen libreflect.so failed, error %s\n", dlerror());
62+
goto done;
63+
}
64+
65+
dlerror(); // reset
66+
int *(*vm_bootstrap)(char *) = dlsym(dlhandle, "vm_bootstrap");
67+
if (vm_bootstrap) {
68+
vm_bootstrap(argc > 1 ? argv[1] : (char *) bootstrap);
69+
}
70+
71+
dlclose(dlhandle);
72+
done:
73+
return status;
74+
}
75+

makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ SHELL:=bash
66

77
all: compile
88

9+
# makefile version of reflection-as-plugin demo
10+
jj: jj_plugin.c ; gcc -g jj_plugin.c -o jj -ldl
11+
912
switch-compiler:; sudo update-alternatives --config c++
1013
build:; mkdir build
1114
cmake: build; cd build && cmake ..

reflect.c

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -61,18 +61,17 @@ static int cif_curate_module(LTV *module, int bootstrap);
6161

6262
LTV *cif_module = NULL; // initialized/populated during bootstrap
6363

64-
__attribute__((constructor))
65-
static void init(void)
66-
{
67-
Dl_info dl_info;
68-
dladdr((void *)init, &dl_info);
69-
fprintf(ERRFILE,CODE_RED "reflection module path is: %s" CODE_RESET "\n",dl_info.dli_fname);
70-
cif_module=LTV_init(NEW(LTV),(char *) dl_info.dli_fname,strlen(dl_info.dli_fname),LT_DUP|LT_RO);
71-
try_depth=1;
72-
cif_preview_module(cif_module);
73-
74-
print_ltv(ERRFILE,CODE_RED,cif_module,CODE_RESET "\n",0);
75-
cif_curate_module(cif_module,true);
64+
void cif_init(int bootstrap) {
65+
if (!cif_module) {
66+
Dl_info dl_info;
67+
dladdr((void *)cif_init, &dl_info);
68+
fprintf(ERRFILE, CODE_RED "reflection module path is: %s" CODE_RESET "\n", dl_info.dli_fname);
69+
cif_module = LTV_init(NEW(LTV), (char *)dl_info.dli_fname, strlen(dl_info.dli_fname), LT_DUP | LT_RO);
70+
cif_preview_module(cif_module);
71+
72+
print_ltv(ERRFILE, CODE_RED, cif_module, CODE_RESET "\n", 0);
73+
cif_curate_module(cif_module, bootstrap);
74+
}
7675
}
7776

7877
char *Type_pushUVAL(TYPE_UVALUE *uval,char *buf);
@@ -1588,7 +1587,7 @@ int cif_curate_module(LTV *module,int bootstrap)
15881587

15891588
int resolve_symbols(char *filename) {
15901589
char *f=bootstrap?NULL:filename;
1591-
if (!(dlhandle=dlopen(f,RTLD_LAZY | RTLD_GLOBAL | RTLD_NODELETE | RTLD_DEEPBIND)))
1590+
if (!(dlhandle = dlopen(f, RTLD_LAZY | RTLD_GLOBAL | RTLD_NODELETE | RTLD_DEEPBIND)))
15921591
fprintf(OUTFILE,"failed while dlopen'ing %s; continuing without resolving global functions/variables\n",dlerror());
15931592

15941593
STRY(ltv_traverse(index[1],resolve_types,resolve_types)!=NULL,"linking symbolic type info names"); // links symbols on pre- and post-passes

reflect.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ typedef struct
182182

183183
extern LTV *cif_module;
184184

185+
void cif_init(int bootstrap);
186+
185187
extern LTV *cif_create_cvar(LTV *type,void *data,char *member);
186188
extern LTV *cif_assign_cvar(LTV *cvar,LTV *ltv);
187189
extern int cif_print_cvar(FILE *ofile,LTV *ltv,int depth);

util.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ __thread FILE *ERRFILE_VAR=NULL;
4848

4949
int Gmymalloc=0;
5050

51-
int try_depth=-1;
51+
int try_depth=0;
5252
int try_loglev=2;
5353
int try_infolev=1;
5454
int try_edepth=2;
@@ -84,9 +84,9 @@ void try_loginfo(const char *func,const char *cond)
8484
memset(logstr,' ',TRY_STRLEN);
8585
switch (try_infolev)
8686
{
87-
case 3: snprintf(logstr+indent,TRY_STRLEN,"%s:%s:" CODE_UL "Finished %s",func,cond,try_context.msgstr); break;
88-
case 2: snprintf(logstr+indent,TRY_STRLEN,"%s:" CODE_UL "Finished %s",func,try_context.msgstr); break;
89-
case 1: snprintf(logstr+indent,TRY_STRLEN,"Finished %s",try_context.msgstr); break;
87+
case 3: snprintf(logstr+indent,TRY_STRLEN,"%s:%s:" CODE_UL "%s",func,cond,try_context.msgstr); break;
88+
case 2: snprintf(logstr+indent,TRY_STRLEN,"%s:" CODE_UL "%s",func,try_context.msgstr); break;
89+
case 1: snprintf(logstr+indent,TRY_STRLEN,"%s",try_context.msgstr); break;
9090
case 0: snprintf(logstr+indent,TRY_STRLEN,"%s",""); break;
9191
}
9292

@@ -99,9 +99,9 @@ void try_logerror(const char *func,const char *cond,int status)
9999
char errstr[TRY_STRLEN];
100100
switch (try_loglev)
101101
{
102-
case 3: snprintf(errstr,TRY_STRLEN,"%s:%s:Failed while %s",func,cond,try_context.msgstr); break;
103-
case 2: snprintf(errstr,TRY_STRLEN,"%s:Failed while %s",func,try_context.msgstr); break;
104-
case 1: snprintf(errstr,TRY_STRLEN,"Failed while %s",try_context.msgstr); break;
102+
case 3: snprintf(errstr,TRY_STRLEN,"%s:%s:Failed to %s",func,cond,try_context.msgstr); break;
103+
case 2: snprintf(errstr,TRY_STRLEN,"%s:Failed to %s",func,try_context.msgstr); break;
104+
case 1: snprintf(errstr,TRY_STRLEN,"Failed to %s",try_context.msgstr); break;
105105
case 0: snprintf(errstr,TRY_STRLEN,"%s",""); break;
106106
}
107107

vm.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -89,19 +89,21 @@ typedef struct {
8989
unsigned skipdepth;
9090
} VM_ENV;
9191

92-
__thread LTV *vm_env_stack=NULL; // every thread can have a stack of vm_environments (supports interpreter->C->interpreter->C...
9392
__thread VM_ENV *vm_env=NULL; // every thread can have an active vm environment
9493

9594
static LTV *vm_ltv_container=NULL; // holds LTVs we don't want garbage-collected
9695
static LTV *fun_pop_bc=NULL;
9796

9897
__attribute__((constructor))
99-
static void init(void)
100-
{
101-
VM_CMD fun_pop_asm[] = {{VMOP_FUN_POP}};
102-
vm_ltv_container=LTV_NULL_LIST;
103-
fun_pop_bc=compile(jit_asm,fun_pop_asm,1);
104-
LTV_put(LTV_list(vm_ltv_container),fun_pop_bc,HEAD,NULL);
98+
static void init(void) {
99+
static int initialized = 0;
100+
if (!initialized) {
101+
VM_CMD fun_pop_asm[] = {{VMOP_FUN_POP}};
102+
vm_ltv_container = LTV_NULL_LIST;
103+
fun_pop_bc = compile(jit_asm, fun_pop_asm, 1);
104+
LTV_put(LTV_list(vm_ltv_container), fun_pop_bc, HEAD, NULL);
105+
initialized++;
106+
}
105107
}
106108

107109

@@ -685,8 +687,7 @@ static void vm_closure_thunk(ffi_cif *CIF,void *RET,void **ARGS,void *USER_DATA)
685687
int status=0;
686688
char *argid=NULL;
687689

688-
if (!vm_env_stack)
689-
vm_env_stack=LTV_NULL_LIST;
690+
LTV *vm_env_stack = LTV_NULL_LIST;
690691

691692
LTV *continuation=(LTV *) USER_DATA;
692693

@@ -765,7 +766,7 @@ extern LTV *vm_eval(LTV *root,LTV *code,LTV *arg) {
765766
}
766767

767768
extern int vm_bootstrap(char *bootstrap) {
768-
try_depth=0;
769+
cif_init(0); // must dlopen as lib name when running from library
769770
LTV *rval=vm_eval(cif_module,LTV_init(NEW(LTV),bootstrap,-1,LT_NONE),LTV_NULL);
770771
if (rval)
771772
print_ltv(OUTFILE,"",rval,"\n",0);

0 commit comments

Comments
 (0)