Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JIT compiler + bugfixes #66

Open
wants to merge 219 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
219 commits
Select commit Hold shift + click to select a range
5dee334
Add support for checking unresolved symbols and reporting back all lo…
invalid-email-address Sep 27, 2022
99fa53d
Add JIT compiler and test cases
invalid-email-address Nov 2, 2022
d9e02ae
Add support for deduplicating type descriptors by relocating code to …
invalid-email-address Sep 22, 2022
b6f56cf
Fix implementation of replacing local package names with import paths…
invalid-email-address Sep 25, 2022
3aa05b7
RODATA is where type descriptors will be - we should load these too
invalid-email-address Sep 27, 2022
f6f93d7
Don't add to the package list if the only thing included is the init …
invalid-email-address Sep 29, 2022
b5a35af
Improve error
invalid-email-address Oct 7, 2022
9d192e7
Split previously pclntab into separate tables (as done in runtime) to…
invalid-email-address Oct 7, 2022
8ea84f6
Fix bug with deferred returns not being added due to pointer equality…
invalid-email-address Oct 7, 2022
779b105
Add support for ASM function wrappers (ABIInternal -> ABI0) and retur…
invalid-email-address Oct 7, 2022
63fd6dc
Add support for loading native archive entries (e.g. CGo DNS resolution)
invalid-email-address Nov 2, 2022
a6eb4dd
Add patch of first module's itabs to relocate unreachable methods to …
invalid-email-address Nov 2, 2022
958a899
Fix occasional error "go.info.runtime.itabTable: relocation target go…
invalid-email-address Nov 7, 2022
d9a3941
Add proper TLS resolution for externally linked binaries
invalid-email-address Nov 9, 2022
2449b31
Bugfix type registration and improve deduplication (not all pointer t…
invalid-email-address Nov 12, 2022
93daf95
Make mprotect readonly by default, and add MprotectMakeExecutable
invalid-email-address Nov 14, 2022
7109fd4
Add reflectlite - a stripped back version of reflect package (with ed…
invalid-email-address Nov 14, 2022
32cdf40
Make string container configurable per linker/module, and add option …
invalid-email-address Nov 14, 2022
c1c6f72
Add go binary config to jit
invalid-email-address Nov 15, 2022
33fc193
Make TestJITHttpGet more reliable by ensuring idle connection handlin…
invalid-email-address Nov 15, 2022
1a68b1c
Prevent infinite recursion in reflectlite
invalid-email-address Nov 16, 2022
c2f190e
Bugfix JIT - incorrect package names preventing init funcs from running
invalid-email-address Nov 16, 2022
150be90
Expose parsed files in LoadableUnit, and unload data on error during …
invalid-email-address Nov 17, 2022
07aaa6b
Fix firstmodule itab patching to be safely reversible, and assorted o…
invalid-email-address Nov 18, 2022
4d9b7e9
Don't try to open executable as ELF on darwin
invalid-email-address Nov 19, 2022
e68225e
Make symbol order in linker deterministic to help reproduce linker bu…
invalid-email-address Nov 22, 2022
a493847
Add test for open coded defers - currently fails if linker symbol ord…
invalid-email-address Nov 23, 2022
86ff306
Fix clobbered arm64 ADRP relocations during type deduplication
invalid-email-address Nov 25, 2022
0fe15e4
WIP - mmap manager + implement faster version of vmmap via Cgo
invalid-email-address Nov 24, 2022
c109f0a
Add lookup for CGo symbols from //go:cgo_import_dynamic pragma on Darwin
invalid-email-address Nov 27, 2022
0be2497
Add binary self-patch for darwin to allow read only Mach-O segments t…
invalid-email-address Nov 27, 2022
69eb7a8
Make libc work for all architectures, and support without CGo
invalid-email-address Nov 27, 2022
e358723
Use the non-default tls.Config in http test to prevent contaminating …
invalid-email-address Nov 27, 2022
842dbe1
Add build tag to disable darwin patch and skip CGo test on darwin + a…
invalid-email-address Nov 27, 2022
6d2c0c9
Implement darwin vmmap fallback when Cgo is disabled
invalid-email-address Nov 28, 2022
27e167f
Fixes for darwin/arm64
invalid-email-address Nov 28, 2022
1f4d84f
Fix incorrect execve args for darwin
invalid-email-address Nov 29, 2022
f3882ef
Expose buildEnv in jit tests
invalid-email-address Nov 29, 2022
6aacb38
Add problem test for linux/arm64
invalid-email-address Nov 29, 2022
2a3bf42
Word align data symbols for arm64
invalid-email-address Nov 29, 2022
e3a28da
unused import
invalid-email-address Nov 30, 2022
5541b09
Copy + Sign + Replace patched executable mach-o file for darwin/arm64…
invalid-email-address Nov 30, 2022
af5853c
Fix type conversion to support method closures (kinda)
invalid-email-address Dec 1, 2022
24dd6c3
Make test fail
invalid-email-address Dec 1, 2022
f551a99
Make inter-module function conversion even more dangerous
invalid-email-address Dec 2, 2022
a07f62e
Oops
invalid-email-address Dec 2, 2022
ff25308
Fix ADRP idempotency
invalid-email-address Dec 3, 2022
fa837ea
arm64 BL instruction clobbers X30 (link register) - use B instead
invalid-email-address Dec 5, 2022
50987ec
Avoid any writes to executable code on darwin/arm64
invalid-email-address Dec 5, 2022
de3a882
Adjust placeholder native object code copy to avoid invalid slice on …
invalid-email-address Dec 5, 2022
8acd87d
Add JIT example to README.md
invalid-email-address Dec 5, 2022
2d45388
Don't free errors provided by libdl, and do register CGo symbols on o…
invalid-email-address Dec 6, 2022
e8f31d8
Actually implement ELF relocations for amd64 and arm64
invalid-email-address Dec 6, 2022
bcffcc4
Stabilise some tests and commit relocation/deduplication debug writer
invalid-email-address Dec 8, 2022
9f203ad
Get x86 Mach-O relocations working
invalid-email-address Dec 8, 2022
f81ab11
arm64 mach-o relocs
invalid-email-address Dec 8, 2022
f5fac0e
Improve UnresolvedExternalSymbols by describing what uses the symbol
invalid-email-address Dec 8, 2022
6595a94
Fix deduplication debug logger
invalid-email-address Dec 9, 2022
b42e180
Experiment - try adding a relocation epilogue to every function which…
invalid-email-address Dec 9, 2022
1302235
Put R_CALL back
invalid-email-address Dec 9, 2022
abdbe55
Try word aligning arm64 call epilogues
invalid-email-address Dec 9, 2022
b3a9583
Backup PCREL instructions 2 bytes before the actual reloc
invalid-email-address Dec 10, 2022
cb4aaf9
Adjust alignment of functions and epilogues
invalid-email-address Dec 10, 2022
2a931f5
Try making darwin arm64 mmapper more fussy about address hints
invalid-email-address Dec 10, 2022
35d15bf
Reduce number of syscalls when patching itabs
invalid-email-address Dec 11, 2022
a5d1e36
Bugfix arm64 asm - use X17 (IP1 - intra-procedure-call corruptible re…
invalid-email-address Dec 12, 2022
e8de539
Simplify ADRP reloc code thanks to bidi linkless branch
invalid-email-address Dec 13, 2022
a9f5e94
Bugfix linux/arm64 - need to flush instruction cache after relocation…
invalid-email-address Dec 13, 2022
5c991af
Missing brackets
invalid-email-address Dec 13, 2022
6fe97a8
Experiment - rewrite PCREL relocation implementation to use shorter a…
invalid-email-address Dec 14, 2022
5333f4e
Don't align code on 8 byte boundaries unnecessarily for x86 (save som…
invalid-email-address Dec 14, 2022
e476794
Add missing NOFRAME to mmap_linux_arm64.s read_CTR_ELO_Register()
invalid-email-address Dec 14, 2022
679486b
Fix accidental itab lock copy
invalid-email-address Dec 20, 2022
d2eab40
Bump go.mod to 1.9 for MacOS
invalid-email-address Dec 21, 2022
844d352
Add SkipTypeDeduplicationForPackages linker option and make JIT copy …
invalid-email-address Dec 23, 2022
c3734ae
fix copy symlink resolution
invalid-email-address Jan 11, 2023
c6c6095
Add more granular control over whether to use duplicate symbols or fi…
invalid-email-address Jan 11, 2023
a9377e2
Improve type conversion for interface{} nested values
invalid-email-address Jan 11, 2023
07f6477
Add missing case for converting eface
invalid-email-address Jan 28, 2023
136cd6e
WIP - mmap manager and mprotect for Windows
invalid-email-address Jan 11, 2023
abb7ff0
Simplify by using VirtualQueryEx across the entire address space, and…
invalid-email-address Jan 30, 2023
c6a75f3
fix #68 adapter golang 1.20
pkujhd Feb 2, 2023
ac161f3
Edit readme
invalid-email-address Feb 13, 2023
e0dbc39
Hard fork due to difficulty in collaboration
invalid-email-address Mar 7, 2023
763e00f
Import paths varint encoded
invalid-email-address Mar 7, 2023
b57d4df
Expose module mapped addresses to allow users to know whether a type …
invalid-email-address Mar 7, 2023
6021434
Add support for R_ARM_PCREL_LDST relocs in Go 1.20 (porting https://g…
invalid-email-address Mar 8, 2023
8a36682
Register libresolv_* Cgo symbols on darwin
invalid-email-address Mar 8, 2023
a9a20e8
Bake in syscall.syscall9 on darwin on Go 1.20
invalid-email-address Mar 8, 2023
51aa958
delete useless code. typemap already is filled in buildModule
pkujhd Nov 4, 2022
d72b1e6
Update README.md
pkujhd Nov 4, 2022
e6c4bda
delete useless code
pkujhd Nov 5, 2022
d887dcf
Merge branch 'master' into jit
eh-steve Mar 8, 2023
b10260b
Merge pull request #1 from eh-steve/jit
eh-steve Mar 8, 2023
06a14a6
Bump JIT go.mod after hard fork
invalid-email-address Mar 14, 2023
7cdeb31
Bake in a bit more of reflect
invalid-email-address Mar 19, 2023
ea4b10e
Revert fed0a9e753219949a4bb1e6b5a6e5a3a99dffc7e as it was simply mask…
invalid-email-address Mar 19, 2023
e743844
Merge pull request #2 from eh-steve/bugfix-gcdata-revert-fed0a9e
eh-steve Mar 19, 2023
4b1a4ec
Type deduplication safety improvements (#3)
eh-steve Apr 16, 2023
25375e9
Add bakeInPlatform() for OS/arch specific things
invalid-email-address Apr 20, 2023
66e5836
Bump jit go.mod
invalid-email-address Apr 20, 2023
c82e80d
WIP - assuming gc is patched to emit types for exported functions, bu…
invalid-email-address Apr 16, 2023
ee664f0
Add PatchGC() function and simplify JIT builds (no copy)
invalid-email-address Apr 18, 2023
8a2f6fc
Always use heap strings (remove config) - required bugfix of epilogue…
invalid-email-address Apr 18, 2023
e17d43b
Bake in a few more types
invalid-email-address Apr 21, 2023
bcfdfc6
Make patch allow moves across unix filesystem boundaries
invalid-email-address Apr 21, 2023
560857f
Store ·f function containers in CodeModule.Syms for use in inter-modu…
invalid-email-address Apr 21, 2023
efaa543
Add some GCs to TestJitComplexFunctions in case a JIT net poll is sti…
invalid-email-address Apr 21, 2023
926232c
Add CLI tool for gc patching (easier to run via sudo)
invalid-email-address Apr 21, 2023
8731517
Try removing replaces
invalid-email-address Apr 21, 2023
672a667
Update error message
invalid-email-address Apr 21, 2023
3d651de
Update README.md
invalid-email-address Apr 21, 2023
080c0ac
Delete goloader examples
invalid-email-address Apr 21, 2023
25bb7ea
Delete old compatibility files for now unsupported Go versions
invalid-email-address Apr 21, 2023
77f01ac
Bump go.mod/go.sum
invalid-email-address Apr 21, 2023
9fbc78a
Improve error messages + make sure type deduplication relocation erro…
invalid-email-address Apr 24, 2023
ced9de2
Update go.yml
eh-steve Apr 24, 2023
92bfb52
Bump go.mod
invalid-email-address Apr 24, 2023
ecab11a
Bump go.mod
invalid-email-address Apr 24, 2023
0a3825b
Fucking windows...
invalid-email-address Apr 25, 2023
3d64ae6
Bump go.mod again
invalid-email-address Apr 25, 2023
e6e91a8
Bump go.mod again
invalid-email-address Apr 25, 2023
85442ab
Force building of packages for named (resolved) symbols but whose pkg…
invalid-email-address Apr 26, 2023
c05fb81
Bump go.mod
invalid-email-address Apr 26, 2023
fb86c80
Update http tests
invalid-email-address Apr 26, 2023
1e357ef
Fix another type registration bug
invalid-email-address May 22, 2023
0173934
Simplify registerType(), and use the exact same recursive approach fo…
invalid-email-address May 27, 2023
35590ba
Bugfix inlinetree - attempt to use inlined func's funcID, otherwise a…
invalid-email-address May 27, 2023
9a06e95
Properly add both types of ABI wrapper funcs with the correct abi0 or…
invalid-email-address May 27, 2023
834f6b1
itab.go - rebase ifn/tfn offsets according to whether the type is in …
invalid-email-address May 27, 2023
3e97478
Always pointer align data as even on amd64, certain bulk memmove oper…
invalid-email-address May 27, 2023
1e3f4c9
Expose linker.Autolib()
invalid-email-address May 27, 2023
8be239b
Bugfix addSymbolMap() where duplicate functions would always point fi…
invalid-email-address May 27, 2023
31f0674
Rudimentary reachability analysis/deadcode elimination.
invalid-email-address May 27, 2023
59ea6e9
JIT - remove forbidden packages (this was previously a problem becaus…
invalid-email-address May 27, 2023
560bf48
Bump go.mod
invalid-email-address May 27, 2023
272ab53
Skip k8s tests according to go version
invalid-email-address May 27, 2023
215ee69
Placeholder func for PE relocs
invalid-email-address May 27, 2023
fc5c53c
Fix libc_error symbol lookup
invalid-email-address May 27, 2023
46b12e8
Add CGO_ENABLED={0,1} to workflow matrix
invalid-email-address May 27, 2023
702420f
darwin/arm64 requires CGO
invalid-email-address May 27, 2023
dbafe91
Share build env
invalid-email-address May 27, 2023
c8664c3
Bugfix use of copy2Slice instead of putAddress
invalid-email-address May 29, 2023
2dfa21a
Update jit/jit.go
eh-steve May 29, 2023
9ca6ff1
Add -dynlink by default and add support for R_GOTPCREL and R_TLS_IE (…
invalid-email-address May 30, 2023
1b34eb1
Make issue 78 test demonstrate the problem with PCREL MOVs implemente…
invalid-email-address May 30, 2023
d8a08b5
Multiple fixes:
invalid-email-address May 31, 2023
db5e251
Bump go.mod
invalid-email-address May 31, 2023
fa7ee6a
Express arm epilogue sizes in terms of asm sizes and add reloctype R_…
invalid-email-address May 31, 2023
c198962
Add another test case for issue #77
invalid-email-address May 31, 2023
23ada92
Fix R_TLS_IE when CGo is disabled
invalid-email-address May 31, 2023
36661c7
Don't escape go.shape pkgPath during type registration
invalid-email-address Jun 7, 2023
cca00cb
Actually implement R_ARM64_GOTPCREL relocs, and make the use of -dynl…
invalid-email-address Jun 7, 2023
38c6920
Bump go.mod
invalid-email-address Jun 7, 2023
d0614cc
More PCREL arithmetic mistakes!
invalid-email-address Jun 7, 2023
03a29a7
Further bugfix PCREL CMPL code (needed indirect), and MOV code (incom…
invalid-email-address Jun 8, 2023
c77a933
Don't attempt to register missing types with no package as CGo symbols
invalid-email-address Jun 8, 2023
dc641fe
Further tweaks to CMPL PCREL reloc asm
invalid-email-address Jun 8, 2023
c2f2dc8
Add concurrency limit of GOMAXPROCS to jit dependency builds
invalid-email-address Jun 8, 2023
7197f92
Add ForceTestRelocationEpilogues linker option
invalid-email-address Jun 8, 2023
f327336
Experiment - try using handwritten asm wrappers to call libdl on darw…
invalid-email-address Jun 8, 2023
f5f6b9a
Add CGo-less darwin/arm64 support
invalid-email-address Jun 8, 2023
b02ff0b
Bump go.mod
invalid-email-address Jun 8, 2023
dd00131
Update README.md (optimistically!)
eh-steve Jun 8, 2023
90e23bf
bugfix darwin/arm64 go1.18 inter-module closure conversion
invalid-email-address Jun 8, 2023
b61966e
Deterministic symbol resolution order
invalid-email-address Jun 8, 2023
88881ba
Bump go.mod
invalid-email-address Jun 8, 2023
41c3eec
When testing jit.BuildGoText, cd into the testdata module to avoid po…
invalid-email-address Jun 8, 2023
2c8b682
If a symbol from a package is still missing after loading that packag…
invalid-email-address Jun 9, 2023
6596c04
Finish off minimal PE relocs implementation
invalid-email-address Jun 9, 2023
3fdc78b
Skip k8s build on windows due to golang/x/sys/windows init() being un…
invalid-email-address Jun 9, 2023
c296023
Skip PE reloc support for windows on go1.18 + skip CGo test
invalid-email-address Jun 9, 2023
7978b05
Test for Issue #74
invalid-email-address May 17, 2023
6995482
Test for issue #75 (#8)
eh-steve Jun 9, 2023
ddae436
Skip another test on windows
invalid-email-address Jun 9, 2023
c11a2fc
If a symbol we suspect of being linknamed and implemented in runtime …
invalid-email-address Jun 10, 2023
3c6149b
Bump go.mod
invalid-email-address Jun 10, 2023
c5cebc6
Another type registration bugfix
invalid-email-address Jun 10, 2023
6c4cc83
Bump go.mod
invalid-email-address Jun 10, 2023
dde53fd
Simplify PCREL CGo CALLs
invalid-email-address Jun 15, 2023
b9bb87e
Simplify PCREL CGo CALLs
invalid-email-address Jun 15, 2023
f7f9a7d
Bump go.mod
invalid-email-address Jun 15, 2023
37877e0
Use reflect.(*rtype).Elem during type registration
invalid-email-address Jul 1, 2023
e554af9
Bump go.mod
invalid-email-address Jul 1, 2023
652eae0
WIP - support Go 1.21 (RC3)
invalid-email-address Jul 5, 2023
7655ed9
Handle errors during regSymbol(), and register RODATA too
invalid-email-address Jul 7, 2023
dc59d91
Fix mistake in symbol size calculation
invalid-email-address Jul 7, 2023
4a0097f
Add protobuf test
invalid-email-address Jul 7, 2023
78c4c33
Force static data to be marked as reachable to ensure packages contai…
invalid-email-address Jul 7, 2023
2a6a636
Patch firstmodule type's method types if marked unreachable (-1), and…
invalid-email-address Jul 7, 2023
fca27fc
Fix ordering of inittasks via Autolib() order (not R_INITORDER), also…
invalid-email-address Jul 7, 2023
8b0797c
Add Issue55 version of TestPatchMultipleModuleItabs
invalid-email-address Jul 8, 2023
f194a46
Fix protobufunload and mistake in DataAddr()
invalid-email-address Jul 8, 2023
1ffa41a
Fix Macho relocs + WIP support for more elf and macho arm64 reloc types
invalid-email-address Jul 8, 2023
98581d0
Fix PE relocs (to support .bss sections) + add more substantial Cgo t…
invalid-email-address Jul 9, 2023
8ec528f
Make 2 versions x86 asm on darwin/amd64, since on 1.21, the toolchain…
invalid-email-address Jul 17, 2023
1160752
Skip advanced CGo test in CI
invalid-email-address Jul 19, 2023
ae4c14e
Bump go.mod
invalid-email-address Jul 30, 2023
b789213
Bump patchgc
invalid-email-address Jul 30, 2023
319945f
Fix patchgc for cross-device copies on Windows
invalid-email-address Sep 5, 2023
2b17d7c
Bump patchgc
invalid-email-address Sep 5, 2023
58fac1d
Fix darwin/macho self patch when os.Args[0] is not an absolute or rel…
invalid-email-address Sep 24, 2023
2133bbf
Add test for issue 87
invalid-email-address Sep 5, 2023
684a15f
Update CALL relocs - try JMP (to epilogue) then CALL (target func) th…
invalid-email-address Sep 6, 2023
5aecb8e
Improve type registration and behaviour under 1.21
invalid-email-address Dec 7, 2023
6762cf3
Make go toolchain commands output to stderr/stdout if DebugLog = true
invalid-email-address Dec 7, 2023
8ca31c1
Try go test -a -c for rebuilding stdlibs on Windows?
invalid-email-address Dec 7, 2023
c00480d
fix #91, when pcdata is empty, so pcdata offset is zero
invalid-email-address Nov 15, 2023
2780e3b
Adjust readFuncData to add a 0 for empty string funcdata
invalid-email-address Dec 7, 2023
da303ad
fix #93, fix fill findfuncbucket error
invalid-email-address Dec 2, 2023
0bef61c
Run patchgc with -a to force rebuild of stdlib on Windows
invalid-email-address Dec 7, 2023
72cbd0a
Add test for type aliases to pointer types
invalid-email-address Dec 7, 2023
504d75e
Don't write GoList output to stdout
invalid-email-address Jan 2, 2024
180c407
Bump go.mod
invalid-email-address Jan 2, 2024
7233482
Don't stream IO in GoList
invalid-email-address Jan 2, 2024
67105cf
Improve error in patchgc
invalid-email-address Jan 2, 2024
9344fa5
Change API of ConvertTypesAcrossModules to make it clearer that old v…
invalid-email-address Jan 2, 2024
8186a8d
Bump go.mod
invalid-email-address Jan 2, 2024
7e1d084
(Untested) Go 1.22 support
invalid-email-address Jan 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 20 additions & 42 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: goloader Testing
name: goloader

on:
push:
Expand All @@ -14,58 +14,36 @@ jobs:
strategy:
fail-fast: false
matrix:
go-version: [1.8.x, 1.9.x, 1.10.x, 1.11.x, 1.12.x, 1.13.x, 1.14.x, 1.15.x, 1.16.x, 1.17.x, 1.18.x, 1.19.x]
os: [ubuntu-latest, windows-latest, macos-latest]
exclude:
- os: macos-latest
go-version: 1.8.x
- os: macos-latest
go-version: 1.9.x
- os: macos-latest
go-version: 1.10.x
include:
- os: macos-11
go-version: 1.8.x
- os: macos-11
go-version: 1.9.x
- os: macos-11
go-version: 1.10.x
go-version: [ 1.18.X, 1.19.X, 1.20.X , 1.21.X ]
os: [ubuntu-latest, windows-latest, macos-latest, [self-hosted, Linux, ARM64], [self-hosted, macOS, ARM64]]
cgo-enabled: ["CGO_ENABLED=0", "CGO_ENABLED=1"]
dynlink: ["JIT_GC_DYNLINK=1", "JIT_GC_DYNLINK=0"]
runs-on: ${{ matrix.os }}

steps:
- name: Set up Go
uses: actions/setup-go@v2
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go-version }}

check-latest: true
cache-dependency-path: jit/go.sum

- name: Rename cmd/internal
shell: sh
run:
cp -r $GOROOT/src/cmd/internal $GOROOT/src/cmd/objfile

run: |
eval $(go env | sed -r 's/^(set )?(\w+)=("|'"'"'?)(.*)\3$/\2="\4"/g') && cp -r $GOROOT/src/cmd/internal $GOROOT/src/cmd/objfile

- name: Patch gc
shell: sh
run:
go run -a github.com/eh-steve/goloader/jit/patchgc@2aedbae4eb66fb4d0a4f24efbeb1873007792bca

- name: Checkout code
uses: actions/checkout@v3
with:
path: ${{ env.GOPATH }}/src/github.com/${{ github.repository }}

- name: Build
run:
go build github.com/pkujhd/goloader/examples/loader

- name: Compile const.go
shell: sh
run:
go tool compile $GOPATH/src/github.com/pkujhd/goloader/examples/const/const.go

- name: Compile base.go

- name: Test
shell: sh
run:
go tool compile $GOPATH/src/github.com/pkujhd/goloader/examples/base/base.go

- name: Test base.o
run:
./loader -o base.o -run main.main

- name: Test const.o
run:
./loader -o const.o -run main.main
cd $GOPATH/src/github.com/eh-steve/goloader/jit && export ${{ matrix.cgo-enabled }} ${{ matrix.dynlink }} && go test -a -c . && ./jit.test -test.v
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ before_install:

script:
- export GO111MODULE=auto
- go build github.com/pkujhd/goloader/examples/loader
- go tool compile $GOPATH/src/github.com/pkujhd/goloader/examples/base/base.go
- go tool compile $GOPATH/src/github.com/pkujhd/goloader/examples/const/const.go
- go build github.com/eh-steve/goloader/examples/loader
- go tool compile $GOPATH/src/github.com/eh-steve/goloader/examples/base/base.go
- go tool compile $GOPATH/src/github.com/eh-steve/goloader/examples/const/const.go
- ./loader -o base.o -run main.main
- ./loader -o const.o -run main.main
180 changes: 140 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,70 +1,170 @@
# Goloader/JIT Compiler for Go

# Goloader
[![Build Status](https://github.com/eh-steve/goloader/actions/workflows/go.yml/badge.svg)](https://github.com/eh-steve/goloader/actions/workflows/go.yml)

![Build Status](https://github.com/pkujhd/goloader/workflows/goloader%20Testing/badge.svg)
The `goloader/jit` package can compile and load Go code from text, file, folder or remote package (including code with
package imports).

Goloader can load and run Golang code at runtime.
It automatically resolves package dependencies recursively, and provides a type safe way of interacting with the built
functions.

Forked from **https://github.com/dearplain/goloader**, Take over maintenance because the original author is not in maintenance
Forked from [dearplain](https://github.com/dearplain/goloader) and [pkujhd](https://github.com/pkujhd/goloader).

## How does it work?

Goloader works like a linker: it relocates the address of symbols in an object file, generates runnable code, and then reuses the runtime function and the type pointer of the loader.
# Usage

Goloader provides some information to the runtime and gc of Go, which allows it to work correctly with them.
## Build

Please note that Goloader is not a scripting engine. It reads the output of Go compiler and makes them runnable. All features of Go are supported, and run just as fast and lightweight as native Go code.
**Make sure you're using go >= 1.18.**

## Comparison with plugin
First, execute the following command. This is because Goloader relies on the internal package, which is forbidden by the
Go compiler.

Goloader reuses the Go runtime, which makes it much smaller. And code loaded by Goloader is unloadable.
```
cp -r $GOROOT/src/cmd/internal $GOROOT/src/cmd/objfile
```

Goloader supports pprof tool(Yes, you can see code loaded by Goloader in pprof).
## Go compiler patch

## Build
To allow the loader to know the types of exported functions, this package will attempt to patch the Go compiler (gc) to
emit these if not already patched.

**Make sure you're using go >= 1.8.**
The effect of the patch can be found in [`jit/gc.patch`](https://github.com/eh-steve/goloader/blob/master/jit/gc.patch).

First, execute the following command, then do build and test. This is because Goloader relies on the internal package, which is forbidden by the Go compiler.
```
cp -r $GOROOT/src/cmd/internal $GOROOT/src/cmd/objfile
```bash
go install github.com/eh-steve/goloader/jit/patchgc@latest
# You may need to run patchgc as sudo if your $GOROOT is owned by root
# (alternatively `chown -R $USER:$USER $GOROOT`)
patchgc
```

## Examples
## Example Usage

```go
package main

import (
"fmt"
"github.com/eh-steve/goloader/jit"
)

func main() {
conf := jit.BuildConfig{
KeepTempFiles: false, // Files are copied/written to a temp dir to ensure it is writable. This retains the temporary copies
ExtraBuildFlags: []string{"-x"}, // Flags passed to go build command
BuildEnv: nil, // Env vars to set for go build toolchain
TmpDir: "", // To control where temporary files are copied
DebugLog: true, //
}

loadable, err := jit.BuildGoFiles(conf, "./path/to/file1.go", "/path/to/file2.go")
if err != nil {
panic(err)
}
// or
loadable, err = jit.BuildGoPackage(conf, "./path/to/package")
if err != nil {
panic(err)
}
// or
loadable, err = jit.BuildGoPackageRemote(conf, "github.com/some/package/v4", "latest")
if err != nil {
panic(err)
}
// or
loadable, err = jit.BuildGoText(conf, `
package mypackage

import "encoding/json"

func MyFunc(input []byte) (interface{}, error) {
var output interface{}
err := json.Unmarshal(input, &output)
return output, err
}
`)

if err != nil {
panic(err)
}

module, err := loadable.Load()
// module.SymbolsByPkg is a map[string]map[string]interface{} of all packages and their exported functions and global vars
symbols := module.SymbolsByPkg[loadable.ImportPath]
if err != nil {
panic(err)
}
defer func() {
err = module.Unload()
if err != nil {
panic(err)
}
}()
switch f := symbols["MyFunc"].(type) {
case func([]byte) (interface{}, error):
result, err := f([]byte(`{"k":"v"}`))
if err != nil {
panic(err)
}
fmt.Println(result)
default:
panic("Function signature was not what was expected")
}
}

```
export GO111MODULE=auto
go build github.com/pkujhd/goloader/examples/loader

go tool compile $GOPATH/src/github.com/pkujhd/goloader/examples/schedule/schedule.go
./loader -o schedule.o -run main.main -times 10
## How does it work?

go tool compile $GOPATH/src/github.com/pkujhd/goloader/examples/base/base.go
./loader -o base.o -run main.main
Goloader works like a linker, it relocates the addresses of symbols in an object file, generates runnable code, and then
reuses the runtime functions and the type pointers of the loader where available.

go tool compile $GOPATH/src/github.com/pkujhd/goloader/examples/http/http.go
./loader -o http.o -run main.main
Goloader provides some information to the runtime and garbage collector of Go, which allows it to work correctly with
them.

go install github.com/pkujhd/goloader/examples/basecontext
go tool compile -I $GOPATH/pkg/`go env GOOS`_`go env GOARCH`/ $GOPATH/src/github.com/pkujhd/goloader/examples/inter/inter.go
./loader -o $GOPATH/pkg/`go env GOOS`_`go env GOARCH`/github.com/pkujhd/goloader/examples/basecontext.a:github.com/pkujhd/goloader/examples/basecontext -o inter.o
Please note that Goloader is not a scripting engine. It reads the archives emitted from the Go compiler and makes them
runnable. All features of Go are supported, and run just as fast and lightweight as native Go code.

#build multiple go files
go tool compile -I $GOPATH/pkg/`go env GOOS`_`go env GOARCH`/ -o test.o test1.go test2.go
./loader -o test.o -run main.main
## Comparison with `plugin`

```
Plugin:

## Warning
* Can't load plugins not built with exact same versions of packages that host binary
uses (`plugin was built with a different version of package`) - this makes them basically unusable in most large
projects
* Introduces dependency on `libdl`/CGo (and doesn't work on Windows)
* Prevents linker deadcode elimination for unreachable methods (increases host binary size with unused methods)
* Can't be unloaded/dynamically updated
* Duplicates a lot of the go runtime (large binary sizes)

Don't use "-s -w" compile argument, It strips symbol table.
Goloader:

This has currently only been tested and developed on:
* Can build/load any packages (somewhat unsafely - it attempts to verify that types across JIT packages and host
packages match, but doesn't do the same checks for function signatures)
* Pure Go - no dependency on `libdl`/Cgo
* Patches host itabs containing unreachable methods instead of preventing linker deadcode elimination
* Can be unloaded, and objects from one version of a JIT package can be converted at runtime to those from another
version, to allow dynamic adjustment of functions/methods without losing state
* Reuses the runtime from the host binary (much smaller binaries)

Golang 1.8-1.19 (x64/x86, darwin, linux, windows)
Goloader supports pprof tool (yes, you can see code loaded by Goloader in pprof), but does not (yet) support debugging
with `delve`.

Golang 1.10-1.19 (arm, linux, android)
## OS/Arch Compatibility

Golang 1.8-1.19 (arm64, linux, android)
JIT compiler tested/passing on:

Golang 1.16-1.19 (arm64, darwin)
| **OS/Arch** | amd64/+CGo | arm64/+CGo | amd64/-CGo | arm64/-CGo |
|--------------------|--------------------|--------------------|--------------------|--------------------|
| Linux/go-1.20.3 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| Darwin/go-1.20.3 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| Windows/go-1.20.3 | :heavy_check_mark: | :interrobang: | :heavy_check_mark: | :interrobang: |
| Linux/go-1.19.4 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| Darwin/go-1.19.4 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| Windows/go-1.19.4 | :heavy_check_mark: | :interrobang: | :heavy_check_mark: | :interrobang: |
| Linux/go-1.18.8 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| Darwin/go-1.18.8 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| Windows/go-1.18.8 | :x: | :interrobang: | :heavy_check_mark: | :interrobang: |

## Warning

Don't use "-s -w" compile argument, It strips symbol table.
61 changes: 42 additions & 19 deletions asm_bytes.go
Original file line number Diff line number Diff line change
@@ -1,33 +1,56 @@
package goloader

const (
x86amd64MOVcode byte = 0x8B
x86amd64LEAcode byte = 0x8D
x86amd64CMPLcode byte = 0x83
x86amd64MOVcode byte = 0x8B
x86amd64LEAcode byte = 0x8D
x86amd64CMPLcode byte = 0x83
x86amd64CALLcode byte = 0xE8
x86amd64CALL2code byte = 0xFF
x86amd64JMPcode byte = 0xE9
)

// arm/arm64
var (
armcode = []byte{0x04, 0xF0, 0x1F, 0xE5} //LDR PC, [PC, #-4]
arm64code = []byte{
0x49, 0x00, 0x00, 0x58, // LDR X9 [PC+8]
0x20, 0x01, 0x1F, 0xD6} // BR X9
arm64BLcode = []byte{0x00, 0x00, 0x00, 0x94} // BL [PC+0x0]
armcode = []byte{0x04, 0xF0, 0x1F, 0xE5} //LDR PC, [PC, #-4]
arm64CALLCode = []byte{
// X16 and X17 are the IP0 and IP1 intra-procedure-call corruptible registers -
// since Go only uses them for the stack prologue and epilogue calculations,
// and we should already be clear of that by the time we hit a R_CALLARM64,
// so we should be able to safely use them for far jumps
0x51, 0x00, 0x00, 0x58, // LDR X17 [PC+8] - read 64 bit address from PC+8 into X17
0x20, 0x02, 0x1f, 0xd6, // BR X17 - jump to address in X17
}
arm64Bcode = []byte{0x00, 0x00, 0x00, 0x14} // B [PC+0x0]
arm64NopCode = []byte{0x1f, 0x20, 0x03, 0xd5}
)

const (
armLDRCode8Bytes = uint32(0x58000040) // LDR PC+8
armLDRCode12Bytes = uint32(0x58000060) // LDR PC+12
)

// x86/amd64
var (
x86amd64JMPLcode = []byte{0xff, 0x25, 0x00, 0x00, 0x00, 0x00} // JMPL *ADDRESS
x86amd64NOPcode = byte(0x90)
x86amd64JMPLcode = []byte{0xff, 0x25, 0x00, 0x00, 0x00, 0x00} // JMPL *ADDRESS
x86amd64JMPNearCode = []byte{0xE9, 0x00, 0x00, 0x00, 0x00} // JMP (PCREL offset)+4
x86amd64JMPShortCode = []byte{0xEB, 0x00} // JMP (PCREL offset)+1
x86amd64CALLFarCode = []byte{
0xff, 0x15, 0x00, 0x00, 0x00, 0x00, // CALL ptr [RIP]
}
x86amd64replaceCMPLcode = []byte{
0x50, // PUSH EAX
0x53, // PUSH EBX
0x48, 0x8b, 0x05, 0x0f, 0x00, 0x00, 0x00, // MOVE EAX x
0x48, 0x8b, 0x18, // MOVE EBX [EAX]
0x48, 0x83, 0xfb, 0x00, // CMPL EBX x(8bits)
0x5b, // POP EBX
0x58, // POP EAX
0xff, 0x25, 0x08, 0x00, 0x00, 0x00} // JMPL *ADDRESS
0x50, // PUSH RAX
0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MOVABS RAX, imm64 (64 bit)
0x48, 0x83, 0x38, 0x00, // CMPL [RAX] x(8bits)
0x58, // POP RAX
}
x86amd64replaceMOVQcodeRAX = []byte{
0x48, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MOVABS RAX, [addr64] (64 bit)
}
x86amd64replaceMOVQcode = []byte{
0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //MOVE RxX x
0xff, 0x25, 0x00, 0x00, 0x00, 0x00} //JMPL *ADDRESS
0x50, // PUSH RAX
0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MOVABS RAX, imm64 (64 bit)
0x48, 0x8b, 0x00, // MOV RxX, [RAX] (64 bit)
0x58, // POP RAX
}
)
Loading