From a1837d94013cdd948efbf4f11a6aa5314da8b456 Mon Sep 17 00:00:00 2001 From: Sol Boucher Date: Fri, 8 Mar 2019 03:28:54 -0500 Subject: [PATCH 1/7] Start work on a collection of demo executables and dynamic libraries This currently demonstrates: * dynamic bindings between a binary and a library (bin_other) * static bindings within a binary (bin_self) * dynamic bindings between one library and another (lib_other.so) * dynamic bindings within a library (lib_self.so) --- .gitignore | 7 +++++++ Makefile | 31 +++++++++++++++++++++++++++++++ decls.c | 17 +++++++++++++++++ defns.c | 14 ++++++++++++++ 4 files changed, 69 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 decls.c create mode 100644 defns.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..45de0dc --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +/*_other +/*_self + +*_other.s +*_self.c +*.o +*.so diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f700116 --- /dev/null +++ b/Makefile @@ -0,0 +1,31 @@ +LN := ln -s + +override CFLAGS := -std=c99 -O2 -Wall -Wextra -Wpedantic $(CFLAGS) +override LDFLAGS := -Wl,-R\$$ORIGIN $(LDFLAGS) +override LDLIBS := decls.c $(LDLIBS) + +ALL := bin_other bin_self lib_other.so lib_self.so + +.PHONY: all +all: $(ALL) + +bin_other: lib_self.so +lib_other.so: lib_self.so + +%_other.s: + $(LN) /dev/null $@ + +%_self.c: defns.c + $(LN) $< $@ + +lib%.so: lib%.o + $(CC) $(LDFLAGS) -shared -fpic -o $@ $^ $(LDLIBS) + +.PHONY: distclean +distclean: clean + $(RM) $(shell sed -n 's/\///p' .gitignore) *.so + +.PHONY: clean +clean: + $(RM) *.o + find . -maxdepth 1 -type l -exec $(RM) {} \; diff --git a/decls.c b/decls.c new file mode 100644 index 0000000..732678b --- /dev/null +++ b/decls.c @@ -0,0 +1,17 @@ +#include + +extern const bool global_rodata; +extern bool global_data; +extern bool global_bss; + +void code_direct(void); +void code_indirect(void); + +int main(void) { + code_direct(); + + void (*volatile addr)(void); + (addr = code_indirect)(); + + return global_rodata ^ global_data ^ global_bss; +} diff --git a/defns.c b/defns.c new file mode 100644 index 0000000..58d839f --- /dev/null +++ b/defns.c @@ -0,0 +1,14 @@ +#include +#include + +const bool global_rodata = true; +bool global_data = true; +bool global_bss; + +void code_direct(void) { + puts(__FILE__ ":code_direct()"); +} + +void code_indirect(void) { + puts(__FILE__ ":code_indirect()"); +} From 6d82df8b737571edd87c0a4fb17a2f947613dc78 Mon Sep 17 00:00:00 2001 From: Sol Boucher Date: Fri, 8 Mar 2019 03:41:30 -0500 Subject: [PATCH 2/7] Support generating filtered and sorted dynamic relocation and symbol table listings for comparison --- .gitignore | 2 ++ Makefile | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 45de0dc..f504925 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,6 @@ *_other.s *_self.c *.o +*.R *.so +*.T diff --git a/Makefile b/Makefile index f700116..18298ce 100644 --- a/Makefile +++ b/Makefile @@ -4,11 +4,20 @@ override CFLAGS := -std=c99 -O2 -Wall -Wextra -Wpedantic $(CFLAGS) override LDFLAGS := -Wl,-R\$$ORIGIN $(LDFLAGS) override LDLIBS := decls.c $(LDLIBS) +override GREPFLAGS := '\<[a-z]\+_[a-z]\+\>\S*$$' $(GREPFLAGS) +override SORTFLAGS := -k2 $(SORTFLAGS) + ALL := bin_other bin_self lib_other.so lib_self.so .PHONY: all all: $(ALL) +.PHONY: r +r: $(ALL:=.R) + +.PHONY: t +t: $(ALL:=.T) + bin_other: lib_self.so lib_other.so: lib_self.so @@ -21,11 +30,17 @@ lib_other.so: lib_self.so lib%.so: lib%.o $(CC) $(LDFLAGS) -shared -fpic -o $@ $^ $(LDLIBS) +%.R: % + objdump -R $< | grep $(GREPFLAGS) | sort $(SORTFLAGS) >$@ + +%.T: % + objdump -T $< | grep $(GREPFLAGS) | sort $(SORTFLAGS) >$@ + .PHONY: distclean distclean: clean $(RM) $(shell sed -n 's/\///p' .gitignore) *.so .PHONY: clean clean: - $(RM) *.o + $(RM) *.o *.R *.T find . -maxdepth 1 -type l -exec $(RM) {} \; From 589b0906923c9287ee49635d2479732ba4f6dc1d Mon Sep 17 00:00:00 2001 From: Sol Boucher Date: Fri, 8 Mar 2019 03:44:49 -0500 Subject: [PATCH 3/7] Makefile: support building an executable without COPY relocations This demonstrates how GLOB_DAT relocations can fill the same role in non--position-independent executables that still contain position-independent code. --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 18298ce..47d1e51 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ override LDLIBS := decls.c $(LDLIBS) override GREPFLAGS := '\<[a-z]\+_[a-z]\+\>\S*$$' $(GREPFLAGS) override SORTFLAGS := -k2 $(SORTFLAGS) -ALL := bin_other bin_self lib_other.so lib_self.so +ALL := bin_other pic_other bin_self lib_other.so lib_self.so .PHONY: all all: $(ALL) @@ -21,6 +21,9 @@ t: $(ALL:=.T) bin_other: lib_self.so lib_other.so: lib_self.so +pic_other: lib_self.so +pic_other: private LDFLAGS += -fpic + %_other.s: $(LN) /dev/null $@ From e1ea3db482378f162d292b5e50c7e886b5c2f002 Mon Sep 17 00:00:00 2001 From: Sol Boucher Date: Fri, 8 Mar 2019 03:47:51 -0500 Subject: [PATCH 4/7] Support building test executables for running code in the dynamic libraries These can be used e.g. to verify that symbol resolution occurs in the expected order. --- .gitignore | 1 + Makefile | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index f504925..e2a2df1 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ *.R *.so *.T +load_*.s diff --git a/Makefile b/Makefile index 47d1e51..2efb31b 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,8 @@ LN := ln -s override CFLAGS := -std=c99 -O2 -Wall -Wextra -Wpedantic $(CFLAGS) override LDFLAGS := -Wl,-R\$$ORIGIN $(LDFLAGS) -override LDLIBS := decls.c $(LDLIBS) + LDLIBS_ := $(LDLIBS) +override LDLIBS = $(if $(filter load_%,$@),,decls.c) $(LDLIBS_) override GREPFLAGS := '\<[a-z]\+_[a-z]\+\>\S*$$' $(GREPFLAGS) override SORTFLAGS := -k2 $(SORTFLAGS) @@ -18,18 +19,27 @@ r: $(ALL:=.R) .PHONY: t t: $(ALL:=.T) +.PHONY: load +load: load_other load_self + bin_other: lib_self.so lib_other.so: lib_self.so pic_other: lib_self.so pic_other: private LDFLAGS += -fpic +load_other: load_other.s lib_other.so +load_self: load_self.s lib_self.so + %_other.s: $(LN) /dev/null $@ %_self.c: defns.c $(LN) $< $@ +load_%.s: + $(LN) /dev/null $@ + lib%.so: lib%.o $(CC) $(LDFLAGS) -shared -fpic -o $@ $^ $(LDLIBS) From ed871b2c394b561f759163cd693705d186d68487 Mon Sep 17 00:00:00 2001 From: Sol Boucher Date: Fri, 8 Mar 2019 04:03:52 -0500 Subject: [PATCH 5/7] Generate executables and shared libraries that interpose their dependencies' symbols --- .gitignore | 2 ++ Makefile | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index e2a2df1..6dbf437 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ +/*_interpose /*_other /*_self +*_interpose.c *_other.s *_self.c *.o diff --git a/Makefile b/Makefile index 2efb31b..4503b8e 100644 --- a/Makefile +++ b/Makefile @@ -3,12 +3,12 @@ LN := ln -s override CFLAGS := -std=c99 -O2 -Wall -Wextra -Wpedantic $(CFLAGS) override LDFLAGS := -Wl,-R\$$ORIGIN $(LDFLAGS) LDLIBS_ := $(LDLIBS) -override LDLIBS = $(if $(filter load_%,$@),,decls.c) $(LDLIBS_) +override LDLIBS = $(if $(filter %_interpose %_interpose.so load_%,$@),,decls.c) $(LDLIBS_) override GREPFLAGS := '\<[a-z]\+_[a-z]\+\>\S*$$' $(GREPFLAGS) override SORTFLAGS := -k2 $(SORTFLAGS) -ALL := bin_other pic_other bin_self lib_other.so lib_self.so +ALL := bin_other pic_other bin_self bin_interpose lib_other.so lib_self.so lib_interpose.so .PHONY: all all: $(ALL) @@ -20,7 +20,7 @@ r: $(ALL:=.R) t: $(ALL:=.T) .PHONY: load -load: load_other load_self +load: load_other load_self load_interpose bin_other: lib_self.so lib_other.so: lib_self.so @@ -28,8 +28,14 @@ lib_other.so: lib_self.so pic_other: lib_self.so pic_other: private LDFLAGS += -fpic +bin_interpose: lib_self.so +lib_interpose.so: lib_self.so +lib_interpose.so: private LDFLAGS += -umain + load_other: load_other.s lib_other.so load_self: load_self.s lib_self.so +load_interpose: load_interpose.s lib_interpose.so +load_interpose: private LDFLAGS += -Wl,--unresolved-symbols=ignore-all %_other.s: $(LN) /dev/null $@ @@ -37,6 +43,9 @@ load_self: load_self.s lib_self.so %_self.c: defns.c $(LN) $< $@ +%_interpose.c: defns.c + $(LN) $< $@ + load_%.s: $(LN) /dev/null $@ From f76ad6bdc28d022427d894e7e2456e98f32e1940 Mon Sep 17 00:00:00 2001 From: Sol Boucher Date: Fri, 8 Mar 2019 05:28:00 -0500 Subject: [PATCH 6/7] Have main() print the containing object file to make the semantics of interposition clearer --- Makefile | 2 +- decls.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4503b8e..8a287a2 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ LN := ln -s override CFLAGS := -std=c99 -O2 -Wall -Wextra -Wpedantic $(CFLAGS) override LDFLAGS := -Wl,-R\$$ORIGIN $(LDFLAGS) LDLIBS_ := $(LDLIBS) -override LDLIBS = $(if $(filter %_interpose %_interpose.so load_%,$@),,decls.c) $(LDLIBS_) +override LDLIBS = $(if $(filter %_interpose %_interpose.so load_%,$@),,decls.c -ldl) $(LDLIBS_) override GREPFLAGS := '\<[a-z]\+_[a-z]\+\>\S*$$' $(GREPFLAGS) override SORTFLAGS := -k2 $(SORTFLAGS) diff --git a/decls.c b/decls.c index 732678b..aa28576 100644 --- a/decls.c +++ b/decls.c @@ -1,4 +1,8 @@ +#include +#include #include +#include +#include extern const bool global_rodata; extern bool global_data; @@ -7,7 +11,18 @@ extern bool global_bss; void code_direct(void); void code_indirect(void); +static inline const char *objname(void) { + const struct link_map *l; + for(l = dlopen(NULL, RTLD_LAZY); l->l_ld != _DYNAMIC; l = l->l_next) + assert(l); + + extern const char *const __progname; + return *l->l_name ? strrchr(l->l_name, '/') + 1 : __progname; +} + int main(void) { + printf("%s:main()\n", objname()); + code_direct(); void (*volatile addr)(void); From 8c05813db7614f12da83468b08a618899e27a98b Mon Sep 17 00:00:00 2001 From: Sol Boucher Date: Fri, 15 Mar 2019 18:30:31 -0400 Subject: [PATCH 7/7] tls: Subdirectory with demos of all four TLS models --- tls/Makefile | 44 ++++++++++++++++++++++++++++++++++++++++++++ tls/entry.c | 18 ++++++++++++++++++ tls/local.c | 16 ++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 tls/Makefile create mode 100644 tls/entry.c create mode 100644 tls/local.c diff --git a/tls/Makefile b/tls/Makefile new file mode 100644 index 0000000..01f9677 --- /dev/null +++ b/tls/Makefile @@ -0,0 +1,44 @@ +LN := ln -s + +override ASFLAGS := $(ASFLAGS) + CFLAGS_ := $(CFLAGS) +override CFLAGS = -std=c99 -O2 -Wall -Wextra -Wpedantic $(if $(filter lib%.o,$@),-fpic) $(CFLAGS_) +override CPPFLAGS := $(CPPFLAGS) +override LDFLAGS := -Wl,-R\$$ORIGIN $(LDFLAGS) +override LDLIBS := $(LDLIBS) + +ALL := tls_local_exec tls_initial_exec tls_local_dynamic tls_global_dynamic + +.PHONY: all +all: $(ALL) + +tls_local_exec: liblocal_exec.o +liblocal_exec.so: +libinitial_exec.so: libinitial_exec.o +liblocal_dynamic.so: liblocal_dynamic.o +libglobal_dynamic.so: libglobal_dynamic.o + +libinitial_exec.o: private CFLAGS += -ftls-model=initial-exec +libglobal_dynamic.o: private CPPFLAGS += -Dglobal + +entry.o: private CPPFLAGS += -D_GNU_SOURCE + +empty.s: + $(LN) /dev/null $@ + +.PHONY: distclean +distclean: clean + $(RM) $(ALL) *.so + +.PHONY: clean +clean: + $(RM) *.o empty.s + +lib%.c: local.c + $(LN) $< $@ + +lib%.so: entry.o + $(CC) $(LDFLAGS) -shared -fpic -o $@ $^ $(LDLIBS) -ldl + +tls_%: empty.o lib%.so + $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) diff --git a/tls/entry.c b/tls/entry.c new file mode 100644 index 0000000..38388de --- /dev/null +++ b/tls/entry.c @@ -0,0 +1,18 @@ +#include +#include +#include +#include + +bool local_location(bool **, bool **); + +int main(int argc, char **argv) { + bool *data, *bss; + local_location(&data, &bss); + printf("l %2d d %#lx b %#lx\n", argc - 1, (uintptr_t) data, (uintptr_t) bss); + + void *l = dlmopen(LM_ID_NEWLM, argv[0], RTLD_LAZY); + int (*m)(int, char **) = (int (*)(int, char **)) (uintptr_t) dlsym(l, "main"); + m(argc + 1, argv); + + return 0; +} diff --git a/tls/local.c b/tls/local.c new file mode 100644 index 0000000..cde85f7 --- /dev/null +++ b/tls/local.c @@ -0,0 +1,16 @@ +#include + +#ifdef global +#undef global +#define thread_local __thread +#else +#define thread_local static __thread +#endif + +thread_local bool local_data = true; +thread_local bool local_bss; + +void local_location(bool **data, bool **bss) { + *data = &local_data; + *bss = &local_bss; +}