├── .gitignore ├── LICENSE ├── README.md ├── debug.go ├── fileui.go ├── fileui_code.go ├── filterlist.go ├── focus.go ├── geom.go ├── go.mod ├── go.sum ├── icons.go ├── internal ├── README.md ├── disasm │ ├── code.go │ ├── file.go │ ├── linerange.go │ └── lineset.go ├── f32color │ └── color.go ├── go │ ├── LICENSE │ ├── expose.go_ │ ├── src │ │ ├── abi │ │ │ ├── abi.go │ │ │ ├── abi_amd64.go │ │ │ ├── abi_arm64.go │ │ │ ├── abi_generic.go │ │ │ ├── abi_loong64.go │ │ │ ├── abi_ppc64x.go │ │ │ ├── abi_riscv64.go │ │ │ ├── compiletype.go │ │ │ ├── escape.go │ │ │ ├── funcpc.go │ │ │ ├── funcpc_gccgo.go │ │ │ ├── iface.go │ │ │ ├── map_noswiss.go │ │ │ ├── map_select_noswiss.go │ │ │ ├── map_select_swiss.go │ │ │ ├── map_swiss.go │ │ │ ├── rangefuncconsts.go │ │ │ ├── runtime.go │ │ │ ├── stack.go │ │ │ ├── stub.s │ │ │ ├── switch.go │ │ │ ├── symtab.go │ │ │ └── type.go │ │ ├── archive │ │ │ └── archive.go │ │ ├── bio │ │ │ ├── buf.go │ │ │ ├── buf_mmap.go │ │ │ ├── buf_nommap.go │ │ │ └── must.go │ │ ├── bisect │ │ │ └── bisect.go │ │ ├── buildcfg │ │ │ ├── cfg.go │ │ │ ├── exp.go │ │ │ └── zbootstrap.go │ │ ├── disasm │ │ │ ├── disasm.go │ │ │ └── expose.go │ │ ├── goarch │ │ │ ├── gengoarch.go │ │ │ ├── goarch.go │ │ │ ├── goarch_386.go │ │ │ ├── goarch_amd64.go │ │ │ ├── goarch_arm.go │ │ │ ├── goarch_arm64.go │ │ │ ├── goarch_loong64.go │ │ │ ├── goarch_mips.go │ │ │ ├── goarch_mips64.go │ │ │ ├── goarch_mips64le.go │ │ │ ├── goarch_mipsle.go │ │ │ ├── goarch_ppc64.go │ │ │ ├── goarch_ppc64le.go │ │ │ ├── goarch_riscv64.go │ │ │ ├── goarch_s390x.go │ │ │ ├── goarch_wasm.go │ │ │ ├── zgoarch_386.go │ │ │ ├── zgoarch_amd64.go │ │ │ ├── zgoarch_arm.go │ │ │ ├── zgoarch_arm64.go │ │ │ ├── zgoarch_arm64be.go │ │ │ ├── zgoarch_armbe.go │ │ │ ├── zgoarch_loong64.go │ │ │ ├── zgoarch_mips.go │ │ │ ├── zgoarch_mips64.go │ │ │ ├── zgoarch_mips64le.go │ │ │ ├── zgoarch_mips64p32.go │ │ │ ├── zgoarch_mips64p32le.go │ │ │ ├── zgoarch_mipsle.go │ │ │ ├── zgoarch_ppc.go │ │ │ ├── zgoarch_ppc64.go │ │ │ ├── zgoarch_ppc64le.go │ │ │ ├── zgoarch_riscv.go │ │ │ ├── zgoarch_riscv64.go │ │ │ ├── zgoarch_s390.go │ │ │ ├── zgoarch_s390x.go │ │ │ ├── zgoarch_sparc.go │ │ │ ├── zgoarch_sparc64.go │ │ │ └── zgoarch_wasm.go │ │ ├── goexperiment │ │ │ ├── exp_aliastypeparams_off.go │ │ │ ├── exp_aliastypeparams_on.go │ │ │ ├── exp_arenas_off.go │ │ │ ├── exp_arenas_on.go │ │ │ ├── exp_boringcrypto_off.go │ │ │ ├── exp_boringcrypto_on.go │ │ │ ├── exp_cacheprog_off.go │ │ │ ├── exp_cacheprog_on.go │ │ │ ├── exp_cgocheck2_off.go │ │ │ ├── exp_cgocheck2_on.go │ │ │ ├── exp_coverageredesign_off.go │ │ │ ├── exp_coverageredesign_on.go │ │ │ ├── exp_fieldtrack_off.go │ │ │ ├── exp_fieldtrack_on.go │ │ │ ├── exp_heapminimum512kib_off.go │ │ │ ├── exp_heapminimum512kib_on.go │ │ │ ├── exp_loopvar_off.go │ │ │ ├── exp_loopvar_on.go │ │ │ ├── exp_newinliner_off.go │ │ │ ├── exp_newinliner_on.go │ │ │ ├── exp_preemptibleloops_off.go │ │ │ ├── exp_preemptibleloops_on.go │ │ │ ├── exp_rangefunc_off.go │ │ │ ├── exp_rangefunc_on.go │ │ │ ├── exp_regabiargs_off.go │ │ │ ├── exp_regabiargs_on.go │ │ │ ├── exp_regabiwrappers_off.go │ │ │ ├── exp_regabiwrappers_on.go │ │ │ ├── exp_spinbitmutex_off.go │ │ │ ├── exp_spinbitmutex_on.go │ │ │ ├── exp_staticlockranking_off.go │ │ │ ├── exp_staticlockranking_on.go │ │ │ ├── exp_swissmap_off.go │ │ │ ├── exp_swissmap_on.go │ │ │ ├── exp_synchashtriemap_off.go │ │ │ ├── exp_synchashtriemap_on.go │ │ │ ├── exp_synctest_off.go │ │ │ ├── exp_synctest_on.go │ │ │ ├── flags.go │ │ │ └── mkconsts.go │ │ ├── goobj │ │ │ ├── builtin.go │ │ │ ├── builtinlist.go │ │ │ ├── funcinfo.go │ │ │ ├── mkbuiltin.go │ │ │ └── objfile.go │ │ ├── objabi │ │ │ ├── autotype.go │ │ │ ├── flag.go │ │ │ ├── funcid.go │ │ │ ├── head.go │ │ │ ├── line.go │ │ │ ├── path.go │ │ │ ├── pkgspecial.go │ │ │ ├── reloctype.go │ │ │ ├── reloctype_string.go │ │ │ ├── stack.go │ │ │ ├── symkind.go │ │ │ ├── symkind_string.go │ │ │ ├── util.go │ │ │ └── zbootstrap.go │ │ ├── objfile │ │ │ ├── elf.go │ │ │ ├── goobj.go │ │ │ ├── macho.go │ │ │ ├── objfile.go │ │ │ ├── pe.go │ │ │ ├── plan9obj.go │ │ │ └── xcoff.go │ │ ├── saferio │ │ │ └── io.go │ │ ├── src │ │ │ ├── pos.go │ │ │ └── xpos.go │ │ ├── sys │ │ │ ├── arch.go │ │ │ └── args.go │ │ ├── unsafeheader │ │ │ └── unsafeheader.go │ │ └── xcoff │ │ │ ├── ar.go │ │ │ ├── file.go │ │ │ └── xcoff.go │ └── update.go ├── goobj │ ├── code.go │ └── file.go └── wasmobj │ └── file.go ├── main.go ├── screenshot.gif ├── selectlist.go ├── testdata └── c-wasm │ ├── .gitignore │ ├── Makefile │ ├── example-clang.wasm │ ├── example.c │ └── example.wasm ├── util.go ├── widgets.go └── windows.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | .idea/ 17 | 18 | lensm -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2022 Egon Elbre 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lensm 2 | 3 | A tool for viewing assembly and source. 4 | 5 | ![Screenshot](./screenshot.gif) 6 | 7 | Install with the usual Go commands: 8 | 9 | ``` 10 | go install loov.dev/lensm@main 11 | ``` 12 | 13 | _For Linux you may need to add some [additional dependencies](https://gioui.org/doc/install/linux). You can use `go install --tags nowayland loov.dev/lensm@main` or `go install --tags nox11 loov.dev/lensm@main` respectively to skip building Wayland or X11 version._ 14 | 15 | To run the program provide a regular expression filter for the 16 | function you want to inspect. `-watch` allows to automatically 17 | reload the executable and information when it changes. 18 | 19 | ``` 20 | lensm -watch -filter Fibonacci lensm 21 | ``` 22 | 23 | Note: The program requires a binary that is built on your computer, otherwise the source code for the functions cannot be loaded. 24 | 25 | ## Why? 26 | 27 | I wrote a blog post at https://www.storj.io/blog/lensm on why and how the core functionality works. 28 | -------------------------------------------------------------------------------- /debug.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | const N = 44 4 | 5 | func Fibonacci(n int) int { 6 | if n <= 1 { 7 | return n 8 | } 9 | return Fibonacci(n-1) + Fibonacci(n-2) 10 | } 11 | 12 | var _ = Fibonacci(0) 13 | -------------------------------------------------------------------------------- /filterlist.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "regexp" 6 | 7 | "gioui.org/layout" 8 | "gioui.org/op" 9 | "gioui.org/op/clip" 10 | "gioui.org/op/paint" 11 | "gioui.org/unit" 12 | "gioui.org/widget" 13 | "gioui.org/widget/material" 14 | ) 15 | 16 | type FilterListItem interface { 17 | Name() string 18 | } 19 | 20 | // FilterList lists symbols for filtering and selection. 21 | type FilterList[T FilterListItem] struct { 22 | All []T 23 | Filter widget.Editor 24 | FilterError string 25 | Filtered []T 26 | 27 | Selected string 28 | SelectedItem T 29 | 30 | List SelectList 31 | } 32 | 33 | // NewFilterList creates a new list with the specified theme. 34 | func NewFilterList[T FilterListItem](theme *material.Theme) *FilterList[T] { 35 | ui := &FilterList[T]{} 36 | ui.Filter.SingleLine = true 37 | ui.List = NewVerticalSelectList(unit.Dp(theme.TextSize) + 4) 38 | return ui 39 | } 40 | 41 | // SelectIndex selects the specified item. 42 | func (ui *FilterList[T]) SelectIndex(index int) { 43 | if !InRange(index, len(ui.Filtered)) { 44 | return 45 | } 46 | 47 | ui.List.Selected = index 48 | ui.Selected = ui.Filtered[index].Name() 49 | ui.SelectedItem = ui.Filtered[index] 50 | } 51 | 52 | // SetItems updates the full list. 53 | func (ui *FilterList[T]) SetItems(all []T) { 54 | ui.All = all 55 | ui.updateFiltered() 56 | } 57 | 58 | // SetFilter sets the filter. 59 | func (ui *FilterList[T]) SetFilter(filter string) { 60 | ui.Filter.SetText(filter) 61 | ui.updateFiltered() 62 | } 63 | 64 | // updateFiltered updates the filtered list from the unfiltered content. 65 | func (ui *FilterList[T]) updateFiltered() { 66 | defer func() { 67 | ui.List.Selected = -1 68 | for i, item := range ui.Filtered { 69 | if item.Name() == ui.Selected { 70 | ui.List.Selected = i 71 | ui.SelectedItem = item 72 | // TODO, maybe scroll into view? 73 | break 74 | } 75 | } 76 | }() 77 | 78 | rx, err := regexp.Compile("(?i)" + ui.Filter.Text()) 79 | ui.FilterError = "" 80 | if err != nil { 81 | ui.FilterError = err.Error() 82 | return 83 | } 84 | 85 | ui.Filtered = ui.Filtered[:0] 86 | for _, item := range ui.All { 87 | if rx.MatchString(item.Name()) { 88 | ui.Filtered = append(ui.Filtered, item) 89 | } 90 | } 91 | } 92 | 93 | // Layout draws the list. 94 | func (ui *FilterList[T]) Layout(th *material.Theme, gtx layout.Context) layout.Dimensions { 95 | paint.FillShape(gtx.Ops, secondaryBackground, clip.Rect{Max: gtx.Constraints.Min}.Op()) 96 | 97 | ui.SelectIndex(ui.List.Selected) 98 | 99 | changed := false 100 | for { 101 | ev, ok := ui.Filter.Update(gtx) 102 | if !ok { 103 | break 104 | } 105 | if _, ok := ev.(widget.ChangeEvent); ok { 106 | changed = true 107 | } 108 | } 109 | 110 | if changed { 111 | ui.updateFiltered() 112 | gtx.Execute(op.InvalidateCmd{}) 113 | } 114 | 115 | return layout.Flex{ 116 | Axis: layout.Vertical, 117 | }.Layout(gtx, 118 | layout.Rigid(func(gtx layout.Context) layout.Dimensions { 119 | return FocusBorder(th, gtx.Focused(&ui.Filter)).Layout(gtx, 120 | material.Editor(th, &ui.Filter, "Filter (regexp)").Layout) 121 | }), 122 | layout.Rigid(func(gtx layout.Context) layout.Dimensions { 123 | if ui.FilterError == "" { 124 | return layout.Dimensions{} 125 | } 126 | return material.Body1(th, ui.FilterError).Layout(gtx) 127 | }), 128 | layout.Flexed(1, func(gtx layout.Context) layout.Dimensions { 129 | return ui.List.Layout(th, gtx, len(ui.Filtered), 130 | StringListItem(th, &ui.List, func(index int) string { 131 | return ui.Filtered[index].Name() 132 | })) 133 | }), 134 | layout.Rigid(func(gtx layout.Context) layout.Dimensions { 135 | body := material.Body1(th, fmt.Sprintf("%d / %d", len(ui.Filtered), len(ui.All))) 136 | body.TextSize *= 0.8 137 | return layout.Center.Layout(gtx, body.Layout) 138 | }), 139 | ) 140 | } 141 | -------------------------------------------------------------------------------- /focus.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "image/color" 5 | 6 | "gioui.org/layout" 7 | "gioui.org/unit" 8 | "gioui.org/widget" 9 | "gioui.org/widget/material" 10 | ) 11 | 12 | // FocusBorderStyle implements a styling a focused widget. 13 | type FocusBorderStyle struct { 14 | Focused bool 15 | BorderWidth unit.Dp 16 | Color color.NRGBA 17 | } 18 | 19 | // FocusBorder creates a focus border for a focused widget. 20 | func FocusBorder(th *material.Theme, focused bool) FocusBorderStyle { 21 | return FocusBorderStyle{ 22 | Focused: focused, 23 | BorderWidth: unit.Dp(2), 24 | Color: th.ContrastBg, 25 | } 26 | } 27 | 28 | // Layout adds a focus border and styling. 29 | func (focus FocusBorderStyle) Layout(gtx layout.Context, w layout.Widget) layout.Dimensions { 30 | inset := layout.UniformInset(focus.BorderWidth) 31 | if !focus.Focused { 32 | return inset.Layout(gtx, w) 33 | } 34 | 35 | return widget.Border{ 36 | Color: focus.Color, 37 | Width: focus.BorderWidth, 38 | }.Layout(gtx, func(gtx layout.Context) layout.Dimensions { 39 | return inset.Layout(gtx, w) 40 | }) 41 | } 42 | -------------------------------------------------------------------------------- /geom.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type Bounds struct{ Min, Max float32 } 4 | 5 | func BoundsWidth(min, width int) Bounds { 6 | return Bounds{Min: float32(min), Max: float32(min + width)} 7 | } 8 | 9 | func (b Bounds) Width() float32 { return b.Max - b.Min } 10 | 11 | func (b Bounds) Lerp(p float32) float32 { 12 | return b.Min + p*(b.Max-b.Min) 13 | } 14 | 15 | func (b Bounds) Contains(v float32) bool { 16 | return b.Min <= v && v <= b.Max 17 | } 18 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module loov.dev/lensm 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | gioui.org v0.8.0 7 | github.com/tetratelabs/wabin v0.0.0-20230304001439-f6f874872834 8 | golang.org/x/arch v0.14.0 9 | golang.org/x/exp v0.0.0-20240707233637-46b078467d37 10 | golang.org/x/exp/shiny v0.0.0-20240707233637-46b078467d37 11 | ) 12 | 13 | require ( 14 | gioui.org/shader v1.0.8 // indirect 15 | github.com/go-text/typesetting v0.2.1 // indirect 16 | golang.org/x/image v0.18.0 // indirect 17 | golang.org/x/sys v0.22.0 // indirect 18 | golang.org/x/text v0.16.0 // indirect 19 | ) 20 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | eliasnaur.com/font v0.0.0-20230308162249-dd43949cb42d h1:ARo7NCVvN2NdhLlJE9xAbKweuI9L6UgfTbYb0YwPacY= 2 | eliasnaur.com/font v0.0.0-20230308162249-dd43949cb42d/go.mod h1:OYVuxibdk9OSLX8vAqydtRPP87PyTFcT9uH3MlEGBQA= 3 | gioui.org v0.8.0 h1:QV5p5JvsmSmGiIXVYOKn6d9YDliTfjtLlVf5J+BZ9Pg= 4 | gioui.org v0.8.0/go.mod h1:vEMmpxMOd/iwJhXvGVIzWEbxMWhnMQ9aByOGQdlQ8rc= 5 | gioui.org/cpu v0.0.0-20210808092351-bfe733dd3334/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ= 6 | gioui.org/shader v1.0.8 h1:6ks0o/A+b0ne7RzEqRZK5f4Gboz2CfG+mVliciy6+qA= 7 | gioui.org/shader v1.0.8/go.mod h1:mWdiME581d/kV7/iEhLmUgUK5iZ09XR5XpduXzbePVM= 8 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 9 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 10 | github.com/go-text/typesetting v0.2.1 h1:x0jMOGyO3d1qFAPI0j4GSsh7M0Q3Ypjzr4+CEVg82V8= 11 | github.com/go-text/typesetting v0.2.1/go.mod h1:mTOxEwasOFpAMBjEQDhdWRckoLLeI/+qrQeBCTGEt6M= 12 | github.com/go-text/typesetting-utils v0.0.0-20241103174707-87a29e9e6066 h1:qCuYC+94v2xrb1PoS4NIDe7DGYtLnU2wWiQe9a1B1c0= 13 | github.com/go-text/typesetting-utils v0.0.0-20241103174707-87a29e9e6066/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o= 14 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 15 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 16 | github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= 17 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 18 | github.com/tetratelabs/wabin v0.0.0-20230304001439-f6f874872834 h1:ZF+QBjOI+tILZjBaFj3HgFonKXUcwgJ4djLb6i42S3Q= 19 | github.com/tetratelabs/wabin v0.0.0-20230304001439-f6f874872834/go.mod h1:m9ymHTgNSEjuxvw8E7WWe4Pl4hZQHXONY8wE6dMLaRk= 20 | golang.org/x/arch v0.14.0 h1:z9JUEZWr8x4rR0OU6c4/4t6E6jOZ8/QBS2bBYBm4tx4= 21 | golang.org/x/arch v0.14.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= 22 | golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w= 23 | golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= 24 | golang.org/x/exp/shiny v0.0.0-20240707233637-46b078467d37 h1:SOSg7+sueresE4IbmmGM60GmlIys+zNX63d6/J4CMtU= 25 | golang.org/x/exp/shiny v0.0.0-20240707233637-46b078467d37/go.mod h1:3F+MieQB7dRYLTmnncoFbb1crS5lfQoTfDgQy6K4N0o= 26 | golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ= 27 | golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= 28 | golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= 29 | golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 30 | golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= 31 | golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= 32 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 33 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 34 | -------------------------------------------------------------------------------- /icons.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "gioui.org/widget" 5 | "golang.org/x/exp/shiny/materialdesign/icons" 6 | ) 7 | 8 | // OpenInNewIcon is used for opening Code in a new window. 9 | var OpenInNewIcon = func() *widget.Icon { 10 | icon, _ := widget.NewIcon(icons.ActionOpenInNew) 11 | return icon 12 | }() 13 | -------------------------------------------------------------------------------- /internal/README.md: -------------------------------------------------------------------------------- 1 | `go` folder contains code vendored from [Go project](https://go.googlesource.com/go/). -------------------------------------------------------------------------------- /internal/disasm/code.go: -------------------------------------------------------------------------------- 1 | package disasm 2 | 3 | // Code combines the disassembly and the source code mapping. 4 | type Code struct { 5 | // Name is the name of the code block, e.g. function or method name. 6 | Name string 7 | // File is where the code is located. 8 | File string 9 | 10 | // Insts is the slice of a all instructions in the code. 11 | Insts []Inst 12 | // MaxJump is the maximum layers of jumps for the codeblock. 13 | // This is used to determine how much padding is created for 14 | // the jump lines. 15 | MaxJump int 16 | 17 | // Source is the slice of a codeblocks that were used to create the instructions. 18 | Source []Source 19 | } 20 | 21 | // Inst represents a single instruction. 22 | type Inst struct { 23 | // PC is the program counter, usually offset in the binary. 24 | PC uint64 25 | // Text is the textual representation of this instruction. 26 | Text string 27 | // File is the location where this instruction was compiled from. 28 | File string 29 | // Line is the line in the file where this instruction was compiled from. 30 | Line int 31 | 32 | // RefPC is a reference to another program counter, e.g. a call. 33 | RefPC uint64 34 | // RefOffset is a reference to a relative jump. 35 | RefOffset int 36 | // RefStack is the depth that the jump line should be drawn at. 37 | RefStack int 38 | 39 | // Call is a named target that should be present in Funcs. 40 | // This is used to make the instruction clickable and follow to the 41 | // called target. 42 | Call string 43 | } 44 | 45 | // Source represents code from a single file. 46 | type Source struct { 47 | // File is the file name for the source code. 48 | File string 49 | // Blocks is a slice of blocks that were used for compiling the instructions. 50 | Blocks []SourceBlock 51 | } 52 | 53 | // SourceBlock represents a single sequential codeblock that references the instructions. 54 | type SourceBlock struct { 55 | // LineRange is the range of lines that it references from the file. 56 | LineRange 57 | // Lines are textual representation of the source starting from `LineRange.From`. 58 | Lines []string 59 | // Related contains a set of ranges in the instructions. 60 | // e.g. for source code Lines[5] there will be drawn relation shapes to each 61 | // instructions `for _, r := range Related[5] { draw(Insts[r.From:r.To]) }` 62 | Related [][]LineRange 63 | } 64 | -------------------------------------------------------------------------------- /internal/disasm/file.go: -------------------------------------------------------------------------------- 1 | package disasm 2 | 3 | // File represents an object file, a module or anything that contains functions. 4 | type File interface { 5 | // Close closes the underlying data. 6 | Close() error 7 | // Funcs enumerates all the visualizable code blocks. 8 | Funcs() []Func 9 | } 10 | 11 | // Func represents a function or method that can be independently rendered. 12 | type Func interface { 13 | // Name is the name of the func. 14 | Name() string 15 | // Load loads the source code and disassembles it. 16 | Load(opt Options) *Code 17 | } 18 | 19 | // Options defines configuration for loading the func. 20 | type Options struct { 21 | // Context is the number of lines that should be additionally included for context. 22 | // This can often contain function documentation. 23 | Context int 24 | } 25 | -------------------------------------------------------------------------------- /internal/disasm/linerange.go: -------------------------------------------------------------------------------- 1 | package disasm 2 | 3 | // LineRange represents a list of lines. 4 | type LineRange struct{ From, To int } 5 | 6 | // LineRangesContain checks whether line a or line b is contained in the ranges. 7 | func LineRangesContain(ranges []LineRange, a, b int) bool { 8 | for _, r := range ranges { 9 | if (r.From <= a && a < r.To) || (r.From <= b && b < r.To) { 10 | return true 11 | } 12 | } 13 | return false 14 | } 15 | -------------------------------------------------------------------------------- /internal/disasm/lineset.go: -------------------------------------------------------------------------------- 1 | package disasm 2 | 3 | import ( 4 | "sort" 5 | 6 | "golang.org/x/exp/slices" 7 | ) 8 | 9 | // LineSet represents a set of needed lines. 10 | type LineSet struct { 11 | list []int 12 | } 13 | 14 | // Add adds line to the needed set. 15 | func (rs *LineSet) Add(line int) { 16 | if len(rs.list) == 0 { 17 | rs.list = append(rs.list, line) 18 | return 19 | } 20 | at := sort.SearchInts(rs.list, line) 21 | if at >= len(rs.list) { 22 | rs.list = append(rs.list, line) 23 | } else if rs.list[at] != line { 24 | rs.list = slices.Insert(rs.list, at, line) 25 | } 26 | } 27 | 28 | // Ranges converts line set to line ranges and adds context for extra information. 29 | func (rs *LineSet) Ranges(context int) []LineRange { 30 | if len(rs.list) == 0 { 31 | return nil 32 | } 33 | 34 | var all []LineRange 35 | 36 | current := LineRange{From: rs.list[0] - context, To: rs.list[0] + context + 1} 37 | if current.From < 1 { 38 | current.From = 1 39 | } 40 | for _, line := range rs.list { 41 | if line-context <= current.To { 42 | current.To = line + context + 1 43 | } else { 44 | all = append(all, current) 45 | current = LineRange{From: line - context, To: line + context + 1} 46 | } 47 | } 48 | all = append(all, current) 49 | 50 | return all 51 | } 52 | 53 | // RangesZero returns a ranges without expanding by context. 54 | func (rs *LineSet) RangesZero() []LineRange { 55 | if len(rs.list) == 0 { 56 | return nil 57 | } 58 | 59 | var all []LineRange 60 | 61 | current := LineRange{From: rs.list[0], To: rs.list[0] + 1} 62 | for _, line := range rs.list { 63 | if line <= current.To { 64 | current.To = line + 1 65 | } else { 66 | all = append(all, current) 67 | current = LineRange{From: line, To: line + 1} 68 | } 69 | } 70 | all = append(all, current) 71 | 72 | return all 73 | } 74 | -------------------------------------------------------------------------------- /internal/f32color/color.go: -------------------------------------------------------------------------------- 1 | package f32color 2 | 3 | import ( 4 | "image/color" 5 | "math" 6 | ) 7 | 8 | var ( 9 | White = color.NRGBA{0xFF, 0xFF, 0xFF, 0xFF} 10 | Black = color.NRGBA{0x00, 0x00, 0x00, 0xFF} 11 | Red = color.NRGBA{0xFF, 0x00, 0x00, 0xFF} 12 | Green = color.NRGBA{0x00, 0xFF, 0x00, 0xFF} 13 | Blue = color.NRGBA{0x00, 0x00, 0xFF, 0xFF} 14 | Yellow = color.NRGBA{0xFF, 0xFF, 0x00, 0xFF} 15 | 16 | Transparent = color.NRGBA{0xFF, 0xFF, 0xFF, 0x00} 17 | ) 18 | 19 | func NRGBAHex(hex uint32) color.NRGBA { 20 | return color.NRGBA{ 21 | R: uint8(hex >> 24), 22 | G: uint8(hex >> 16), 23 | B: uint8(hex >> 8), 24 | A: uint8(hex >> 0), 25 | } 26 | } 27 | 28 | // Gray8 returns the corresponding gray value. 29 | func Gray8(v byte) color.NRGBA { 30 | return color.NRGBA{R: v, G: v, B: v, A: 0xFF} 31 | } 32 | 33 | // RGB returns color based on RGB in range 0..1 34 | func RGB(r, g, b float32) color.NRGBA { 35 | return color.NRGBA{R: sat8(r), G: sat8(g), B: sat8(b), A: 0xFF} 36 | } 37 | 38 | // RGBA returns color based on RGBA in range 0..1 39 | func RGBA(r, g, b, a float32) color.NRGBA { 40 | return color.NRGBA{R: sat8(r), G: sat8(g), B: sat8(b), A: sat8(a)} 41 | } 42 | 43 | // HSLA returns color based on HSLA in range 0..1 44 | func HSLA(h, s, l, a float32) color.NRGBA { return RGBA(hsla(h, s, l, a)) } 45 | 46 | // HSL returns color based on HSL in range 0..1 47 | func HSL(h, s, l float32) color.NRGBA { return HSLA(h, s, l, 1) } 48 | 49 | // RGBAFloat returns RGBA scaled to 0..1 50 | func RGBAFloat(c color.NRGBA) (r, g, b, a float32) { 51 | return float32(c.R) / 0xFF, float32(c.G) / 0xFF, float32(c.B) / 0xFF, float32(c.A) / 0xFF 52 | } 53 | 54 | // Lerp linearly interpolates each RGBA component separately 55 | func RGBALerp(a, b color.NRGBA, p float32) color.NRGBA { 56 | ar, ag, ab, aa := RGBAFloat(a) 57 | br, bg, bb, ba := RGBAFloat(b) 58 | return RGBA( 59 | lerpClamp(ar, br, p), 60 | lerpClamp(ag, bg, p), 61 | lerpClamp(ab, bb, p), 62 | lerpClamp(aa, ba, p), 63 | ) 64 | } 65 | 66 | func hue(v1, v2, h float32) float32 { 67 | if h < 0 { 68 | h += 1 69 | } 70 | if h > 1 { 71 | h -= 1 72 | } 73 | if 6*h < 1 { 74 | return v1 + (v2-v1)*6*h 75 | } else if 2*h < 1 { 76 | return v2 77 | } else if 3*h < 2 { 78 | return v1 + (v2-v1)*(2.0/3.0-h)*6 79 | } 80 | 81 | return v1 82 | } 83 | 84 | func hsla(h, s, l, a float32) (r, g, b, ra float32) { 85 | if s == 0 { 86 | return l, l, l, a 87 | } 88 | 89 | h = mod32(h, 1) 90 | 91 | var v2 float32 92 | if l < 0.5 { 93 | v2 = l * (1 + s) 94 | } else { 95 | v2 = (l + s) - s*l 96 | } 97 | 98 | v1 := 2*l - v2 99 | r = hue(v1, v2, h+1.0/3.0) 100 | g = hue(v1, v2, h) 101 | b = hue(v1, v2, h-1.0/3.0) 102 | ra = a 103 | 104 | return 105 | } 106 | 107 | // sat8 converts 0..1 float to 0..255 uint8 108 | func sat8(v float32) uint8 { 109 | v *= 255.0 110 | if v >= 255 { 111 | return 255 112 | } else if v <= 0 { 113 | return 0 114 | } 115 | return uint8(v) 116 | } 117 | 118 | func lerpClamp(p, min, max float32) float32 { 119 | if p < 0 { 120 | return min 121 | } else if p > 1 { 122 | return max 123 | } 124 | return min + (max-min)*p 125 | } 126 | 127 | func mod32(x, y float32) float32 { return float32(math.Mod(float64(x), float64(y))) } 128 | -------------------------------------------------------------------------------- /internal/go/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /internal/go/expose.go_: -------------------------------------------------------------------------------- 1 | package disasm 2 | 3 | import "loov.dev/lensm/internal/go/src/objfile" 4 | 5 | func (d *Disasm) Syms() []objfile.Sym { return d.syms } 6 | func (d *Disasm) TextStart() uint64 { return d.textStart } 7 | func (d *Disasm) TextEnd() uint64 { return d.textEnd } 8 | func (d *Disasm) PCLN() objfile.Liner { return d.pcln } 9 | -------------------------------------------------------------------------------- /internal/go/src/abi/abi.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package abi 6 | 7 | import ( 8 | "loov.dev/lensm/internal/go/src/goarch" 9 | "unsafe" 10 | ) 11 | 12 | // RegArgs is a struct that has space for each argument 13 | // and return value register on the current architecture. 14 | // 15 | // Assembly code knows the layout of the first two fields 16 | // of RegArgs. 17 | // 18 | // RegArgs also contains additional space to hold pointers 19 | // when it may not be safe to keep them only in the integer 20 | // register space otherwise. 21 | type RegArgs struct { 22 | // Values in these slots should be precisely the bit-by-bit 23 | // representation of how they would appear in a register. 24 | // 25 | // This means that on big endian arches, integer values should 26 | // be in the top bits of the slot. Floats are usually just 27 | // directly represented, but some architectures treat narrow 28 | // width floating point values specially (e.g. they're promoted 29 | // first, or they need to be NaN-boxed). 30 | Ints [IntArgRegs]uintptr // untyped integer registers 31 | Floats [FloatArgRegs]uint64 // untyped float registers 32 | 33 | // Fields above this point are known to assembly. 34 | 35 | // Ptrs is a space that duplicates Ints but with pointer type, 36 | // used to make pointers passed or returned in registers 37 | // visible to the GC by making the type unsafe.Pointer. 38 | Ptrs [IntArgRegs]unsafe.Pointer 39 | 40 | // ReturnIsPtr is a bitmap that indicates which registers 41 | // contain or will contain pointers on the return path from 42 | // a reflectcall. The i'th bit indicates whether the i'th 43 | // register contains or will contain a valid Go pointer. 44 | ReturnIsPtr IntArgRegBitmap 45 | } 46 | 47 | func (r *RegArgs) Dump() { 48 | print("Ints:") 49 | for _, x := range r.Ints { 50 | print(" ", x) 51 | } 52 | println() 53 | print("Floats:") 54 | for _, x := range r.Floats { 55 | print(" ", x) 56 | } 57 | println() 58 | print("Ptrs:") 59 | for _, x := range r.Ptrs { 60 | print(" ", x) 61 | } 62 | println() 63 | } 64 | 65 | // IntRegArgAddr returns a pointer inside of r.Ints[reg] that is appropriately 66 | // offset for an argument of size argSize. 67 | // 68 | // argSize must be non-zero, fit in a register, and a power-of-two. 69 | // 70 | // This method is a helper for dealing with the endianness of different CPU 71 | // architectures, since sub-word-sized arguments in big endian architectures 72 | // need to be "aligned" to the upper edge of the register to be interpreted 73 | // by the CPU correctly. 74 | func (r *RegArgs) IntRegArgAddr(reg int, argSize uintptr) unsafe.Pointer { 75 | if argSize > goarch.PtrSize || argSize == 0 || argSize&(argSize-1) != 0 { 76 | panic("invalid argSize") 77 | } 78 | offset := uintptr(0) 79 | if goarch.BigEndian { 80 | offset = goarch.PtrSize - argSize 81 | } 82 | return unsafe.Pointer(uintptr(unsafe.Pointer(&r.Ints[reg])) + offset) 83 | } 84 | 85 | // IntArgRegBitmap is a bitmap large enough to hold one bit per 86 | // integer argument/return register. 87 | type IntArgRegBitmap [(IntArgRegs + 7) / 8]uint8 88 | 89 | // Set sets the i'th bit of the bitmap to 1. 90 | func (b *IntArgRegBitmap) Set(i int) { 91 | b[i/8] |= uint8(1) << (i % 8) 92 | } 93 | 94 | // Get returns whether the i'th bit of the bitmap is set. 95 | // 96 | // nosplit because it's called in extremely sensitive contexts, like 97 | // on the reflectcall return path. 98 | // 99 | //go:nosplit 100 | func (b *IntArgRegBitmap) Get(i int) bool { 101 | return b[i/8]&(uint8(1)<<(i%8)) != 0 102 | } 103 | -------------------------------------------------------------------------------- /internal/go/src/abi/abi_amd64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package abi 6 | 7 | const ( 8 | // See abi_generic.go. 9 | 10 | // RAX, RBX, RCX, RDI, RSI, R8, R9, R10, R11. 11 | IntArgRegs = 9 12 | 13 | // X0 -> X14. 14 | FloatArgRegs = 15 15 | 16 | // We use SSE2 registers which support 64-bit float operations. 17 | EffectiveFloatRegSize = 8 18 | ) 19 | -------------------------------------------------------------------------------- /internal/go/src/abi/abi_arm64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package abi 6 | 7 | const ( 8 | // See abi_generic.go. 9 | 10 | // R0 - R15. 11 | IntArgRegs = 16 12 | 13 | // F0 - F15. 14 | FloatArgRegs = 16 15 | 16 | EffectiveFloatRegSize = 8 17 | ) 18 | -------------------------------------------------------------------------------- /internal/go/src/abi/abi_generic.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build !goexperiment.regabiargs && !amd64 && !arm64 && !loong64 && !ppc64 && !ppc64le && !riscv64 6 | 7 | package abi 8 | 9 | const ( 10 | // ABI-related constants. 11 | // 12 | // In the generic case, these are all zero 13 | // which lets them gracefully degrade to ABI0. 14 | 15 | // IntArgRegs is the number of registers dedicated 16 | // to passing integer argument values. Result registers are identical 17 | // to argument registers, so this number is used for those too. 18 | IntArgRegs = 0 19 | 20 | // FloatArgRegs is the number of registers dedicated 21 | // to passing floating-point argument values. Result registers are 22 | // identical to argument registers, so this number is used for 23 | // those too. 24 | FloatArgRegs = 0 25 | 26 | // EffectiveFloatRegSize describes the width of floating point 27 | // registers on the current platform from the ABI's perspective. 28 | // 29 | // Since Go only supports 32-bit and 64-bit floating point primitives, 30 | // this number should be either 0, 4, or 8. 0 indicates no floating 31 | // point registers for the ABI or that floating point values will be 32 | // passed via the softfloat ABI. 33 | // 34 | // For platforms that support larger floating point register widths, 35 | // such as x87's 80-bit "registers" (not that we support x87 currently), 36 | // use 8. 37 | EffectiveFloatRegSize = 0 38 | ) 39 | -------------------------------------------------------------------------------- /internal/go/src/abi/abi_loong64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package abi 6 | 7 | const ( 8 | // See abi_generic.go. 9 | 10 | // R4 - R19 11 | IntArgRegs = 16 12 | 13 | // F0 - F15 14 | FloatArgRegs = 16 15 | 16 | EffectiveFloatRegSize = 8 17 | ) 18 | -------------------------------------------------------------------------------- /internal/go/src/abi/abi_ppc64x.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build ppc64 || ppc64le 6 | 7 | package abi 8 | 9 | const ( 10 | // See abi_generic.go. 11 | 12 | // R3 - R10, R14 - R17. 13 | IntArgRegs = 12 14 | 15 | // F1 - F12. 16 | FloatArgRegs = 12 17 | 18 | EffectiveFloatRegSize = 8 19 | ) 20 | -------------------------------------------------------------------------------- /internal/go/src/abi/abi_riscv64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package abi 6 | 7 | const ( 8 | // See abi_generic.go. 9 | 10 | // X8 - X23 11 | IntArgRegs = 16 12 | 13 | // F8 - F23. 14 | FloatArgRegs = 16 15 | 16 | EffectiveFloatRegSize = 8 17 | ) 18 | -------------------------------------------------------------------------------- /internal/go/src/abi/compiletype.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package abi 6 | 7 | // These functions are the build-time version of the Go type data structures. 8 | 9 | // Their contents must be kept in sync with their definitions. 10 | // Because the host and target type sizes can differ, the compiler and 11 | // linker cannot use the host information that they might get from 12 | // either unsafe.Sizeof and Alignof, nor runtime, reflect, or reflectlite. 13 | 14 | // CommonSize returns sizeof(Type) for a compilation target with a given ptrSize 15 | func CommonSize(ptrSize int) int { return 4*ptrSize + 8 + 8 } 16 | 17 | // StructFieldSize returns sizeof(StructField) for a compilation target with a given ptrSize 18 | func StructFieldSize(ptrSize int) int { return 3 * ptrSize } 19 | 20 | // UncommonSize returns sizeof(UncommonType). This currently does not depend on ptrSize. 21 | // This exported function is in an internal package, so it may change to depend on ptrSize in the future. 22 | func UncommonSize() uint64 { return 4 + 2 + 2 + 4 + 4 } 23 | 24 | // TFlagOff returns the offset of Type.TFlag for a compilation target with a given ptrSize 25 | func TFlagOff(ptrSize int) int { return 2*ptrSize + 4 } 26 | 27 | // ITabTypeOff returns the offset of ITab.Type for a compilation target with a given ptrSize 28 | func ITabTypeOff(ptrSize int) int { return ptrSize } 29 | -------------------------------------------------------------------------------- /internal/go/src/abi/escape.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package abi 6 | 7 | import "unsafe" 8 | 9 | // NoEscape hides the pointer p from escape analysis, preventing it 10 | // from escaping to the heap. It compiles down to nothing. 11 | // 12 | // WARNING: This is very subtle to use correctly. The caller must 13 | // ensure that it's truly safe for p to not escape to the heap by 14 | // maintaining runtime pointer invariants (for example, that globals 15 | // and the heap may not generally point into a stack). 16 | // 17 | //go:nosplit 18 | //go:nocheckptr 19 | func NoEscape(p unsafe.Pointer) unsafe.Pointer { 20 | x := uintptr(p) 21 | return unsafe.Pointer(x ^ 0) 22 | } 23 | 24 | var alwaysFalse bool 25 | var escapeSink any 26 | 27 | // Escape forces any pointers in x to escape to the heap. 28 | func Escape[T any](x T) T { 29 | if alwaysFalse { 30 | escapeSink = x 31 | } 32 | return x 33 | } 34 | -------------------------------------------------------------------------------- /internal/go/src/abi/funcpc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build !gccgo 6 | 7 | package abi 8 | 9 | // FuncPC* intrinsics. 10 | // 11 | // CAREFUL: In programs with plugins, FuncPC* can return different values 12 | // for the same function (because there are actually multiple copies of 13 | // the same function in the address space). To be safe, don't use the 14 | // results of this function in any == expression. It is only safe to 15 | // use the result as an address at which to start executing code. 16 | 17 | // FuncPCABI0 returns the entry PC of the function f, which must be a 18 | // direct reference of a function defined as ABI0. Otherwise it is a 19 | // compile-time error. 20 | // 21 | // Implemented as a compile intrinsic. 22 | func FuncPCABI0(f interface{}) uintptr 23 | 24 | // FuncPCABIInternal returns the entry PC of the function f. If f is a 25 | // direct reference of a function, it must be defined as ABIInternal. 26 | // Otherwise it is a compile-time error. If f is not a direct reference 27 | // of a defined function, it assumes that f is a func value. Otherwise 28 | // the behavior is undefined. 29 | // 30 | // Implemented as a compile intrinsic. 31 | func FuncPCABIInternal(f interface{}) uintptr 32 | -------------------------------------------------------------------------------- /internal/go/src/abi/funcpc_gccgo.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // For bootstrapping with gccgo. 6 | 7 | //go:build gccgo 8 | 9 | package abi 10 | 11 | import "unsafe" 12 | 13 | func FuncPCABI0(f interface{}) uintptr { 14 | words := (*[2]unsafe.Pointer)(unsafe.Pointer(&f)) 15 | return *(*uintptr)(unsafe.Pointer(words[1])) 16 | } 17 | 18 | func FuncPCABIInternal(f interface{}) uintptr { 19 | words := (*[2]unsafe.Pointer)(unsafe.Pointer(&f)) 20 | return *(*uintptr)(unsafe.Pointer(words[1])) 21 | } 22 | -------------------------------------------------------------------------------- /internal/go/src/abi/iface.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package abi 6 | 7 | import "unsafe" 8 | 9 | // The first word of every non-empty interface type contains an *ITab. 10 | // It records the underlying concrete type (Type), the interface type it 11 | // is implementing (Inter), and some ancillary information. 12 | // 13 | // allocated in non-garbage-collected memory 14 | type ITab struct { 15 | Inter *InterfaceType 16 | Type *Type 17 | Hash uint32 // copy of Type.Hash. Used for type switches. 18 | Fun [1]uintptr // variable sized. fun[0]==0 means Type does not implement Inter. 19 | } 20 | 21 | // EmptyInterface describes the layout of a "interface{}" or a "any." 22 | // These are represented differently than non-empty interface, as the first 23 | // word always points to an abi.Type. 24 | type EmptyInterface struct { 25 | Type *Type 26 | Data unsafe.Pointer 27 | } 28 | -------------------------------------------------------------------------------- /internal/go/src/abi/map_noswiss.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package abi 6 | 7 | import ( 8 | "unsafe" 9 | ) 10 | 11 | // Map constants common to several packages 12 | // runtime/runtime-gdb.py:MapTypePrinter contains its own copy 13 | const ( 14 | // Maximum number of key/elem pairs a bucket can hold. 15 | OldMapBucketCountBits = 3 // log2 of number of elements in a bucket. 16 | OldMapBucketCount = 1 << OldMapBucketCountBits 17 | 18 | // Maximum key or elem size to keep inline (instead of mallocing per element). 19 | // Must fit in a uint8. 20 | // Note: fast map functions cannot handle big elems (bigger than MapMaxElemBytes). 21 | OldMapMaxKeyBytes = 128 22 | OldMapMaxElemBytes = 128 // Must fit in a uint8. 23 | ) 24 | 25 | type OldMapType struct { 26 | Type 27 | Key *Type 28 | Elem *Type 29 | Bucket *Type // internal type representing a hash bucket 30 | // function for hashing keys (ptr to key, seed) -> hash 31 | Hasher func(unsafe.Pointer, uintptr) uintptr 32 | KeySize uint8 // size of key slot 33 | ValueSize uint8 // size of elem slot 34 | BucketSize uint16 // size of bucket 35 | Flags uint32 36 | } 37 | 38 | // Note: flag values must match those used in the TMAP case 39 | // in ../cmd/compile/internal/reflectdata/reflect.go:writeType. 40 | func (mt *OldMapType) IndirectKey() bool { // store ptr to key instead of key itself 41 | return mt.Flags&1 != 0 42 | } 43 | func (mt *OldMapType) IndirectElem() bool { // store ptr to elem instead of elem itself 44 | return mt.Flags&2 != 0 45 | } 46 | func (mt *OldMapType) ReflexiveKey() bool { // true if k==k for all keys 47 | return mt.Flags&4 != 0 48 | } 49 | func (mt *OldMapType) NeedKeyUpdate() bool { // true if we need to update key on an overwrite 50 | return mt.Flags&8 != 0 51 | } 52 | func (mt *OldMapType) HashMightPanic() bool { // true if hash function might panic 53 | return mt.Flags&16 != 0 54 | } 55 | -------------------------------------------------------------------------------- /internal/go/src/abi/map_select_noswiss.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build !goexperiment.swissmap 6 | 7 | package abi 8 | 9 | // See comment in map_select_swiss.go. 10 | type mapType = OldMapType 11 | -------------------------------------------------------------------------------- /internal/go/src/abi/map_select_swiss.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build goexperiment.swissmap 6 | 7 | package abi 8 | 9 | // Select the map type that this binary is built using. This is for common 10 | // lookup methods like Type.Key to know which type to use. 11 | // 12 | // Note that mapType *must not be used by any functions called in the 13 | // compiler to build a target program* because the compiler must use the map 14 | // type determined by run-time GOEXPERIMENT, not the build tags used to build 15 | // the compiler. 16 | // 17 | // TODO(prattmic): This package is rather confusing because it has many 18 | // functions that can't be used by the compiler (e.g., Type.Uncommon depends on 19 | // the layout of type + uncommon objects in the binary. It would be incorrect 20 | // for an ad-hoc local Type object). It may be best to move code that isn't 21 | // usable by the compiler out of the package. 22 | type mapType = SwissMapType 23 | -------------------------------------------------------------------------------- /internal/go/src/abi/map_swiss.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package abi 6 | 7 | import ( 8 | "unsafe" 9 | ) 10 | 11 | // Map constants common to several packages 12 | // runtime/runtime-gdb.py:MapTypePrinter contains its own copy 13 | const ( 14 | // Number of bits in the group.slot count. 15 | SwissMapGroupSlotsBits = 3 16 | 17 | // Number of slots in a group. 18 | SwissMapGroupSlots = 1 << SwissMapGroupSlotsBits // 8 19 | 20 | // Maximum key or elem size to keep inline (instead of mallocing per element). 21 | // Must fit in a uint8. 22 | SwissMapMaxKeyBytes = 128 23 | SwissMapMaxElemBytes = 128 24 | 25 | ctrlEmpty = 0b10000000 26 | bitsetLSB = 0x0101010101010101 27 | 28 | // Value of control word with all empty slots. 29 | SwissMapCtrlEmpty = bitsetLSB * uint64(ctrlEmpty) 30 | ) 31 | 32 | type SwissMapType struct { 33 | Type 34 | Key *Type 35 | Elem *Type 36 | Group *Type // internal type representing a slot group 37 | // function for hashing keys (ptr to key, seed) -> hash 38 | Hasher func(unsafe.Pointer, uintptr) uintptr 39 | GroupSize uintptr // == Group.Size_ 40 | SlotSize uintptr // size of key/elem slot 41 | ElemOff uintptr // offset of elem in key/elem slot 42 | Flags uint32 43 | } 44 | 45 | // Flag values 46 | const ( 47 | SwissMapNeedKeyUpdate = 1 << iota 48 | SwissMapHashMightPanic 49 | SwissMapIndirectKey 50 | SwissMapIndirectElem 51 | ) 52 | 53 | func (mt *SwissMapType) NeedKeyUpdate() bool { // true if we need to update key on an overwrite 54 | return mt.Flags&SwissMapNeedKeyUpdate != 0 55 | } 56 | func (mt *SwissMapType) HashMightPanic() bool { // true if hash function might panic 57 | return mt.Flags&SwissMapHashMightPanic != 0 58 | } 59 | func (mt *SwissMapType) IndirectKey() bool { // store ptr to key instead of key itself 60 | return mt.Flags&SwissMapIndirectKey != 0 61 | } 62 | func (mt *SwissMapType) IndirectElem() bool { // store ptr to elem instead of elem itself 63 | return mt.Flags&SwissMapIndirectElem != 0 64 | } 65 | -------------------------------------------------------------------------------- /internal/go/src/abi/rangefuncconsts.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package abi 6 | 7 | type RF_State int 8 | 9 | // These constants are shared between the compiler, which uses them for state functions 10 | // and panic indicators, and the runtime, which turns them into more meaningful strings 11 | // For best code generation, RF_DONE and RF_READY should be 0 and 1. 12 | const ( 13 | RF_DONE = RF_State(iota) // body of loop has exited in a non-panic way 14 | RF_READY // body of loop has not exited yet, is not running -- this is not a panic index 15 | RF_PANIC // body of loop is either currently running, or has panicked 16 | RF_EXHAUSTED // iterator function return, i.e., sequence is "exhausted" 17 | RF_MISSING_PANIC = 4 // body of loop panicked but iterator function defer-recovered it away 18 | ) 19 | -------------------------------------------------------------------------------- /internal/go/src/abi/runtime.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package abi 6 | 7 | // ZeroValSize is the size in bytes of runtime.zeroVal. 8 | const ZeroValSize = 1024 9 | -------------------------------------------------------------------------------- /internal/go/src/abi/stack.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package abi 6 | 7 | const ( 8 | // StackNosplitBase is the base maximum number of bytes that a chain of 9 | // NOSPLIT functions can use. 10 | // 11 | // This value must be multiplied by the stack guard multiplier, so do not 12 | // use it directly. See runtime/stack.go:stackNosplit and 13 | // cmd/internal/objabi/stack.go:StackNosplit. 14 | StackNosplitBase = 800 15 | 16 | // We have three different sequences for stack bounds checks, depending on 17 | // whether the stack frame of a function is small, big, or huge. 18 | 19 | // After a stack split check the SP is allowed to be StackSmall bytes below 20 | // the stack guard. 21 | // 22 | // Functions that need frames <= StackSmall can perform the stack check 23 | // using a single comparison directly between the stack guard and the SP 24 | // because we ensure that StackSmall bytes of stack space are available 25 | // beyond the stack guard. 26 | StackSmall = 128 27 | 28 | // Functions that need frames <= StackBig can assume that neither 29 | // SP-framesize nor stackGuard-StackSmall will underflow, and thus use a 30 | // more efficient check. In order to ensure this, StackBig must be <= the 31 | // size of the unmapped space at zero. 32 | StackBig = 4096 33 | ) 34 | -------------------------------------------------------------------------------- /internal/go/src/abi/stub.s: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file silences errors about body-less functions 6 | // that are provided by intrinsics in the latest version of the compiler, 7 | // but may not be known to the bootstrap compiler. 8 | -------------------------------------------------------------------------------- /internal/go/src/abi/switch.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package abi 6 | 7 | type InterfaceSwitch struct { 8 | Cache *InterfaceSwitchCache 9 | NCases int 10 | 11 | // Array of NCases elements. 12 | // Each case must be a non-empty interface type. 13 | Cases [1]*InterfaceType 14 | } 15 | 16 | type InterfaceSwitchCache struct { 17 | Mask uintptr // mask for index. Must be a power of 2 minus 1 18 | Entries [1]InterfaceSwitchCacheEntry // Mask+1 entries total 19 | } 20 | 21 | type InterfaceSwitchCacheEntry struct { 22 | // type of source value (a *Type) 23 | Typ uintptr 24 | // case # to dispatch to 25 | Case int 26 | // itab to use for resulting case variable (a *runtime.itab) 27 | Itab uintptr 28 | } 29 | 30 | const go122InterfaceSwitchCache = true 31 | 32 | func UseInterfaceSwitchCache(goarch string) bool { 33 | if !go122InterfaceSwitchCache { 34 | return false 35 | } 36 | // We need an atomic load instruction to make the cache multithreaded-safe. 37 | // (AtomicLoadPtr needs to be implemented in cmd/compile/internal/ssa/_gen/ARCH.rules.) 38 | switch goarch { 39 | case "amd64", "arm64", "loong64", "mips", "mipsle", "mips64", "mips64le", "ppc64", "ppc64le", "riscv64", "s390x": 40 | return true 41 | default: 42 | return false 43 | } 44 | } 45 | 46 | type TypeAssert struct { 47 | Cache *TypeAssertCache 48 | Inter *InterfaceType 49 | CanFail bool 50 | } 51 | type TypeAssertCache struct { 52 | Mask uintptr 53 | Entries [1]TypeAssertCacheEntry 54 | } 55 | type TypeAssertCacheEntry struct { 56 | // type of source value (a *runtime._type) 57 | Typ uintptr 58 | // itab to use for result (a *runtime.itab) 59 | // nil if CanFail is set and conversion would fail. 60 | Itab uintptr 61 | } 62 | -------------------------------------------------------------------------------- /internal/go/src/abi/symtab.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package abi 6 | 7 | // A FuncFlag records bits about a function, passed to the runtime. 8 | type FuncFlag uint8 9 | 10 | const ( 11 | // FuncFlagTopFrame indicates a function that appears at the top of its stack. 12 | // The traceback routine stop at such a function and consider that a 13 | // successful, complete traversal of the stack. 14 | // Examples of TopFrame functions include goexit, which appears 15 | // at the top of a user goroutine stack, and mstart, which appears 16 | // at the top of a system goroutine stack. 17 | FuncFlagTopFrame FuncFlag = 1 << iota 18 | 19 | // FuncFlagSPWrite indicates a function that writes an arbitrary value to SP 20 | // (any write other than adding or subtracting a constant amount). 21 | // The traceback routines cannot encode such changes into the 22 | // pcsp tables, so the function traceback cannot safely unwind past 23 | // SPWrite functions. Stopping at an SPWrite function is considered 24 | // to be an incomplete unwinding of the stack. In certain contexts 25 | // (in particular garbage collector stack scans) that is a fatal error. 26 | FuncFlagSPWrite 27 | 28 | // FuncFlagAsm indicates that a function was implemented in assembly. 29 | FuncFlagAsm 30 | ) 31 | 32 | // A FuncID identifies particular functions that need to be treated 33 | // specially by the runtime. 34 | // Note that in some situations involving plugins, there may be multiple 35 | // copies of a particular special runtime function. 36 | type FuncID uint8 37 | 38 | const ( 39 | // If you add a FuncID, you probably also want to add an entry to the map in 40 | // ../../cmd/internal/objabi/funcid.go 41 | 42 | FuncIDNormal FuncID = iota // not a special function 43 | FuncID_abort 44 | FuncID_asmcgocall 45 | FuncID_asyncPreempt 46 | FuncID_cgocallback 47 | FuncID_corostart 48 | FuncID_debugCallV2 49 | FuncID_gcBgMarkWorker 50 | FuncID_goexit 51 | FuncID_gogo 52 | FuncID_gopanic 53 | FuncID_handleAsyncEvent 54 | FuncID_mcall 55 | FuncID_morestack 56 | FuncID_mstart 57 | FuncID_panicwrap 58 | FuncID_rt0_go 59 | FuncID_runfinq 60 | FuncID_runtime_main 61 | FuncID_sigpanic 62 | FuncID_systemstack 63 | FuncID_systemstack_switch 64 | FuncIDWrapper // any autogenerated code (hash/eq algorithms, method wrappers, etc.) 65 | ) 66 | 67 | // ArgsSizeUnknown is set in Func.argsize to mark all functions 68 | // whose argument size is unknown (C vararg functions, and 69 | // assembly code without an explicit specification). 70 | // This value is generated by the compiler, assembler, or linker. 71 | const ArgsSizeUnknown = -0x80000000 72 | 73 | // IDs for PCDATA and FUNCDATA tables in Go binaries. 74 | // 75 | // These must agree with ../../../runtime/funcdata.h. 76 | const ( 77 | PCDATA_UnsafePoint = 0 78 | PCDATA_StackMapIndex = 1 79 | PCDATA_InlTreeIndex = 2 80 | PCDATA_ArgLiveIndex = 3 81 | 82 | FUNCDATA_ArgsPointerMaps = 0 83 | FUNCDATA_LocalsPointerMaps = 1 84 | FUNCDATA_StackObjects = 2 85 | FUNCDATA_InlTree = 3 86 | FUNCDATA_OpenCodedDeferInfo = 4 87 | FUNCDATA_ArgInfo = 5 88 | FUNCDATA_ArgLiveInfo = 6 89 | FUNCDATA_WrapInfo = 7 90 | ) 91 | 92 | // Special values for the PCDATA_UnsafePoint table. 93 | const ( 94 | UnsafePointSafe = -1 // Safe for async preemption 95 | UnsafePointUnsafe = -2 // Unsafe for async preemption 96 | 97 | // UnsafePointRestart1(2) apply on a sequence of instructions, within 98 | // which if an async preemption happens, we should back off the PC 99 | // to the start of the sequence when resuming. 100 | // We need two so we can distinguish the start/end of the sequence 101 | // in case that two sequences are next to each other. 102 | UnsafePointRestart1 = -3 103 | UnsafePointRestart2 = -4 104 | 105 | // Like UnsafePointRestart1, but back to function entry if async preempted. 106 | UnsafePointRestartAtEntry = -5 107 | ) 108 | 109 | const MINFUNC = 16 // minimum size for a function 110 | 111 | const FuncTabBucketSize = 256 * MINFUNC // size of bucket in the pc->func lookup table 112 | -------------------------------------------------------------------------------- /internal/go/src/bio/buf.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package bio implements common I/O abstractions used within the Go toolchain. 6 | package bio 7 | 8 | import ( 9 | "bufio" 10 | "io" 11 | "log" 12 | "os" 13 | ) 14 | 15 | // Reader implements a seekable buffered io.Reader. 16 | type Reader struct { 17 | f *os.File 18 | *bufio.Reader 19 | } 20 | 21 | // Writer implements a seekable buffered io.Writer. 22 | type Writer struct { 23 | f *os.File 24 | *bufio.Writer 25 | } 26 | 27 | // Create creates the file named name and returns a Writer 28 | // for that file. 29 | func Create(name string) (*Writer, error) { 30 | f, err := os.Create(name) 31 | if err != nil { 32 | return nil, err 33 | } 34 | return &Writer{f: f, Writer: bufio.NewWriter(f)}, nil 35 | } 36 | 37 | // Open returns a Reader for the file named name. 38 | func Open(name string) (*Reader, error) { 39 | f, err := os.Open(name) 40 | if err != nil { 41 | return nil, err 42 | } 43 | return NewReader(f), nil 44 | } 45 | 46 | // NewReader returns a Reader from an open file. 47 | func NewReader(f *os.File) *Reader { 48 | return &Reader{f: f, Reader: bufio.NewReader(f)} 49 | } 50 | 51 | func (r *Reader) MustSeek(offset int64, whence int) int64 { 52 | if whence == 1 { 53 | offset -= int64(r.Buffered()) 54 | } 55 | off, err := r.f.Seek(offset, whence) 56 | if err != nil { 57 | log.Fatalf("seeking in output: %v", err) 58 | } 59 | r.Reset(r.f) 60 | return off 61 | } 62 | 63 | func (w *Writer) MustSeek(offset int64, whence int) int64 { 64 | if err := w.Flush(); err != nil { 65 | log.Fatalf("writing output: %v", err) 66 | } 67 | off, err := w.f.Seek(offset, whence) 68 | if err != nil { 69 | log.Fatalf("seeking in output: %v", err) 70 | } 71 | return off 72 | } 73 | 74 | func (r *Reader) Offset() int64 { 75 | off, err := r.f.Seek(0, 1) 76 | if err != nil { 77 | log.Fatalf("seeking in output [0, 1]: %v", err) 78 | } 79 | off -= int64(r.Buffered()) 80 | return off 81 | } 82 | 83 | func (w *Writer) Offset() int64 { 84 | if err := w.Flush(); err != nil { 85 | log.Fatalf("writing output: %v", err) 86 | } 87 | off, err := w.f.Seek(0, 1) 88 | if err != nil { 89 | log.Fatalf("seeking in output [0, 1]: %v", err) 90 | } 91 | return off 92 | } 93 | 94 | func (r *Reader) Close() error { 95 | return r.f.Close() 96 | } 97 | 98 | func (w *Writer) Close() error { 99 | err := w.Flush() 100 | err1 := w.f.Close() 101 | if err == nil { 102 | err = err1 103 | } 104 | return err 105 | } 106 | 107 | func (r *Reader) File() *os.File { 108 | return r.f 109 | } 110 | 111 | func (w *Writer) File() *os.File { 112 | return w.f 113 | } 114 | 115 | // Slice reads the next length bytes of r into a slice. 116 | // 117 | // This slice may be backed by mmap'ed memory. Currently, this memory 118 | // will never be unmapped. The second result reports whether the 119 | // backing memory is read-only. 120 | func (r *Reader) Slice(length uint64) ([]byte, bool, error) { 121 | if length == 0 { 122 | return []byte{}, false, nil 123 | } 124 | 125 | data, ok := r.sliceOS(length) 126 | if ok { 127 | return data, true, nil 128 | } 129 | 130 | data = make([]byte, length) 131 | _, err := io.ReadFull(r, data) 132 | if err != nil { 133 | return nil, false, err 134 | } 135 | return data, false, nil 136 | } 137 | 138 | // SliceRO returns a slice containing the next length bytes of r 139 | // backed by a read-only mmap'd data. If the mmap cannot be 140 | // established (limit exceeded, region too small, etc) a nil slice 141 | // will be returned. If mmap succeeds, it will never be unmapped. 142 | func (r *Reader) SliceRO(length uint64) []byte { 143 | data, ok := r.sliceOS(length) 144 | if ok { 145 | return data 146 | } 147 | return nil 148 | } 149 | -------------------------------------------------------------------------------- /internal/go/src/bio/buf_mmap.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build unix 6 | 7 | package bio 8 | 9 | import ( 10 | "runtime" 11 | "sync/atomic" 12 | "syscall" 13 | ) 14 | 15 | // mmapLimit is the maximum number of mmaped regions to create before 16 | // falling back to reading into a heap-allocated slice. This exists 17 | // because some operating systems place a limit on the number of 18 | // distinct mapped regions per process. As of this writing: 19 | // 20 | // Darwin unlimited 21 | // DragonFly 1000000 (vm.max_proc_mmap) 22 | // FreeBSD unlimited 23 | // Linux 65530 (vm.max_map_count) // TODO: query /proc/sys/vm/max_map_count? 24 | // NetBSD unlimited 25 | // OpenBSD unlimited 26 | var mmapLimit int32 = 1<<31 - 1 27 | 28 | func init() { 29 | // Linux is the only practically concerning OS. 30 | if runtime.GOOS == "linux" { 31 | mmapLimit = 30000 32 | } 33 | } 34 | 35 | func (r *Reader) sliceOS(length uint64) ([]byte, bool) { 36 | // For small slices, don't bother with the overhead of a 37 | // mapping, especially since we have no way to unmap it. 38 | const threshold = 16 << 10 39 | if length < threshold { 40 | return nil, false 41 | } 42 | 43 | // Have we reached the mmap limit? 44 | if atomic.AddInt32(&mmapLimit, -1) < 0 { 45 | atomic.AddInt32(&mmapLimit, 1) 46 | return nil, false 47 | } 48 | 49 | // Page-align the offset. 50 | off := r.Offset() 51 | align := syscall.Getpagesize() 52 | aoff := off &^ int64(align-1) 53 | 54 | data, err := syscall.Mmap(int(r.f.Fd()), aoff, int(length+uint64(off-aoff)), syscall.PROT_READ, syscall.MAP_SHARED|syscall.MAP_FILE) 55 | if err != nil { 56 | return nil, false 57 | } 58 | 59 | data = data[off-aoff:] 60 | r.MustSeek(int64(length), 1) 61 | return data, true 62 | } 63 | -------------------------------------------------------------------------------- /internal/go/src/bio/buf_nommap.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build !unix 6 | 7 | package bio 8 | 9 | func (r *Reader) sliceOS(length uint64) ([]byte, bool) { 10 | return nil, false 11 | } 12 | -------------------------------------------------------------------------------- /internal/go/src/bio/must.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package bio 6 | 7 | import ( 8 | "io" 9 | "log" 10 | ) 11 | 12 | // MustClose closes Closer c and calls log.Fatal if it returns a non-nil error. 13 | func MustClose(c io.Closer) { 14 | if err := c.Close(); err != nil { 15 | log.Fatal(err) 16 | } 17 | } 18 | 19 | // MustWriter returns a Writer that wraps the provided Writer, 20 | // except that it calls log.Fatal instead of returning a non-nil error. 21 | func MustWriter(w io.Writer) io.Writer { 22 | return mustWriter{w} 23 | } 24 | 25 | type mustWriter struct { 26 | w io.Writer 27 | } 28 | 29 | func (w mustWriter) Write(b []byte) (int, error) { 30 | n, err := w.w.Write(b) 31 | if err != nil { 32 | log.Fatal(err) 33 | } 34 | return n, nil 35 | } 36 | 37 | func (w mustWriter) WriteString(s string) (int, error) { 38 | n, err := io.WriteString(w.w, s) 39 | if err != nil { 40 | log.Fatal(err) 41 | } 42 | return n, nil 43 | } 44 | -------------------------------------------------------------------------------- /internal/go/src/buildcfg/zbootstrap.go: -------------------------------------------------------------------------------- 1 | // Code generated by go tool dist; DO NOT EDIT. 2 | 3 | package buildcfg 4 | 5 | import "runtime" 6 | 7 | const DefaultGO386 = `sse2` 8 | const DefaultGOAMD64 = `v1` 9 | const DefaultGOARM = `7` 10 | const DefaultGOARM64 = `v8.0` 11 | const DefaultGOMIPS = `hardfloat` 12 | const DefaultGOMIPS64 = `hardfloat` 13 | const DefaultGOPPC64 = `power8` 14 | const DefaultGORISCV64 = `rva20u64` 15 | const defaultGOEXPERIMENT = `` 16 | const defaultGO_EXTLINK_ENABLED = `` 17 | const defaultGO_LDSO = `` 18 | const version = `go1.24.0` 19 | const defaultGOOS = runtime.GOOS 20 | const defaultGOARCH = runtime.GOARCH 21 | const DefaultGOFIPS140 = `off` 22 | -------------------------------------------------------------------------------- /internal/go/src/disasm/expose.go: -------------------------------------------------------------------------------- 1 | package disasm 2 | 3 | import "loov.dev/lensm/internal/go/src/objfile" 4 | 5 | func (d *Disasm) Syms() []objfile.Sym { return d.syms } 6 | func (d *Disasm) TextStart() uint64 { return d.textStart } 7 | func (d *Disasm) TextEnd() uint64 { return d.textEnd } 8 | func (d *Disasm) PCLN() objfile.Liner { return d.pcln } 9 | -------------------------------------------------------------------------------- /internal/go/src/goarch/gengoarch.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build ignore 6 | 7 | package main 8 | 9 | import ( 10 | "bytes" 11 | "fmt" 12 | "log" 13 | "os" 14 | "strings" 15 | ) 16 | 17 | var goarches []string 18 | 19 | func main() { 20 | data, err := os.ReadFile("../../internal/syslist/syslist.go") 21 | if err != nil { 22 | log.Fatal(err) 23 | } 24 | const goarchPrefix = `var KnownArch = map[string]bool{` 25 | inGOARCH := false 26 | for _, line := range strings.Split(string(data), "\n") { 27 | if strings.HasPrefix(line, goarchPrefix) { 28 | inGOARCH = true 29 | } else if inGOARCH && strings.HasPrefix(line, "}") { 30 | break 31 | } else if inGOARCH { 32 | goarch := strings.Fields(line)[0] 33 | goarch = strings.TrimPrefix(goarch, `"`) 34 | goarch = strings.TrimSuffix(goarch, `":`) 35 | goarches = append(goarches, goarch) 36 | } 37 | } 38 | 39 | for _, target := range goarches { 40 | if target == "amd64p32" { 41 | continue 42 | } 43 | var buf bytes.Buffer 44 | fmt.Fprintf(&buf, "// Code generated by gengoarch.go using 'go generate'. DO NOT EDIT.\n\n") 45 | fmt.Fprintf(&buf, "//go:build %s\n\n", target) // must explicitly include target for bootstrapping purposes 46 | fmt.Fprintf(&buf, "package goarch\n\n") 47 | fmt.Fprintf(&buf, "const GOARCH = `%s`\n\n", target) 48 | for _, goarch := range goarches { 49 | value := 0 50 | if goarch == target { 51 | value = 1 52 | } 53 | fmt.Fprintf(&buf, "const Is%s = %d\n", strings.Title(goarch), value) 54 | } 55 | err := os.WriteFile("zgoarch_"+target+".go", buf.Bytes(), 0666) 56 | if err != nil { 57 | log.Fatal(err) 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /internal/go/src/goarch/goarch.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // package goarch contains GOARCH-specific constants. 6 | package goarch 7 | 8 | // The next line makes 'go generate' write the zgoarch*.go files with 9 | // per-arch information, including constants named $GOARCH for every 10 | // GOARCH. The constant is 1 on the current system, 0 otherwise; multiplying 11 | // by them is useful for defining GOARCH-specific constants. 12 | // 13 | //go:generate go run gengoarch.go 14 | 15 | type ArchFamilyType int 16 | 17 | const ( 18 | AMD64 ArchFamilyType = iota 19 | ARM 20 | ARM64 21 | I386 22 | LOONG64 23 | MIPS 24 | MIPS64 25 | PPC64 26 | RISCV64 27 | S390X 28 | WASM 29 | ) 30 | 31 | // PtrSize is the size of a pointer in bytes - unsafe.Sizeof(uintptr(0)) but as an ideal constant. 32 | // It is also the size of the machine's native word size (that is, 4 on 32-bit systems, 8 on 64-bit). 33 | const PtrSize = 4 << (^uintptr(0) >> 63) 34 | 35 | // ArchFamily is the architecture family (AMD64, ARM, ...) 36 | const ArchFamily ArchFamilyType = _ArchFamily 37 | 38 | // BigEndian reports whether the architecture is big-endian. 39 | const BigEndian = IsArmbe|IsArm64be|IsMips|IsMips64|IsPpc|IsPpc64|IsS390|IsS390x|IsSparc|IsSparc64 == 1 40 | 41 | // DefaultPhysPageSize is the default physical page size. 42 | const DefaultPhysPageSize = _DefaultPhysPageSize 43 | 44 | // PCQuantum is the minimal unit for a program counter (1 on x86, 4 on most other systems). 45 | // The various PC tables record PC deltas pre-divided by PCQuantum. 46 | const PCQuantum = _PCQuantum 47 | 48 | // Int64Align is the required alignment for a 64-bit integer (4 on 32-bit systems, 8 on 64-bit). 49 | const Int64Align = PtrSize 50 | 51 | // MinFrameSize is the size of the system-reserved words at the bottom 52 | // of a frame (just above the architectural stack pointer). 53 | // It is zero on x86 and PtrSize on most non-x86 (LR-based) systems. 54 | // On PowerPC it is larger, to cover three more reserved words: 55 | // the compiler word, the link editor word, and the TOC save word. 56 | const MinFrameSize = _MinFrameSize 57 | 58 | // StackAlign is the required alignment of the SP register. 59 | // The stack must be at least word aligned, but some architectures require more. 60 | const StackAlign = _StackAlign 61 | -------------------------------------------------------------------------------- /internal/go/src/goarch/goarch_386.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package goarch 6 | 7 | const ( 8 | _ArchFamily = I386 9 | _DefaultPhysPageSize = 4096 10 | _PCQuantum = 1 11 | _MinFrameSize = 0 12 | _StackAlign = PtrSize 13 | ) 14 | -------------------------------------------------------------------------------- /internal/go/src/goarch/goarch_amd64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package goarch 6 | 7 | const ( 8 | _ArchFamily = AMD64 9 | _DefaultPhysPageSize = 4096 10 | _PCQuantum = 1 11 | _MinFrameSize = 0 12 | _StackAlign = PtrSize 13 | ) 14 | -------------------------------------------------------------------------------- /internal/go/src/goarch/goarch_arm.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package goarch 6 | 7 | const ( 8 | _ArchFamily = ARM 9 | _DefaultPhysPageSize = 65536 10 | _PCQuantum = 4 11 | _MinFrameSize = 4 12 | _StackAlign = PtrSize 13 | ) 14 | -------------------------------------------------------------------------------- /internal/go/src/goarch/goarch_arm64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package goarch 6 | 7 | const ( 8 | _ArchFamily = ARM64 9 | _DefaultPhysPageSize = 65536 10 | _PCQuantum = 4 11 | _MinFrameSize = 8 12 | _StackAlign = 16 13 | ) 14 | -------------------------------------------------------------------------------- /internal/go/src/goarch/goarch_loong64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build loong64 6 | 7 | package goarch 8 | 9 | const ( 10 | _ArchFamily = LOONG64 11 | _DefaultPhysPageSize = 16384 12 | _PCQuantum = 4 13 | _MinFrameSize = 8 14 | _StackAlign = PtrSize 15 | ) 16 | -------------------------------------------------------------------------------- /internal/go/src/goarch/goarch_mips.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package goarch 6 | 7 | const ( 8 | _ArchFamily = MIPS 9 | _DefaultPhysPageSize = 65536 10 | _PCQuantum = 4 11 | _MinFrameSize = 4 12 | _StackAlign = PtrSize 13 | ) 14 | -------------------------------------------------------------------------------- /internal/go/src/goarch/goarch_mips64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package goarch 6 | 7 | const ( 8 | _ArchFamily = MIPS64 9 | _DefaultPhysPageSize = 16384 10 | _PCQuantum = 4 11 | _MinFrameSize = 8 12 | _StackAlign = PtrSize 13 | ) 14 | -------------------------------------------------------------------------------- /internal/go/src/goarch/goarch_mips64le.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package goarch 6 | 7 | const ( 8 | _ArchFamily = MIPS64 9 | _DefaultPhysPageSize = 16384 10 | _PCQuantum = 4 11 | _MinFrameSize = 8 12 | _StackAlign = PtrSize 13 | ) 14 | -------------------------------------------------------------------------------- /internal/go/src/goarch/goarch_mipsle.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package goarch 6 | 7 | const ( 8 | _ArchFamily = MIPS 9 | _DefaultPhysPageSize = 65536 10 | _PCQuantum = 4 11 | _MinFrameSize = 4 12 | _StackAlign = PtrSize 13 | ) 14 | -------------------------------------------------------------------------------- /internal/go/src/goarch/goarch_ppc64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package goarch 6 | 7 | const ( 8 | _ArchFamily = PPC64 9 | _DefaultPhysPageSize = 65536 10 | _PCQuantum = 4 11 | _MinFrameSize = 32 12 | _StackAlign = 16 13 | ) 14 | -------------------------------------------------------------------------------- /internal/go/src/goarch/goarch_ppc64le.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package goarch 6 | 7 | const ( 8 | _ArchFamily = PPC64 9 | _DefaultPhysPageSize = 65536 10 | _PCQuantum = 4 11 | _MinFrameSize = 32 12 | _StackAlign = 16 13 | ) 14 | -------------------------------------------------------------------------------- /internal/go/src/goarch/goarch_riscv64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package goarch 6 | 7 | const ( 8 | _ArchFamily = RISCV64 9 | _DefaultPhysPageSize = 4096 10 | _PCQuantum = 4 11 | _MinFrameSize = 8 12 | _StackAlign = PtrSize 13 | ) 14 | -------------------------------------------------------------------------------- /internal/go/src/goarch/goarch_s390x.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package goarch 6 | 7 | const ( 8 | _ArchFamily = S390X 9 | _DefaultPhysPageSize = 4096 10 | _PCQuantum = 2 11 | _MinFrameSize = 8 12 | _StackAlign = PtrSize 13 | ) 14 | -------------------------------------------------------------------------------- /internal/go/src/goarch/goarch_wasm.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package goarch 6 | 7 | const ( 8 | _ArchFamily = WASM 9 | _DefaultPhysPageSize = 65536 10 | _PCQuantum = 1 11 | _MinFrameSize = 0 12 | _StackAlign = PtrSize 13 | ) 14 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_386.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build 386 4 | 5 | package goarch 6 | 7 | const GOARCH = `386` 8 | 9 | const Is386 = 1 10 | const IsAmd64 = 0 11 | const IsAmd64p32 = 0 12 | const IsArm = 0 13 | const IsArmbe = 0 14 | const IsArm64 = 0 15 | const IsArm64be = 0 16 | const IsLoong64 = 0 17 | const IsMips = 0 18 | const IsMipsle = 0 19 | const IsMips64 = 0 20 | const IsMips64le = 0 21 | const IsMips64p32 = 0 22 | const IsMips64p32le = 0 23 | const IsPpc = 0 24 | const IsPpc64 = 0 25 | const IsPpc64le = 0 26 | const IsRiscv = 0 27 | const IsRiscv64 = 0 28 | const IsS390 = 0 29 | const IsS390x = 0 30 | const IsSparc = 0 31 | const IsSparc64 = 0 32 | const IsWasm = 0 33 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_amd64.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build amd64 4 | 5 | package goarch 6 | 7 | const GOARCH = `amd64` 8 | 9 | const Is386 = 0 10 | const IsAmd64 = 1 11 | const IsAmd64p32 = 0 12 | const IsArm = 0 13 | const IsArmbe = 0 14 | const IsArm64 = 0 15 | const IsArm64be = 0 16 | const IsLoong64 = 0 17 | const IsMips = 0 18 | const IsMipsle = 0 19 | const IsMips64 = 0 20 | const IsMips64le = 0 21 | const IsMips64p32 = 0 22 | const IsMips64p32le = 0 23 | const IsPpc = 0 24 | const IsPpc64 = 0 25 | const IsPpc64le = 0 26 | const IsRiscv = 0 27 | const IsRiscv64 = 0 28 | const IsS390 = 0 29 | const IsS390x = 0 30 | const IsSparc = 0 31 | const IsSparc64 = 0 32 | const IsWasm = 0 33 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_arm.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build arm 4 | 5 | package goarch 6 | 7 | const GOARCH = `arm` 8 | 9 | const Is386 = 0 10 | const IsAmd64 = 0 11 | const IsAmd64p32 = 0 12 | const IsArm = 1 13 | const IsArmbe = 0 14 | const IsArm64 = 0 15 | const IsArm64be = 0 16 | const IsLoong64 = 0 17 | const IsMips = 0 18 | const IsMipsle = 0 19 | const IsMips64 = 0 20 | const IsMips64le = 0 21 | const IsMips64p32 = 0 22 | const IsMips64p32le = 0 23 | const IsPpc = 0 24 | const IsPpc64 = 0 25 | const IsPpc64le = 0 26 | const IsRiscv = 0 27 | const IsRiscv64 = 0 28 | const IsS390 = 0 29 | const IsS390x = 0 30 | const IsSparc = 0 31 | const IsSparc64 = 0 32 | const IsWasm = 0 33 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_arm64.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build arm64 4 | 5 | package goarch 6 | 7 | const GOARCH = `arm64` 8 | 9 | const Is386 = 0 10 | const IsAmd64 = 0 11 | const IsAmd64p32 = 0 12 | const IsArm = 0 13 | const IsArmbe = 0 14 | const IsArm64 = 1 15 | const IsArm64be = 0 16 | const IsLoong64 = 0 17 | const IsMips = 0 18 | const IsMipsle = 0 19 | const IsMips64 = 0 20 | const IsMips64le = 0 21 | const IsMips64p32 = 0 22 | const IsMips64p32le = 0 23 | const IsPpc = 0 24 | const IsPpc64 = 0 25 | const IsPpc64le = 0 26 | const IsRiscv = 0 27 | const IsRiscv64 = 0 28 | const IsS390 = 0 29 | const IsS390x = 0 30 | const IsSparc = 0 31 | const IsSparc64 = 0 32 | const IsWasm = 0 33 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_arm64be.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build arm64be 4 | 5 | package goarch 6 | 7 | const GOARCH = `arm64be` 8 | 9 | const Is386 = 0 10 | const IsAmd64 = 0 11 | const IsAmd64p32 = 0 12 | const IsArm = 0 13 | const IsArmbe = 0 14 | const IsArm64 = 0 15 | const IsArm64be = 1 16 | const IsLoong64 = 0 17 | const IsMips = 0 18 | const IsMipsle = 0 19 | const IsMips64 = 0 20 | const IsMips64le = 0 21 | const IsMips64p32 = 0 22 | const IsMips64p32le = 0 23 | const IsPpc = 0 24 | const IsPpc64 = 0 25 | const IsPpc64le = 0 26 | const IsRiscv = 0 27 | const IsRiscv64 = 0 28 | const IsS390 = 0 29 | const IsS390x = 0 30 | const IsSparc = 0 31 | const IsSparc64 = 0 32 | const IsWasm = 0 33 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_armbe.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build armbe 4 | 5 | package goarch 6 | 7 | const GOARCH = `armbe` 8 | 9 | const Is386 = 0 10 | const IsAmd64 = 0 11 | const IsAmd64p32 = 0 12 | const IsArm = 0 13 | const IsArmbe = 1 14 | const IsArm64 = 0 15 | const IsArm64be = 0 16 | const IsLoong64 = 0 17 | const IsMips = 0 18 | const IsMipsle = 0 19 | const IsMips64 = 0 20 | const IsMips64le = 0 21 | const IsMips64p32 = 0 22 | const IsMips64p32le = 0 23 | const IsPpc = 0 24 | const IsPpc64 = 0 25 | const IsPpc64le = 0 26 | const IsRiscv = 0 27 | const IsRiscv64 = 0 28 | const IsS390 = 0 29 | const IsS390x = 0 30 | const IsSparc = 0 31 | const IsSparc64 = 0 32 | const IsWasm = 0 33 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_loong64.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build loong64 4 | 5 | package goarch 6 | 7 | const GOARCH = `loong64` 8 | 9 | const Is386 = 0 10 | const IsAmd64 = 0 11 | const IsAmd64p32 = 0 12 | const IsArm = 0 13 | const IsArmbe = 0 14 | const IsArm64 = 0 15 | const IsArm64be = 0 16 | const IsLoong64 = 1 17 | const IsMips = 0 18 | const IsMipsle = 0 19 | const IsMips64 = 0 20 | const IsMips64le = 0 21 | const IsMips64p32 = 0 22 | const IsMips64p32le = 0 23 | const IsPpc = 0 24 | const IsPpc64 = 0 25 | const IsPpc64le = 0 26 | const IsRiscv = 0 27 | const IsRiscv64 = 0 28 | const IsS390 = 0 29 | const IsS390x = 0 30 | const IsSparc = 0 31 | const IsSparc64 = 0 32 | const IsWasm = 0 33 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_mips.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build mips 4 | 5 | package goarch 6 | 7 | const GOARCH = `mips` 8 | 9 | const Is386 = 0 10 | const IsAmd64 = 0 11 | const IsAmd64p32 = 0 12 | const IsArm = 0 13 | const IsArmbe = 0 14 | const IsArm64 = 0 15 | const IsArm64be = 0 16 | const IsLoong64 = 0 17 | const IsMips = 1 18 | const IsMipsle = 0 19 | const IsMips64 = 0 20 | const IsMips64le = 0 21 | const IsMips64p32 = 0 22 | const IsMips64p32le = 0 23 | const IsPpc = 0 24 | const IsPpc64 = 0 25 | const IsPpc64le = 0 26 | const IsRiscv = 0 27 | const IsRiscv64 = 0 28 | const IsS390 = 0 29 | const IsS390x = 0 30 | const IsSparc = 0 31 | const IsSparc64 = 0 32 | const IsWasm = 0 33 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_mips64.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build mips64 4 | 5 | package goarch 6 | 7 | const GOARCH = `mips64` 8 | 9 | const Is386 = 0 10 | const IsAmd64 = 0 11 | const IsAmd64p32 = 0 12 | const IsArm = 0 13 | const IsArmbe = 0 14 | const IsArm64 = 0 15 | const IsArm64be = 0 16 | const IsLoong64 = 0 17 | const IsMips = 0 18 | const IsMipsle = 0 19 | const IsMips64 = 1 20 | const IsMips64le = 0 21 | const IsMips64p32 = 0 22 | const IsMips64p32le = 0 23 | const IsPpc = 0 24 | const IsPpc64 = 0 25 | const IsPpc64le = 0 26 | const IsRiscv = 0 27 | const IsRiscv64 = 0 28 | const IsS390 = 0 29 | const IsS390x = 0 30 | const IsSparc = 0 31 | const IsSparc64 = 0 32 | const IsWasm = 0 33 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_mips64le.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build mips64le 4 | 5 | package goarch 6 | 7 | const GOARCH = `mips64le` 8 | 9 | const Is386 = 0 10 | const IsAmd64 = 0 11 | const IsAmd64p32 = 0 12 | const IsArm = 0 13 | const IsArmbe = 0 14 | const IsArm64 = 0 15 | const IsArm64be = 0 16 | const IsLoong64 = 0 17 | const IsMips = 0 18 | const IsMipsle = 0 19 | const IsMips64 = 0 20 | const IsMips64le = 1 21 | const IsMips64p32 = 0 22 | const IsMips64p32le = 0 23 | const IsPpc = 0 24 | const IsPpc64 = 0 25 | const IsPpc64le = 0 26 | const IsRiscv = 0 27 | const IsRiscv64 = 0 28 | const IsS390 = 0 29 | const IsS390x = 0 30 | const IsSparc = 0 31 | const IsSparc64 = 0 32 | const IsWasm = 0 33 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_mips64p32.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build mips64p32 4 | 5 | package goarch 6 | 7 | const GOARCH = `mips64p32` 8 | 9 | const Is386 = 0 10 | const IsAmd64 = 0 11 | const IsAmd64p32 = 0 12 | const IsArm = 0 13 | const IsArmbe = 0 14 | const IsArm64 = 0 15 | const IsArm64be = 0 16 | const IsLoong64 = 0 17 | const IsMips = 0 18 | const IsMipsle = 0 19 | const IsMips64 = 0 20 | const IsMips64le = 0 21 | const IsMips64p32 = 1 22 | const IsMips64p32le = 0 23 | const IsPpc = 0 24 | const IsPpc64 = 0 25 | const IsPpc64le = 0 26 | const IsRiscv = 0 27 | const IsRiscv64 = 0 28 | const IsS390 = 0 29 | const IsS390x = 0 30 | const IsSparc = 0 31 | const IsSparc64 = 0 32 | const IsWasm = 0 33 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_mips64p32le.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build mips64p32le 4 | 5 | package goarch 6 | 7 | const GOARCH = `mips64p32le` 8 | 9 | const Is386 = 0 10 | const IsAmd64 = 0 11 | const IsAmd64p32 = 0 12 | const IsArm = 0 13 | const IsArmbe = 0 14 | const IsArm64 = 0 15 | const IsArm64be = 0 16 | const IsLoong64 = 0 17 | const IsMips = 0 18 | const IsMipsle = 0 19 | const IsMips64 = 0 20 | const IsMips64le = 0 21 | const IsMips64p32 = 0 22 | const IsMips64p32le = 1 23 | const IsPpc = 0 24 | const IsPpc64 = 0 25 | const IsPpc64le = 0 26 | const IsRiscv = 0 27 | const IsRiscv64 = 0 28 | const IsS390 = 0 29 | const IsS390x = 0 30 | const IsSparc = 0 31 | const IsSparc64 = 0 32 | const IsWasm = 0 33 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_mipsle.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build mipsle 4 | 5 | package goarch 6 | 7 | const GOARCH = `mipsle` 8 | 9 | const Is386 = 0 10 | const IsAmd64 = 0 11 | const IsAmd64p32 = 0 12 | const IsArm = 0 13 | const IsArmbe = 0 14 | const IsArm64 = 0 15 | const IsArm64be = 0 16 | const IsLoong64 = 0 17 | const IsMips = 0 18 | const IsMipsle = 1 19 | const IsMips64 = 0 20 | const IsMips64le = 0 21 | const IsMips64p32 = 0 22 | const IsMips64p32le = 0 23 | const IsPpc = 0 24 | const IsPpc64 = 0 25 | const IsPpc64le = 0 26 | const IsRiscv = 0 27 | const IsRiscv64 = 0 28 | const IsS390 = 0 29 | const IsS390x = 0 30 | const IsSparc = 0 31 | const IsSparc64 = 0 32 | const IsWasm = 0 33 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_ppc.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build ppc 4 | 5 | package goarch 6 | 7 | const GOARCH = `ppc` 8 | 9 | const Is386 = 0 10 | const IsAmd64 = 0 11 | const IsAmd64p32 = 0 12 | const IsArm = 0 13 | const IsArmbe = 0 14 | const IsArm64 = 0 15 | const IsArm64be = 0 16 | const IsLoong64 = 0 17 | const IsMips = 0 18 | const IsMipsle = 0 19 | const IsMips64 = 0 20 | const IsMips64le = 0 21 | const IsMips64p32 = 0 22 | const IsMips64p32le = 0 23 | const IsPpc = 1 24 | const IsPpc64 = 0 25 | const IsPpc64le = 0 26 | const IsRiscv = 0 27 | const IsRiscv64 = 0 28 | const IsS390 = 0 29 | const IsS390x = 0 30 | const IsSparc = 0 31 | const IsSparc64 = 0 32 | const IsWasm = 0 33 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_ppc64.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build ppc64 4 | 5 | package goarch 6 | 7 | const GOARCH = `ppc64` 8 | 9 | const Is386 = 0 10 | const IsAmd64 = 0 11 | const IsAmd64p32 = 0 12 | const IsArm = 0 13 | const IsArmbe = 0 14 | const IsArm64 = 0 15 | const IsArm64be = 0 16 | const IsLoong64 = 0 17 | const IsMips = 0 18 | const IsMipsle = 0 19 | const IsMips64 = 0 20 | const IsMips64le = 0 21 | const IsMips64p32 = 0 22 | const IsMips64p32le = 0 23 | const IsPpc = 0 24 | const IsPpc64 = 1 25 | const IsPpc64le = 0 26 | const IsRiscv = 0 27 | const IsRiscv64 = 0 28 | const IsS390 = 0 29 | const IsS390x = 0 30 | const IsSparc = 0 31 | const IsSparc64 = 0 32 | const IsWasm = 0 33 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_ppc64le.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build ppc64le 4 | 5 | package goarch 6 | 7 | const GOARCH = `ppc64le` 8 | 9 | const Is386 = 0 10 | const IsAmd64 = 0 11 | const IsAmd64p32 = 0 12 | const IsArm = 0 13 | const IsArmbe = 0 14 | const IsArm64 = 0 15 | const IsArm64be = 0 16 | const IsLoong64 = 0 17 | const IsMips = 0 18 | const IsMipsle = 0 19 | const IsMips64 = 0 20 | const IsMips64le = 0 21 | const IsMips64p32 = 0 22 | const IsMips64p32le = 0 23 | const IsPpc = 0 24 | const IsPpc64 = 0 25 | const IsPpc64le = 1 26 | const IsRiscv = 0 27 | const IsRiscv64 = 0 28 | const IsS390 = 0 29 | const IsS390x = 0 30 | const IsSparc = 0 31 | const IsSparc64 = 0 32 | const IsWasm = 0 33 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_riscv.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build riscv 4 | 5 | package goarch 6 | 7 | const GOARCH = `riscv` 8 | 9 | const Is386 = 0 10 | const IsAmd64 = 0 11 | const IsAmd64p32 = 0 12 | const IsArm = 0 13 | const IsArmbe = 0 14 | const IsArm64 = 0 15 | const IsArm64be = 0 16 | const IsLoong64 = 0 17 | const IsMips = 0 18 | const IsMipsle = 0 19 | const IsMips64 = 0 20 | const IsMips64le = 0 21 | const IsMips64p32 = 0 22 | const IsMips64p32le = 0 23 | const IsPpc = 0 24 | const IsPpc64 = 0 25 | const IsPpc64le = 0 26 | const IsRiscv = 1 27 | const IsRiscv64 = 0 28 | const IsS390 = 0 29 | const IsS390x = 0 30 | const IsSparc = 0 31 | const IsSparc64 = 0 32 | const IsWasm = 0 33 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_riscv64.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build riscv64 4 | 5 | package goarch 6 | 7 | const GOARCH = `riscv64` 8 | 9 | const Is386 = 0 10 | const IsAmd64 = 0 11 | const IsAmd64p32 = 0 12 | const IsArm = 0 13 | const IsArmbe = 0 14 | const IsArm64 = 0 15 | const IsArm64be = 0 16 | const IsLoong64 = 0 17 | const IsMips = 0 18 | const IsMipsle = 0 19 | const IsMips64 = 0 20 | const IsMips64le = 0 21 | const IsMips64p32 = 0 22 | const IsMips64p32le = 0 23 | const IsPpc = 0 24 | const IsPpc64 = 0 25 | const IsPpc64le = 0 26 | const IsRiscv = 0 27 | const IsRiscv64 = 1 28 | const IsS390 = 0 29 | const IsS390x = 0 30 | const IsSparc = 0 31 | const IsSparc64 = 0 32 | const IsWasm = 0 33 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_s390.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build s390 4 | 5 | package goarch 6 | 7 | const GOARCH = `s390` 8 | 9 | const Is386 = 0 10 | const IsAmd64 = 0 11 | const IsAmd64p32 = 0 12 | const IsArm = 0 13 | const IsArmbe = 0 14 | const IsArm64 = 0 15 | const IsArm64be = 0 16 | const IsLoong64 = 0 17 | const IsMips = 0 18 | const IsMipsle = 0 19 | const IsMips64 = 0 20 | const IsMips64le = 0 21 | const IsMips64p32 = 0 22 | const IsMips64p32le = 0 23 | const IsPpc = 0 24 | const IsPpc64 = 0 25 | const IsPpc64le = 0 26 | const IsRiscv = 0 27 | const IsRiscv64 = 0 28 | const IsS390 = 1 29 | const IsS390x = 0 30 | const IsSparc = 0 31 | const IsSparc64 = 0 32 | const IsWasm = 0 33 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_s390x.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build s390x 4 | 5 | package goarch 6 | 7 | const GOARCH = `s390x` 8 | 9 | const Is386 = 0 10 | const IsAmd64 = 0 11 | const IsAmd64p32 = 0 12 | const IsArm = 0 13 | const IsArmbe = 0 14 | const IsArm64 = 0 15 | const IsArm64be = 0 16 | const IsLoong64 = 0 17 | const IsMips = 0 18 | const IsMipsle = 0 19 | const IsMips64 = 0 20 | const IsMips64le = 0 21 | const IsMips64p32 = 0 22 | const IsMips64p32le = 0 23 | const IsPpc = 0 24 | const IsPpc64 = 0 25 | const IsPpc64le = 0 26 | const IsRiscv = 0 27 | const IsRiscv64 = 0 28 | const IsS390 = 0 29 | const IsS390x = 1 30 | const IsSparc = 0 31 | const IsSparc64 = 0 32 | const IsWasm = 0 33 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_sparc.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build sparc 4 | 5 | package goarch 6 | 7 | const GOARCH = `sparc` 8 | 9 | const Is386 = 0 10 | const IsAmd64 = 0 11 | const IsAmd64p32 = 0 12 | const IsArm = 0 13 | const IsArmbe = 0 14 | const IsArm64 = 0 15 | const IsArm64be = 0 16 | const IsLoong64 = 0 17 | const IsMips = 0 18 | const IsMipsle = 0 19 | const IsMips64 = 0 20 | const IsMips64le = 0 21 | const IsMips64p32 = 0 22 | const IsMips64p32le = 0 23 | const IsPpc = 0 24 | const IsPpc64 = 0 25 | const IsPpc64le = 0 26 | const IsRiscv = 0 27 | const IsRiscv64 = 0 28 | const IsS390 = 0 29 | const IsS390x = 0 30 | const IsSparc = 1 31 | const IsSparc64 = 0 32 | const IsWasm = 0 33 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_sparc64.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build sparc64 4 | 5 | package goarch 6 | 7 | const GOARCH = `sparc64` 8 | 9 | const Is386 = 0 10 | const IsAmd64 = 0 11 | const IsAmd64p32 = 0 12 | const IsArm = 0 13 | const IsArmbe = 0 14 | const IsArm64 = 0 15 | const IsArm64be = 0 16 | const IsLoong64 = 0 17 | const IsMips = 0 18 | const IsMipsle = 0 19 | const IsMips64 = 0 20 | const IsMips64le = 0 21 | const IsMips64p32 = 0 22 | const IsMips64p32le = 0 23 | const IsPpc = 0 24 | const IsPpc64 = 0 25 | const IsPpc64le = 0 26 | const IsRiscv = 0 27 | const IsRiscv64 = 0 28 | const IsS390 = 0 29 | const IsS390x = 0 30 | const IsSparc = 0 31 | const IsSparc64 = 1 32 | const IsWasm = 0 33 | -------------------------------------------------------------------------------- /internal/go/src/goarch/zgoarch_wasm.go: -------------------------------------------------------------------------------- 1 | // Code generated by gengoarch.go using 'go generate'. DO NOT EDIT. 2 | 3 | //go:build wasm 4 | 5 | package goarch 6 | 7 | const GOARCH = `wasm` 8 | 9 | const Is386 = 0 10 | const IsAmd64 = 0 11 | const IsAmd64p32 = 0 12 | const IsArm = 0 13 | const IsArmbe = 0 14 | const IsArm64 = 0 15 | const IsArm64be = 0 16 | const IsLoong64 = 0 17 | const IsMips = 0 18 | const IsMipsle = 0 19 | const IsMips64 = 0 20 | const IsMips64le = 0 21 | const IsMips64p32 = 0 22 | const IsMips64p32le = 0 23 | const IsPpc = 0 24 | const IsPpc64 = 0 25 | const IsPpc64le = 0 26 | const IsRiscv = 0 27 | const IsRiscv64 = 0 28 | const IsS390 = 0 29 | const IsS390x = 0 30 | const IsSparc = 0 31 | const IsSparc64 = 0 32 | const IsWasm = 1 33 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_aliastypeparams_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.aliastypeparams 4 | 5 | package goexperiment 6 | 7 | const AliasTypeParams = false 8 | const AliasTypeParamsInt = 0 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_aliastypeparams_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.aliastypeparams 4 | 5 | package goexperiment 6 | 7 | const AliasTypeParams = true 8 | const AliasTypeParamsInt = 1 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_arenas_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.arenas 4 | 5 | package goexperiment 6 | 7 | const Arenas = false 8 | const ArenasInt = 0 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_arenas_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.arenas 4 | 5 | package goexperiment 6 | 7 | const Arenas = true 8 | const ArenasInt = 1 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_boringcrypto_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.boringcrypto 4 | 5 | package goexperiment 6 | 7 | const BoringCrypto = false 8 | const BoringCryptoInt = 0 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_boringcrypto_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.boringcrypto 4 | 5 | package goexperiment 6 | 7 | const BoringCrypto = true 8 | const BoringCryptoInt = 1 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_cacheprog_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.cacheprog 4 | 5 | package goexperiment 6 | 7 | const CacheProg = false 8 | const CacheProgInt = 0 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_cacheprog_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.cacheprog 4 | 5 | package goexperiment 6 | 7 | const CacheProg = true 8 | const CacheProgInt = 1 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_cgocheck2_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.cgocheck2 4 | 5 | package goexperiment 6 | 7 | const CgoCheck2 = false 8 | const CgoCheck2Int = 0 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_cgocheck2_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.cgocheck2 4 | 5 | package goexperiment 6 | 7 | const CgoCheck2 = true 8 | const CgoCheck2Int = 1 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_coverageredesign_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.coverageredesign 4 | 5 | package goexperiment 6 | 7 | const CoverageRedesign = false 8 | const CoverageRedesignInt = 0 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_coverageredesign_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.coverageredesign 4 | 5 | package goexperiment 6 | 7 | const CoverageRedesign = true 8 | const CoverageRedesignInt = 1 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_fieldtrack_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.fieldtrack 4 | 5 | package goexperiment 6 | 7 | const FieldTrack = false 8 | const FieldTrackInt = 0 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_fieldtrack_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.fieldtrack 4 | 5 | package goexperiment 6 | 7 | const FieldTrack = true 8 | const FieldTrackInt = 1 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_heapminimum512kib_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.heapminimum512kib 4 | 5 | package goexperiment 6 | 7 | const HeapMinimum512KiB = false 8 | const HeapMinimum512KiBInt = 0 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_heapminimum512kib_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.heapminimum512kib 4 | 5 | package goexperiment 6 | 7 | const HeapMinimum512KiB = true 8 | const HeapMinimum512KiBInt = 1 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_loopvar_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.loopvar 4 | 5 | package goexperiment 6 | 7 | const LoopVar = false 8 | const LoopVarInt = 0 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_loopvar_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.loopvar 4 | 5 | package goexperiment 6 | 7 | const LoopVar = true 8 | const LoopVarInt = 1 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_newinliner_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.newinliner 4 | 5 | package goexperiment 6 | 7 | const NewInliner = false 8 | const NewInlinerInt = 0 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_newinliner_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.newinliner 4 | 5 | package goexperiment 6 | 7 | const NewInliner = true 8 | const NewInlinerInt = 1 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_preemptibleloops_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.preemptibleloops 4 | 5 | package goexperiment 6 | 7 | const PreemptibleLoops = false 8 | const PreemptibleLoopsInt = 0 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_preemptibleloops_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.preemptibleloops 4 | 5 | package goexperiment 6 | 7 | const PreemptibleLoops = true 8 | const PreemptibleLoopsInt = 1 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_rangefunc_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.rangefunc 4 | 5 | package goexperiment 6 | 7 | const RangeFunc = false 8 | const RangeFuncInt = 0 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_rangefunc_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.rangefunc 4 | 5 | package goexperiment 6 | 7 | const RangeFunc = true 8 | const RangeFuncInt = 1 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_regabiargs_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.regabiargs 4 | 5 | package goexperiment 6 | 7 | const RegabiArgs = false 8 | const RegabiArgsInt = 0 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_regabiargs_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.regabiargs 4 | 5 | package goexperiment 6 | 7 | const RegabiArgs = true 8 | const RegabiArgsInt = 1 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_regabiwrappers_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.regabiwrappers 4 | 5 | package goexperiment 6 | 7 | const RegabiWrappers = false 8 | const RegabiWrappersInt = 0 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_regabiwrappers_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.regabiwrappers 4 | 5 | package goexperiment 6 | 7 | const RegabiWrappers = true 8 | const RegabiWrappersInt = 1 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_spinbitmutex_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.spinbitmutex 4 | 5 | package goexperiment 6 | 7 | const SpinbitMutex = false 8 | const SpinbitMutexInt = 0 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_spinbitmutex_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.spinbitmutex 4 | 5 | package goexperiment 6 | 7 | const SpinbitMutex = true 8 | const SpinbitMutexInt = 1 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_staticlockranking_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.staticlockranking 4 | 5 | package goexperiment 6 | 7 | const StaticLockRanking = false 8 | const StaticLockRankingInt = 0 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_staticlockranking_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.staticlockranking 4 | 5 | package goexperiment 6 | 7 | const StaticLockRanking = true 8 | const StaticLockRankingInt = 1 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_swissmap_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.swissmap 4 | 5 | package goexperiment 6 | 7 | const SwissMap = false 8 | const SwissMapInt = 0 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_swissmap_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.swissmap 4 | 5 | package goexperiment 6 | 7 | const SwissMap = true 8 | const SwissMapInt = 1 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_synchashtriemap_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.synchashtriemap 4 | 5 | package goexperiment 6 | 7 | const SyncHashTrieMap = false 8 | const SyncHashTrieMapInt = 0 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_synchashtriemap_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.synchashtriemap 4 | 5 | package goexperiment 6 | 7 | const SyncHashTrieMap = true 8 | const SyncHashTrieMapInt = 1 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_synctest_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.synctest 4 | 5 | package goexperiment 6 | 7 | const Synctest = false 8 | const SynctestInt = 0 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/exp_synctest_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.synctest 4 | 5 | package goexperiment 6 | 7 | const Synctest = true 8 | const SynctestInt = 1 9 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/flags.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package goexperiment implements support for toolchain experiments. 6 | // 7 | // Toolchain experiments are controlled by the GOEXPERIMENT 8 | // environment variable. GOEXPERIMENT is a comma-separated list of 9 | // experiment names. GOEXPERIMENT can be set at make.bash time, which 10 | // sets the default experiments for binaries built with the tool 11 | // chain; or it can be set at build time. GOEXPERIMENT can also be set 12 | // to "none", which disables any experiments that were enabled at 13 | // make.bash time. 14 | // 15 | // Experiments are exposed to the build in the following ways: 16 | // 17 | // - Build tag goexperiment.x is set if experiment x (lower case) is 18 | // enabled. 19 | // 20 | // - For each experiment x (in camel case), this package contains a 21 | // boolean constant x and an integer constant xInt. 22 | // 23 | // - In runtime assembly, the macro GOEXPERIMENT_x is defined if 24 | // experiment x (lower case) is enabled. 25 | // 26 | // In the toolchain, the set of experiments enabled for the current 27 | // build should be accessed via objabi.Experiment. 28 | // 29 | // The set of experiments is included in the output of runtime.Version() 30 | // and "go version " if it differs from the default experiments. 31 | // 32 | // For the set of experiments supported by the current toolchain, see 33 | // "go doc goexperiment.Flags". 34 | // 35 | // Note that this package defines the set of experiments (in Flags) 36 | // and records the experiments that were enabled when the package 37 | // was compiled (as boolean and integer constants). 38 | // 39 | // Note especially that this package does not itself change behavior 40 | // at run time based on the GOEXPERIMENT variable. 41 | // The code used in builds to interpret the GOEXPERIMENT variable 42 | // is in the separate package internal/buildcfg. 43 | package goexperiment 44 | 45 | //go:generate go run mkconsts.go 46 | 47 | // Flags is the set of experiments that can be enabled or disabled in 48 | // the current toolchain. 49 | // 50 | // When specified in the GOEXPERIMENT environment variable or as build 51 | // tags, experiments use the strings.ToLower of their field name. 52 | // 53 | // For the baseline experimental configuration, see 54 | // [internal/buildcfg.ParseGOEXPERIMENT]. 55 | // 56 | // If you change this struct definition, run "go generate". 57 | type Flags struct { 58 | FieldTrack bool 59 | PreemptibleLoops bool 60 | StaticLockRanking bool 61 | BoringCrypto bool 62 | 63 | // Regabi is split into several sub-experiments that can be 64 | // enabled individually. Not all combinations work. 65 | // The "regabi" GOEXPERIMENT is an alias for all "working" 66 | // subexperiments. 67 | 68 | // RegabiWrappers enables ABI wrappers for calling between 69 | // ABI0 and ABIInternal functions. Without this, the ABIs are 70 | // assumed to be identical so cross-ABI calls are direct. 71 | RegabiWrappers bool 72 | // RegabiArgs enables register arguments/results in all 73 | // compiled Go functions. 74 | // 75 | // Requires wrappers (to do ABI translation), and reflect (so 76 | // reflection calls use registers). 77 | RegabiArgs bool 78 | 79 | // HeapMinimum512KiB reduces the minimum heap size to 512 KiB. 80 | // 81 | // This was originally reduced as part of PacerRedesign, but 82 | // has been broken out to its own experiment that is disabled 83 | // by default. 84 | HeapMinimum512KiB bool 85 | 86 | // CoverageRedesign enables the new compiler-based code coverage 87 | // tooling. 88 | CoverageRedesign bool 89 | 90 | // Arenas causes the "arena" standard library package to be visible 91 | // to the outside world. 92 | Arenas bool 93 | 94 | // CgoCheck2 enables an expensive cgo rule checker. 95 | // When this experiment is enabled, cgo rule checks occur regardless 96 | // of the GODEBUG=cgocheck setting provided at runtime. 97 | CgoCheck2 bool 98 | 99 | // LoopVar changes loop semantics so that each iteration gets its own 100 | // copy of the iteration variable. 101 | LoopVar bool 102 | 103 | // CacheProg adds support to cmd/go to use a child process to implement 104 | // the build cache; see https://github.com/golang/go/issues/59719. 105 | CacheProg bool 106 | 107 | // NewInliner enables a new+improved version of the function 108 | // inlining phase within the Go compiler. 109 | NewInliner bool 110 | 111 | // RangeFunc enables range over func. 112 | RangeFunc bool 113 | 114 | // AliasTypeParams enables type parameters for alias types. 115 | // Requires that gotypesalias=1 is set with GODEBUG. 116 | // This flag will be removed with Go 1.25. 117 | AliasTypeParams bool 118 | 119 | // SwissMap enables the SwissTable-based map implementation. 120 | SwissMap bool 121 | 122 | // SpinbitMutex enables the new "spinbit" mutex implementation on supported 123 | // platforms. See https://go.dev/issue/68578. 124 | SpinbitMutex bool 125 | 126 | // SyncHashTrieMap enables the HashTrieMap sync.Map implementation. 127 | SyncHashTrieMap bool 128 | 129 | // Synctest enables the testing/synctest package. 130 | Synctest bool 131 | } 132 | -------------------------------------------------------------------------------- /internal/go/src/goexperiment/mkconsts.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build ignore 6 | 7 | // mkconsts generates const definition files for each GOEXPERIMENT. 8 | package main 9 | 10 | import ( 11 | "bytes" 12 | "fmt" 13 | "loov.dev/lensm/internal/go/src/goexperiment" 14 | "log" 15 | "os" 16 | "reflect" 17 | "strings" 18 | ) 19 | 20 | func main() { 21 | // Delete existing experiment constant files. 22 | ents, err := os.ReadDir(".") 23 | if err != nil { 24 | log.Fatal(err) 25 | } 26 | for _, ent := range ents { 27 | name := ent.Name() 28 | if !strings.HasPrefix(name, "exp_") { 29 | continue 30 | } 31 | // Check that this is definitely a generated file. 32 | data, err := os.ReadFile(name) 33 | if err != nil { 34 | log.Fatalf("reading %s: %v", name, err) 35 | } 36 | if !bytes.Contains(data, []byte("Code generated by mkconsts")) { 37 | log.Fatalf("%s: expected generated file", name) 38 | } 39 | if err := os.Remove(name); err != nil { 40 | log.Fatal(err) 41 | } 42 | } 43 | 44 | // Generate new experiment constant files. 45 | rt := reflect.TypeOf(&goexperiment.Flags{}).Elem() 46 | for i := 0; i < rt.NumField(); i++ { 47 | f := rt.Field(i).Name 48 | buildTag := "goexperiment." + strings.ToLower(f) 49 | for _, val := range []bool{false, true} { 50 | name := fmt.Sprintf("exp_%s_%s.go", strings.ToLower(f), pick(val, "off", "on")) 51 | data := fmt.Sprintf(`// Code generated by mkconsts.go. DO NOT EDIT. 52 | 53 | //go:build %s%s 54 | 55 | package goexperiment 56 | 57 | const %s = %v 58 | const %sInt = %s 59 | `, pick(val, "!", ""), buildTag, f, val, f, pick(val, "0", "1")) 60 | if err := os.WriteFile(name, []byte(data), 0666); err != nil { 61 | log.Fatalf("writing %s: %v", name, err) 62 | } 63 | } 64 | } 65 | } 66 | 67 | func pick(v bool, f, t string) string { 68 | if v { 69 | return t 70 | } 71 | return f 72 | } 73 | -------------------------------------------------------------------------------- /internal/go/src/goobj/builtin.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package goobj 6 | 7 | import "loov.dev/lensm/internal/go/src/buildcfg" 8 | 9 | // Builtin (compiler-generated) function references appear 10 | // frequently. We assign special indices for them, so they 11 | // don't need to be referenced by name. 12 | 13 | // NBuiltin returns the number of listed builtin 14 | // symbols. 15 | func NBuiltin() int { 16 | return len(builtins) 17 | } 18 | 19 | // BuiltinName returns the name and ABI of the i-th 20 | // builtin symbol. 21 | func BuiltinName(i int) (string, int) { 22 | return builtins[i].name, builtins[i].abi 23 | } 24 | 25 | // BuiltinIdx returns the index of the builtin with the 26 | // given name and abi, or -1 if it is not a builtin. 27 | func BuiltinIdx(name string, abi int) int { 28 | i, ok := builtinMap[name] 29 | if !ok { 30 | return -1 31 | } 32 | if buildcfg.Experiment.RegabiWrappers && builtins[i].abi != abi { 33 | return -1 34 | } 35 | return i 36 | } 37 | 38 | //go:generate go run mkbuiltin.go 39 | 40 | var builtinMap map[string]int 41 | 42 | func init() { 43 | builtinMap = make(map[string]int, len(builtins)) 44 | for i, b := range builtins { 45 | builtinMap[b.name] = i 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /internal/go/src/goobj/funcinfo.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package goobj 6 | 7 | import ( 8 | "bytes" 9 | "encoding/binary" 10 | "loov.dev/lensm/internal/go/src/abi" 11 | ) 12 | 13 | // CUFileIndex is used to index the filenames that are stored in the 14 | // per-package/per-CU FileList. 15 | type CUFileIndex uint32 16 | 17 | // FuncInfo is serialized as a symbol (aux symbol). The symbol data is 18 | // the binary encoding of the struct below. 19 | type FuncInfo struct { 20 | Args uint32 21 | Locals uint32 22 | FuncID abi.FuncID 23 | FuncFlag abi.FuncFlag 24 | StartLine int32 25 | File []CUFileIndex 26 | InlTree []InlTreeNode 27 | } 28 | 29 | func (a *FuncInfo) Write(w *bytes.Buffer) { 30 | writeUint8 := func(x uint8) { 31 | w.WriteByte(x) 32 | } 33 | var b [4]byte 34 | writeUint32 := func(x uint32) { 35 | binary.LittleEndian.PutUint32(b[:], x) 36 | w.Write(b[:]) 37 | } 38 | 39 | writeUint32(a.Args) 40 | writeUint32(a.Locals) 41 | writeUint8(uint8(a.FuncID)) 42 | writeUint8(uint8(a.FuncFlag)) 43 | writeUint8(0) // pad to uint32 boundary 44 | writeUint8(0) 45 | writeUint32(uint32(a.StartLine)) 46 | 47 | writeUint32(uint32(len(a.File))) 48 | for _, f := range a.File { 49 | writeUint32(uint32(f)) 50 | } 51 | writeUint32(uint32(len(a.InlTree))) 52 | for i := range a.InlTree { 53 | a.InlTree[i].Write(w) 54 | } 55 | } 56 | 57 | // FuncInfoLengths is a cache containing a roadmap of offsets and 58 | // lengths for things within a serialized FuncInfo. Each length field 59 | // stores the number of items (e.g. files, inltree nodes, etc), and the 60 | // corresponding "off" field stores the byte offset of the start of 61 | // the items in question. 62 | type FuncInfoLengths struct { 63 | NumFile uint32 64 | FileOff uint32 65 | NumInlTree uint32 66 | InlTreeOff uint32 67 | Initialized bool 68 | } 69 | 70 | func (*FuncInfo) ReadFuncInfoLengths(b []byte) FuncInfoLengths { 71 | var result FuncInfoLengths 72 | 73 | // Offset to the number of the file table. This value is determined by counting 74 | // the number of bytes until we write funcdataoff to the file. 75 | const numfileOff = 16 76 | result.NumFile = binary.LittleEndian.Uint32(b[numfileOff:]) 77 | result.FileOff = numfileOff + 4 78 | 79 | numinltreeOff := result.FileOff + 4*result.NumFile 80 | result.NumInlTree = binary.LittleEndian.Uint32(b[numinltreeOff:]) 81 | result.InlTreeOff = numinltreeOff + 4 82 | 83 | result.Initialized = true 84 | 85 | return result 86 | } 87 | 88 | func (*FuncInfo) ReadArgs(b []byte) uint32 { return binary.LittleEndian.Uint32(b) } 89 | 90 | func (*FuncInfo) ReadLocals(b []byte) uint32 { return binary.LittleEndian.Uint32(b[4:]) } 91 | 92 | func (*FuncInfo) ReadFuncID(b []byte) abi.FuncID { return abi.FuncID(b[8]) } 93 | 94 | func (*FuncInfo) ReadFuncFlag(b []byte) abi.FuncFlag { return abi.FuncFlag(b[9]) } 95 | 96 | func (*FuncInfo) ReadStartLine(b []byte) int32 { return int32(binary.LittleEndian.Uint32(b[12:])) } 97 | 98 | func (*FuncInfo) ReadFile(b []byte, filesoff uint32, k uint32) CUFileIndex { 99 | return CUFileIndex(binary.LittleEndian.Uint32(b[filesoff+4*k:])) 100 | } 101 | 102 | func (*FuncInfo) ReadInlTree(b []byte, inltreeoff uint32, k uint32) InlTreeNode { 103 | const inlTreeNodeSize = 4 * 6 104 | var result InlTreeNode 105 | result.Read(b[inltreeoff+k*inlTreeNodeSize:]) 106 | return result 107 | } 108 | 109 | // InlTreeNode is the serialized form of FileInfo.InlTree. 110 | type InlTreeNode struct { 111 | Parent int32 112 | File CUFileIndex 113 | Line int32 114 | Func SymRef 115 | ParentPC int32 116 | } 117 | 118 | func (inl *InlTreeNode) Write(w *bytes.Buffer) { 119 | var b [4]byte 120 | writeUint32 := func(x uint32) { 121 | binary.LittleEndian.PutUint32(b[:], x) 122 | w.Write(b[:]) 123 | } 124 | writeUint32(uint32(inl.Parent)) 125 | writeUint32(uint32(inl.File)) 126 | writeUint32(uint32(inl.Line)) 127 | writeUint32(inl.Func.PkgIdx) 128 | writeUint32(inl.Func.SymIdx) 129 | writeUint32(uint32(inl.ParentPC)) 130 | } 131 | 132 | // Read an InlTreeNode from b, return the remaining bytes. 133 | func (inl *InlTreeNode) Read(b []byte) []byte { 134 | readUint32 := func() uint32 { 135 | x := binary.LittleEndian.Uint32(b) 136 | b = b[4:] 137 | return x 138 | } 139 | inl.Parent = int32(readUint32()) 140 | inl.File = CUFileIndex(readUint32()) 141 | inl.Line = int32(readUint32()) 142 | inl.Func = SymRef{readUint32(), readUint32()} 143 | inl.ParentPC = int32(readUint32()) 144 | return b 145 | } 146 | -------------------------------------------------------------------------------- /internal/go/src/goobj/mkbuiltin.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build ignore 6 | 7 | // Generate builtinlist.go from cmd/compile/internal/typecheck/_builtin/runtime.go. 8 | 9 | package main 10 | 11 | import ( 12 | "bytes" 13 | "flag" 14 | "fmt" 15 | "go/ast" 16 | "go/format" 17 | "go/parser" 18 | "go/token" 19 | "io" 20 | "log" 21 | "os" 22 | "path/filepath" 23 | "strings" 24 | ) 25 | 26 | var stdout = flag.Bool("stdout", false, "write to stdout instead of builtinlist.go") 27 | 28 | func main() { 29 | flag.Parse() 30 | 31 | var b bytes.Buffer 32 | fmt.Fprintln(&b, "// Code generated by mkbuiltin.go. DO NOT EDIT.") 33 | fmt.Fprintln(&b) 34 | fmt.Fprintln(&b, "package goobj") 35 | 36 | mkbuiltin(&b) 37 | 38 | out, err := format.Source(b.Bytes()) 39 | if err != nil { 40 | log.Fatal(err) 41 | } 42 | if *stdout { 43 | _, err = os.Stdout.Write(out) 44 | } else { 45 | err = os.WriteFile("builtinlist.go", out, 0666) 46 | } 47 | if err != nil { 48 | log.Fatal(err) 49 | } 50 | } 51 | 52 | func mkbuiltin(w io.Writer) { 53 | pkg := "runtime" 54 | fset := token.NewFileSet() 55 | path := filepath.Join("..", "..", "compile", "internal", "typecheck", "_builtin", "runtime.go") 56 | f, err := parser.ParseFile(fset, path, nil, 0) 57 | if err != nil { 58 | log.Fatal(err) 59 | } 60 | 61 | decls := make(map[string]bool) 62 | 63 | fmt.Fprintf(w, "var builtins = [...]struct{ name string; abi int }{\n") 64 | for _, decl := range f.Decls { 65 | switch decl := decl.(type) { 66 | case *ast.FuncDecl: 67 | if decl.Recv != nil { 68 | log.Fatal("methods unsupported") 69 | } 70 | if decl.Body != nil { 71 | log.Fatal("unexpected function body") 72 | } 73 | declName := pkg + "." + decl.Name.Name 74 | decls[declName] = true 75 | fmt.Fprintf(w, "{%q, 1},\n", declName) // functions are ABIInternal (1) 76 | case *ast.GenDecl: 77 | if decl.Tok == token.IMPORT { 78 | continue 79 | } 80 | if decl.Tok != token.VAR { 81 | log.Fatal("unhandled declaration kind", decl.Tok) 82 | } 83 | for _, spec := range decl.Specs { 84 | spec := spec.(*ast.ValueSpec) 85 | if len(spec.Values) != 0 { 86 | log.Fatal("unexpected values") 87 | } 88 | for _, name := range spec.Names { 89 | declName := pkg + "." + name.Name 90 | decls[declName] = true 91 | fmt.Fprintf(w, "{%q, 0},\n", declName) // variables are ABI0 92 | } 93 | } 94 | default: 95 | log.Fatal("unhandled decl type", decl) 96 | } 97 | } 98 | 99 | // The list above only contains ones that are used by the frontend. 100 | // The backend may create more references of builtin functions. 101 | // We also want to include predefined types. 102 | // Add them. 103 | extras := append(fextras[:], enumerateBasicTypes()...) 104 | for _, b := range extras { 105 | prefix := "" 106 | if !strings.HasPrefix(b.name, "type:") { 107 | prefix = pkg + "." 108 | } 109 | name := prefix + b.name 110 | if decls[name] { 111 | log.Fatalf("%q already added -- mkbuiltin.go out of sync?", name) 112 | } 113 | fmt.Fprintf(w, "{%q, %d},\n", name, b.abi) 114 | } 115 | fmt.Fprintln(w, "}") 116 | } 117 | 118 | // enumerateBasicTypes returns the symbol names for basic types that are 119 | // defined in the runtime and referenced in other packages. 120 | // Needs to be kept in sync with reflect.go:WriteBasicTypes() and 121 | // reflect.go:writeType() in the compiler. 122 | func enumerateBasicTypes() []extra { 123 | names := [...]string{ 124 | "int8", "uint8", "int16", "uint16", 125 | "int32", "uint32", "int64", "uint64", 126 | "float32", "float64", "complex64", "complex128", 127 | "unsafe.Pointer", "uintptr", "bool", "string", "error", 128 | "func(error) string"} 129 | result := []extra{} 130 | for _, n := range names { 131 | result = append(result, extra{"type:" + n, 0}) 132 | result = append(result, extra{"type:*" + n, 0}) 133 | } 134 | return result 135 | } 136 | 137 | type extra struct { 138 | name string 139 | abi int 140 | } 141 | 142 | var fextras = [...]extra{ 143 | // compiler frontend inserted calls (sysfunc) 144 | {"deferproc", 1}, 145 | {"deferprocStack", 1}, 146 | {"deferreturn", 1}, 147 | {"newproc", 1}, 148 | {"panicoverflow", 1}, 149 | {"sigpanic", 1}, 150 | 151 | // compiler backend inserted calls 152 | {"gcWriteBarrier", 1}, 153 | {"duffzero", 1}, 154 | {"duffcopy", 1}, 155 | 156 | // assembler backend inserted calls 157 | {"morestack", 0}, // asm function, ABI0 158 | {"morestackc", 0}, // asm function, ABI0 159 | {"morestack_noctxt", 0}, // asm function, ABI0 160 | } 161 | -------------------------------------------------------------------------------- /internal/go/src/objabi/autotype.go: -------------------------------------------------------------------------------- 1 | // Derived from Inferno utils/6l/l.h and related files. 2 | // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/l.h 3 | // 4 | // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 | // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 | // Portions Copyright © 1997-1999 Vita Nuova Limited 7 | // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 | // Portions Copyright © 2004,2006 Bruce Ellis 9 | // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 | // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 | // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 | // 13 | // Permission is hereby granted, free of charge, to any person obtaining a copy 14 | // of this software and associated documentation files (the "Software"), to deal 15 | // in the Software without restriction, including without limitation the rights 16 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | // copies of the Software, and to permit persons to whom the Software is 18 | // furnished to do so, subject to the following conditions: 19 | // 20 | // The above copyright notice and this permission notice shall be included in 21 | // all copies or substantial portions of the Software. 22 | // 23 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 | // THE SOFTWARE. 30 | 31 | package objabi 32 | 33 | // Auto.name 34 | const ( 35 | A_AUTO = 1 + iota 36 | A_PARAM 37 | A_DELETED_AUTO 38 | ) 39 | -------------------------------------------------------------------------------- /internal/go/src/objabi/funcid.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package objabi 6 | 7 | import ( 8 | "loov.dev/lensm/internal/go/src/abi" 9 | "strings" 10 | ) 11 | 12 | var funcIDs = map[string]abi.FuncID{ 13 | "abort": abi.FuncID_abort, 14 | "asmcgocall": abi.FuncID_asmcgocall, 15 | "asyncPreempt": abi.FuncID_asyncPreempt, 16 | "cgocallback": abi.FuncID_cgocallback, 17 | "corostart": abi.FuncID_corostart, 18 | "debugCallV2": abi.FuncID_debugCallV2, 19 | "gcBgMarkWorker": abi.FuncID_gcBgMarkWorker, 20 | "rt0_go": abi.FuncID_rt0_go, 21 | "goexit": abi.FuncID_goexit, 22 | "gogo": abi.FuncID_gogo, 23 | "gopanic": abi.FuncID_gopanic, 24 | "handleAsyncEvent": abi.FuncID_handleAsyncEvent, 25 | "main": abi.FuncID_runtime_main, 26 | "mcall": abi.FuncID_mcall, 27 | "morestack": abi.FuncID_morestack, 28 | "mstart": abi.FuncID_mstart, 29 | "panicwrap": abi.FuncID_panicwrap, 30 | "runfinq": abi.FuncID_runfinq, 31 | "sigpanic": abi.FuncID_sigpanic, 32 | "systemstack_switch": abi.FuncID_systemstack_switch, 33 | "systemstack": abi.FuncID_systemstack, 34 | 35 | // Don't show in call stack but otherwise not special. 36 | "deferreturn": abi.FuncIDWrapper, 37 | } 38 | 39 | // Get the function ID for the named function in the named file. 40 | // The function should be package-qualified. 41 | func GetFuncID(name string, isWrapper bool) abi.FuncID { 42 | if isWrapper { 43 | return abi.FuncIDWrapper 44 | } 45 | if strings.HasPrefix(name, "runtime.") { 46 | if id, ok := funcIDs[name[len("runtime."):]]; ok { 47 | return id 48 | } 49 | } 50 | return abi.FuncIDNormal 51 | } 52 | -------------------------------------------------------------------------------- /internal/go/src/objabi/head.go: -------------------------------------------------------------------------------- 1 | // Derived from Inferno utils/6l/l.h and related files. 2 | // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/l.h 3 | // 4 | // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 | // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 | // Portions Copyright © 1997-1999 Vita Nuova Limited 7 | // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 | // Portions Copyright © 2004,2006 Bruce Ellis 9 | // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 | // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 | // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 | // 13 | // Permission is hereby granted, free of charge, to any person obtaining a copy 14 | // of this software and associated documentation files (the "Software"), to deal 15 | // in the Software without restriction, including without limitation the rights 16 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | // copies of the Software, and to permit persons to whom the Software is 18 | // furnished to do so, subject to the following conditions: 19 | // 20 | // The above copyright notice and this permission notice shall be included in 21 | // all copies or substantial portions of the Software. 22 | // 23 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 | // THE SOFTWARE. 30 | 31 | package objabi 32 | 33 | import "fmt" 34 | 35 | // HeadType is the executable header type. 36 | type HeadType uint8 37 | 38 | const ( 39 | Hunknown HeadType = iota 40 | Hdarwin 41 | Hdragonfly 42 | Hfreebsd 43 | Hjs 44 | Hlinux 45 | Hnetbsd 46 | Hopenbsd 47 | Hplan9 48 | Hsolaris 49 | Hwasip1 50 | Hwindows 51 | Haix 52 | ) 53 | 54 | func (h *HeadType) Set(s string) error { 55 | switch s { 56 | case "aix": 57 | *h = Haix 58 | case "darwin", "ios": 59 | *h = Hdarwin 60 | case "dragonfly": 61 | *h = Hdragonfly 62 | case "freebsd": 63 | *h = Hfreebsd 64 | case "js": 65 | *h = Hjs 66 | case "linux", "android": 67 | *h = Hlinux 68 | case "netbsd": 69 | *h = Hnetbsd 70 | case "openbsd": 71 | *h = Hopenbsd 72 | case "plan9": 73 | *h = Hplan9 74 | case "illumos", "solaris": 75 | *h = Hsolaris 76 | case "wasip1": 77 | *h = Hwasip1 78 | case "windows": 79 | *h = Hwindows 80 | default: 81 | return fmt.Errorf("invalid headtype: %q", s) 82 | } 83 | return nil 84 | } 85 | 86 | func (h HeadType) String() string { 87 | switch h { 88 | case Haix: 89 | return "aix" 90 | case Hdarwin: 91 | return "darwin" 92 | case Hdragonfly: 93 | return "dragonfly" 94 | case Hfreebsd: 95 | return "freebsd" 96 | case Hjs: 97 | return "js" 98 | case Hlinux: 99 | return "linux" 100 | case Hnetbsd: 101 | return "netbsd" 102 | case Hopenbsd: 103 | return "openbsd" 104 | case Hplan9: 105 | return "plan9" 106 | case Hsolaris: 107 | return "solaris" 108 | case Hwasip1: 109 | return "wasip1" 110 | case Hwindows: 111 | return "windows" 112 | } 113 | return fmt.Sprintf("HeadType(%d)", h) 114 | } 115 | -------------------------------------------------------------------------------- /internal/go/src/objabi/line.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package objabi 6 | 7 | import ( 8 | "loov.dev/lensm/internal/go/src/buildcfg" 9 | "os" 10 | "path/filepath" 11 | "runtime" 12 | "strings" 13 | ) 14 | 15 | // WorkingDir returns the current working directory 16 | // (or "/???" if the directory cannot be identified), 17 | // with "/" as separator. 18 | func WorkingDir() string { 19 | var path string 20 | path, _ = os.Getwd() 21 | if path == "" { 22 | path = "/???" 23 | } 24 | return filepath.ToSlash(path) 25 | } 26 | 27 | // AbsFile returns the absolute filename for file in the given directory, 28 | // as rewritten by the rewrites argument. 29 | // For unrewritten paths, AbsFile rewrites a leading $GOROOT prefix to the literal "$GOROOT". 30 | // If the resulting path is the empty string, the result is "??". 31 | // 32 | // The rewrites argument is a ;-separated list of rewrites. 33 | // Each rewrite is of the form "prefix" or "prefix=>replace", 34 | // where prefix must match a leading sequence of path elements 35 | // and is either removed entirely or replaced by the replacement. 36 | func AbsFile(dir, file, rewrites string) string { 37 | abs := file 38 | if dir != "" && !filepath.IsAbs(file) { 39 | abs = filepath.Join(dir, file) 40 | } 41 | 42 | abs, rewritten := ApplyRewrites(abs, rewrites) 43 | if !rewritten && buildcfg.GOROOT != "" && hasPathPrefix(abs, buildcfg.GOROOT) { 44 | abs = "$GOROOT" + abs[len(buildcfg.GOROOT):] 45 | } 46 | 47 | // Rewrite paths to match the slash convention of the target. 48 | // This helps ensure that cross-compiled distributions remain 49 | // bit-for-bit identical to natively compiled distributions. 50 | if runtime.GOOS == "windows" { 51 | abs = strings.ReplaceAll(abs, `\`, "/") 52 | } 53 | 54 | if abs == "" { 55 | abs = "??" 56 | } 57 | return abs 58 | } 59 | 60 | // ApplyRewrites returns the filename for file in the given directory, 61 | // as rewritten by the rewrites argument. 62 | // 63 | // The rewrites argument is a ;-separated list of rewrites. 64 | // Each rewrite is of the form "prefix" or "prefix=>replace", 65 | // where prefix must match a leading sequence of path elements 66 | // and is either removed entirely or replaced by the replacement. 67 | func ApplyRewrites(file, rewrites string) (string, bool) { 68 | start := 0 69 | for i := 0; i <= len(rewrites); i++ { 70 | if i == len(rewrites) || rewrites[i] == ';' { 71 | if new, ok := applyRewrite(file, rewrites[start:i]); ok { 72 | return new, true 73 | } 74 | start = i + 1 75 | } 76 | } 77 | 78 | return file, false 79 | } 80 | 81 | // applyRewrite applies the rewrite to the path, 82 | // returning the rewritten path and a boolean 83 | // indicating whether the rewrite applied at all. 84 | func applyRewrite(path, rewrite string) (string, bool) { 85 | prefix, replace := rewrite, "" 86 | if j := strings.LastIndex(rewrite, "=>"); j >= 0 { 87 | prefix, replace = rewrite[:j], rewrite[j+len("=>"):] 88 | } 89 | 90 | if prefix == "" || !hasPathPrefix(path, prefix) { 91 | return path, false 92 | } 93 | if len(path) == len(prefix) { 94 | return replace, true 95 | } 96 | if replace == "" { 97 | return path[len(prefix)+1:], true 98 | } 99 | return replace + path[len(prefix):], true 100 | } 101 | 102 | // Does s have t as a path prefix? 103 | // That is, does s == t or does s begin with t followed by a slash? 104 | // For portability, we allow ASCII case folding, so that hasPathPrefix("a/b/c", "A/B") is true. 105 | // Similarly, we allow slash folding, so that hasPathPrefix("a/b/c", "a\\b") is true. 106 | // We do not allow full Unicode case folding, for fear of causing more confusion 107 | // or harm than good. (For an example of the kinds of things that can go wrong, 108 | // see http://article.gmane.org/gmane.linux.kernel/1853266.) 109 | func hasPathPrefix(s string, t string) bool { 110 | if len(t) > len(s) { 111 | return false 112 | } 113 | var i int 114 | for i = 0; i < len(t); i++ { 115 | cs := int(s[i]) 116 | ct := int(t[i]) 117 | if 'A' <= cs && cs <= 'Z' { 118 | cs += 'a' - 'A' 119 | } 120 | if 'A' <= ct && ct <= 'Z' { 121 | ct += 'a' - 'A' 122 | } 123 | if cs == '\\' { 124 | cs = '/' 125 | } 126 | if ct == '\\' { 127 | ct = '/' 128 | } 129 | if cs != ct { 130 | return false 131 | } 132 | } 133 | return i >= len(s) || s[i] == '/' || s[i] == '\\' 134 | } 135 | -------------------------------------------------------------------------------- /internal/go/src/objabi/path.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package objabi 6 | 7 | import ( 8 | "fmt" 9 | "strconv" 10 | "strings" 11 | ) 12 | 13 | // PathToPrefix converts raw string to the prefix that will be used in the 14 | // symbol table. All control characters, space, '%' and '"', as well as 15 | // non-7-bit clean bytes turn into %xx. The period needs escaping only in the 16 | // last segment of the path, and it makes for happier users if we escape that as 17 | // little as possible. 18 | func PathToPrefix(s string) string { 19 | slash := strings.LastIndex(s, "/") 20 | // check for chars that need escaping 21 | n := 0 22 | for r := 0; r < len(s); r++ { 23 | if c := s[r]; c <= ' ' || (c == '.' && r > slash) || c == '%' || c == '"' || c >= 0x7F { 24 | n++ 25 | } 26 | } 27 | 28 | // quick exit 29 | if n == 0 { 30 | return s 31 | } 32 | 33 | // escape 34 | const hex = "0123456789abcdef" 35 | p := make([]byte, 0, len(s)+2*n) 36 | for r := 0; r < len(s); r++ { 37 | if c := s[r]; c <= ' ' || (c == '.' && r > slash) || c == '%' || c == '"' || c >= 0x7F { 38 | p = append(p, '%', hex[c>>4], hex[c&0xF]) 39 | } else { 40 | p = append(p, c) 41 | } 42 | } 43 | 44 | return string(p) 45 | } 46 | 47 | // PrefixToPath is the inverse of PathToPrefix, replacing escape sequences with 48 | // the original character. 49 | func PrefixToPath(s string) (string, error) { 50 | percent := strings.IndexByte(s, '%') 51 | if percent == -1 { 52 | return s, nil 53 | } 54 | 55 | p := make([]byte, 0, len(s)) 56 | for i := 0; i < len(s); { 57 | if s[i] != '%' { 58 | p = append(p, s[i]) 59 | i++ 60 | continue 61 | } 62 | if i+2 >= len(s) { 63 | // Not enough characters remaining to be a valid escape 64 | // sequence. 65 | return "", fmt.Errorf("malformed prefix %q: escape sequence must contain two hex digits", s) 66 | } 67 | 68 | b, err := strconv.ParseUint(s[i+1:i+3], 16, 8) 69 | if err != nil { 70 | // Not a valid escape sequence. 71 | return "", fmt.Errorf("malformed prefix %q: escape sequence %q must contain two hex digits", s, s[i:i+3]) 72 | } 73 | 74 | p = append(p, byte(b)) 75 | i += 3 76 | } 77 | return string(p), nil 78 | } 79 | -------------------------------------------------------------------------------- /internal/go/src/objabi/pkgspecial.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package objabi 6 | 7 | import "sync" 8 | 9 | // PkgSpecial indicates special build properties of a given runtime-related 10 | // package. 11 | type PkgSpecial struct { 12 | // Runtime indicates that this package is "runtime" or imported by 13 | // "runtime". This has several effects (which maybe should be split out): 14 | // 15 | // - Implicit allocation is disallowed. 16 | // 17 | // - Various runtime pragmas are enabled. 18 | // 19 | // - Optimizations are always enabled. 20 | // 21 | // - Checkptr is always disabled. 22 | // 23 | // This should be set for runtime and all packages it imports, and may be 24 | // set for additional packages. 25 | Runtime bool 26 | 27 | // NoInstrument indicates this package should not receive sanitizer 28 | // instrumentation. In many of these, instrumentation could cause infinite 29 | // recursion. This is all runtime packages, plus those that support the 30 | // sanitizers. 31 | NoInstrument bool 32 | 33 | // NoRaceFunc indicates functions in this package should not get 34 | // racefuncenter/racefuncexit instrumentation Memory accesses in these 35 | // packages are either uninteresting or will cause false positives. 36 | NoRaceFunc bool 37 | 38 | // AllowAsmABI indicates that assembly in this package is allowed to use ABI 39 | // selectors in symbol names. Generally this is needed for packages that 40 | // interact closely with the runtime package or have performance-critical 41 | // assembly. 42 | AllowAsmABI bool 43 | } 44 | 45 | var runtimePkgs = []string{ 46 | "runtime", 47 | 48 | "loov.dev/lensm/internal/go/src/runtime/atomic", 49 | "loov.dev/lensm/internal/go/src/runtime/exithook", 50 | "loov.dev/lensm/internal/go/src/runtime/maps", 51 | "loov.dev/lensm/internal/go/src/runtime/math", 52 | "loov.dev/lensm/internal/go/src/runtime/sys", 53 | "loov.dev/lensm/internal/go/src/runtime/syscall", 54 | 55 | "loov.dev/lensm/internal/go/src/abi", 56 | "loov.dev/lensm/internal/go/src/bytealg", 57 | "loov.dev/lensm/internal/go/src/byteorder", 58 | "loov.dev/lensm/internal/go/src/chacha8rand", 59 | "loov.dev/lensm/internal/go/src/coverage/rtcov", 60 | "loov.dev/lensm/internal/go/src/cpu", 61 | "loov.dev/lensm/internal/go/src/goarch", 62 | "loov.dev/lensm/internal/go/src/godebugs", 63 | "loov.dev/lensm/internal/go/src/goexperiment", 64 | "loov.dev/lensm/internal/go/src/goos", 65 | "loov.dev/lensm/internal/go/src/profilerecord", 66 | "loov.dev/lensm/internal/go/src/stringslite", 67 | } 68 | 69 | // extraNoInstrumentPkgs is the set of packages in addition to runtimePkgs that 70 | // should have NoInstrument set. 71 | var extraNoInstrumentPkgs = []string{ 72 | "runtime/race", 73 | "runtime/msan", 74 | "runtime/asan", 75 | // We omit bytealg even though it's imported by runtime because it also 76 | // backs a lot of package bytes. Currently we don't have a way to omit race 77 | // instrumentation when used from the runtime while keeping race 78 | // instrumentation when used from user code. Somehow this doesn't seem to 79 | // cause problems, though we may be skating on thin ice. See #61204. 80 | "-internal/bytealg", 81 | } 82 | 83 | var noRaceFuncPkgs = []string{"sync", "sync/atomic", "internal/sync", "internal/runtime/atomic"} 84 | 85 | var allowAsmABIPkgs = []string{ 86 | "runtime", 87 | "reflect", 88 | "syscall", 89 | "loov.dev/lensm/internal/go/src/bytealg", 90 | "loov.dev/lensm/internal/go/src/chacha8rand", 91 | "loov.dev/lensm/internal/go/src/runtime/syscall", 92 | "runtime/internal/startlinetest", 93 | } 94 | 95 | // LookupPkgSpecial returns special build properties for the given package path. 96 | func LookupPkgSpecial(pkgPath string) PkgSpecial { 97 | return pkgSpecialsOnce()[pkgPath] 98 | } 99 | 100 | var pkgSpecialsOnce = sync.OnceValue(func() map[string]PkgSpecial { 101 | // Construct pkgSpecials from various package lists. This lets us use 102 | // more flexible logic, while keeping the final map simple, and avoids 103 | // the init-time cost of a map. 104 | pkgSpecials := make(map[string]PkgSpecial) 105 | set := func(elt string, f func(*PkgSpecial)) { 106 | s := pkgSpecials[elt] 107 | f(&s) 108 | pkgSpecials[elt] = s 109 | } 110 | for _, pkg := range runtimePkgs { 111 | set(pkg, func(ps *PkgSpecial) { ps.Runtime = true; ps.NoInstrument = true }) 112 | } 113 | for _, pkg := range extraNoInstrumentPkgs { 114 | if pkg[0] == '-' { 115 | set(pkg[1:], func(ps *PkgSpecial) { ps.NoInstrument = false }) 116 | } else { 117 | set(pkg, func(ps *PkgSpecial) { ps.NoInstrument = true }) 118 | } 119 | } 120 | for _, pkg := range noRaceFuncPkgs { 121 | set(pkg, func(ps *PkgSpecial) { ps.NoRaceFunc = true }) 122 | } 123 | for _, pkg := range allowAsmABIPkgs { 124 | set(pkg, func(ps *PkgSpecial) { ps.AllowAsmABI = true }) 125 | } 126 | return pkgSpecials 127 | }) 128 | -------------------------------------------------------------------------------- /internal/go/src/objabi/reloctype_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type=RelocType"; DO NOT EDIT. 2 | 3 | package objabi 4 | 5 | import "strconv" 6 | 7 | func _() { 8 | // An "invalid array index" compiler error signifies that the constant values have changed. 9 | // Re-run the stringer command to generate them again. 10 | var x [1]struct{} 11 | _ = x[R_ADDR-1] 12 | _ = x[R_ADDRPOWER-2] 13 | _ = x[R_ADDRARM64-3] 14 | _ = x[R_ADDRMIPS-4] 15 | _ = x[R_ADDROFF-5] 16 | _ = x[R_SIZE-6] 17 | _ = x[R_CALL-7] 18 | _ = x[R_CALLARM-8] 19 | _ = x[R_CALLARM64-9] 20 | _ = x[R_CALLIND-10] 21 | _ = x[R_CALLPOWER-11] 22 | _ = x[R_CALLMIPS-12] 23 | _ = x[R_CONST-13] 24 | _ = x[R_PCREL-14] 25 | _ = x[R_TLS_LE-15] 26 | _ = x[R_TLS_IE-16] 27 | _ = x[R_GOTOFF-17] 28 | _ = x[R_PLT0-18] 29 | _ = x[R_PLT1-19] 30 | _ = x[R_PLT2-20] 31 | _ = x[R_USEFIELD-21] 32 | _ = x[R_USETYPE-22] 33 | _ = x[R_USEIFACE-23] 34 | _ = x[R_USEIFACEMETHOD-24] 35 | _ = x[R_USENAMEDMETHOD-25] 36 | _ = x[R_METHODOFF-26] 37 | _ = x[R_KEEP-27] 38 | _ = x[R_POWER_TOC-28] 39 | _ = x[R_GOTPCREL-29] 40 | _ = x[R_JMPMIPS-30] 41 | _ = x[R_DWARFSECREF-31] 42 | _ = x[R_DWARFFILEREF-32] 43 | _ = x[R_ARM64_TLS_LE-33] 44 | _ = x[R_ARM64_TLS_IE-34] 45 | _ = x[R_ARM64_GOTPCREL-35] 46 | _ = x[R_ARM64_GOT-36] 47 | _ = x[R_ARM64_PCREL-37] 48 | _ = x[R_ARM64_PCREL_LDST8-38] 49 | _ = x[R_ARM64_PCREL_LDST16-39] 50 | _ = x[R_ARM64_PCREL_LDST32-40] 51 | _ = x[R_ARM64_PCREL_LDST64-41] 52 | _ = x[R_ARM64_LDST8-42] 53 | _ = x[R_ARM64_LDST16-43] 54 | _ = x[R_ARM64_LDST32-44] 55 | _ = x[R_ARM64_LDST64-45] 56 | _ = x[R_ARM64_LDST128-46] 57 | _ = x[R_POWER_TLS_LE-47] 58 | _ = x[R_POWER_TLS_IE-48] 59 | _ = x[R_POWER_TLS-49] 60 | _ = x[R_POWER_TLS_IE_PCREL34-50] 61 | _ = x[R_POWER_TLS_LE_TPREL34-51] 62 | _ = x[R_ADDRPOWER_DS-52] 63 | _ = x[R_ADDRPOWER_GOT-53] 64 | _ = x[R_ADDRPOWER_GOT_PCREL34-54] 65 | _ = x[R_ADDRPOWER_PCREL-55] 66 | _ = x[R_ADDRPOWER_TOCREL-56] 67 | _ = x[R_ADDRPOWER_TOCREL_DS-57] 68 | _ = x[R_ADDRPOWER_D34-58] 69 | _ = x[R_ADDRPOWER_PCREL34-59] 70 | _ = x[R_RISCV_JAL-60] 71 | _ = x[R_RISCV_JAL_TRAMP-61] 72 | _ = x[R_RISCV_CALL-62] 73 | _ = x[R_RISCV_PCREL_ITYPE-63] 74 | _ = x[R_RISCV_PCREL_STYPE-64] 75 | _ = x[R_RISCV_TLS_IE-65] 76 | _ = x[R_RISCV_TLS_LE-66] 77 | _ = x[R_RISCV_GOT_HI20-67] 78 | _ = x[R_RISCV_PCREL_HI20-68] 79 | _ = x[R_RISCV_PCREL_LO12_I-69] 80 | _ = x[R_RISCV_PCREL_LO12_S-70] 81 | _ = x[R_RISCV_BRANCH-71] 82 | _ = x[R_RISCV_RVC_BRANCH-72] 83 | _ = x[R_RISCV_RVC_JUMP-73] 84 | _ = x[R_PCRELDBL-74] 85 | _ = x[R_LOONG64_ADDR_HI-75] 86 | _ = x[R_LOONG64_ADDR_LO-76] 87 | _ = x[R_LOONG64_TLS_LE_HI-77] 88 | _ = x[R_LOONG64_TLS_LE_LO-78] 89 | _ = x[R_CALLLOONG64-79] 90 | _ = x[R_LOONG64_TLS_IE_HI-80] 91 | _ = x[R_LOONG64_TLS_IE_LO-81] 92 | _ = x[R_LOONG64_GOT_HI-82] 93 | _ = x[R_LOONG64_GOT_LO-83] 94 | _ = x[R_LOONG64_ADD64-84] 95 | _ = x[R_LOONG64_SUB64-85] 96 | _ = x[R_JMP16LOONG64-86] 97 | _ = x[R_JMP21LOONG64-87] 98 | _ = x[R_JMPLOONG64-88] 99 | _ = x[R_ADDRMIPSU-89] 100 | _ = x[R_ADDRMIPSTLS-90] 101 | _ = x[R_ADDRCUOFF-91] 102 | _ = x[R_WASMIMPORT-92] 103 | _ = x[R_XCOFFREF-93] 104 | _ = x[R_PEIMAGEOFF-94] 105 | _ = x[R_INITORDER-95] 106 | } 107 | 108 | const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_USENAMEDMETHODR_METHODOFFR_KEEPR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_PCREL_LDST8R_ARM64_PCREL_LDST16R_ARM64_PCREL_LDST32R_ARM64_PCREL_LDST64R_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_POWER_TLS_IE_PCREL34R_POWER_TLS_LE_TPREL34R_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_GOT_PCREL34R_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_ADDRPOWER_D34R_ADDRPOWER_PCREL34R_RISCV_JALR_RISCV_JAL_TRAMPR_RISCV_CALLR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IER_RISCV_TLS_LER_RISCV_GOT_HI20R_RISCV_PCREL_HI20R_RISCV_PCREL_LO12_IR_RISCV_PCREL_LO12_SR_RISCV_BRANCHR_RISCV_RVC_BRANCHR_RISCV_RVC_JUMPR_PCRELDBLR_LOONG64_ADDR_HIR_LOONG64_ADDR_LOR_LOONG64_TLS_LE_HIR_LOONG64_TLS_LE_LOR_CALLLOONG64R_LOONG64_TLS_IE_HIR_LOONG64_TLS_IE_LOR_LOONG64_GOT_HIR_LOONG64_GOT_LOR_LOONG64_ADD64R_LOONG64_SUB64R_JMP16LOONG64R_JMP21LOONG64R_JMPLOONG64R_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREFR_PEIMAGEOFFR_INITORDER" 109 | 110 | var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 116, 123, 131, 139, 147, 153, 159, 165, 175, 184, 194, 210, 226, 237, 243, 254, 264, 273, 286, 300, 314, 328, 344, 355, 368, 387, 407, 427, 447, 460, 474, 488, 502, 517, 531, 545, 556, 578, 600, 614, 629, 652, 669, 687, 708, 723, 742, 753, 770, 782, 801, 820, 834, 848, 864, 882, 902, 922, 936, 954, 970, 980, 997, 1014, 1033, 1052, 1065, 1084, 1103, 1119, 1135, 1150, 1165, 1179, 1193, 1205, 1216, 1229, 1240, 1252, 1262, 1274, 1285} 111 | 112 | func (i RelocType) String() string { 113 | i -= 1 114 | if i < 0 || i >= RelocType(len(_RelocType_index)-1) { 115 | return "RelocType(" + strconv.FormatInt(int64(i+1), 10) + ")" 116 | } 117 | return _RelocType_name[_RelocType_index[i]:_RelocType_index[i+1]] 118 | } 119 | -------------------------------------------------------------------------------- /internal/go/src/objabi/stack.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package objabi 6 | 7 | import ( 8 | "loov.dev/lensm/internal/go/src/abi" 9 | "loov.dev/lensm/internal/go/src/buildcfg" 10 | ) 11 | 12 | func StackNosplit(race bool) int { 13 | // This arithmetic must match that in runtime/stack.go:stackNosplit. 14 | return abi.StackNosplitBase * stackGuardMultiplier(race) 15 | } 16 | 17 | // stackGuardMultiplier returns a multiplier to apply to the default 18 | // stack guard size. Larger multipliers are used for non-optimized 19 | // builds that have larger stack frames or for specific targets. 20 | func stackGuardMultiplier(race bool) int { 21 | // This arithmetic must match that in internal/runtime/sys/consts.go:StackGuardMultiplier. 22 | n := 1 23 | // On AIX and OpenBSD, a larger stack is needed for syscalls. 24 | if buildcfg.GOOS == "aix" || buildcfg.GOOS == "openbsd" { 25 | n += 1 26 | } 27 | // The race build also needs more stack. 28 | if race { 29 | n += 1 30 | } 31 | return n 32 | } 33 | -------------------------------------------------------------------------------- /internal/go/src/objabi/symkind.go: -------------------------------------------------------------------------------- 1 | // Derived from Inferno utils/6l/l.h and related files. 2 | // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/l.h 3 | // 4 | // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 | // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 | // Portions Copyright © 1997-1999 Vita Nuova Limited 7 | // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 | // Portions Copyright © 2004,2006 Bruce Ellis 9 | // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 | // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 | // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 | // 13 | // Permission is hereby granted, free of charge, to any person obtaining a copy 14 | // of this software and associated documentation files (the "Software"), to deal 15 | // in the Software without restriction, including without limitation the rights 16 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | // copies of the Software, and to permit persons to whom the Software is 18 | // furnished to do so, subject to the following conditions: 19 | // 20 | // The above copyright notice and this permission notice shall be included in 21 | // all copies or substantial portions of the Software. 22 | // 23 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 | // THE SOFTWARE. 30 | 31 | package objabi 32 | 33 | // A SymKind describes the kind of memory represented by a symbol. 34 | type SymKind uint8 35 | 36 | // Defined SymKind values. 37 | // These are used to index into cmd/link/internal/sym/AbiSymKindToSymKind 38 | // 39 | // TODO(rsc): Give idiomatic Go names. 40 | // 41 | //go:generate stringer -type=SymKind 42 | const ( 43 | // An otherwise invalid zero value for the type 44 | Sxxx SymKind = iota 45 | // Executable instructions 46 | STEXT 47 | STEXTFIPS 48 | // Read only static data 49 | SRODATA 50 | SRODATAFIPS 51 | // Static data that does not contain any pointers 52 | SNOPTRDATA 53 | SNOPTRDATAFIPS 54 | // Static data 55 | SDATA 56 | SDATAFIPS 57 | // Statically data that is initially all 0s 58 | SBSS 59 | // Statically data that is initially all 0s and does not contain pointers 60 | SNOPTRBSS 61 | // Thread-local data that is initially all 0s 62 | STLSBSS 63 | // Debugging data 64 | SDWARFCUINFO 65 | SDWARFCONST 66 | SDWARFFCN 67 | SDWARFABSFCN 68 | SDWARFTYPE 69 | SDWARFVAR 70 | SDWARFRANGE 71 | SDWARFLOC 72 | SDWARFLINES 73 | // Coverage instrumentation counter for libfuzzer. 74 | SLIBFUZZER_8BIT_COUNTER 75 | // Coverage instrumentation counter, aux variable for cmd/cover 76 | SCOVERAGE_COUNTER 77 | SCOVERAGE_AUXVAR 78 | 79 | SSEHUNWINDINFO 80 | // Update cmd/link/internal/sym/AbiSymKindToSymKind for new SymKind values. 81 | ) 82 | 83 | // IsText reports whether t is one of the text kinds. 84 | func (t SymKind) IsText() bool { 85 | return t == STEXT || t == STEXTFIPS 86 | } 87 | 88 | // IsDATA reports whether t is one of the DATA kinds (SDATA or SDATAFIPS, 89 | // excluding NOPTRDATA, RODATA, BSS, and so on). 90 | func (t SymKind) IsDATA() bool { 91 | return t == SDATA || t == SDATAFIPS 92 | } 93 | 94 | // IsFIPS reports whether t is one fo the FIPS kinds. 95 | func (t SymKind) IsFIPS() bool { 96 | return t == STEXTFIPS || t == SRODATAFIPS || t == SNOPTRDATAFIPS || t == SDATAFIPS 97 | } 98 | -------------------------------------------------------------------------------- /internal/go/src/objabi/symkind_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type=SymKind"; DO NOT EDIT. 2 | 3 | package objabi 4 | 5 | import "strconv" 6 | 7 | func _() { 8 | // An "invalid array index" compiler error signifies that the constant values have changed. 9 | // Re-run the stringer command to generate them again. 10 | var x [1]struct{} 11 | _ = x[Sxxx-0] 12 | _ = x[STEXT-1] 13 | _ = x[STEXTFIPS-2] 14 | _ = x[SRODATA-3] 15 | _ = x[SRODATAFIPS-4] 16 | _ = x[SNOPTRDATA-5] 17 | _ = x[SNOPTRDATAFIPS-6] 18 | _ = x[SDATA-7] 19 | _ = x[SDATAFIPS-8] 20 | _ = x[SBSS-9] 21 | _ = x[SNOPTRBSS-10] 22 | _ = x[STLSBSS-11] 23 | _ = x[SDWARFCUINFO-12] 24 | _ = x[SDWARFCONST-13] 25 | _ = x[SDWARFFCN-14] 26 | _ = x[SDWARFABSFCN-15] 27 | _ = x[SDWARFTYPE-16] 28 | _ = x[SDWARFVAR-17] 29 | _ = x[SDWARFRANGE-18] 30 | _ = x[SDWARFLOC-19] 31 | _ = x[SDWARFLINES-20] 32 | _ = x[SLIBFUZZER_8BIT_COUNTER-21] 33 | _ = x[SCOVERAGE_COUNTER-22] 34 | _ = x[SCOVERAGE_AUXVAR-23] 35 | _ = x[SSEHUNWINDINFO-24] 36 | } 37 | 38 | const _SymKind_name = "SxxxSTEXTSTEXTFIPSSRODATASRODATAFIPSSNOPTRDATASNOPTRDATAFIPSSDATASDATAFIPSSBSSSNOPTRBSSSTLSBSSSDWARFCUINFOSDWARFCONSTSDWARFFCNSDWARFABSFCNSDWARFTYPESDWARFVARSDWARFRANGESDWARFLOCSDWARFLINESSLIBFUZZER_8BIT_COUNTERSCOVERAGE_COUNTERSCOVERAGE_AUXVARSSEHUNWINDINFO" 39 | 40 | var _SymKind_index = [...]uint16{0, 4, 9, 18, 25, 36, 46, 60, 65, 74, 78, 87, 94, 106, 117, 126, 138, 148, 157, 168, 177, 188, 211, 228, 244, 258} 41 | 42 | func (i SymKind) String() string { 43 | if i >= SymKind(len(_SymKind_index)-1) { 44 | return "SymKind(" + strconv.FormatInt(int64(i), 10) + ")" 45 | } 46 | return _SymKind_name[_SymKind_index[i]:_SymKind_index[i+1]] 47 | } 48 | -------------------------------------------------------------------------------- /internal/go/src/objabi/util.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package objabi 6 | 7 | import ( 8 | "fmt" 9 | "strings" 10 | 11 | "loov.dev/lensm/internal/go/src/buildcfg" 12 | ) 13 | 14 | const ( 15 | ElfRelocOffset = 256 16 | MachoRelocOffset = 2048 // reserve enough space for ELF relocations 17 | GlobalDictPrefix = ".dict" // prefix for names of global dictionaries 18 | ) 19 | 20 | // HeaderString returns the toolchain configuration string written in 21 | // Go object headers. This string ensures we don't attempt to import 22 | // or link object files that are incompatible with each other. This 23 | // string always starts with "go object ". 24 | func HeaderString() string { 25 | archExtra := "" 26 | if k, v := buildcfg.GOGOARCH(); k != "" && v != "" { 27 | archExtra = " " + k + "=" + v 28 | } 29 | return fmt.Sprintf("go object %s %s %s%s X:%s\n", 30 | buildcfg.GOOS, buildcfg.GOARCH, 31 | buildcfg.Version, archExtra, 32 | strings.Join(buildcfg.Experiment.Enabled(), ",")) 33 | } 34 | -------------------------------------------------------------------------------- /internal/go/src/objabi/zbootstrap.go: -------------------------------------------------------------------------------- 1 | // Code generated by go tool dist; DO NOT EDIT. 2 | 3 | package objabi 4 | -------------------------------------------------------------------------------- /internal/go/src/objfile/elf.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Parsing of ELF executables (Linux, FreeBSD, and so on). 6 | 7 | package objfile 8 | 9 | import ( 10 | "debug/dwarf" 11 | "debug/elf" 12 | "encoding/binary" 13 | "fmt" 14 | "io" 15 | ) 16 | 17 | type elfFile struct { 18 | elf *elf.File 19 | } 20 | 21 | func openElf(r io.ReaderAt) (rawFile, error) { 22 | f, err := elf.NewFile(r) 23 | if err != nil { 24 | return nil, err 25 | } 26 | return &elfFile{f}, nil 27 | } 28 | 29 | func (f *elfFile) symbols() ([]Sym, error) { 30 | elfSyms, err := f.elf.Symbols() 31 | if err != nil { 32 | return nil, err 33 | } 34 | 35 | var syms []Sym 36 | for _, s := range elfSyms { 37 | sym := Sym{Addr: s.Value, Name: s.Name, Size: int64(s.Size), Code: '?'} 38 | switch s.Section { 39 | case elf.SHN_UNDEF: 40 | sym.Code = 'U' 41 | case elf.SHN_COMMON: 42 | sym.Code = 'B' 43 | default: 44 | i := int(s.Section) 45 | if i < 0 || i >= len(f.elf.Sections) { 46 | break 47 | } 48 | sect := f.elf.Sections[i] 49 | switch sect.Flags & (elf.SHF_WRITE | elf.SHF_ALLOC | elf.SHF_EXECINSTR) { 50 | case elf.SHF_ALLOC | elf.SHF_EXECINSTR: 51 | sym.Code = 'T' 52 | case elf.SHF_ALLOC: 53 | sym.Code = 'R' 54 | case elf.SHF_ALLOC | elf.SHF_WRITE: 55 | sym.Code = 'D' 56 | } 57 | } 58 | if elf.ST_BIND(s.Info) == elf.STB_LOCAL { 59 | sym.Code += 'a' - 'A' 60 | } 61 | syms = append(syms, sym) 62 | } 63 | 64 | return syms, nil 65 | } 66 | 67 | func (f *elfFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) { 68 | if sect := f.elf.Section(".text"); sect != nil { 69 | textStart = sect.Addr 70 | } 71 | 72 | sect := f.elf.Section(".gosymtab") 73 | if sect == nil { 74 | // try .data.rel.ro.gosymtab, for PIE binaries 75 | sect = f.elf.Section(".data.rel.ro.gosymtab") 76 | } 77 | if sect != nil { 78 | if symtab, err = sect.Data(); err != nil { 79 | return 0, nil, nil, err 80 | } 81 | } else { 82 | // if both sections failed, try the symbol 83 | symtab = f.symbolData("runtime.symtab", "runtime.esymtab") 84 | } 85 | 86 | sect = f.elf.Section(".gopclntab") 87 | if sect == nil { 88 | // try .data.rel.ro.gopclntab, for PIE binaries 89 | sect = f.elf.Section(".data.rel.ro.gopclntab") 90 | } 91 | if sect != nil { 92 | if pclntab, err = sect.Data(); err != nil { 93 | return 0, nil, nil, err 94 | } 95 | } else { 96 | // if both sections failed, try the symbol 97 | pclntab = f.symbolData("runtime.pclntab", "runtime.epclntab") 98 | } 99 | 100 | return textStart, symtab, pclntab, nil 101 | } 102 | 103 | func (f *elfFile) text() (textStart uint64, text []byte, err error) { 104 | sect := f.elf.Section(".text") 105 | if sect == nil { 106 | return 0, nil, fmt.Errorf("text section not found") 107 | } 108 | textStart = sect.Addr 109 | text, err = sect.Data() 110 | return 111 | } 112 | 113 | func (f *elfFile) goarch() string { 114 | switch f.elf.Machine { 115 | case elf.EM_386: 116 | return "386" 117 | case elf.EM_X86_64: 118 | return "amd64" 119 | case elf.EM_ARM: 120 | return "arm" 121 | case elf.EM_AARCH64: 122 | return "arm64" 123 | case elf.EM_LOONGARCH: 124 | return "loong64" 125 | case elf.EM_PPC64: 126 | if f.elf.ByteOrder == binary.LittleEndian { 127 | return "ppc64le" 128 | } 129 | return "ppc64" 130 | case elf.EM_RISCV: 131 | if f.elf.Class == elf.ELFCLASS64 { 132 | return "riscv64" 133 | } 134 | case elf.EM_S390: 135 | return "s390x" 136 | } 137 | return "" 138 | } 139 | 140 | func (f *elfFile) loadAddress() (uint64, error) { 141 | for _, p := range f.elf.Progs { 142 | if p.Type == elf.PT_LOAD && p.Flags&elf.PF_X != 0 { 143 | // The memory mapping that contains the segment 144 | // starts at an aligned address. Apparently this 145 | // is what pprof expects, as it uses this and the 146 | // start address of the mapping to compute PC 147 | // delta. 148 | return p.Vaddr - p.Vaddr%p.Align, nil 149 | } 150 | } 151 | return 0, fmt.Errorf("unknown load address") 152 | } 153 | 154 | func (f *elfFile) dwarf() (*dwarf.Data, error) { 155 | return f.elf.DWARF() 156 | } 157 | 158 | func (f *elfFile) symbolData(start, end string) []byte { 159 | elfSyms, err := f.elf.Symbols() 160 | if err != nil { 161 | return nil 162 | } 163 | var addr, eaddr uint64 164 | for _, s := range elfSyms { 165 | if s.Name == start { 166 | addr = s.Value 167 | } else if s.Name == end { 168 | eaddr = s.Value 169 | } 170 | if addr != 0 && eaddr != 0 { 171 | break 172 | } 173 | } 174 | if addr == 0 || eaddr < addr { 175 | return nil 176 | } 177 | size := eaddr - addr 178 | data := make([]byte, size) 179 | for _, prog := range f.elf.Progs { 180 | if prog.Vaddr <= addr && addr+size-1 <= prog.Vaddr+prog.Filesz-1 { 181 | if _, err := prog.ReadAt(data, int64(addr-prog.Vaddr)); err != nil { 182 | return nil 183 | } 184 | return data 185 | } 186 | } 187 | return nil 188 | } 189 | -------------------------------------------------------------------------------- /internal/go/src/objfile/macho.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Parsing of Mach-O executables (OS X). 6 | 7 | package objfile 8 | 9 | import ( 10 | "debug/dwarf" 11 | "debug/macho" 12 | "fmt" 13 | "io" 14 | "slices" 15 | "sort" 16 | ) 17 | 18 | const stabTypeMask = 0xe0 19 | 20 | type machoFile struct { 21 | macho *macho.File 22 | } 23 | 24 | func openMacho(r io.ReaderAt) (rawFile, error) { 25 | f, err := macho.NewFile(r) 26 | if err != nil { 27 | return nil, err 28 | } 29 | return &machoFile{f}, nil 30 | } 31 | 32 | func (f *machoFile) symbols() ([]Sym, error) { 33 | if f.macho.Symtab == nil { 34 | return nil, nil 35 | } 36 | 37 | // Build sorted list of addresses of all symbols. 38 | // We infer the size of a symbol by looking at where the next symbol begins. 39 | var addrs []uint64 40 | for _, s := range f.macho.Symtab.Syms { 41 | // Skip stab debug info. 42 | if s.Type&stabTypeMask == 0 { 43 | addrs = append(addrs, s.Value) 44 | } 45 | } 46 | slices.Sort(addrs) 47 | 48 | var syms []Sym 49 | for _, s := range f.macho.Symtab.Syms { 50 | if s.Type&stabTypeMask != 0 { 51 | // Skip stab debug info. 52 | continue 53 | } 54 | sym := Sym{Name: s.Name, Addr: s.Value, Code: '?'} 55 | i := sort.Search(len(addrs), func(x int) bool { return addrs[x] > s.Value }) 56 | if i < len(addrs) { 57 | sym.Size = int64(addrs[i] - s.Value) 58 | } 59 | if s.Sect == 0 { 60 | sym.Code = 'U' 61 | } else if int(s.Sect) <= len(f.macho.Sections) { 62 | sect := f.macho.Sections[s.Sect-1] 63 | switch sect.Seg { 64 | case "__TEXT", "__DATA_CONST": 65 | sym.Code = 'R' 66 | case "__DATA": 67 | sym.Code = 'D' 68 | } 69 | switch sect.Seg + " " + sect.Name { 70 | case "__TEXT __text": 71 | sym.Code = 'T' 72 | case "__DATA __bss", "__DATA __noptrbss": 73 | sym.Code = 'B' 74 | } 75 | } 76 | syms = append(syms, sym) 77 | } 78 | 79 | return syms, nil 80 | } 81 | 82 | func (f *machoFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) { 83 | if sect := f.macho.Section("__text"); sect != nil { 84 | textStart = sect.Addr 85 | } 86 | if sect := f.macho.Section("__gosymtab"); sect != nil { 87 | if symtab, err = sect.Data(); err != nil { 88 | return 0, nil, nil, err 89 | } 90 | } 91 | if sect := f.macho.Section("__gopclntab"); sect != nil { 92 | if pclntab, err = sect.Data(); err != nil { 93 | return 0, nil, nil, err 94 | } 95 | } 96 | return textStart, symtab, pclntab, nil 97 | } 98 | 99 | func (f *machoFile) text() (textStart uint64, text []byte, err error) { 100 | sect := f.macho.Section("__text") 101 | if sect == nil { 102 | return 0, nil, fmt.Errorf("text section not found") 103 | } 104 | textStart = sect.Addr 105 | text, err = sect.Data() 106 | return 107 | } 108 | 109 | func (f *machoFile) goarch() string { 110 | switch f.macho.Cpu { 111 | case macho.Cpu386: 112 | return "386" 113 | case macho.CpuAmd64: 114 | return "amd64" 115 | case macho.CpuArm: 116 | return "arm" 117 | case macho.CpuArm64: 118 | return "arm64" 119 | case macho.CpuPpc64: 120 | return "ppc64" 121 | } 122 | return "" 123 | } 124 | 125 | func (f *machoFile) loadAddress() (uint64, error) { 126 | if seg := f.macho.Segment("__TEXT"); seg != nil { 127 | return seg.Addr, nil 128 | } 129 | return 0, fmt.Errorf("unknown load address") 130 | } 131 | 132 | func (f *machoFile) dwarf() (*dwarf.Data, error) { 133 | return f.macho.DWARF() 134 | } 135 | -------------------------------------------------------------------------------- /internal/go/src/objfile/objfile.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package objfile implements portable access to OS-specific executable files. 6 | package objfile 7 | 8 | import ( 9 | "loov.dev/lensm/internal/go/src/archive" 10 | "cmp" 11 | "debug/dwarf" 12 | "debug/gosym" 13 | "fmt" 14 | "io" 15 | "os" 16 | "slices" 17 | ) 18 | 19 | type rawFile interface { 20 | symbols() (syms []Sym, err error) 21 | pcln() (textStart uint64, symtab, pclntab []byte, err error) 22 | text() (textStart uint64, text []byte, err error) 23 | goarch() string 24 | loadAddress() (uint64, error) 25 | dwarf() (*dwarf.Data, error) 26 | } 27 | 28 | // A File is an opened executable file. 29 | type File struct { 30 | r *os.File 31 | entries []*Entry 32 | } 33 | 34 | type Entry struct { 35 | name string 36 | raw rawFile 37 | } 38 | 39 | // A Sym is a symbol defined in an executable file. 40 | type Sym struct { 41 | Name string // symbol name 42 | Addr uint64 // virtual address of symbol 43 | Size int64 // size in bytes 44 | Code rune // nm code (T for text, D for data, and so on) 45 | Type string // XXX? 46 | Relocs []Reloc // in increasing Addr order 47 | } 48 | 49 | type Reloc struct { 50 | Addr uint64 // Address of first byte that reloc applies to. 51 | Size uint64 // Number of bytes 52 | Stringer RelocStringer 53 | } 54 | 55 | type RelocStringer interface { 56 | // insnOffset is the offset of the instruction containing the relocation 57 | // from the start of the symbol containing the relocation. 58 | String(insnOffset uint64) string 59 | } 60 | 61 | var openers = []func(io.ReaderAt) (rawFile, error){ 62 | openElf, 63 | openMacho, 64 | openPE, 65 | openPlan9, 66 | openXcoff, 67 | } 68 | 69 | // Open opens the named file. 70 | // The caller must call f.Close when the file is no longer needed. 71 | func Open(name string) (*File, error) { 72 | r, err := os.Open(name) 73 | if err != nil { 74 | return nil, err 75 | } 76 | if f, err := openGoFile(r); err == nil { 77 | return f, nil 78 | } else if _, ok := err.(archive.ErrGoObjOtherVersion); ok { 79 | return nil, fmt.Errorf("open %s: %v", name, err) 80 | } 81 | for _, try := range openers { 82 | if raw, err := try(r); err == nil { 83 | return &File{r, []*Entry{{raw: raw}}}, nil 84 | } 85 | } 86 | r.Close() 87 | return nil, fmt.Errorf("open %s: unrecognized object file", name) 88 | } 89 | 90 | func (f *File) Close() error { 91 | return f.r.Close() 92 | } 93 | 94 | func (f *File) Entries() []*Entry { 95 | return f.entries 96 | } 97 | 98 | func (f *File) Symbols() ([]Sym, error) { 99 | return f.entries[0].Symbols() 100 | } 101 | 102 | func (f *File) PCLineTable() (Liner, error) { 103 | return f.entries[0].PCLineTable() 104 | } 105 | 106 | func (f *File) Text() (uint64, []byte, error) { 107 | return f.entries[0].Text() 108 | } 109 | 110 | func (f *File) GOARCH() string { 111 | return f.entries[0].GOARCH() 112 | } 113 | 114 | func (f *File) LoadAddress() (uint64, error) { 115 | return f.entries[0].LoadAddress() 116 | } 117 | 118 | func (f *File) DWARF() (*dwarf.Data, error) { 119 | return f.entries[0].DWARF() 120 | } 121 | 122 | func (e *Entry) Name() string { 123 | return e.name 124 | } 125 | 126 | func (e *Entry) Symbols() ([]Sym, error) { 127 | syms, err := e.raw.symbols() 128 | if err != nil { 129 | return nil, err 130 | } 131 | slices.SortFunc(syms, func(a, b Sym) int { 132 | return cmp.Compare(a.Addr, b.Addr) 133 | }) 134 | return syms, nil 135 | } 136 | 137 | func (e *Entry) PCLineTable() (Liner, error) { 138 | // If the raw file implements Liner directly, use that. 139 | // Currently, only Go intermediate objects and archives (goobj) use this path. 140 | if pcln, ok := e.raw.(Liner); ok { 141 | return pcln, nil 142 | } 143 | // Otherwise, read the pcln tables and build a Liner out of that. 144 | textStart, symtab, pclntab, err := e.raw.pcln() 145 | if err != nil { 146 | return nil, err 147 | } 148 | syms, err := e.raw.symbols() 149 | if err == nil { 150 | for _, s := range syms { 151 | if s.Name == "runtime.text" { 152 | textStart = s.Addr 153 | break 154 | } 155 | } 156 | } 157 | return gosym.NewTable(symtab, gosym.NewLineTable(pclntab, textStart)) 158 | } 159 | 160 | func (e *Entry) Text() (uint64, []byte, error) { 161 | return e.raw.text() 162 | } 163 | 164 | func (e *Entry) GOARCH() string { 165 | return e.raw.goarch() 166 | } 167 | 168 | // LoadAddress returns the expected load address of the file. 169 | // This differs from the actual load address for a position-independent 170 | // executable. 171 | func (e *Entry) LoadAddress() (uint64, error) { 172 | return e.raw.loadAddress() 173 | } 174 | 175 | // DWARF returns DWARF debug data for the file, if any. 176 | // This is for cmd/pprof to locate cgo functions. 177 | func (e *Entry) DWARF() (*dwarf.Data, error) { 178 | return e.raw.dwarf() 179 | } 180 | 181 | type Liner interface { 182 | // Given a pc, returns the corresponding file, line, and function data. 183 | // If unknown, returns "",0,nil. 184 | PCToLine(uint64) (string, int, *gosym.Func) 185 | } 186 | -------------------------------------------------------------------------------- /internal/go/src/objfile/pe.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Parsing of PE executables (Microsoft Windows). 6 | 7 | package objfile 8 | 9 | import ( 10 | "debug/dwarf" 11 | "debug/pe" 12 | "fmt" 13 | "io" 14 | "slices" 15 | "sort" 16 | ) 17 | 18 | type peFile struct { 19 | pe *pe.File 20 | } 21 | 22 | func openPE(r io.ReaderAt) (rawFile, error) { 23 | f, err := pe.NewFile(r) 24 | if err != nil { 25 | return nil, err 26 | } 27 | return &peFile{f}, nil 28 | } 29 | 30 | func (f *peFile) symbols() ([]Sym, error) { 31 | // Build sorted list of addresses of all symbols. 32 | // We infer the size of a symbol by looking at where the next symbol begins. 33 | var addrs []uint64 34 | 35 | imageBase, _ := f.imageBase() 36 | 37 | var syms []Sym 38 | for _, s := range f.pe.Symbols { 39 | const ( 40 | N_UNDEF = 0 // An undefined (extern) symbol 41 | N_ABS = -1 // An absolute symbol (e_value is a constant, not an address) 42 | N_DEBUG = -2 // A debugging symbol 43 | ) 44 | sym := Sym{Name: s.Name, Addr: uint64(s.Value), Code: '?'} 45 | switch s.SectionNumber { 46 | case N_UNDEF: 47 | sym.Code = 'U' 48 | case N_ABS: 49 | sym.Code = 'C' 50 | case N_DEBUG: 51 | sym.Code = '?' 52 | default: 53 | if s.SectionNumber < 0 || len(f.pe.Sections) < int(s.SectionNumber) { 54 | return nil, fmt.Errorf("invalid section number in symbol table") 55 | } 56 | sect := f.pe.Sections[s.SectionNumber-1] 57 | const ( 58 | text = 0x20 59 | data = 0x40 60 | bss = 0x80 61 | permW = 0x80000000 62 | ) 63 | ch := sect.Characteristics 64 | switch { 65 | case ch&text != 0: 66 | sym.Code = 'T' 67 | case ch&data != 0: 68 | if ch&permW == 0 { 69 | sym.Code = 'R' 70 | } else { 71 | sym.Code = 'D' 72 | } 73 | case ch&bss != 0: 74 | sym.Code = 'B' 75 | } 76 | sym.Addr += imageBase + uint64(sect.VirtualAddress) 77 | } 78 | syms = append(syms, sym) 79 | addrs = append(addrs, sym.Addr) 80 | } 81 | 82 | slices.Sort(addrs) 83 | for i := range syms { 84 | j := sort.Search(len(addrs), func(x int) bool { return addrs[x] > syms[i].Addr }) 85 | if j < len(addrs) { 86 | syms[i].Size = int64(addrs[j] - syms[i].Addr) 87 | } 88 | } 89 | 90 | return syms, nil 91 | } 92 | 93 | func (f *peFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) { 94 | imageBase, err := f.imageBase() 95 | if err != nil { 96 | return 0, nil, nil, err 97 | } 98 | 99 | if sect := f.pe.Section(".text"); sect != nil { 100 | textStart = imageBase + uint64(sect.VirtualAddress) 101 | } 102 | if pclntab, err = loadPETable(f.pe, "runtime.pclntab", "runtime.epclntab"); err != nil { 103 | // We didn't find the symbols, so look for the names used in 1.3 and earlier. 104 | // TODO: Remove code looking for the old symbols when we no longer care about 1.3. 105 | var err2 error 106 | if pclntab, err2 = loadPETable(f.pe, "pclntab", "epclntab"); err2 != nil { 107 | return 0, nil, nil, err 108 | } 109 | } 110 | if symtab, err = loadPETable(f.pe, "runtime.symtab", "runtime.esymtab"); err != nil { 111 | // Same as above. 112 | var err2 error 113 | if symtab, err2 = loadPETable(f.pe, "symtab", "esymtab"); err2 != nil { 114 | return 0, nil, nil, err 115 | } 116 | } 117 | return textStart, symtab, pclntab, nil 118 | } 119 | 120 | func (f *peFile) text() (textStart uint64, text []byte, err error) { 121 | imageBase, err := f.imageBase() 122 | if err != nil { 123 | return 0, nil, err 124 | } 125 | 126 | sect := f.pe.Section(".text") 127 | if sect == nil { 128 | return 0, nil, fmt.Errorf("text section not found") 129 | } 130 | textStart = imageBase + uint64(sect.VirtualAddress) 131 | text, err = sect.Data() 132 | return 133 | } 134 | 135 | func findPESymbol(f *pe.File, name string) (*pe.Symbol, error) { 136 | for _, s := range f.Symbols { 137 | if s.Name != name { 138 | continue 139 | } 140 | if s.SectionNumber <= 0 { 141 | return nil, fmt.Errorf("symbol %s: invalid section number %d", name, s.SectionNumber) 142 | } 143 | if len(f.Sections) < int(s.SectionNumber) { 144 | return nil, fmt.Errorf("symbol %s: section number %d is larger than max %d", name, s.SectionNumber, len(f.Sections)) 145 | } 146 | return s, nil 147 | } 148 | return nil, fmt.Errorf("no %s symbol found", name) 149 | } 150 | 151 | func loadPETable(f *pe.File, sname, ename string) ([]byte, error) { 152 | ssym, err := findPESymbol(f, sname) 153 | if err != nil { 154 | return nil, err 155 | } 156 | esym, err := findPESymbol(f, ename) 157 | if err != nil { 158 | return nil, err 159 | } 160 | if ssym.SectionNumber != esym.SectionNumber { 161 | return nil, fmt.Errorf("%s and %s symbols must be in the same section", sname, ename) 162 | } 163 | sect := f.Sections[ssym.SectionNumber-1] 164 | data, err := sect.Data() 165 | if err != nil { 166 | return nil, err 167 | } 168 | return data[ssym.Value:esym.Value], nil 169 | } 170 | 171 | func (f *peFile) goarch() string { 172 | switch f.pe.Machine { 173 | case pe.IMAGE_FILE_MACHINE_I386: 174 | return "386" 175 | case pe.IMAGE_FILE_MACHINE_AMD64: 176 | return "amd64" 177 | case pe.IMAGE_FILE_MACHINE_ARMNT: 178 | return "arm" 179 | case pe.IMAGE_FILE_MACHINE_ARM64: 180 | return "arm64" 181 | default: 182 | return "" 183 | } 184 | } 185 | 186 | func (f *peFile) loadAddress() (uint64, error) { 187 | return f.imageBase() 188 | } 189 | 190 | func (f *peFile) imageBase() (uint64, error) { 191 | switch oh := f.pe.OptionalHeader.(type) { 192 | case *pe.OptionalHeader32: 193 | return uint64(oh.ImageBase), nil 194 | case *pe.OptionalHeader64: 195 | return oh.ImageBase, nil 196 | default: 197 | return 0, fmt.Errorf("pe file format not recognized") 198 | } 199 | } 200 | 201 | func (f *peFile) dwarf() (*dwarf.Data, error) { 202 | return f.pe.DWARF() 203 | } 204 | -------------------------------------------------------------------------------- /internal/go/src/objfile/plan9obj.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Parsing of Plan 9 a.out executables. 6 | 7 | package objfile 8 | 9 | import ( 10 | "debug/dwarf" 11 | "debug/plan9obj" 12 | "errors" 13 | "fmt" 14 | "io" 15 | "slices" 16 | "sort" 17 | ) 18 | 19 | var validSymType = map[rune]bool{ 20 | 'T': true, 21 | 't': true, 22 | 'D': true, 23 | 'd': true, 24 | 'B': true, 25 | 'b': true, 26 | } 27 | 28 | type plan9File struct { 29 | plan9 *plan9obj.File 30 | } 31 | 32 | func openPlan9(r io.ReaderAt) (rawFile, error) { 33 | f, err := plan9obj.NewFile(r) 34 | if err != nil { 35 | return nil, err 36 | } 37 | return &plan9File{f}, nil 38 | } 39 | 40 | func (f *plan9File) symbols() ([]Sym, error) { 41 | plan9Syms, err := f.plan9.Symbols() 42 | if err != nil { 43 | return nil, err 44 | } 45 | 46 | // Build sorted list of addresses of all symbols. 47 | // We infer the size of a symbol by looking at where the next symbol begins. 48 | var addrs []uint64 49 | for _, s := range plan9Syms { 50 | if !validSymType[s.Type] { 51 | continue 52 | } 53 | addrs = append(addrs, s.Value) 54 | } 55 | slices.Sort(addrs) 56 | 57 | var syms []Sym 58 | 59 | for _, s := range plan9Syms { 60 | if !validSymType[s.Type] { 61 | continue 62 | } 63 | sym := Sym{Addr: s.Value, Name: s.Name, Code: s.Type} 64 | i := sort.Search(len(addrs), func(x int) bool { return addrs[x] > s.Value }) 65 | if i < len(addrs) { 66 | sym.Size = int64(addrs[i] - s.Value) 67 | } 68 | syms = append(syms, sym) 69 | } 70 | 71 | return syms, nil 72 | } 73 | 74 | func (f *plan9File) pcln() (textStart uint64, symtab, pclntab []byte, err error) { 75 | textStart = f.plan9.LoadAddress + f.plan9.HdrSize 76 | if pclntab, err = loadPlan9Table(f.plan9, "runtime.pclntab", "runtime.epclntab"); err != nil { 77 | // We didn't find the symbols, so look for the names used in 1.3 and earlier. 78 | // TODO: Remove code looking for the old symbols when we no longer care about 1.3. 79 | var err2 error 80 | if pclntab, err2 = loadPlan9Table(f.plan9, "pclntab", "epclntab"); err2 != nil { 81 | return 0, nil, nil, err 82 | } 83 | } 84 | if symtab, err = loadPlan9Table(f.plan9, "runtime.symtab", "runtime.esymtab"); err != nil { 85 | // Same as above. 86 | var err2 error 87 | if symtab, err2 = loadPlan9Table(f.plan9, "symtab", "esymtab"); err2 != nil { 88 | return 0, nil, nil, err 89 | } 90 | } 91 | return textStart, symtab, pclntab, nil 92 | } 93 | 94 | func (f *plan9File) text() (textStart uint64, text []byte, err error) { 95 | sect := f.plan9.Section("text") 96 | if sect == nil { 97 | return 0, nil, fmt.Errorf("text section not found") 98 | } 99 | textStart = f.plan9.LoadAddress + f.plan9.HdrSize 100 | text, err = sect.Data() 101 | return 102 | } 103 | 104 | func findPlan9Symbol(f *plan9obj.File, name string) (*plan9obj.Sym, error) { 105 | syms, err := f.Symbols() 106 | if err != nil { 107 | return nil, err 108 | } 109 | for _, s := range syms { 110 | if s.Name != name { 111 | continue 112 | } 113 | return &s, nil 114 | } 115 | return nil, fmt.Errorf("no %s symbol found", name) 116 | } 117 | 118 | func loadPlan9Table(f *plan9obj.File, sname, ename string) ([]byte, error) { 119 | ssym, err := findPlan9Symbol(f, sname) 120 | if err != nil { 121 | return nil, err 122 | } 123 | esym, err := findPlan9Symbol(f, ename) 124 | if err != nil { 125 | return nil, err 126 | } 127 | sect := f.Section("text") 128 | if sect == nil { 129 | return nil, err 130 | } 131 | data, err := sect.Data() 132 | if err != nil { 133 | return nil, err 134 | } 135 | textStart := f.LoadAddress + f.HdrSize 136 | return data[ssym.Value-textStart : esym.Value-textStart], nil 137 | } 138 | 139 | func (f *plan9File) goarch() string { 140 | switch f.plan9.Magic { 141 | case plan9obj.Magic386: 142 | return "386" 143 | case plan9obj.MagicAMD64: 144 | return "amd64" 145 | case plan9obj.MagicARM: 146 | return "arm" 147 | } 148 | return "" 149 | } 150 | 151 | func (f *plan9File) loadAddress() (uint64, error) { 152 | return 0, fmt.Errorf("unknown load address") 153 | } 154 | 155 | func (f *plan9File) dwarf() (*dwarf.Data, error) { 156 | return nil, errors.New("no DWARF data in Plan 9 file") 157 | } 158 | -------------------------------------------------------------------------------- /internal/go/src/objfile/xcoff.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Parsing of XCOFF executable (AIX) 6 | 7 | package objfile 8 | 9 | import ( 10 | "debug/dwarf" 11 | "fmt" 12 | "loov.dev/lensm/internal/go/src/xcoff" 13 | "io" 14 | "unicode" 15 | ) 16 | 17 | type xcoffFile struct { 18 | xcoff *xcoff.File 19 | } 20 | 21 | func openXcoff(r io.ReaderAt) (rawFile, error) { 22 | f, err := xcoff.NewFile(r) 23 | if err != nil { 24 | return nil, err 25 | } 26 | return &xcoffFile{f}, nil 27 | } 28 | 29 | func (f *xcoffFile) symbols() ([]Sym, error) { 30 | var syms []Sym 31 | for _, s := range f.xcoff.Symbols { 32 | const ( 33 | N_UNDEF = 0 // An undefined (extern) symbol 34 | N_ABS = -1 // An absolute symbol (e_value is a constant, not an address) 35 | N_DEBUG = -2 // A debugging symbol 36 | ) 37 | sym := Sym{Name: s.Name, Addr: s.Value, Code: '?'} 38 | 39 | switch s.SectionNumber { 40 | case N_UNDEF: 41 | sym.Code = 'U' 42 | case N_ABS: 43 | sym.Code = 'C' 44 | case N_DEBUG: 45 | sym.Code = '?' 46 | default: 47 | if s.SectionNumber < 0 || len(f.xcoff.Sections) < int(s.SectionNumber) { 48 | return nil, fmt.Errorf("invalid section number in symbol table") 49 | } 50 | sect := f.xcoff.Sections[s.SectionNumber-1] 51 | 52 | // debug/xcoff returns an offset in the section not the actual address 53 | sym.Addr += sect.VirtualAddress 54 | 55 | if s.AuxCSect.SymbolType&0x3 == xcoff.XTY_LD { 56 | // The size of a function is contained in the 57 | // AUX_FCN entry 58 | sym.Size = s.AuxFcn.Size 59 | } else { 60 | sym.Size = s.AuxCSect.Length 61 | } 62 | 63 | sym.Size = s.AuxCSect.Length 64 | 65 | switch sect.Type { 66 | case xcoff.STYP_TEXT: 67 | if s.AuxCSect.StorageMappingClass == xcoff.XMC_RO { 68 | sym.Code = 'R' 69 | } else { 70 | sym.Code = 'T' 71 | } 72 | case xcoff.STYP_DATA: 73 | sym.Code = 'D' 74 | case xcoff.STYP_BSS: 75 | sym.Code = 'B' 76 | } 77 | 78 | if s.StorageClass == xcoff.C_HIDEXT { 79 | // Local symbol 80 | sym.Code = unicode.ToLower(sym.Code) 81 | } 82 | 83 | } 84 | syms = append(syms, sym) 85 | } 86 | 87 | return syms, nil 88 | } 89 | 90 | func (f *xcoffFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) { 91 | if sect := f.xcoff.Section(".text"); sect != nil { 92 | textStart = sect.VirtualAddress 93 | } 94 | if pclntab, err = loadXCOFFTable(f.xcoff, "runtime.pclntab", "runtime.epclntab"); err != nil { 95 | return 0, nil, nil, err 96 | } 97 | symtab, _ = loadXCOFFTable(f.xcoff, "runtime.symtab", "runtime.esymtab") // ignore error, this symbol is not useful anyway 98 | return textStart, symtab, pclntab, nil 99 | } 100 | 101 | func (f *xcoffFile) text() (textStart uint64, text []byte, err error) { 102 | sect := f.xcoff.Section(".text") 103 | if sect == nil { 104 | return 0, nil, fmt.Errorf("text section not found") 105 | } 106 | textStart = sect.VirtualAddress 107 | text, err = sect.Data() 108 | return 109 | } 110 | 111 | func findXCOFFSymbol(f *xcoff.File, name string) (*xcoff.Symbol, error) { 112 | for _, s := range f.Symbols { 113 | if s.Name != name { 114 | continue 115 | } 116 | if s.SectionNumber <= 0 { 117 | return nil, fmt.Errorf("symbol %s: invalid section number %d", name, s.SectionNumber) 118 | } 119 | if len(f.Sections) < int(s.SectionNumber) { 120 | return nil, fmt.Errorf("symbol %s: section number %d is larger than max %d", name, s.SectionNumber, len(f.Sections)) 121 | } 122 | return s, nil 123 | } 124 | return nil, fmt.Errorf("no %s symbol found", name) 125 | } 126 | 127 | func loadXCOFFTable(f *xcoff.File, sname, ename string) ([]byte, error) { 128 | ssym, err := findXCOFFSymbol(f, sname) 129 | if err != nil { 130 | return nil, err 131 | } 132 | esym, err := findXCOFFSymbol(f, ename) 133 | if err != nil { 134 | return nil, err 135 | } 136 | if ssym.SectionNumber != esym.SectionNumber { 137 | return nil, fmt.Errorf("%s and %s symbols must be in the same section", sname, ename) 138 | } 139 | sect := f.Sections[ssym.SectionNumber-1] 140 | data, err := sect.Data() 141 | if err != nil { 142 | return nil, err 143 | } 144 | return data[ssym.Value:esym.Value], nil 145 | } 146 | 147 | func (f *xcoffFile) goarch() string { 148 | switch f.xcoff.TargetMachine { 149 | case xcoff.U802TOCMAGIC: 150 | return "ppc" 151 | case xcoff.U64_TOCMAGIC: 152 | return "ppc64" 153 | } 154 | return "" 155 | } 156 | 157 | func (f *xcoffFile) loadAddress() (uint64, error) { 158 | return 0, fmt.Errorf("unknown load address") 159 | } 160 | 161 | func (f *xcoffFile) dwarf() (*dwarf.Data, error) { 162 | return f.xcoff.DWARF() 163 | } 164 | -------------------------------------------------------------------------------- /internal/go/src/saferio/io.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package saferio provides I/O functions that avoid allocating large 6 | // amounts of memory unnecessarily. This is intended for packages that 7 | // read data from an [io.Reader] where the size is part of the input 8 | // data but the input may be corrupt, or may be provided by an 9 | // untrustworthy attacker. 10 | package saferio 11 | 12 | import ( 13 | "io" 14 | "unsafe" 15 | ) 16 | 17 | // chunk is an arbitrary limit on how much memory we are willing 18 | // to allocate without concern. 19 | const chunk = 10 << 20 // 10M 20 | 21 | // ReadData reads n bytes from the input stream, but avoids allocating 22 | // all n bytes if n is large. This avoids crashing the program by 23 | // allocating all n bytes in cases where n is incorrect. 24 | // 25 | // The error is io.EOF only if no bytes were read. 26 | // If an io.EOF happens after reading some but not all the bytes, 27 | // ReadData returns io.ErrUnexpectedEOF. 28 | func ReadData(r io.Reader, n uint64) ([]byte, error) { 29 | if int64(n) < 0 || n != uint64(int(n)) { 30 | // n is too large to fit in int, so we can't allocate 31 | // a buffer large enough. Treat this as a read failure. 32 | return nil, io.ErrUnexpectedEOF 33 | } 34 | 35 | if n < chunk { 36 | buf := make([]byte, n) 37 | _, err := io.ReadFull(r, buf) 38 | if err != nil { 39 | return nil, err 40 | } 41 | return buf, nil 42 | } 43 | 44 | var buf []byte 45 | buf1 := make([]byte, chunk) 46 | for n > 0 { 47 | next := n 48 | if next > chunk { 49 | next = chunk 50 | } 51 | _, err := io.ReadFull(r, buf1[:next]) 52 | if err != nil { 53 | if len(buf) > 0 && err == io.EOF { 54 | err = io.ErrUnexpectedEOF 55 | } 56 | return nil, err 57 | } 58 | buf = append(buf, buf1[:next]...) 59 | n -= next 60 | } 61 | return buf, nil 62 | } 63 | 64 | // ReadDataAt reads n bytes from the input stream at off, but avoids 65 | // allocating all n bytes if n is large. This avoids crashing the program 66 | // by allocating all n bytes in cases where n is incorrect. 67 | func ReadDataAt(r io.ReaderAt, n uint64, off int64) ([]byte, error) { 68 | if int64(n) < 0 || n != uint64(int(n)) { 69 | // n is too large to fit in int, so we can't allocate 70 | // a buffer large enough. Treat this as a read failure. 71 | return nil, io.ErrUnexpectedEOF 72 | } 73 | 74 | if n < chunk { 75 | buf := make([]byte, n) 76 | _, err := r.ReadAt(buf, off) 77 | if err != nil { 78 | // io.SectionReader can return EOF for n == 0, 79 | // but for our purposes that is a success. 80 | if err != io.EOF || n > 0 { 81 | return nil, err 82 | } 83 | } 84 | return buf, nil 85 | } 86 | 87 | var buf []byte 88 | buf1 := make([]byte, chunk) 89 | for n > 0 { 90 | next := n 91 | if next > chunk { 92 | next = chunk 93 | } 94 | _, err := r.ReadAt(buf1[:next], off) 95 | if err != nil { 96 | return nil, err 97 | } 98 | buf = append(buf, buf1[:next]...) 99 | n -= next 100 | off += int64(next) 101 | } 102 | return buf, nil 103 | } 104 | 105 | // SliceCapWithSize returns the capacity to use when allocating a slice. 106 | // After the slice is allocated with the capacity, it should be 107 | // built using append. This will avoid allocating too much memory 108 | // if the capacity is large and incorrect. 109 | // 110 | // A negative result means that the value is always too big. 111 | func SliceCapWithSize(size, c uint64) int { 112 | if int64(c) < 0 || c != uint64(int(c)) { 113 | return -1 114 | } 115 | if size > 0 && c > (1<<64-1)/size { 116 | return -1 117 | } 118 | if c*size > chunk { 119 | c = chunk / size 120 | if c == 0 { 121 | c = 1 122 | } 123 | } 124 | return int(c) 125 | } 126 | 127 | // SliceCap is like SliceCapWithSize but using generics. 128 | func SliceCap[E any](c uint64) int { 129 | var v E 130 | size := uint64(unsafe.Sizeof(v)) 131 | return SliceCapWithSize(size, c) 132 | } 133 | -------------------------------------------------------------------------------- /internal/go/src/src/xpos.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file implements the compressed encoding of source 6 | // positions using a lookup table. 7 | 8 | package src 9 | 10 | // XPos is a more compact representation of Pos. 11 | type XPos struct { 12 | index int32 13 | lico 14 | } 15 | 16 | // NoXPos is a valid unknown position. 17 | var NoXPos XPos 18 | 19 | // IsKnown reports whether the position p is known. 20 | // XPos.IsKnown() matches Pos.IsKnown() for corresponding 21 | // positions. 22 | func (p XPos) IsKnown() bool { 23 | return p.index != 0 || p.Line() != 0 24 | } 25 | 26 | // Before reports whether the position p comes before q in the source. 27 | // For positions with different bases, ordering is by base index. 28 | func (p XPos) Before(q XPos) bool { 29 | n, m := p.index, q.index 30 | return n < m || n == m && p.lico < q.lico 31 | } 32 | 33 | // SameFile reports whether p and q are positions in the same file. 34 | func (p XPos) SameFile(q XPos) bool { 35 | return p.index == q.index 36 | } 37 | 38 | // SameFileAndLine reports whether p and q are positions on the same line in the same file. 39 | func (p XPos) SameFileAndLine(q XPos) bool { 40 | return p.index == q.index && p.lico.SameLine(q.lico) 41 | } 42 | 43 | // After reports whether the position p comes after q in the source. 44 | // For positions with different bases, ordering is by base index. 45 | func (p XPos) After(q XPos) bool { 46 | n, m := p.index, q.index 47 | return n > m || n == m && p.lico > q.lico 48 | } 49 | 50 | // WithNotStmt returns the same location to be marked with DWARF is_stmt=0 51 | func (p XPos) WithNotStmt() XPos { 52 | p.lico = p.lico.withNotStmt() 53 | return p 54 | } 55 | 56 | // WithDefaultStmt returns the same location with undetermined is_stmt 57 | func (p XPos) WithDefaultStmt() XPos { 58 | p.lico = p.lico.withDefaultStmt() 59 | return p 60 | } 61 | 62 | // WithIsStmt returns the same location to be marked with DWARF is_stmt=1 63 | func (p XPos) WithIsStmt() XPos { 64 | p.lico = p.lico.withIsStmt() 65 | return p 66 | } 67 | 68 | // WithBogusLine returns a bogus line that won't match any recorded for the source code. 69 | // Its use is to disrupt the statements within an infinite loop so that the debugger 70 | // will not itself loop infinitely waiting for the line number to change. 71 | // gdb chooses not to display the bogus line; delve shows it with a complaint, but the 72 | // alternative behavior is to hang. 73 | func (p XPos) WithBogusLine() XPos { 74 | if p.index == 0 { 75 | // See #35652 76 | panic("Assigning a bogus line to XPos with no file will cause mysterious downstream failures.") 77 | } 78 | p.lico = makeBogusLico() 79 | return p 80 | } 81 | 82 | // WithXlogue returns the same location but marked with DWARF function prologue/epilogue 83 | func (p XPos) WithXlogue(x PosXlogue) XPos { 84 | p.lico = p.lico.withXlogue(x) 85 | return p 86 | } 87 | 88 | // LineNumber returns a string for the line number, "?" if it is not known. 89 | func (p XPos) LineNumber() string { 90 | if !p.IsKnown() { 91 | return "?" 92 | } 93 | return p.lico.lineNumber() 94 | } 95 | 96 | // FileIndex returns a smallish non-negative integer corresponding to the 97 | // file for this source position. Smallish is relative; it can be thousands 98 | // large, but not millions. 99 | func (p XPos) FileIndex() int32 { 100 | return p.index 101 | } 102 | 103 | func (p XPos) LineNumberHTML() string { 104 | if !p.IsKnown() { 105 | return "?" 106 | } 107 | return p.lico.lineNumberHTML() 108 | } 109 | 110 | // AtColumn1 returns the same location but shifted to column 1. 111 | func (p XPos) AtColumn1() XPos { 112 | p.lico = p.lico.atColumn1() 113 | return p 114 | } 115 | 116 | // A PosTable tracks Pos -> XPos conversions and vice versa. 117 | // Its zero value is a ready-to-use PosTable. 118 | type PosTable struct { 119 | baseList []*PosBase 120 | indexMap map[*PosBase]int 121 | nameMap map[string]int // Maps file symbol name to index for debug information. 122 | } 123 | 124 | // XPos returns the corresponding XPos for the given pos, 125 | // adding pos to t if necessary. 126 | func (t *PosTable) XPos(pos Pos) XPos { 127 | return XPos{t.baseIndex(pos.base), pos.lico} 128 | } 129 | 130 | func (t *PosTable) baseIndex(base *PosBase) int32 { 131 | if base == nil { 132 | return 0 133 | } 134 | 135 | if i, ok := t.indexMap[base]; ok { 136 | return int32(i) 137 | } 138 | 139 | if base.fileIndex >= 0 { 140 | panic("PosBase already registered with a PosTable") 141 | } 142 | 143 | if t.indexMap == nil { 144 | t.baseList = append(t.baseList, nil) 145 | t.indexMap = make(map[*PosBase]int) 146 | t.nameMap = make(map[string]int) 147 | } 148 | 149 | i := len(t.baseList) 150 | t.indexMap[base] = i 151 | t.baseList = append(t.baseList, base) 152 | 153 | fileIndex, ok := t.nameMap[base.absFilename] 154 | if !ok { 155 | fileIndex = len(t.nameMap) 156 | t.nameMap[base.absFilename] = fileIndex 157 | } 158 | base.fileIndex = fileIndex 159 | 160 | return int32(i) 161 | } 162 | 163 | // Pos returns the corresponding Pos for the given p. 164 | // If p cannot be translated via t, the function panics. 165 | func (t *PosTable) Pos(p XPos) Pos { 166 | var base *PosBase 167 | if p.index != 0 { 168 | base = t.baseList[p.index] 169 | } 170 | return Pos{base, p.lico} 171 | } 172 | 173 | // FileTable returns a slice of all files used to build this package. 174 | func (t *PosTable) FileTable() []string { 175 | // Create a LUT of the global package level file indices. This table is what 176 | // is written in the debug_lines header, the file[N] will be referenced as 177 | // N+1 in the debug_lines table. 178 | fileLUT := make([]string, len(t.nameMap)) 179 | for str, i := range t.nameMap { 180 | fileLUT[i] = str 181 | } 182 | return fileLUT 183 | } 184 | -------------------------------------------------------------------------------- /internal/go/src/sys/args.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package sys 6 | 7 | // ExecArgLengthLimit is the number of bytes we can safely 8 | // pass as arguments to an exec.Command. 9 | // 10 | // Windows has a limit of 32 KB. To be conservative and not worry about whether 11 | // that includes spaces or not, just use 30 KB. Darwin's limit is less clear. 12 | // The OS claims 256KB, but we've seen failures with arglen as small as 50KB. 13 | const ExecArgLengthLimit = (30 << 10) 14 | -------------------------------------------------------------------------------- /internal/go/src/unsafeheader/unsafeheader.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package unsafeheader contains header declarations for the Go runtime's slice 6 | // and string implementations. 7 | // 8 | // This package allows packages that cannot import "reflect" to use types that 9 | // are tested to be equivalent to reflect.SliceHeader and reflect.StringHeader. 10 | package unsafeheader 11 | 12 | import ( 13 | "unsafe" 14 | ) 15 | 16 | // Slice is the runtime representation of a slice. 17 | // It cannot be used safely or portably and its representation may 18 | // change in a later release. 19 | // 20 | // Unlike reflect.SliceHeader, its Data field is sufficient to guarantee the 21 | // data it references will not be garbage collected. 22 | type Slice struct { 23 | Data unsafe.Pointer 24 | Len int 25 | Cap int 26 | } 27 | 28 | // String is the runtime representation of a string. 29 | // It cannot be used safely or portably and its representation may 30 | // change in a later release. 31 | // 32 | // Unlike reflect.StringHeader, its Data field is sufficient to guarantee the 33 | // data it references will not be garbage collected. 34 | type String struct { 35 | Data unsafe.Pointer 36 | Len int 37 | } 38 | -------------------------------------------------------------------------------- /internal/go/update.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | //go:generate go run update.go 4 | 5 | import ( 6 | "bytes" 7 | "io/fs" 8 | "os" 9 | "os/exec" 10 | "path/filepath" 11 | "strings" 12 | ) 13 | 14 | func main() { 15 | must0(os.RemoveAll("src")) 16 | must0(os.Mkdir("src", 0755)) 17 | 18 | goroot := strings.TrimSpace(must(run("go", "env", "GOROOT"))) 19 | for _, subdir := range []string{"archive", "bio", "goobj", "objabi", "objfile", "src", "sys", "disasm"} { 20 | dir := filepath.Join(goroot, "src/cmd/internal", subdir) 21 | copydir(dir, filepath.Join("src", subdir)) 22 | } 23 | for _, subdir := range []string{"abi", "goarch", "bisect", "buildcfg", "goexperiment", "saferio", "unsafeheader", "xcoff"} { 24 | dir := filepath.Join(goroot, "src/internal", subdir) 25 | copydir(dir, filepath.Join("src", subdir)) 26 | } 27 | 28 | must0(os.WriteFile("src/disasm/expose.go", must(os.ReadFile("expose.go_")), 0644)) 29 | must0(os.Remove("src/abi/abi_test.s")) 30 | } 31 | 32 | func copydir(srcdir, dstdir string) { 33 | must0(os.MkdirAll(dstdir, 0755)) 34 | must0(filepath.WalkDir(srcdir, func(path string, d fs.DirEntry, err error) error { 35 | if err != nil { 36 | return err 37 | } 38 | base := must(filepath.Rel(srcdir, path)) 39 | 40 | if d.IsDir() { 41 | if d.Name() == "testdata" { 42 | return fs.SkipDir 43 | } 44 | return os.MkdirAll(filepath.Join(dstdir, base), 0755) 45 | } 46 | if strings.HasSuffix(d.Name(), "_test.go") { 47 | return nil 48 | } 49 | 50 | dstfile := filepath.Join(dstdir, base) 51 | data := must(os.ReadFile(path)) 52 | 53 | data = bytes.ReplaceAll(data, []byte(` "cmd/internal/`), []byte(` "loov.dev/lensm/internal/go/src/`)) 54 | data = bytes.ReplaceAll(data, []byte(`import "cmd/internal/`), []byte(`import "loov.dev/lensm/internal/go/src/`)) 55 | data = bytes.ReplaceAll(data, []byte(` "internal/`), []byte(` "loov.dev/lensm/internal/go/src/`)) 56 | data = bytes.ReplaceAll(data, []byte(`import "internal/`), []byte(`import "loov.dev/lensm/internal/go/src/`)) 57 | 58 | return os.WriteFile(dstfile, data, 0755) 59 | })) 60 | } 61 | 62 | func run(cmd string, args ...string) (string, error) { 63 | out, err := exec.Command(cmd, args...).Output() 64 | return string(out), err 65 | } 66 | 67 | func must0(err error) { 68 | if err != nil { 69 | panic(err) 70 | } 71 | } 72 | 73 | func must[T any](v T, err error) T { 74 | if err != nil { 75 | panic(err) 76 | } 77 | return v 78 | } 79 | -------------------------------------------------------------------------------- /internal/goobj/file.go: -------------------------------------------------------------------------------- 1 | package goobj 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "regexp" 7 | "sort" 8 | "strings" 9 | 10 | "loov.dev/lensm/internal/disasm" 11 | godisasm "loov.dev/lensm/internal/go/src/disasm" 12 | "loov.dev/lensm/internal/go/src/objfile" 13 | ) 14 | 15 | var _ disasm.File = (*File)(nil) 16 | var _ disasm.Func = (*Function)(nil) 17 | 18 | // File contains information about the object file. 19 | type File struct { 20 | objfile *objfile.File 21 | disasm *godisasm.Disasm 22 | funcs []disasm.Func 23 | 24 | cache map[*Function]*disasm.Code 25 | } 26 | 27 | func (file *File) Funcs() []disasm.Func { return file.funcs } 28 | 29 | // Function contains information about the executable. 30 | type Function struct { 31 | obj *File 32 | sym objfile.Sym 33 | 34 | sortName string 35 | } 36 | 37 | func (fn *Function) Name() string { return fn.sym.Name } 38 | 39 | func (file *File) Close() error { 40 | return file.objfile.Close() 41 | } 42 | 43 | func Load(path string) (*File, error) { 44 | f, err := objfile.Open(path) 45 | if err != nil { 46 | return nil, err 47 | } 48 | 49 | dis, err := godisasm.DisasmForFile(f) 50 | if err != nil { 51 | _ = f.Close() 52 | return nil, err 53 | } 54 | 55 | file := &File{ 56 | objfile: f, 57 | disasm: dis, 58 | cache: make(map[*Function]*disasm.Code), 59 | } 60 | 61 | for _, sym := range dis.Syms() { 62 | if sym.Code != 'T' && sym.Code != 't' || sym.Addr < dis.TextStart() { 63 | continue 64 | } 65 | sym := &Function{ 66 | obj: file, 67 | sym: sym, 68 | sortName: sortingName(sym.Name), 69 | } 70 | file.funcs = append(file.funcs, sym) 71 | } 72 | 73 | sort.SliceStable(file.funcs, func(i, k int) bool { 74 | return sortingName(file.funcs[i].Name()) < sortingName(file.funcs[k].Name()) 75 | }) 76 | 77 | return file, nil 78 | } 79 | 80 | func (fn *Function) Load(opts disasm.Options) *disasm.Code { 81 | return fn.obj.LoadCode(fn, opts) 82 | } 83 | 84 | func (file *File) LoadCode(fn *Function, opts disasm.Options) *disasm.Code { 85 | code, ok := file.cache[fn] 86 | if !ok { 87 | var err error 88 | code, err = Disassemble(fn.obj.disasm, fn, opts) 89 | file.cache[fn] = code 90 | if err != nil { 91 | _, _ = fmt.Fprintln(os.Stderr, err) 92 | } 93 | } 94 | 95 | return code 96 | } 97 | 98 | var rxCodeDelimiter = regexp.MustCompile(`[ *().]+`) 99 | 100 | func sortingName(sym string) string { 101 | sym = strings.ToLower(sym) 102 | return rxCodeDelimiter.ReplaceAllString(sym, " ") 103 | } 104 | -------------------------------------------------------------------------------- /internal/wasmobj/file.go: -------------------------------------------------------------------------------- 1 | package wasmobj 2 | 3 | import ( 4 | "debug/dwarf" 5 | "fmt" 6 | "os" 7 | "sort" 8 | "strings" 9 | 10 | "github.com/tetratelabs/wabin/binary" 11 | "github.com/tetratelabs/wabin/wasm" 12 | 13 | "loov.dev/lensm/internal/disasm" 14 | ) 15 | 16 | var _ disasm.File = (*File)(nil) 17 | var _ disasm.Func = (*Func)(nil) 18 | 19 | // File contains information about the object file. 20 | type File struct { 21 | module *wasm.Module 22 | dwarf *dwarf.Data 23 | 24 | funcs []disasm.Func 25 | } 26 | 27 | func (file *File) Funcs() []disasm.Func { return file.funcs } 28 | 29 | // Func contains information about the executable. 30 | type Func struct { 31 | obj *File 32 | index wasm.Index 33 | name string 34 | code *wasm.Code 35 | sortName string 36 | } 37 | 38 | func (fn *Func) Name() string { return fn.name } 39 | 40 | func (file *File) Close() error { 41 | return nil 42 | } 43 | 44 | func Load(path string) (*File, error) { 45 | obj := &File{} 46 | 47 | data, err := os.ReadFile(path) 48 | if err != nil { 49 | return nil, err 50 | } 51 | 52 | module, err := binary.DecodeModule(data, wasm.CoreFeaturesV2) 53 | if err != nil { 54 | return nil, err 55 | } 56 | obj.module = module 57 | 58 | tryParseDWARF(module) 59 | 60 | fmt.Println("LOCAL NAMES", module.NameSection.LocalNames) 61 | fmt.Println("FUNC NAMES", module.NameSection.FunctionNames) 62 | 63 | for i, fnname := range module.NameSection.FunctionNames { 64 | code := module.CodeSection[i] 65 | sym := &Func{ 66 | obj: obj, 67 | index: fnname.Index, 68 | name: fnname.Name, 69 | code: code, 70 | sortName: strings.ToLower(fnname.Name), 71 | } 72 | obj.funcs = append(obj.funcs, sym) 73 | } 74 | 75 | sort.SliceStable(obj.funcs, func(i, k int) bool { 76 | return strings.ToLower(obj.funcs[i].Name()) < strings.ToLower(obj.funcs[k].Name()) 77 | }) 78 | 79 | return obj, nil 80 | } 81 | 82 | func (fn *Func) Load(opts disasm.Options) *disasm.Code { 83 | return fn.obj.LoadCode(fn, opts) 84 | } 85 | 86 | func (file *File) LoadCode(fn *Func, opts disasm.Options) *disasm.Code { 87 | code := &disasm.Code{ 88 | Name: fn.name, 89 | } 90 | 91 | // TODO: https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-instr 92 | 93 | for i, b := range fn.code.Body { 94 | code.Insts = append(code.Insts, disasm.Inst{ 95 | PC: uint64(i), 96 | Text: fmt.Sprintf("BYTE 0x%0x2", b), 97 | }) 98 | } 99 | return code 100 | } 101 | 102 | /* 103 | func (file *File) LoadCode(fn *Func, opts disasm.Options) *disasm.Code { 104 | dis, err := wasmdisasm.NewDisassembly(*fn.fn, file.module) 105 | if err != nil { 106 | return &disasm.Code{Name: err.Error()} 107 | } 108 | 109 | code := &disasm.Code{ 110 | Name: fn.fn.Name, 111 | } 112 | 113 | for i, ix := range dis.Code { 114 | code.Insts = append(code.Insts, file.toInstr(dis, i, ix)) 115 | } 116 | 117 | return code 118 | } 119 | func (file *File) toInstr(dis *wasmdisasm.Disassembly, i int, ix wasmdisasm.Instr) disasm.Inst { 120 | inst := disasm.Inst{ 121 | PC: uint64(i), 122 | Text: ix.Op.Name + " " + file.immediatesToString(ix.Immediates), 123 | } 124 | 125 | switch ix.Op.Code { 126 | case operators.Call: 127 | target := ix.Immediates[0].(uint32) 128 | fn := file.module.FunctionIndexSpace[target] 129 | inst.Text = ix.Op.Name + " " + fn.Name 130 | inst.Call = fn.Name 131 | 132 | // TODO: figure out ix.Branches and ix.Block.IfElseIndex (similar) 133 | default: 134 | 135 | } 136 | 137 | return inst 138 | } 139 | 140 | func (file *File) immediatesToString(xs []interface{}) string { 141 | var str strings.Builder 142 | for _, im := range xs { 143 | fmt.Fprintf(&str, " %v", im) 144 | } 145 | return str.String() 146 | } 147 | */ 148 | 149 | func tryParseDWARF(module *wasm.Module) { 150 | customSectionData := func(name string) []byte { 151 | for _, sec := range module.CustomSections { 152 | if sec.Name == name { 153 | return sec.Data 154 | } 155 | } 156 | return nil 157 | } 158 | 159 | dwarfdata, err := dwarf.New( 160 | customSectionData(".debug_abbrev"), 161 | customSectionData(".debug_aranges"), 162 | customSectionData(".debug_frame"), 163 | customSectionData(".debug_info"), 164 | customSectionData(".debug_line"), 165 | customSectionData(".debug_pubnames"), 166 | customSectionData(".debug_ranges"), 167 | customSectionData(".debug_str"), 168 | ) 169 | if err != nil { 170 | fmt.Println("ERROR", err) 171 | return 172 | } 173 | 174 | rd := dwarfdata.Reader() 175 | for { 176 | entry, err := rd.Next() 177 | if entry == nil && err == nil { 178 | break 179 | } 180 | if err != nil { 181 | fmt.Println(err) 182 | break 183 | } 184 | if entry.Tag == dwarf.TagCompileUnit { 185 | lrd, err := dwarfdata.LineReader(entry) 186 | if err != nil { 187 | fmt.Println(err) 188 | break 189 | } 190 | 191 | for _, fln := range lrd.Files() { 192 | fmt.Println(fln) 193 | } 194 | 195 | var lineEntry dwarf.LineEntry 196 | for lrd.Next(&lineEntry) == nil { 197 | fmt.Println( 198 | lineEntry.Address, 199 | lineEntry.Line, 200 | lineEntry.Column, 201 | lineEntry.File.Name, 202 | ) 203 | } 204 | } 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "image" 7 | "image/color" 8 | "log" 9 | "os" 10 | "runtime/pprof" 11 | 12 | "gioui.org/app" 13 | "gioui.org/text" 14 | "gioui.org/unit" 15 | "gioui.org/widget/material" 16 | ) 17 | 18 | func main() { 19 | cpuprofile := flag.String("cpuprofile", "", "enable cpu profiling") 20 | textSize := flag.Int("text-size", 12, "default font size") 21 | filter := flag.String("filter", "", "filter the functions by regexp") 22 | watch := flag.Bool("watch", false, "auto reload executable") 23 | context := flag.Int("context", 3, "source line context") 24 | font := flag.String("font", "", "user font") 25 | 26 | workInProgressWASM = os.Getenv("LENSM_EXPERIMENT_WASM") != "" 27 | 28 | flag.Parse() 29 | exePath := flag.Arg(0) 30 | 31 | if exePath == "" { 32 | fmt.Fprintln(os.Stderr, "lensm ") 33 | flag.Usage() 34 | os.Exit(1) 35 | } 36 | 37 | windows := &Windows{} 38 | 39 | theme := material.NewTheme() 40 | theme.Shaper = text.NewShaper(text.WithCollection(LoadFonts(*font))) 41 | theme.TextSize = unit.Sp(*textSize) 42 | 43 | ui := NewExeUI(windows, theme) 44 | ui.Config = FileUIConfig{ 45 | Path: exePath, 46 | Watch: *watch, 47 | Context: *context, 48 | } 49 | ui.Funcs.SetFilter(*filter) 50 | 51 | windows.Open("lensm", image.Pt(1400, 900), ui.Run) 52 | 53 | go func() { 54 | profile(*cpuprofile, windows.Wait) 55 | os.Exit(0) 56 | }() 57 | 58 | // This starts Gio main. 59 | app.Main() 60 | } 61 | 62 | var ( 63 | secondaryBackground = color.NRGBA{R: 0xF0, G: 0xF0, B: 0xF0, A: 0xFF} 64 | splitterColor = color.NRGBA{R: 0x80, G: 0x80, B: 0x80, A: 0xFF} 65 | ) 66 | 67 | func profile(cpuprofile string, fn func()) { 68 | if cpuprofile != "" { 69 | f, err := os.Create(cpuprofile) 70 | if err != nil { 71 | log.Fatal(err) 72 | } 73 | pprof.StartCPUProfile(f) 74 | defer pprof.StopCPUProfile() 75 | } 76 | fn() 77 | } 78 | -------------------------------------------------------------------------------- /screenshot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loov/lensm/5a794198685440f24484a6be21d5bdfa7dba2cf2/screenshot.gif -------------------------------------------------------------------------------- /selectlist.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "image" 5 | "image/color" 6 | 7 | "gioui.org/f32" 8 | "gioui.org/font" 9 | "gioui.org/io/event" 10 | "gioui.org/io/key" 11 | "gioui.org/io/pointer" 12 | "gioui.org/layout" 13 | "gioui.org/op" 14 | "gioui.org/op/clip" 15 | "gioui.org/op/paint" 16 | "gioui.org/unit" 17 | "gioui.org/widget" 18 | "gioui.org/widget/material" 19 | ) 20 | 21 | // NewVerticalSelectList creates a new select list with the specified item height. 22 | func NewVerticalSelectList(itemHeight unit.Dp) SelectList { 23 | return SelectList{ 24 | List: widget.List{ 25 | List: layout.List{ 26 | Axis: layout.Vertical, 27 | }, 28 | }, 29 | ItemHeight: itemHeight, 30 | } 31 | } 32 | 33 | // SelectList draws a list where items can be selected. 34 | type SelectList struct { 35 | widget.List 36 | 37 | Selected int 38 | Hovered int 39 | 40 | ItemHeight unit.Dp 41 | } 42 | 43 | // Layout draws the list. 44 | func (list *SelectList) Layout(th *material.Theme, gtx layout.Context, length int, element layout.ListElement) layout.Dimensions { 45 | return FocusBorder(th, gtx.Focused(list)).Layout(gtx, func(gtx layout.Context) layout.Dimensions { 46 | size := gtx.Constraints.Max 47 | gtx.Constraints = layout.Exact(size) 48 | defer clip.Rect{Max: size}.Push(gtx.Ops).Pop() 49 | 50 | event.Op(gtx.Ops, list) 51 | 52 | changed := false 53 | grabbed := false 54 | 55 | itemHeight := gtx.Metric.Dp(list.ItemHeight) 56 | if itemHeight == 0 { 57 | itemHeight = gtx.Metric.Sp(th.TextSize) 58 | } 59 | 60 | pointerClicked := false 61 | pointerHovered := false 62 | pointerPosition := f32.Point{} 63 | for { 64 | // TODO: fix navigation when in filter. 65 | ev, ok := gtx.Event( 66 | key.FocusFilter{Target: list}, 67 | key.Filter{Focus: list, Name: key.NameUpArrow}, 68 | key.Filter{Focus: list, Name: key.NameDownArrow}, 69 | key.Filter{Focus: list, Name: key.NameHome}, 70 | key.Filter{Focus: list, Name: key.NameEnd}, 71 | key.Filter{Focus: list, Name: key.NamePageUp}, 72 | key.Filter{Focus: list, Name: key.NamePageDown}, 73 | pointer.Filter{ 74 | Target: list, 75 | Kinds: pointer.Press | pointer.Move, 76 | }, 77 | ) 78 | if !ok { 79 | break 80 | } 81 | 82 | switch ev := ev.(type) { 83 | case key.Event: 84 | if ev.State == key.Press { 85 | offset := 0 86 | switch ev.Name { 87 | case key.NameHome: 88 | offset = -length 89 | case key.NameEnd: 90 | offset = length 91 | case key.NameUpArrow: 92 | offset = -1 93 | case key.NameDownArrow: 94 | offset = 1 95 | case key.NamePageUp: 96 | offset = -list.List.Position.Count 97 | case key.NamePageDown: 98 | offset = list.List.Position.Count 99 | } 100 | 101 | if offset != 0 { 102 | target := list.Selected + offset 103 | if target < 0 { 104 | target = 0 105 | } 106 | if target >= length { 107 | target = length - 1 108 | } 109 | if list.Selected != target { 110 | list.Selected = target 111 | changed = true 112 | } 113 | } 114 | 115 | // if we get input and don't have a focus, then grab it 116 | if !gtx.Focused(list) { 117 | gtx.Execute(op.InvalidateCmd{}) 118 | } 119 | } 120 | 121 | case pointer.Event: 122 | switch ev.Kind { 123 | case pointer.Press: 124 | if !gtx.Focused(list) && !grabbed { 125 | grabbed = true 126 | gtx.Execute(key.FocusCmd{Tag: list}) 127 | } 128 | pointerClicked = true 129 | pointerPosition = ev.Position 130 | case pointer.Move: 131 | pointerHovered = true 132 | pointerPosition = ev.Position 133 | case pointer.Cancel: 134 | list.Hovered = -1 135 | } 136 | } 137 | } 138 | 139 | if pointerClicked || pointerHovered { 140 | // TODO: make this independent of fixed item height 141 | clientClickY := list.Position.First*itemHeight + list.Position.Offset + int(pointerPosition.Y) 142 | target := clientClickY / itemHeight 143 | if 0 <= target && target <= length { 144 | if pointerClicked && list.Selected != target { 145 | list.Selected = target 146 | } 147 | if pointerHovered && list.Hovered != target { 148 | list.Hovered = target 149 | } 150 | } 151 | } 152 | 153 | if changed { 154 | pos := &list.List.Position 155 | switch { 156 | case list.Selected < pos.First+1: 157 | list.List.Position = layout.Position{First: list.Selected - 1} 158 | case pos.First+pos.Count-1 <= list.Selected: 159 | list.List.Position = layout.Position{First: list.Selected - pos.Count + 2} 160 | } 161 | } 162 | 163 | style := material.List(th, &list.List) 164 | style.AnchorStrategy = material.Overlay 165 | return style.Layout(gtx, length, 166 | func(gtx layout.Context, index int) layout.Dimensions { 167 | gtx.Constraints = layout.Exact(image.Point{ 168 | X: gtx.Constraints.Max.X, 169 | Y: itemHeight, 170 | }) 171 | return element(gtx, index) 172 | }) 173 | }) 174 | } 175 | 176 | // StringListItem creates a string item drawer that reacts to hover and selection. 177 | func StringListItem(th *material.Theme, state *SelectList, item func(int) string) layout.ListElement { 178 | return func(gtx layout.Context, index int) layout.Dimensions { 179 | defer clip.Rect{Max: gtx.Constraints.Max}.Push(gtx.Ops).Pop() 180 | 181 | bg := color.NRGBA{} 182 | fg := th.Fg 183 | weight := font.Normal 184 | 185 | switch { 186 | case state.Selected == index: 187 | if gtx.Focused(state) { 188 | bg = th.ContrastBg 189 | fg = th.ContrastFg 190 | } 191 | weight = font.Black 192 | case state.Hovered == index: 193 | bg = th.ContrastBg 194 | bg.A /= 4 195 | } 196 | 197 | if bg != (color.NRGBA{}) { 198 | paint.Fill(gtx.Ops, bg) 199 | } 200 | inset := layout.Inset{Top: 1, Right: 4, Bottom: 1, Left: 4} 201 | return inset.Layout(gtx, func(gtx layout.Context) layout.Dimensions { 202 | label := material.Body1(th, item(index)) 203 | label.Color = fg 204 | label.MaxLines = 1 205 | label.TextSize = th.TextSize * 8 / 10 206 | label.Font.Weight = weight 207 | gtx.Constraints.Max.X = maxLineWidth 208 | return label.Layout(gtx) 209 | }) 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /testdata/c-wasm/.gitignore: -------------------------------------------------------------------------------- 1 | *.s.o 2 | *.s -------------------------------------------------------------------------------- /testdata/c-wasm/Makefile: -------------------------------------------------------------------------------- 1 | PHONY := llc 2 | llc: 3 | clang --target=wasm32 -emit-llvm -g -c -S example.c 4 | llc -O0 -march=wasm32 \ 5 | --filetype=obj \ 6 | example.s 7 | wasm-ld --no-entry --export-all -o example.wasm example.s.o 8 | 9 | PHONY := clang 10 | clang: 11 | clang -g --target=wasm32 --no-standard-libraries -Wl,--no-entry -o example-clang.wasm example.c 12 | 13 | PHONY := odump-clang 14 | odump: 15 | wasm-objdump -x example-clang.wasm 16 | wasm-objdump -x example.wasm 17 | -------------------------------------------------------------------------------- /testdata/c-wasm/example-clang.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loov/lensm/5a794198685440f24484a6be21d5bdfa7dba2cf2/testdata/c-wasm/example-clang.wasm -------------------------------------------------------------------------------- /testdata/c-wasm/example.c: -------------------------------------------------------------------------------- 1 | int internal_add(int a, int b) { 2 | if(a > 5) { 3 | return a - b; 4 | } 5 | return a + b; 6 | } 7 | 8 | __attribute__((export_name("add"))) 9 | int add(int a, int b) 10 | { 11 | int res; 12 | res = internal_add(a, b); 13 | return res; 14 | } -------------------------------------------------------------------------------- /testdata/c-wasm/example.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loov/lensm/5a794198685440f24484a6be21d5bdfa7dba2cf2/testdata/c-wasm/example.wasm -------------------------------------------------------------------------------- /util.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | const maxLineWidth = 10 * 1024 4 | 5 | // InRange checks whether v is in bounds for length. 6 | func InRange(v int, length int) bool { 7 | return 0 <= v && v < length 8 | } 9 | -------------------------------------------------------------------------------- /widgets.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "image" 5 | "image/color" 6 | "time" 7 | 8 | "gioui.org/font" 9 | "gioui.org/layout" 10 | "gioui.org/op" 11 | "gioui.org/op/clip" 12 | "gioui.org/op/paint" 13 | "gioui.org/unit" 14 | "gioui.org/widget" 15 | "gioui.org/widget/material" 16 | ) 17 | 18 | // SourceLine is a single-line of text. 19 | type SourceLine struct { 20 | TopLeft image.Point 21 | Width int 22 | Text string 23 | TextHeight unit.Sp 24 | Italic bool 25 | Bold bool 26 | Color color.NRGBA 27 | } 28 | 29 | // Layout draws the text. 30 | func (line SourceLine) Layout(th *material.Theme, gtx layout.Context) { 31 | gtx.Constraints.Min.X = 0 32 | gtx.Constraints.Max.X = maxLineWidth 33 | gtx.Constraints.Min.Y = 0 34 | gtx.Constraints.Max.Y = maxLineWidth 35 | 36 | defer op.Offset(line.TopLeft).Push(gtx.Ops).Pop() 37 | if line.Width > 0 { 38 | maxSize := image.Pt(line.Width, gtx.Metric.Sp(line.TextHeight)) 39 | defer clip.Rect{Max: maxSize}.Push(gtx.Ops).Pop() 40 | } 41 | 42 | f := font.Font{Typeface: "override-monospace,Go,monospace", Weight: font.Normal} 43 | if line.Italic { 44 | f.Style = font.Italic 45 | } 46 | if line.Bold { 47 | f.Weight = font.Black 48 | } 49 | paint.ColorOp{Color: line.Color}.Add(gtx.Ops) 50 | widget.Label{MaxLines: 1}.Layout(gtx, th.Shaper, f, line.TextHeight, line.Text, op.CallOp{}) 51 | } 52 | 53 | type VerticalLine struct { 54 | Width unit.Dp 55 | Color color.NRGBA 56 | } 57 | 58 | func (line VerticalLine) Layout(gtx layout.Context) layout.Dimensions { 59 | size := image.Point{ 60 | X: gtx.Metric.Dp(line.Width), 61 | Y: gtx.Constraints.Min.Y, 62 | } 63 | paint.FillShape(gtx.Ops, line.Color, clip.Rect{Max: size}.Op()) 64 | return layout.Dimensions{ 65 | Size: size, 66 | } 67 | } 68 | 69 | type HorizontalLine struct { 70 | Height unit.Dp 71 | Color color.NRGBA 72 | } 73 | 74 | func (line HorizontalLine) Layout(gtx layout.Context) layout.Dimensions { 75 | size := image.Point{ 76 | X: gtx.Constraints.Min.X, 77 | Y: gtx.Metric.Dp(line.Height), 78 | } 79 | paint.FillShape(gtx.Ops, line.Color, clip.Rect{Max: size}.Op()) 80 | return layout.Dimensions{ 81 | Size: size, 82 | } 83 | } 84 | 85 | type ScrollAnimation struct { 86 | active bool 87 | from, to float32 88 | duration time.Duration 89 | start time.Time 90 | } 91 | 92 | func (anim *ScrollAnimation) Start(gtx layout.Context, from, to float32, duration time.Duration) { 93 | anim.active = true 94 | anim.from = from 95 | anim.to = to 96 | anim.duration = duration 97 | anim.start = gtx.Now 98 | gtx.Execute(op.InvalidateCmd{}) 99 | } 100 | 101 | func (anim *ScrollAnimation) Stop() { anim.active = false } 102 | 103 | func (anim *ScrollAnimation) Update(gtx layout.Context) (float32, bool) { 104 | if !anim.active { 105 | return anim.to, false 106 | } 107 | gtx.Execute(op.InvalidateCmd{}) 108 | 109 | elapsed := gtx.Now.Sub(anim.start) 110 | if elapsed > anim.duration { 111 | anim.active = false 112 | return anim.to, true 113 | } 114 | 115 | progress := float32(elapsed) / float32(anim.duration) 116 | progress = easeInOutCubic(progress) 117 | 118 | pos := anim.from + progress*(anim.to-anim.from) 119 | return pos, true 120 | } 121 | 122 | func easeInOutCubic(t float32) float32 { 123 | if t < .5 { 124 | return 4 * t * t * t 125 | } 126 | return (t-1)*(2*t-2)*(2*t-2) + 1 127 | } 128 | -------------------------------------------------------------------------------- /windows.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "image" 6 | "log" 7 | "os" 8 | "sync" 9 | 10 | "gioui.org/app" 11 | "gioui.org/font" 12 | "gioui.org/font/gofont" 13 | "gioui.org/font/opentype" 14 | "gioui.org/layout" 15 | "gioui.org/op" 16 | "gioui.org/unit" 17 | ) 18 | 19 | type Windows struct { 20 | active sync.WaitGroup 21 | } 22 | 23 | func (windows *Windows) Open(title string, sizeDp image.Point, run func(*app.Window) error) { 24 | windows.active.Add(1) 25 | go func() { 26 | defer windows.active.Done() 27 | 28 | window := new(app.Window) 29 | window.Option( 30 | app.Title(title), 31 | app.Size(unit.Dp(sizeDp.X), unit.Dp(sizeDp.Y)), 32 | ) 33 | if err := run(window); err != nil { 34 | log.Println(err) 35 | } 36 | }() 37 | } 38 | 39 | func (windows *Windows) Wait() { 40 | windows.active.Wait() 41 | } 42 | 43 | func WidgetWindow(widget layout.Widget) func(*app.Window) error { 44 | return func(w *app.Window) error { 45 | var ops op.Ops 46 | for { 47 | e := w.Event() 48 | switch e := e.(type) { 49 | case app.FrameEvent: 50 | gtx := app.NewContext(&ops, e) 51 | widget(gtx) 52 | e.Frame(gtx.Ops) 53 | 54 | case app.DestroyEvent: 55 | return e.Err 56 | } 57 | } 58 | } 59 | } 60 | 61 | func LoadFonts(userfont string) []font.FontFace { 62 | collection := gofont.Collection() 63 | if userfont == "" { 64 | return collection 65 | } 66 | b, err := os.ReadFile(userfont) 67 | if err != nil { 68 | panic(fmt.Errorf("failed to parse font: %v", err)) 69 | } 70 | face, err := opentype.Parse(b) 71 | if err != nil { 72 | panic(fmt.Errorf("failed to parse font: %v", err)) 73 | } 74 | fnt := font.Font{Typeface: "override-monospace,monospace", Weight: font.Normal} 75 | fface := font.FontFace{Font: fnt, Face: face} 76 | return append(collection, fface) 77 | } 78 | --------------------------------------------------------------------------------